From 3fcb8ef7b2c60e1bb4d7b8fc799b4be24f9cf757 Mon Sep 17 00:00:00 2001 From: tabris Date: Fri, 31 Oct 2025 06:45:08 -0400 Subject: [PATCH] filogic kernel edge - change from frank-w's tree to just a git-format-patches from his tree --- config/sources/families/filogic.conf | 7 +- .../patches.armbian/0001-6.16.12.diff | 185462 --------------- ...et-next-rework-IRQ-handling-in-mtk_e.patch | 0 ...ernet-mtk_eth_soc-support-named-IRQs.patch | 99 + ...mtk_eth_soc-add-consts-for-irq-index.patch | 129 + ...k_eth_soc-skip-first-IRQ-if-not-used.patch | 68 + ..._eth_soc-only-use-legacy-mode-on-mis.patch | 37 + ...ld-script-config-defconfig-and-fit-s.patch | 2766 + ...itional-build-script-config-defconfi.patch | 3796 + ...nfig-r3-fix-warning-about-BASE_SMALL.patch | 25 + ...0009-build.conf-change-upload-target.patch | 23 + ...-mt7623-swap-mmc-and-put-uart2-first.patch | 87 + ...rm64-dts-disable-dtbs-for-dtbs_check.patch | 307 + ...terconnect-add-mt7988-cci-compatible.patch | 45 + ...m64-dts-mediatek-mt7988-add-cci-node.patch | 92 + ...ek-mt7988a-bpi-r4-add-proc-supply-fo.patch | 32 + ...atek-mt7988a-bpi-r4-drop-unused-pins.patch | 151 + ...ediatek-mt7988a-bpi-r4-add-gpio-leds.patch | 50 + ...etter-further-mt7988-devicetree-work.patch | 0 ...mediatek-net-update-mac-subnode-patt.patch | 32 + ...-net-mediatek-net-allow-up-to-8-IRQs.patch | 90 + ...ngs-net-mediatek-net-allow-irq-names.patch | 141 + ...s-net-mediatek-net-add-sram-property.patch | 107 + ...dsa-mediatek-mt7530-add-dsa-port-def.patch | 51 + ...dsa-mediatek-mt7530-add-internal-mdi.patch | 44 + ...64-dts-mediatek-mt7986-add-sram-node.patch | 53 + ...ek-mt7986-add-interrupts-for-RSS-and.patch | 36 + ...atek-mt7988-add-basic-ethernet-nodes.patch | 208 + ...-dts-mediatek-mt7988-add-switch-node.patch | 184 + ...ek-mt7988a-bpi-r4-add-aliases-for-et.patch | 34 + ...ek-mt7988a-bpi-r4-add-sfp-cages-and-.patch | 114 + ...ek-mt7988a-bpi-r4-configure-switch-p.patch | 102 + ...ek-mt7988a-bpi-r4-drop-readonly-from.patch | 31 + ...pcs-mediatek-sgmiisys-add-phys-and-r.patch | 52 + ...dt-binding-sgmiisys-re-add-pcs-cells.patch | 26 + .../0034-dts-re-add-sgmiisys.patch | 61 + ...-add-cpufreq-calibration-efuse-subno.patch | 27 + ..._eth_soc-move-desc-assignment-below-.patch | 39 + ...-dts-enable-mt818-36-for-cci-testing.patch | 121 + ...-dts-enable-mt818-36-for-cci-testing.patch | 122 + .../0039-enable-bpi-r3-DTBs-for-testing.patch | 37 + ...iatek-for-arm-to-increase-dtbs_check.patch | 97 + ...able-some-arm64-dts-to-check-binding.patch | 41 + .../0042-defconfig-r4-add-sram-driver.patch | 25 + ..._eth_soc-improve-support-for-named-i.patch | 52 + ...t-mtk_eth_soc-fix-kernel-doc-comment.patch | 32 + ..._eth_soc-use-generic-allocator-for-S.patch | 324 + .../0046-defconfig-r3-add-sram.patch | 21 + ...64-r4-add-ubi-partition-to-spin-nand.patch | 53 + .../0048-add-mtd-rw-driver.patch | 594 + ...ts-add-usxgmii-pcs-and-link-both-pcs.patch | 56 + ...s-update-bpi-r4.dtsi-to-actual-state.patch | 142 + ..._eth_soc-add-paths-and-SerDes-modes-.patch | 578 + ...-and-use-MAC-supported_interfaces-in.patch | 108 + ...-introduce-phy_interface_copy-helper.patch | 36 + ...roduce-internal-phylink-PCS-handling.patch | 388 + ...phylink_release_pcs-to-externally-re.patch | 142 + ...t-Firmware-node-support-for-PCS-driv.patch | 401 + ...ink-support-late-PCS-provider-attach.patch | 263 + ...ethernet-controller-permit-to-define.patch | 34 + ...airoha-add-PCS-driver-for-Airoha-SoC.patch | 2938 + ...pcs-Document-support-for-Airoha-Ethe.patch | 141 + ...lynxi-add-platform-driver-for-MT7988.patch | 367 + ...pcs-add-bindings-for-MediaTek-USXGMI.patch | 87 + ...-add-driver-for-MediaTek-USXGMII-PCS.patch | 576 + ..._eth_soc-add-more-DMA-monitor-for-MT.patch | 141 + ...rng-add-driver-for-MediaTek-TRNG-SMC.patch | 140 + ...ata-and-disable-pcie-slot-CN8-shared.patch | 39 + .../0067-arm64-dts-mt7622-fix-sata.patch | 29 + ...kernels-for-bpi-boards-to-deb-packag.patch | 65 + .../0069-kdeb-fix-deb-build-for-R3-R4.patch | 26 + .../0070-build.conf-change-to-r4.patch | 25 + ...able-STRICT_DEVMEM-to-allow-register.patch | 22 + ..._eth_soc-add-register-definitions-fo.patch | 125 + ...ethernet-mtk_eth_soc-add-rss-support.patch | 1300 + ..._eth_soc-drop-RSS-capabilty-for-mt79.patch | 31 + ...fix-mtk_-get-set-_rxfh-callback-head.patch | 87 + ...ethernet-mtk_eth_soc-Add-LRO-support.patch | 514 + ...077-readme-add-README.md-for-RSS-LRO.patch | 101 + ..._eth_soc-support-forced-reset-contro.patch | 61 + ...net-mediatek-add-proprietary-debugfs.patch | 3007 + .../patches.armbian/0080-enable-debugfs.patch | 52 + ..._eth_soc-add-RSS-capabilty-for-mt798.patch | 31 + ..._eth_soc-enable-lro-stats-from-debug.patch | 53 + ...nge-mt7986-from-RSS-to-LRO-only-1-po.patch | 78 + ..._eth_soc-check-if-irqs-were-loaded-t.patch | 47 + .../archive/filogic-6.16/series.armbian | 11 +- patch/kernel/archive/filogic-6.16/series.conf | 96 +- 88 files changed, 22985 insertions(+), 185480 deletions(-) delete mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0001-6.16.12.diff create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0001-v6-coverletter-net-next-rework-IRQ-handling-in-mtk_e.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0002-net-ethernet-mtk_eth_soc-support-named-IRQs.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0003-net-ethernet-mtk_eth_soc-add-consts-for-irq-index.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0004-net-ethernet-mtk_eth_soc-skip-first-IRQ-if-not-used.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0005-net-ethernet-mtk_eth_soc-only-use-legacy-mode-on-mis.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0006-build.sh-add-build-script-config-defconfig-and-fit-s.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0007-build.sh-add-additional-build-script-config-defconfi.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0008-defconfig-r3-fix-warning-about-BASE_SMALL.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0009-build.conf-change-upload-target.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0010-arm-dts-mt7623-swap-mmc-and-put-uart2-first.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0011-arm64-dts-disable-dtbs-for-dtbs_check.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0012-dt-bindings-interconnect-add-mt7988-cci-compatible.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0013-arm64-dts-mediatek-mt7988-add-cci-node.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0014-arm64-dts-mediatek-mt7988a-bpi-r4-add-proc-supply-fo.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0015-arm64-dts-mediatek-mt7988a-bpi-r4-drop-unused-pins.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0016-arm64-dts-mediatek-mt7988a-bpi-r4-add-gpio-leds.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0017-v9-coverletter-further-mt7988-devicetree-work.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0018-dt-bindings-net-mediatek-net-update-mac-subnode-patt.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0019-dt-bindings-net-mediatek-net-allow-up-to-8-IRQs.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0020-dt-bindings-net-mediatek-net-allow-irq-names.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0021-dt-bindings-net-mediatek-net-add-sram-property.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0022-dt-bindings-net-dsa-mediatek-mt7530-add-dsa-port-def.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0023-dt-bindings-net-dsa-mediatek-mt7530-add-internal-mdi.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0024-arm64-dts-mediatek-mt7986-add-sram-node.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0025-arm64-dts-mediatek-mt7986-add-interrupts-for-RSS-and.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0026-arm64-dts-mediatek-mt7988-add-basic-ethernet-nodes.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0027-arm64-dts-mediatek-mt7988-add-switch-node.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0028-arm64-dts-mediatek-mt7988a-bpi-r4-add-aliases-for-et.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0029-arm64-dts-mediatek-mt7988a-bpi-r4-add-sfp-cages-and-.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0030-arm64-dts-mediatek-mt7988a-bpi-r4-configure-switch-p.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0031-arm64-dts-mediatek-mt7988a-bpi-r4-drop-readonly-from.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0032-dt-bindings-net-pcs-mediatek-sgmiisys-add-phys-and-r.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0033-dt-binding-sgmiisys-re-add-pcs-cells.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0034-dts-re-add-sgmiisys.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0035-arm64-dts-mt7988-add-cpufreq-calibration-efuse-subno.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0036-net-ethernet-mtk_eth_soc-move-desc-assignment-below-.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0037-dts-enable-mt818-36-for-cci-testing.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0038-Revert-dts-enable-mt818-36-for-cci-testing.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0039-enable-bpi-r3-DTBs-for-testing.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0040-only-enable-mediatek-for-arm-to-increase-dtbs_check.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0041-enable-some-arm64-dts-to-check-binding.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0042-defconfig-r4-add-sram-driver.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0043-net-ethernet-mtk_eth_soc-improve-support-for-named-i.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0044-net-ethernet-mtk_eth_soc-fix-kernel-doc-comment.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0045-net-ethernet-mtk_eth_soc-use-generic-allocator-for-S.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0046-defconfig-r3-add-sram.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0047-WIP-dts64-r4-add-ubi-partition-to-spin-nand.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0048-add-mtd-rw-driver.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0049-arm64-dts-add-usxgmii-pcs-and-link-both-pcs.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0050-arm64-dts-update-bpi-r4.dtsi-to-actual-state.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0051-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0052-net-phylink-keep-and-use-MAC-supported_interfaces-in.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0053-net-phy-introduce-phy_interface_copy-helper.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0054-net-phylink-introduce-internal-phylink-PCS-handling.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0055-net-phylink-add-phylink_release_pcs-to-externally-re.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0056-net-pcs-implement-Firmware-node-support-for-PCS-driv.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0057-net-phylink-support-late-PCS-provider-attach.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0058-dt-bindings-net-ethernet-controller-permit-to-define.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0059-net-pcs-airoha-add-PCS-driver-for-Airoha-SoC.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0060-dt-bindings-net-pcs-Document-support-for-Airoha-Ethe.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0061-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0062-dt-bindings-net-pcs-add-bindings-for-MediaTek-USXGMI.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0063-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0064-net-ethernet-mtk_eth_soc-add-more-DMA-monitor-for-MT.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0065-hwrng-add-driver-for-MediaTek-TRNG-SMC.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0066-dts64-enable-sata-and-disable-pcie-slot-CN8-shared.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0067-arm64-dts-mt7622-fix-sata.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0068-kdeb-try-to-add-kernels-for-bpi-boards-to-deb-packag.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0069-kdeb-fix-deb-build-for-R3-R4.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0070-build.conf-change-to-r4.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0071-defconfig-r4-disable-STRICT_DEVMEM-to-allow-register.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0072-net-ethernet-mtk_eth_soc-add-register-definitions-fo.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0073-net-ethernet-mtk_eth_soc-add-rss-support.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0074-net-mediatek-mtk_eth_soc-drop-RSS-capabilty-for-mt79.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0075-net-mtk_eth_soc-fix-mtk_-get-set-_rxfh-callback-head.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0076-net-ethernet-mtk_eth_soc-Add-LRO-support.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0077-readme-add-README.md-for-RSS-LRO.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0078-net-ethernet-mtk_eth_soc-support-forced-reset-contro.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0079-net-mediatek-add-proprietary-debugfs.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0080-enable-debugfs.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0081-net-mediatek-mtk_eth_soc-add-RSS-capabilty-for-mt798.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0082-net-mediatek-mtk_eth_soc-enable-lro-stats-from-debug.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0083-net-mediatek-change-mt7986-from-RSS-to-LRO-only-1-po.patch create mode 100644 patch/kernel/archive/filogic-6.16/patches.armbian/0084-net-mediatek-mtk_eth_soc-check-if-irqs-were-loaded-t.patch mode change 100644 => 120000 patch/kernel/archive/filogic-6.16/series.armbian diff --git a/config/sources/families/filogic.conf b/config/sources/families/filogic.conf index 07c2d6cf0a..bdb417e213 100644 --- a/config/sources/families/filogic.conf +++ b/config/sources/families/filogic.conf @@ -59,11 +59,8 @@ case $BRANCH in ;; edge) - KERNELSOURCE='https://github.com/frank-w/BPI-Router-Linux.git' - KERNELBRANCH="branch:6.16-rsslro" - #KERNELSOURCE='https://github.com/tabrisnet/BPI-Router-Linux.git' - # this is just frank-w's 6.16-rsslro with the kernel.org 6.16.12 patch applied. - #KERNELBRANCH="branch:6.16.12-rsslro" + #KERNELSOURCE='https://github.com/frank-w/BPI-Router-Linux.git' + #KERNELBRANCH="branch:6.16-rsslro" declare -g KERNEL_MAJOR_MINOR="6.16" KERNELPATCHDIR="archive/${LINUXFAMILY}-${KERNEL_MAJOR_MINOR}" LINUXCONFIG="linux-${LINUXFAMILY}-${BRANCH}" diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0001-6.16.12.diff b/patch/kernel/archive/filogic-6.16/patches.armbian/0001-6.16.12.diff deleted file mode 100644 index 5ca9638670..0000000000 --- a/patch/kernel/archive/filogic-6.16/patches.armbian/0001-6.16.12.diff +++ /dev/null @@ -1,185462 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: tabrisnet -Date: Sun, 22 Oct 2025 13:57:50 +0000 -Subject: v6.16.12-rsslro - -frank-w/BPI-Router-Linux-kernel v6.16-rsslro -then rebased with git.kernel.org's stable tree v6.16.12 - -Note, the rebase was clean but applying the upstream patches has glitches -due to some backported patches to the stable tree. ---- - -diff -purNx .git BPI-Router-Linux-kernel/arch/alpha/include/asm/pgtable.h BPI-Router-Linux-kernel-6.16.12/arch/alpha/include/asm/pgtable.h ---- BPI-Router-Linux-kernel/arch/alpha/include/asm/pgtable.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/alpha/include/asm/pgtable.h 2025-10-22 13:53:56.279170279 -0400 -@@ -327,7 +327,7 @@ extern inline pte_t mk_swap_pte(unsigned - #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) - #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/arcregs.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/arcregs.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/arcregs.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/arcregs.h 2025-10-22 13:53:56.279170279 -0400 -@@ -144,7 +144,7 @@ - #define ARC_AUX_AGU_MOD2 0x5E2 - #define ARC_AUX_AGU_MOD3 0x5E3 - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #include - -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/atomic64-arcv2.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/atomic64-arcv2.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/atomic64-arcv2.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/atomic64-arcv2.h 2025-10-22 13:53:56.279170279 -0400 -@@ -137,12 +137,9 @@ ATOMIC64_OPS(xor, xor, xor) - #undef ATOMIC64_OP_RETURN - #undef ATOMIC64_OP - --static inline s64 --arch_atomic64_cmpxchg(atomic64_t *ptr, s64 expected, s64 new) -+static inline u64 __arch_cmpxchg64_relaxed(volatile void *ptr, u64 old, u64 new) - { -- s64 prev; -- -- smp_mb(); -+ u64 prev; - - __asm__ __volatile__( - "1: llockd %0, [%1] \n" -@@ -152,14 +149,12 @@ arch_atomic64_cmpxchg(atomic64_t *ptr, s - " bnz 1b \n" - "2: \n" - : "=&r"(prev) -- : "r"(ptr), "ir"(expected), "r"(new) -- : "cc"); /* memory clobber comes from smp_mb() */ -- -- smp_mb(); -+ : "r"(ptr), "ir"(old), "r"(new) -+ : "memory", "cc"); - - return prev; - } --#define arch_atomic64_cmpxchg arch_atomic64_cmpxchg -+#define arch_cmpxchg64_relaxed __arch_cmpxchg64_relaxed - - static inline s64 arch_atomic64_xchg(atomic64_t *ptr, s64 new) - { -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/atomic.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/atomic.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/atomic.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/atomic.h 2025-10-22 13:53:56.279170279 -0400 -@@ -6,7 +6,7 @@ - #ifndef _ASM_ARC_ATOMIC_H - #define _ASM_ARC_ATOMIC_H - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #include - #include -@@ -31,6 +31,6 @@ - #include - #endif - --#endif /* !__ASSEMBLY__ */ -+#endif /* !__ASSEMBLER__ */ - - #endif -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/bitops.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/bitops.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/bitops.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/bitops.h 2025-10-22 13:53:56.279170279 -0400 -@@ -10,7 +10,7 @@ - #error only can be included directly - #endif - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #include - #include -@@ -192,6 +192,6 @@ static inline __attribute__ ((const)) un - #include - #include - --#endif /* !__ASSEMBLY__ */ -+#endif /* !__ASSEMBLER__ */ - - #endif -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/bug.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/bug.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/bug.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/bug.h 2025-10-22 13:53:56.279170279 -0400 -@@ -6,7 +6,7 @@ - #ifndef _ASM_ARC_BUG_H - #define _ASM_ARC_BUG_H - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #include - -@@ -29,6 +29,6 @@ void die(const char *str, struct pt_regs - - #include - --#endif /* !__ASSEMBLY__ */ -+#endif /* !__ASSEMBLER__ */ - - #endif -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/cache.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/cache.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/cache.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/cache.h 2025-10-22 13:53:56.279170279 -0400 -@@ -23,7 +23,7 @@ - */ - #define ARC_UNCACHED_ADDR_SPACE 0xc0000000 - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #include - -@@ -65,7 +65,7 @@ - extern int ioc_enable; - extern unsigned long perip_base, perip_end; - --#endif /* !__ASSEMBLY__ */ -+#endif /* !__ASSEMBLER__ */ - - /* Instruction cache related Auxiliary registers */ - #define ARC_REG_IC_BCR 0x77 /* Build Config reg */ -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/current.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/current.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/current.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/current.h 2025-10-22 13:53:56.279170279 -0400 -@@ -9,7 +9,7 @@ - #ifndef _ASM_ARC_CURRENT_H - #define _ASM_ARC_CURRENT_H - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #ifdef CONFIG_ARC_CURR_IN_REG - -@@ -20,6 +20,6 @@ register struct task_struct *curr_arc as - #include - #endif /* ! CONFIG_ARC_CURR_IN_REG */ - --#endif /* ! __ASSEMBLY__ */ -+#endif /* ! __ASSEMBLER__ */ - - #endif /* _ASM_ARC_CURRENT_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/dsp.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/dsp.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/dsp.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/dsp.h 2025-10-22 13:53:56.279170279 -0400 -@@ -7,7 +7,7 @@ - #ifndef __ASM_ARC_DSP_H - #define __ASM_ARC_DSP_H - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - /* - * DSP-related saved registers - need to be saved only when you are -@@ -24,6 +24,6 @@ struct dsp_callee_regs { - #endif - }; - --#endif /* !__ASSEMBLY__ */ -+#endif /* !__ASSEMBLER__ */ - - #endif /* __ASM_ARC_DSP_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/dsp-impl.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/dsp-impl.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/dsp-impl.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/dsp-impl.h 2025-10-22 13:53:56.279170279 -0400 -@@ -11,7 +11,7 @@ - - #define DSP_CTRL_DISABLED_ALL 0 - --#ifdef __ASSEMBLY__ -+#ifdef __ASSEMBLER__ - - /* clobbers r5 register */ - .macro DSP_EARLY_INIT -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/dwarf.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/dwarf.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/dwarf.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/dwarf.h 2025-10-22 13:53:56.279170279 -0400 -@@ -6,7 +6,7 @@ - #ifndef _ASM_ARC_DWARF_H - #define _ASM_ARC_DWARF_H - --#ifdef __ASSEMBLY__ -+#ifdef __ASSEMBLER__ - - #ifdef ARC_DW2_UNWIND_AS_CFI - -@@ -38,6 +38,6 @@ - - #endif /* !ARC_DW2_UNWIND_AS_CFI */ - --#endif /* __ASSEMBLY__ */ -+#endif /* __ASSEMBLER__ */ - - #endif /* _ASM_ARC_DWARF_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/entry.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/entry.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/entry.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/entry.h 2025-10-22 13:53:56.279170279 -0400 -@@ -13,7 +13,7 @@ - #include /* For VMALLOC_START */ - #include - --#ifdef __ASSEMBLY__ -+#ifdef __ASSEMBLER__ - - #ifdef CONFIG_ISA_ARCOMPACT - #include /* ISA specific bits */ -@@ -146,7 +146,7 @@ - - #endif /* CONFIG_ARC_CURR_IN_REG */ - --#else /* !__ASSEMBLY__ */ -+#else /* !__ASSEMBLER__ */ - - extern void do_signal(struct pt_regs *); - extern void do_notify_resume(struct pt_regs *); -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/irqflags-arcv2.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/irqflags-arcv2.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/irqflags-arcv2.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/irqflags-arcv2.h 2025-10-22 13:53:56.279170279 -0400 -@@ -50,7 +50,7 @@ - #define ISA_INIT_STATUS_BITS (STATUS_IE_MASK | __AD_ENB | \ - (ARCV2_IRQ_DEF_PRIO << 1)) - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - /* - * Save IRQ state and disable IRQs -@@ -170,6 +170,6 @@ static inline void arc_softirq_clear(int - seti - .endm - --#endif /* __ASSEMBLY__ */ -+#endif /* __ASSEMBLER__ */ - - #endif -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/irqflags-compact.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/irqflags-compact.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/irqflags-compact.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/irqflags-compact.h 2025-10-22 13:53:56.279170279 -0400 -@@ -40,7 +40,7 @@ - - #define ISA_INIT_STATUS_BITS STATUS_IE_MASK - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - /****************************************************************** - * IRQ Control Macros -@@ -196,6 +196,6 @@ static inline int arch_irqs_disabled(voi - flag \scratch - .endm - --#endif /* __ASSEMBLY__ */ -+#endif /* __ASSEMBLER__ */ - - #endif -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/jump_label.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/jump_label.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/jump_label.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/jump_label.h 2025-10-22 13:53:56.279170279 -0400 -@@ -2,7 +2,7 @@ - #ifndef _ASM_ARC_JUMP_LABEL_H - #define _ASM_ARC_JUMP_LABEL_H - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #include - #include -@@ -68,5 +68,5 @@ struct jump_entry { - jump_label_t key; - }; - --#endif /* __ASSEMBLY__ */ -+#endif /* __ASSEMBLER__ */ - #endif -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/linkage.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/linkage.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/linkage.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/linkage.h 2025-10-22 13:53:56.279170279 -0400 -@@ -12,7 +12,7 @@ - #define __ALIGN .align 4 - #define __ALIGN_STR __stringify(__ALIGN) - --#ifdef __ASSEMBLY__ -+#ifdef __ASSEMBLER__ - - .macro ST2 e, o, off - #ifdef CONFIG_ARC_HAS_LL64 -@@ -61,7 +61,7 @@ - CFI_ENDPROC ASM_NL \ - .size name, .-name - --#else /* !__ASSEMBLY__ */ -+#else /* !__ASSEMBLER__ */ - - #ifdef CONFIG_ARC_HAS_ICCM - #define __arcfp_code __section(".text.arcfp") -@@ -75,6 +75,6 @@ - #define __arcfp_data __section(".data") - #endif - --#endif /* __ASSEMBLY__ */ -+#endif /* __ASSEMBLER__ */ - - #endif -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/mmu-arcv2.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/mmu-arcv2.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/mmu-arcv2.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/mmu-arcv2.h 2025-10-22 13:53:56.279170279 -0400 -@@ -69,7 +69,7 @@ - - #define PTE_BITS_NON_RWX_IN_PD1 (PAGE_MASK_PHYS | _PAGE_CACHEABLE) - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - struct mm_struct; - extern int pae40_exist_but_not_enab(void); -@@ -100,6 +100,6 @@ static inline void mmu_setup_pgd(struct - sr \reg, [ARC_REG_PID] - .endm - --#endif /* !__ASSEMBLY__ */ -+#endif /* !__ASSEMBLER__ */ - - #endif -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/mmu.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/mmu.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/mmu.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/mmu.h 2025-10-22 13:53:56.279170279 -0400 -@@ -6,7 +6,7 @@ - #ifndef _ASM_ARC_MMU_H - #define _ASM_ARC_MMU_H - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #include /* NR_CPUS */ - -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/page.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/page.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/page.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/page.h 2025-10-22 13:53:56.279170279 -0400 -@@ -19,7 +19,7 @@ - - #endif /* CONFIG_ARC_HAS_PAE40 */ - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #define clear_page(paddr) memset((paddr), 0, PAGE_SIZE) - #define copy_user_page(to, from, vaddr, pg) copy_page(to, from) -@@ -136,6 +136,6 @@ static inline unsigned long virt_to_pfn( - #include /* page_to_pfn, pfn_to_page */ - #include - --#endif /* !__ASSEMBLY__ */ -+#endif /* !__ASSEMBLER__ */ - - #endif -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/pgtable-bits-arcv2.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/pgtable-bits-arcv2.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/pgtable-bits-arcv2.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/pgtable-bits-arcv2.h 2025-10-22 13:53:56.279170279 -0400 -@@ -75,7 +75,7 @@ - * This is to enable COW mechanism - */ - /* xwr */ --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #define pte_write(pte) (pte_val(pte) & _PAGE_WRITE) - #define pte_dirty(pte) (pte_val(pte) & _PAGE_DIRTY) -@@ -130,7 +130,7 @@ void update_mmu_cache_range(struct vm_fa - #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) - #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; - } -@@ -142,6 +142,6 @@ PTE_BIT_FUNC(swp_clear_exclusive, &= ~(_ - #include - #endif - --#endif /* __ASSEMBLY__ */ -+#endif /* __ASSEMBLER__ */ - - #endif -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/pgtable.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/pgtable.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/pgtable.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/pgtable.h 2025-10-22 13:53:56.279170279 -0400 -@@ -19,7 +19,7 @@ - */ - #define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - extern char empty_zero_page[PAGE_SIZE]; - #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) -@@ -29,6 +29,6 @@ extern pgd_t swapper_pg_dir[] __aligned( - /* to cope with aliasing VIPT cache */ - #define HAVE_ARCH_UNMAPPED_AREA - --#endif /* __ASSEMBLY__ */ -+#endif /* __ASSEMBLER__ */ - - #endif -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/pgtable-levels.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/pgtable-levels.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/pgtable-levels.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/pgtable-levels.h 2025-10-22 13:53:56.279170279 -0400 -@@ -85,7 +85,7 @@ - - #define PTRS_PER_PTE BIT(PMD_SHIFT - PAGE_SHIFT) - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #if CONFIG_PGTABLE_LEVELS > 3 - #include -@@ -181,6 +181,6 @@ - #define pmd_leaf(x) (pmd_val(x) & _PAGE_HW_SZ) - #endif - --#endif /* !__ASSEMBLY__ */ -+#endif /* !__ASSEMBLER__ */ - - #endif -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/processor.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/processor.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/processor.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/processor.h 2025-10-22 13:53:56.279170279 -0400 -@@ -11,7 +11,7 @@ - #ifndef __ASM_ARC_PROCESSOR_H - #define __ASM_ARC_PROCESSOR_H - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #include - #include -@@ -66,7 +66,7 @@ extern void start_thread(struct pt_regs - - extern unsigned int __get_wchan(struct task_struct *p); - --#endif /* !__ASSEMBLY__ */ -+#endif /* !__ASSEMBLER__ */ - - /* - * Default System Memory Map on ARC -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/ptrace.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/ptrace.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/ptrace.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/ptrace.h 2025-10-22 13:53:56.279170279 -0400 -@@ -10,7 +10,7 @@ - #include - #include - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - typedef union { - struct { -@@ -172,6 +172,6 @@ static inline unsigned long regs_get_reg - extern int syscall_trace_enter(struct pt_regs *); - extern void syscall_trace_exit(struct pt_regs *); - --#endif /* !__ASSEMBLY__ */ -+#endif /* !__ASSEMBLER__ */ - - #endif /* __ASM_PTRACE_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/switch_to.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/switch_to.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/switch_to.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/switch_to.h 2025-10-22 13:53:56.279170279 -0400 -@@ -6,7 +6,7 @@ - #ifndef _ASM_ARC_SWITCH_TO_H - #define _ASM_ARC_SWITCH_TO_H - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #include - #include -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/asm/thread_info.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/thread_info.h ---- BPI-Router-Linux-kernel/arch/arc/include/asm/thread_info.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/asm/thread_info.h 2025-10-22 13:53:56.279170279 -0400 -@@ -24,7 +24,7 @@ - #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) - #define THREAD_SHIFT (PAGE_SHIFT << THREAD_SIZE_ORDER) - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #include - -@@ -62,7 +62,7 @@ static inline __attribute_const__ struct - return (struct thread_info *)(sp & ~(THREAD_SIZE - 1)); - } - --#endif /* !__ASSEMBLY__ */ -+#endif /* !__ASSEMBLER__ */ - - /* - * thread information flags -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/include/uapi/asm/ptrace.h BPI-Router-Linux-kernel-6.16.12/arch/arc/include/uapi/asm/ptrace.h ---- BPI-Router-Linux-kernel/arch/arc/include/uapi/asm/ptrace.h 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/include/uapi/asm/ptrace.h 2025-10-22 13:53:56.279170279 -0400 -@@ -14,7 +14,7 @@ - - #define PTRACE_GET_THREAD_AREA 25 - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - /* - * Userspace ABI: Register state needed by - * -ptrace (gdbserver) -@@ -53,6 +53,6 @@ struct user_regs_arcv2 { - unsigned long r30, r58, r59; - }; - --#endif /* !__ASSEMBLY__ */ -+#endif /* !__ASSEMBLER__ */ - - #endif /* _UAPI__ASM_ARC_PTRACE_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/arc/kernel/unwind.c BPI-Router-Linux-kernel-6.16.12/arch/arc/kernel/unwind.c ---- BPI-Router-Linux-kernel/arch/arc/kernel/unwind.c 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arc/kernel/unwind.c 2025-10-22 13:53:56.279170279 -0400 -@@ -241,15 +241,6 @@ static int cmp_eh_frame_hdr_table_entrie - return (e1->start > e2->start) - (e1->start < e2->start); - } - --static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size) --{ -- struct eh_frame_hdr_table_entry *e1 = p1; -- struct eh_frame_hdr_table_entry *e2 = p2; -- -- swap(e1->start, e2->start); -- swap(e1->fde, e2->fde); --} -- - static void init_unwind_hdr(struct unwind_table *table, - void *(*alloc) (unsigned long)) - { -@@ -345,7 +336,7 @@ static void init_unwind_hdr(struct unwin - sort(header->table, - n, - sizeof(*header->table), -- cmp_eh_frame_hdr_table_entries, swap_eh_frame_hdr_table_entries); -+ cmp_eh_frame_hdr_table_entries, NULL); - - table->hdrsz = hdrSize; - smp_wmb(); -diff -purNx .git BPI-Router-Linux-kernel/arch/arm/boot/dts/allwinner/sun8i-v3s.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm/boot/dts/allwinner/sun8i-v3s.dtsi ---- BPI-Router-Linux-kernel/arch/arm/boot/dts/allwinner/sun8i-v3s.dtsi 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm/boot/dts/allwinner/sun8i-v3s.dtsi 2025-10-22 13:53:56.279170279 -0400 -@@ -652,7 +652,7 @@ - reg = <0x01cb4000 0x3000>; - interrupts = ; - clocks = <&ccu CLK_BUS_CSI>, -- <&ccu CLK_CSI1_SCLK>, -+ <&ccu CLK_CSI_SCLK>, - <&ccu CLK_DRAM_CSI>; - clock-names = "bus", "mod", "ram"; - resets = <&ccu RST_BUS_CSI>; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_sodia.dts BPI-Router-Linux-kernel-6.16.12/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_sodia.dts ---- BPI-Router-Linux-kernel/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_sodia.dts 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_sodia.dts 2025-10-22 13:53:56.283170260 -0400 -@@ -66,8 +66,10 @@ - mdio0 { - #address-cells = <1>; - #size-cells = <0>; -- phy0: ethernet-phy@0 { -- reg = <0>; -+ compatible = "snps,dwmac-mdio"; -+ -+ phy0: ethernet-phy@4 { -+ reg = <4>; - rxd0-skew-ps = <0>; - rxd1-skew-ps = <0>; - rxd2-skew-ps = <0>; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm/boot/dts/marvell/kirkwood-openrd-client.dts BPI-Router-Linux-kernel-6.16.12/arch/arm/boot/dts/marvell/kirkwood-openrd-client.dts ---- BPI-Router-Linux-kernel/arch/arm/boot/dts/marvell/kirkwood-openrd-client.dts 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm/boot/dts/marvell/kirkwood-openrd-client.dts 2025-10-22 13:53:56.283170260 -0400 -@@ -38,7 +38,7 @@ - simple-audio-card,mclk-fs = <256>; - - simple-audio-card,cpu { -- sound-dai = <&audio0 0>; -+ sound-dai = <&audio0>; - }; - - simple-audio-card,codec { -diff -purNx .git BPI-Router-Linux-kernel/arch/arm/boot/dts/microchip/at91-sama7d65_curiosity.dts BPI-Router-Linux-kernel-6.16.12/arch/arm/boot/dts/microchip/at91-sama7d65_curiosity.dts ---- BPI-Router-Linux-kernel/arch/arm/boot/dts/microchip/at91-sama7d65_curiosity.dts 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm/boot/dts/microchip/at91-sama7d65_curiosity.dts 2025-10-22 13:53:56.283170260 -0400 -@@ -352,6 +352,8 @@ - - &sdmmc1 { - bus-width = <4>; -+ no-1-8-v; -+ sdhci-caps-mask = <0x0 0x00200000>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_sdmmc1_default>; - status = "okay"; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm/boot/dts/microchip/sam9x7.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm/boot/dts/microchip/sam9x7.dtsi ---- BPI-Router-Linux-kernel/arch/arm/boot/dts/microchip/sam9x7.dtsi 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm/boot/dts/microchip/sam9x7.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -45,11 +45,13 @@ - clocks { - slow_xtal: clock-slowxtal { - compatible = "fixed-clock"; -+ clock-output-names = "slow_xtal"; - #clock-cells = <0>; - }; - - main_xtal: clock-mainxtal { - compatible = "fixed-clock"; -+ clock-output-names = "main_xtal"; - #clock-cells = <0>; - }; - }; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm/boot/dts/microchip/sama7d65.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm/boot/dts/microchip/sama7d65.dtsi ---- BPI-Router-Linux-kernel/arch/arm/boot/dts/microchip/sama7d65.dtsi 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm/boot/dts/microchip/sama7d65.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -38,11 +38,13 @@ - clocks { - main_xtal: clock-mainxtal { - compatible = "fixed-clock"; -+ clock-output-names = "main_xtal"; - #clock-cells = <0>; - }; - - slow_xtal: clock-slowxtal { - compatible = "fixed-clock"; -+ clock-output-names = "slow_xtal"; - #clock-cells = <0>; - }; - }; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi ---- BPI-Router-Linux-kernel/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm/boot/dts/nxp/imx/imx6ul-kontron-bl-common.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -168,7 +168,6 @@ - pinctrl-0 = <&pinctrl_uart2>; - linux,rs485-enabled-at-boot-time; - rs485-rx-during-tx; -- rs485-rts-active-low; - uart-has-rtscts; - status = "okay"; - }; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm/boot/dts/nxp/vf/vfxxx.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm/boot/dts/nxp/vf/vfxxx.dtsi ---- BPI-Router-Linux-kernel/arch/arm/boot/dts/nxp/vf/vfxxx.dtsi 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm/boot/dts/nxp/vf/vfxxx.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -603,7 +603,7 @@ - - ftm: ftm@400b8000 { - compatible = "fsl,ftm-timer"; -- reg = <0x400b8000 0x1000 0x400b9000 0x1000>; -+ reg = <0x400b8000 0x1000>, <0x400b9000 0x1000>; - interrupts = <44 IRQ_TYPE_LEVEL_HIGH>; - clock-names = "ftm-evt", "ftm-src", - "ftm-evt-counter-en", "ftm-src-counter-en"; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm/boot/dts/ti/omap/am335x-boneblack.dts BPI-Router-Linux-kernel-6.16.12/arch/arm/boot/dts/ti/omap/am335x-boneblack.dts ---- BPI-Router-Linux-kernel/arch/arm/boot/dts/ti/omap/am335x-boneblack.dts 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm/boot/dts/ti/omap/am335x-boneblack.dts 2025-10-22 13:53:56.283170260 -0400 -@@ -35,7 +35,7 @@ - "P9_18 [spi0_d1]", - "P9_17 [spi0_cs0]", - "[mmc0_cd]", -- "P8_42A [ecappwm0]", -+ "P9_42A [ecappwm0]", - "P8_35 [lcd d12]", - "P8_33 [lcd d13]", - "P8_31 [lcd d14]", -diff -purNx .git BPI-Router-Linux-kernel/arch/arm/crypto/aes-neonbs-glue.c BPI-Router-Linux-kernel-6.16.12/arch/arm/crypto/aes-neonbs-glue.c ---- BPI-Router-Linux-kernel/arch/arm/crypto/aes-neonbs-glue.c 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm/crypto/aes-neonbs-glue.c 2025-10-22 13:53:56.283170260 -0400 -@@ -206,7 +206,7 @@ static int ctr_encrypt(struct skcipher_r - while (walk.nbytes > 0) { - const u8 *src = walk.src.virt.addr; - u8 *dst = walk.dst.virt.addr; -- int bytes = walk.nbytes; -+ unsigned int bytes = walk.nbytes; - - if (unlikely(bytes < AES_BLOCK_SIZE)) - src = dst = memcpy(buf + sizeof(buf) - bytes, -diff -purNx .git BPI-Router-Linux-kernel/arch/arm/include/asm/pgtable.h BPI-Router-Linux-kernel-6.16.12/arch/arm/include/asm/pgtable.h ---- BPI-Router-Linux-kernel/arch/arm/include/asm/pgtable.h 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm/include/asm/pgtable.h 2025-10-22 13:53:56.283170260 -0400 -@@ -301,7 +301,7 @@ static inline pte_t pte_modify(pte_t pte - #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) - #define __swp_entry_to_pte(swp) __pte((swp).val) - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_isset(pte, L_PTE_SWP_EXCLUSIVE); - } -diff -purNx .git BPI-Router-Linux-kernel/arch/arm/Kconfig BPI-Router-Linux-kernel-6.16.12/arch/arm/Kconfig ---- BPI-Router-Linux-kernel/arch/arm/Kconfig 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm/Kconfig 2025-10-22 13:53:56.279170279 -0400 -@@ -121,7 +121,7 @@ config ARM - select HAVE_KERNEL_XZ - select HAVE_KPROBES if !XIP_KERNEL && !CPU_ENDIAN_BE32 && !CPU_V7M - select HAVE_KRETPROBES if HAVE_KPROBES -- select HAVE_LD_DEAD_CODE_DATA_ELIMINATION if (LD_VERSION >= 23600 || LD_CAN_USE_KEEP_IN_OVERLAY) -+ select HAVE_LD_DEAD_CODE_DATA_ELIMINATION if (LD_VERSION >= 23600 || LD_IS_LLD) && LD_CAN_USE_KEEP_IN_OVERLAY - select HAVE_MOD_ARCH_SPECIFIC - select HAVE_NMI - select HAVE_OPTPROBES if !THUMB2_KERNEL -diff -purNx .git BPI-Router-Linux-kernel/arch/arm/lib/crypto/poly1305-glue.c BPI-Router-Linux-kernel-6.16.12/arch/arm/lib/crypto/poly1305-glue.c ---- BPI-Router-Linux-kernel/arch/arm/lib/crypto/poly1305-glue.c 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm/lib/crypto/poly1305-glue.c 2025-10-22 13:53:56.283170260 -0400 -@@ -7,6 +7,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -39,7 +40,7 @@ void poly1305_blocks_arch(struct poly130 - { - len = round_down(len, POLY1305_BLOCK_SIZE); - if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && -- static_branch_likely(&have_neon)) { -+ static_branch_likely(&have_neon) && likely(may_use_simd())) { - do { - unsigned int todo = min_t(unsigned int, len, SZ_4K); - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm/mach-rockchip/platsmp.c BPI-Router-Linux-kernel-6.16.12/arch/arm/mach-rockchip/platsmp.c ---- BPI-Router-Linux-kernel/arch/arm/mach-rockchip/platsmp.c 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm/mach-rockchip/platsmp.c 2025-10-22 13:53:56.283170260 -0400 -@@ -279,11 +279,6 @@ static void __init rockchip_smp_prepare_ - } - - if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) { -- if (rockchip_smp_prepare_sram(node)) { -- of_node_put(node); -- return; -- } -- - /* enable the SCU power domain */ - pmu_set_power_domain(PMU_PWRDN_SCU, true); - -@@ -316,11 +311,19 @@ static void __init rockchip_smp_prepare_ - asm ("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr)); - ncores = ((l2ctlr >> 24) & 0x3) + 1; - } -- of_node_put(node); - - /* Make sure that all cores except the first are really off */ - for (i = 1; i < ncores; i++) - pmu_set_power_domain(0 + i, false); -+ -+ if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) { -+ if (rockchip_smp_prepare_sram(node)) { -+ of_node_put(node); -+ return; -+ } -+ } -+ -+ of_node_put(node); - } - - static void __init rk3036_smp_prepare_cpus(unsigned int max_cpus) -diff -purNx .git BPI-Router-Linux-kernel/arch/arm/mach-s3c/gpio-samsung.c BPI-Router-Linux-kernel-6.16.12/arch/arm/mach-s3c/gpio-samsung.c ---- BPI-Router-Linux-kernel/arch/arm/mach-s3c/gpio-samsung.c 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm/mach-s3c/gpio-samsung.c 2025-10-22 13:53:56.283170260 -0400 -@@ -516,7 +516,7 @@ static void __init samsung_gpiolib_add(s - gc->direction_input = samsung_gpiolib_2bit_input; - if (!gc->direction_output) - gc->direction_output = samsung_gpiolib_2bit_output; -- if (!gc->set) -+ if (!gc->set_rv) - gc->set_rv = samsung_gpiolib_set; - if (!gc->get) - gc->get = samsung_gpiolib_get; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm/mach-tegra/reset.c BPI-Router-Linux-kernel-6.16.12/arch/arm/mach-tegra/reset.c ---- BPI-Router-Linux-kernel/arch/arm/mach-tegra/reset.c 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm/mach-tegra/reset.c 2025-10-22 13:53:56.283170260 -0400 -@@ -63,7 +63,7 @@ static void __init tegra_cpu_reset_handl - BUG_ON(is_enabled); - BUG_ON(tegra_cpu_reset_handler_size > TEGRA_IRAM_RESET_HANDLER_SIZE); - -- memcpy(iram_base, (void *)__tegra_cpu_reset_handler_start, -+ memcpy_toio(iram_base, (void *)__tegra_cpu_reset_handler_start, - tegra_cpu_reset_handler_size); - - err = call_firmware_op(set_cpu_boot_addr, 0, reset_address); -diff -purNx .git BPI-Router-Linux-kernel/arch/arm/Makefile BPI-Router-Linux-kernel-6.16.12/arch/arm/Makefile ---- BPI-Router-Linux-kernel/arch/arm/Makefile 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm/Makefile 2025-10-22 13:53:56.279170279 -0400 -@@ -149,7 +149,7 @@ endif - # Need -Uarm for gcc < 3.x - KBUILD_CPPFLAGS +=$(cpp-y) - KBUILD_CFLAGS +=$(CFLAGS_ABI) $(CFLAGS_ISA) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm --KBUILD_AFLAGS +=$(CFLAGS_ABI) $(AFLAGS_ISA) -Wa,$(arch-y) $(tune-y) -include asm/unified.h -msoft-float -+KBUILD_AFLAGS +=$(CFLAGS_ABI) $(AFLAGS_ISA) -Wa,$(arch-y) $(tune-y) -include $(srctree)/arch/arm/include/asm/unified.h -msoft-float - KBUILD_RUSTFLAGS += --target=arm-unknown-linux-gnueabi - - CHECKFLAGS += -D__arm__ -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -131,7 +131,7 @@ - "PH5", "PH6", "PH7", "PH9", "PH10", - "PH14", "PH15", "PH16", "PH17", "PH18"; - allwinner,pinmux = <5>; -- function = "emac0"; -+ function = "gmac0"; - drive-strength = <40>; - bias-disable; - }; -@@ -540,8 +540,8 @@ - status = "disabled"; - }; - -- emac0: ethernet@4500000 { -- compatible = "allwinner,sun55i-a523-emac0", -+ gmac0: ethernet@4500000 { -+ compatible = "allwinner,sun55i-a523-gmac0", - "allwinner,sun50i-a64-emac"; - reg = <0x04500000 0x10000>; - clocks = <&ccu CLK_BUS_EMAC0>; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts 2025-10-22 13:53:56.283170260 -0400 -@@ -12,7 +12,7 @@ - compatible = "radxa,cubie-a5e", "allwinner,sun55i-a527"; - - aliases { -- ethernet0 = &emac0; -+ ethernet0 = &gmac0; - serial0 = &uart0; - }; - -@@ -55,7 +55,7 @@ - status = "okay"; - }; - --&emac0 { -+&gmac0 { - phy-mode = "rgmii-id"; - phy-handle = <&ext_rgmii_phy>; - phy-supply = <®_cldo3>; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts 2025-10-22 13:53:56.283170260 -0400 -@@ -12,7 +12,7 @@ - compatible = "yuzukihd,avaota-a1", "allwinner,sun55i-t527"; - - aliases { -- ethernet0 = &emac0; -+ ethernet0 = &gmac0; - serial0 = &uart0; - }; - -@@ -65,7 +65,7 @@ - status = "okay"; - }; - --&emac0 { -+&gmac0 { - phy-mode = "rgmii-id"; - phy-handle = <&ext_rgmii_phy>; - phy-supply = <®_dcdc4>; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/apple/spi1-nvram.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/apple/spi1-nvram.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/apple/spi1-nvram.dtsi 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/apple/spi1-nvram.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -20,8 +20,6 @@ - compatible = "jedec,spi-nor"; - reg = <0x0>; - spi-max-frequency = <25000000>; -- #address-cells = <1>; -- #size-cells = <1>; - - partitions { - compatible = "fixed-partitions"; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/apple/t8012-j132.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/apple/t8012-j132.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/apple/t8012-j132.dts 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/apple/t8012-j132.dts 2025-10-22 13:53:56.283170260 -0400 -@@ -7,6 +7,7 @@ - /dts-v1/; - - #include "t8012-jxxx.dtsi" -+#include "t8012-touchbar.dtsi" - - / { - model = "Apple T2 MacBookPro15,2 (j132)"; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/apple/t8103.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/apple/t8103.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/apple/t8103.dtsi 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/apple/t8103.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -405,8 +405,6 @@ - compatible = "apple,t8103-display-pipe-mipi", "apple,h7-display-pipe-mipi"; - reg = <0x2 0x28600000 0x0 0x100000>; - power-domains = <&ps_mipi_dsi>; -- #address-cells = <1>; -- #size-cells = <0>; - status = "disabled"; - - ports { -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/apple/t8103-j293.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/apple/t8103-j293.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/apple/t8103-j293.dts 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/apple/t8103-j293.dts 2025-10-22 13:53:56.283170260 -0400 -@@ -100,6 +100,8 @@ - - &displaydfr_mipi { - status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; - - dfr_panel: panel@0 { - compatible = "apple,j293-summit", "apple,summit"; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -71,7 +71,7 @@ - */ - &port00 { - bus-range = <1 1>; -- wifi0: network@0,0 { -+ wifi0: wifi@0,0 { - compatible = "pci14e4,4425"; - reg = <0x10000 0x0 0x0 0x0 0x0>; - /* To be filled by the loader */ -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/apple/t8112.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/apple/t8112.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/apple/t8112.dtsi 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/apple/t8112.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -420,8 +420,6 @@ - compatible = "apple,t8112-display-pipe-mipi", "apple,h7-display-pipe-mipi"; - reg = <0x2 0x28600000 0x0 0x100000>; - power-domains = <&ps_mipi_dsi>; -- #address-cells = <1>; -- #size-cells = <0>; - status = "disabled"; - - ports { -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/apple/t8112-j493.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/apple/t8112-j493.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/apple/t8112-j493.dts 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/apple/t8112-j493.dts 2025-10-22 13:53:56.283170260 -0400 -@@ -63,6 +63,8 @@ - - &displaydfr_mipi { - status = "okay"; -+ #address-cells = <1>; -+ #size-cells = <0>; - - dfr_panel: panel@0 { - compatible = "apple,j493-summit", "apple,summit"; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/exynos/exynos7870.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/exynos/exynos7870.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/exynos/exynos7870.dtsi 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/exynos/exynos7870.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -327,6 +327,7 @@ - phys = <&usbdrd_phy 0>; - - usb-role-switch; -+ snps,usb2-gadget-lpm-disable; - }; - }; - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/exynos/exynos7870-j6lte.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/exynos/exynos7870-j6lte.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/exynos/exynos7870-j6lte.dts 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/exynos/exynos7870-j6lte.dts 2025-10-22 13:53:56.283170260 -0400 -@@ -89,7 +89,7 @@ - memory@40000000 { - device_type = "memory"; - reg = <0x0 0x40000000 0x3d800000>, -- <0x0 0x80000000 0x7d800000>; -+ <0x0 0x80000000 0x40000000>; - }; - - pwrseq_mmc1: pwrseq-mmc1 { -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/exynos/exynos7870-on7xelte.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/exynos/exynos7870-on7xelte.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/exynos/exynos7870-on7xelte.dts 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/exynos/exynos7870-on7xelte.dts 2025-10-22 13:53:56.283170260 -0400 -@@ -78,7 +78,7 @@ - memory@40000000 { - device_type = "memory"; - reg = <0x0 0x40000000 0x3e400000>, -- <0x0 0x80000000 0xbe400000>; -+ <0x0 0x80000000 0x80000000>; - }; - - pwrseq_mmc1: pwrseq-mmc1 { -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/exynos/google/gs101.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/exynos/google/gs101.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/exynos/google/gs101.dtsi 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/exynos/google/gs101.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -155,6 +155,7 @@ - idle-state-name = "c2"; - compatible = "arm,idle-state"; - arm,psci-suspend-param = <0x0010000>; -+ local-timer-stop; - entry-latency-us = <70>; - exit-latency-us = <160>; - min-residency-us = <2000>; -@@ -164,6 +165,7 @@ - idle-state-name = "c2"; - compatible = "arm,idle-state"; - arm,psci-suspend-param = <0x0010000>; -+ local-timer-stop; - entry-latency-us = <150>; - exit-latency-us = <190>; - min-residency-us = <2500>; -@@ -173,6 +175,7 @@ - idle-state-name = "c2"; - compatible = "arm,idle-state"; - arm,psci-suspend-param = <0x0010000>; -+ local-timer-stop; - entry-latency-us = <235>; - exit-latency-us = <220>; - min-residency-us = <3500>; -@@ -1368,6 +1371,7 @@ - <&cmu_hsi2 CLK_GOUT_HSI2_SYSREG_HSI2_PCLK>; - clock-names = "core_clk", "sclk_unipro_main", "fmp", - "aclk", "pclk", "sysreg"; -+ dma-coherent; - freq-table-hz = <0 0>, <0 0>, <0 0>, <0 0>, <0 0>, <0 0>; - pinctrl-0 = <&ufs_rst_n &ufs_refclk_out>; - pinctrl-names = "default"; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -687,11 +687,12 @@ - }; - - wdog0: watchdog@2ad0000 { -- compatible = "fsl,imx21-wdt"; -+ compatible = "fsl,ls1046a-wdt", "fsl,imx21-wdt"; - reg = <0x0 0x2ad0000 0x0 0x10000>; - interrupts = ; - clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL - QORIQ_CLK_PLL_DIV(2)>; -+ big-endian; - }; - - edma0: dma-controller@2c00000 { -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mm-beacon-som.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mm-beacon-som.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mm-beacon-som.dtsi 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mm-beacon-som.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -294,6 +294,8 @@ - pinctrl-0 = <&pinctrl_usdhc3>; - pinctrl-1 = <&pinctrl_usdhc3_100mhz>; - pinctrl-2 = <&pinctrl_usdhc3_200mhz>; -+ assigned-clocks = <&clk IMX8MM_CLK_USDHC3>; -+ assigned-clock-rates = <400000000>; - bus-width = <8>; - non-removable; - status = "okay"; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -464,6 +464,7 @@ - }; - - reg_nvcc_sd: LDO5 { -+ regulator-always-on; - regulator-max-microvolt = <3300000>; - regulator-min-microvolt = <1800000>; - regulator-name = "On-module +V3.3_1.8_SD (LDO5)"; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mn-beacon-som.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mn-beacon-som.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mn-beacon-som.dtsi 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mn-beacon-som.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -305,6 +305,8 @@ - pinctrl-0 = <&pinctrl_usdhc3>; - pinctrl-1 = <&pinctrl_usdhc3_100mhz>; - pinctrl-2 = <&pinctrl_usdhc3_200mhz>; -+ assigned-clocks = <&clk IMX8MN_CLK_USDHC3>; -+ assigned-clock-rates = <400000000>; - bus-width = <8>; - non-removable; - status = "okay"; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts 2025-10-22 13:53:56.283170260 -0400 -@@ -555,6 +555,7 @@ - pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; - cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; - vmmc-supply = <®_usdhc2_vmmc>; -+ vqmmc-supply = <&ldo5>; - bus-width = <4>; - status = "okay"; - }; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -609,6 +609,7 @@ - pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; - cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; - vmmc-supply = <®_usdhc2_vmmc>; -+ vqmmc-supply = <&ldo5>; - bus-width = <4>; - status = "okay"; - }; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp.dtsi 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -298,7 +298,7 @@ - cpu-thermal { - polling-delay-passive = <250>; - polling-delay = <2000>; -- thermal-sensors = <&tmu 0>; -+ thermal-sensors = <&tmu 1>; - trips { - cpu_alert0: trip0 { - temperature = <85000>; -@@ -328,7 +328,7 @@ - soc-thermal { - polling-delay-passive = <250>; - polling-delay = <2000>; -- thermal-sensors = <&tmu 1>; -+ thermal-sensors = <&tmu 0>; - trips { - soc_alert0: trip0 { - temperature = <85000>; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp-toradex-smarc-dev.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp-toradex-smarc-dev.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp-toradex-smarc-dev.dts 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp-toradex-smarc-dev.dts 2025-10-22 13:53:56.283170260 -0400 -@@ -102,11 +102,6 @@ - <&pinctrl_gpio13>; - }; - --&gpio3 { -- pinctrl-names = "default"; -- pinctrl-0 = <&pinctrl_lvds_dsi_sel>; --}; -- - &gpio4 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_gpio4>, <&pinctrl_gpio6>; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp-toradex-smarc.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp-toradex-smarc.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp-toradex-smarc.dtsi 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp-toradex-smarc.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -320,6 +320,8 @@ - }; - - &gpio3 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_lvds_dsi_sel>; - gpio-line-names = "ETH_0_INT#", /* 0 */ - "SLEEP#", - "", -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql.dtsi 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -24,6 +24,20 @@ - regulator-max-microvolt = <3300000>; - regulator-always-on; - }; -+ -+ reg_usdhc2_vqmmc: regulator-usdhc2-vqmmc { -+ compatible = "regulator-gpio"; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&pinctrl_reg_usdhc2_vqmmc>; -+ regulator-name = "V_SD2"; -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <3300000>; -+ gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>; -+ states = <1800000 0x1>, -+ <3300000 0x0>; -+ vin-supply = <&ldo5_reg>; -+ status = "disabled"; -+ }; - }; - - &A53_0 { -@@ -180,6 +194,10 @@ - }; - }; - -+&usdhc2 { -+ vqmmc-supply = <®_usdhc2_vqmmc>; -+}; -+ - &usdhc3 { - pinctrl-names = "default", "state_100mhz", "state_200mhz"; - pinctrl-0 = <&pinctrl_usdhc3>; -@@ -229,6 +247,10 @@ - fsl,pins = ; - }; - -+ pinctrl_reg_usdhc2_vqmmc: regusdhc2vqmmcgrp { -+ fsl,pins = ; -+ }; -+ - pinctrl_usdhc3: usdhc3grp { - fsl,pins = , - , -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mp-ras314.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mp-ras314.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mp-ras314.dts 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mp-ras314.dts 2025-10-22 13:53:56.283170260 -0400 -@@ -467,6 +467,10 @@ - status = "okay"; - }; - -+®_usdhc2_vqmmc { -+ status = "okay"; -+}; -+ - &sai5 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_sai5>; -@@ -876,8 +880,7 @@ - , - , - , -- , -- ; -+ ; - }; - - pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp { -@@ -886,8 +889,7 @@ - , - , - , -- , -- ; -+ ; - }; - - pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp { -@@ -896,8 +898,7 @@ - , - , - , -- , -- ; -+ ; - }; - - pinctrl_usdhc2_gpio: usdhc2-gpiogrp { -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts 2025-10-22 13:53:56.283170260 -0400 -@@ -603,6 +603,10 @@ - status = "okay"; - }; - -+®_usdhc2_vqmmc { -+ status = "okay"; -+}; -+ - &sai3 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_sai3>; -@@ -982,8 +986,7 @@ - , - , - , -- , -- ; -+ ; - }; - - pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp { -@@ -992,8 +995,7 @@ - , - , - , -- , -- ; -+ ; - }; - - pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp { -@@ -1002,8 +1004,7 @@ - , - , - , -- , -- ; -+ ; - }; - - pinctrl_usdhc2_gpio: usdhc2-gpiogrp { -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp-venice-gw71xx.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp-venice-gw71xx.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp-venice-gw71xx.dtsi 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp-venice-gw71xx.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -70,7 +70,7 @@ - tpm@1 { - compatible = "atmel,attpm20p", "tcg,tpm_tis-spi"; - reg = <0x1>; -- spi-max-frequency = <36000000>; -+ spi-max-frequency = <25000000>; - }; - }; - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -110,7 +110,7 @@ - tpm@1 { - compatible = "atmel,attpm20p", "tcg,tpm_tis-spi"; - reg = <0x1>; -- spi-max-frequency = <36000000>; -+ spi-max-frequency = <25000000>; - }; - }; - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -122,7 +122,7 @@ - tpm@1 { - compatible = "atmel,attpm20p", "tcg,tpm_tis-spi"; - reg = <0x1>; -- spi-max-frequency = <36000000>; -+ spi-max-frequency = <25000000>; - }; - }; - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts 2025-10-22 13:53:56.283170260 -0400 -@@ -201,7 +201,7 @@ - tpm@0 { - compatible = "atmel,attpm20p", "tcg,tpm_tis-spi"; - reg = <0x0>; -- spi-max-frequency = <36000000>; -+ spi-max-frequency = <25000000>; - }; - }; - -@@ -301,7 +301,7 @@ - &gpio3 { - gpio-line-names = - "", "", "", "", "", "", "m2_rst", "", -- "", "", "", "", "", "", "m2_gpio10", "", -+ "", "", "", "", "", "", "m2_wdis2#", "", - "", "", "", "", "", "", "", "", - "", "", "", "", "", "", "", ""; - }; -@@ -310,7 +310,7 @@ - gpio-line-names = - "", "", "m2_off#", "", "", "", "", "", - "", "", "", "", "", "", "", "", -- "", "", "m2_wdis#", "", "", "", "", "", -+ "", "", "m2_wdis1#", "", "", "", "", "", - "", "", "", "", "", "", "", "rs485_en"; - }; - -@@ -811,14 +811,14 @@ - MX8MP_IOMUXC_GPIO1_IO09__GPIO1_IO09 0x40000040 /* DIO0 */ - MX8MP_IOMUXC_GPIO1_IO11__GPIO1_IO11 0x40000040 /* DIO1 */ - MX8MP_IOMUXC_SAI1_RXD0__GPIO4_IO02 0x40000040 /* M2SKT_OFF# */ -- MX8MP_IOMUXC_SAI1_TXD6__GPIO4_IO18 0x40000150 /* M2SKT_WDIS# */ -+ MX8MP_IOMUXC_SAI1_TXD6__GPIO4_IO18 0x40000150 /* M2SKT_WDIS1# */ - MX8MP_IOMUXC_SD1_DATA4__GPIO2_IO06 0x40000040 /* M2SKT_PIN20 */ - MX8MP_IOMUXC_SD1_STROBE__GPIO2_IO11 0x40000040 /* M2SKT_PIN22 */ - MX8MP_IOMUXC_SD2_CLK__GPIO2_IO13 0x40000150 /* PCIE1_WDIS# */ - MX8MP_IOMUXC_SD2_CMD__GPIO2_IO14 0x40000150 /* PCIE3_WDIS# */ - MX8MP_IOMUXC_SD2_DATA3__GPIO2_IO18 0x40000150 /* PCIE2_WDIS# */ - MX8MP_IOMUXC_NAND_DATA00__GPIO3_IO06 0x40000040 /* M2SKT_RST# */ -- MX8MP_IOMUXC_NAND_DQS__GPIO3_IO14 0x40000040 /* M2SKT_GPIO10 */ -+ MX8MP_IOMUXC_NAND_DQS__GPIO3_IO14 0x40000150 /* M2KST_WDIS2# */ - MX8MP_IOMUXC_SAI3_TXD__GPIO5_IO01 0x40000104 /* UART_TERM */ - MX8MP_IOMUXC_SAI3_TXFS__GPIO4_IO31 0x40000104 /* UART_RS485 */ - MX8MP_IOMUXC_SAI3_TXC__GPIO5_IO00 0x40000104 /* UART_HALF */ -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: (GPL-2.0-or-later OR MIT) - /* -- * Copyright (c) 2022 TQ-Systems GmbH , -+ * Copyright (c) 2022-2025 TQ-Systems GmbH , - * D-82229 Seefeld, Germany. - * Author: Markus Niebel - */ -@@ -110,11 +110,11 @@ - regulator-ramp-delay = <3125>; - }; - -- /* V_DDRQ - 1.1 LPDDR4 or 0.6 LPDDR4X */ -+ /* V_DDRQ - 0.6 V for LPDDR4X */ - buck2: BUCK2 { - regulator-name = "BUCK2"; - regulator-min-microvolt = <600000>; -- regulator-max-microvolt = <1100000>; -+ regulator-max-microvolt = <600000>; - regulator-boot-on; - regulator-always-on; - regulator-ramp-delay = <3125>; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx95-15x15-evk.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx95-15x15-evk.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx95-15x15-evk.dts 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx95-15x15-evk.dts 2025-10-22 13:53:56.283170260 -0400 -@@ -574,17 +574,17 @@ - &scmi_iomuxc { - pinctrl_emdio: emdiogrp { - fsl,pins = < -- IMX95_PAD_ENET2_MDC__NETCMIX_TOP_NETC_MDC 0x57e -- IMX95_PAD_ENET2_MDIO__NETCMIX_TOP_NETC_MDIO 0x97e -+ IMX95_PAD_ENET2_MDC__NETCMIX_TOP_NETC_MDC 0x50e -+ IMX95_PAD_ENET2_MDIO__NETCMIX_TOP_NETC_MDIO 0x90e - >; - }; - - pinctrl_enetc0: enetc0grp { - fsl,pins = < -- IMX95_PAD_ENET1_TD3__NETCMIX_TOP_ETH0_RGMII_TD3 0x57e -- IMX95_PAD_ENET1_TD2__NETCMIX_TOP_ETH0_RGMII_TD2 0x57e -- IMX95_PAD_ENET1_TD1__NETCMIX_TOP_ETH0_RGMII_TD1 0x57e -- IMX95_PAD_ENET1_TD0__NETCMIX_TOP_ETH0_RGMII_TD0 0x57e -+ IMX95_PAD_ENET1_TD3__NETCMIX_TOP_ETH0_RGMII_TD3 0x50e -+ IMX95_PAD_ENET1_TD2__NETCMIX_TOP_ETH0_RGMII_TD2 0x50e -+ IMX95_PAD_ENET1_TD1__NETCMIX_TOP_ETH0_RGMII_TD1 0x50e -+ IMX95_PAD_ENET1_TD0__NETCMIX_TOP_ETH0_RGMII_TD0 0x50e - IMX95_PAD_ENET1_TX_CTL__NETCMIX_TOP_ETH0_RGMII_TX_CTL 0x57e - IMX95_PAD_ENET1_TXC__NETCMIX_TOP_ETH0_RGMII_TX_CLK 0x58e - IMX95_PAD_ENET1_RX_CTL__NETCMIX_TOP_ETH0_RGMII_RX_CTL 0x57e -@@ -598,10 +598,10 @@ - - pinctrl_enetc1: enetc1grp { - fsl,pins = < -- IMX95_PAD_ENET2_TD3__NETCMIX_TOP_ETH1_RGMII_TD3 0x57e -- IMX95_PAD_ENET2_TD2__NETCMIX_TOP_ETH1_RGMII_TD2 0x57e -- IMX95_PAD_ENET2_TD1__NETCMIX_TOP_ETH1_RGMII_TD1 0x57e -- IMX95_PAD_ENET2_TD0__NETCMIX_TOP_ETH1_RGMII_TD0 0x57e -+ IMX95_PAD_ENET2_TD3__NETCMIX_TOP_ETH1_RGMII_TD3 0x50e -+ IMX95_PAD_ENET2_TD2__NETCMIX_TOP_ETH1_RGMII_TD2 0x50e -+ IMX95_PAD_ENET2_TD1__NETCMIX_TOP_ETH1_RGMII_TD1 0x50e -+ IMX95_PAD_ENET2_TD0__NETCMIX_TOP_ETH1_RGMII_TD0 0x50e - IMX95_PAD_ENET2_TX_CTL__NETCMIX_TOP_ETH1_RGMII_TX_CTL 0x57e - IMX95_PAD_ENET2_TXC__NETCMIX_TOP_ETH1_RGMII_TX_CLK 0x58e - IMX95_PAD_ENET2_RX_CTL__NETCMIX_TOP_ETH1_RGMII_RX_CTL 0x57e -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx95-19x19-evk.dts 2025-10-22 13:53:56.283170260 -0400 -@@ -566,17 +566,17 @@ - &scmi_iomuxc { - pinctrl_emdio: emdiogrp{ - fsl,pins = < -- IMX95_PAD_ENET1_MDC__NETCMIX_TOP_NETC_MDC 0x57e -- IMX95_PAD_ENET1_MDIO__NETCMIX_TOP_NETC_MDIO 0x97e -+ IMX95_PAD_ENET1_MDC__NETCMIX_TOP_NETC_MDC 0x50e -+ IMX95_PAD_ENET1_MDIO__NETCMIX_TOP_NETC_MDIO 0x90e - >; - }; - - pinctrl_enetc0: enetc0grp { - fsl,pins = < -- IMX95_PAD_ENET1_TD3__NETCMIX_TOP_ETH0_RGMII_TD3 0x57e -- IMX95_PAD_ENET1_TD2__NETCMIX_TOP_ETH0_RGMII_TD2 0x57e -- IMX95_PAD_ENET1_TD1__NETCMIX_TOP_ETH0_RGMII_TD1 0x57e -- IMX95_PAD_ENET1_TD0__NETCMIX_TOP_ETH0_RGMII_TD0 0x57e -+ IMX95_PAD_ENET1_TD3__NETCMIX_TOP_ETH0_RGMII_TD3 0x50e -+ IMX95_PAD_ENET1_TD2__NETCMIX_TOP_ETH0_RGMII_TD2 0x50e -+ IMX95_PAD_ENET1_TD1__NETCMIX_TOP_ETH0_RGMII_TD1 0x50e -+ IMX95_PAD_ENET1_TD0__NETCMIX_TOP_ETH0_RGMII_TD0 0x50e - IMX95_PAD_ENET1_TX_CTL__NETCMIX_TOP_ETH0_RGMII_TX_CTL 0x57e - IMX95_PAD_ENET1_TXC__NETCMIX_TOP_ETH0_RGMII_TX_CLK 0x58e - IMX95_PAD_ENET1_RX_CTL__NETCMIX_TOP_ETH0_RGMII_RX_CTL 0x57e -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx95.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx95.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/freescale/imx95.dtsi 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/freescale/imx95.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -1708,7 +1708,7 @@ - <0x9 0 1 0>; - reg-names = "dbi","atu", "dbi2", "app", "dma", "addr_space"; - num-lanes = <1>; -- interrupts = ; -+ interrupts = ; - interrupt-names = "dma"; - clocks = <&scmi_clk IMX95_CLK_HSIO>, - <&scmi_clk IMX95_CLK_HSIOPLL>, -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/marvell/cn9130-cf.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/marvell/cn9130-cf.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/marvell/cn9130-cf.dtsi 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/marvell/cn9130-cf.dtsi 2025-10-22 13:53:56.283170260 -0400 -@@ -152,11 +152,12 @@ - - /* SRDS #0 - SATA on M.2 connector */ - &cp0_sata0 { -- phys = <&cp0_comphy0 1>; - status = "okay"; - -- /* only port 1 is available */ -- /delete-node/ sata-port@0; -+ sata-port@1 { -+ phys = <&cp0_comphy0 1>; -+ status = "okay"; -+ }; - }; - - /* microSD */ -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/marvell/cn9131-cf-solidwan.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/marvell/cn9131-cf-solidwan.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/marvell/cn9131-cf-solidwan.dts 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/marvell/cn9131-cf-solidwan.dts 2025-10-22 13:53:56.283170260 -0400 -@@ -563,11 +563,13 @@ - - /* SRDS #1 - SATA on M.2 (J44) */ - &cp1_sata0 { -- phys = <&cp1_comphy1 0>; - status = "okay"; - - /* only port 0 is available */ -- /delete-node/ sata-port@1; -+ sata-port@0 { -+ phys = <&cp1_comphy1 0>; -+ status = "okay"; -+ }; - }; - - &cp1_syscon0 { -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/marvell/cn9132-clearfog.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/marvell/cn9132-clearfog.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/marvell/cn9132-clearfog.dts 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/marvell/cn9132-clearfog.dts 2025-10-22 13:53:56.287170240 -0400 -@@ -413,7 +413,13 @@ - /* SRDS #0,#1,#2,#3 - PCIe */ - &cp0_pcie0 { - num-lanes = <4>; -- phys = <&cp0_comphy0 0>, <&cp0_comphy1 0>, <&cp0_comphy2 0>, <&cp0_comphy3 0>; -+ /* -+ * The mvebu-comphy driver does not currently know how to pass correct -+ * lane-count to ATF while configuring the serdes lanes. -+ * Rely on bootloader configuration only. -+ * -+ * phys = <&cp0_comphy0 0>, <&cp0_comphy1 0>, <&cp0_comphy2 0>, <&cp0_comphy3 0>; -+ */ - status = "okay"; - }; - -@@ -475,7 +481,13 @@ - /* SRDS #0,#1 - PCIe */ - &cp1_pcie0 { - num-lanes = <2>; -- phys = <&cp1_comphy0 0>, <&cp1_comphy1 0>; -+ /* -+ * The mvebu-comphy driver does not currently know how to pass correct -+ * lane-count to ATF while configuring the serdes lanes. -+ * Rely on bootloader configuration only. -+ * -+ * phys = <&cp1_comphy0 0>, <&cp1_comphy1 0>; -+ */ - status = "okay"; - }; - -@@ -512,10 +524,9 @@ - status = "okay"; - - /* only port 1 is available */ -- /delete-node/ sata-port@0; -- - sata-port@1 { - phys = <&cp1_comphy3 1>; -+ status = "okay"; - }; - }; - -@@ -631,9 +642,8 @@ - status = "okay"; - - /* only port 1 is available */ -- /delete-node/ sata-port@0; -- - sata-port@1 { -+ status = "okay"; - phys = <&cp2_comphy3 1>; - }; - }; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/marvell/cn9132-sr-cex7.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/marvell/cn9132-sr-cex7.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/marvell/cn9132-sr-cex7.dtsi 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/marvell/cn9132-sr-cex7.dtsi 2025-10-22 13:53:56.287170240 -0400 -@@ -137,6 +137,14 @@ - pinctrl-0 = <&ap_mmc0_pins>; - pinctrl-names = "default"; - vqmmc-supply = <&v_1_8>; -+ /* -+ * Not stable in HS modes - phy needs "more calibration", so disable -+ * UHS (by preventing voltage switch), SDR104, SDR50 and DDR50 modes. -+ */ -+ no-1-8-v; -+ no-sd; -+ no-sdio; -+ non-removable; - status = "okay"; - }; - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/qcom/msm8976.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/qcom/msm8976.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/qcom/msm8976.dtsi 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/qcom/msm8976.dtsi 2025-10-22 13:53:56.287170240 -0400 -@@ -1331,6 +1331,7 @@ - clock-names = "bam_clk"; - #dma-cells = <1>; - qcom,ee = <0>; -+ qcom,controlled-remotely; - }; - - blsp1_uart1: serial@78af000 { -@@ -1451,6 +1452,7 @@ - clock-names = "bam_clk"; - #dma-cells = <1>; - qcom,ee = <0>; -+ qcom,controlled-remotely; - }; - - blsp2_uart2: serial@7af0000 { -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/qcom/qcs615.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/qcom/qcs615.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/qcom/qcs615.dtsi 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/qcom/qcs615.dtsi 2025-10-22 13:53:56.287170240 -0400 -@@ -1902,6 +1902,7 @@ - - clocks = <&aoss_qmp>; - clock-names = "apb_pclk"; -+ status = "disabled"; - - in-ports { - port { -@@ -2461,6 +2462,9 @@ - - clocks = <&aoss_qmp>; - clock-names = "apb_pclk"; -+ -+ /* Not all required clocks can be enabled from the OS */ -+ status = "fail"; - }; - - cti@6c20000 { -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/qcom/sa8775p.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/qcom/sa8775p.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/qcom/sa8775p.dtsi 2025-10-22 13:53:23.055329891 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/qcom/sa8775p.dtsi 2025-10-22 13:53:56.287170240 -0400 -@@ -5571,8 +5571,8 @@ - - interrupts-extended = <&intc GIC_SPI 768 IRQ_TYPE_EDGE_RISING>, - <&smp2p_gpdsp0_in 0 0>, -- <&smp2p_gpdsp0_in 2 0>, - <&smp2p_gpdsp0_in 1 0>, -+ <&smp2p_gpdsp0_in 2 0>, - <&smp2p_gpdsp0_in 3 0>; - interrupt-names = "wdog", "fatal", "ready", - "handover", "stop-ack"; -@@ -5614,8 +5614,8 @@ - - interrupts-extended = <&intc GIC_SPI 624 IRQ_TYPE_EDGE_RISING>, - <&smp2p_gpdsp1_in 0 0>, -- <&smp2p_gpdsp1_in 2 0>, - <&smp2p_gpdsp1_in 1 0>, -+ <&smp2p_gpdsp1_in 2 0>, - <&smp2p_gpdsp1_in 3 0>; - interrupt-names = "wdog", "fatal", "ready", - "handover", "stop-ack"; -@@ -5755,8 +5755,8 @@ - - interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>, - <&smp2p_cdsp0_in 0 IRQ_TYPE_EDGE_RISING>, -- <&smp2p_cdsp0_in 2 IRQ_TYPE_EDGE_RISING>, - <&smp2p_cdsp0_in 1 IRQ_TYPE_EDGE_RISING>, -+ <&smp2p_cdsp0_in 2 IRQ_TYPE_EDGE_RISING>, - <&smp2p_cdsp0_in 3 IRQ_TYPE_EDGE_RISING>; - interrupt-names = "wdog", "fatal", "ready", - "handover", "stop-ack"; -@@ -5887,8 +5887,8 @@ - - interrupts-extended = <&intc GIC_SPI 798 IRQ_TYPE_EDGE_RISING>, - <&smp2p_cdsp1_in 0 IRQ_TYPE_EDGE_RISING>, -- <&smp2p_cdsp1_in 2 IRQ_TYPE_EDGE_RISING>, - <&smp2p_cdsp1_in 1 IRQ_TYPE_EDGE_RISING>, -+ <&smp2p_cdsp1_in 2 IRQ_TYPE_EDGE_RISING>, - <&smp2p_cdsp1_in 3 IRQ_TYPE_EDGE_RISING>; - interrupt-names = "wdog", "fatal", "ready", - "handover", "stop-ack"; -@@ -6043,8 +6043,8 @@ - - interrupts-extended = <&pdc 6 IRQ_TYPE_EDGE_RISING>, - <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>, -- <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>, - <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>, -+ <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>, - <&smp2p_adsp_in 3 IRQ_TYPE_EDGE_RISING>; - interrupt-names = "wdog", "fatal", "ready", "handover", - "stop-ack"; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/qcom/sc7180.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/qcom/sc7180.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/qcom/sc7180.dtsi 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/qcom/sc7180.dtsi 2025-10-22 13:53:56.287170240 -0400 -@@ -3526,18 +3526,18 @@ - #interrupt-cells = <4>; - }; - -- sram@146aa000 { -+ sram@14680000 { - compatible = "qcom,sc7180-imem", "syscon", "simple-mfd"; -- reg = <0 0x146aa000 0 0x2000>; -+ reg = <0 0x14680000 0 0x2e000>; - - #address-cells = <1>; - #size-cells = <1>; - -- ranges = <0 0 0x146aa000 0x2000>; -+ ranges = <0 0 0x14680000 0x2e000>; - -- pil-reloc@94c { -+ pil-reloc@2a94c { - compatible = "qcom,pil-reloc-info"; -- reg = <0x94c 0xc8>; -+ reg = <0x2a94c 0xc8>; - }; - }; - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts 2025-10-22 13:53:56.287170240 -0400 -@@ -1090,6 +1090,8 @@ - }; - - &pmk8280_rtc { -+ qcom,uefi-rtc-info; -+ - status = "okay"; - }; - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/qcom/sdm845.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/qcom/sdm845.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/qcom/sdm845.dtsi 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/qcom/sdm845.dtsi 2025-10-22 13:53:56.287170240 -0400 -@@ -5081,18 +5081,18 @@ - #interrupt-cells = <4>; - }; - -- sram@146bf000 { -+ sram@14680000 { - compatible = "qcom,sdm845-imem", "syscon", "simple-mfd"; -- reg = <0 0x146bf000 0 0x1000>; -+ reg = <0 0x14680000 0 0x40000>; - - #address-cells = <1>; - #size-cells = <1>; - -- ranges = <0 0 0x146bf000 0x1000>; -+ ranges = <0 0 0x14680000 0x40000>; - -- pil-reloc@94c { -+ pil-reloc@3f94c { - compatible = "qcom,pil-reloc-info"; -- reg = <0x94c 0xc8>; -+ reg = <0x3f94c 0xc8>; - }; - }; - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/qcom/x1e80100.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/qcom/x1e80100.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/qcom/x1e80100.dtsi 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/qcom/x1e80100.dtsi 2025-10-22 13:53:56.287170240 -0400 -@@ -8548,7 +8548,7 @@ - ; - }; - -- thermal-zones { -+ thermal_zones: thermal-zones { - aoss0-thermal { - thermal-sensors = <&tsens0 0>; - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/qcom/x1e80100-pmics.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/qcom/x1e80100-pmics.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/qcom/x1e80100-pmics.dtsi 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/qcom/x1e80100-pmics.dtsi 2025-10-22 13:53:56.287170240 -0400 -@@ -224,6 +224,7 @@ - reg-names = "rtc", "alarm"; - interrupts = <0x0 0x62 0x1 IRQ_TYPE_EDGE_RISING>; - qcom,no-alarm; /* alarm owned by ADSP */ -+ qcom,uefi-rtc-info; - }; - - pmk8550_sdam_2: nvram@7100 { -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/qcom/x1p42100.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/qcom/x1p42100.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/qcom/x1p42100.dtsi 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/qcom/x1p42100.dtsi 2025-10-22 13:53:56.287170240 -0400 -@@ -18,6 +18,7 @@ - /delete-node/ &cpu_pd10; - /delete-node/ &cpu_pd11; - /delete-node/ &pcie3_phy; -+/delete-node/ &thermal_zones; - - &gcc { - compatible = "qcom,x1p42100-gcc", "qcom,x1e80100-gcc"; -@@ -79,3 +80,558 @@ - status = "disabled"; - }; - }; -+ -+/* While physically present, this controller is left unconfigured and unused */ -+&tsens3 { -+ status = "disabled"; -+}; -+ -+/ { -+ thermal-zones { -+ aoss0-thermal { -+ thermal-sensors = <&tsens0 0>; -+ -+ trips { -+ trip-point0 { -+ temperature = <90000>; -+ hysteresis = <2000>; -+ type = "hot"; -+ }; -+ -+ trip-point1 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ cpu0-0-top-thermal { -+ thermal-sensors = <&tsens0 1>; -+ -+ trips { -+ trip-point0 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ cpu0-0-btm-thermal { -+ thermal-sensors = <&tsens0 2>; -+ -+ trips { -+ trip-point0 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ cpu0-1-top-thermal { -+ thermal-sensors = <&tsens0 3>; -+ -+ trips { -+ trip-point0 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ cpu0-1-btm-thermal { -+ thermal-sensors = <&tsens0 4>; -+ -+ trips { -+ trip-point0 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ cpu0-2-top-thermal { -+ thermal-sensors = <&tsens0 5>; -+ -+ trips { -+ trip-point0 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ cpu0-2-btm-thermal { -+ thermal-sensors = <&tsens0 6>; -+ -+ trips { -+ trip-point0 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ cpu0-3-top-thermal { -+ thermal-sensors = <&tsens0 7>; -+ -+ trips { -+ trip-point0 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ cpu0-3-btm-thermal { -+ thermal-sensors = <&tsens0 8>; -+ -+ trips { -+ trip-point0 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ cpuss0-top-thermal { -+ thermal-sensors = <&tsens0 9>; -+ -+ trips { -+ trip-point0 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ cpuss0-btm-thermal { -+ thermal-sensors = <&tsens0 10>; -+ -+ trips { -+ trip-point0 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ mem-thermal { -+ thermal-sensors = <&tsens0 11>; -+ -+ trips { -+ trip-point0 { -+ temperature = <90000>; -+ hysteresis = <2000>; -+ type = "hot"; -+ }; -+ -+ trip-point1 { -+ temperature = <115000>; -+ hysteresis = <0>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ video-thermal { -+ thermal-sensors = <&tsens0 12>; -+ -+ trips { -+ trip-point0 { -+ temperature = <90000>; -+ hysteresis = <2000>; -+ type = "hot"; -+ }; -+ -+ trip-point1 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ aoss1-thermal { -+ thermal-sensors = <&tsens1 0>; -+ -+ trips { -+ trip-point0 { -+ temperature = <90000>; -+ hysteresis = <2000>; -+ type = "hot"; -+ }; -+ -+ trip-point1 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ cpu1-0-top-thermal { -+ thermal-sensors = <&tsens1 1>; -+ -+ trips { -+ trip-point0 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ cpu1-0-btm-thermal { -+ thermal-sensors = <&tsens1 2>; -+ -+ trips { -+ trip-point0 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ cpu1-1-top-thermal { -+ thermal-sensors = <&tsens1 3>; -+ -+ trips { -+ trip-point0 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ cpu1-1-btm-thermal { -+ thermal-sensors = <&tsens1 4>; -+ -+ trips { -+ trip-point0 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ cpu1-2-top-thermal { -+ thermal-sensors = <&tsens1 5>; -+ -+ trips { -+ trip-point0 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ cpu1-2-btm-thermal { -+ thermal-sensors = <&tsens1 6>; -+ -+ trips { -+ trip-point0 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ cpu1-3-top-thermal { -+ thermal-sensors = <&tsens1 7>; -+ -+ trips { -+ trip-point0 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ cpu1-3-btm-thermal { -+ thermal-sensors = <&tsens1 8>; -+ -+ trips { -+ trip-point0 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ cpuss1-top-thermal { -+ thermal-sensors = <&tsens1 9>; -+ -+ trips { -+ trip-point0 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ cpuss1-btm-thermal { -+ thermal-sensors = <&tsens1 10>; -+ -+ trips { -+ trip-point0 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ aoss2-thermal { -+ thermal-sensors = <&tsens2 0>; -+ -+ trips { -+ trip-point0 { -+ temperature = <90000>; -+ hysteresis = <2000>; -+ type = "hot"; -+ }; -+ -+ trip-point1 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ nsp0-thermal { -+ thermal-sensors = <&tsens2 1>; -+ -+ trips { -+ trip-point0 { -+ temperature = <90000>; -+ hysteresis = <2000>; -+ type = "hot"; -+ }; -+ -+ trip-point1 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ nsp1-thermal { -+ thermal-sensors = <&tsens2 2>; -+ -+ trips { -+ trip-point0 { -+ temperature = <90000>; -+ hysteresis = <2000>; -+ type = "hot"; -+ }; -+ -+ trip-point1 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ nsp2-thermal { -+ thermal-sensors = <&tsens2 3>; -+ -+ trips { -+ trip-point0 { -+ temperature = <90000>; -+ hysteresis = <2000>; -+ type = "hot"; -+ }; -+ -+ trip-point1 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ nsp3-thermal { -+ thermal-sensors = <&tsens2 4>; -+ -+ trips { -+ trip-point0 { -+ temperature = <90000>; -+ hysteresis = <2000>; -+ type = "hot"; -+ }; -+ -+ trip-point1 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ gpuss-0-thermal { -+ polling-delay-passive = <200>; -+ -+ thermal-sensors = <&tsens2 5>; -+ -+ cooling-maps { -+ map0 { -+ trip = <&gpuss0_alert0>; -+ cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; -+ }; -+ }; -+ -+ trips { -+ gpuss0_alert0: trip-point0 { -+ temperature = <95000>; -+ hysteresis = <1000>; -+ type = "passive"; -+ }; -+ -+ trip-point1 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ gpuss-1-thermal { -+ polling-delay-passive = <200>; -+ -+ thermal-sensors = <&tsens2 6>; -+ -+ cooling-maps { -+ map0 { -+ trip = <&gpuss1_alert0>; -+ cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; -+ }; -+ }; -+ -+ trips { -+ gpuss1_alert0: trip-point0 { -+ temperature = <95000>; -+ hysteresis = <1000>; -+ type = "passive"; -+ }; -+ -+ trip-point1 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ gpuss-2-thermal { -+ polling-delay-passive = <200>; -+ -+ thermal-sensors = <&tsens2 7>; -+ -+ cooling-maps { -+ map0 { -+ trip = <&gpuss2_alert0>; -+ cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; -+ }; -+ }; -+ -+ trips { -+ gpuss2_alert0: trip-point0 { -+ temperature = <95000>; -+ hysteresis = <1000>; -+ type = "passive"; -+ }; -+ -+ trip-point1 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ gpuss-3-thermal { -+ polling-delay-passive = <200>; -+ -+ thermal-sensors = <&tsens2 8>; -+ -+ cooling-maps { -+ map0 { -+ trip = <&gpuss3_alert0>; -+ cooling-device = <&gpu THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; -+ }; -+ }; -+ -+ trips { -+ gpuss3_alert0: trip-point0 { -+ temperature = <95000>; -+ hysteresis = <1000>; -+ type = "passive"; -+ }; -+ -+ trip-point1 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ camera0-thermal { -+ thermal-sensors = <&tsens2 9>; -+ -+ trips { -+ trip-point0 { -+ temperature = <90000>; -+ hysteresis = <2000>; -+ type = "hot"; -+ }; -+ -+ trip-point1 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ -+ camera1-thermal { -+ thermal-sensors = <&tsens2 10>; -+ -+ trips { -+ trip-point0 { -+ temperature = <90000>; -+ hysteresis = <2000>; -+ type = "hot"; -+ }; -+ -+ trip-point1 { -+ temperature = <115000>; -+ hysteresis = <1000>; -+ type = "critical"; -+ }; -+ }; -+ }; -+ }; -+}; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/renesas/Makefile BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/renesas/Makefile ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/renesas/Makefile 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/renesas/Makefile 2025-10-22 13:53:56.287170240 -0400 -@@ -96,6 +96,7 @@ dtb-$(CONFIG_ARCH_R8A779G0) += r8a779g2- - - DTC_FLAGS_r8a779g3-sparrow-hawk += -Wno-spi_bus_bridge - dtb-$(CONFIG_ARCH_R8A779G0) += r8a779g3-sparrow-hawk.dtb -+dtb-$(CONFIG_ARCH_R8A779G0) += r8a779g3-sparrow-hawk-fan-pwm.dtbo - r8a779g3-sparrow-hawk-fan-pwm-dtbs := r8a779g3-sparrow-hawk.dtb r8a779g3-sparrow-hawk-fan-pwm.dtbo - dtb-$(CONFIG_ARCH_R8A779G0) += r8a779g3-sparrow-hawk-fan-pwm.dtb - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/px30.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/px30.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/px30.dtsi 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/px30.dtsi 2025-10-22 13:53:56.287170240 -0400 -@@ -1271,8 +1271,6 @@ - - port@0 { - reg = <0>; -- #address-cells = <1>; -- #size-cells = <0>; - }; - }; - }; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/px30-evb.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/px30-evb.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/px30-evb.dts 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/px30-evb.dts 2025-10-22 13:53:56.287170240 -0400 -@@ -483,8 +483,7 @@ - - ports { - port@0 { -- mipi_in_ucam: endpoint@0 { -- reg = <0>; -+ mipi_in_ucam: endpoint { - data-lanes = <1 2>; - remote-endpoint = <&ucam_out>; - }; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/px30-pp1516.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/px30-pp1516.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/px30-pp1516.dtsi 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/px30-pp1516.dtsi 2025-10-22 13:53:56.287170240 -0400 -@@ -444,8 +444,7 @@ - - ports { - port@0 { -- mipi_in_ucam: endpoint@0 { -- reg = <0>; -+ mipi_in_ucam: endpoint { - data-lanes = <1 2>; - remote-endpoint = <&ucam_out>; - }; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi 2025-10-22 13:53:56.287170240 -0400 -@@ -379,6 +379,18 @@ - <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; - }; - }; -+ -+ spi1 { -+ spi1_csn0_gpio_pin: spi1-csn0-gpio-pin { -+ rockchip,pins = -+ <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up_4ma>; -+ }; -+ -+ spi1_csn1_gpio_pin: spi1-csn1-gpio-pin { -+ rockchip,pins = -+ <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up_4ma>; -+ }; -+ }; - }; - - &pmu_io_domains { -@@ -396,6 +408,17 @@ - vqmmc-supply = <&vccio_sd>; - }; - -+&spi1 { -+ /* -+ * Hardware CS has a very slow rise time of about 6us, -+ * causing transmission errors. -+ * With cs-gpios we have a rise time of about 20ns. -+ */ -+ cs-gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_LOW>, <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&spi1_clk &spi1_csn0_gpio_pin &spi1_csn1_gpio_pin &spi1_miso &spi1_mosi>; -+}; -+ - &tsadc { - status = "okay"; - }; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts 2025-10-22 13:53:56.287170240 -0400 -@@ -966,6 +966,7 @@ - reg = <0>; - m25p,fast-read; - spi-max-frequency = <10000000>; -+ vcc-supply = <&vcc_3v0>; - }; - }; - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3528.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3528.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3528.dtsi 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3528.dtsi 2025-10-22 13:53:56.291170221 -0400 -@@ -445,7 +445,7 @@ - clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>; - clock-names = "baudclk", "apb_pclk"; - interrupts = ; -- dmas = <&dmac 8>, <&dmac 9>; -+ dmas = <&dmac 9>, <&dmac 8>; - reg-io-width = <4>; - reg-shift = <2>; - status = "disabled"; -@@ -457,7 +457,7 @@ - clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>; - clock-names = "baudclk", "apb_pclk"; - interrupts = ; -- dmas = <&dmac 10>, <&dmac 11>; -+ dmas = <&dmac 11>, <&dmac 10>; - reg-io-width = <4>; - reg-shift = <2>; - status = "disabled"; -@@ -469,7 +469,7 @@ - clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>; - clock-names = "baudclk", "apb_pclk"; - interrupts = ; -- dmas = <&dmac 12>, <&dmac 13>; -+ dmas = <&dmac 13>, <&dmac 12>; - reg-io-width = <4>; - reg-shift = <2>; - status = "disabled"; -@@ -481,7 +481,7 @@ - clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>; - clock-names = "baudclk", "apb_pclk"; - interrupts = ; -- dmas = <&dmac 14>, <&dmac 15>; -+ dmas = <&dmac 15>, <&dmac 14>; - reg-io-width = <4>; - reg-shift = <2>; - status = "disabled"; -@@ -493,7 +493,7 @@ - clocks = <&cru SCLK_UART4>, <&cru PCLK_UART4>; - clock-names = "baudclk", "apb_pclk"; - interrupts = ; -- dmas = <&dmac 16>, <&dmac 17>; -+ dmas = <&dmac 17>, <&dmac 16>; - reg-io-width = <4>; - reg-shift = <2>; - status = "disabled"; -@@ -505,7 +505,7 @@ - clocks = <&cru SCLK_UART5>, <&cru PCLK_UART5>; - clock-names = "baudclk", "apb_pclk"; - interrupts = ; -- dmas = <&dmac 18>, <&dmac 19>; -+ dmas = <&dmac 19>, <&dmac 18>; - reg-io-width = <4>; - reg-shift = <2>; - status = "disabled"; -@@ -517,7 +517,7 @@ - clocks = <&cru SCLK_UART6>, <&cru PCLK_UART6>; - clock-names = "baudclk", "apb_pclk"; - interrupts = ; -- dmas = <&dmac 20>, <&dmac 21>; -+ dmas = <&dmac 21>, <&dmac 20>; - reg-io-width = <4>; - reg-shift = <2>; - status = "disabled"; -@@ -529,7 +529,7 @@ - clocks = <&cru SCLK_UART7>, <&cru PCLK_UART7>; - clock-names = "baudclk", "apb_pclk"; - interrupts = ; -- dmas = <&dmac 22>, <&dmac 23>; -+ dmas = <&dmac 23>, <&dmac 22>; - reg-io-width = <4>; - reg-shift = <2>; - status = "disabled"; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3528-pinctrl.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3528-pinctrl.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3528-pinctrl.dtsi 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3528-pinctrl.dtsi 2025-10-22 13:53:56.291170221 -0400 -@@ -98,42 +98,42 @@ - - fephy { - /omit-if-no-ref/ -- fephym0_led_dpx: fephym0-led_dpx { -+ fephym0_led_dpx: fephym0-led-dpx { - rockchip,pins = - /* fephy_led_dpx_m0 */ - <4 RK_PB5 2 &pcfg_pull_none>; - }; - - /omit-if-no-ref/ -- fephym0_led_link: fephym0-led_link { -+ fephym0_led_link: fephym0-led-link { - rockchip,pins = - /* fephy_led_link_m0 */ - <4 RK_PC0 2 &pcfg_pull_none>; - }; - - /omit-if-no-ref/ -- fephym0_led_spd: fephym0-led_spd { -+ fephym0_led_spd: fephym0-led-spd { - rockchip,pins = - /* fephy_led_spd_m0 */ - <4 RK_PB7 2 &pcfg_pull_none>; - }; - - /omit-if-no-ref/ -- fephym1_led_dpx: fephym1-led_dpx { -+ fephym1_led_dpx: fephym1-led-dpx { - rockchip,pins = - /* fephy_led_dpx_m1 */ - <2 RK_PA4 5 &pcfg_pull_none>; - }; - - /omit-if-no-ref/ -- fephym1_led_link: fephym1-led_link { -+ fephym1_led_link: fephym1-led-link { - rockchip,pins = - /* fephy_led_link_m1 */ - <2 RK_PA6 5 &pcfg_pull_none>; - }; - - /omit-if-no-ref/ -- fephym1_led_spd: fephym1-led_spd { -+ fephym1_led_spd: fephym1-led-spd { - rockchip,pins = - /* fephy_led_spd_m1 */ - <2 RK_PA5 5 &pcfg_pull_none>; -@@ -779,7 +779,7 @@ - }; - - /omit-if-no-ref/ -- rgmii_rx_bus2: rgmii-rx_bus2 { -+ rgmii_rx_bus2: rgmii-rx-bus2 { - rockchip,pins = - /* rgmii_rxd0 */ - <3 RK_PA3 2 &pcfg_pull_none>, -@@ -790,7 +790,7 @@ - }; - - /omit-if-no-ref/ -- rgmii_tx_bus2: rgmii-tx_bus2 { -+ rgmii_tx_bus2: rgmii-tx-bus2 { - rockchip,pins = - /* rgmii_txd0 */ - <3 RK_PA1 2 &pcfg_pull_none_drv_level_2>, -@@ -801,7 +801,7 @@ - }; - - /omit-if-no-ref/ -- rgmii_rgmii_clk: rgmii-rgmii_clk { -+ rgmii_rgmii_clk: rgmii-rgmii-clk { - rockchip,pins = - /* rgmii_rxclk */ - <3 RK_PA5 2 &pcfg_pull_none>, -@@ -810,7 +810,7 @@ - }; - - /omit-if-no-ref/ -- rgmii_rgmii_bus: rgmii-rgmii_bus { -+ rgmii_rgmii_bus: rgmii-rgmii-bus { - rockchip,pins = - /* rgmii_rxd2 */ - <3 RK_PA7 2 &pcfg_pull_none>, -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3528-radxa-e20c.dts 2025-10-22 13:53:56.291170221 -0400 -@@ -278,6 +278,7 @@ - &sdhci { - bus-width = <8>; - cap-mmc-highspeed; -+ mmc-hs200-1_8v; - no-sd; - no-sdio; - non-removable; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3566-quartz64-a.dts 2025-10-22 13:53:56.291170221 -0400 -@@ -30,6 +30,7 @@ - - fan: gpio_fan { - compatible = "gpio-fan"; -+ fan-supply = <&vcc12v_dcin>; - gpios = <&gpio0 RK_PD5 GPIO_ACTIVE_HIGH>; - gpio-fan,speed-map = - < 0 0>, -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3568-nanopi-r5s.dts 2025-10-22 13:53:56.291170221 -0400 -@@ -29,7 +29,6 @@ - function-enumerator = <1>; - gpios = <&gpio3 RK_PD6 GPIO_ACTIVE_HIGH>; - label = "LAN-1"; -- linux,default-trigger = "netdev"; - }; - - led-lan2 { -@@ -39,7 +38,6 @@ - function-enumerator = <2>; - gpios = <&gpio3 RK_PD7 GPIO_ACTIVE_HIGH>; - label = "LAN-2"; -- linux,default-trigger = "netdev"; - }; - - power_led: led-sys { -@@ -56,7 +54,6 @@ - function = LED_FUNCTION_WAN; - gpios = <&gpio2 RK_PC1 GPIO_ACTIVE_HIGH>; - label = "WAN"; -- linux,default-trigger = "netdev"; - }; - }; - }; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3576-armsom-sige5.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3576-armsom-sige5.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3576-armsom-sige5.dts 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3576-armsom-sige5.dts 2025-10-22 13:53:56.291170221 -0400 -@@ -211,10 +211,38 @@ - status = "okay"; - }; - -+&cpu_b0 { -+ cpu-supply = <&vdd_cpu_big_s0>; -+}; -+ -+&cpu_b1 { -+ cpu-supply = <&vdd_cpu_big_s0>; -+}; -+ -+&cpu_b2 { -+ cpu-supply = <&vdd_cpu_big_s0>; -+}; -+ -+&cpu_b3 { -+ cpu-supply = <&vdd_cpu_big_s0>; -+}; -+ - &cpu_l0 { - cpu-supply = <&vdd_cpu_lit_s0>; - }; - -+&cpu_l1 { -+ cpu-supply = <&vdd_cpu_lit_s0>; -+}; -+ -+&cpu_l2 { -+ cpu-supply = <&vdd_cpu_lit_s0>; -+}; -+ -+&cpu_l3 { -+ cpu-supply = <&vdd_cpu_lit_s0>; -+}; -+ - &gmac0 { - phy-mode = "rgmii-id"; - clock_in_out = "output"; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3576.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3576.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3576.dtsi 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3576.dtsi 2025-10-22 13:53:56.291170221 -0400 -@@ -615,7 +615,7 @@ - <0 0 0 2 &pcie1_intc 1>, - <0 0 0 3 &pcie1_intc 2>, - <0 0 0 4 &pcie1_intc 3>; -- linux,pci-domain = <0>; -+ linux,pci-domain = <1>; - max-link-speed = <2>; - num-ib-windows = <8>; - num-viewport = <8>; -@@ -1155,12 +1155,14 @@ - <&cru HCLK_VOP>, - <&cru DCLK_VP0>, - <&cru DCLK_VP1>, -- <&cru DCLK_VP2>; -+ <&cru DCLK_VP2>, -+ <&hdptxphy>; - clock-names = "aclk", - "hclk", - "dclk_vp0", - "dclk_vp1", -- "dclk_vp2"; -+ "dclk_vp2", -+ "pll_hdmiphy0"; - iommus = <&vop_mmu>; - power-domains = <&power RK3576_PD_VOP>; - rockchip,grf = <&sys_grf>; -@@ -2391,6 +2393,7 @@ - reg = <0x0 0x2b000000 0x0 0x2000>; - clocks = <&cru CLK_PHY_REF_SRC>, <&cru PCLK_HDPTX_APB>; - clock-names = "ref", "apb"; -+ #clock-cells = <0>; - resets = <&cru SRST_P_HDPTX_APB>, <&cru SRST_HDPTX_INIT>, - <&cru SRST_HDPTX_CMN>, <&cru SRST_HDPTX_LANE>; - reset-names = "apb", "init", "cmn", "lane"; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3576-rock-4d.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3576-rock-4d.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3576-rock-4d.dts 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3576-rock-4d.dts 2025-10-22 13:53:56.291170221 -0400 -@@ -641,14 +641,16 @@ - - &mdio0 { - rgmii_phy0: ethernet-phy@1 { -- compatible = "ethernet-phy-ieee802.3-c22"; -+ compatible = "ethernet-phy-id001c.c916"; - reg = <0x1>; - clocks = <&cru REFCLKO25M_GMAC0_OUT>; -+ assigned-clocks = <&cru REFCLKO25M_GMAC0_OUT>; -+ assigned-clock-rates = <25000000>; - pinctrl-names = "default"; - pinctrl-0 = <&rtl8211f_rst>; - reset-assert-us = <20000>; - reset-deassert-us = <100000>; -- reset-gpio = <&gpio2 RK_PB5 GPIO_ACTIVE_LOW>; -+ reset-gpios = <&gpio2 RK_PB5 GPIO_ACTIVE_LOW>; - }; - }; - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3582-radxa-e52c.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3582-radxa-e52c.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3582-radxa-e52c.dts 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3582-radxa-e52c.dts 2025-10-22 13:53:56.291170221 -0400 -@@ -250,6 +250,7 @@ - compatible = "belling,bl24c16a", "atmel,24c16"; - reg = <0x50>; - pagesize = <16>; -+ read-only; - vcc-supply = <&vcc_3v3_pmu>; - }; - }; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3588-base-pinctrl.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3588-base-pinctrl.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3588-base-pinctrl.dtsi 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3588-base-pinctrl.dtsi 2025-10-22 13:53:56.291170221 -0400 -@@ -578,14 +578,14 @@ - hdmim0_tx0_scl: hdmim0-tx0-scl { - rockchip,pins = - /* hdmim0_tx0_scl */ -- <4 RK_PB7 5 &pcfg_pull_none>; -+ <4 RK_PB7 5 &pcfg_pull_none_drv_level_5_smt>; - }; - - /omit-if-no-ref/ - hdmim0_tx0_sda: hdmim0-tx0-sda { - rockchip,pins = - /* hdmim0_tx0_sda */ -- <4 RK_PC0 5 &pcfg_pull_none>; -+ <4 RK_PC0 5 &pcfg_pull_none_drv_level_1_smt>; - }; - - /omit-if-no-ref/ -@@ -640,14 +640,14 @@ - hdmim1_tx0_scl: hdmim1-tx0-scl { - rockchip,pins = - /* hdmim1_tx0_scl */ -- <0 RK_PD5 11 &pcfg_pull_none>; -+ <0 RK_PD5 11 &pcfg_pull_none_drv_level_5_smt>; - }; - - /omit-if-no-ref/ - hdmim1_tx0_sda: hdmim1-tx0-sda { - rockchip,pins = - /* hdmim1_tx0_sda */ -- <0 RK_PD4 11 &pcfg_pull_none>; -+ <0 RK_PD4 11 &pcfg_pull_none_drv_level_1_smt>; - }; - - /omit-if-no-ref/ -@@ -668,14 +668,14 @@ - hdmim1_tx1_scl: hdmim1-tx1-scl { - rockchip,pins = - /* hdmim1_tx1_scl */ -- <3 RK_PC6 5 &pcfg_pull_none>; -+ <3 RK_PC6 5 &pcfg_pull_none_drv_level_5_smt>; - }; - - /omit-if-no-ref/ - hdmim1_tx1_sda: hdmim1-tx1-sda { - rockchip,pins = - /* hdmim1_tx1_sda */ -- <3 RK_PC5 5 &pcfg_pull_none>; -+ <3 RK_PC5 5 &pcfg_pull_none_drv_level_1_smt>; - }; - /omit-if-no-ref/ - hdmim2_rx_cec: hdmim2-rx-cec { -@@ -709,14 +709,14 @@ - hdmim2_tx0_scl: hdmim2-tx0-scl { - rockchip,pins = - /* hdmim2_tx0_scl */ -- <3 RK_PC7 5 &pcfg_pull_none>; -+ <3 RK_PC7 5 &pcfg_pull_none_drv_level_5_smt>; - }; - - /omit-if-no-ref/ - hdmim2_tx0_sda: hdmim2-tx0-sda { - rockchip,pins = - /* hdmim2_tx0_sda */ -- <3 RK_PD0 5 &pcfg_pull_none>; -+ <3 RK_PD0 5 &pcfg_pull_none_drv_level_1_smt>; - }; - - /omit-if-no-ref/ -@@ -730,14 +730,14 @@ - hdmim2_tx1_scl: hdmim2-tx1-scl { - rockchip,pins = - /* hdmim2_tx1_scl */ -- <1 RK_PA4 5 &pcfg_pull_none>; -+ <1 RK_PA4 5 &pcfg_pull_none_drv_level_5_smt>; - }; - - /omit-if-no-ref/ - hdmim2_tx1_sda: hdmim2-tx1-sda { - rockchip,pins = - /* hdmim2_tx1_sda */ -- <1 RK_PA3 5 &pcfg_pull_none>; -+ <1 RK_PA3 5 &pcfg_pull_none_drv_level_1_smt>; - }; - - /omit-if-no-ref/ -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5.dtsi 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5.dtsi 2025-10-22 13:53:56.291170221 -0400 -@@ -321,6 +321,7 @@ - bus-width = <4>; - cap-mmc-highspeed; - cap-sd-highspeed; -+ cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; - disable-wp; - max-frequency = <150000000>; - no-sdio; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3588-extra-pinctrl.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3588-extra-pinctrl.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3588-extra-pinctrl.dtsi 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3588-extra-pinctrl.dtsi 2025-10-22 13:53:56.291170221 -0400 -@@ -160,14 +160,15 @@ - hdmim0_tx1_scl: hdmim0-tx1-scl { - rockchip,pins = - /* hdmim0_tx1_scl */ -- <2 RK_PB5 4 &pcfg_pull_none>; -+ <2 RK_PB5 4 &pcfg_pull_none_drv_level_3_smt>; - }; - - /omit-if-no-ref/ - hdmim0_tx1_sda: hdmim0-tx1-sda { - rockchip,pins = - /* hdmim0_tx1_sda */ -- <2 RK_PB4 4 &pcfg_pull_none>; -+ <2 RK_PB4 4 &pcfg_pull_none_drv_level_1_smt>; -+ - }; - }; - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5.dtsi 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5.dtsi 2025-10-22 13:53:56.291170221 -0400 -@@ -365,6 +365,8 @@ - max-frequency = <200000000>; - mmc-hs400-1_8v; - mmc-hs400-enhanced-strobe; -+ vmmc-supply = <&vcc_3v3_s3>; -+ vqmmc-supply = <&vcc_1v8_s3>; - status = "okay"; - }; - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts 2025-10-22 13:53:23.059329871 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts 2025-10-22 13:53:56.291170221 -0400 -@@ -77,7 +77,7 @@ - pinctrl-names = "default"; - pinctrl-0 = <&hp_detect>; - simple-audio-card,aux-devs = <&speaker_amp>, <&headphone_amp>; -- simple-audio-card,hp-det-gpios = <&gpio1 RK_PD3 GPIO_ACTIVE_LOW>; -+ simple-audio-card,hp-det-gpios = <&gpio1 RK_PD3 GPIO_ACTIVE_HIGH>; - simple-audio-card,widgets = - "Microphone", "Onboard Microphone", - "Microphone", "Microphone Jack", -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3588s-coolpi-4b.dts 2025-10-22 13:53:56.291170221 -0400 -@@ -474,6 +474,7 @@ - bus-width = <4>; - cap-mmc-highspeed; - cap-sd-highspeed; -+ cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>; - disable-wp; - max-frequency = <150000000>; - no-sdio; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5.dtsi 2025-10-22 13:53:56.291170221 -0400 -@@ -42,9 +42,8 @@ - simple-audio-card,bitclock-master = <&masterdai>; - simple-audio-card,format = "i2s"; - simple-audio-card,frame-master = <&masterdai>; -- simple-audio-card,hp-det-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_LOW>; -+ simple-audio-card,hp-det-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>; - simple-audio-card,mclk-fs = <256>; -- simple-audio-card,pin-switches = "Headphones"; - simple-audio-card,routing = - "Headphones", "LOUT1", - "Headphones", "ROUT1", -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rk3588-turing-rk1.dtsi 2025-10-22 13:53:56.291170221 -0400 -@@ -398,17 +398,6 @@ - - regulators { - vdd_gpu_s0: vdd_gpu_mem_s0: dcdc-reg1 { -- /* -- * RK3588's GPU power domain cannot be enabled -- * without this regulator active, but it -- * doesn't have to be on when the GPU PD is -- * disabled. Because the PD binding does not -- * currently allow us to express this -- * relationship, we have no choice but to do -- * this instead: -- */ -- regulator-always-on; -- - regulator-boot-on; - regulator-min-microvolt = <550000>; - regulator-max-microvolt = <950000>; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rockchip-pinconf.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rockchip-pinconf.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/rockchip/rockchip-pinconf.dtsi 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/rockchip/rockchip-pinconf.dtsi 2025-10-22 13:53:56.291170221 -0400 -@@ -333,6 +333,41 @@ - }; - - /omit-if-no-ref/ -+ pcfg_pull_none_drv_level_1_smt: pcfg-pull-none-drv-level-1-smt { -+ bias-disable; -+ drive-strength = <1>; -+ input-schmitt-enable; -+ }; -+ -+ /omit-if-no-ref/ -+ pcfg_pull_none_drv_level_2_smt: pcfg-pull-none-drv-level-2-smt { -+ bias-disable; -+ drive-strength = <2>; -+ input-schmitt-enable; -+ }; -+ -+ /omit-if-no-ref/ -+ pcfg_pull_none_drv_level_3_smt: pcfg-pull-none-drv-level-3-smt { -+ bias-disable; -+ drive-strength = <3>; -+ input-schmitt-enable; -+ }; -+ -+ /omit-if-no-ref/ -+ pcfg_pull_none_drv_level_4_smt: pcfg-pull-none-drv-level-4-smt { -+ bias-disable; -+ drive-strength = <4>; -+ input-schmitt-enable; -+ }; -+ -+ /omit-if-no-ref/ -+ pcfg_pull_none_drv_level_5_smt: pcfg-pull-none-drv-level-5-smt { -+ bias-disable; -+ drive-strength = <5>; -+ input-schmitt-enable; -+ }; -+ -+ /omit-if-no-ref/ - pcfg_output_high: pcfg-output-high { - output-high; - }; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/st/stm32mp251.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/st/stm32mp251.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/st/stm32mp251.dtsi 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/st/stm32mp251.dtsi 2025-10-22 13:53:56.291170221 -0400 -@@ -150,7 +150,7 @@ - , - , - ; -- always-on; -+ arm,no-tick-in-suspend; - }; - - soc@0 { -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/ti/k3-am625-sk.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/ti/k3-am625-sk.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/ti/k3-am625-sk.dts 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/ti/k3-am625-sk.dts 2025-10-22 13:53:56.291170221 -0400 -@@ -106,6 +106,22 @@ - }; - - &main_pmx0 { -+ main_mmc0_pins_default: main-mmc0-default-pins { -+ bootph-all; -+ pinctrl-single,pins = < -+ AM62X_IOPAD(0x220, PIN_INPUT, 0) /* (Y3) MMC0_CMD */ -+ AM62X_IOPAD(0x218, PIN_INPUT, 0) /* (AB1) MMC0_CLK */ -+ AM62X_IOPAD(0x214, PIN_INPUT, 0) /* (AA2) MMC0_DAT0 */ -+ AM62X_IOPAD(0x210, PIN_INPUT_PULLUP, 0) /* (AA1) MMC0_DAT1 */ -+ AM62X_IOPAD(0x20c, PIN_INPUT_PULLUP, 0) /* (AA3) MMC0_DAT2 */ -+ AM62X_IOPAD(0x208, PIN_INPUT_PULLUP, 0) /* (Y4) MMC0_DAT3 */ -+ AM62X_IOPAD(0x204, PIN_INPUT_PULLUP, 0) /* (AB2) MMC0_DAT4 */ -+ AM62X_IOPAD(0x200, PIN_INPUT_PULLUP, 0) /* (AC1) MMC0_DAT5 */ -+ AM62X_IOPAD(0x1fc, PIN_INPUT_PULLUP, 0) /* (AD2) MMC0_DAT6 */ -+ AM62X_IOPAD(0x1f8, PIN_INPUT_PULLUP, 0) /* (AC2) MMC0_DAT7 */ -+ >; -+ }; -+ - main_rgmii2_pins_default: main-rgmii2-default-pins { - bootph-all; - pinctrl-single,pins = < -@@ -195,6 +211,14 @@ - }; - }; - -+&sdhci0 { -+ bootph-all; -+ non-removable; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&main_mmc0_pins_default>; -+ status = "okay"; -+}; -+ - &sdhci1 { - vmmc-supply = <&vdd_mmc1>; - vqmmc-supply = <&vdd_sd_dv>; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts 2025-10-22 13:53:56.291170221 -0400 -@@ -301,8 +301,8 @@ - - main_uart1_pins_default: main-uart1-default-pins { - pinctrl-single,pins = < -- AM62AX_IOPAD(0x01e8, PIN_INPUT, 1) /* (C17) I2C1_SCL.UART1_RXD */ -- AM62AX_IOPAD(0x01ec, PIN_OUTPUT, 1) /* (E17) I2C1_SDA.UART1_TXD */ -+ AM62AX_IOPAD(0x01ac, PIN_INPUT, 2) /* (B21) MCASP0_AFSR.UART1_RXD */ -+ AM62AX_IOPAD(0x01b0, PIN_OUTPUT, 2) /* (A21) MCASP0_ACLKR.UART1_TXD */ - AM62AX_IOPAD(0x0194, PIN_INPUT, 2) /* (C19) MCASP0_AXR3.UART1_CTSn */ - AM62AX_IOPAD(0x0198, PIN_OUTPUT, 2) /* (B19) MCASP0_AXR2.UART1_RTSn */ - >; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts 2025-10-22 13:53:56.291170221 -0400 -@@ -74,6 +74,22 @@ - }; - - &main_pmx0 { -+ main_mmc0_pins_default: main-mmc0-default-pins { -+ bootph-all; -+ pinctrl-single,pins = < -+ AM62X_IOPAD(0x220, PIN_INPUT, 0) /* (V3) MMC0_CMD */ -+ AM62X_IOPAD(0x218, PIN_INPUT, 0) /* (Y1) MMC0_CLK */ -+ AM62X_IOPAD(0x214, PIN_INPUT, 0) /* (V2) MMC0_DAT0 */ -+ AM62X_IOPAD(0x210, PIN_INPUT, 0) /* (V1) MMC0_DAT1 */ -+ AM62X_IOPAD(0x20c, PIN_INPUT, 0) /* (W2) MMC0_DAT2 */ -+ AM62X_IOPAD(0x208, PIN_INPUT, 0) /* (W1) MMC0_DAT3 */ -+ AM62X_IOPAD(0x204, PIN_INPUT, 0) /* (Y2) MMC0_DAT4 */ -+ AM62X_IOPAD(0x200, PIN_INPUT, 0) /* (W3) MMC0_DAT5 */ -+ AM62X_IOPAD(0x1fc, PIN_INPUT, 0) /* (W4) MMC0_DAT6 */ -+ AM62X_IOPAD(0x1f8, PIN_INPUT, 0) /* (V4) MMC0_DAT7 */ -+ >; -+ }; -+ - vddshv_sdio_pins_default: vddshv-sdio-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x07c, PIN_OUTPUT, 7) /* (M19) GPMC0_CLK.GPIO0_31 */ -@@ -144,6 +160,14 @@ - }; - }; - -+&sdhci0 { -+ bootph-all; -+ non-removable; -+ pinctrl-names = "default"; -+ pinctrl-0 = <&main_mmc0_pins_default>; -+ status = "okay"; -+}; -+ - &sdhci1 { - vmmc-supply = <&vdd_mmc1>; - vqmmc-supply = <&vddshv_sdio>; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/ti/k3-am62-main.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/ti/k3-am62-main.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/ti/k3-am62-main.dtsi 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/ti/k3-am62-main.dtsi 2025-10-22 13:53:56.291170221 -0400 -@@ -553,7 +553,6 @@ - clocks = <&k3_clks 57 5>, <&k3_clks 57 6>; - clock-names = "clk_ahb", "clk_xin"; - bus-width = <8>; -- mmc-ddr-1_8v; - mmc-hs200-1_8v; - ti,clkbuf-sel = <0x7>; - ti,otap-del-sel-legacy = <0x0>; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/ti/k3-am62p-j722s-common-main.dtsi 2025-10-22 13:53:56.291170221 -0400 -@@ -259,7 +259,7 @@ - - main_pmx0: pinctrl@f4000 { - compatible = "pinctrl-single"; -- reg = <0x00 0xf4000 0x00 0x2ac>; -+ reg = <0x00 0xf4000 0x00 0x2b0>; - #pinctrl-cells = <1>; - pinctrl-single,register-width = <32>; - pinctrl-single,function-mask = <0xffffffff>; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/ti/k3-am62p-verdin.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/ti/k3-am62p-verdin.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/ti/k3-am62p-verdin.dtsi 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/ti/k3-am62p-verdin.dtsi 2025-10-22 13:53:56.291170221 -0400 -@@ -426,14 +426,14 @@ - /* Verdin PWM_3_DSI as GPIO */ - pinctrl_pwm3_dsi_gpio: main-gpio1-16-default-pins { - pinctrl-single,pins = < -- AM62PX_IOPAD(0x01b8, PIN_OUTPUT, 7) /* (E20) SPI0_CS1.GPIO1_16 */ /* SODIMM 19 */ -+ AM62PX_IOPAD(0x01b8, PIN_INPUT, 7) /* (E20) SPI0_CS1.GPIO1_16 */ /* SODIMM 19 */ - >; - }; - - /* Verdin SD_1_CD# */ - pinctrl_sd1_cd: main-gpio1-48-default-pins { - pinctrl-single,pins = < -- AM62PX_IOPAD(0x0240, PIN_INPUT, 7) /* (D23) MMC1_SDCD.GPIO1_48 */ /* SODIMM 84 */ -+ AM62PX_IOPAD(0x0240, PIN_INPUT_PULLUP, 7) /* (D23) MMC1_SDCD.GPIO1_48 */ /* SODIMM 84 */ - >; - }; - -@@ -717,8 +717,8 @@ - /* Verdin I2C_3_HDMI */ - pinctrl_mcu_i2c0: mcu-i2c0-default-pins { - pinctrl-single,pins = < -- AM62PX_MCU_IOPAD(0x0044, PIN_INPUT, 0) /* (E11) MCU_I2C0_SCL */ /* SODIMM 59 */ -- AM62PX_MCU_IOPAD(0x0048, PIN_INPUT, 0) /* (D11) MCU_I2C0_SDA */ /* SODIMM 57 */ -+ AM62PX_MCU_IOPAD(0x0044, PIN_INPUT_PULLUP, 0) /* (E11) MCU_I2C0_SCL */ /* SODIMM 59 */ -+ AM62PX_MCU_IOPAD(0x0048, PIN_INPUT_PULLUP, 0) /* (D11) MCU_I2C0_SDA */ /* SODIMM 57 */ - >; - }; - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/ti/k3-am62-verdin.dtsi 2025-10-22 13:53:56.291170221 -0400 -@@ -507,16 +507,16 @@ - /* Verdin I2C_2_DSI */ - pinctrl_i2c2: main-i2c2-default-pins { - pinctrl-single,pins = < -- AM62X_IOPAD(0x00b0, PIN_INPUT, 1) /* (K22) GPMC0_CSn2.I2C2_SCL */ /* SODIMM 55 */ -- AM62X_IOPAD(0x00b4, PIN_INPUT, 1) /* (K24) GPMC0_CSn3.I2C2_SDA */ /* SODIMM 53 */ -+ AM62X_IOPAD(0x00b0, PIN_INPUT_PULLUP, 1) /* (K22) GPMC0_CSn2.I2C2_SCL */ /* SODIMM 55 */ -+ AM62X_IOPAD(0x00b4, PIN_INPUT_PULLUP, 1) /* (K24) GPMC0_CSn3.I2C2_SDA */ /* SODIMM 53 */ - >; - }; - - /* Verdin I2C_4_CSI */ - pinctrl_i2c3: main-i2c3-default-pins { - pinctrl-single,pins = < -- AM62X_IOPAD(0x01d0, PIN_INPUT, 2) /* (A15) UART0_CTSn.I2C3_SCL */ /* SODIMM 95 */ -- AM62X_IOPAD(0x01d4, PIN_INPUT, 2) /* (B15) UART0_RTSn.I2C3_SDA */ /* SODIMM 93 */ -+ AM62X_IOPAD(0x01d0, PIN_INPUT_PULLUP, 2) /* (A15) UART0_CTSn.I2C3_SCL */ /* SODIMM 95 */ -+ AM62X_IOPAD(0x01d4, PIN_INPUT_PULLUP, 2) /* (B15) UART0_RTSn.I2C3_SDA */ /* SODIMM 93 */ - >; - }; - -@@ -786,8 +786,8 @@ - /* Verdin I2C_3_HDMI */ - pinctrl_mcu_i2c0: mcu-i2c0-default-pins { - pinctrl-single,pins = < -- AM62X_MCU_IOPAD(0x0044, PIN_INPUT, 0) /* (A8) MCU_I2C0_SCL */ /* SODIMM 59 */ -- AM62X_MCU_IOPAD(0x0048, PIN_INPUT, 0) /* (D10) MCU_I2C0_SDA */ /* SODIMM 57 */ -+ AM62X_MCU_IOPAD(0x0044, PIN_INPUT_PULLUP, 0) /* (A8) MCU_I2C0_SCL */ /* SODIMM 59 */ -+ AM62X_MCU_IOPAD(0x0048, PIN_INPUT_PULLUP, 0) /* (D10) MCU_I2C0_SDA */ /* SODIMM 57 */ - >; - }; - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi 2025-10-22 13:53:56.291170221 -0400 -@@ -203,22 +203,6 @@ - >; - }; - -- main_mmc0_pins_default: main-mmc0-default-pins { -- bootph-all; -- pinctrl-single,pins = < -- AM62X_IOPAD(0x220, PIN_INPUT, 0) /* (Y3/V3) MMC0_CMD */ -- AM62X_IOPAD(0x218, PIN_INPUT, 0) /* (AB1/Y1) MMC0_CLK */ -- AM62X_IOPAD(0x214, PIN_INPUT, 0) /* (AA2/V2) MMC0_DAT0 */ -- AM62X_IOPAD(0x210, PIN_INPUT, 0) /* (AA1/V1) MMC0_DAT1 */ -- AM62X_IOPAD(0x20c, PIN_INPUT, 0) /* (AA3/W2) MMC0_DAT2 */ -- AM62X_IOPAD(0x208, PIN_INPUT, 0) /* (Y4/W1) MMC0_DAT3 */ -- AM62X_IOPAD(0x204, PIN_INPUT, 0) /* (AB2/Y2) MMC0_DAT4 */ -- AM62X_IOPAD(0x200, PIN_INPUT, 0) /* (AC1/W3) MMC0_DAT5 */ -- AM62X_IOPAD(0x1fc, PIN_INPUT, 0) /* (AD2/W4) MMC0_DAT6 */ -- AM62X_IOPAD(0x1f8, PIN_INPUT, 0) /* (AC2/V4) MMC0_DAT7 */ -- >; -- }; -- - main_mmc1_pins_default: main-mmc1-default-pins { - bootph-all; - pinctrl-single,pins = < -@@ -457,14 +441,6 @@ - clock-frequency = <400000>; - }; - --&sdhci0 { -- bootph-all; -- status = "okay"; -- non-removable; -- pinctrl-names = "default"; -- pinctrl-0 = <&main_mmc0_pins_default>; --}; -- - &sdhci1 { - /* SD/MMC */ - bootph-all; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/ti/k3-am642-phyboard-electra-rdk.dts 2025-10-22 13:53:56.291170221 -0400 -@@ -322,6 +322,8 @@ - &icssg0_mdio { - pinctrl-names = "default"; - pinctrl-0 = <&icssg0_mdio_pins_default &clkout0_pins_default>; -+ assigned-clocks = <&k3_clks 157 123>; -+ assigned-clock-parents = <&k3_clks 157 125>; - status = "okay"; - - icssg0_phy1: ethernet-phy@1 { -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/ti/k3-j722s-evm.dts BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/ti/k3-j722s-evm.dts ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/ti/k3-j722s-evm.dts 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/ti/k3-j722s-evm.dts 2025-10-22 13:53:56.291170221 -0400 -@@ -634,7 +634,7 @@ - /* P05 - USB2.0_MUX_SEL */ - gpio-hog; - gpios = <5 GPIO_ACTIVE_LOW>; -- output-high; -+ output-low; - }; - - p01_hog: p01-hog { -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/boot/dts/ti/k3-pinctrl.h BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/ti/k3-pinctrl.h ---- BPI-Router-Linux-kernel/arch/arm64/boot/dts/ti/k3-pinctrl.h 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/boot/dts/ti/k3-pinctrl.h 2025-10-22 13:53:56.291170221 -0400 -@@ -8,6 +8,7 @@ - #ifndef DTS_ARM64_TI_K3_PINCTRL_H - #define DTS_ARM64_TI_K3_PINCTRL_H - -+#define ST_EN_SHIFT (14) - #define PULLUDEN_SHIFT (16) - #define PULLTYPESEL_SHIFT (17) - #define RXACTIVE_SHIFT (18) -@@ -19,6 +20,10 @@ - #define DS_PULLUD_EN_SHIFT (27) - #define DS_PULLTYPE_SEL_SHIFT (28) - -+/* Schmitt trigger configuration */ -+#define ST_DISABLE (0 << ST_EN_SHIFT) -+#define ST_ENABLE (1 << ST_EN_SHIFT) -+ - #define PULL_DISABLE (1 << PULLUDEN_SHIFT) - #define PULL_ENABLE (0 << PULLUDEN_SHIFT) - -@@ -32,9 +37,13 @@ - #define PIN_OUTPUT (INPUT_DISABLE | PULL_DISABLE) - #define PIN_OUTPUT_PULLUP (INPUT_DISABLE | PULL_UP) - #define PIN_OUTPUT_PULLDOWN (INPUT_DISABLE | PULL_DOWN) --#define PIN_INPUT (INPUT_EN | PULL_DISABLE) --#define PIN_INPUT_PULLUP (INPUT_EN | PULL_UP) --#define PIN_INPUT_PULLDOWN (INPUT_EN | PULL_DOWN) -+#define PIN_INPUT (INPUT_EN | ST_ENABLE | PULL_DISABLE) -+#define PIN_INPUT_PULLUP (INPUT_EN | ST_ENABLE | PULL_UP) -+#define PIN_INPUT_PULLDOWN (INPUT_EN | ST_ENABLE | PULL_DOWN) -+/* Input configurations with Schmitt Trigger disabled */ -+#define PIN_INPUT_NOST (INPUT_EN | PULL_DISABLE) -+#define PIN_INPUT_PULLUP_NOST (INPUT_EN | PULL_UP) -+#define PIN_INPUT_PULLDOWN_NOST (INPUT_EN | PULL_DOWN) - - #define PIN_DEBOUNCE_DISABLE (0 << DEBOUNCE_SHIFT) - #define PIN_DEBOUNCE_CONF1 (1 << DEBOUNCE_SHIFT) -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/configs/defconfig BPI-Router-Linux-kernel-6.16.12/arch/arm64/configs/defconfig ---- BPI-Router-Linux-kernel/arch/arm64/configs/defconfig 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/configs/defconfig 2025-10-22 13:53:56.291170221 -0400 -@@ -1444,6 +1444,7 @@ CONFIG_PLATFORM_MHU=y - CONFIG_BCM2835_MBOX=y - CONFIG_QCOM_APCS_IPC=y - CONFIG_MTK_ADSP_MBOX=m -+CONFIG_QCOM_CPUCP_MBOX=m - CONFIG_QCOM_IPCC=y - CONFIG_ROCKCHIP_IOMMU=y - CONFIG_TEGRA_IOMMU_SMMU=y -@@ -1573,6 +1574,7 @@ CONFIG_RESET_QCOM_AOSS=y - CONFIG_RESET_QCOM_PDC=m - CONFIG_RESET_RZG2L_USBPHY_CTRL=y - CONFIG_RESET_TI_SCI=y -+CONFIG_PHY_SNPS_EUSB2=m - CONFIG_PHY_XGENE=y - CONFIG_PHY_CAN_TRANSCEIVER=m - CONFIG_PHY_NXP_PTN3222=m -@@ -1597,7 +1599,6 @@ CONFIG_PHY_QCOM_EDP=m - CONFIG_PHY_QCOM_PCIE2=m - CONFIG_PHY_QCOM_QMP=m - CONFIG_PHY_QCOM_QUSB2=m --CONFIG_PHY_QCOM_SNPS_EUSB2=m - CONFIG_PHY_QCOM_EUSB2_REPEATER=m - CONFIG_PHY_QCOM_M31_USB=m - CONFIG_PHY_QCOM_USB_HS=m -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/include/asm/acpi.h BPI-Router-Linux-kernel-6.16.12/arch/arm64/include/asm/acpi.h ---- BPI-Router-Linux-kernel/arch/arm64/include/asm/acpi.h 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/include/asm/acpi.h 2025-10-22 13:53:56.291170221 -0400 -@@ -150,7 +150,7 @@ acpi_set_mailbox_entry(int cpu, struct a - {} - #endif - --static inline const char *acpi_get_enable_method(int cpu) -+static __always_inline const char *acpi_get_enable_method(int cpu) - { - if (acpi_psci_present()) - return "psci"; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/include/asm/assembler.h BPI-Router-Linux-kernel-6.16.12/arch/arm64/include/asm/assembler.h ---- BPI-Router-Linux-kernel/arch/arm64/include/asm/assembler.h 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/include/asm/assembler.h 2025-10-22 13:53:56.291170221 -0400 -@@ -41,6 +41,11 @@ - /* - * Save/restore interrupts. - */ -+ .macro save_and_disable_daif, flags -+ mrs \flags, daif -+ msr daifset, #0xf -+ .endm -+ - .macro save_and_disable_irq, flags - mrs \flags, daif - msr daifset, #3 -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/include/asm/el2_setup.h BPI-Router-Linux-kernel-6.16.12/arch/arm64/include/asm/el2_setup.h ---- BPI-Router-Linux-kernel/arch/arm64/include/asm/el2_setup.h 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/include/asm/el2_setup.h 2025-10-22 13:53:56.291170221 -0400 -@@ -287,17 +287,6 @@ - .Lskip_fgt2_\@: - .endm - --.macro __init_el2_gcs -- mrs_s x1, SYS_ID_AA64PFR1_EL1 -- ubfx x1, x1, #ID_AA64PFR1_EL1_GCS_SHIFT, #4 -- cbz x1, .Lskip_gcs_\@ -- -- /* Ensure GCS is not enabled when we start trying to do BLs */ -- msr_s SYS_GCSCR_EL1, xzr -- msr_s SYS_GCSCRE0_EL1, xzr --.Lskip_gcs_\@: --.endm -- - /** - * Initialize EL2 registers to sane values. This should be called early on all - * cores that were booted in EL2. Note that everything gets initialised as -@@ -319,7 +308,6 @@ - __init_el2_cptr - __init_el2_fgt - __init_el2_fgt2 -- __init_el2_gcs - .endm - - #ifndef __KVM_NVHE_HYPERVISOR__ -@@ -371,6 +359,13 @@ - msr_s SYS_MPAMHCR_EL2, xzr // clear TRAP_MPAMIDR_EL1 -> EL2 - - .Lskip_mpam_\@: -+ check_override id_aa64pfr1, ID_AA64PFR1_EL1_GCS_SHIFT, .Linit_gcs_\@, .Lskip_gcs_\@, x1, x2 -+ -+.Linit_gcs_\@: -+ msr_s SYS_GCSCR_EL1, xzr -+ msr_s SYS_GCSCRE0_EL1, xzr -+ -+.Lskip_gcs_\@: - check_override id_aa64pfr0, ID_AA64PFR0_EL1_SVE_SHIFT, .Linit_sve_\@, .Lskip_sve_\@, x1, x2 - - .Linit_sve_\@: /* SVE register access */ -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/include/asm/gcs.h BPI-Router-Linux-kernel-6.16.12/arch/arm64/include/asm/gcs.h ---- BPI-Router-Linux-kernel/arch/arm64/include/asm/gcs.h 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/include/asm/gcs.h 2025-10-22 13:53:56.291170221 -0400 -@@ -58,7 +58,7 @@ static inline u64 gcsss2(void) - - static inline bool task_gcs_el0_enabled(struct task_struct *task) - { -- return current->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE; -+ return task->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE; - } - - void gcs_set_el0_mode(struct task_struct *task); -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/include/asm/kvm_emulate.h BPI-Router-Linux-kernel-6.16.12/arch/arm64/include/asm/kvm_emulate.h ---- BPI-Router-Linux-kernel/arch/arm64/include/asm/kvm_emulate.h 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/include/asm/kvm_emulate.h 2025-10-22 13:53:56.291170221 -0400 -@@ -561,68 +561,6 @@ static __always_inline void kvm_incr_pc( - vcpu_set_flag((v), e); \ - } while (0) - --#define __build_check_all_or_none(r, bits) \ -- BUILD_BUG_ON(((r) & (bits)) && ((r) & (bits)) != (bits)) -- --#define __cpacr_to_cptr_clr(clr, set) \ -- ({ \ -- u64 cptr = 0; \ -- \ -- if ((set) & CPACR_EL1_FPEN) \ -- cptr |= CPTR_EL2_TFP; \ -- if ((set) & CPACR_EL1_ZEN) \ -- cptr |= CPTR_EL2_TZ; \ -- if ((set) & CPACR_EL1_SMEN) \ -- cptr |= CPTR_EL2_TSM; \ -- if ((clr) & CPACR_EL1_TTA) \ -- cptr |= CPTR_EL2_TTA; \ -- if ((clr) & CPTR_EL2_TAM) \ -- cptr |= CPTR_EL2_TAM; \ -- if ((clr) & CPTR_EL2_TCPAC) \ -- cptr |= CPTR_EL2_TCPAC; \ -- \ -- cptr; \ -- }) -- --#define __cpacr_to_cptr_set(clr, set) \ -- ({ \ -- u64 cptr = 0; \ -- \ -- if ((clr) & CPACR_EL1_FPEN) \ -- cptr |= CPTR_EL2_TFP; \ -- if ((clr) & CPACR_EL1_ZEN) \ -- cptr |= CPTR_EL2_TZ; \ -- if ((clr) & CPACR_EL1_SMEN) \ -- cptr |= CPTR_EL2_TSM; \ -- if ((set) & CPACR_EL1_TTA) \ -- cptr |= CPTR_EL2_TTA; \ -- if ((set) & CPTR_EL2_TAM) \ -- cptr |= CPTR_EL2_TAM; \ -- if ((set) & CPTR_EL2_TCPAC) \ -- cptr |= CPTR_EL2_TCPAC; \ -- \ -- cptr; \ -- }) -- --#define cpacr_clear_set(clr, set) \ -- do { \ -- BUILD_BUG_ON((set) & CPTR_VHE_EL2_RES0); \ -- BUILD_BUG_ON((clr) & CPACR_EL1_E0POE); \ -- __build_check_all_or_none((clr), CPACR_EL1_FPEN); \ -- __build_check_all_or_none((set), CPACR_EL1_FPEN); \ -- __build_check_all_or_none((clr), CPACR_EL1_ZEN); \ -- __build_check_all_or_none((set), CPACR_EL1_ZEN); \ -- __build_check_all_or_none((clr), CPACR_EL1_SMEN); \ -- __build_check_all_or_none((set), CPACR_EL1_SMEN); \ -- \ -- if (has_vhe() || has_hvhe()) \ -- sysreg_clear_set(cpacr_el1, clr, set); \ -- else \ -- sysreg_clear_set(cptr_el2, \ -- __cpacr_to_cptr_clr(clr, set), \ -- __cpacr_to_cptr_set(clr, set));\ -- } while (0) -- - /* - * Returns a 'sanitised' view of CPTR_EL2, translating from nVHE to the VHE - * format if E2H isn't set. -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/include/asm/kvm_host.h BPI-Router-Linux-kernel-6.16.12/arch/arm64/include/asm/kvm_host.h ---- BPI-Router-Linux-kernel/arch/arm64/include/asm/kvm_host.h 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/include/asm/kvm_host.h 2025-10-22 13:53:56.291170221 -0400 -@@ -1107,14 +1107,36 @@ static inline u64 *___ctxt_sys_reg(const - #define ctxt_sys_reg(c,r) (*__ctxt_sys_reg(c,r)) - - u64 kvm_vcpu_apply_reg_masks(const struct kvm_vcpu *, enum vcpu_sysreg, u64); -+ -+#define __vcpu_assign_sys_reg(v, r, val) \ -+ do { \ -+ const struct kvm_cpu_context *ctxt = &(v)->arch.ctxt; \ -+ u64 __v = (val); \ -+ if (vcpu_has_nv((v)) && (r) >= __SANITISED_REG_START__) \ -+ __v = kvm_vcpu_apply_reg_masks((v), (r), __v); \ -+ \ -+ ctxt_sys_reg(ctxt, (r)) = __v; \ -+ } while (0) -+ -+#define __vcpu_rmw_sys_reg(v, r, op, val) \ -+ do { \ -+ const struct kvm_cpu_context *ctxt = &(v)->arch.ctxt; \ -+ u64 __v = ctxt_sys_reg(ctxt, (r)); \ -+ __v op (val); \ -+ if (vcpu_has_nv((v)) && (r) >= __SANITISED_REG_START__) \ -+ __v = kvm_vcpu_apply_reg_masks((v), (r), __v); \ -+ \ -+ ctxt_sys_reg(ctxt, (r)) = __v; \ -+ } while (0) -+ - #define __vcpu_sys_reg(v,r) \ -- (*({ \ -+ ({ \ - const struct kvm_cpu_context *ctxt = &(v)->arch.ctxt; \ -- u64 *__r = __ctxt_sys_reg(ctxt, (r)); \ -+ u64 __v = ctxt_sys_reg(ctxt, (r)); \ - if (vcpu_has_nv((v)) && (r) >= __SANITISED_REG_START__) \ -- *__r = kvm_vcpu_apply_reg_masks((v), (r), *__r);\ -- __r; \ -- })) -+ __v = kvm_vcpu_apply_reg_masks((v), (r), __v); \ -+ __v; \ -+ }) - - u64 vcpu_read_sys_reg(const struct kvm_vcpu *vcpu, int reg); - void vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg); -@@ -1127,6 +1149,8 @@ static inline bool __vcpu_read_sys_reg_f - * System registers listed in the switch are not saved on every - * exit from the guest but are only saved on vcpu_put. - * -+ * SYSREGS_ON_CPU *MUST* be checked before using this helper. -+ * - * Note that MPIDR_EL1 for the guest is set by KVM via VMPIDR_EL2 but - * should never be listed below, because the guest cannot modify its - * own MPIDR_EL1 and MPIDR_EL1 is accessed for VCPU A from VCPU B's -@@ -1178,6 +1202,8 @@ static inline bool __vcpu_write_sys_reg_ - * System registers listed in the switch are not restored on every - * entry to the guest but are only restored on vcpu_load. - * -+ * SYSREGS_ON_CPU *MUST* be checked before using this helper. -+ * - * Note that MPIDR_EL1 for the guest is set by KVM via VMPIDR_EL2 but - * should never be listed below, because the MPIDR should only be set - * once, before running the VCPU, and never changed later. -@@ -1267,9 +1293,8 @@ void kvm_arm_resume_guest(struct kvm *kv - }) - - /* -- * The couple of isb() below are there to guarantee the same behaviour -- * on VHE as on !VHE, where the eret to EL1 acts as a context -- * synchronization event. -+ * The isb() below is there to guarantee the same behaviour on VHE as on !VHE, -+ * where the eret to EL1 acts as a context synchronization event. - */ - #define kvm_call_hyp(f, ...) \ - do { \ -@@ -1287,7 +1312,6 @@ void kvm_arm_resume_guest(struct kvm *kv - \ - if (has_vhe()) { \ - ret = f(__VA_ARGS__); \ -- isb(); \ - } else { \ - ret = kvm_call_hyp_nvhe(f, ##__VA_ARGS__); \ - } \ -@@ -1460,7 +1484,6 @@ int kvm_vm_ioctl_get_reg_writable_masks( - struct reg_mask_range *range); - - /* Guest/host FPSIMD coordination helpers */ --int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu); - void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu); - void kvm_arch_vcpu_ctxflush_fp(struct kvm_vcpu *vcpu); - void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu); -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/include/asm/mmu.h BPI-Router-Linux-kernel-6.16.12/arch/arm64/include/asm/mmu.h ---- BPI-Router-Linux-kernel/arch/arm64/include/asm/mmu.h 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/include/asm/mmu.h 2025-10-22 13:53:56.291170221 -0400 -@@ -17,6 +17,13 @@ - #include - #include - -+enum pgtable_type { -+ TABLE_PTE, -+ TABLE_PMD, -+ TABLE_PUD, -+ TABLE_P4D, -+}; -+ - typedef struct { - atomic64_t id; - #ifdef CONFIG_COMPAT -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/include/asm/module.h BPI-Router-Linux-kernel-6.16.12/arch/arm64/include/asm/module.h ---- BPI-Router-Linux-kernel/arch/arm64/include/asm/module.h 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/include/asm/module.h 2025-10-22 13:53:56.291170221 -0400 -@@ -19,6 +19,7 @@ struct mod_arch_specific { - - /* for CONFIG_DYNAMIC_FTRACE */ - struct plt_entry *ftrace_trampolines; -+ struct plt_entry *init_ftrace_trampolines; - }; - - u64 module_emit_plt_entry(struct module *mod, Elf64_Shdr *sechdrs, -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/include/asm/module.lds.h BPI-Router-Linux-kernel-6.16.12/arch/arm64/include/asm/module.lds.h ---- BPI-Router-Linux-kernel/arch/arm64/include/asm/module.lds.h 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/include/asm/module.lds.h 2025-10-22 13:53:56.291170221 -0400 -@@ -2,6 +2,7 @@ SECTIONS { - .plt 0 : { BYTE(0) } - .init.plt 0 : { BYTE(0) } - .text.ftrace_trampoline 0 : { BYTE(0) } -+ .init.text.ftrace_trampoline 0 : { BYTE(0) } - - #ifdef CONFIG_KASAN_SW_TAGS - /* -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/include/asm/pgtable.h BPI-Router-Linux-kernel-6.16.12/arch/arm64/include/asm/pgtable.h ---- BPI-Router-Linux-kernel/arch/arm64/include/asm/pgtable.h 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/include/asm/pgtable.h 2025-10-22 13:53:56.291170221 -0400 -@@ -563,7 +563,7 @@ static inline pte_t pte_swp_mkexclusive( - return set_pte_bit(pte, __pgprot(PTE_SWP_EXCLUSIVE)); - } - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_val(pte) & PTE_SWP_EXCLUSIVE; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/Kconfig BPI-Router-Linux-kernel-6.16.12/arch/arm64/Kconfig ---- BPI-Router-Linux-kernel/arch/arm64/Kconfig 2025-10-22 13:53:23.051329910 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/Kconfig 2025-10-22 13:53:56.283170260 -0400 -@@ -256,6 +256,7 @@ config ARM64 - select HOTPLUG_SMT if HOTPLUG_CPU - select IRQ_DOMAIN - select IRQ_FORCED_THREADING -+ select JUMP_LABEL - select KASAN_VMALLOC if KASAN - select LOCK_MM_AND_FIND_VMA - select MODULES_USE_ELF_RELA -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kernel/acpi.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/acpi.c ---- BPI-Router-Linux-kernel/arch/arm64/kernel/acpi.c 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/acpi.c 2025-10-22 13:53:56.291170221 -0400 -@@ -197,6 +197,8 @@ out: - */ - void __init acpi_boot_table_init(void) - { -+ int ret; -+ - /* - * Enable ACPI instead of device tree unless - * - ACPI has been disabled explicitly (acpi=off), or -@@ -250,10 +252,12 @@ done: - * behaviour, use acpi=nospcr to disable console in ACPI SPCR - * table as default serial console. - */ -- acpi_parse_spcr(earlycon_acpi_spcr_enable, -+ ret = acpi_parse_spcr(earlycon_acpi_spcr_enable, - !param_acpi_nospcr); -- pr_info("Use ACPI SPCR as default console: %s\n", -- param_acpi_nospcr ? "No" : "Yes"); -+ if (!ret || param_acpi_nospcr || !IS_ENABLED(CONFIG_ACPI_SPCR_TABLE)) -+ pr_info("Use ACPI SPCR as default console: No\n"); -+ else -+ pr_info("Use ACPI SPCR as default console: Yes\n"); - - if (IS_ENABLED(CONFIG_ACPI_BGRT)) - acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt); -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kernel/cpufeature.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/cpufeature.c ---- BPI-Router-Linux-kernel/arch/arm64/kernel/cpufeature.c 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/cpufeature.c 2025-10-22 13:53:56.295170202 -0400 -@@ -84,6 +84,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1941,11 +1942,11 @@ static bool has_pmuv3(const struct arm64 - extern - void create_kpti_ng_temp_pgd(pgd_t *pgdir, phys_addr_t phys, unsigned long virt, - phys_addr_t size, pgprot_t prot, -- phys_addr_t (*pgtable_alloc)(int), int flags); -+ phys_addr_t (*pgtable_alloc)(enum pgtable_type), int flags); - - static phys_addr_t __initdata kpti_ng_temp_alloc; - --static phys_addr_t __init kpti_ng_pgd_alloc(int shift) -+static phys_addr_t __init kpti_ng_pgd_alloc(enum pgtable_type type) - { - kpti_ng_temp_alloc -= PAGE_SIZE; - return kpti_ng_temp_alloc; -@@ -3135,6 +3136,13 @@ static bool has_sve_feature(const struct - } - #endif - -+#ifdef CONFIG_ARM64_SME -+static bool has_sme_feature(const struct arm64_cpu_capabilities *cap, int scope) -+{ -+ return system_supports_sme() && has_user_cpuid_feature(cap, scope); -+} -+#endif -+ - static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = { - HWCAP_CAP(ID_AA64ISAR0_EL1, AES, PMULL, CAP_HWCAP, KERNEL_HWCAP_PMULL), - HWCAP_CAP(ID_AA64ISAR0_EL1, AES, AES, CAP_HWCAP, KERNEL_HWCAP_AES), -@@ -3223,31 +3231,31 @@ static const struct arm64_cpu_capabiliti - HWCAP_CAP(ID_AA64ISAR2_EL1, BC, IMP, CAP_HWCAP, KERNEL_HWCAP_HBC), - #ifdef CONFIG_ARM64_SME - HWCAP_CAP(ID_AA64PFR1_EL1, SME, IMP, CAP_HWCAP, KERNEL_HWCAP_SME), -- HWCAP_CAP(ID_AA64SMFR0_EL1, FA64, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_FA64), -- HWCAP_CAP(ID_AA64SMFR0_EL1, LUTv2, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_LUTV2), -- HWCAP_CAP(ID_AA64SMFR0_EL1, SMEver, SME2p2, CAP_HWCAP, KERNEL_HWCAP_SME2P2), -- HWCAP_CAP(ID_AA64SMFR0_EL1, SMEver, SME2p1, CAP_HWCAP, KERNEL_HWCAP_SME2P1), -- HWCAP_CAP(ID_AA64SMFR0_EL1, SMEver, SME2, CAP_HWCAP, KERNEL_HWCAP_SME2), -- HWCAP_CAP(ID_AA64SMFR0_EL1, I16I64, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_I16I64), -- HWCAP_CAP(ID_AA64SMFR0_EL1, F64F64, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_F64F64), -- HWCAP_CAP(ID_AA64SMFR0_EL1, I16I32, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_I16I32), -- HWCAP_CAP(ID_AA64SMFR0_EL1, B16B16, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_B16B16), -- HWCAP_CAP(ID_AA64SMFR0_EL1, F16F16, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_F16F16), -- HWCAP_CAP(ID_AA64SMFR0_EL1, F8F16, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_F8F16), -- HWCAP_CAP(ID_AA64SMFR0_EL1, F8F32, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_F8F32), -- HWCAP_CAP(ID_AA64SMFR0_EL1, I8I32, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_I8I32), -- HWCAP_CAP(ID_AA64SMFR0_EL1, F16F32, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_F16F32), -- HWCAP_CAP(ID_AA64SMFR0_EL1, B16F32, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_B16F32), -- HWCAP_CAP(ID_AA64SMFR0_EL1, BI32I32, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_BI32I32), -- HWCAP_CAP(ID_AA64SMFR0_EL1, F32F32, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_F32F32), -- HWCAP_CAP(ID_AA64SMFR0_EL1, SF8FMA, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8FMA), -- HWCAP_CAP(ID_AA64SMFR0_EL1, SF8DP4, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8DP4), -- HWCAP_CAP(ID_AA64SMFR0_EL1, SF8DP2, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8DP2), -- HWCAP_CAP(ID_AA64SMFR0_EL1, SBitPerm, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SBITPERM), -- HWCAP_CAP(ID_AA64SMFR0_EL1, AES, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_AES), -- HWCAP_CAP(ID_AA64SMFR0_EL1, SFEXPA, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SFEXPA), -- HWCAP_CAP(ID_AA64SMFR0_EL1, STMOP, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_STMOP), -- HWCAP_CAP(ID_AA64SMFR0_EL1, SMOP4, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SMOP4), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, FA64, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_FA64), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, LUTv2, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_LUTV2), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, SMEver, SME2p2, CAP_HWCAP, KERNEL_HWCAP_SME2P2), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, SMEver, SME2p1, CAP_HWCAP, KERNEL_HWCAP_SME2P1), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, SMEver, SME2, CAP_HWCAP, KERNEL_HWCAP_SME2), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, I16I64, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_I16I64), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, F64F64, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_F64F64), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, I16I32, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_I16I32), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, B16B16, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_B16B16), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, F16F16, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_F16F16), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, F8F16, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_F8F16), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, F8F32, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_F8F32), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, I8I32, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_I8I32), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, F16F32, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_F16F32), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, B16F32, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_B16F32), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, BI32I32, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_BI32I32), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, F32F32, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_F32F32), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, SF8FMA, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8FMA), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, SF8DP4, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8DP4), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, SF8DP2, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SF8DP2), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, SBitPerm, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SBITPERM), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, AES, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_AES), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, SFEXPA, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SFEXPA), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, STMOP, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_STMOP), -+ HWCAP_CAP_MATCH_ID(has_sme_feature, ID_AA64SMFR0_EL1, SMOP4, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_SMOP4), - #endif /* CONFIG_ARM64_SME */ - HWCAP_CAP(ID_AA64FPFR0_EL1, F8CVT, IMP, CAP_HWCAP, KERNEL_HWCAP_F8CVT), - HWCAP_CAP(ID_AA64FPFR0_EL1, F8FMA, IMP, CAP_HWCAP, KERNEL_HWCAP_F8FMA), -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kernel/efi.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/efi.c ---- BPI-Router-Linux-kernel/arch/arm64/kernel/efi.c 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/efi.c 2025-10-22 13:53:56.295170202 -0400 -@@ -15,6 +15,7 @@ - - #include - #include -+#include - - static bool region_is_misaligned(const efi_memory_desc_t *md) - { -@@ -214,9 +215,13 @@ static int __init arm64_efi_rt_init(void - if (!efi_enabled(EFI_RUNTIME_SERVICES)) - return 0; - -- p = __vmalloc_node(THREAD_SIZE, THREAD_ALIGN, GFP_KERNEL, -- NUMA_NO_NODE, &&l); --l: if (!p) { -+ if (!IS_ENABLED(CONFIG_VMAP_STACK)) { -+ clear_bit(EFI_RUNTIME_SERVICES, &efi.flags); -+ return -ENOMEM; -+ } -+ -+ p = arch_alloc_vmap_stack(THREAD_SIZE, NUMA_NO_NODE); -+ if (!p) { - pr_warn("Failed to allocate EFI runtime stack\n"); - clear_bit(EFI_RUNTIME_SERVICES, &efi.flags); - return -ENOMEM; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kernel/entry.S BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/entry.S ---- BPI-Router-Linux-kernel/arch/arm64/kernel/entry.S 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/entry.S 2025-10-22 13:53:56.295170202 -0400 -@@ -825,6 +825,7 @@ SYM_CODE_END(__bp_harden_el1_vectors) - * - */ - SYM_FUNC_START(cpu_switch_to) -+ save_and_disable_daif x11 - mov x10, #THREAD_CPU_CONTEXT - add x8, x0, x10 - mov x9, sp -@@ -848,6 +849,7 @@ SYM_FUNC_START(cpu_switch_to) - ptrauth_keys_install_kernel x1, x8, x9, x10 - scs_save x0 - scs_load_current -+ restore_irq x11 - ret - SYM_FUNC_END(cpu_switch_to) - NOKPROBE(cpu_switch_to) -@@ -874,6 +876,7 @@ NOKPROBE(ret_from_fork) - * Calls func(regs) using this CPU's irq stack and shadow irq stack. - */ - SYM_FUNC_START(call_on_irq_stack) -+ save_and_disable_daif x9 - #ifdef CONFIG_SHADOW_CALL_STACK - get_current_task x16 - scs_save x16 -@@ -888,8 +891,10 @@ SYM_FUNC_START(call_on_irq_stack) - - /* Move to the new stack and call the function there */ - add sp, x16, #IRQ_STACK_SIZE -+ restore_irq x9 - blr x1 - -+ save_and_disable_daif x9 - /* - * Restore the SP from the FP, and restore the FP and LR from the frame - * record. -@@ -897,6 +902,7 @@ SYM_FUNC_START(call_on_irq_stack) - mov sp, x29 - ldp x29, x30, [sp], #16 - scs_load_current -+ restore_irq x9 - ret - SYM_FUNC_END(call_on_irq_stack) - NOKPROBE(call_on_irq_stack) -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kernel/ftrace.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/ftrace.c ---- BPI-Router-Linux-kernel/arch/arm64/kernel/ftrace.c 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/ftrace.c 2025-10-22 13:53:56.295170202 -0400 -@@ -258,10 +258,17 @@ int ftrace_update_ftrace_func(ftrace_fun - return ftrace_modify_code(pc, 0, new, false); - } - --static struct plt_entry *get_ftrace_plt(struct module *mod) -+static struct plt_entry *get_ftrace_plt(struct module *mod, unsigned long addr) - { - #ifdef CONFIG_MODULES -- struct plt_entry *plt = mod->arch.ftrace_trampolines; -+ struct plt_entry *plt = NULL; -+ -+ if (within_module_mem_type(addr, mod, MOD_INIT_TEXT)) -+ plt = mod->arch.init_ftrace_trampolines; -+ else if (within_module_mem_type(addr, mod, MOD_TEXT)) -+ plt = mod->arch.ftrace_trampolines; -+ else -+ return NULL; - - return &plt[FTRACE_PLT_IDX]; - #else -@@ -332,7 +339,7 @@ static bool ftrace_find_callable_addr(st - if (WARN_ON(!mod)) - return false; - -- plt = get_ftrace_plt(mod); -+ plt = get_ftrace_plt(mod, pc); - if (!plt) { - pr_err("ftrace: no module PLT for %ps\n", (void *)*addr); - return false; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kernel/machine_kexec_file.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/machine_kexec_file.c ---- BPI-Router-Linux-kernel/arch/arm64/kernel/machine_kexec_file.c 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/machine_kexec_file.c 2025-10-22 13:53:56.295170202 -0400 -@@ -94,7 +94,7 @@ int load_other_segments(struct kimage *i - char *initrd, unsigned long initrd_len, - char *cmdline) - { -- struct kexec_buf kbuf; -+ struct kexec_buf kbuf = {}; - void *dtb = NULL; - unsigned long initrd_load_addr = 0, dtb_len, - orig_segments = image->nr_segments; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kernel/Makefile BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/Makefile ---- BPI-Router-Linux-kernel/arch/arm64/kernel/Makefile 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/Makefile 2025-10-22 13:53:56.291170221 -0400 -@@ -34,7 +34,7 @@ obj-y := debug-monitors.o entry.o irq. - cpufeature.o alternative.o cacheinfo.o \ - smp.o smp_spin_table.o topology.o smccc-call.o \ - syscall.o proton-pack.o idle.o patching.o pi/ \ -- rsi.o -+ rsi.o jump_label.o - - obj-$(CONFIG_COMPAT) += sys32.o signal32.o \ - sys_compat.o -@@ -47,7 +47,6 @@ obj-$(CONFIG_PERF_EVENTS) += perf_regs. - obj-$(CONFIG_HARDLOCKUP_DETECTOR_PERF) += watchdog_hld.o - obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o - obj-$(CONFIG_CPU_PM) += sleep.o suspend.o --obj-$(CONFIG_JUMP_LABEL) += jump_label.o - obj-$(CONFIG_KGDB) += kgdb.o - obj-$(CONFIG_EFI) += efi.o efi-rt-wrapper.o - obj-$(CONFIG_PCI) += pci.o -@@ -81,7 +80,7 @@ obj-y += head.o - always-$(KBUILD_BUILTIN) += vmlinux.lds - - ifeq ($(CONFIG_DEBUG_EFI),y) --AFLAGS_head.o += -DVMLINUX_PATH="\"$(realpath $(objtree)/vmlinux)\"" -+AFLAGS_head.o += -DVMLINUX_PATH="\"$(abspath vmlinux)\"" - endif - - # for cleaning -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kernel/module.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/module.c ---- BPI-Router-Linux-kernel/arch/arm64/kernel/module.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/module.c 2025-10-22 13:53:56.295170202 -0400 -@@ -453,6 +453,17 @@ static int module_init_ftrace_plt(const - __init_plt(&plts[FTRACE_PLT_IDX], FTRACE_ADDR); - - mod->arch.ftrace_trampolines = plts; -+ -+ s = find_section(hdr, sechdrs, ".init.text.ftrace_trampoline"); -+ if (!s) -+ return -ENOEXEC; -+ -+ plts = (void *)s->sh_addr; -+ -+ __init_plt(&plts[FTRACE_PLT_IDX], FTRACE_ADDR); -+ -+ mod->arch.init_ftrace_trampolines = plts; -+ - #endif - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kernel/module-plts.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/module-plts.c ---- BPI-Router-Linux-kernel/arch/arm64/kernel/module-plts.c 2025-10-22 13:53:23.063329853 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/module-plts.c 2025-10-22 13:53:56.295170202 -0400 -@@ -283,7 +283,7 @@ int module_frob_arch_sections(Elf_Ehdr * - unsigned long core_plts = 0; - unsigned long init_plts = 0; - Elf64_Sym *syms = NULL; -- Elf_Shdr *pltsec, *tramp = NULL; -+ Elf_Shdr *pltsec, *tramp = NULL, *init_tramp = NULL; - int i; - - /* -@@ -298,6 +298,9 @@ int module_frob_arch_sections(Elf_Ehdr * - else if (!strcmp(secstrings + sechdrs[i].sh_name, - ".text.ftrace_trampoline")) - tramp = sechdrs + i; -+ else if (!strcmp(secstrings + sechdrs[i].sh_name, -+ ".init.text.ftrace_trampoline")) -+ init_tramp = sechdrs + i; - else if (sechdrs[i].sh_type == SHT_SYMTAB) - syms = (Elf64_Sym *)sechdrs[i].sh_addr; - } -@@ -363,5 +366,12 @@ int module_frob_arch_sections(Elf_Ehdr * - tramp->sh_size = NR_FTRACE_PLTS * sizeof(struct plt_entry); - } - -+ if (init_tramp) { -+ init_tramp->sh_type = SHT_NOBITS; -+ init_tramp->sh_flags = SHF_EXECINSTR | SHF_ALLOC; -+ init_tramp->sh_addralign = __alignof__(struct plt_entry); -+ init_tramp->sh_size = NR_FTRACE_PLTS * sizeof(struct plt_entry); -+ } -+ - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kernel/process.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/process.c ---- BPI-Router-Linux-kernel/arch/arm64/kernel/process.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/process.c 2025-10-22 13:53:56.295170202 -0400 -@@ -288,7 +288,9 @@ static void flush_gcs(void) - if (!system_supports_gcs()) - return; - -- gcs_free(current); -+ current->thread.gcspr_el0 = 0; -+ current->thread.gcs_base = 0; -+ current->thread.gcs_size = 0; - current->thread.gcs_el0_mode = 0; - write_sysreg_s(GCSCRE0_EL1_nTR, SYS_GCSCRE0_EL1); - write_sysreg_s(0, SYS_GCSPR_EL0); -@@ -305,13 +307,13 @@ static int copy_thread_gcs(struct task_s - p->thread.gcs_base = 0; - p->thread.gcs_size = 0; - -+ p->thread.gcs_el0_mode = current->thread.gcs_el0_mode; -+ p->thread.gcs_el0_locked = current->thread.gcs_el0_locked; -+ - gcs = gcs_alloc_thread_stack(p, args); - if (IS_ERR_VALUE(gcs)) - return PTR_ERR((void *)gcs); - -- p->thread.gcs_el0_mode = current->thread.gcs_el0_mode; -- p->thread.gcs_el0_locked = current->thread.gcs_el0_locked; -- - return 0; - } - -@@ -671,6 +673,11 @@ static void permission_overlay_switch(st - current->thread.por_el0 = read_sysreg_s(SYS_POR_EL0); - if (current->thread.por_el0 != next->thread.por_el0) { - write_sysreg_s(next->thread.por_el0, SYS_POR_EL0); -+ /* -+ * No ISB required as we can tolerate spurious Overlay faults - -+ * the fault handler will check again based on the new value -+ * of POR_EL0. -+ */ - } - } - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kernel/ptrace.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/ptrace.c ---- BPI-Router-Linux-kernel/arch/arm64/kernel/ptrace.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/ptrace.c 2025-10-22 13:53:56.295170202 -0400 -@@ -141,7 +141,7 @@ unsigned long regs_get_kernel_stack_nth( - - addr += n; - if (regs_within_kernel_stack(regs, (unsigned long)addr)) -- return *addr; -+ return READ_ONCE_NOCHECK(*addr); - else - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kernel/smp.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/smp.c ---- BPI-Router-Linux-kernel/arch/arm64/kernel/smp.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/smp.c 2025-10-22 13:53:56.295170202 -0400 -@@ -1143,7 +1143,7 @@ static inline unsigned int num_other_onl - void smp_send_stop(void) - { - static unsigned long stop_in_progress; -- cpumask_t mask; -+ static cpumask_t mask; - unsigned long timeout; - - /* -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kernel/stacktrace.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/stacktrace.c ---- BPI-Router-Linux-kernel/arch/arm64/kernel/stacktrace.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/stacktrace.c 2025-10-22 13:53:56.295170202 -0400 -@@ -152,6 +152,8 @@ kunwind_recover_return_address(struct ku - orig_pc = kretprobe_find_ret_addr(state->task, - (void *)state->common.fp, - &state->kr_cur); -+ if (!orig_pc) -+ return -EINVAL; - state->common.pc = orig_pc; - state->flags.kretprobe = 1; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kernel/traps.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/traps.c ---- BPI-Router-Linux-kernel/arch/arm64/kernel/traps.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kernel/traps.c 2025-10-22 13:53:56.295170202 -0400 -@@ -931,6 +931,7 @@ void __noreturn panic_bad_stack(struct p - - void __noreturn arm64_serror_panic(struct pt_regs *regs, unsigned long esr) - { -+ add_taint(TAINT_MACHINE_CHECK, LOCKDEP_STILL_OK); - console_verbose(); - - pr_crit("SError Interrupt on CPU%d, code 0x%016lx -- %s\n", -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kvm/arch_timer.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/arch_timer.c ---- BPI-Router-Linux-kernel/arch/arm64/kvm/arch_timer.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/arch_timer.c 2025-10-22 13:53:56.295170202 -0400 -@@ -108,16 +108,16 @@ static void timer_set_ctl(struct arch_ti - - switch(arch_timer_ctx_index(ctxt)) { - case TIMER_VTIMER: -- __vcpu_sys_reg(vcpu, CNTV_CTL_EL0) = ctl; -+ __vcpu_assign_sys_reg(vcpu, CNTV_CTL_EL0, ctl); - break; - case TIMER_PTIMER: -- __vcpu_sys_reg(vcpu, CNTP_CTL_EL0) = ctl; -+ __vcpu_assign_sys_reg(vcpu, CNTP_CTL_EL0, ctl); - break; - case TIMER_HVTIMER: -- __vcpu_sys_reg(vcpu, CNTHV_CTL_EL2) = ctl; -+ __vcpu_assign_sys_reg(vcpu, CNTHV_CTL_EL2, ctl); - break; - case TIMER_HPTIMER: -- __vcpu_sys_reg(vcpu, CNTHP_CTL_EL2) = ctl; -+ __vcpu_assign_sys_reg(vcpu, CNTHP_CTL_EL2, ctl); - break; - default: - WARN_ON(1); -@@ -130,16 +130,16 @@ static void timer_set_cval(struct arch_t - - switch(arch_timer_ctx_index(ctxt)) { - case TIMER_VTIMER: -- __vcpu_sys_reg(vcpu, CNTV_CVAL_EL0) = cval; -+ __vcpu_assign_sys_reg(vcpu, CNTV_CVAL_EL0, cval); - break; - case TIMER_PTIMER: -- __vcpu_sys_reg(vcpu, CNTP_CVAL_EL0) = cval; -+ __vcpu_assign_sys_reg(vcpu, CNTP_CVAL_EL0, cval); - break; - case TIMER_HVTIMER: -- __vcpu_sys_reg(vcpu, CNTHV_CVAL_EL2) = cval; -+ __vcpu_assign_sys_reg(vcpu, CNTHV_CVAL_EL2, cval); - break; - case TIMER_HPTIMER: -- __vcpu_sys_reg(vcpu, CNTHP_CVAL_EL2) = cval; -+ __vcpu_assign_sys_reg(vcpu, CNTHP_CVAL_EL2, cval); - break; - default: - WARN_ON(1); -@@ -1036,7 +1036,7 @@ void kvm_timer_vcpu_reset(struct kvm_vcp - if (vcpu_has_nv(vcpu)) { - struct arch_timer_offset *offs = &vcpu_vtimer(vcpu)->offset; - -- offs->vcpu_offset = &__vcpu_sys_reg(vcpu, CNTVOFF_EL2); -+ offs->vcpu_offset = __ctxt_sys_reg(&vcpu->arch.ctxt, CNTVOFF_EL2); - offs->vm_offset = &vcpu->kvm->arch.timer_data.poffset; - } - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kvm/arm.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/arm.c ---- BPI-Router-Linux-kernel/arch/arm64/kvm/arm.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/arm.c 2025-10-22 13:53:56.295170202 -0400 -@@ -825,10 +825,6 @@ int kvm_arch_vcpu_run_pid_change(struct - if (!kvm_arm_vcpu_is_finalized(vcpu)) - return -EPERM; - -- ret = kvm_arch_vcpu_run_map_fp(vcpu); -- if (ret) -- return ret; -- - if (likely(vcpu_has_run_once(vcpu))) - return 0; - -@@ -2129,7 +2125,7 @@ static void cpu_hyp_init(void *discard) - - static void cpu_hyp_uninit(void *discard) - { -- if (__this_cpu_read(kvm_hyp_initialized)) { -+ if (!is_protected_kvm_enabled() && __this_cpu_read(kvm_hyp_initialized)) { - cpu_hyp_reset(); - __this_cpu_write(kvm_hyp_initialized, 0); - } -@@ -2345,8 +2341,13 @@ static void __init teardown_hyp_mode(voi - - free_hyp_pgds(); - for_each_possible_cpu(cpu) { -+ if (per_cpu(kvm_hyp_initialized, cpu)) -+ continue; -+ - free_pages(per_cpu(kvm_arm_hyp_stack_base, cpu), NVHE_STACK_SHIFT - PAGE_SHIFT); -- free_pages(kvm_nvhe_sym(kvm_arm_hyp_percpu_base)[cpu], nvhe_percpu_order()); -+ -+ if (!kvm_nvhe_sym(kvm_arm_hyp_percpu_base)[cpu]) -+ continue; - - if (free_sve) { - struct cpu_sve_state *sve_state; -@@ -2354,6 +2355,9 @@ static void __init teardown_hyp_mode(voi - sve_state = per_cpu_ptr_nvhe_sym(kvm_host_data, cpu)->sve_state; - free_pages((unsigned long) sve_state, pkvm_host_sve_state_order()); - } -+ -+ free_pages(kvm_nvhe_sym(kvm_arm_hyp_percpu_base)[cpu], nvhe_percpu_order()); -+ - } - } - -@@ -2764,7 +2768,8 @@ void kvm_arch_irq_bypass_del_producer(st - bool kvm_arch_irqfd_route_changed(struct kvm_kernel_irq_routing_entry *old, - struct kvm_kernel_irq_routing_entry *new) - { -- if (new->type != KVM_IRQ_ROUTING_MSI) -+ if (old->type != KVM_IRQ_ROUTING_MSI || -+ new->type != KVM_IRQ_ROUTING_MSI) - return true; - - return memcmp(&old->msi, &new->msi, sizeof(new->msi)); -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kvm/debug.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/debug.c ---- BPI-Router-Linux-kernel/arch/arm64/kvm/debug.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/debug.c 2025-10-22 13:53:56.295170202 -0400 -@@ -216,9 +216,9 @@ void kvm_debug_set_guest_ownership(struc - void kvm_debug_handle_oslar(struct kvm_vcpu *vcpu, u64 val) - { - if (val & OSLAR_EL1_OSLK) -- __vcpu_sys_reg(vcpu, OSLSR_EL1) |= OSLSR_EL1_OSLK; -+ __vcpu_rmw_sys_reg(vcpu, OSLSR_EL1, |=, OSLSR_EL1_OSLK); - else -- __vcpu_sys_reg(vcpu, OSLSR_EL1) &= ~OSLSR_EL1_OSLK; -+ __vcpu_rmw_sys_reg(vcpu, OSLSR_EL1, &=, ~OSLSR_EL1_OSLK); - - preempt_disable(); - kvm_arch_vcpu_put(vcpu); -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kvm/fpsimd.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/fpsimd.c ---- BPI-Router-Linux-kernel/arch/arm64/kvm/fpsimd.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/fpsimd.c 2025-10-22 13:53:56.295170202 -0400 -@@ -15,32 +15,6 @@ - #include - - /* -- * Called on entry to KVM_RUN unless this vcpu previously ran at least -- * once and the most recent prior KVM_RUN for this vcpu was called from -- * the same task as current (highly likely). -- * -- * This is guaranteed to execute before kvm_arch_vcpu_load_fp(vcpu), -- * such that on entering hyp the relevant parts of current are already -- * mapped. -- */ --int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu) --{ -- struct user_fpsimd_state *fpsimd = ¤t->thread.uw.fpsimd_state; -- int ret; -- -- /* pKVM has its own tracking of the host fpsimd state. */ -- if (is_protected_kvm_enabled()) -- return 0; -- -- /* Make sure the host task fpsimd state is visible to hyp: */ -- ret = kvm_share_hyp(fpsimd, fpsimd + 1); -- if (ret) -- return ret; -- -- return 0; --} -- --/* - * Prepare vcpu for saving the host's FPSIMD state and loading the guest's. - * The actual loading is done by the FPSIMD access trap taken to hyp. - * -@@ -103,8 +77,8 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm - fp_state.sve_state = vcpu->arch.sve_state; - fp_state.sve_vl = vcpu->arch.sve_max_vl; - fp_state.sme_state = NULL; -- fp_state.svcr = &__vcpu_sys_reg(vcpu, SVCR); -- fp_state.fpmr = &__vcpu_sys_reg(vcpu, FPMR); -+ fp_state.svcr = __ctxt_sys_reg(&vcpu->arch.ctxt, SVCR); -+ fp_state.fpmr = __ctxt_sys_reg(&vcpu->arch.ctxt, FPMR); - fp_state.fp_type = &vcpu->arch.fp_type; - - if (vcpu_has_sve(vcpu)) -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kvm/hyp/exception.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/hyp/exception.c ---- BPI-Router-Linux-kernel/arch/arm64/kvm/hyp/exception.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/hyp/exception.c 2025-10-22 13:53:56.295170202 -0400 -@@ -26,7 +26,8 @@ static inline u64 __vcpu_read_sys_reg(co - - if (unlikely(vcpu_has_nv(vcpu))) - return vcpu_read_sys_reg(vcpu, reg); -- else if (__vcpu_read_sys_reg_from_cpu(reg, &val)) -+ else if (vcpu_get_flag(vcpu, SYSREGS_ON_CPU) && -+ __vcpu_read_sys_reg_from_cpu(reg, &val)) - return val; - - return __vcpu_sys_reg(vcpu, reg); -@@ -36,8 +37,9 @@ static inline void __vcpu_write_sys_reg( - { - if (unlikely(vcpu_has_nv(vcpu))) - vcpu_write_sys_reg(vcpu, val, reg); -- else if (!__vcpu_write_sys_reg_to_cpu(val, reg)) -- __vcpu_sys_reg(vcpu, reg) = val; -+ else if (!vcpu_get_flag(vcpu, SYSREGS_ON_CPU) || -+ !__vcpu_write_sys_reg_to_cpu(val, reg)) -+ __vcpu_assign_sys_reg(vcpu, reg, val); - } - - static void __vcpu_write_spsr(struct kvm_vcpu *vcpu, unsigned long target_mode, -@@ -51,7 +53,7 @@ static void __vcpu_write_spsr(struct kvm - } else if (has_vhe()) { - write_sysreg_el1(val, SYS_SPSR); - } else { -- __vcpu_sys_reg(vcpu, SPSR_EL1) = val; -+ __vcpu_assign_sys_reg(vcpu, SPSR_EL1, val); - } - } - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kvm/hyp/include/hyp/switch.h BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/hyp/include/hyp/switch.h ---- BPI-Router-Linux-kernel/arch/arm64/kvm/hyp/include/hyp/switch.h 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/hyp/include/hyp/switch.h 2025-10-22 13:53:56.295170202 -0400 -@@ -45,7 +45,7 @@ static inline void __fpsimd_save_fpexc32 - if (!vcpu_el1_is_32bit(vcpu)) - return; - -- __vcpu_sys_reg(vcpu, FPEXC32_EL2) = read_sysreg(fpexc32_el2); -+ __vcpu_assign_sys_reg(vcpu, FPEXC32_EL2, read_sysreg(fpexc32_el2)); - } - - static inline void __activate_traps_fpsimd32(struct kvm_vcpu *vcpu) -@@ -65,6 +65,136 @@ static inline void __activate_traps_fpsi - } - } - -+static inline void __activate_cptr_traps_nvhe(struct kvm_vcpu *vcpu) -+{ -+ u64 val = CPTR_NVHE_EL2_RES1 | CPTR_EL2_TAM | CPTR_EL2_TTA; -+ -+ /* -+ * Always trap SME since it's not supported in KVM. -+ * TSM is RES1 if SME isn't implemented. -+ */ -+ val |= CPTR_EL2_TSM; -+ -+ if (!vcpu_has_sve(vcpu) || !guest_owns_fp_regs()) -+ val |= CPTR_EL2_TZ; -+ -+ if (!guest_owns_fp_regs()) -+ val |= CPTR_EL2_TFP; -+ -+ write_sysreg(val, cptr_el2); -+} -+ -+static inline void __activate_cptr_traps_vhe(struct kvm_vcpu *vcpu) -+{ -+ /* -+ * With VHE (HCR.E2H == 1), accesses to CPACR_EL1 are routed to -+ * CPTR_EL2. In general, CPACR_EL1 has the same layout as CPTR_EL2, -+ * except for some missing controls, such as TAM. -+ * In this case, CPTR_EL2.TAM has the same position with or without -+ * VHE (HCR.E2H == 1) which allows us to use here the CPTR_EL2.TAM -+ * shift value for trapping the AMU accesses. -+ */ -+ u64 val = CPTR_EL2_TAM | CPACR_EL1_TTA; -+ u64 cptr; -+ -+ if (guest_owns_fp_regs()) { -+ val |= CPACR_EL1_FPEN; -+ if (vcpu_has_sve(vcpu)) -+ val |= CPACR_EL1_ZEN; -+ } -+ -+ if (!vcpu_has_nv(vcpu)) -+ goto write; -+ -+ /* -+ * The architecture is a bit crap (what a surprise): an EL2 guest -+ * writing to CPTR_EL2 via CPACR_EL1 can't set any of TCPAC or TTA, -+ * as they are RES0 in the guest's view. To work around it, trap the -+ * sucker using the very same bit it can't set... -+ */ -+ if (vcpu_el2_e2h_is_set(vcpu) && is_hyp_ctxt(vcpu)) -+ val |= CPTR_EL2_TCPAC; -+ -+ /* -+ * Layer the guest hypervisor's trap configuration on top of our own if -+ * we're in a nested context. -+ */ -+ if (is_hyp_ctxt(vcpu)) -+ goto write; -+ -+ cptr = vcpu_sanitised_cptr_el2(vcpu); -+ -+ /* -+ * Pay attention, there's some interesting detail here. -+ * -+ * The CPTR_EL2.xEN fields are 2 bits wide, although there are only two -+ * meaningful trap states when HCR_EL2.TGE = 0 (running a nested guest): -+ * -+ * - CPTR_EL2.xEN = x0, traps are enabled -+ * - CPTR_EL2.xEN = x1, traps are disabled -+ * -+ * In other words, bit[0] determines if guest accesses trap or not. In -+ * the interest of simplicity, clear the entire field if the guest -+ * hypervisor has traps enabled to dispel any illusion of something more -+ * complicated taking place. -+ */ -+ if (!(SYS_FIELD_GET(CPACR_EL1, FPEN, cptr) & BIT(0))) -+ val &= ~CPACR_EL1_FPEN; -+ if (!(SYS_FIELD_GET(CPACR_EL1, ZEN, cptr) & BIT(0))) -+ val &= ~CPACR_EL1_ZEN; -+ -+ if (kvm_has_feat(vcpu->kvm, ID_AA64MMFR3_EL1, S2POE, IMP)) -+ val |= cptr & CPACR_EL1_E0POE; -+ -+ val |= cptr & CPTR_EL2_TCPAC; -+ -+write: -+ write_sysreg(val, cpacr_el1); -+} -+ -+static inline void __activate_cptr_traps(struct kvm_vcpu *vcpu) -+{ -+ if (!guest_owns_fp_regs()) -+ __activate_traps_fpsimd32(vcpu); -+ -+ if (has_vhe() || has_hvhe()) -+ __activate_cptr_traps_vhe(vcpu); -+ else -+ __activate_cptr_traps_nvhe(vcpu); -+} -+ -+static inline void __deactivate_cptr_traps_nvhe(struct kvm_vcpu *vcpu) -+{ -+ u64 val = CPTR_NVHE_EL2_RES1; -+ -+ if (!cpus_have_final_cap(ARM64_SVE)) -+ val |= CPTR_EL2_TZ; -+ if (!cpus_have_final_cap(ARM64_SME)) -+ val |= CPTR_EL2_TSM; -+ -+ write_sysreg(val, cptr_el2); -+} -+ -+static inline void __deactivate_cptr_traps_vhe(struct kvm_vcpu *vcpu) -+{ -+ u64 val = CPACR_EL1_FPEN; -+ -+ if (cpus_have_final_cap(ARM64_SVE)) -+ val |= CPACR_EL1_ZEN; -+ if (cpus_have_final_cap(ARM64_SME)) -+ val |= CPACR_EL1_SMEN; -+ -+ write_sysreg(val, cpacr_el1); -+} -+ -+static inline void __deactivate_cptr_traps(struct kvm_vcpu *vcpu) -+{ -+ if (has_vhe() || has_hvhe()) -+ __deactivate_cptr_traps_vhe(vcpu); -+ else -+ __deactivate_cptr_traps_nvhe(vcpu); -+} -+ - #define reg_to_fgt_masks(reg) \ - ({ \ - struct fgt_masks *m; \ -@@ -456,7 +586,7 @@ static inline void fpsimd_lazy_switch_to - */ - if (vcpu_has_sve(vcpu)) { - zcr_el1 = read_sysreg_el1(SYS_ZCR); -- __vcpu_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu)) = zcr_el1; -+ __vcpu_assign_sys_reg(vcpu, vcpu_sve_zcr_elx(vcpu), zcr_el1); - - /* - * The guest's state is always saved using the guest's max VL. -@@ -486,11 +616,6 @@ static void kvm_hyp_save_fpsimd_host(str - */ - if (system_supports_sve()) { - __hyp_sve_save_host(); -- -- /* Re-enable SVE traps if not supported for the guest vcpu. */ -- if (!vcpu_has_sve(vcpu)) -- cpacr_clear_set(CPACR_EL1_ZEN, 0); -- - } else { - __fpsimd_save_state(host_data_ptr(host_ctxt.fp_regs)); - } -@@ -541,10 +666,7 @@ static inline bool kvm_hyp_handle_fpsimd - /* Valid trap. Switch the context: */ - - /* First disable enough traps to allow us to update the registers */ -- if (sve_guest || (is_protected_kvm_enabled() && system_supports_sve())) -- cpacr_clear_set(0, CPACR_EL1_FPEN | CPACR_EL1_ZEN); -- else -- cpacr_clear_set(0, CPACR_EL1_FPEN); -+ __deactivate_cptr_traps(vcpu); - isb(); - - /* Write out the host state if it's in the registers */ -@@ -566,6 +688,13 @@ static inline bool kvm_hyp_handle_fpsimd - - *host_data_ptr(fp_owner) = FP_STATE_GUEST_OWNED; - -+ /* -+ * Re-enable traps necessary for the current state of the guest, e.g. -+ * those enabled by a guest hypervisor. The ERET to the guest will -+ * provide the necessary context synchronization. -+ */ -+ __activate_cptr_traps(vcpu); -+ - return true; - } - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h ---- BPI-Router-Linux-kernel/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h 2025-10-22 13:53:56.295170202 -0400 -@@ -307,11 +307,11 @@ static inline void __sysreg32_save_state - vcpu->arch.ctxt.spsr_irq = read_sysreg(spsr_irq); - vcpu->arch.ctxt.spsr_fiq = read_sysreg(spsr_fiq); - -- __vcpu_sys_reg(vcpu, DACR32_EL2) = read_sysreg(dacr32_el2); -- __vcpu_sys_reg(vcpu, IFSR32_EL2) = read_sysreg(ifsr32_el2); -+ __vcpu_assign_sys_reg(vcpu, DACR32_EL2, read_sysreg(dacr32_el2)); -+ __vcpu_assign_sys_reg(vcpu, IFSR32_EL2, read_sysreg(ifsr32_el2)); - - if (has_vhe() || kvm_debug_regs_in_use(vcpu)) -- __vcpu_sys_reg(vcpu, DBGVCR32_EL2) = read_sysreg(dbgvcr32_el2); -+ __vcpu_assign_sys_reg(vcpu, DBGVCR32_EL2, read_sysreg(dbgvcr32_el2)); - } - - static inline void __sysreg32_restore_state(struct kvm_vcpu *vcpu) -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kvm/hyp/nvhe/hyp-main.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/hyp/nvhe/hyp-main.c ---- BPI-Router-Linux-kernel/arch/arm64/kvm/hyp/nvhe/hyp-main.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/hyp/nvhe/hyp-main.c 2025-10-22 13:53:56.295170202 -0400 -@@ -26,7 +26,7 @@ void __kvm_hyp_host_forward_smc(struct k - - static void __hyp_sve_save_guest(struct kvm_vcpu *vcpu) - { -- __vcpu_sys_reg(vcpu, ZCR_EL1) = read_sysreg_el1(SYS_ZCR); -+ __vcpu_assign_sys_reg(vcpu, ZCR_EL1, read_sysreg_el1(SYS_ZCR)); - /* - * On saving/restoring guest sve state, always use the maximum VL for - * the guest. The layout of the data when saving the sve state depends -@@ -69,7 +69,10 @@ static void fpsimd_sve_sync(struct kvm_v - if (!guest_owns_fp_regs()) - return; - -- cpacr_clear_set(0, CPACR_EL1_FPEN | CPACR_EL1_ZEN); -+ /* -+ * Traps have been disabled by __deactivate_cptr_traps(), but there -+ * hasn't necessarily been a context synchronization event yet. -+ */ - isb(); - - if (vcpu_has_sve(vcpu)) -@@ -79,7 +82,7 @@ static void fpsimd_sve_sync(struct kvm_v - - has_fpmr = kvm_has_fpmr(kern_hyp_va(vcpu->kvm)); - if (has_fpmr) -- __vcpu_sys_reg(vcpu, FPMR) = read_sysreg_s(SYS_FPMR); -+ __vcpu_assign_sys_reg(vcpu, FPMR, read_sysreg_s(SYS_FPMR)); - - if (system_supports_sve()) - __hyp_sve_restore_host(); -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kvm/hyp/nvhe/mem_protect.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/hyp/nvhe/mem_protect.c ---- BPI-Router-Linux-kernel/arch/arm64/kvm/hyp/nvhe/mem_protect.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/hyp/nvhe/mem_protect.c 2025-10-22 13:53:56.295170202 -0400 -@@ -479,6 +479,7 @@ static int host_stage2_adjust_range(u64 - { - struct kvm_mem_range cur; - kvm_pte_t pte; -+ u64 granule; - s8 level; - int ret; - -@@ -496,18 +497,21 @@ static int host_stage2_adjust_range(u64 - return -EPERM; - } - -- do { -- u64 granule = kvm_granule_size(level); -+ for (; level <= KVM_PGTABLE_LAST_LEVEL; level++) { -+ if (!kvm_level_supports_block_mapping(level)) -+ continue; -+ granule = kvm_granule_size(level); - cur.start = ALIGN_DOWN(addr, granule); - cur.end = cur.start + granule; -- level++; -- } while ((level <= KVM_PGTABLE_LAST_LEVEL) && -- !(kvm_level_supports_block_mapping(level) && -- range_included(&cur, range))); -+ if (!range_included(&cur, range)) -+ continue; -+ *range = cur; -+ return 0; -+ } - -- *range = cur; -+ WARN_ON(1); - -- return 0; -+ return -EINVAL; - } - - int host_stage2_idmap_locked(phys_addr_t addr, u64 size, -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kvm/hyp/nvhe/switch.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/hyp/nvhe/switch.c ---- BPI-Router-Linux-kernel/arch/arm64/kvm/hyp/nvhe/switch.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/hyp/nvhe/switch.c 2025-10-22 13:53:56.295170202 -0400 -@@ -47,65 +47,6 @@ struct fgt_masks hdfgwtr2_masks; - - extern void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc); - --static void __activate_cptr_traps(struct kvm_vcpu *vcpu) --{ -- u64 val = CPTR_EL2_TAM; /* Same bit irrespective of E2H */ -- -- if (!guest_owns_fp_regs()) -- __activate_traps_fpsimd32(vcpu); -- -- if (has_hvhe()) { -- val |= CPACR_EL1_TTA; -- -- if (guest_owns_fp_regs()) { -- val |= CPACR_EL1_FPEN; -- if (vcpu_has_sve(vcpu)) -- val |= CPACR_EL1_ZEN; -- } -- -- write_sysreg(val, cpacr_el1); -- } else { -- val |= CPTR_EL2_TTA | CPTR_NVHE_EL2_RES1; -- -- /* -- * Always trap SME since it's not supported in KVM. -- * TSM is RES1 if SME isn't implemented. -- */ -- val |= CPTR_EL2_TSM; -- -- if (!vcpu_has_sve(vcpu) || !guest_owns_fp_regs()) -- val |= CPTR_EL2_TZ; -- -- if (!guest_owns_fp_regs()) -- val |= CPTR_EL2_TFP; -- -- write_sysreg(val, cptr_el2); -- } --} -- --static void __deactivate_cptr_traps(struct kvm_vcpu *vcpu) --{ -- if (has_hvhe()) { -- u64 val = CPACR_EL1_FPEN; -- -- if (cpus_have_final_cap(ARM64_SVE)) -- val |= CPACR_EL1_ZEN; -- if (cpus_have_final_cap(ARM64_SME)) -- val |= CPACR_EL1_SMEN; -- -- write_sysreg(val, cpacr_el1); -- } else { -- u64 val = CPTR_NVHE_EL2_RES1; -- -- if (!cpus_have_final_cap(ARM64_SVE)) -- val |= CPTR_EL2_TZ; -- if (!cpus_have_final_cap(ARM64_SME)) -- val |= CPTR_EL2_TSM; -- -- write_sysreg(val, cptr_el2); -- } --} -- - static void __activate_traps(struct kvm_vcpu *vcpu) - { - ___activate_traps(vcpu, vcpu->arch.hcr_el2); -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kvm/hyp/vhe/switch.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/hyp/vhe/switch.c ---- BPI-Router-Linux-kernel/arch/arm64/kvm/hyp/vhe/switch.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/hyp/vhe/switch.c 2025-10-22 13:53:56.295170202 -0400 -@@ -48,8 +48,7 @@ DEFINE_PER_CPU(unsigned long, kvm_hyp_ve - - static u64 __compute_hcr(struct kvm_vcpu *vcpu) - { -- u64 guest_hcr = __vcpu_sys_reg(vcpu, HCR_EL2); -- u64 hcr = vcpu->arch.hcr_el2; -+ u64 guest_hcr, hcr = vcpu->arch.hcr_el2; - - if (!vcpu_has_nv(vcpu)) - return hcr; -@@ -68,10 +67,21 @@ static u64 __compute_hcr(struct kvm_vcpu - if (!vcpu_el2_e2h_is_set(vcpu)) - hcr |= HCR_NV1; - -+ /* -+ * Nothing in HCR_EL2 should impact running in hypervisor -+ * context, apart from bits we have defined as RESx (E2H, -+ * HCD and co), or that cannot be set directly (the EXCLUDE -+ * bits). Given that we OR the guest's view with the host's, -+ * we can use the 0 value as the starting point, and only -+ * use the config-driven RES1 bits. -+ */ -+ guest_hcr = kvm_vcpu_apply_reg_masks(vcpu, HCR_EL2, 0); -+ - write_sysreg_s(vcpu->arch.ctxt.vncr_array, SYS_VNCR_EL2); - } else { - host_data_clear_flag(VCPU_IN_HYP_CONTEXT); - -+ guest_hcr = __vcpu_sys_reg(vcpu, HCR_EL2); - if (guest_hcr & HCR_NV) { - u64 va = __fix_to_virt(vncr_fixmap(smp_processor_id())); - -@@ -90,87 +100,6 @@ static u64 __compute_hcr(struct kvm_vcpu - return hcr | (guest_hcr & ~NV_HCR_GUEST_EXCLUDE); - } - --static void __activate_cptr_traps(struct kvm_vcpu *vcpu) --{ -- u64 cptr; -- -- /* -- * With VHE (HCR.E2H == 1), accesses to CPACR_EL1 are routed to -- * CPTR_EL2. In general, CPACR_EL1 has the same layout as CPTR_EL2, -- * except for some missing controls, such as TAM. -- * In this case, CPTR_EL2.TAM has the same position with or without -- * VHE (HCR.E2H == 1) which allows us to use here the CPTR_EL2.TAM -- * shift value for trapping the AMU accesses. -- */ -- u64 val = CPACR_EL1_TTA | CPTR_EL2_TAM; -- -- if (guest_owns_fp_regs()) { -- val |= CPACR_EL1_FPEN; -- if (vcpu_has_sve(vcpu)) -- val |= CPACR_EL1_ZEN; -- } else { -- __activate_traps_fpsimd32(vcpu); -- } -- -- if (!vcpu_has_nv(vcpu)) -- goto write; -- -- /* -- * The architecture is a bit crap (what a surprise): an EL2 guest -- * writing to CPTR_EL2 via CPACR_EL1 can't set any of TCPAC or TTA, -- * as they are RES0 in the guest's view. To work around it, trap the -- * sucker using the very same bit it can't set... -- */ -- if (vcpu_el2_e2h_is_set(vcpu) && is_hyp_ctxt(vcpu)) -- val |= CPTR_EL2_TCPAC; -- -- /* -- * Layer the guest hypervisor's trap configuration on top of our own if -- * we're in a nested context. -- */ -- if (is_hyp_ctxt(vcpu)) -- goto write; -- -- cptr = vcpu_sanitised_cptr_el2(vcpu); -- -- /* -- * Pay attention, there's some interesting detail here. -- * -- * The CPTR_EL2.xEN fields are 2 bits wide, although there are only two -- * meaningful trap states when HCR_EL2.TGE = 0 (running a nested guest): -- * -- * - CPTR_EL2.xEN = x0, traps are enabled -- * - CPTR_EL2.xEN = x1, traps are disabled -- * -- * In other words, bit[0] determines if guest accesses trap or not. In -- * the interest of simplicity, clear the entire field if the guest -- * hypervisor has traps enabled to dispel any illusion of something more -- * complicated taking place. -- */ -- if (!(SYS_FIELD_GET(CPACR_EL1, FPEN, cptr) & BIT(0))) -- val &= ~CPACR_EL1_FPEN; -- if (!(SYS_FIELD_GET(CPACR_EL1, ZEN, cptr) & BIT(0))) -- val &= ~CPACR_EL1_ZEN; -- -- if (kvm_has_feat(vcpu->kvm, ID_AA64MMFR3_EL1, S2POE, IMP)) -- val |= cptr & CPACR_EL1_E0POE; -- -- val |= cptr & CPTR_EL2_TCPAC; -- --write: -- write_sysreg(val, cpacr_el1); --} -- --static void __deactivate_cptr_traps(struct kvm_vcpu *vcpu) --{ -- u64 val = CPACR_EL1_FPEN | CPACR_EL1_ZEN_EL1EN; -- -- if (cpus_have_final_cap(ARM64_SME)) -- val |= CPACR_EL1_SMEN_EL1EN; -- -- write_sysreg(val, cpacr_el1); --} -- - static void __activate_traps(struct kvm_vcpu *vcpu) - { - u64 val; -@@ -223,9 +152,9 @@ static void __deactivate_traps(struct kv - */ - val = read_sysreg_el0(SYS_CNTP_CVAL); - if (map.direct_ptimer == vcpu_ptimer(vcpu)) -- __vcpu_sys_reg(vcpu, CNTP_CVAL_EL0) = val; -+ __vcpu_assign_sys_reg(vcpu, CNTP_CVAL_EL0, val); - if (map.direct_ptimer == vcpu_hptimer(vcpu)) -- __vcpu_sys_reg(vcpu, CNTHP_CVAL_EL2) = val; -+ __vcpu_assign_sys_reg(vcpu, CNTHP_CVAL_EL2, val); - - offset = read_sysreg_s(SYS_CNTPOFF_EL2); - -@@ -639,10 +568,10 @@ static int __kvm_vcpu_run_vhe(struct kvm - host_ctxt = host_data_ptr(host_ctxt); - guest_ctxt = &vcpu->arch.ctxt; - -- sysreg_save_host_state_vhe(host_ctxt); -- - fpsimd_lazy_switch_to_guest(vcpu); - -+ sysreg_save_host_state_vhe(host_ctxt); -+ - /* - * Note that ARM erratum 1165522 requires us to configure both stage 1 - * and stage 2 translation for the guest context before we clear -@@ -667,15 +596,23 @@ static int __kvm_vcpu_run_vhe(struct kvm - - __deactivate_traps(vcpu); - -- fpsimd_lazy_switch_to_host(vcpu); -- - sysreg_restore_host_state_vhe(host_ctxt); - -+ __debug_switch_to_host(vcpu); -+ -+ /* -+ * Ensure that all system register writes above have taken effect -+ * before returning to the host. In VHE mode, CPTR traps for -+ * FPSIMD/SVE/SME also apply to EL2, so FPSIMD/SVE/SME state must be -+ * manipulated after the ISB. -+ */ -+ isb(); -+ -+ fpsimd_lazy_switch_to_host(vcpu); -+ - if (guest_owns_fp_regs()) - __fpsimd_save_fpexc32(vcpu); - -- __debug_switch_to_host(vcpu); -- - return exit_code; - } - NOKPROBE_SYMBOL(__kvm_vcpu_run_vhe); -@@ -705,12 +642,6 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu - */ - local_daif_restore(DAIF_PROCCTX_NOIRQ); - -- /* -- * When we exit from the guest we change a number of CPU configuration -- * parameters, such as traps. We rely on the isb() in kvm_call_hyp*() -- * to make sure these changes take effect before running the host or -- * additional guests. -- */ - return ret; - } - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kvm/hyp/vhe/sysreg-sr.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/hyp/vhe/sysreg-sr.c ---- BPI-Router-Linux-kernel/arch/arm64/kvm/hyp/vhe/sysreg-sr.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/hyp/vhe/sysreg-sr.c 2025-10-22 13:53:56.295170202 -0400 -@@ -18,17 +18,17 @@ - static void __sysreg_save_vel2_state(struct kvm_vcpu *vcpu) - { - /* These registers are common with EL1 */ -- __vcpu_sys_reg(vcpu, PAR_EL1) = read_sysreg(par_el1); -- __vcpu_sys_reg(vcpu, TPIDR_EL1) = read_sysreg(tpidr_el1); -+ __vcpu_assign_sys_reg(vcpu, PAR_EL1, read_sysreg(par_el1)); -+ __vcpu_assign_sys_reg(vcpu, TPIDR_EL1, read_sysreg(tpidr_el1)); - -- __vcpu_sys_reg(vcpu, ESR_EL2) = read_sysreg_el1(SYS_ESR); -- __vcpu_sys_reg(vcpu, AFSR0_EL2) = read_sysreg_el1(SYS_AFSR0); -- __vcpu_sys_reg(vcpu, AFSR1_EL2) = read_sysreg_el1(SYS_AFSR1); -- __vcpu_sys_reg(vcpu, FAR_EL2) = read_sysreg_el1(SYS_FAR); -- __vcpu_sys_reg(vcpu, MAIR_EL2) = read_sysreg_el1(SYS_MAIR); -- __vcpu_sys_reg(vcpu, VBAR_EL2) = read_sysreg_el1(SYS_VBAR); -- __vcpu_sys_reg(vcpu, CONTEXTIDR_EL2) = read_sysreg_el1(SYS_CONTEXTIDR); -- __vcpu_sys_reg(vcpu, AMAIR_EL2) = read_sysreg_el1(SYS_AMAIR); -+ __vcpu_assign_sys_reg(vcpu, ESR_EL2, read_sysreg_el1(SYS_ESR)); -+ __vcpu_assign_sys_reg(vcpu, AFSR0_EL2, read_sysreg_el1(SYS_AFSR0)); -+ __vcpu_assign_sys_reg(vcpu, AFSR1_EL2, read_sysreg_el1(SYS_AFSR1)); -+ __vcpu_assign_sys_reg(vcpu, FAR_EL2, read_sysreg_el1(SYS_FAR)); -+ __vcpu_assign_sys_reg(vcpu, MAIR_EL2, read_sysreg_el1(SYS_MAIR)); -+ __vcpu_assign_sys_reg(vcpu, VBAR_EL2, read_sysreg_el1(SYS_VBAR)); -+ __vcpu_assign_sys_reg(vcpu, CONTEXTIDR_EL2, read_sysreg_el1(SYS_CONTEXTIDR)); -+ __vcpu_assign_sys_reg(vcpu, AMAIR_EL2, read_sysreg_el1(SYS_AMAIR)); - - /* - * In VHE mode those registers are compatible between EL1 and EL2, -@@ -46,21 +46,21 @@ static void __sysreg_save_vel2_state(str - * are always trapped, ensuring that the in-memory - * copy is always up-to-date. A small blessing... - */ -- __vcpu_sys_reg(vcpu, SCTLR_EL2) = read_sysreg_el1(SYS_SCTLR); -- __vcpu_sys_reg(vcpu, TTBR0_EL2) = read_sysreg_el1(SYS_TTBR0); -- __vcpu_sys_reg(vcpu, TTBR1_EL2) = read_sysreg_el1(SYS_TTBR1); -- __vcpu_sys_reg(vcpu, TCR_EL2) = read_sysreg_el1(SYS_TCR); -+ __vcpu_assign_sys_reg(vcpu, SCTLR_EL2, read_sysreg_el1(SYS_SCTLR)); -+ __vcpu_assign_sys_reg(vcpu, TTBR0_EL2, read_sysreg_el1(SYS_TTBR0)); -+ __vcpu_assign_sys_reg(vcpu, TTBR1_EL2, read_sysreg_el1(SYS_TTBR1)); -+ __vcpu_assign_sys_reg(vcpu, TCR_EL2, read_sysreg_el1(SYS_TCR)); - - if (ctxt_has_tcrx(&vcpu->arch.ctxt)) { -- __vcpu_sys_reg(vcpu, TCR2_EL2) = read_sysreg_el1(SYS_TCR2); -+ __vcpu_assign_sys_reg(vcpu, TCR2_EL2, read_sysreg_el1(SYS_TCR2)); - - if (ctxt_has_s1pie(&vcpu->arch.ctxt)) { -- __vcpu_sys_reg(vcpu, PIRE0_EL2) = read_sysreg_el1(SYS_PIRE0); -- __vcpu_sys_reg(vcpu, PIR_EL2) = read_sysreg_el1(SYS_PIR); -+ __vcpu_assign_sys_reg(vcpu, PIRE0_EL2, read_sysreg_el1(SYS_PIRE0)); -+ __vcpu_assign_sys_reg(vcpu, PIR_EL2, read_sysreg_el1(SYS_PIR)); - } - - if (ctxt_has_s1poe(&vcpu->arch.ctxt)) -- __vcpu_sys_reg(vcpu, POR_EL2) = read_sysreg_el1(SYS_POR); -+ __vcpu_assign_sys_reg(vcpu, POR_EL2, read_sysreg_el1(SYS_POR)); - } - - /* -@@ -70,13 +70,13 @@ static void __sysreg_save_vel2_state(str - */ - val = read_sysreg_el1(SYS_CNTKCTL); - val &= CNTKCTL_VALID_BITS; -- __vcpu_sys_reg(vcpu, CNTHCTL_EL2) &= ~CNTKCTL_VALID_BITS; -- __vcpu_sys_reg(vcpu, CNTHCTL_EL2) |= val; -+ __vcpu_rmw_sys_reg(vcpu, CNTHCTL_EL2, &=, ~CNTKCTL_VALID_BITS); -+ __vcpu_rmw_sys_reg(vcpu, CNTHCTL_EL2, |=, val); - } - -- __vcpu_sys_reg(vcpu, SP_EL2) = read_sysreg(sp_el1); -- __vcpu_sys_reg(vcpu, ELR_EL2) = read_sysreg_el1(SYS_ELR); -- __vcpu_sys_reg(vcpu, SPSR_EL2) = read_sysreg_el1(SYS_SPSR); -+ __vcpu_assign_sys_reg(vcpu, SP_EL2, read_sysreg(sp_el1)); -+ __vcpu_assign_sys_reg(vcpu, ELR_EL2, read_sysreg_el1(SYS_ELR)); -+ __vcpu_assign_sys_reg(vcpu, SPSR_EL2, read_sysreg_el1(SYS_SPSR)); - } - - static void __sysreg_restore_vel2_state(struct kvm_vcpu *vcpu) -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kvm/nested.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/nested.c ---- BPI-Router-Linux-kernel/arch/arm64/kvm/nested.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/nested.c 2025-10-22 13:53:56.295170202 -0400 -@@ -1402,6 +1402,21 @@ static void kvm_map_l1_vncr(struct kvm_v - } - } - -+#define has_tgran_2(__r, __sz) \ -+ ({ \ -+ u64 _s1, _s2, _mmfr0 = __r; \ -+ \ -+ _s2 = SYS_FIELD_GET(ID_AA64MMFR0_EL1, \ -+ TGRAN##__sz##_2, _mmfr0); \ -+ \ -+ _s1 = SYS_FIELD_GET(ID_AA64MMFR0_EL1, \ -+ TGRAN##__sz, _mmfr0); \ -+ \ -+ ((_s2 != ID_AA64MMFR0_EL1_TGRAN##__sz##_2_NI && \ -+ _s2 != ID_AA64MMFR0_EL1_TGRAN##__sz##_2_TGRAN##__sz) || \ -+ (_s2 == ID_AA64MMFR0_EL1_TGRAN##__sz##_2_TGRAN##__sz && \ -+ _s1 != ID_AA64MMFR0_EL1_TGRAN##__sz##_NI)); \ -+ }) - /* - * Our emulated CPU doesn't support all the possible features. For the - * sake of simplicity (and probably mental sanity), wipe out a number -@@ -1411,6 +1426,8 @@ static void kvm_map_l1_vncr(struct kvm_v - */ - u64 limit_nv_id_reg(struct kvm *kvm, u32 reg, u64 val) - { -+ u64 orig_val = val; -+ - switch (reg) { - case SYS_ID_AA64ISAR0_EL1: - /* Support everything but TME */ -@@ -1480,13 +1497,16 @@ u64 limit_nv_id_reg(struct kvm *kvm, u32 - */ - switch (PAGE_SIZE) { - case SZ_4K: -- val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR0_EL1, TGRAN4_2, IMP); -+ if (has_tgran_2(orig_val, 4)) -+ val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR0_EL1, TGRAN4_2, IMP); - fallthrough; - case SZ_16K: -- val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR0_EL1, TGRAN16_2, IMP); -+ if (has_tgran_2(orig_val, 16)) -+ val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR0_EL1, TGRAN16_2, IMP); - fallthrough; - case SZ_64K: -- val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR0_EL1, TGRAN64_2, IMP); -+ if (has_tgran_2(orig_val, 64)) -+ val |= SYS_FIELD_PREP_ENUM(ID_AA64MMFR0_EL1, TGRAN64_2, IMP); - break; - } - -@@ -1757,7 +1777,7 @@ int kvm_init_nv_sysregs(struct kvm_vcpu - - out: - for (enum vcpu_sysreg sr = __SANITISED_REG_START__; sr < NR_SYS_REGS; sr++) -- (void)__vcpu_sys_reg(vcpu, sr); -+ __vcpu_rmw_sys_reg(vcpu, sr, |=, 0); - - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kvm/pmu-emul.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/pmu-emul.c ---- BPI-Router-Linux-kernel/arch/arm64/kvm/pmu-emul.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/pmu-emul.c 2025-10-22 13:53:56.295170202 -0400 -@@ -178,7 +178,7 @@ static void kvm_pmu_set_pmc_value(struct - val |= lower_32_bits(val); - } - -- __vcpu_sys_reg(vcpu, reg) = val; -+ __vcpu_assign_sys_reg(vcpu, reg, val); - - /* Recreate the perf event to reflect the updated sample_period */ - kvm_pmu_create_perf_event(pmc); -@@ -204,7 +204,7 @@ void kvm_pmu_set_counter_value(struct kv - void kvm_pmu_set_counter_value_user(struct kvm_vcpu *vcpu, u64 select_idx, u64 val) - { - kvm_pmu_release_perf_event(kvm_vcpu_idx_to_pmc(vcpu, select_idx)); -- __vcpu_sys_reg(vcpu, counter_index_to_reg(select_idx)) = val; -+ __vcpu_assign_sys_reg(vcpu, counter_index_to_reg(select_idx), val); - kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu); - } - -@@ -239,7 +239,7 @@ static void kvm_pmu_stop_counter(struct - - reg = counter_index_to_reg(pmc->idx); - -- __vcpu_sys_reg(vcpu, reg) = val; -+ __vcpu_assign_sys_reg(vcpu, reg, val); - - kvm_pmu_release_perf_event(pmc); - } -@@ -503,14 +503,14 @@ static void kvm_pmu_counter_increment(st - reg = __vcpu_sys_reg(vcpu, counter_index_to_reg(i)) + 1; - if (!kvm_pmc_is_64bit(pmc)) - reg = lower_32_bits(reg); -- __vcpu_sys_reg(vcpu, counter_index_to_reg(i)) = reg; -+ __vcpu_assign_sys_reg(vcpu, counter_index_to_reg(i), reg); - - /* No overflow? move on */ - if (kvm_pmc_has_64bit_overflow(pmc) ? reg : lower_32_bits(reg)) - continue; - - /* Mark overflow */ -- __vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(i); -+ __vcpu_rmw_sys_reg(vcpu, PMOVSSET_EL0, |=, BIT(i)); - - if (kvm_pmu_counter_can_chain(pmc)) - kvm_pmu_counter_increment(vcpu, BIT(i + 1), -@@ -556,7 +556,7 @@ static void kvm_pmu_perf_overflow(struct - perf_event->attr.sample_period = period; - perf_event->hw.sample_period = period; - -- __vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= BIT(idx); -+ __vcpu_rmw_sys_reg(vcpu, PMOVSSET_EL0, |=, BIT(idx)); - - if (kvm_pmu_counter_can_chain(pmc)) - kvm_pmu_counter_increment(vcpu, BIT(idx + 1), -@@ -602,7 +602,7 @@ void kvm_pmu_handle_pmcr(struct kvm_vcpu - kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu); - - /* The reset bits don't indicate any state, and shouldn't be saved. */ -- __vcpu_sys_reg(vcpu, PMCR_EL0) = val & ~(ARMV8_PMU_PMCR_C | ARMV8_PMU_PMCR_P); -+ __vcpu_assign_sys_reg(vcpu, PMCR_EL0, (val & ~(ARMV8_PMU_PMCR_C | ARMV8_PMU_PMCR_P))); - - if (val & ARMV8_PMU_PMCR_C) - kvm_pmu_set_counter_value(vcpu, ARMV8_PMU_CYCLE_IDX, 0); -@@ -779,7 +779,7 @@ void kvm_pmu_set_counter_event_type(stru - u64 reg; - - reg = counter_index_to_evtreg(pmc->idx); -- __vcpu_sys_reg(vcpu, reg) = data & kvm_pmu_evtyper_mask(vcpu->kvm); -+ __vcpu_assign_sys_reg(vcpu, reg, (data & kvm_pmu_evtyper_mask(vcpu->kvm))); - - kvm_pmu_create_perf_event(pmc); - } -@@ -914,9 +914,9 @@ void kvm_vcpu_reload_pmu(struct kvm_vcpu - { - u64 mask = kvm_pmu_implemented_counter_mask(vcpu); - -- __vcpu_sys_reg(vcpu, PMOVSSET_EL0) &= mask; -- __vcpu_sys_reg(vcpu, PMINTENSET_EL1) &= mask; -- __vcpu_sys_reg(vcpu, PMCNTENSET_EL0) &= mask; -+ __vcpu_rmw_sys_reg(vcpu, PMOVSSET_EL0, &=, mask); -+ __vcpu_rmw_sys_reg(vcpu, PMINTENSET_EL1, &=, mask); -+ __vcpu_rmw_sys_reg(vcpu, PMCNTENSET_EL0, &=, mask); - - kvm_pmu_reprogram_counter_mask(vcpu, mask); - } -@@ -1038,7 +1038,7 @@ static void kvm_arm_set_nr_counters(stru - u64 val = __vcpu_sys_reg(vcpu, MDCR_EL2); - val &= ~MDCR_EL2_HPMN; - val |= FIELD_PREP(MDCR_EL2_HPMN, kvm->arch.nr_pmu_counters); -- __vcpu_sys_reg(vcpu, MDCR_EL2) = val; -+ __vcpu_assign_sys_reg(vcpu, MDCR_EL2, val); - } - } - } -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kvm/sys_regs.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/sys_regs.c ---- BPI-Router-Linux-kernel/arch/arm64/kvm/sys_regs.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/sys_regs.c 2025-10-22 13:53:56.295170202 -0400 -@@ -228,7 +228,7 @@ void vcpu_write_sys_reg(struct kvm_vcpu - * to reverse-translate virtual EL2 system registers for a - * non-VHE guest hypervisor. - */ -- __vcpu_sys_reg(vcpu, reg) = val; -+ __vcpu_assign_sys_reg(vcpu, reg, val); - - switch (reg) { - case CNTHCTL_EL2: -@@ -263,7 +263,7 @@ void vcpu_write_sys_reg(struct kvm_vcpu - return; - - memory_write: -- __vcpu_sys_reg(vcpu, reg) = val; -+ __vcpu_assign_sys_reg(vcpu, reg, val); - } - - /* CSSELR values; used to index KVM_REG_ARM_DEMUX_ID_CCSIDR */ -@@ -605,7 +605,7 @@ static int set_oslsr_el1(struct kvm_vcpu - if ((val ^ rd->val) & ~OSLSR_EL1_OSLK) - return -EINVAL; - -- __vcpu_sys_reg(vcpu, rd->reg) = val; -+ __vcpu_assign_sys_reg(vcpu, rd->reg, val); - return 0; - } - -@@ -791,7 +791,7 @@ static u64 reset_pmu_reg(struct kvm_vcpu - mask |= GENMASK(n - 1, 0); - - reset_unknown(vcpu, r); -- __vcpu_sys_reg(vcpu, r->reg) &= mask; -+ __vcpu_rmw_sys_reg(vcpu, r->reg, &=, mask); - - return __vcpu_sys_reg(vcpu, r->reg); - } -@@ -799,7 +799,7 @@ static u64 reset_pmu_reg(struct kvm_vcpu - static u64 reset_pmevcntr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) - { - reset_unknown(vcpu, r); -- __vcpu_sys_reg(vcpu, r->reg) &= GENMASK(31, 0); -+ __vcpu_rmw_sys_reg(vcpu, r->reg, &=, GENMASK(31, 0)); - - return __vcpu_sys_reg(vcpu, r->reg); - } -@@ -811,7 +811,7 @@ static u64 reset_pmevtyper(struct kvm_vc - return 0; - - reset_unknown(vcpu, r); -- __vcpu_sys_reg(vcpu, r->reg) &= kvm_pmu_evtyper_mask(vcpu->kvm); -+ __vcpu_rmw_sys_reg(vcpu, r->reg, &=, kvm_pmu_evtyper_mask(vcpu->kvm)); - - return __vcpu_sys_reg(vcpu, r->reg); - } -@@ -819,7 +819,7 @@ static u64 reset_pmevtyper(struct kvm_vc - static u64 reset_pmselr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) - { - reset_unknown(vcpu, r); -- __vcpu_sys_reg(vcpu, r->reg) &= PMSELR_EL0_SEL_MASK; -+ __vcpu_rmw_sys_reg(vcpu, r->reg, &=, PMSELR_EL0_SEL_MASK); - - return __vcpu_sys_reg(vcpu, r->reg); - } -@@ -835,7 +835,7 @@ static u64 reset_pmcr(struct kvm_vcpu *v - * The value of PMCR.N field is included when the - * vCPU register is read via kvm_vcpu_read_pmcr(). - */ -- __vcpu_sys_reg(vcpu, r->reg) = pmcr; -+ __vcpu_assign_sys_reg(vcpu, r->reg, pmcr); - - return __vcpu_sys_reg(vcpu, r->reg); - } -@@ -907,7 +907,7 @@ static bool access_pmselr(struct kvm_vcp - return false; - - if (p->is_write) -- __vcpu_sys_reg(vcpu, PMSELR_EL0) = p->regval; -+ __vcpu_assign_sys_reg(vcpu, PMSELR_EL0, p->regval); - else - /* return PMSELR.SEL field */ - p->regval = __vcpu_sys_reg(vcpu, PMSELR_EL0) -@@ -1076,7 +1076,7 @@ static int set_pmreg(struct kvm_vcpu *vc - { - u64 mask = kvm_pmu_accessible_counter_mask(vcpu); - -- __vcpu_sys_reg(vcpu, r->reg) = val & mask; -+ __vcpu_assign_sys_reg(vcpu, r->reg, val & mask); - kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu); - - return 0; -@@ -1103,10 +1103,10 @@ static bool access_pmcnten(struct kvm_vc - val = p->regval & mask; - if (r->Op2 & 0x1) - /* accessing PMCNTENSET_EL0 */ -- __vcpu_sys_reg(vcpu, PMCNTENSET_EL0) |= val; -+ __vcpu_rmw_sys_reg(vcpu, PMCNTENSET_EL0, |=, val); - else - /* accessing PMCNTENCLR_EL0 */ -- __vcpu_sys_reg(vcpu, PMCNTENSET_EL0) &= ~val; -+ __vcpu_rmw_sys_reg(vcpu, PMCNTENSET_EL0, &=, ~val); - - kvm_pmu_reprogram_counter_mask(vcpu, val); - } else { -@@ -1129,10 +1129,10 @@ static bool access_pminten(struct kvm_vc - - if (r->Op2 & 0x1) - /* accessing PMINTENSET_EL1 */ -- __vcpu_sys_reg(vcpu, PMINTENSET_EL1) |= val; -+ __vcpu_rmw_sys_reg(vcpu, PMINTENSET_EL1, |=, val); - else - /* accessing PMINTENCLR_EL1 */ -- __vcpu_sys_reg(vcpu, PMINTENSET_EL1) &= ~val; -+ __vcpu_rmw_sys_reg(vcpu, PMINTENSET_EL1, &=, ~val); - } else { - p->regval = __vcpu_sys_reg(vcpu, PMINTENSET_EL1); - } -@@ -1151,10 +1151,10 @@ static bool access_pmovs(struct kvm_vcpu - if (p->is_write) { - if (r->CRm & 0x2) - /* accessing PMOVSSET_EL0 */ -- __vcpu_sys_reg(vcpu, PMOVSSET_EL0) |= (p->regval & mask); -+ __vcpu_rmw_sys_reg(vcpu, PMOVSSET_EL0, |=, (p->regval & mask)); - else - /* accessing PMOVSCLR_EL0 */ -- __vcpu_sys_reg(vcpu, PMOVSSET_EL0) &= ~(p->regval & mask); -+ __vcpu_rmw_sys_reg(vcpu, PMOVSSET_EL0, &=, ~(p->regval & mask)); - } else { - p->regval = __vcpu_sys_reg(vcpu, PMOVSSET_EL0); - } -@@ -1185,8 +1185,8 @@ static bool access_pmuserenr(struct kvm_ - if (!vcpu_mode_priv(vcpu)) - return undef_access(vcpu, p, r); - -- __vcpu_sys_reg(vcpu, PMUSERENR_EL0) = -- p->regval & ARMV8_PMU_USERENR_MASK; -+ __vcpu_assign_sys_reg(vcpu, PMUSERENR_EL0, -+ (p->regval & ARMV8_PMU_USERENR_MASK)); - } else { - p->regval = __vcpu_sys_reg(vcpu, PMUSERENR_EL0) - & ARMV8_PMU_USERENR_MASK; -@@ -1237,7 +1237,7 @@ static int set_pmcr(struct kvm_vcpu *vcp - if (!kvm_supports_32bit_el0()) - val |= ARMV8_PMU_PMCR_LC; - -- __vcpu_sys_reg(vcpu, r->reg) = val; -+ __vcpu_assign_sys_reg(vcpu, r->reg, val); - kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu); - - return 0; -@@ -2213,7 +2213,7 @@ static u64 reset_clidr(struct kvm_vcpu * - if (kvm_has_mte(vcpu->kvm)) - clidr |= 2ULL << CLIDR_TTYPE_SHIFT(loc); - -- __vcpu_sys_reg(vcpu, r->reg) = clidr; -+ __vcpu_assign_sys_reg(vcpu, r->reg, clidr); - - return __vcpu_sys_reg(vcpu, r->reg); - } -@@ -2227,7 +2227,7 @@ static int set_clidr(struct kvm_vcpu *vc - if ((val & CLIDR_EL1_RES0) || (!(ctr_el0 & CTR_EL0_IDC) && idc)) - return -EINVAL; - -- __vcpu_sys_reg(vcpu, rd->reg) = val; -+ __vcpu_assign_sys_reg(vcpu, rd->reg, val); - - return 0; - } -@@ -2404,7 +2404,7 @@ static bool access_sp_el1(struct kvm_vcp - const struct sys_reg_desc *r) - { - if (p->is_write) -- __vcpu_sys_reg(vcpu, SP_EL1) = p->regval; -+ __vcpu_assign_sys_reg(vcpu, SP_EL1, p->regval); - else - p->regval = __vcpu_sys_reg(vcpu, SP_EL1); - -@@ -2428,7 +2428,7 @@ static bool access_spsr(struct kvm_vcpu - const struct sys_reg_desc *r) - { - if (p->is_write) -- __vcpu_sys_reg(vcpu, SPSR_EL1) = p->regval; -+ __vcpu_assign_sys_reg(vcpu, SPSR_EL1, p->regval); - else - p->regval = __vcpu_sys_reg(vcpu, SPSR_EL1); - -@@ -2440,7 +2440,7 @@ static bool access_cntkctl_el12(struct k - const struct sys_reg_desc *r) - { - if (p->is_write) -- __vcpu_sys_reg(vcpu, CNTKCTL_EL1) = p->regval; -+ __vcpu_assign_sys_reg(vcpu, CNTKCTL_EL1, p->regval); - else - p->regval = __vcpu_sys_reg(vcpu, CNTKCTL_EL1); - -@@ -2454,7 +2454,9 @@ static u64 reset_hcr(struct kvm_vcpu *vc - if (!cpus_have_final_cap(ARM64_HAS_HCR_NV1)) - val |= HCR_E2H; - -- return __vcpu_sys_reg(vcpu, r->reg) = val; -+ __vcpu_assign_sys_reg(vcpu, r->reg, val); -+ -+ return __vcpu_sys_reg(vcpu, r->reg); - } - - static unsigned int __el2_visibility(const struct kvm_vcpu *vcpu, -@@ -2622,10 +2624,10 @@ static bool access_mdcr(struct kvm_vcpu - */ - if (hpmn > vcpu->kvm->arch.nr_pmu_counters) { - hpmn = vcpu->kvm->arch.nr_pmu_counters; -- u64_replace_bits(val, hpmn, MDCR_EL2_HPMN); -+ u64p_replace_bits(&val, hpmn, MDCR_EL2_HPMN); - } - -- __vcpu_sys_reg(vcpu, MDCR_EL2) = val; -+ __vcpu_assign_sys_reg(vcpu, MDCR_EL2, val); - - /* - * Request a reload of the PMU to enable/disable the counters -@@ -2754,7 +2756,7 @@ static int set_imp_id_reg(struct kvm_vcp - - static u64 reset_mdcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) - { -- __vcpu_sys_reg(vcpu, r->reg) = vcpu->kvm->arch.nr_pmu_counters; -+ __vcpu_assign_sys_reg(vcpu, r->reg, vcpu->kvm->arch.nr_pmu_counters); - return vcpu->kvm->arch.nr_pmu_counters; - } - -@@ -4790,7 +4792,7 @@ void kvm_reset_sys_regs(struct kvm_vcpu - r->reset(vcpu, r); - - if (r->reg >= __SANITISED_REG_START__ && r->reg < NR_SYS_REGS) -- (void)__vcpu_sys_reg(vcpu, r->reg); -+ __vcpu_rmw_sys_reg(vcpu, r->reg, |=, 0); - } - - set_bit(KVM_ARCH_FLAG_ID_REGS_INITIALIZED, &kvm->arch.flags); -@@ -5012,7 +5014,7 @@ int kvm_sys_reg_set_user(struct kvm_vcpu - if (r->set_user) { - ret = (r->set_user)(vcpu, r, val); - } else { -- __vcpu_sys_reg(vcpu, r->reg) = val; -+ __vcpu_assign_sys_reg(vcpu, r->reg, val); - ret = 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kvm/sys_regs.h BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/sys_regs.h ---- BPI-Router-Linux-kernel/arch/arm64/kvm/sys_regs.h 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/sys_regs.h 2025-10-22 13:53:56.295170202 -0400 -@@ -137,7 +137,7 @@ static inline u64 reset_unknown(struct k - { - BUG_ON(!r->reg); - BUG_ON(r->reg >= NR_SYS_REGS); -- __vcpu_sys_reg(vcpu, r->reg) = 0x1de7ec7edbadc0deULL; -+ __vcpu_assign_sys_reg(vcpu, r->reg, 0x1de7ec7edbadc0deULL); - return __vcpu_sys_reg(vcpu, r->reg); - } - -@@ -145,7 +145,7 @@ static inline u64 reset_val(struct kvm_v - { - BUG_ON(!r->reg); - BUG_ON(r->reg >= NR_SYS_REGS); -- __vcpu_sys_reg(vcpu, r->reg) = r->val; -+ __vcpu_assign_sys_reg(vcpu, r->reg, r->val); - return __vcpu_sys_reg(vcpu, r->reg); - } - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/kvm/vgic/vgic-v3-nested.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/vgic/vgic-v3-nested.c ---- BPI-Router-Linux-kernel/arch/arm64/kvm/vgic/vgic-v3-nested.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/kvm/vgic/vgic-v3-nested.c 2025-10-22 13:53:56.295170202 -0400 -@@ -36,6 +36,11 @@ struct shadow_if { - - static DEFINE_PER_CPU(struct shadow_if, shadow_if); - -+static int lr_map_idx_to_shadow_idx(struct shadow_if *shadow_if, int idx) -+{ -+ return hweight16(shadow_if->lr_map & (BIT(idx) - 1)); -+} -+ - /* - * Nesting GICv3 support - * -@@ -209,6 +214,29 @@ u64 vgic_v3_get_misr(struct kvm_vcpu *vc - return reg; - } - -+static u64 translate_lr_pintid(struct kvm_vcpu *vcpu, u64 lr) -+{ -+ struct vgic_irq *irq; -+ -+ if (!(lr & ICH_LR_HW)) -+ return lr; -+ -+ /* We have the HW bit set, check for validity of pINTID */ -+ irq = vgic_get_vcpu_irq(vcpu, FIELD_GET(ICH_LR_PHYS_ID_MASK, lr)); -+ /* If there was no real mapping, nuke the HW bit */ -+ if (!irq || !irq->hw || irq->intid > VGIC_MAX_SPI) -+ lr &= ~ICH_LR_HW; -+ -+ /* Translate the virtual mapping to the real one, even if invalid */ -+ if (irq) { -+ lr &= ~ICH_LR_PHYS_ID_MASK; -+ lr |= FIELD_PREP(ICH_LR_PHYS_ID_MASK, (u64)irq->hwintid); -+ vgic_put_irq(vcpu->kvm, irq); -+ } -+ -+ return lr; -+} -+ - /* - * For LRs which have HW bit set such as timer interrupts, we modify them to - * have the host hardware interrupt number instead of the virtual one programmed -@@ -217,58 +245,37 @@ u64 vgic_v3_get_misr(struct kvm_vcpu *vc - static void vgic_v3_create_shadow_lr(struct kvm_vcpu *vcpu, - struct vgic_v3_cpu_if *s_cpu_if) - { -- unsigned long lr_map = 0; -- int index = 0; -+ struct shadow_if *shadow_if; -+ -+ shadow_if = container_of(s_cpu_if, struct shadow_if, cpuif); -+ shadow_if->lr_map = 0; - - for (int i = 0; i < kvm_vgic_global_state.nr_lr; i++) { - u64 lr = __vcpu_sys_reg(vcpu, ICH_LRN(i)); -- struct vgic_irq *irq; - - if (!(lr & ICH_LR_STATE)) -- lr = 0; -+ continue; - -- if (!(lr & ICH_LR_HW)) -- goto next; -+ lr = translate_lr_pintid(vcpu, lr); - -- /* We have the HW bit set, check for validity of pINTID */ -- irq = vgic_get_vcpu_irq(vcpu, FIELD_GET(ICH_LR_PHYS_ID_MASK, lr)); -- if (!irq || !irq->hw || irq->intid > VGIC_MAX_SPI ) { -- /* There was no real mapping, so nuke the HW bit */ -- lr &= ~ICH_LR_HW; -- if (irq) -- vgic_put_irq(vcpu->kvm, irq); -- goto next; -- } -- -- /* Translate the virtual mapping to the real one */ -- lr &= ~ICH_LR_PHYS_ID_MASK; -- lr |= FIELD_PREP(ICH_LR_PHYS_ID_MASK, (u64)irq->hwintid); -- -- vgic_put_irq(vcpu->kvm, irq); -- --next: -- s_cpu_if->vgic_lr[index] = lr; -- if (lr) { -- lr_map |= BIT(i); -- index++; -- } -+ s_cpu_if->vgic_lr[hweight16(shadow_if->lr_map)] = lr; -+ shadow_if->lr_map |= BIT(i); - } - -- container_of(s_cpu_if, struct shadow_if, cpuif)->lr_map = lr_map; -- s_cpu_if->used_lrs = index; -+ s_cpu_if->used_lrs = hweight16(shadow_if->lr_map); - } - - void vgic_v3_sync_nested(struct kvm_vcpu *vcpu) - { - struct shadow_if *shadow_if = get_shadow_if(); -- int i, index = 0; -+ int i; - - for_each_set_bit(i, &shadow_if->lr_map, kvm_vgic_global_state.nr_lr) { - u64 lr = __vcpu_sys_reg(vcpu, ICH_LRN(i)); - struct vgic_irq *irq; - - if (!(lr & ICH_LR_HW) || !(lr & ICH_LR_STATE)) -- goto next; -+ continue; - - /* - * If we had a HW lr programmed by the guest hypervisor, we -@@ -277,15 +284,13 @@ void vgic_v3_sync_nested(struct kvm_vcpu - */ - irq = vgic_get_vcpu_irq(vcpu, FIELD_GET(ICH_LR_PHYS_ID_MASK, lr)); - if (WARN_ON(!irq)) /* Shouldn't happen as we check on load */ -- goto next; -+ continue; - -- lr = __gic_v3_get_lr(index); -+ lr = __gic_v3_get_lr(lr_map_idx_to_shadow_idx(shadow_if, i)); - if (!(lr & ICH_LR_STATE)) - irq->active = false; - - vgic_put_irq(vcpu->kvm, irq); -- next: -- index++; - } - } - -@@ -356,25 +361,23 @@ void vgic_v3_put_nested(struct kvm_vcpu - val = __vcpu_sys_reg(vcpu, ICH_HCR_EL2); - val &= ~ICH_HCR_EL2_EOIcount_MASK; - val |= (s_cpu_if->vgic_hcr & ICH_HCR_EL2_EOIcount_MASK); -- __vcpu_sys_reg(vcpu, ICH_HCR_EL2) = val; -- __vcpu_sys_reg(vcpu, ICH_VMCR_EL2) = s_cpu_if->vgic_vmcr; -+ __vcpu_assign_sys_reg(vcpu, ICH_HCR_EL2, val); -+ __vcpu_assign_sys_reg(vcpu, ICH_VMCR_EL2, s_cpu_if->vgic_vmcr); - - for (i = 0; i < 4; i++) { -- __vcpu_sys_reg(vcpu, ICH_AP0RN(i)) = s_cpu_if->vgic_ap0r[i]; -- __vcpu_sys_reg(vcpu, ICH_AP1RN(i)) = s_cpu_if->vgic_ap1r[i]; -+ __vcpu_assign_sys_reg(vcpu, ICH_AP0RN(i), s_cpu_if->vgic_ap0r[i]); -+ __vcpu_assign_sys_reg(vcpu, ICH_AP1RN(i), s_cpu_if->vgic_ap1r[i]); - } - - for_each_set_bit(i, &shadow_if->lr_map, kvm_vgic_global_state.nr_lr) { - val = __vcpu_sys_reg(vcpu, ICH_LRN(i)); - - val &= ~ICH_LR_STATE; -- val |= s_cpu_if->vgic_lr[i] & ICH_LR_STATE; -+ val |= s_cpu_if->vgic_lr[lr_map_idx_to_shadow_idx(shadow_if, i)] & ICH_LR_STATE; - -- __vcpu_sys_reg(vcpu, ICH_LRN(i)) = val; -- s_cpu_if->vgic_lr[i] = 0; -+ __vcpu_assign_sys_reg(vcpu, ICH_LRN(i), val); - } - -- shadow_if->lr_map = 0; - vcpu->arch.vgic_cpu.vgic_v3.used_lrs = 0; - } - -@@ -398,9 +401,7 @@ void vgic_v3_nested_update_mi(struct kvm - { - bool level; - -- level = __vcpu_sys_reg(vcpu, ICH_HCR_EL2) & ICH_HCR_EL2_En; -- if (level) -- level &= vgic_v3_get_misr(vcpu); -+ level = (__vcpu_sys_reg(vcpu, ICH_HCR_EL2) & ICH_HCR_EL2_En) && vgic_v3_get_misr(vcpu); - kvm_vgic_inject_irq(vcpu->kvm, vcpu, - vcpu->kvm->arch.vgic.mi_intid, level, vcpu); - } -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/lib/crypto/poly1305-glue.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/lib/crypto/poly1305-glue.c ---- BPI-Router-Linux-kernel/arch/arm64/lib/crypto/poly1305-glue.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/lib/crypto/poly1305-glue.c 2025-10-22 13:53:56.295170202 -0400 -@@ -7,6 +7,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -33,19 +34,19 @@ void poly1305_blocks_arch(struct poly130 - unsigned int len, u32 padbit) - { - len = round_down(len, POLY1305_BLOCK_SIZE); -- if (static_branch_likely(&have_neon)) { -+ if (static_branch_likely(&have_neon) && likely(may_use_simd())) { - do { - unsigned int todo = min_t(unsigned int, len, SZ_4K); - - kernel_neon_begin(); -- poly1305_blocks_neon(state, src, todo, 1); -+ poly1305_blocks_neon(state, src, todo, padbit); - kernel_neon_end(); - - len -= todo; - src += todo; - } while (len); - } else -- poly1305_blocks(state, src, len, 1); -+ poly1305_blocks(state, src, len, padbit); - } - EXPORT_SYMBOL_GPL(poly1305_blocks_arch); - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/mm/fault.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/mm/fault.c ---- BPI-Router-Linux-kernel/arch/arm64/mm/fault.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/mm/fault.c 2025-10-22 13:53:56.295170202 -0400 -@@ -487,17 +487,29 @@ static void do_bad_area(unsigned long fa - } - } - --static bool fault_from_pkey(unsigned long esr, struct vm_area_struct *vma, -- unsigned int mm_flags) -+static bool fault_from_pkey(struct vm_area_struct *vma, unsigned int mm_flags) - { -- unsigned long iss2 = ESR_ELx_ISS2(esr); -- - if (!system_supports_poe()) - return false; - -- if (esr_fsc_is_permission_fault(esr) && (iss2 & ESR_ELx_Overlay)) -- return true; -- -+ /* -+ * We do not check whether an Overlay fault has occurred because we -+ * cannot make a decision based solely on its value: -+ * -+ * - If Overlay is set, a fault did occur due to POE, but it may be -+ * spurious in those cases where we update POR_EL0 without ISB (e.g. -+ * on context-switch). We would then need to manually check POR_EL0 -+ * against vma_pkey(vma), which is exactly what -+ * arch_vma_access_permitted() does. -+ * -+ * - If Overlay is not set, we may still need to report a pkey fault. -+ * This is the case if an access was made within a mapping but with no -+ * page mapped, and POR_EL0 forbids the access (according to -+ * vma_pkey()). Such access will result in a SIGSEGV regardless -+ * because core code checks arch_vma_access_permitted(), but in order -+ * to report the correct error code - SEGV_PKUERR - we must handle -+ * that case here. -+ */ - return !arch_vma_access_permitted(vma, - mm_flags & FAULT_FLAG_WRITE, - mm_flags & FAULT_FLAG_INSTRUCTION, -@@ -635,7 +647,7 @@ static int __kprobes do_page_fault(unsig - goto bad_area; - } - -- if (fault_from_pkey(esr, vma, mm_flags)) { -+ if (fault_from_pkey(vma, mm_flags)) { - pkey = vma_pkey(vma); - vma_end_read(vma); - fault = 0; -@@ -679,7 +691,7 @@ retry: - goto bad_area; - } - -- if (fault_from_pkey(esr, vma, mm_flags)) { -+ if (fault_from_pkey(vma, mm_flags)) { - pkey = vma_pkey(vma); - mmap_read_unlock(mm); - fault = 0; -@@ -826,6 +838,7 @@ static int do_sea(unsigned long far, uns - */ - siaddr = untagged_addr(far); - } -+ add_taint(TAINT_MACHINE_CHECK, LOCKDEP_STILL_OK); - arm64_notify_die(inf->name, regs, inf->sig, inf->code, siaddr, esr); - - return 0; -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/mm/mmu.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/mm/mmu.c ---- BPI-Router-Linux-kernel/arch/arm64/mm/mmu.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/mm/mmu.c 2025-10-22 13:53:56.295170202 -0400 -@@ -46,13 +46,6 @@ - #define NO_CONT_MAPPINGS BIT(1) - #define NO_EXEC_MAPPINGS BIT(2) /* assumes FEAT_HPDS is not used */ - --enum pgtable_type { -- TABLE_PTE, -- TABLE_PMD, -- TABLE_PUD, -- TABLE_P4D, --}; -- - u64 kimage_voffset __ro_after_init; - EXPORT_SYMBOL(kimage_voffset); - -@@ -1305,7 +1298,8 @@ int pud_free_pmd_page(pud_t *pudp, unsig - next = addr; - end = addr + PUD_SIZE; - do { -- pmd_free_pte_page(pmdp, next); -+ if (pmd_present(pmdp_get(pmdp))) -+ pmd_free_pte_page(pmdp, next); - } while (pmdp++, next += PMD_SIZE, next != end); - - pud_clear(pudp); -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/mm/proc.S BPI-Router-Linux-kernel-6.16.12/arch/arm64/mm/proc.S ---- BPI-Router-Linux-kernel/arch/arm64/mm/proc.S 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/mm/proc.S 2025-10-22 13:53:56.295170202 -0400 -@@ -518,7 +518,6 @@ alternative_else_nop_endif - msr REG_PIR_EL1, x0 - - orr tcr2, tcr2, TCR2_EL1_PIE -- msr REG_TCR2_EL1, x0 - - .Lskip_indirection: - -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/mm/ptdump_debugfs.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/mm/ptdump_debugfs.c ---- BPI-Router-Linux-kernel/arch/arm64/mm/ptdump_debugfs.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/mm/ptdump_debugfs.c 2025-10-22 13:53:56.295170202 -0400 -@@ -1,6 +1,5 @@ - // SPDX-License-Identifier: GPL-2.0 - #include --#include - #include - - #include -@@ -9,9 +8,7 @@ static int ptdump_show(struct seq_file * - { - struct ptdump_info *info = m->private; - -- get_online_mems(); - ptdump_walk(m, info); -- put_online_mems(); - return 0; - } - DEFINE_SHOW_ATTRIBUTE(ptdump); -diff -purNx .git BPI-Router-Linux-kernel/arch/arm64/net/bpf_jit_comp.c BPI-Router-Linux-kernel-6.16.12/arch/arm64/net/bpf_jit_comp.c ---- BPI-Router-Linux-kernel/arch/arm64/net/bpf_jit_comp.c 2025-10-22 13:53:23.067329834 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/arm64/net/bpf_jit_comp.c 2025-10-22 13:53:56.295170202 -0400 -@@ -412,6 +412,7 @@ static void push_callee_regs(struct jit_ - emit(A64_PUSH(A64_R(23), A64_R(24), A64_SP), ctx); - emit(A64_PUSH(A64_R(25), A64_R(26), A64_SP), ctx); - emit(A64_PUSH(A64_R(27), A64_R(28), A64_SP), ctx); -+ ctx->fp_used = true; - } else { - find_used_callee_regs(ctx); - for (i = 0; i + 1 < ctx->nr_used_callee_reg; i += 2) { -diff -purNx .git BPI-Router-Linux-kernel/arch/csky/include/asm/pgtable.h BPI-Router-Linux-kernel-6.16.12/arch/csky/include/asm/pgtable.h ---- BPI-Router-Linux-kernel/arch/csky/include/asm/pgtable.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/csky/include/asm/pgtable.h 2025-10-22 13:53:56.295170202 -0400 -@@ -200,7 +200,7 @@ static inline pte_t pte_mkyoung(pte_t pt - return pte; - } - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/hexagon/include/asm/pgtable.h BPI-Router-Linux-kernel-6.16.12/arch/hexagon/include/asm/pgtable.h ---- BPI-Router-Linux-kernel/arch/hexagon/include/asm/pgtable.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/hexagon/include/asm/pgtable.h 2025-10-22 13:53:56.299170182 -0400 -@@ -387,7 +387,7 @@ static inline unsigned long pmd_page_vad - (((type & 0x1f) << 1) | \ - ((offset & 0x3ffff8) << 10) | ((offset & 0x7) << 7)) }) - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/acenv.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/acenv.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/acenv.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/acenv.h 2025-10-22 13:53:56.299170182 -0400 -@@ -10,9 +10,8 @@ - #ifndef _ASM_LOONGARCH_ACENV_H - #define _ASM_LOONGARCH_ACENV_H - --/* -- * This header is required by ACPI core, but we have nothing to fill in -- * right now. Will be updated later when needed. -- */ -+#ifdef CONFIG_ARCH_STRICT_ALIGN -+#define ACPI_MISALIGNMENT_NOT_SUPPORTED -+#endif /* CONFIG_ARCH_STRICT_ALIGN */ - - #endif /* _ASM_LOONGARCH_ACENV_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/addrspace.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/addrspace.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/addrspace.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/addrspace.h 2025-10-22 13:53:56.299170182 -0400 -@@ -18,12 +18,12 @@ - /* - * This gives the physical RAM offset. - */ --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - #ifndef PHYS_OFFSET - #define PHYS_OFFSET _UL(0) - #endif - extern unsigned long vm_map_base; --#endif /* __ASSEMBLY__ */ -+#endif /* __ASSEMBLER__ */ - - #ifndef IO_BASE - #define IO_BASE CSR_DMW0_BASE -@@ -66,7 +66,7 @@ extern unsigned long vm_map_base; - #define FIXADDR_TOP ((unsigned long)(long)(int)0xfffe0000) - #endif - --#ifdef __ASSEMBLY__ -+#ifdef __ASSEMBLER__ - #define _ATYPE_ - #define _ATYPE32_ - #define _ATYPE64_ -@@ -85,7 +85,7 @@ extern unsigned long vm_map_base; - /* - * 32/64-bit LoongArch address spaces - */ --#ifdef __ASSEMBLY__ -+#ifdef __ASSEMBLER__ - #define _ACAST32_ - #define _ACAST64_ - #else -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/alternative-asm.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/alternative-asm.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/alternative-asm.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/alternative-asm.h 2025-10-22 13:53:56.299170182 -0400 -@@ -2,7 +2,7 @@ - #ifndef _ASM_ALTERNATIVE_ASM_H - #define _ASM_ALTERNATIVE_ASM_H - --#ifdef __ASSEMBLY__ -+#ifdef __ASSEMBLER__ - - #include - -@@ -77,6 +77,6 @@ - .previous - .endm - --#endif /* __ASSEMBLY__ */ -+#endif /* __ASSEMBLER__ */ - - #endif /* _ASM_ALTERNATIVE_ASM_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/alternative.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/alternative.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/alternative.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/alternative.h 2025-10-22 13:53:56.299170182 -0400 -@@ -2,7 +2,7 @@ - #ifndef _ASM_ALTERNATIVE_H - #define _ASM_ALTERNATIVE_H - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #include - #include -@@ -106,6 +106,6 @@ extern void apply_alternatives(struct al - #define alternative_2(oldinstr, newinstr1, feature1, newinstr2, feature2) \ - (asm volatile(ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2) ::: "memory")) - --#endif /* __ASSEMBLY__ */ -+#endif /* __ASSEMBLER__ */ - - #endif /* _ASM_ALTERNATIVE_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/asm-extable.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/asm-extable.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/asm-extable.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/asm-extable.h 2025-10-22 13:53:56.299170182 -0400 -@@ -7,7 +7,7 @@ - #define EX_TYPE_UACCESS_ERR_ZERO 2 - #define EX_TYPE_BPF 3 - --#ifdef __ASSEMBLY__ -+#ifdef __ASSEMBLER__ - - #define __ASM_EXTABLE_RAW(insn, fixup, type, data) \ - .pushsection __ex_table, "a"; \ -@@ -22,7 +22,7 @@ - __ASM_EXTABLE_RAW(\insn, \fixup, EX_TYPE_FIXUP, 0) - .endm - --#else /* __ASSEMBLY__ */ -+#else /* __ASSEMBLER__ */ - - #include - #include -@@ -60,6 +60,6 @@ - #define _ASM_EXTABLE_UACCESS_ERR(insn, fixup, err) \ - _ASM_EXTABLE_UACCESS_ERR_ZERO(insn, fixup, err, zero) - --#endif /* __ASSEMBLY__ */ -+#endif /* __ASSEMBLER__ */ - - #endif /* __ASM_ASM_EXTABLE_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/asm.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/asm.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/asm.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/asm.h 2025-10-22 13:53:56.299170182 -0400 -@@ -110,7 +110,7 @@ - #define LONG_SRA srai.w - #define LONG_SRAV sra.w - --#ifdef __ASSEMBLY__ -+#ifdef __ASSEMBLER__ - #define LONG .word - #endif - #define LONGSIZE 4 -@@ -131,7 +131,7 @@ - #define LONG_SRA srai.d - #define LONG_SRAV sra.d - --#ifdef __ASSEMBLY__ -+#ifdef __ASSEMBLER__ - #define LONG .dword - #endif - #define LONGSIZE 8 -@@ -158,7 +158,7 @@ - - #define PTR_SCALESHIFT 2 - --#ifdef __ASSEMBLY__ -+#ifdef __ASSEMBLER__ - #define PTR .word - #endif - #define PTRSIZE 4 -@@ -181,7 +181,7 @@ - - #define PTR_SCALESHIFT 3 - --#ifdef __ASSEMBLY__ -+#ifdef __ASSEMBLER__ - #define PTR .dword - #endif - #define PTRSIZE 8 -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/cpu.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/cpu.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/cpu.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/cpu.h 2025-10-22 13:53:56.299170182 -0400 -@@ -46,7 +46,7 @@ - - #define PRID_PRODUCT_MASK 0x0fff - --#if !defined(__ASSEMBLY__) -+#if !defined(__ASSEMBLER__) - - enum cpu_type_enum { - CPU_UNKNOWN, -@@ -55,7 +55,7 @@ enum cpu_type_enum { - CPU_LAST - }; - --#endif /* !__ASSEMBLY */ -+#endif /* !__ASSEMBLER__ */ - - /* - * ISA Level encodings -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/ftrace.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/ftrace.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/ftrace.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/ftrace.h 2025-10-22 13:53:56.299170182 -0400 -@@ -14,7 +14,7 @@ - - #define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */ - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #ifndef CONFIG_DYNAMIC_FTRACE - -@@ -84,7 +84,7 @@ __arch_ftrace_set_direct_caller(struct p - - #endif - --#endif /* __ASSEMBLY__ */ -+#endif /* __ASSEMBLER__ */ - - #endif /* CONFIG_FUNCTION_TRACER */ - -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/gpr-num.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/gpr-num.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/gpr-num.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/gpr-num.h 2025-10-22 13:53:56.299170182 -0400 -@@ -2,7 +2,7 @@ - #ifndef __ASM_GPR_NUM_H - #define __ASM_GPR_NUM_H - --#ifdef __ASSEMBLY__ -+#ifdef __ASSEMBLER__ - - .equ .L__gpr_num_zero, 0 - .irp num,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 -@@ -25,7 +25,7 @@ - .equ .L__gpr_num_$s\num, 23 + \num - .endr - --#else /* __ASSEMBLY__ */ -+#else /* __ASSEMBLER__ */ - - #define __DEFINE_ASM_GPR_NUMS \ - " .equ .L__gpr_num_zero, 0\n" \ -@@ -47,6 +47,6 @@ - " .equ .L__gpr_num_$s\\num, 23 + \\num\n" \ - " .endr\n" \ - --#endif /* __ASSEMBLY__ */ -+#endif /* __ASSEMBLER__ */ - - #endif /* __ASM_GPR_NUM_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/irqflags.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/irqflags.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/irqflags.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/irqflags.h 2025-10-22 13:53:56.299170182 -0400 -@@ -5,7 +5,7 @@ - #ifndef _ASM_IRQFLAGS_H - #define _ASM_IRQFLAGS_H - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #include - #include -@@ -80,6 +80,6 @@ static inline int arch_irqs_disabled(voi - return arch_irqs_disabled_flags(arch_local_save_flags()); - } - --#endif /* #ifndef __ASSEMBLY__ */ -+#endif /* #ifndef __ASSEMBLER__ */ - - #endif /* _ASM_IRQFLAGS_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/jump_label.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/jump_label.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/jump_label.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/jump_label.h 2025-10-22 13:53:56.299170182 -0400 -@@ -7,7 +7,7 @@ - #ifndef __ASM_JUMP_LABEL_H - #define __ASM_JUMP_LABEL_H - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #include - -@@ -50,5 +50,5 @@ l_yes: - return true; - } - --#endif /* __ASSEMBLY__ */ -+#endif /* __ASSEMBLER__ */ - #endif /* __ASM_JUMP_LABEL_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/kasan.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/kasan.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/kasan.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/kasan.h 2025-10-22 13:53:56.299170182 -0400 -@@ -2,7 +2,7 @@ - #ifndef __ASM_KASAN_H - #define __ASM_KASAN_H - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #include - #include -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/kvm_mmu.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/kvm_mmu.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/kvm_mmu.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/kvm_mmu.h 2025-10-22 13:53:56.299170182 -0400 -@@ -16,6 +16,13 @@ - */ - #define KVM_MMU_CACHE_MIN_PAGES (CONFIG_PGTABLE_LEVELS - 1) - -+/* -+ * _PAGE_MODIFIED is a SW pte bit, it records page ever written on host -+ * kernel, on secondary MMU it records the page writeable attribute, in -+ * order for fast path handling. -+ */ -+#define KVM_PAGE_WRITEABLE _PAGE_MODIFIED -+ - #define _KVM_FLUSH_PGTABLE 0x1 - #define _KVM_HAS_PGMASK 0x2 - #define kvm_pfn_pte(pfn, prot) (((pfn) << PFN_PTE_SHIFT) | pgprot_val(prot)) -@@ -52,10 +59,10 @@ static inline void kvm_set_pte(kvm_pte_t - WRITE_ONCE(*ptep, val); - } - --static inline int kvm_pte_write(kvm_pte_t pte) { return pte & _PAGE_WRITE; } --static inline int kvm_pte_dirty(kvm_pte_t pte) { return pte & _PAGE_DIRTY; } - static inline int kvm_pte_young(kvm_pte_t pte) { return pte & _PAGE_ACCESSED; } - static inline int kvm_pte_huge(kvm_pte_t pte) { return pte & _PAGE_HUGE; } -+static inline int kvm_pte_dirty(kvm_pte_t pte) { return pte & __WRITEABLE; } -+static inline int kvm_pte_writeable(kvm_pte_t pte) { return pte & KVM_PAGE_WRITEABLE; } - - static inline kvm_pte_t kvm_pte_mkyoung(kvm_pte_t pte) - { -@@ -69,12 +76,12 @@ static inline kvm_pte_t kvm_pte_mkold(kv - - static inline kvm_pte_t kvm_pte_mkdirty(kvm_pte_t pte) - { -- return pte | _PAGE_DIRTY; -+ return pte | __WRITEABLE; - } - - static inline kvm_pte_t kvm_pte_mkclean(kvm_pte_t pte) - { -- return pte & ~_PAGE_DIRTY; -+ return pte & ~__WRITEABLE; - } - - static inline kvm_pte_t kvm_pte_mkhuge(kvm_pte_t pte) -@@ -87,6 +94,11 @@ static inline kvm_pte_t kvm_pte_mksmall( - return pte & ~_PAGE_HUGE; - } - -+static inline kvm_pte_t kvm_pte_mkwriteable(kvm_pte_t pte) -+{ -+ return pte | KVM_PAGE_WRITEABLE; -+} -+ - static inline int kvm_need_flush(kvm_ptw_ctx *ctx) - { - return ctx->flag & _KVM_FLUSH_PGTABLE; -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/loongarch.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/loongarch.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/loongarch.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/loongarch.h 2025-10-22 13:53:56.299170182 -0400 -@@ -9,15 +9,15 @@ - #include - #include - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - #include - - /* CPUCFG */ - #define read_cpucfg(reg) __cpucfg(reg) - --#endif /* !__ASSEMBLY__ */ -+#endif /* !__ASSEMBLER__ */ - --#ifdef __ASSEMBLY__ -+#ifdef __ASSEMBLER__ - - /* LoongArch Registers */ - #define REG_ZERO 0x0 -@@ -53,7 +53,7 @@ - #define REG_S7 0x1e - #define REG_S8 0x1f - --#endif /* __ASSEMBLY__ */ -+#endif /* __ASSEMBLER__ */ - - /* Bit fields for CPUCFG registers */ - #define LOONGARCH_CPUCFG0 0x0 -@@ -171,7 +171,7 @@ - * SW emulation for KVM hypervirsor, see arch/loongarch/include/uapi/asm/kvm_para.h - */ - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - /* CSR */ - #define csr_read32(reg) __csrrd_w(reg) -@@ -187,7 +187,7 @@ - #define iocsr_write32(val, reg) __iocsrwr_w(val, reg) - #define iocsr_write64(val, reg) __iocsrwr_d(val, reg) - --#endif /* !__ASSEMBLY__ */ -+#endif /* !__ASSEMBLER__ */ - - /* CSR register number */ - -@@ -1195,7 +1195,7 @@ - #define LOONGARCH_IOCSR_EXTIOI_ROUTE_BASE 0x1c00 - #define IOCSR_EXTIOI_VECTOR_NUM 256 - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - static __always_inline u64 drdtime(void) - { -@@ -1357,7 +1357,7 @@ __BUILD_CSR_OP(tlbidx) - #define clear_csr_estat(val) \ - csr_xchg32(~(val), val, LOONGARCH_CSR_ESTAT) - --#endif /* __ASSEMBLY__ */ -+#endif /* __ASSEMBLER__ */ - - /* Generic EntryLo bit definitions */ - #define ENTRYLO_V (_ULCAST_(1) << 0) -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/orc_types.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/orc_types.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/orc_types.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/orc_types.h 2025-10-22 13:53:56.299170182 -0400 -@@ -34,7 +34,7 @@ - #define ORC_TYPE_REGS 3 - #define ORC_TYPE_REGS_PARTIAL 4 - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - /* - * This struct is more or less a vastly simplified version of the DWARF Call - * Frame Information standard. It contains only the necessary parts of DWARF -@@ -53,6 +53,6 @@ struct orc_entry { - unsigned int type:3; - unsigned int signal:1; - }; --#endif /* __ASSEMBLY__ */ -+#endif /* __ASSEMBLER__ */ - - #endif /* _ORC_TYPES_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/page.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/page.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/page.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/page.h 2025-10-22 13:53:56.299170182 -0400 -@@ -15,7 +15,7 @@ - #define HPAGE_MASK (~(HPAGE_SIZE - 1)) - #define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #include - #include -@@ -110,6 +110,6 @@ extern int __virt_addr_valid(volatile vo - #include - #include - --#endif /* !__ASSEMBLY__ */ -+#endif /* !__ASSEMBLER__ */ - - #endif /* _ASM_PAGE_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/pgtable-bits.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/pgtable-bits.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/pgtable-bits.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/pgtable-bits.h 2025-10-22 13:53:56.299170182 -0400 -@@ -92,7 +92,7 @@ - #define PAGE_KERNEL_WUC __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \ - _PAGE_GLOBAL | _PAGE_KERN | _CACHE_WUC) - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #define _PAGE_IOREMAP pgprot_val(PAGE_KERNEL_SUC) - -@@ -127,6 +127,6 @@ static inline pgprot_t pgprot_writecombi - return __pgprot(prot); - } - --#endif /* !__ASSEMBLY__ */ -+#endif /* !__ASSEMBLER__ */ - - #endif /* _ASM_PGTABLE_BITS_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/pgtable.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/pgtable.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/pgtable.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/pgtable.h 2025-10-22 13:53:56.299170182 -0400 -@@ -55,7 +55,7 @@ - - #define USER_PTRS_PER_PGD ((TASK_SIZE64 / PGDIR_SIZE)?(TASK_SIZE64 / PGDIR_SIZE):1) - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #include - #include -@@ -301,7 +301,7 @@ static inline pte_t mk_swap_pte(unsigned - #define __pmd_to_swp_entry(pmd) ((swp_entry_t) { pmd_val(pmd) }) - #define __swp_entry_to_pmd(x) ((pmd_t) { (x).val | _PAGE_HUGE }) - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; - } -@@ -618,6 +618,6 @@ static inline long pmd_protnone(pmd_t pm - #define HAVE_ARCH_UNMAPPED_AREA - #define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN - --#endif /* !__ASSEMBLY__ */ -+#endif /* !__ASSEMBLER__ */ - - #endif /* _ASM_PGTABLE_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/prefetch.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/prefetch.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/prefetch.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/prefetch.h 2025-10-22 13:53:56.299170182 -0400 -@@ -8,7 +8,7 @@ - #define Pref_Load 0 - #define Pref_Store 8 - --#ifdef __ASSEMBLY__ -+#ifdef __ASSEMBLER__ - - .macro __pref hint addr - #ifdef CONFIG_CPU_HAS_PREFETCH -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/smp.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/smp.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/smp.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/smp.h 2025-10-22 13:53:56.299170182 -0400 -@@ -39,7 +39,7 @@ int loongson_cpu_disable(void); - void loongson_cpu_die(unsigned int cpu); - #endif - --static inline void plat_smp_setup(void) -+static inline void __init plat_smp_setup(void) - { - loongson_smp_setup(); - } -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/thread_info.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/thread_info.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/thread_info.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/thread_info.h 2025-10-22 13:53:56.299170182 -0400 -@@ -10,7 +10,7 @@ - - #ifdef __KERNEL__ - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #include - -@@ -53,7 +53,7 @@ static inline struct thread_info *curren - - register unsigned long current_stack_pointer __asm__("$sp"); - --#endif /* !__ASSEMBLY__ */ -+#endif /* !__ASSEMBLER__ */ - - /* thread information allocation */ - #define THREAD_SIZE SZ_16K -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/types.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/types.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/types.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/types.h 2025-10-22 13:53:56.299170182 -0400 -@@ -8,7 +8,7 @@ - #include - #include - --#ifdef __ASSEMBLY__ -+#ifdef __ASSEMBLER__ - #define _ULCAST_ - #define _U64CAST_ - #else -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/unwind_hints.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/unwind_hints.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/unwind_hints.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/unwind_hints.h 2025-10-22 13:53:56.299170182 -0400 -@@ -5,7 +5,7 @@ - #include - #include - --#ifdef __ASSEMBLY__ -+#ifdef __ASSEMBLER__ - - .macro UNWIND_HINT_UNDEFINED - UNWIND_HINT type=UNWIND_HINT_TYPE_UNDEFINED -@@ -23,7 +23,7 @@ - UNWIND_HINT sp_reg=ORC_REG_SP type=UNWIND_HINT_TYPE_CALL - .endm - --#else /* !__ASSEMBLY__ */ -+#else /* !__ASSEMBLER__ */ - - #define UNWIND_HINT_SAVE \ - UNWIND_HINT(UNWIND_HINT_TYPE_SAVE, 0, 0, 0) -@@ -31,6 +31,6 @@ - #define UNWIND_HINT_RESTORE \ - UNWIND_HINT(UNWIND_HINT_TYPE_RESTORE, 0, 0, 0) - --#endif /* !__ASSEMBLY__ */ -+#endif /* !__ASSEMBLER__ */ - - #endif /* _ASM_LOONGARCH_UNWIND_HINTS_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/vdso/arch_data.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/vdso/arch_data.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/vdso/arch_data.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/vdso/arch_data.h 2025-10-22 13:53:56.299170182 -0400 -@@ -7,7 +7,7 @@ - #ifndef _VDSO_ARCH_DATA_H - #define _VDSO_ARCH_DATA_H - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #include - #include -@@ -20,6 +20,6 @@ struct vdso_arch_data { - struct vdso_pcpu_data pdata[NR_CPUS]; - }; - --#endif /* __ASSEMBLY__ */ -+#endif /* __ASSEMBLER__ */ - - #endif -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/vdso/getrandom.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/vdso/getrandom.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/vdso/getrandom.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/vdso/getrandom.h 2025-10-22 13:53:56.299170182 -0400 -@@ -5,7 +5,7 @@ - #ifndef __ASM_VDSO_GETRANDOM_H - #define __ASM_VDSO_GETRANDOM_H - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #include - #include -@@ -28,6 +28,6 @@ static __always_inline ssize_t getrandom - return ret; - } - --#endif /* !__ASSEMBLY__ */ -+#endif /* !__ASSEMBLER__ */ - - #endif /* __ASM_VDSO_GETRANDOM_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/vdso/gettimeofday.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/vdso/gettimeofday.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/vdso/gettimeofday.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/vdso/gettimeofday.h 2025-10-22 13:53:56.299170182 -0400 -@@ -7,7 +7,7 @@ - #ifndef __ASM_VDSO_GETTIMEOFDAY_H - #define __ASM_VDSO_GETTIMEOFDAY_H - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #include - #include -@@ -89,6 +89,6 @@ static inline bool loongarch_vdso_hres_c - } - #define __arch_vdso_hres_capable loongarch_vdso_hres_capable - --#endif /* !__ASSEMBLY__ */ -+#endif /* !__ASSEMBLER__ */ - - #endif /* __ASM_VDSO_GETTIMEOFDAY_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/vdso/processor.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/vdso/processor.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/vdso/processor.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/vdso/processor.h 2025-10-22 13:53:56.299170182 -0400 -@@ -5,10 +5,10 @@ - #ifndef __ASM_VDSO_PROCESSOR_H - #define __ASM_VDSO_PROCESSOR_H - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #define cpu_relax() barrier() - --#endif /* __ASSEMBLY__ */ -+#endif /* __ASSEMBLER__ */ - - #endif /* __ASM_VDSO_PROCESSOR_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/vdso/vdso.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/vdso/vdso.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/vdso/vdso.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/vdso/vdso.h 2025-10-22 13:53:56.299170182 -0400 -@@ -7,7 +7,7 @@ - #ifndef _ASM_VDSO_VDSO_H - #define _ASM_VDSO_VDSO_H - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #include - #include -@@ -16,6 +16,6 @@ - - #define VVAR_SIZE (VDSO_NR_PAGES << PAGE_SHIFT) - --#endif /* __ASSEMBLY__ */ -+#endif /* __ASSEMBLER__ */ - - #endif -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/include/asm/vdso/vsyscall.h BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/vdso/vsyscall.h ---- BPI-Router-Linux-kernel/arch/loongarch/include/asm/vdso/vsyscall.h 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/include/asm/vdso/vsyscall.h 2025-10-22 13:53:56.299170182 -0400 -@@ -2,13 +2,13 @@ - #ifndef __ASM_VDSO_VSYSCALL_H - #define __ASM_VDSO_VSYSCALL_H - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - - #include - - /* The asm-generic header needs to be included after the definitions above */ - #include - --#endif /* !__ASSEMBLY__ */ -+#endif /* !__ASSEMBLER__ */ - - #endif /* __ASM_VDSO_VSYSCALL_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/Kconfig BPI-Router-Linux-kernel-6.16.12/arch/loongarch/Kconfig ---- BPI-Router-Linux-kernel/arch/loongarch/Kconfig 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/Kconfig 2025-10-22 13:53:56.299170182 -0400 -@@ -301,6 +301,10 @@ config AS_HAS_LVZ_EXTENSION - config CC_HAS_ANNOTATE_TABLEJUMP - def_bool $(cc-option,-mannotate-tablejump) - -+config RUSTC_HAS_ANNOTATE_TABLEJUMP -+ depends on RUST -+ def_bool $(rustc-option,-Cllvm-args=--loongarch-annotate-tablejump) -+ - menu "Kernel type and options" - - source "kernel/Kconfig.hz" -@@ -566,10 +570,14 @@ config ARCH_STRICT_ALIGN - -mstrict-align build parameter to prevent unaligned accesses. - - CPUs with h/w unaligned access support: -- Loongson-2K2000/2K3000/3A5000/3C5000/3D5000. -+ Loongson-2K2000/2K3000 and all of Loongson-3 series processors -+ based on LoongArch. - - CPUs without h/w unaligned access support: -- Loongson-2K500/2K1000. -+ Loongson-2K0300/2K0500/2K1000. -+ -+ If you want to make sure whether to support unaligned memory access -+ on your hardware, please read the bit 20 (UAL) of CPUCFG1 register. - - This option is enabled by default to make the kernel be able to run - on all LoongArch systems. But you can disable it manually if you want -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/kernel/acpi.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/acpi.c ---- BPI-Router-Linux-kernel/arch/loongarch/kernel/acpi.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/acpi.c 2025-10-22 13:53:56.299170182 -0400 -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - #include - #include - #include -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/kernel/alternative.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/alternative.c ---- BPI-Router-Linux-kernel/arch/loongarch/kernel/alternative.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/alternative.c 2025-10-22 13:53:56.299170182 -0400 -@@ -1,4 +1,5 @@ - // SPDX-License-Identifier: GPL-2.0-only -+#include - #include - #include - #include -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/kernel/efi.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/efi.c ---- BPI-Router-Linux-kernel/arch/loongarch/kernel/efi.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/efi.c 2025-10-22 13:53:56.299170182 -0400 -@@ -144,6 +144,18 @@ void __init efi_init(void) - if (efi_memmap_init_early(&data) < 0) - panic("Unable to map EFI memory map.\n"); - -+ /* -+ * Reserve the physical memory region occupied by the EFI -+ * memory map table (header + descriptors). This is crucial -+ * for kdump, as the kdump kernel relies on this original -+ * memmap passed by the bootloader. Without reservation, -+ * this region could be overwritten by the primary kernel. -+ * Also, set the EFI_PRESERVE_BS_REGIONS flag to indicate that -+ * critical boot services code/data regions like this are preserved. -+ */ -+ memblock_reserve((phys_addr_t)boot_memmap, sizeof(*tbl) + data.size); -+ set_bit(EFI_PRESERVE_BS_REGIONS, &efi.flags); -+ - early_memunmap(tbl, sizeof(*tbl)); - } - -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/kernel/elf.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/elf.c ---- BPI-Router-Linux-kernel/arch/loongarch/kernel/elf.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/elf.c 2025-10-22 13:53:56.299170182 -0400 -@@ -6,7 +6,6 @@ - - #include - #include --#include - #include - - #include -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/kernel/env.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/env.c ---- BPI-Router-Linux-kernel/arch/loongarch/kernel/env.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/env.c 2025-10-22 13:53:56.299170182 -0400 -@@ -39,16 +39,19 @@ void __init init_environ(void) - - static int __init init_cpu_fullname(void) - { -- struct device_node *root; - int cpu, ret; -- char *model; -+ char *cpuname; -+ const char *model; -+ struct device_node *root; - - /* Parsing cpuname from DTS model property */ - root = of_find_node_by_path("/"); -- ret = of_property_read_string(root, "model", (const char **)&model); -+ ret = of_property_read_string(root, "model", &model); -+ if (ret == 0) { -+ cpuname = kstrdup(model, GFP_KERNEL); -+ loongson_sysconf.cpuname = strsep(&cpuname, " "); -+ } - of_node_put(root); -- if (ret == 0) -- loongson_sysconf.cpuname = strsep(&model, " "); - - if (loongson_sysconf.cpuname && !strncmp(loongson_sysconf.cpuname, "Loongson", 8)) { - for (cpu = 0; cpu < NR_CPUS; cpu++) -@@ -106,6 +109,8 @@ static int __init boardinfo_init(void) - struct kobject *loongson_kobj; - - loongson_kobj = kobject_create_and_add("loongson", firmware_kobj); -+ if (!loongson_kobj) -+ return -ENOMEM; - - return sysfs_create_file(loongson_kobj, &boardinfo_attr.attr); - } -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/kernel/kfpu.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/kfpu.c ---- BPI-Router-Linux-kernel/arch/loongarch/kernel/kfpu.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/kfpu.c 2025-10-22 13:53:56.299170182 -0400 -@@ -4,6 +4,7 @@ - */ - - #include -+#include - #include - #include - #include -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/kernel/module-sections.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/module-sections.c ---- BPI-Router-Linux-kernel/arch/loongarch/kernel/module-sections.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/module-sections.c 2025-10-22 13:53:56.299170182 -0400 -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include - - Elf_Addr module_emit_got_entry(struct module *mod, Elf_Shdr *sechdrs, Elf_Addr val) - { -@@ -61,39 +62,38 @@ Elf_Addr module_emit_plt_entry(struct mo - return (Elf_Addr)&plt[nr]; - } - --static int is_rela_equal(const Elf_Rela *x, const Elf_Rela *y) --{ -- return x->r_info == y->r_info && x->r_addend == y->r_addend; --} -+#define cmp_3way(a, b) ((a) < (b) ? -1 : (a) > (b)) - --static bool duplicate_rela(const Elf_Rela *rela, int idx) -+static int compare_rela(const void *x, const void *y) - { -- int i; -+ int ret; -+ const Elf_Rela *rela_x = x, *rela_y = y; - -- for (i = 0; i < idx; i++) { -- if (is_rela_equal(&rela[i], &rela[idx])) -- return true; -- } -+ ret = cmp_3way(rela_x->r_info, rela_y->r_info); -+ if (ret == 0) -+ ret = cmp_3way(rela_x->r_addend, rela_y->r_addend); - -- return false; -+ return ret; - } - - static void count_max_entries(Elf_Rela *relas, int num, - unsigned int *plts, unsigned int *gots) - { -- unsigned int i, type; -+ unsigned int i; -+ -+ sort(relas, num, sizeof(Elf_Rela), compare_rela, NULL); - - for (i = 0; i < num; i++) { -- type = ELF_R_TYPE(relas[i].r_info); -- switch (type) { -+ if (i && !compare_rela(&relas[i-1], &relas[i])) -+ continue; -+ -+ switch (ELF_R_TYPE(relas[i].r_info)) { - case R_LARCH_SOP_PUSH_PLT_PCREL: - case R_LARCH_B26: -- if (!duplicate_rela(relas, i)) -- (*plts)++; -+ (*plts)++; - break; - case R_LARCH_GOT_PC_HI20: -- if (!duplicate_rela(relas, i)) -- (*gots)++; -+ (*gots)++; - break; - default: - break; /* Do nothing. */ -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/kernel/paravirt.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/paravirt.c ---- BPI-Router-Linux-kernel/arch/loongarch/kernel/paravirt.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/paravirt.c 2025-10-22 13:53:56.299170182 -0400 -@@ -1,5 +1,4 @@ - // SPDX-License-Identifier: GPL-2.0 --#include - #include - #include - #include -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/kernel/relocate_kernel.S BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/relocate_kernel.S ---- BPI-Router-Linux-kernel/arch/loongarch/kernel/relocate_kernel.S 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/relocate_kernel.S 2025-10-22 13:53:56.299170182 -0400 -@@ -109,4 +109,4 @@ SYM_CODE_END(kexec_smp_wait) - relocate_new_kernel_end: - - .section ".data" --SYM_DATA(relocate_new_kernel_size, .long relocate_new_kernel_end - relocate_new_kernel) -+SYM_DATA(relocate_new_kernel_size, .quad relocate_new_kernel_end - relocate_new_kernel) -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/kernel/signal.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/signal.c ---- BPI-Router-Linux-kernel/arch/loongarch/kernel/signal.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/signal.c 2025-10-22 13:53:56.299170182 -0400 -@@ -677,6 +677,11 @@ static int setup_sigcontext(struct pt_re - for (i = 1; i < 32; i++) - err |= __put_user(regs->regs[i], &sc->sc_regs[i]); - -+#ifdef CONFIG_CPU_HAS_LBT -+ if (extctx->lbt.addr) -+ err |= protected_save_lbt_context(extctx); -+#endif -+ - if (extctx->lasx.addr) - err |= protected_save_lasx_context(extctx); - else if (extctx->lsx.addr) -@@ -684,11 +689,6 @@ static int setup_sigcontext(struct pt_re - else if (extctx->fpu.addr) - err |= protected_save_fpu_context(extctx); - --#ifdef CONFIG_CPU_HAS_LBT -- if (extctx->lbt.addr) -- err |= protected_save_lbt_context(extctx); --#endif -- - /* Set the "end" magic */ - info = (struct sctx_info *)extctx->end.addr; - err |= __put_user(0, &info->magic); -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/kernel/stacktrace.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/stacktrace.c ---- BPI-Router-Linux-kernel/arch/loongarch/kernel/stacktrace.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/stacktrace.c 2025-10-22 13:53:56.299170182 -0400 -@@ -51,12 +51,13 @@ int arch_stack_walk_reliable(stack_trace - if (task == current) { - regs->regs[3] = (unsigned long)__builtin_frame_address(0); - regs->csr_era = (unsigned long)__builtin_return_address(0); -+ regs->regs[22] = 0; - } else { - regs->regs[3] = thread_saved_fp(task); - regs->csr_era = thread_saved_ra(task); -+ regs->regs[22] = task->thread.reg22; - } - regs->regs[1] = 0; -- regs->regs[22] = 0; - - for (unwind_start(&state, task, regs); - !unwind_done(&state) && !unwind_error(&state); unwind_next_frame(&state)) { -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/kernel/time.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/time.c ---- BPI-Router-Linux-kernel/arch/loongarch/kernel/time.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/time.c 2025-10-22 13:53:56.299170182 -0400 -@@ -5,6 +5,7 @@ - * Copyright (C) 2020-2022 Loongson Technology Corporation Limited - */ - #include -+#include - #include - #include - #include -@@ -102,7 +103,24 @@ static int constant_timer_next_event(uns - return 0; - } - --static unsigned long __init get_loops_per_jiffy(void) -+static int arch_timer_starting(unsigned int cpu) -+{ -+ set_csr_ecfg(ECFGF_TIMER); -+ -+ return 0; -+} -+ -+static int arch_timer_dying(unsigned int cpu) -+{ -+ constant_set_state_shutdown(this_cpu_ptr(&constant_clockevent_device)); -+ -+ /* Clear Timer Interrupt */ -+ write_csr_tintclear(CSR_TINTCLR_TI); -+ -+ return 0; -+} -+ -+static unsigned long get_loops_per_jiffy(void) - { - unsigned long lpj = (unsigned long)const_clock_freq; - -@@ -172,6 +190,10 @@ int constant_clockevent_init(void) - lpj_fine = get_loops_per_jiffy(); - pr_info("Constant clock event device register\n"); - -+ cpuhp_setup_state(CPUHP_AP_LOONGARCH_ARCH_TIMER_STARTING, -+ "clockevents/loongarch/timer:starting", -+ arch_timer_starting, arch_timer_dying); -+ - return 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/kernel/traps.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/traps.c ---- BPI-Router-Linux-kernel/arch/loongarch/kernel/traps.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/traps.c 2025-10-22 13:53:56.299170182 -0400 -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include - #include - #include -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/kernel/unwind_guess.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/unwind_guess.c ---- BPI-Router-Linux-kernel/arch/loongarch/kernel/unwind_guess.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/unwind_guess.c 2025-10-22 13:53:56.299170182 -0400 -@@ -3,6 +3,7 @@ - * Copyright (C) 2022 Loongson Technology Corporation Limited - */ - #include -+#include - - unsigned long unwind_get_return_address(struct unwind_state *state) - { -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/kernel/unwind_orc.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/unwind_orc.c ---- BPI-Router-Linux-kernel/arch/loongarch/kernel/unwind_orc.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/unwind_orc.c 2025-10-22 13:53:56.299170182 -0400 -@@ -1,6 +1,7 @@ - // SPDX-License-Identifier: GPL-2.0-only --#include -+#include - #include -+#include - #include - #include - #include -@@ -507,7 +508,7 @@ bool unwind_next_frame(struct unwind_sta - - state->pc = bt_address(pc); - if (!state->pc) { -- pr_err("cannot find unwind pc at %pK\n", (void *)pc); -+ pr_err("cannot find unwind pc at %p\n", (void *)pc); - goto err; - } - -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/kernel/unwind_prologue.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/unwind_prologue.c ---- BPI-Router-Linux-kernel/arch/loongarch/kernel/unwind_prologue.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/unwind_prologue.c 2025-10-22 13:53:56.299170182 -0400 -@@ -3,6 +3,7 @@ - * Copyright (C) 2022 Loongson Technology Corporation Limited - */ - #include -+#include - #include - #include - -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/kernel/vdso.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/vdso.c ---- BPI-Router-Linux-kernel/arch/loongarch/kernel/vdso.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kernel/vdso.c 2025-10-22 13:53:56.299170182 -0400 -@@ -54,6 +54,9 @@ static int __init init_vdso(void) - vdso_info.code_mapping.pages = - kcalloc(vdso_info.size / PAGE_SIZE, sizeof(struct page *), GFP_KERNEL); - -+ if (!vdso_info.code_mapping.pages) -+ return -ENOMEM; -+ - pfn = __phys_to_pfn(__pa_symbol(vdso_info.vdso)); - for (i = 0; i < vdso_info.size / PAGE_SIZE; i++) - vdso_info.code_mapping.pages[i] = pfn_to_page(pfn + i); -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/kvm/intc/eiointc.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kvm/intc/eiointc.c ---- BPI-Router-Linux-kernel/arch/loongarch/kvm/intc/eiointc.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kvm/intc/eiointc.c 2025-10-22 13:53:56.299170182 -0400 -@@ -9,7 +9,8 @@ - - static void eiointc_set_sw_coreisr(struct loongarch_eiointc *s) - { -- int ipnum, cpu, irq_index, irq_mask, irq; -+ int ipnum, cpu, cpuid, irq; -+ struct kvm_vcpu *vcpu; - - for (irq = 0; irq < EIOINTC_IRQS; irq++) { - ipnum = s->ipmap.reg_u8[irq / 32]; -@@ -17,20 +18,23 @@ static void eiointc_set_sw_coreisr(struc - ipnum = count_trailing_zeros(ipnum); - ipnum = (ipnum >= 0 && ipnum < 4) ? ipnum : 0; - } -- irq_index = irq / 32; -- irq_mask = BIT(irq & 0x1f); - -- cpu = s->coremap.reg_u8[irq]; -- if (!!(s->coreisr.reg_u32[cpu][irq_index] & irq_mask)) -- set_bit(irq, s->sw_coreisr[cpu][ipnum]); -+ cpuid = s->coremap.reg_u8[irq]; -+ vcpu = kvm_get_vcpu_by_cpuid(s->kvm, cpuid); -+ if (!vcpu) -+ continue; -+ -+ cpu = vcpu->vcpu_id; -+ if (test_bit(irq, (unsigned long *)s->coreisr.reg_u32[cpu])) -+ __set_bit(irq, s->sw_coreisr[cpu][ipnum]); - else -- clear_bit(irq, s->sw_coreisr[cpu][ipnum]); -+ __clear_bit(irq, s->sw_coreisr[cpu][ipnum]); - } - } - - static void eiointc_update_irq(struct loongarch_eiointc *s, int irq, int level) - { -- int ipnum, cpu, found, irq_index, irq_mask; -+ int ipnum, cpu, found; - struct kvm_vcpu *vcpu; - struct kvm_interrupt vcpu_irq; - -@@ -41,20 +45,22 @@ static void eiointc_update_irq(struct lo - } - - cpu = s->sw_coremap[irq]; -- vcpu = kvm_get_vcpu(s->kvm, cpu); -- irq_index = irq / 32; -- irq_mask = BIT(irq & 0x1f); -+ vcpu = kvm_get_vcpu_by_id(s->kvm, cpu); -+ if (unlikely(vcpu == NULL)) { -+ kvm_err("%s: invalid target cpu: %d\n", __func__, cpu); -+ return; -+ } - - if (level) { - /* if not enable return false */ -- if (((s->enable.reg_u32[irq_index]) & irq_mask) == 0) -+ if (!test_bit(irq, (unsigned long *)s->enable.reg_u32)) - return; -- s->coreisr.reg_u32[cpu][irq_index] |= irq_mask; -+ __set_bit(irq, (unsigned long *)s->coreisr.reg_u32[cpu]); - found = find_first_bit(s->sw_coreisr[cpu][ipnum], EIOINTC_IRQS); -- set_bit(irq, s->sw_coreisr[cpu][ipnum]); -+ __set_bit(irq, s->sw_coreisr[cpu][ipnum]); - } else { -- s->coreisr.reg_u32[cpu][irq_index] &= ~irq_mask; -- clear_bit(irq, s->sw_coreisr[cpu][ipnum]); -+ __clear_bit(irq, (unsigned long *)s->coreisr.reg_u32[cpu]); -+ __clear_bit(irq, s->sw_coreisr[cpu][ipnum]); - found = find_first_bit(s->sw_coreisr[cpu][ipnum], EIOINTC_IRQS); - } - -@@ -66,20 +72,25 @@ static void eiointc_update_irq(struct lo - } - - static inline void eiointc_update_sw_coremap(struct loongarch_eiointc *s, -- int irq, void *pvalue, u32 len, bool notify) -+ int irq, u64 val, u32 len, bool notify) - { -- int i, cpu; -- u64 val = *(u64 *)pvalue; -+ int i, cpu, cpuid; -+ struct kvm_vcpu *vcpu; - - for (i = 0; i < len; i++) { -- cpu = val & 0xff; -+ cpuid = val & 0xff; - val = val >> 8; - - if (!(s->status & BIT(EIOINTC_ENABLE_CPU_ENCODE))) { -- cpu = ffs(cpu) - 1; -- cpu = (cpu >= 4) ? 0 : cpu; -+ cpuid = ffs(cpuid) - 1; -+ cpuid = (cpuid >= 4) ? 0 : cpuid; - } - -+ vcpu = kvm_get_vcpu_by_cpuid(s->kvm, cpuid); -+ if (!vcpu) -+ continue; -+ -+ cpu = vcpu->vcpu_id; - if (s->sw_coremap[irq + i] == cpu) - continue; - -@@ -99,8 +110,8 @@ void eiointc_set_irq(struct loongarch_ei - unsigned long flags; - unsigned long *isr = (unsigned long *)s->isr.reg_u8; - -- level ? set_bit(irq, isr) : clear_bit(irq, isr); - spin_lock_irqsave(&s->lock, flags); -+ level ? __set_bit(irq, isr) : __clear_bit(irq, isr); - eiointc_update_irq(s, irq, level); - spin_unlock_irqrestore(&s->lock, flags); - } -@@ -305,6 +316,11 @@ static int kvm_eiointc_read(struct kvm_v - return -EINVAL; - } - -+ if (addr & (len - 1)) { -+ kvm_err("%s: eiointc not aligned addr %llx len %d\n", __func__, addr, len); -+ return -EINVAL; -+ } -+ - vcpu->kvm->stat.eiointc_read_exits++; - spin_lock_irqsave(&eiointc->lock, flags); - switch (len) { -@@ -398,7 +414,7 @@ static int loongarch_eiointc_writeb(stru - irq = offset - EIOINTC_COREMAP_START; - index = irq; - s->coremap.reg_u8[index] = data; -- eiointc_update_sw_coremap(s, irq, (void *)&data, sizeof(data), true); -+ eiointc_update_sw_coremap(s, irq, data, sizeof(data), true); - break; - default: - ret = -EINVAL; -@@ -436,17 +452,16 @@ static int loongarch_eiointc_writew(stru - break; - case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END: - index = (offset - EIOINTC_ENABLE_START) >> 1; -- old_data = s->enable.reg_u32[index]; -+ old_data = s->enable.reg_u16[index]; - s->enable.reg_u16[index] = data; - /* - * 1: enable irq. - * update irq when isr is set. - */ - data = s->enable.reg_u16[index] & ~old_data & s->isr.reg_u16[index]; -- index = index << 1; - for (i = 0; i < sizeof(data); i++) { - u8 mask = (data >> (i * 8)) & 0xff; -- eiointc_enable_irq(vcpu, s, index + i, mask, 1); -+ eiointc_enable_irq(vcpu, s, index * 2 + i, mask, 1); - } - /* - * 0: disable irq. -@@ -455,7 +470,7 @@ static int loongarch_eiointc_writew(stru - data = ~s->enable.reg_u16[index] & old_data & s->isr.reg_u16[index]; - for (i = 0; i < sizeof(data); i++) { - u8 mask = (data >> (i * 8)) & 0xff; -- eiointc_enable_irq(vcpu, s, index, mask, 0); -+ eiointc_enable_irq(vcpu, s, index * 2 + i, mask, 0); - } - break; - case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END: -@@ -484,7 +499,7 @@ static int loongarch_eiointc_writew(stru - irq = offset - EIOINTC_COREMAP_START; - index = irq >> 1; - s->coremap.reg_u16[index] = data; -- eiointc_update_sw_coremap(s, irq, (void *)&data, sizeof(data), true); -+ eiointc_update_sw_coremap(s, irq, data, sizeof(data), true); - break; - default: - ret = -EINVAL; -@@ -529,10 +544,9 @@ static int loongarch_eiointc_writel(stru - * update irq when isr is set. - */ - data = s->enable.reg_u32[index] & ~old_data & s->isr.reg_u32[index]; -- index = index << 2; - for (i = 0; i < sizeof(data); i++) { - u8 mask = (data >> (i * 8)) & 0xff; -- eiointc_enable_irq(vcpu, s, index + i, mask, 1); -+ eiointc_enable_irq(vcpu, s, index * 4 + i, mask, 1); - } - /* - * 0: disable irq. -@@ -541,7 +555,7 @@ static int loongarch_eiointc_writel(stru - data = ~s->enable.reg_u32[index] & old_data & s->isr.reg_u32[index]; - for (i = 0; i < sizeof(data); i++) { - u8 mask = (data >> (i * 8)) & 0xff; -- eiointc_enable_irq(vcpu, s, index, mask, 0); -+ eiointc_enable_irq(vcpu, s, index * 4 + i, mask, 0); - } - break; - case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END: -@@ -570,7 +584,7 @@ static int loongarch_eiointc_writel(stru - irq = offset - EIOINTC_COREMAP_START; - index = irq >> 2; - s->coremap.reg_u32[index] = data; -- eiointc_update_sw_coremap(s, irq, (void *)&data, sizeof(data), true); -+ eiointc_update_sw_coremap(s, irq, data, sizeof(data), true); - break; - default: - ret = -EINVAL; -@@ -615,10 +629,9 @@ static int loongarch_eiointc_writeq(stru - * update irq when isr is set. - */ - data = s->enable.reg_u64[index] & ~old_data & s->isr.reg_u64[index]; -- index = index << 3; - for (i = 0; i < sizeof(data); i++) { - u8 mask = (data >> (i * 8)) & 0xff; -- eiointc_enable_irq(vcpu, s, index + i, mask, 1); -+ eiointc_enable_irq(vcpu, s, index * 8 + i, mask, 1); - } - /* - * 0: disable irq. -@@ -627,7 +640,7 @@ static int loongarch_eiointc_writeq(stru - data = ~s->enable.reg_u64[index] & old_data & s->isr.reg_u64[index]; - for (i = 0; i < sizeof(data); i++) { - u8 mask = (data >> (i * 8)) & 0xff; -- eiointc_enable_irq(vcpu, s, index, mask, 0); -+ eiointc_enable_irq(vcpu, s, index * 8 + i, mask, 0); - } - break; - case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END: -@@ -656,7 +669,7 @@ static int loongarch_eiointc_writeq(stru - irq = offset - EIOINTC_COREMAP_START; - index = irq >> 3; - s->coremap.reg_u64[index] = data; -- eiointc_update_sw_coremap(s, irq, (void *)&data, sizeof(data), true); -+ eiointc_update_sw_coremap(s, irq, data, sizeof(data), true); - break; - default: - ret = -EINVAL; -@@ -679,6 +692,11 @@ static int kvm_eiointc_write(struct kvm_ - return -EINVAL; - } - -+ if (addr & (len - 1)) { -+ kvm_err("%s: eiointc not aligned addr %llx len %d\n", __func__, addr, len); -+ return -EINVAL; -+ } -+ - vcpu->kvm->stat.eiointc_write_exits++; - spin_lock_irqsave(&eiointc->lock, flags); - switch (len) { -@@ -787,20 +805,31 @@ static int kvm_eiointc_ctrl_access(struc - int ret = 0; - unsigned long flags; - unsigned long type = (unsigned long)attr->attr; -- u32 i, start_irq; -+ u32 i, start_irq, val; - void __user *data; - struct loongarch_eiointc *s = dev->kvm->arch.eiointc; - - data = (void __user *)attr->addr; -+ switch (type) { -+ case KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_NUM_CPU: -+ case KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_FEATURE: -+ if (copy_from_user(&val, data, 4)) -+ return -EFAULT; -+ break; -+ default: -+ break; -+ } -+ - spin_lock_irqsave(&s->lock, flags); - switch (type) { - case KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_NUM_CPU: -- if (copy_from_user(&s->num_cpu, data, 4)) -- ret = -EFAULT; -+ if (val >= EIOINTC_ROUTE_MAX_VCPUS) -+ ret = -EINVAL; -+ else -+ s->num_cpu = val; - break; - case KVM_DEV_LOONGARCH_EXTIOI_CTRL_INIT_FEATURE: -- if (copy_from_user(&s->features, data, 4)) -- ret = -EFAULT; -+ s->features = val; - if (!(s->features & BIT(EIOINTC_HAS_VIRT_EXTENSION))) - s->status |= BIT(EIOINTC_ENABLE); - break; -@@ -809,7 +838,7 @@ static int kvm_eiointc_ctrl_access(struc - for (i = 0; i < (EIOINTC_IRQS / 4); i++) { - start_irq = i * 4; - eiointc_update_sw_coremap(s, start_irq, -- (void *)&s->coremap.reg_u32[i], sizeof(u32), false); -+ s->coremap.reg_u32[i], sizeof(u32), false); - } - break; - default: -@@ -822,19 +851,17 @@ static int kvm_eiointc_ctrl_access(struc - - static int kvm_eiointc_regs_access(struct kvm_device *dev, - struct kvm_device_attr *attr, -- bool is_write) -+ bool is_write, int *data) - { -- int addr, cpuid, offset, ret = 0; -+ int addr, cpu, offset, ret = 0; - unsigned long flags; - void *p = NULL; -- void __user *data; - struct loongarch_eiointc *s; - - s = dev->kvm->arch.eiointc; - addr = attr->attr; -- cpuid = addr >> 16; -+ cpu = addr >> 16; - addr &= 0xffff; -- data = (void __user *)attr->addr; - switch (addr) { - case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END: - offset = (addr - EIOINTC_NODETYPE_START) / 4; -@@ -857,8 +884,11 @@ static int kvm_eiointc_regs_access(struc - p = &s->isr.reg_u32[offset]; - break; - case EIOINTC_COREISR_START ... EIOINTC_COREISR_END: -+ if (cpu >= s->num_cpu) -+ return -EINVAL; -+ - offset = (addr - EIOINTC_COREISR_START) / 4; -- p = &s->coreisr.reg_u32[cpuid][offset]; -+ p = &s->coreisr.reg_u32[cpu][offset]; - break; - case EIOINTC_COREMAP_START ... EIOINTC_COREMAP_END: - offset = (addr - EIOINTC_COREMAP_START) / 4; -@@ -870,13 +900,10 @@ static int kvm_eiointc_regs_access(struc - } - - spin_lock_irqsave(&s->lock, flags); -- if (is_write) { -- if (copy_from_user(p, data, 4)) -- ret = -EFAULT; -- } else { -- if (copy_to_user(data, p, 4)) -- ret = -EFAULT; -- } -+ if (is_write) -+ memcpy(p, data, 4); -+ else -+ memcpy(data, p, 4); - spin_unlock_irqrestore(&s->lock, flags); - - return ret; -@@ -884,24 +911,28 @@ static int kvm_eiointc_regs_access(struc - - static int kvm_eiointc_sw_status_access(struct kvm_device *dev, - struct kvm_device_attr *attr, -- bool is_write) -+ bool is_write, int *data) - { - int addr, ret = 0; - unsigned long flags; - void *p = NULL; -- void __user *data; - struct loongarch_eiointc *s; - - s = dev->kvm->arch.eiointc; - addr = attr->attr; - addr &= 0xffff; - -- data = (void __user *)attr->addr; - switch (addr) { - case KVM_DEV_LOONGARCH_EXTIOI_SW_STATUS_NUM_CPU: -+ if (is_write) -+ return ret; -+ - p = &s->num_cpu; - break; - case KVM_DEV_LOONGARCH_EXTIOI_SW_STATUS_FEATURE: -+ if (is_write) -+ return ret; -+ - p = &s->features; - break; - case KVM_DEV_LOONGARCH_EXTIOI_SW_STATUS_STATE: -@@ -912,13 +943,10 @@ static int kvm_eiointc_sw_status_access( - return -EINVAL; - } - spin_lock_irqsave(&s->lock, flags); -- if (is_write) { -- if (copy_from_user(p, data, 4)) -- ret = -EFAULT; -- } else { -- if (copy_to_user(data, p, 4)) -- ret = -EFAULT; -- } -+ if (is_write) -+ memcpy(p, data, 4); -+ else -+ memcpy(data, p, 4); - spin_unlock_irqrestore(&s->lock, flags); - - return ret; -@@ -927,11 +955,27 @@ static int kvm_eiointc_sw_status_access( - static int kvm_eiointc_get_attr(struct kvm_device *dev, - struct kvm_device_attr *attr) - { -+ int ret, data; -+ - switch (attr->group) { - case KVM_DEV_LOONGARCH_EXTIOI_GRP_REGS: -- return kvm_eiointc_regs_access(dev, attr, false); -+ ret = kvm_eiointc_regs_access(dev, attr, false, &data); -+ if (ret) -+ return ret; -+ -+ if (copy_to_user((void __user *)attr->addr, &data, 4)) -+ ret = -EFAULT; -+ -+ return ret; - case KVM_DEV_LOONGARCH_EXTIOI_GRP_SW_STATUS: -- return kvm_eiointc_sw_status_access(dev, attr, false); -+ ret = kvm_eiointc_sw_status_access(dev, attr, false, &data); -+ if (ret) -+ return ret; -+ -+ if (copy_to_user((void __user *)attr->addr, &data, 4)) -+ ret = -EFAULT; -+ -+ return ret; - default: - return -EINVAL; - } -@@ -940,13 +984,21 @@ static int kvm_eiointc_get_attr(struct k - static int kvm_eiointc_set_attr(struct kvm_device *dev, - struct kvm_device_attr *attr) - { -+ int data; -+ - switch (attr->group) { - case KVM_DEV_LOONGARCH_EXTIOI_GRP_CTRL: - return kvm_eiointc_ctrl_access(dev, attr); - case KVM_DEV_LOONGARCH_EXTIOI_GRP_REGS: -- return kvm_eiointc_regs_access(dev, attr, true); -+ if (copy_from_user(&data, (void __user *)attr->addr, 4)) -+ return -EFAULT; -+ -+ return kvm_eiointc_regs_access(dev, attr, true, &data); - case KVM_DEV_LOONGARCH_EXTIOI_GRP_SW_STATUS: -- return kvm_eiointc_sw_status_access(dev, attr, true); -+ if (copy_from_user(&data, (void __user *)attr->addr, 4)) -+ return -EFAULT; -+ -+ return kvm_eiointc_sw_status_access(dev, attr, true, &data); - default: - return -EINVAL; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/kvm/intc/ipi.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kvm/intc/ipi.c ---- BPI-Router-Linux-kernel/arch/loongarch/kvm/intc/ipi.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kvm/intc/ipi.c 2025-10-22 13:53:56.299170182 -0400 -@@ -99,7 +99,7 @@ static void write_mailbox(struct kvm_vcp - static int send_ipi_data(struct kvm_vcpu *vcpu, gpa_t addr, uint64_t data) - { - int i, idx, ret; -- uint32_t val = 0, mask = 0; -+ uint64_t val = 0, mask = 0; - - /* - * Bit 27-30 is mask for byte writing. -@@ -108,7 +108,7 @@ static int send_ipi_data(struct kvm_vcpu - if ((data >> 27) & 0xf) { - /* Read the old val */ - idx = srcu_read_lock(&vcpu->kvm->srcu); -- ret = kvm_io_bus_read(vcpu, KVM_IOCSR_BUS, addr, sizeof(val), &val); -+ ret = kvm_io_bus_read(vcpu, KVM_IOCSR_BUS, addr, 4, &val); - srcu_read_unlock(&vcpu->kvm->srcu, idx); - if (unlikely(ret)) { - kvm_err("%s: : read data from addr %llx failed\n", __func__, addr); -@@ -124,7 +124,7 @@ static int send_ipi_data(struct kvm_vcpu - } - val |= ((uint32_t)(data >> 32) & ~mask); - idx = srcu_read_lock(&vcpu->kvm->srcu); -- ret = kvm_io_bus_write(vcpu, KVM_IOCSR_BUS, addr, sizeof(val), &val); -+ ret = kvm_io_bus_write(vcpu, KVM_IOCSR_BUS, addr, 4, &val); - srcu_read_unlock(&vcpu->kvm->srcu, idx); - if (unlikely(ret)) - kvm_err("%s: : write data to addr %llx failed\n", __func__, addr); -@@ -318,7 +318,7 @@ static int kvm_ipi_regs_access(struct kv - cpu = (attr->attr >> 16) & 0x3ff; - addr = attr->attr & 0xff; - -- vcpu = kvm_get_vcpu(dev->kvm, cpu); -+ vcpu = kvm_get_vcpu_by_id(dev->kvm, cpu); - if (unlikely(vcpu == NULL)) { - kvm_err("%s: invalid target cpu: %d\n", __func__, cpu); - return -EINVAL; -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/kvm/intc/pch_pic.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kvm/intc/pch_pic.c ---- BPI-Router-Linux-kernel/arch/loongarch/kvm/intc/pch_pic.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kvm/intc/pch_pic.c 2025-10-22 13:53:56.299170182 -0400 -@@ -195,6 +195,11 @@ static int kvm_pch_pic_read(struct kvm_v - return -EINVAL; - } - -+ if (addr & (len - 1)) { -+ kvm_err("%s: pch pic not aligned addr %llx len %d\n", __func__, addr, len); -+ return -EINVAL; -+ } -+ - /* statistics of pch pic reading */ - vcpu->kvm->stat.pch_pic_read_exits++; - ret = loongarch_pch_pic_read(s, addr, len, val); -@@ -302,6 +307,11 @@ static int kvm_pch_pic_write(struct kvm_ - return -EINVAL; - } - -+ if (addr & (len - 1)) { -+ kvm_err("%s: pch pic not aligned addr %llx len %d\n", __func__, addr, len); -+ return -EINVAL; -+ } -+ - /* statistics of pch pic writing */ - vcpu->kvm->stat.pch_pic_write_exits++; - ret = loongarch_pch_pic_write(s, addr, len, val); -@@ -338,6 +348,7 @@ static int kvm_pch_pic_regs_access(struc - struct kvm_device_attr *attr, - bool is_write) - { -+ char buf[8]; - int addr, offset, len = 8, ret = 0; - void __user *data; - void *p = NULL; -@@ -387,17 +398,23 @@ static int kvm_pch_pic_regs_access(struc - return -EINVAL; - } - -- spin_lock(&s->lock); -- /* write or read value according to is_write */ - if (is_write) { -- if (copy_from_user(p, data, len)) -- ret = -EFAULT; -- } else { -- if (copy_to_user(data, p, len)) -- ret = -EFAULT; -+ if (copy_from_user(buf, data, len)) -+ return -EFAULT; - } -+ -+ spin_lock(&s->lock); -+ if (is_write) -+ memcpy(p, buf, len); -+ else -+ memcpy(buf, p, len); - spin_unlock(&s->lock); - -+ if (!is_write) { -+ if (copy_to_user(data, buf, len)) -+ return -EFAULT; -+ } -+ - return ret; - } - -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/kvm/mmu.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kvm/mmu.c ---- BPI-Router-Linux-kernel/arch/loongarch/kvm/mmu.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kvm/mmu.c 2025-10-22 13:53:56.299170182 -0400 -@@ -569,7 +569,7 @@ static int kvm_map_page_fast(struct kvm_ - /* Track access to pages marked old */ - new = kvm_pte_mkyoung(*ptep); - if (write && !kvm_pte_dirty(new)) { -- if (!kvm_pte_write(new)) { -+ if (!kvm_pte_writeable(new)) { - ret = -EFAULT; - goto out; - } -@@ -856,9 +856,9 @@ retry: - prot_bits |= _CACHE_SUC; - - if (writeable) { -- prot_bits |= _PAGE_WRITE; -+ prot_bits = kvm_pte_mkwriteable(prot_bits); - if (write) -- prot_bits |= __WRITEABLE; -+ prot_bits = kvm_pte_mkdirty(prot_bits); - } - - /* Disable dirty logging on HugePages */ -@@ -904,7 +904,7 @@ retry: - kvm_release_faultin_page(kvm, page, false, writeable); - spin_unlock(&kvm->mmu_lock); - -- if (prot_bits & _PAGE_DIRTY) -+ if (kvm_pte_dirty(prot_bits)) - mark_page_dirty_in_slot(kvm, memslot, gfn); - - out: -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/kvm/vcpu.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kvm/vcpu.c ---- BPI-Router-Linux-kernel/arch/loongarch/kvm/vcpu.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/kvm/vcpu.c 2025-10-22 13:53:56.299170182 -0400 -@@ -1277,9 +1277,11 @@ int kvm_own_lbt(struct kvm_vcpu *vcpu) - return -EINVAL; - - preempt_disable(); -- set_csr_euen(CSR_EUEN_LBTEN); -- _restore_lbt(&vcpu->arch.lbt); -- vcpu->arch.aux_inuse |= KVM_LARCH_LBT; -+ if (!(vcpu->arch.aux_inuse & KVM_LARCH_LBT)) { -+ set_csr_euen(CSR_EUEN_LBTEN); -+ _restore_lbt(&vcpu->arch.lbt); -+ vcpu->arch.aux_inuse |= KVM_LARCH_LBT; -+ } - preempt_enable(); - - return 0; -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/lib/crc32-loongarch.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/lib/crc32-loongarch.c ---- BPI-Router-Linux-kernel/arch/loongarch/lib/crc32-loongarch.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/lib/crc32-loongarch.c 2025-10-22 13:53:56.299170182 -0400 -@@ -11,6 +11,7 @@ - - #include - #include -+#include - #include - #include - -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/lib/csum.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/lib/csum.c ---- BPI-Router-Linux-kernel/arch/loongarch/lib/csum.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/lib/csum.c 2025-10-22 13:53:56.299170182 -0400 -@@ -2,6 +2,7 @@ - // Copyright (C) 2019-2020 Arm Ltd. - - #include -+#include - #include - #include - -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/Makefile BPI-Router-Linux-kernel-6.16.12/arch/loongarch/Makefile ---- BPI-Router-Linux-kernel/arch/loongarch/Makefile 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/Makefile 2025-10-22 13:53:56.299170182 -0400 -@@ -106,6 +106,17 @@ KBUILD_CFLAGS += -mannotate-tablejump - else - KBUILD_CFLAGS += -fno-jump-tables # keep compatibility with older compilers - endif -+ifdef CONFIG_RUSTC_HAS_ANNOTATE_TABLEJUMP -+KBUILD_RUSTFLAGS += -Cllvm-args=--loongarch-annotate-tablejump -+else -+KBUILD_RUSTFLAGS += -Zno-jump-tables # keep compatibility with older compilers -+endif -+ifdef CONFIG_LTO_CLANG -+# The annotate-tablejump option can not be passed to LLVM backend when LTO is enabled. -+# Ensure it is aware of linker with LTO, '--loongarch-annotate-tablejump' also needs to -+# be passed via '-mllvm' to ld.lld. -+KBUILD_LDFLAGS += -mllvm --loongarch-annotate-tablejump -+endif - endif - - KBUILD_RUSTFLAGS += --target=loongarch64-unknown-none-softfloat -Ccode-model=small -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/mm/ioremap.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/mm/ioremap.c ---- BPI-Router-Linux-kernel/arch/loongarch/mm/ioremap.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/mm/ioremap.c 2025-10-22 13:53:56.299170182 -0400 -@@ -16,12 +16,12 @@ void __init early_iounmap(void __iomem * - - } - --void *early_memremap_ro(resource_size_t phys_addr, unsigned long size) -+void * __init early_memremap_ro(resource_size_t phys_addr, unsigned long size) - { - return early_memremap(phys_addr, size); - } - --void *early_memremap_prot(resource_size_t phys_addr, unsigned long size, -+void * __init early_memremap_prot(resource_size_t phys_addr, unsigned long size, - unsigned long prot_val) - { - return early_memremap(phys_addr, size); -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/net/bpf_jit.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/net/bpf_jit.c ---- BPI-Router-Linux-kernel/arch/loongarch/net/bpf_jit.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/net/bpf_jit.c 2025-10-22 13:53:56.299170182 -0400 -@@ -208,11 +208,9 @@ bool bpf_jit_supports_far_kfunc_call(voi - return true; - } - --/* initialized on the first pass of build_body() */ --static int out_offset = -1; --static int emit_bpf_tail_call(struct jit_ctx *ctx) -+static int emit_bpf_tail_call(struct jit_ctx *ctx, int insn) - { -- int off; -+ int off, tc_ninsn = 0; - u8 tcc = tail_call_reg(ctx); - u8 a1 = LOONGARCH_GPR_A1; - u8 a2 = LOONGARCH_GPR_A2; -@@ -222,7 +220,7 @@ static int emit_bpf_tail_call(struct jit - const int idx0 = ctx->idx; - - #define cur_offset (ctx->idx - idx0) --#define jmp_offset (out_offset - (cur_offset)) -+#define jmp_offset (tc_ninsn - (cur_offset)) - - /* - * a0: &ctx -@@ -232,6 +230,7 @@ static int emit_bpf_tail_call(struct jit - * if (index >= array->map.max_entries) - * goto out; - */ -+ tc_ninsn = insn ? ctx->offset[insn+1] - ctx->offset[insn] : ctx->offset[0]; - off = offsetof(struct bpf_array, map.max_entries); - emit_insn(ctx, ldwu, t1, a1, off); - /* bgeu $a2, $t1, jmp_offset */ -@@ -263,15 +262,6 @@ static int emit_bpf_tail_call(struct jit - emit_insn(ctx, ldd, t3, t2, off); - __build_epilogue(ctx, true); - -- /* out: */ -- if (out_offset == -1) -- out_offset = cur_offset; -- if (cur_offset != out_offset) { -- pr_err_once("tail_call out_offset = %d, expected %d!\n", -- cur_offset, out_offset); -- return -1; -- } -- - return 0; - - toofar: -@@ -916,7 +906,7 @@ static int build_insn(const struct bpf_i - /* tail call */ - case BPF_JMP | BPF_TAIL_CALL: - mark_tail_call(ctx); -- if (emit_bpf_tail_call(ctx) < 0) -+ if (emit_bpf_tail_call(ctx, i) < 0) - return -EINVAL; - break; - -@@ -1342,7 +1332,6 @@ out: - if (tmp_blinded) - bpf_jit_prog_release_other(prog, prog == orig_prog ? tmp : orig_prog); - -- out_offset = -1; - - return prog; - -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/pci/pci.c BPI-Router-Linux-kernel-6.16.12/arch/loongarch/pci/pci.c ---- BPI-Router-Linux-kernel/arch/loongarch/pci/pci.c 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/pci/pci.c 2025-10-22 13:53:56.299170182 -0400 -@@ -3,7 +3,6 @@ - * Copyright (C) 2020-2022 Loongson Technology Corporation Limited - */ - #include --#include - #include - #include - #include -diff -purNx .git BPI-Router-Linux-kernel/arch/loongarch/vdso/Makefile BPI-Router-Linux-kernel-6.16.12/arch/loongarch/vdso/Makefile ---- BPI-Router-Linux-kernel/arch/loongarch/vdso/Makefile 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/loongarch/vdso/Makefile 2025-10-22 13:53:56.299170182 -0400 -@@ -36,7 +36,7 @@ endif - - # VDSO linker flags. - ldflags-y := -Bsymbolic --no-undefined -soname=linux-vdso.so.1 \ -- $(filter -E%,$(KBUILD_CFLAGS)) -nostdlib -shared --build-id -T -+ $(filter -E%,$(KBUILD_CFLAGS)) -shared --build-id -T - - # - # Shared build commands. -diff -purNx .git BPI-Router-Linux-kernel/arch/m68k/include/asm/mcf_pgtable.h BPI-Router-Linux-kernel-6.16.12/arch/m68k/include/asm/mcf_pgtable.h ---- BPI-Router-Linux-kernel/arch/m68k/include/asm/mcf_pgtable.h 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/m68k/include/asm/mcf_pgtable.h 2025-10-22 13:53:56.299170182 -0400 -@@ -268,7 +268,7 @@ extern pgd_t kernel_pg_dir[PTRS_PER_PGD] - #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) - #define __swp_entry_to_pte(x) (__pte((x).val)) - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/m68k/include/asm/motorola_pgtable.h BPI-Router-Linux-kernel-6.16.12/arch/m68k/include/asm/motorola_pgtable.h ---- BPI-Router-Linux-kernel/arch/m68k/include/asm/motorola_pgtable.h 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/m68k/include/asm/motorola_pgtable.h 2025-10-22 13:53:56.299170182 -0400 -@@ -185,7 +185,7 @@ extern pgd_t kernel_pg_dir[128]; - #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) - #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/m68k/include/asm/sun3_pgtable.h BPI-Router-Linux-kernel-6.16.12/arch/m68k/include/asm/sun3_pgtable.h ---- BPI-Router-Linux-kernel/arch/m68k/include/asm/sun3_pgtable.h 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/m68k/include/asm/sun3_pgtable.h 2025-10-22 13:53:56.299170182 -0400 -@@ -169,7 +169,7 @@ extern pgd_t kernel_pg_dir[PTRS_PER_PGD] - #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) - #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/m68k/Kconfig.debug BPI-Router-Linux-kernel-6.16.12/arch/m68k/Kconfig.debug ---- BPI-Router-Linux-kernel/arch/m68k/Kconfig.debug 2025-10-22 13:53:23.071329814 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/m68k/Kconfig.debug 2025-10-22 13:53:56.299170182 -0400 -@@ -10,7 +10,7 @@ config BOOTPARAM_STRING - - config EARLY_PRINTK - bool "Early printk" -- depends on !(SUN3 || M68000 || COLDFIRE) -+ depends on MMU_MOTOROLA - help - Write kernel log output directly to a serial port. - Where implemented, output goes to the framebuffer as well. -diff -purNx .git BPI-Router-Linux-kernel/arch/m68k/kernel/early_printk.c BPI-Router-Linux-kernel-6.16.12/arch/m68k/kernel/early_printk.c ---- BPI-Router-Linux-kernel/arch/m68k/kernel/early_printk.c 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/m68k/kernel/early_printk.c 2025-10-22 13:53:56.299170182 -0400 -@@ -16,25 +16,10 @@ - #include "../mvme147/mvme147.h" - #include "../mvme16x/mvme16x.h" - --asmlinkage void __init debug_cons_nputs(const char *s, unsigned n); -- --static void __ref debug_cons_write(struct console *c, -- const char *s, unsigned n) --{ --#if !(defined(CONFIG_SUN3) || defined(CONFIG_M68000) || \ -- defined(CONFIG_COLDFIRE)) -- if (MACH_IS_MVME147) -- mvme147_scc_write(c, s, n); -- else if (MACH_IS_MVME16x) -- mvme16x_cons_write(c, s, n); -- else -- debug_cons_nputs(s, n); --#endif --} -+asmlinkage void __init debug_cons_nputs(struct console *c, const char *s, unsigned int n); - - static struct console early_console_instance = { - .name = "debug", -- .write = debug_cons_write, - .flags = CON_PRINTBUFFER | CON_BOOT, - .index = -1 - }; -@@ -44,6 +29,12 @@ static int __init setup_early_printk(cha - if (early_console || buf) - return 0; - -+ if (MACH_IS_MVME147) -+ early_console_instance.write = mvme147_scc_write; -+ else if (MACH_IS_MVME16x) -+ early_console_instance.write = mvme16x_cons_write; -+ else -+ early_console_instance.write = debug_cons_nputs; - early_console = &early_console_instance; - register_console(early_console); - -@@ -51,20 +42,15 @@ static int __init setup_early_printk(cha - } - early_param("earlyprintk", setup_early_printk); - --/* -- * debug_cons_nputs() defined in arch/m68k/kernel/head.S cannot be called -- * after init sections are discarded (for platforms that use it). -- */ --#if !(defined(CONFIG_SUN3) || defined(CONFIG_M68000) || \ -- defined(CONFIG_COLDFIRE)) -- - static int __init unregister_early_console(void) - { -- if (!early_console || MACH_IS_MVME16x) -- return 0; -+ /* -+ * debug_cons_nputs() defined in arch/m68k/kernel/head.S cannot be -+ * called after init sections are discarded (for platforms that use it). -+ */ -+ if (early_console && early_console->write == debug_cons_nputs) -+ return unregister_console(early_console); - -- return unregister_console(early_console); -+ return 0; - } - late_initcall(unregister_early_console); -- --#endif -diff -purNx .git BPI-Router-Linux-kernel/arch/m68k/kernel/head.S BPI-Router-Linux-kernel-6.16.12/arch/m68k/kernel/head.S ---- BPI-Router-Linux-kernel/arch/m68k/kernel/head.S 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/m68k/kernel/head.S 2025-10-22 13:53:56.299170182 -0400 -@@ -3263,8 +3263,8 @@ func_return putn - * turns around and calls the internal routines. This routine - * is used by the boot console. - * -- * The calling parameters are: -- * void debug_cons_nputs(const char *str, unsigned length) -+ * The function signature is - -+ * void debug_cons_nputs(struct console *c, const char *s, unsigned int n) - * - * This routine does NOT understand variable arguments only - * simple strings! -@@ -3273,8 +3273,8 @@ ENTRY(debug_cons_nputs) - moveml %d0/%d1/%a0,%sp@- - movew %sr,%sp@- - ori #0x0700,%sr -- movel %sp@(18),%a0 /* fetch parameter */ -- movel %sp@(22),%d1 /* fetch parameter */ -+ movel %sp@(22),%a0 /* char *s */ -+ movel %sp@(26),%d1 /* unsigned int n */ - jra 2f - 1: - #ifdef CONSOLE_DEBUG -@@ -3400,6 +3400,7 @@ L(console_clear_loop): - - movel %d4,%d1 /* screen height in pixels */ - divul %a0@(FONT_DESC_HEIGHT),%d1 /* d1 = max num rows */ -+ subql #1,%d1 /* row range is 0 to num - 1 */ - - movel %d0,%a2@(Lconsole_struct_num_columns) - movel %d1,%a2@(Lconsole_struct_num_rows) -@@ -3546,15 +3547,14 @@ func_start console_putc,%a0/%a1/%d0-%d7 - cmpib #10,%d7 - jne L(console_not_lf) - movel %a0@(Lconsole_struct_cur_row),%d0 -- addil #1,%d0 -- movel %d0,%a0@(Lconsole_struct_cur_row) - movel %a0@(Lconsole_struct_num_rows),%d1 - cmpl %d1,%d0 - jcs 1f -- subil #1,%d0 -- movel %d0,%a0@(Lconsole_struct_cur_row) - console_scroll -+ jra L(console_exit) - 1: -+ addql #1,%d0 -+ movel %d0,%a0@(Lconsole_struct_cur_row) - jra L(console_exit) - - L(console_not_lf): -@@ -3581,12 +3581,6 @@ L(console_not_cr): - */ - L(console_not_home): - movel %a0@(Lconsole_struct_cur_column),%d0 -- addql #1,%a0@(Lconsole_struct_cur_column) -- movel %a0@(Lconsole_struct_num_columns),%d1 -- cmpl %d1,%d0 -- jcs 1f -- console_putc #'\n' /* recursion is OK! */ --1: - movel %a0@(Lconsole_struct_cur_row),%d1 - - /* -@@ -3633,6 +3627,23 @@ L(console_do_font_scanline): - addq #1,%d1 - dbra %d7,L(console_read_char_scanline) - -+ /* -+ * Register usage in the code below: -+ * a0 = pointer to console globals -+ * d0 = cursor column -+ * d1 = cursor column limit -+ */ -+ -+ lea %pc@(L(console_globals)),%a0 -+ -+ movel %a0@(Lconsole_struct_cur_column),%d0 -+ addql #1,%d0 -+ movel %d0,%a0@(Lconsole_struct_cur_column) /* Update cursor pos */ -+ movel %a0@(Lconsole_struct_num_columns),%d1 -+ cmpl %d1,%d0 -+ jcs L(console_exit) -+ console_putc #'\n' /* Line wrap using tail recursion */ -+ - L(console_exit): - func_return console_putc - -diff -purNx .git BPI-Router-Linux-kernel/arch/microblaze/include/asm/pgtable.h BPI-Router-Linux-kernel-6.16.12/arch/microblaze/include/asm/pgtable.h ---- BPI-Router-Linux-kernel/arch/microblaze/include/asm/pgtable.h 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/microblaze/include/asm/pgtable.h 2025-10-22 13:53:56.299170182 -0400 -@@ -398,7 +398,7 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD - #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 2 }) - #define __swp_entry_to_pte(x) ((pte_t) { (x).val << 2 }) - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/mips/alchemy/common/gpiolib.c BPI-Router-Linux-kernel-6.16.12/arch/mips/alchemy/common/gpiolib.c ---- BPI-Router-Linux-kernel/arch/mips/alchemy/common/gpiolib.c 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/mips/alchemy/common/gpiolib.c 2025-10-22 13:53:56.299170182 -0400 -@@ -40,9 +40,11 @@ static int gpio2_get(struct gpio_chip *c - return !!alchemy_gpio2_get_value(offset + ALCHEMY_GPIO2_BASE); - } - --static void gpio2_set(struct gpio_chip *chip, unsigned offset, int value) -+static int gpio2_set(struct gpio_chip *chip, unsigned offset, int value) - { - alchemy_gpio2_set_value(offset + ALCHEMY_GPIO2_BASE, value); -+ -+ return 0; - } - - static int gpio2_direction_input(struct gpio_chip *chip, unsigned offset) -@@ -68,10 +70,12 @@ static int gpio1_get(struct gpio_chip *c - return !!alchemy_gpio1_get_value(offset + ALCHEMY_GPIO1_BASE); - } - --static void gpio1_set(struct gpio_chip *chip, -+static int gpio1_set(struct gpio_chip *chip, - unsigned offset, int value) - { - alchemy_gpio1_set_value(offset + ALCHEMY_GPIO1_BASE, value); -+ -+ return 0; - } - - static int gpio1_direction_input(struct gpio_chip *chip, unsigned offset) -@@ -97,7 +101,7 @@ struct gpio_chip alchemy_gpio_chip[] = { - .direction_input = gpio1_direction_input, - .direction_output = gpio1_direction_output, - .get = gpio1_get, -- .set = gpio1_set, -+ .set_rv = gpio1_set, - .to_irq = gpio1_to_irq, - .base = ALCHEMY_GPIO1_BASE, - .ngpio = ALCHEMY_GPIO1_NUM, -@@ -107,7 +111,7 @@ struct gpio_chip alchemy_gpio_chip[] = { - .direction_input = gpio2_direction_input, - .direction_output = gpio2_direction_output, - .get = gpio2_get, -- .set = gpio2_set, -+ .set_rv = gpio2_set, - .to_irq = gpio2_to_irq, - .base = ALCHEMY_GPIO2_BASE, - .ngpio = ALCHEMY_GPIO2_NUM, -diff -purNx .git BPI-Router-Linux-kernel/arch/mips/boot/dts/lantiq/danube_easy50712.dts BPI-Router-Linux-kernel-6.16.12/arch/mips/boot/dts/lantiq/danube_easy50712.dts ---- BPI-Router-Linux-kernel/arch/mips/boot/dts/lantiq/danube_easy50712.dts 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/mips/boot/dts/lantiq/danube_easy50712.dts 2025-10-22 13:53:56.299170182 -0400 -@@ -82,13 +82,16 @@ - }; - }; - -- etop@e180000 { -+ ethernet@e180000 { - compatible = "lantiq,etop-xway"; - reg = <0xe180000 0x40000>; - interrupt-parent = <&icu0>; - interrupts = <73 78>; -+ interrupt-names = "tx", "rx"; - phy-mode = "rmii"; - mac-address = [ 00 11 22 33 44 55 ]; -+ lantiq,rx-burst-length = <4>; -+ lantiq,tx-burst-length = <4>; - }; - - stp0: stp@e100bb0 { -diff -purNx .git BPI-Router-Linux-kernel/arch/mips/include/asm/pgtable.h BPI-Router-Linux-kernel-6.16.12/arch/mips/include/asm/pgtable.h ---- BPI-Router-Linux-kernel/arch/mips/include/asm/pgtable.h 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/mips/include/asm/pgtable.h 2025-10-22 13:53:56.299170182 -0400 -@@ -534,7 +534,7 @@ static inline pte_t pte_modify(pte_t pte - #endif - - #if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte.pte_low & _PAGE_SWP_EXCLUSIVE; - } -@@ -551,7 +551,7 @@ static inline pte_t pte_swp_clear_exclus - return pte; - } - #else --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/mips/include/asm/vpe.h BPI-Router-Linux-kernel-6.16.12/arch/mips/include/asm/vpe.h ---- BPI-Router-Linux-kernel/arch/mips/include/asm/vpe.h 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/mips/include/asm/vpe.h 2025-10-22 13:53:56.303170163 -0400 -@@ -119,4 +119,12 @@ void cleanup_tc(struct tc *tc); - - int __init vpe_module_init(void); - void __exit vpe_module_exit(void); -+ -+#ifdef CONFIG_MIPS_VPE_LOADER_MT -+void *vpe_alloc(void); -+int vpe_start(void *vpe, unsigned long start); -+int vpe_stop(void *vpe); -+int vpe_free(void *vpe); -+#endif /* CONFIG_MIPS_VPE_LOADER_MT */ -+ - #endif /* _ASM_VPE_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/mips/kernel/process.c BPI-Router-Linux-kernel-6.16.12/arch/mips/kernel/process.c ---- BPI-Router-Linux-kernel/arch/mips/kernel/process.c 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/mips/kernel/process.c 2025-10-22 13:53:56.303170163 -0400 -@@ -690,18 +690,20 @@ unsigned long mips_stack_top(void) - } - - /* Space for the VDSO, data page & GIC user page */ -- top -= PAGE_ALIGN(current->thread.abi->vdso->size); -- top -= PAGE_SIZE; -- top -= mips_gic_present() ? PAGE_SIZE : 0; -+ if (current->thread.abi) { -+ top -= PAGE_ALIGN(current->thread.abi->vdso->size); -+ top -= PAGE_SIZE; -+ top -= mips_gic_present() ? PAGE_SIZE : 0; -+ -+ /* Space to randomize the VDSO base */ -+ if (current->flags & PF_RANDOMIZE) -+ top -= VDSO_RANDOMIZE_SIZE; -+ } - - /* Space for cache colour alignment */ - if (cpu_has_dc_aliases) - top -= shm_align_mask + 1; - -- /* Space to randomize the VDSO base */ -- if (current->flags & PF_RANDOMIZE) -- top -= VDSO_RANDOMIZE_SIZE; -- - return top; - } - -diff -purNx .git BPI-Router-Linux-kernel/arch/mips/lantiq/falcon/sysctrl.c BPI-Router-Linux-kernel-6.16.12/arch/mips/lantiq/falcon/sysctrl.c ---- BPI-Router-Linux-kernel/arch/mips/lantiq/falcon/sysctrl.c 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/mips/lantiq/falcon/sysctrl.c 2025-10-22 13:53:56.303170163 -0400 -@@ -214,19 +214,16 @@ void __init ltq_soc_init(void) - of_node_put(np_syseth); - of_node_put(np_sysgpe); - -- if ((request_mem_region(res_status.start, resource_size(&res_status), -- res_status.name) < 0) || -- (request_mem_region(res_ebu.start, resource_size(&res_ebu), -- res_ebu.name) < 0) || -- (request_mem_region(res_sys[0].start, -- resource_size(&res_sys[0]), -- res_sys[0].name) < 0) || -- (request_mem_region(res_sys[1].start, -- resource_size(&res_sys[1]), -- res_sys[1].name) < 0) || -- (request_mem_region(res_sys[2].start, -- resource_size(&res_sys[2]), -- res_sys[2].name) < 0)) -+ if ((!request_mem_region(res_status.start, resource_size(&res_status), -+ res_status.name)) || -+ (!request_mem_region(res_ebu.start, resource_size(&res_ebu), -+ res_ebu.name)) || -+ (!request_mem_region(res_sys[0].start, resource_size(&res_sys[0]), -+ res_sys[0].name)) || -+ (!request_mem_region(res_sys[1].start, resource_size(&res_sys[1]), -+ res_sys[1].name)) || -+ (!request_mem_region(res_sys[2].start, resource_size(&res_sys[2]), -+ res_sys[2].name))) - pr_err("Failed to request core resources"); - - status_membase = ioremap(res_status.start, -diff -purNx .git BPI-Router-Linux-kernel/arch/mips/lantiq/xway/sysctrl.c BPI-Router-Linux-kernel-6.16.12/arch/mips/lantiq/xway/sysctrl.c ---- BPI-Router-Linux-kernel/arch/mips/lantiq/xway/sysctrl.c 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/mips/lantiq/xway/sysctrl.c 2025-10-22 13:53:56.303170163 -0400 -@@ -497,7 +497,7 @@ void __init ltq_soc_init(void) - ifccr = CGU_IFCCR_VR9; - pcicr = CGU_PCICR_VR9; - } else { -- clkdev_add_pmu("1e180000.etop", NULL, 1, 0, PMU_PPE); -+ clkdev_add_pmu("1e180000.ethernet", NULL, 1, 0, PMU_PPE); - } - - if (!of_machine_is_compatible("lantiq,ase")) -@@ -531,9 +531,9 @@ void __init ltq_soc_init(void) - CLOCK_133M, CLOCK_133M); - clkdev_add_pmu("1e101000.usb", "otg", 1, 0, PMU_USB0); - clkdev_add_pmu("1f203018.usb2-phy", "phy", 1, 0, PMU_USB0_P); -- clkdev_add_pmu("1e180000.etop", "ppe", 1, 0, PMU_PPE); -- clkdev_add_cgu("1e180000.etop", "ephycgu", CGU_EPHY); -- clkdev_add_pmu("1e180000.etop", "ephy", 1, 0, PMU_EPHY); -+ clkdev_add_pmu("1e180000.ethernet", "ppe", 1, 0, PMU_PPE); -+ clkdev_add_cgu("1e180000.ethernet", "ephycgu", CGU_EPHY); -+ clkdev_add_pmu("1e180000.ethernet", "ephy", 1, 0, PMU_EPHY); - clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_ASE_SDIO); - clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE); - } else if (of_machine_is_compatible("lantiq,grx390")) { -@@ -592,7 +592,7 @@ void __init ltq_soc_init(void) - clkdev_add_pmu("1e101000.usb", "otg", 1, 0, PMU_USB0 | PMU_AHBM); - clkdev_add_pmu("1f203034.usb2-phy", "phy", 1, 0, PMU_USB1_P); - clkdev_add_pmu("1e106000.usb", "otg", 1, 0, PMU_USB1 | PMU_AHBM); -- clkdev_add_pmu("1e180000.etop", "switch", 1, 0, PMU_SWITCH); -+ clkdev_add_pmu("1e180000.ethernet", "switch", 1, 0, PMU_SWITCH); - clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO); - clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU); - clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE); -diff -purNx .git BPI-Router-Linux-kernel/arch/mips/lib/crypto/chacha-core.S BPI-Router-Linux-kernel-6.16.12/arch/mips/lib/crypto/chacha-core.S ---- BPI-Router-Linux-kernel/arch/mips/lib/crypto/chacha-core.S 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/mips/lib/crypto/chacha-core.S 2025-10-22 13:53:56.303170163 -0400 -@@ -55,17 +55,13 @@ - #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - #define MSB 0 - #define LSB 3 --#define ROTx rotl --#define ROTR(n) rotr n, 24 - #define CPU_TO_LE32(n) \ -- wsbh n; \ -+ wsbh n, n; \ - rotr n, 16; - #else - #define MSB 3 - #define LSB 0 --#define ROTx rotr - #define CPU_TO_LE32(n) --#define ROTR(n) - #endif - - #define FOR_EACH_WORD(x) \ -@@ -192,10 +188,10 @@ CONCAT3(.Lchacha_mips_xor_aligned_, PLUS - xor X(W), X(B); \ - xor X(Y), X(C); \ - xor X(Z), X(D); \ -- rotl X(V), S; \ -- rotl X(W), S; \ -- rotl X(Y), S; \ -- rotl X(Z), S; -+ rotr X(V), 32 - S; \ -+ rotr X(W), 32 - S; \ -+ rotr X(Y), 32 - S; \ -+ rotr X(Z), 32 - S; - - .text - .set reorder -@@ -372,21 +368,19 @@ chacha_crypt_arch: - /* First byte */ - lbu T1, 0(IN) - addiu $at, BYTES, 1 -- CPU_TO_LE32(SAVED_X) -- ROTR(SAVED_X) - xor T1, SAVED_X - sb T1, 0(OUT) - beqz $at, .Lchacha_mips_xor_done - /* Second byte */ - lbu T1, 1(IN) - addiu $at, BYTES, 2 -- ROTx SAVED_X, 8 -+ rotr SAVED_X, 8 - xor T1, SAVED_X - sb T1, 1(OUT) - beqz $at, .Lchacha_mips_xor_done - /* Third byte */ - lbu T1, 2(IN) -- ROTx SAVED_X, 8 -+ rotr SAVED_X, 8 - xor T1, SAVED_X - sb T1, 2(OUT) - b .Lchacha_mips_xor_done -diff -purNx .git BPI-Router-Linux-kernel/arch/mips/mm/tlb-r4k.c BPI-Router-Linux-kernel-6.16.12/arch/mips/mm/tlb-r4k.c ---- BPI-Router-Linux-kernel/arch/mips/mm/tlb-r4k.c 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/mips/mm/tlb-r4k.c 2025-10-22 13:53:56.303170163 -0400 -@@ -508,6 +508,60 @@ static int __init set_ntlb(char *str) - - __setup("ntlb=", set_ntlb); - -+/* Initialise all TLB entries with unique values */ -+static void r4k_tlb_uniquify(void) -+{ -+ int entry = num_wired_entries(); -+ -+ htw_stop(); -+ write_c0_entrylo0(0); -+ write_c0_entrylo1(0); -+ -+ while (entry < current_cpu_data.tlbsize) { -+ unsigned long asid_mask = cpu_asid_mask(¤t_cpu_data); -+ unsigned long asid = 0; -+ int idx; -+ -+ /* Skip wired MMID to make ginvt_mmid work */ -+ if (cpu_has_mmid) -+ asid = MMID_KERNEL_WIRED + 1; -+ -+ /* Check for match before using UNIQUE_ENTRYHI */ -+ do { -+ if (cpu_has_mmid) { -+ write_c0_memorymapid(asid); -+ write_c0_entryhi(UNIQUE_ENTRYHI(entry)); -+ } else { -+ write_c0_entryhi(UNIQUE_ENTRYHI(entry) | asid); -+ } -+ mtc0_tlbw_hazard(); -+ tlb_probe(); -+ tlb_probe_hazard(); -+ idx = read_c0_index(); -+ /* No match or match is on current entry */ -+ if (idx < 0 || idx == entry) -+ break; -+ /* -+ * If we hit a match, we need to try again with -+ * a different ASID. -+ */ -+ asid++; -+ } while (asid < asid_mask); -+ -+ if (idx >= 0 && idx != entry) -+ panic("Unable to uniquify TLB entry %d", idx); -+ -+ write_c0_index(entry); -+ mtc0_tlbw_hazard(); -+ tlb_write_indexed(); -+ entry++; -+ } -+ -+ tlbw_use_hazard(); -+ htw_start(); -+ flush_micro_tlb(); -+} -+ - /* - * Configure TLB (for init or after a CPU has been powered off). - */ -@@ -547,7 +601,7 @@ static void r4k_tlb_configure(void) - temp_tlb_entry = current_cpu_data.tlbsize - 1; - - /* From this point on the ARC firmware is dead. */ -- local_flush_tlb_all(); -+ r4k_tlb_uniquify(); - - /* Did I tell you that ARC SUCKS? */ - } -diff -purNx .git BPI-Router-Linux-kernel/arch/nios2/include/asm/pgtable.h BPI-Router-Linux-kernel-6.16.12/arch/nios2/include/asm/pgtable.h ---- BPI-Router-Linux-kernel/arch/nios2/include/asm/pgtable.h 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/nios2/include/asm/pgtable.h 2025-10-22 13:53:56.303170163 -0400 -@@ -259,7 +259,7 @@ static inline unsigned long pmd_page_vad - #define __swp_entry_to_pte(swp) ((pte_t) { (swp).val }) - #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/openrisc/include/asm/pgtable.h BPI-Router-Linux-kernel-6.16.12/arch/openrisc/include/asm/pgtable.h ---- BPI-Router-Linux-kernel/arch/openrisc/include/asm/pgtable.h 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/openrisc/include/asm/pgtable.h 2025-10-22 13:53:56.303170163 -0400 -@@ -411,7 +411,7 @@ static inline void update_mmu_cache_rang - #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) - #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/parisc/include/asm/pgtable.h BPI-Router-Linux-kernel-6.16.12/arch/parisc/include/asm/pgtable.h ---- BPI-Router-Linux-kernel/arch/parisc/include/asm/pgtable.h 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/parisc/include/asm/pgtable.h 2025-10-22 13:53:56.303170163 -0400 -@@ -276,7 +276,7 @@ extern unsigned long *empty_zero_page; - #define pte_none(x) (pte_val(x) == 0) - #define pte_present(x) (pte_val(x) & _PAGE_PRESENT) - #define pte_user(x) (pte_val(x) & _PAGE_USER) --#define pte_clear(mm, addr, xp) set_pte(xp, __pte(0)) -+#define pte_clear(mm, addr, xp) set_pte_at((mm), (addr), (xp), __pte(0)) - - #define pmd_flag(x) (pmd_val(x) & PxD_FLAG_MASK) - #define pmd_address(x) ((unsigned long)(pmd_val(x) &~ PxD_FLAG_MASK) << PxD_VALUE_SHIFT) -@@ -392,6 +392,7 @@ static inline void set_ptes(struct mm_st - } - } - #define set_ptes set_ptes -+#define set_pte_at(mm, addr, ptep, pte) set_ptes(mm, addr, ptep, pte, 1) - - /* Used for deferring calls to flush_dcache_page() */ - -@@ -425,7 +426,7 @@ static inline void set_ptes(struct mm_st - #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) - #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; - } -@@ -456,7 +457,7 @@ static inline int ptep_test_and_clear_yo - if (!pte_young(pte)) { - return 0; - } -- set_pte(ptep, pte_mkold(pte)); -+ set_pte_at(vma->vm_mm, addr, ptep, pte_mkold(pte)); - return 1; - } - -@@ -466,7 +467,7 @@ pte_t ptep_clear_flush(struct vm_area_st - struct mm_struct; - static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) - { -- set_pte(ptep, pte_wrprotect(*ptep)); -+ set_pte_at(mm, addr, ptep, pte_wrprotect(*ptep)); - } - - #define pte_same(A,B) (pte_val(A) == pte_val(B)) -diff -purNx .git BPI-Router-Linux-kernel/arch/parisc/include/asm/special_insns.h BPI-Router-Linux-kernel-6.16.12/arch/parisc/include/asm/special_insns.h ---- BPI-Router-Linux-kernel/arch/parisc/include/asm/special_insns.h 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/parisc/include/asm/special_insns.h 2025-10-22 13:53:56.303170163 -0400 -@@ -32,6 +32,34 @@ - pa; \ - }) - -+/** -+ * prober_user() - Probe user read access -+ * @sr: Space regster. -+ * @va: Virtual address. -+ * -+ * Return: Non-zero if address is accessible. -+ * -+ * Due to the way _PAGE_READ is handled in TLB entries, we need -+ * a special check to determine whether a user address is accessible. -+ * The ldb instruction does the initial access check. If it is -+ * successful, the probe instruction checks user access rights. -+ */ -+#define prober_user(sr, va) ({ \ -+ unsigned long read_allowed; \ -+ __asm__ __volatile__( \ -+ "copy %%r0,%0\n" \ -+ "8:\tldb 0(%%sr%1,%2),%%r0\n" \ -+ "\tproberi (%%sr%1,%2),%3,%0\n" \ -+ "9:\n" \ -+ ASM_EXCEPTIONTABLE_ENTRY(8b, 9b, \ -+ "or %%r0,%%r0,%%r0") \ -+ : "=&r" (read_allowed) \ -+ : "i" (sr), "r" (va), "i" (PRIV_USER) \ -+ : "memory" \ -+ ); \ -+ read_allowed; \ -+}) -+ - #define CR_EIEM 15 /* External Interrupt Enable Mask */ - #define CR_CR16 16 /* CR16 Interval Timer */ - #define CR_EIRR 23 /* External Interrupt Request Register */ -diff -purNx .git BPI-Router-Linux-kernel/arch/parisc/include/asm/uaccess.h BPI-Router-Linux-kernel-6.16.12/arch/parisc/include/asm/uaccess.h ---- BPI-Router-Linux-kernel/arch/parisc/include/asm/uaccess.h 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/parisc/include/asm/uaccess.h 2025-10-22 13:53:56.303170163 -0400 -@@ -42,9 +42,24 @@ - __gu_err; \ - }) - --#define __get_user(val, ptr) \ --({ \ -- __get_user_internal(SR_USER, val, ptr); \ -+#define __probe_user_internal(sr, error, ptr) \ -+({ \ -+ __asm__("\tproberi (%%sr%1,%2),%3,%0\n" \ -+ "\tcmpiclr,= 1,%0,%0\n" \ -+ "\tldi %4,%0\n" \ -+ : "=r"(error) \ -+ : "i"(sr), "r"(ptr), "i"(PRIV_USER), \ -+ "i"(-EFAULT)); \ -+}) -+ -+#define __get_user(val, ptr) \ -+({ \ -+ register long __gu_err; \ -+ \ -+ __gu_err = __get_user_internal(SR_USER, val, ptr); \ -+ if (likely(!__gu_err)) \ -+ __probe_user_internal(SR_USER, __gu_err, ptr); \ -+ __gu_err; \ - }) - - #define __get_user_asm(sr, val, ldx, ptr) \ -diff -purNx .git BPI-Router-Linux-kernel/arch/parisc/kernel/cache.c BPI-Router-Linux-kernel-6.16.12/arch/parisc/kernel/cache.c ---- BPI-Router-Linux-kernel/arch/parisc/kernel/cache.c 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/parisc/kernel/cache.c 2025-10-22 13:53:56.303170163 -0400 -@@ -429,7 +429,7 @@ static inline pte_t *get_ptep(struct mm_ - return ptep; - } - --static inline bool pte_needs_flush(pte_t pte) -+static inline bool pte_needs_cache_flush(pte_t pte) - { - return (pte_val(pte) & (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_NO_CACHE)) - == (_PAGE_PRESENT | _PAGE_ACCESSED); -@@ -630,7 +630,7 @@ static void flush_cache_page_if_present( - ptep = get_ptep(vma->vm_mm, vmaddr); - if (ptep) { - pte = ptep_get(ptep); -- needs_flush = pte_needs_flush(pte); -+ needs_flush = pte_needs_cache_flush(pte); - pte_unmap(ptep); - } - if (needs_flush) -@@ -841,7 +841,7 @@ void flush_cache_vmap(unsigned long star - } - - vm = find_vm_area((void *)start); -- if (WARN_ON_ONCE(!vm)) { -+ if (!vm) { - flush_cache_all(); - return; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/parisc/kernel/entry.S BPI-Router-Linux-kernel-6.16.12/arch/parisc/kernel/entry.S ---- BPI-Router-Linux-kernel/arch/parisc/kernel/entry.S 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/parisc/kernel/entry.S 2025-10-22 13:53:56.303170163 -0400 -@@ -499,6 +499,12 @@ - * this happens is quite subtle, read below */ - .macro make_insert_tlb spc,pte,prot,tmp - space_to_prot \spc \prot /* create prot id from space */ -+ -+#if _PAGE_SPECIAL_BIT == _PAGE_DMB_BIT -+ /* need to drop DMB bit, as it's used as SPECIAL flag */ -+ depi 0,_PAGE_SPECIAL_BIT,1,\pte -+#endif -+ - /* The following is the real subtlety. This is depositing - * T <-> _PAGE_REFTRAP - * D <-> _PAGE_DIRTY -@@ -511,17 +517,18 @@ - * Finally, _PAGE_READ goes in the top bit of PL1 (so we - * trigger an access rights trap in user space if the user - * tries to read an unreadable page */ --#if _PAGE_SPECIAL_BIT == _PAGE_DMB_BIT -- /* need to drop DMB bit, as it's used as SPECIAL flag */ -- depi 0,_PAGE_SPECIAL_BIT,1,\pte --#endif - depd \pte,8,7,\prot - - /* PAGE_USER indicates the page can be read with user privileges, - * so deposit X1|11 to PL1|PL2 (remember the upper bit of PL1 -- * contains _PAGE_READ) */ -+ * contains _PAGE_READ). While the kernel can't directly write -+ * user pages which have _PAGE_WRITE zero, it can read pages -+ * which have _PAGE_READ zero (PL <= PL1). Thus, the kernel -+ * exception fault handler doesn't trigger when reading pages -+ * that aren't user read accessible */ - extrd,u,*= \pte,_PAGE_USER_BIT+32,1,%r0 - depdi 7,11,3,\prot -+ - /* If we're a gateway page, drop PL2 back to zero for promotion - * to kernel privilege (so we can execute the page as kernel). - * Any privilege promotion page always denys read and write */ -diff -purNx .git BPI-Router-Linux-kernel/arch/parisc/kernel/syscall.S BPI-Router-Linux-kernel-6.16.12/arch/parisc/kernel/syscall.S ---- BPI-Router-Linux-kernel/arch/parisc/kernel/syscall.S 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/parisc/kernel/syscall.S 2025-10-22 13:53:56.303170163 -0400 -@@ -613,6 +613,9 @@ lws_compare_and_swap32: - lws_compare_and_swap: - /* Trigger memory reference interruptions without writing to memory */ - 1: ldw 0(%r26), %r28 -+ proberi (%r26), PRIV_USER, %r28 -+ comb,=,n %r28, %r0, lws_fault /* backwards, likely not taken */ -+ nop - 2: stbys,e %r0, 0(%r26) - - /* Calculate 8-bit hash index from virtual address */ -@@ -767,6 +770,9 @@ cas2_lock_start: - copy %r26, %r28 - depi_safe 0, 31, 2, %r28 - 10: ldw 0(%r28), %r1 -+ proberi (%r28), PRIV_USER, %r1 -+ comb,=,n %r1, %r0, lws_fault /* backwards, likely not taken */ -+ nop - 11: stbys,e %r0, 0(%r28) - - /* Calculate 8-bit hash index from virtual address */ -@@ -951,41 +957,47 @@ atomic_xchg_begin: - - /* 8-bit exchange */ - 1: ldb 0(%r24), %r20 -+ proberi (%r24), PRIV_USER, %r20 -+ comb,=,n %r20, %r0, lws_fault /* backwards, likely not taken */ -+ nop - copy %r23, %r20 - depi_safe 0, 31, 2, %r20 - b atomic_xchg_start - 2: stbys,e %r0, 0(%r20) -- nop -- nop -- nop - - /* 16-bit exchange */ - 3: ldh 0(%r24), %r20 -+ proberi (%r24), PRIV_USER, %r20 -+ comb,=,n %r20, %r0, lws_fault /* backwards, likely not taken */ -+ nop - copy %r23, %r20 - depi_safe 0, 31, 2, %r20 - b atomic_xchg_start - 4: stbys,e %r0, 0(%r20) -- nop -- nop -- nop - - /* 32-bit exchange */ - 5: ldw 0(%r24), %r20 -+ proberi (%r24), PRIV_USER, %r20 -+ comb,=,n %r20, %r0, lws_fault /* backwards, likely not taken */ -+ nop - b atomic_xchg_start - 6: stbys,e %r0, 0(%r23) - nop - nop -- nop -- nop -- nop - - /* 64-bit exchange */ - #ifdef CONFIG_64BIT - 7: ldd 0(%r24), %r20 -+ proberi (%r24), PRIV_USER, %r20 -+ comb,=,n %r20, %r0, lws_fault /* backwards, likely not taken */ -+ nop - 8: stdby,e %r0, 0(%r23) - #else - 7: ldw 0(%r24), %r20 - 8: ldw 4(%r24), %r20 -+ proberi (%r24), PRIV_USER, %r20 -+ comb,=,n %r20, %r0, lws_fault /* backwards, likely not taken */ -+ nop - copy %r23, %r20 - depi_safe 0, 31, 2, %r20 - 9: stbys,e %r0, 0(%r20) -diff -purNx .git BPI-Router-Linux-kernel/arch/parisc/lib/memcpy.c BPI-Router-Linux-kernel-6.16.12/arch/parisc/lib/memcpy.c ---- BPI-Router-Linux-kernel/arch/parisc/lib/memcpy.c 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/parisc/lib/memcpy.c 2025-10-22 13:53:56.303170163 -0400 -@@ -12,6 +12,7 @@ - #include - #include - #include -+#include - - #define get_user_space() mfsp(SR_USER) - #define get_kernel_space() SR_KERNEL -@@ -32,9 +33,25 @@ EXPORT_SYMBOL(raw_copy_to_user); - unsigned long raw_copy_from_user(void *dst, const void __user *src, - unsigned long len) - { -+ unsigned long start = (unsigned long) src; -+ unsigned long end = start + len; -+ unsigned long newlen = len; -+ - mtsp(get_user_space(), SR_TEMP1); - mtsp(get_kernel_space(), SR_TEMP2); -- return pa_memcpy(dst, (void __force *)src, len); -+ -+ /* Check region is user accessible */ -+ if (start) -+ while (start < end) { -+ if (!prober_user(SR_TEMP1, start)) { -+ newlen = (start - (unsigned long) src); -+ break; -+ } -+ start += PAGE_SIZE; -+ /* align to page boundry which may have different permission */ -+ start = PAGE_ALIGN_DOWN(start); -+ } -+ return len - newlen + pa_memcpy(dst, (void __force *)src, newlen); - } - EXPORT_SYMBOL(raw_copy_from_user); - -diff -purNx .git BPI-Router-Linux-kernel/arch/parisc/Makefile BPI-Router-Linux-kernel-6.16.12/arch/parisc/Makefile ---- BPI-Router-Linux-kernel/arch/parisc/Makefile 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/parisc/Makefile 2025-10-22 13:53:56.303170163 -0400 -@@ -39,7 +39,9 @@ endif - - export LD_BFD - --# Set default 32 bits cross compilers for vdso -+# Set default 32 bits cross compilers for vdso. -+# This means that for 64BIT, both the 64-bit tools and the 32-bit tools -+# need to be in the path. - CC_ARCHES_32 = hppa hppa2.0 hppa1.1 - CC_SUFFIXES = linux linux-gnu unknown-linux-gnu suse-linux - CROSS32_COMPILE := $(call cc-cross-prefix, \ -@@ -139,7 +141,7 @@ palo lifimage: vmlinuz - fi - @if test ! -f "$(PALOCONF)"; then \ - cp $(srctree)/arch/parisc/defpalo.conf $(objtree)/palo.conf; \ -- echo 'A generic palo config file ($(objree)/palo.conf) has been created for you.'; \ -+ echo 'A generic palo config file ($(objtree)/palo.conf) has been created for you.'; \ - echo 'You should check it and re-run "make palo".'; \ - echo 'WARNING: the "lifimage" file is now placed in this directory by default!'; \ - false; \ -diff -purNx .git BPI-Router-Linux-kernel/arch/parisc/mm/fault.c BPI-Router-Linux-kernel-6.16.12/arch/parisc/mm/fault.c ---- BPI-Router-Linux-kernel/arch/parisc/mm/fault.c 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/parisc/mm/fault.c 2025-10-22 13:53:56.303170163 -0400 -@@ -363,6 +363,10 @@ bad_area: - mmap_read_unlock(mm); - - bad_area_nosemaphore: -+ if (!user_mode(regs) && fixup_exception(regs)) { -+ return; -+ } -+ - if (user_mode(regs)) { - int signo, si_code; - -diff -purNx .git BPI-Router-Linux-kernel/arch/powerpc/boot/dts/microwatt.dts BPI-Router-Linux-kernel-6.16.12/arch/powerpc/boot/dts/microwatt.dts ---- BPI-Router-Linux-kernel/arch/powerpc/boot/dts/microwatt.dts 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/powerpc/boot/dts/microwatt.dts 2025-10-22 13:53:56.303170163 -0400 -@@ -4,7 +4,7 @@ - / { - #size-cells = <0x02>; - #address-cells = <0x02>; -- model-name = "microwatt"; -+ model = "microwatt"; - compatible = "microwatt-soc"; - - aliases { -diff -purNx .git BPI-Router-Linux-kernel/arch/powerpc/boot/dts/mpc8315erdb.dts BPI-Router-Linux-kernel-6.16.12/arch/powerpc/boot/dts/mpc8315erdb.dts ---- BPI-Router-Linux-kernel/arch/powerpc/boot/dts/mpc8315erdb.dts 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/powerpc/boot/dts/mpc8315erdb.dts 2025-10-22 13:53:56.303170163 -0400 -@@ -6,6 +6,7 @@ - */ - - /dts-v1/; -+#include - - / { - compatible = "fsl,mpc8315erdb"; -@@ -358,6 +359,15 @@ - interrupt-parent = <&ipic>; - fsl,mpc8313-wakeup-timer = <>m1>; - }; -+ -+ gpio: gpio-controller@c00 { -+ compatible = "fsl,mpc8314-gpio"; -+ reg = <0xc00 0x100>; -+ interrupts = <74 IRQ_TYPE_LEVEL_LOW>; -+ interrupt-parent = <&ipic>; -+ gpio-controller; -+ #gpio-cells = <2>; -+ }; - }; - - pci0: pci@e0008500 { -diff -purNx .git BPI-Router-Linux-kernel/arch/powerpc/configs/ppc6xx_defconfig BPI-Router-Linux-kernel-6.16.12/arch/powerpc/configs/ppc6xx_defconfig ---- BPI-Router-Linux-kernel/arch/powerpc/configs/ppc6xx_defconfig 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/powerpc/configs/ppc6xx_defconfig 2025-10-22 13:53:56.303170163 -0400 -@@ -252,7 +252,6 @@ CONFIG_NET_SCH_DSMARK=m - CONFIG_NET_SCH_NETEM=m - CONFIG_NET_SCH_INGRESS=m - CONFIG_NET_CLS_BASIC=m --CONFIG_NET_CLS_TCINDEX=m - CONFIG_NET_CLS_ROUTE4=m - CONFIG_NET_CLS_FW=m - CONFIG_NET_CLS_U32=m -diff -purNx .git BPI-Router-Linux-kernel/arch/powerpc/include/asm/book3s/32/pgtable.h BPI-Router-Linux-kernel-6.16.12/arch/powerpc/include/asm/book3s/32/pgtable.h ---- BPI-Router-Linux-kernel/arch/powerpc/include/asm/book3s/32/pgtable.h 2025-10-22 13:53:23.075329795 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/powerpc/include/asm/book3s/32/pgtable.h 2025-10-22 13:53:56.303170163 -0400 -@@ -365,7 +365,7 @@ static inline void __ptep_set_access_fla - #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 3 }) - #define __swp_entry_to_pte(x) ((pte_t) { (x).val << 3 }) - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/powerpc/include/asm/book3s/64/pgtable.h BPI-Router-Linux-kernel-6.16.12/arch/powerpc/include/asm/book3s/64/pgtable.h ---- BPI-Router-Linux-kernel/arch/powerpc/include/asm/book3s/64/pgtable.h 2025-10-22 13:53:23.115329604 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/powerpc/include/asm/book3s/64/pgtable.h 2025-10-22 13:53:56.375169816 -0400 -@@ -693,7 +693,7 @@ static inline pte_t pte_swp_mkexclusive( - return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_SWP_EXCLUSIVE)); - } - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return !!(pte_raw(pte) & cpu_to_be64(_PAGE_SWP_EXCLUSIVE)); - } -diff -purNx .git BPI-Router-Linux-kernel/arch/powerpc/include/asm/floppy.h BPI-Router-Linux-kernel-6.16.12/arch/powerpc/include/asm/floppy.h ---- BPI-Router-Linux-kernel/arch/powerpc/include/asm/floppy.h 2025-10-22 13:53:23.115329604 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/powerpc/include/asm/floppy.h 2025-10-22 13:53:56.375169816 -0400 -@@ -144,9 +144,12 @@ static int hard_dma_setup(char *addr, un - bus_addr = 0; - } - -- if (!bus_addr) /* need to map it */ -+ if (!bus_addr) { /* need to map it */ - bus_addr = dma_map_single(&isa_bridge_pcidev->dev, addr, size, - dir); -+ if (dma_mapping_error(&isa_bridge_pcidev->dev, bus_addr)) -+ return -ENOMEM; -+ } - - /* remember this one as prev */ - prev_addr = addr; -diff -purNx .git BPI-Router-Linux-kernel/arch/powerpc/include/asm/nohash/pgtable.h BPI-Router-Linux-kernel-6.16.12/arch/powerpc/include/asm/nohash/pgtable.h ---- BPI-Router-Linux-kernel/arch/powerpc/include/asm/nohash/pgtable.h 2025-10-22 13:53:23.115329604 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/powerpc/include/asm/nohash/pgtable.h 2025-10-22 13:53:56.375169816 -0400 -@@ -286,7 +286,7 @@ static inline pte_t pte_modify(pte_t pte - return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)); - } - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/powerpc/include/asm/ppc_asm.h BPI-Router-Linux-kernel-6.16.12/arch/powerpc/include/asm/ppc_asm.h ---- BPI-Router-Linux-kernel/arch/powerpc/include/asm/ppc_asm.h 2025-10-22 13:53:23.115329604 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/powerpc/include/asm/ppc_asm.h 2025-10-22 13:53:56.375169816 -0400 -@@ -183,7 +183,7 @@ - /* - * Used to name C functions called from asm - */ --#ifdef CONFIG_PPC_KERNEL_PCREL -+#if defined(__powerpc64__) && defined(CONFIG_PPC_KERNEL_PCREL) - #define CFUNC(name) name@notoc - #else - #define CFUNC(name) name -diff -purNx .git BPI-Router-Linux-kernel/arch/powerpc/include/uapi/asm/ioctls.h BPI-Router-Linux-kernel-6.16.12/arch/powerpc/include/uapi/asm/ioctls.h ---- BPI-Router-Linux-kernel/arch/powerpc/include/uapi/asm/ioctls.h 2025-10-22 13:53:23.115329604 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/powerpc/include/uapi/asm/ioctls.h 2025-10-22 13:53:56.375169816 -0400 -@@ -23,10 +23,10 @@ - #define TCSETSW _IOW('t', 21, struct termios) - #define TCSETSF _IOW('t', 22, struct termios) - --#define TCGETA _IOR('t', 23, struct termio) --#define TCSETA _IOW('t', 24, struct termio) --#define TCSETAW _IOW('t', 25, struct termio) --#define TCSETAF _IOW('t', 28, struct termio) -+#define TCGETA 0x40147417 /* _IOR('t', 23, struct termio) */ -+#define TCSETA 0x80147418 /* _IOW('t', 24, struct termio) */ -+#define TCSETAW 0x80147419 /* _IOW('t', 25, struct termio) */ -+#define TCSETAF 0x8014741c /* _IOW('t', 28, struct termio) */ - - #define TCSBRK _IO('t', 29) - #define TCXONC _IO('t', 30) -diff -purNx .git BPI-Router-Linux-kernel/arch/powerpc/kernel/eeh.c BPI-Router-Linux-kernel-6.16.12/arch/powerpc/kernel/eeh.c ---- BPI-Router-Linux-kernel/arch/powerpc/kernel/eeh.c 2025-10-22 13:53:23.119329585 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/powerpc/kernel/eeh.c 2025-10-22 13:53:56.375169816 -0400 -@@ -1139,6 +1139,7 @@ int eeh_unfreeze_pe(struct eeh_pe *pe) - - return ret; - } -+EXPORT_SYMBOL_GPL(eeh_unfreeze_pe); - - - static struct pci_device_id eeh_reset_ids[] = { -@@ -1509,6 +1510,8 @@ int eeh_pe_configure(struct eeh_pe *pe) - /* Invalid PE ? */ - if (!pe) - return -ENODEV; -+ else -+ ret = eeh_ops->configure_bridge(pe); - - return ret; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/powerpc/kernel/eeh_driver.c BPI-Router-Linux-kernel-6.16.12/arch/powerpc/kernel/eeh_driver.c ---- BPI-Router-Linux-kernel/arch/powerpc/kernel/eeh_driver.c 2025-10-22 13:53:23.119329585 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/powerpc/kernel/eeh_driver.c 2025-10-22 13:53:56.375169816 -0400 -@@ -257,13 +257,12 @@ static void eeh_pe_report_edev(struct ee - struct pci_driver *driver; - enum pci_ers_result new_result; - -- pci_lock_rescan_remove(); - pdev = edev->pdev; - if (pdev) - get_device(&pdev->dev); -- pci_unlock_rescan_remove(); - if (!pdev) { - eeh_edev_info(edev, "no device"); -+ *result = PCI_ERS_RESULT_DISCONNECT; - return; - } - device_lock(&pdev->dev); -@@ -304,8 +303,9 @@ static void eeh_pe_report(const char *na - struct eeh_dev *edev, *tmp; - - pr_info("EEH: Beginning: '%s'\n", name); -- eeh_for_each_pe(root, pe) eeh_pe_for_each_dev(pe, edev, tmp) -- eeh_pe_report_edev(edev, fn, result); -+ eeh_for_each_pe(root, pe) -+ eeh_pe_for_each_dev(pe, edev, tmp) -+ eeh_pe_report_edev(edev, fn, result); - if (result) - pr_info("EEH: Finished:'%s' with aggregate recovery state:'%s'\n", - name, pci_ers_result_name(*result)); -@@ -383,6 +383,8 @@ static void eeh_dev_restore_state(struct - if (!edev) - return; - -+ pci_lock_rescan_remove(); -+ - /* - * The content in the config space isn't saved because - * the blocked config space on some adapters. We have -@@ -393,14 +395,19 @@ static void eeh_dev_restore_state(struct - if (list_is_last(&edev->entry, &edev->pe->edevs)) - eeh_pe_restore_bars(edev->pe); - -+ pci_unlock_rescan_remove(); - return; - } - - pdev = eeh_dev_to_pci_dev(edev); -- if (!pdev) -+ if (!pdev) { -+ pci_unlock_rescan_remove(); - return; -+ } - - pci_restore_state(pdev); -+ -+ pci_unlock_rescan_remove(); - } - - /** -@@ -647,9 +654,7 @@ static int eeh_reset_device(struct eeh_p - if (any_passed || driver_eeh_aware || (pe->type & EEH_PE_VF)) { - eeh_pe_dev_traverse(pe, eeh_rmv_device, rmv_data); - } else { -- pci_lock_rescan_remove(); - pci_hp_remove_devices(bus); -- pci_unlock_rescan_remove(); - } - - /* -@@ -665,8 +670,6 @@ static int eeh_reset_device(struct eeh_p - if (rc) - return rc; - -- pci_lock_rescan_remove(); -- - /* Restore PE */ - eeh_ops->configure_bridge(pe); - eeh_pe_restore_bars(pe); -@@ -674,7 +677,6 @@ static int eeh_reset_device(struct eeh_p - /* Clear frozen state */ - rc = eeh_clear_pe_frozen_state(pe, false); - if (rc) { -- pci_unlock_rescan_remove(); - return rc; - } - -@@ -709,7 +711,6 @@ static int eeh_reset_device(struct eeh_p - pe->tstamp = tstamp; - pe->freeze_count = cnt; - -- pci_unlock_rescan_remove(); - return 0; - } - -@@ -843,10 +844,13 @@ void eeh_handle_normal_event(struct eeh_ - {LIST_HEAD_INIT(rmv_data.removed_vf_list), 0}; - int devices = 0; - -+ pci_lock_rescan_remove(); -+ - bus = eeh_pe_bus_get(pe); - if (!bus) { - pr_err("%s: Cannot find PCI bus for PHB#%x-PE#%x\n", - __func__, pe->phb->global_number, pe->addr); -+ pci_unlock_rescan_remove(); - return; - } - -@@ -1094,10 +1098,15 @@ recover_failed: - eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true); - eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED); - -- pci_lock_rescan_remove(); -- pci_hp_remove_devices(bus); -- pci_unlock_rescan_remove(); -+ bus = eeh_pe_bus_get(pe); -+ if (bus) -+ pci_hp_remove_devices(bus); -+ else -+ pr_err("%s: PCI bus for PHB#%x-PE#%x disappeared\n", -+ __func__, pe->phb->global_number, pe->addr); -+ - /* The passed PE should no longer be used */ -+ pci_unlock_rescan_remove(); - return; - } - -@@ -1114,6 +1123,8 @@ out: - eeh_clear_slot_attention(edev->pdev); - - eeh_pe_state_clear(pe, EEH_PE_RECOVERING, true); -+ -+ pci_unlock_rescan_remove(); - } - - /** -@@ -1132,6 +1143,7 @@ void eeh_handle_special_event(void) - unsigned long flags; - int rc; - -+ pci_lock_rescan_remove(); - - do { - rc = eeh_ops->next_error(&pe); -@@ -1171,10 +1183,12 @@ void eeh_handle_special_event(void) - - break; - case EEH_NEXT_ERR_NONE: -+ pci_unlock_rescan_remove(); - return; - default: - pr_warn("%s: Invalid value %d from next_error()\n", - __func__, rc); -+ pci_unlock_rescan_remove(); - return; - } - -@@ -1186,7 +1200,9 @@ void eeh_handle_special_event(void) - if (rc == EEH_NEXT_ERR_FROZEN_PE || - rc == EEH_NEXT_ERR_FENCED_PHB) { - eeh_pe_state_mark(pe, EEH_PE_RECOVERING); -+ pci_unlock_rescan_remove(); - eeh_handle_normal_event(pe); -+ pci_lock_rescan_remove(); - } else { - eeh_for_each_pe(pe, tmp_pe) - eeh_pe_for_each_dev(tmp_pe, edev, tmp_edev) -@@ -1199,7 +1215,6 @@ void eeh_handle_special_event(void) - eeh_report_failure, NULL); - eeh_set_channel_state(pe, pci_channel_io_perm_failure); - -- pci_lock_rescan_remove(); - list_for_each_entry(hose, &hose_list, list_node) { - phb_pe = eeh_phb_pe_get(hose); - if (!phb_pe || -@@ -1218,7 +1233,6 @@ void eeh_handle_special_event(void) - } - pci_hp_remove_devices(bus); - } -- pci_unlock_rescan_remove(); - } - - /* -@@ -1228,4 +1242,6 @@ void eeh_handle_special_event(void) - if (rc == EEH_NEXT_ERR_DEAD_IOC) - break; - } while (rc != EEH_NEXT_ERR_NONE); -+ -+ pci_unlock_rescan_remove(); - } -diff -purNx .git BPI-Router-Linux-kernel/arch/powerpc/kernel/eeh_pe.c BPI-Router-Linux-kernel-6.16.12/arch/powerpc/kernel/eeh_pe.c ---- BPI-Router-Linux-kernel/arch/powerpc/kernel/eeh_pe.c 2025-10-22 13:53:23.119329585 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/powerpc/kernel/eeh_pe.c 2025-10-22 13:53:56.375169816 -0400 -@@ -671,10 +671,12 @@ static void eeh_bridge_check_link(struct - eeh_ops->write_config(edev, cap + PCI_EXP_LNKCTL, 2, val); - - /* Check link */ -- if (!edev->pdev->link_active_reporting) { -- eeh_edev_dbg(edev, "No link reporting capability\n"); -- msleep(1000); -- return; -+ if (edev->pdev) { -+ if (!edev->pdev->link_active_reporting) { -+ eeh_edev_dbg(edev, "No link reporting capability\n"); -+ msleep(1000); -+ return; -+ } - } - - /* Wait the link is up until timeout (5s) */ -diff -purNx .git BPI-Router-Linux-kernel/arch/powerpc/kernel/kvm.c BPI-Router-Linux-kernel-6.16.12/arch/powerpc/kernel/kvm.c ---- BPI-Router-Linux-kernel/arch/powerpc/kernel/kvm.c 2025-10-22 13:53:23.119329585 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/powerpc/kernel/kvm.c 2025-10-22 13:53:56.375169816 -0400 -@@ -632,19 +632,19 @@ static void __init kvm_check_ins(u32 *in - #endif - } - -- switch (inst_no_rt & ~KVM_MASK_RB) { - #ifdef CONFIG_PPC_BOOK3S_32 -+ switch (inst_no_rt & ~KVM_MASK_RB) { - case KVM_INST_MTSRIN: - if (features & KVM_MAGIC_FEAT_SR) { - u32 inst_rb = _inst & KVM_MASK_RB; - kvm_patch_ins_mtsrin(inst, inst_rt, inst_rb); - } - break; --#endif - } -+#endif - -- switch (_inst) { - #ifdef CONFIG_BOOKE -+ switch (_inst) { - case KVM_INST_WRTEEI_0: - kvm_patch_ins_wrteei_0(inst); - break; -@@ -652,8 +652,8 @@ static void __init kvm_check_ins(u32 *in - case KVM_INST_WRTEEI_1: - kvm_patch_ins_wrtee(inst, 0, 1); - break; --#endif - } -+#endif - } - - extern u32 kvm_template_start[]; -diff -purNx .git BPI-Router-Linux-kernel/arch/powerpc/kernel/pci-hotplug.c BPI-Router-Linux-kernel-6.16.12/arch/powerpc/kernel/pci-hotplug.c ---- BPI-Router-Linux-kernel/arch/powerpc/kernel/pci-hotplug.c 2025-10-22 13:53:23.119329585 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/powerpc/kernel/pci-hotplug.c 2025-10-22 13:53:56.375169816 -0400 -@@ -141,6 +141,9 @@ void pci_hp_add_devices(struct pci_bus * - struct pci_controller *phb; - struct device_node *dn = pci_bus_to_OF_node(bus); - -+ if (!dn) -+ return; -+ - phb = pci_bus_to_host(bus); - - mode = PCI_PROBE_NORMAL; -diff -purNx .git BPI-Router-Linux-kernel/arch/powerpc/kernel/vdso/Makefile BPI-Router-Linux-kernel-6.16.12/arch/powerpc/kernel/vdso/Makefile ---- BPI-Router-Linux-kernel/arch/powerpc/kernel/vdso/Makefile 2025-10-22 13:53:23.119329585 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/powerpc/kernel/vdso/Makefile 2025-10-22 13:53:56.375169816 -0400 -@@ -53,7 +53,7 @@ ldflags-$(CONFIG_LD_ORPHAN_WARN) += -Wl, - ldflags-y += $(filter-out $(CC_AUTO_VAR_INIT_ZERO_ENABLER) $(CC_FLAGS_FTRACE) -Wa$(comma)%, $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS)) - - CC32FLAGS := -m32 --CC32FLAGSREMOVE := -mcmodel=medium -mabi=elfv1 -mabi=elfv2 -mcall-aixdesc -+CC32FLAGSREMOVE := -mcmodel=medium -mabi=elfv1 -mabi=elfv2 -mcall-aixdesc -mpcrel - ifdef CONFIG_CC_IS_CLANG - # This flag is supported by clang for 64-bit but not 32-bit so it will cause - # an unused command line flag warning for this file. -diff -purNx .git BPI-Router-Linux-kernel/arch/powerpc/platforms/512x/mpc512x_lpbfifo.c BPI-Router-Linux-kernel-6.16.12/arch/powerpc/platforms/512x/mpc512x_lpbfifo.c ---- BPI-Router-Linux-kernel/arch/powerpc/platforms/512x/mpc512x_lpbfifo.c 2025-10-22 13:53:23.119329585 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/powerpc/platforms/512x/mpc512x_lpbfifo.c 2025-10-22 13:53:56.375169816 -0400 -@@ -240,10 +240,8 @@ static int mpc512x_lpbfifo_kick(void) - dma_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - - /* Make DMA channel work with LPB FIFO data register */ -- if (dma_dev->device_config(lpbfifo.chan, &dma_conf)) { -- ret = -EINVAL; -- goto err_dma_prep; -- } -+ if (dma_dev->device_config(lpbfifo.chan, &dma_conf)) -+ return -EINVAL; - - sg_init_table(&sg, 1); - -diff -purNx .git BPI-Router-Linux-kernel/arch/powerpc/platforms/book3s/vas-api.c BPI-Router-Linux-kernel-6.16.12/arch/powerpc/platforms/book3s/vas-api.c ---- BPI-Router-Linux-kernel/arch/powerpc/platforms/book3s/vas-api.c 2025-10-22 13:53:23.119329585 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/powerpc/platforms/book3s/vas-api.c 2025-10-22 13:53:56.375169816 -0400 -@@ -521,6 +521,15 @@ static int coproc_mmap(struct file *fp, - return -EINVAL; - } - -+ /* -+ * Map complete page to the paste address. So the user -+ * space should pass 0ULL to the offset parameter. -+ */ -+ if (vma->vm_pgoff) { -+ pr_debug("Page offset unsupported to map paste address\n"); -+ return -EINVAL; -+ } -+ - /* Ensure instance has an open send window */ - if (!txwin) { - pr_err("No send window open?\n"); -diff -purNx .git BPI-Router-Linux-kernel/arch/powerpc/platforms/powernv/memtrace.c BPI-Router-Linux-kernel-6.16.12/arch/powerpc/platforms/powernv/memtrace.c ---- BPI-Router-Linux-kernel/arch/powerpc/platforms/powernv/memtrace.c 2025-10-22 13:53:23.119329585 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/powerpc/platforms/powernv/memtrace.c 2025-10-22 13:53:56.375169816 -0400 -@@ -48,11 +48,15 @@ static ssize_t memtrace_read(struct file - static int memtrace_mmap(struct file *filp, struct vm_area_struct *vma) - { - struct memtrace_entry *ent = filp->private_data; -+ unsigned long ent_nrpages = ent->size >> PAGE_SHIFT; -+ unsigned long vma_nrpages = vma_pages(vma); - -- if (ent->size < vma->vm_end - vma->vm_start) -+ /* The requested page offset should be within object's page count */ -+ if (vma->vm_pgoff >= ent_nrpages) - return -EINVAL; - -- if (vma->vm_pgoff << PAGE_SHIFT >= ent->size) -+ /* The requested mapping range should remain within the bounds */ -+ if (vma_nrpages > ent_nrpages - vma->vm_pgoff) - return -EINVAL; - - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -diff -purNx .git BPI-Router-Linux-kernel/arch/powerpc/platforms/pseries/dlpar.c BPI-Router-Linux-kernel-6.16.12/arch/powerpc/platforms/pseries/dlpar.c ---- BPI-Router-Linux-kernel/arch/powerpc/platforms/pseries/dlpar.c 2025-10-22 13:53:23.119329585 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/powerpc/platforms/pseries/dlpar.c 2025-10-22 13:53:56.375169816 -0400 -@@ -404,6 +404,45 @@ get_device_node_with_drc_info(u32 index) - return NULL; - } - -+static struct device_node * -+get_device_node_with_drc_indexes(u32 drc_index) -+{ -+ struct device_node *np = NULL; -+ u32 nr_indexes, index; -+ int i, rc; -+ -+ for_each_node_with_property(np, "ibm,drc-indexes") { -+ /* -+ * First element in the array is the total number of -+ * DRC indexes returned. -+ */ -+ rc = of_property_read_u32_index(np, "ibm,drc-indexes", -+ 0, &nr_indexes); -+ if (rc) -+ goto out_put_np; -+ -+ /* -+ * Retrieve DRC index from the list and return the -+ * device node if matched with the specified index. -+ */ -+ for (i = 0; i < nr_indexes; i++) { -+ rc = of_property_read_u32_index(np, "ibm,drc-indexes", -+ i+1, &index); -+ if (rc) -+ goto out_put_np; -+ -+ if (drc_index == index) -+ return np; -+ } -+ } -+ -+ return NULL; -+ -+out_put_np: -+ of_node_put(np); -+ return NULL; -+} -+ - static int dlpar_hp_dt_add(u32 index) - { - struct device_node *np, *nodes; -@@ -423,10 +462,19 @@ static int dlpar_hp_dt_add(u32 index) - goto out; - } - -+ /* -+ * Recent FW provides ibm,drc-info property. So search -+ * for the user specified DRC index from ibm,drc-info -+ * property. If this property is not available, search -+ * in the indexes array from ibm,drc-indexes property. -+ */ - np = get_device_node_with_drc_info(index); - -- if (!np) -- return -EIO; -+ if (!np) { -+ np = get_device_node_with_drc_indexes(index); -+ if (!np) -+ return -EIO; -+ } - - /* Next, configure the connector. */ - nodes = dlpar_configure_connector(cpu_to_be32(index), np); -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/boot/dts/sophgo/sg2044-cpus.dtsi BPI-Router-Linux-kernel-6.16.12/arch/riscv/boot/dts/sophgo/sg2044-cpus.dtsi ---- BPI-Router-Linux-kernel/arch/riscv/boot/dts/sophgo/sg2044-cpus.dtsi 2025-10-22 13:53:23.119329585 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/boot/dts/sophgo/sg2044-cpus.dtsi 2025-10-22 13:53:56.375169816 -0400 -@@ -38,6 +38,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu0_intc: interrupt-controller { -@@ -73,6 +74,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu1_intc: interrupt-controller { -@@ -108,6 +110,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu2_intc: interrupt-controller { -@@ -143,6 +146,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu3_intc: interrupt-controller { -@@ -178,6 +182,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu4_intc: interrupt-controller { -@@ -213,6 +218,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu5_intc: interrupt-controller { -@@ -248,6 +254,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu6_intc: interrupt-controller { -@@ -283,6 +290,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu7_intc: interrupt-controller { -@@ -318,6 +326,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu8_intc: interrupt-controller { -@@ -353,6 +362,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu9_intc: interrupt-controller { -@@ -388,6 +398,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu10_intc: interrupt-controller { -@@ -423,6 +434,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu11_intc: interrupt-controller { -@@ -458,6 +470,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu12_intc: interrupt-controller { -@@ -493,6 +506,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu13_intc: interrupt-controller { -@@ -528,6 +542,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu14_intc: interrupt-controller { -@@ -563,6 +578,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu15_intc: interrupt-controller { -@@ -598,6 +614,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu16_intc: interrupt-controller { -@@ -633,6 +650,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu17_intc: interrupt-controller { -@@ -668,6 +686,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu18_intc: interrupt-controller { -@@ -703,6 +722,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu19_intc: interrupt-controller { -@@ -738,6 +758,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu20_intc: interrupt-controller { -@@ -773,6 +794,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu21_intc: interrupt-controller { -@@ -808,6 +830,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu22_intc: interrupt-controller { -@@ -843,6 +866,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu23_intc: interrupt-controller { -@@ -878,6 +902,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu24_intc: interrupt-controller { -@@ -913,6 +938,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu25_intc: interrupt-controller { -@@ -948,6 +974,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu26_intc: interrupt-controller { -@@ -983,6 +1010,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu27_intc: interrupt-controller { -@@ -1018,6 +1046,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu28_intc: interrupt-controller { -@@ -1053,6 +1082,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu29_intc: interrupt-controller { -@@ -1088,6 +1118,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu30_intc: interrupt-controller { -@@ -1123,6 +1154,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu31_intc: interrupt-controller { -@@ -1158,6 +1190,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu32_intc: interrupt-controller { -@@ -1193,6 +1226,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu33_intc: interrupt-controller { -@@ -1228,6 +1262,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu34_intc: interrupt-controller { -@@ -1263,6 +1298,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu35_intc: interrupt-controller { -@@ -1298,6 +1334,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu36_intc: interrupt-controller { -@@ -1333,6 +1370,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu37_intc: interrupt-controller { -@@ -1368,6 +1406,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu38_intc: interrupt-controller { -@@ -1403,6 +1442,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu39_intc: interrupt-controller { -@@ -1438,6 +1478,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu40_intc: interrupt-controller { -@@ -1473,6 +1514,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu41_intc: interrupt-controller { -@@ -1508,6 +1550,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu42_intc: interrupt-controller { -@@ -1543,6 +1586,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu43_intc: interrupt-controller { -@@ -1578,6 +1622,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu44_intc: interrupt-controller { -@@ -1613,6 +1658,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu45_intc: interrupt-controller { -@@ -1648,6 +1694,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu46_intc: interrupt-controller { -@@ -1683,6 +1730,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu47_intc: interrupt-controller { -@@ -1718,6 +1766,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu48_intc: interrupt-controller { -@@ -1753,6 +1802,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu49_intc: interrupt-controller { -@@ -1788,6 +1838,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu50_intc: interrupt-controller { -@@ -1823,6 +1874,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu51_intc: interrupt-controller { -@@ -1858,6 +1910,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu52_intc: interrupt-controller { -@@ -1893,6 +1946,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu53_intc: interrupt-controller { -@@ -1928,6 +1982,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu54_intc: interrupt-controller { -@@ -1963,6 +2018,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu55_intc: interrupt-controller { -@@ -1998,6 +2054,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu56_intc: interrupt-controller { -@@ -2033,6 +2090,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu57_intc: interrupt-controller { -@@ -2068,6 +2126,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu58_intc: interrupt-controller { -@@ -2103,6 +2162,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu59_intc: interrupt-controller { -@@ -2138,6 +2198,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu60_intc: interrupt-controller { -@@ -2173,6 +2234,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu61_intc: interrupt-controller { -@@ -2208,6 +2270,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu62_intc: interrupt-controller { -@@ -2243,6 +2306,7 @@ - "zvfbfmin", "zvfbfwma", "zvfh", - "zvfhmin"; - riscv,cbom-block-size = <64>; -+ riscv,cbop-block-size = <64>; - riscv,cboz-block-size = <64>; - - cpu63_intc: interrupt-controller { -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/boot/dts/thead/th1520.dtsi BPI-Router-Linux-kernel-6.16.12/arch/riscv/boot/dts/thead/th1520.dtsi ---- BPI-Router-Linux-kernel/arch/riscv/boot/dts/thead/th1520.dtsi 2025-10-22 13:53:23.119329585 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/boot/dts/thead/th1520.dtsi 2025-10-22 13:53:56.375169816 -0400 -@@ -294,8 +294,9 @@ - reg-names = "dwmac", "apb"; - interrupts = <67 IRQ_TYPE_LEVEL_HIGH>; - interrupt-names = "macirq"; -- clocks = <&clk CLK_GMAC_AXI>, <&clk CLK_GMAC1>; -- clock-names = "stmmaceth", "pclk"; -+ clocks = <&clk CLK_GMAC_AXI>, <&clk CLK_GMAC1>, -+ <&clk CLK_PERISYS_APB4_HCLK>; -+ clock-names = "stmmaceth", "pclk", "apb"; - snps,pbl = <32>; - snps,fixed-burst; - snps,multicast-filter-bins = <64>; -@@ -316,8 +317,9 @@ - reg-names = "dwmac", "apb"; - interrupts = <66 IRQ_TYPE_LEVEL_HIGH>; - interrupt-names = "macirq"; -- clocks = <&clk CLK_GMAC_AXI>, <&clk CLK_GMAC0>; -- clock-names = "stmmaceth", "pclk"; -+ clocks = <&clk CLK_GMAC_AXI>, <&clk CLK_GMAC0>, -+ <&clk CLK_PERISYS_APB4_HCLK>; -+ clock-names = "stmmaceth", "pclk", "apb"; - snps,pbl = <32>; - snps,fixed-burst; - snps,multicast-filter-bins = <64>; -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/include/asm/asm.h BPI-Router-Linux-kernel-6.16.12/arch/riscv/include/asm/asm.h ---- BPI-Router-Linux-kernel/arch/riscv/include/asm/asm.h 2025-10-22 13:53:23.119329585 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/include/asm/asm.h 2025-10-22 13:53:56.375169816 -0400 -@@ -91,7 +91,7 @@ - #endif - - .macro asm_per_cpu dst sym tmp -- REG_L \tmp, TASK_TI_CPU_NUM(tp) -+ lw \tmp, TASK_TI_CPU_NUM(tp) - slli \tmp, \tmp, PER_CPU_OFFSET_SHIFT - la \dst, __per_cpu_offset - add \dst, \dst, \tmp -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/include/asm/kvm_aia.h BPI-Router-Linux-kernel-6.16.12/arch/riscv/include/asm/kvm_aia.h ---- BPI-Router-Linux-kernel/arch/riscv/include/asm/kvm_aia.h 2025-10-22 13:53:23.119329585 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/include/asm/kvm_aia.h 2025-10-22 13:53:56.375169816 -0400 -@@ -87,6 +87,9 @@ DECLARE_STATIC_KEY_FALSE(kvm_riscv_aia_a - - extern struct kvm_device_ops kvm_riscv_aia_device_ops; - -+bool kvm_riscv_vcpu_aia_imsic_has_interrupt(struct kvm_vcpu *vcpu); -+void kvm_riscv_vcpu_aia_imsic_load(struct kvm_vcpu *vcpu, int cpu); -+void kvm_riscv_vcpu_aia_imsic_put(struct kvm_vcpu *vcpu); - void kvm_riscv_vcpu_aia_imsic_release(struct kvm_vcpu *vcpu); - int kvm_riscv_vcpu_aia_imsic_update(struct kvm_vcpu *vcpu); - -@@ -161,7 +164,6 @@ void kvm_riscv_aia_destroy_vm(struct kvm - int kvm_riscv_aia_alloc_hgei(int cpu, struct kvm_vcpu *owner, - void __iomem **hgei_va, phys_addr_t *hgei_pa); - void kvm_riscv_aia_free_hgei(int cpu, int hgei); --void kvm_riscv_aia_wakeon_hgei(struct kvm_vcpu *owner, bool enable); - - void kvm_riscv_aia_enable(void); - void kvm_riscv_aia_disable(void); -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/include/asm/kvm_host.h BPI-Router-Linux-kernel-6.16.12/arch/riscv/include/asm/kvm_host.h ---- BPI-Router-Linux-kernel/arch/riscv/include/asm/kvm_host.h 2025-10-22 13:53:23.119329585 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/include/asm/kvm_host.h 2025-10-22 13:53:56.375169816 -0400 -@@ -306,6 +306,9 @@ static inline bool kvm_arch_pmi_in_guest - return IS_ENABLED(CONFIG_GUEST_PERF_EVENTS) && !!vcpu; - } - -+static inline void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu) {} -+static inline void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) {} -+ - #define KVM_RISCV_GSTAGE_TLB_MIN_ORDER 12 - - void kvm_riscv_local_hfence_gvma_vmid_gpa(unsigned long vmid, -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/include/asm/pgtable.h BPI-Router-Linux-kernel-6.16.12/arch/riscv/include/asm/pgtable.h ---- BPI-Router-Linux-kernel/arch/riscv/include/asm/pgtable.h 2025-10-22 13:53:23.119329585 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/include/asm/pgtable.h 2025-10-22 13:53:56.379169797 -0400 -@@ -964,6 +964,23 @@ static inline int pudp_test_and_clear_yo - return ptep_test_and_clear_young(vma, address, (pte_t *)pudp); - } - -+#define __HAVE_ARCH_PUDP_HUGE_GET_AND_CLEAR -+static inline pud_t pudp_huge_get_and_clear(struct mm_struct *mm, -+ unsigned long address, pud_t *pudp) -+{ -+#ifdef CONFIG_SMP -+ pud_t pud = __pud(xchg(&pudp->pud, 0)); -+#else -+ pud_t pud = *pudp; -+ -+ pud_clear(pudp); -+#endif -+ -+ page_table_check_pud_clear(mm, pud); -+ -+ return pud; -+} -+ - static inline int pud_young(pud_t pud) - { - return pte_young(pud_pte(pud)); -@@ -1028,7 +1045,7 @@ static inline pud_t pud_modify(pud_t pud - #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) - #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; - } -@@ -1075,7 +1092,6 @@ static inline pte_t pte_swp_clear_exclus - */ - #ifdef CONFIG_64BIT - #define TASK_SIZE_64 (PGDIR_SIZE * PTRS_PER_PGD / 2) --#define TASK_SIZE_MAX LONG_MAX - - #ifdef CONFIG_COMPAT - #define TASK_SIZE_32 (_AC(0x80000000, UL) - PAGE_SIZE) -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/include/asm/runtime-const.h BPI-Router-Linux-kernel-6.16.12/arch/riscv/include/asm/runtime-const.h ---- BPI-Router-Linux-kernel/arch/riscv/include/asm/runtime-const.h 2025-10-22 13:53:23.119329585 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/include/asm/runtime-const.h 2025-10-22 13:53:56.379169797 -0400 -@@ -206,7 +206,7 @@ static inline void __runtime_fixup_32(__ - addi_insn_mask &= 0x07fff; - } - -- if (lower_immediate & 0x00000fff) { -+ if (lower_immediate & 0x00000fff || lui_insn == RISCV_INSN_NOP4) { - /* replace upper 12 bits of addi with lower 12 bits of val */ - addi_insn &= addi_insn_mask; - addi_insn |= (lower_immediate & 0x00000fff) << 20; -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/include/asm/uaccess.h BPI-Router-Linux-kernel-6.16.12/arch/riscv/include/asm/uaccess.h ---- BPI-Router-Linux-kernel/arch/riscv/include/asm/uaccess.h 2025-10-22 13:53:23.119329585 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/include/asm/uaccess.h 2025-10-22 13:53:56.379169797 -0400 -@@ -127,6 +127,7 @@ do { \ - - #ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT - #define __get_user_8(x, ptr, label) \ -+do { \ - u32 __user *__ptr = (u32 __user *)(ptr); \ - u32 __lo, __hi; \ - asm_goto_output( \ -@@ -141,7 +142,7 @@ do { \ - : : label); \ - (x) = (__typeof__(x))((__typeof__((x) - (x)))( \ - (((u64)__hi << 32) | __lo))); \ -- -+} while (0) - #else /* !CONFIG_CC_HAS_ASM_GOTO_OUTPUT */ - #define __get_user_8(x, ptr, label) \ - do { \ -@@ -208,7 +209,7 @@ do { \ - err = 0; \ - break; \ - __gu_failed: \ -- x = 0; \ -+ x = (__typeof__(x))0; \ - err = -EFAULT; \ - } while (0) - -@@ -310,8 +311,8 @@ do { \ - do { \ - if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && \ - !IS_ALIGNED((uintptr_t)__gu_ptr, sizeof(*__gu_ptr))) { \ -- __inttype(x) val = (__inttype(x))x; \ -- if (__asm_copy_to_user_sum_enabled(__gu_ptr, &(val), sizeof(*__gu_ptr))) \ -+ __typeof__(*(__gu_ptr)) ___val = (x); \ -+ if (__asm_copy_to_user_sum_enabled(__gu_ptr, &(___val), sizeof(*__gu_ptr))) \ - goto label; \ - break; \ - } \ -@@ -437,10 +438,10 @@ unsigned long __must_check clear_user(vo - } - - #define __get_kernel_nofault(dst, src, type, err_label) \ -- __get_user_nocheck(*((type *)(dst)), (type *)(src), err_label) -+ __get_user_nocheck(*((type *)(dst)), (__force __user type *)(src), err_label) - - #define __put_kernel_nofault(dst, src, type, err_label) \ -- __put_user_nocheck(*((type *)(src)), (type *)(dst), err_label) -+ __put_user_nocheck(*((type *)(src)), (__force __user type *)(dst), err_label) - - static __must_check __always_inline bool user_access_begin(const void __user *ptr, size_t len) - { -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/include/asm/vdso/getrandom.h BPI-Router-Linux-kernel-6.16.12/arch/riscv/include/asm/vdso/getrandom.h ---- BPI-Router-Linux-kernel/arch/riscv/include/asm/vdso/getrandom.h 2025-10-22 13:53:23.119329585 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/include/asm/vdso/getrandom.h 2025-10-22 13:53:56.379169797 -0400 -@@ -18,7 +18,7 @@ static __always_inline ssize_t getrandom - register unsigned int flags asm("a2") = _flags; - - asm volatile ("ecall\n" -- : "+r" (ret) -+ : "=r" (ret) - : "r" (nr), "r" (buffer), "r" (len), "r" (flags) - : "memory"); - -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/include/asm/vector.h BPI-Router-Linux-kernel-6.16.12/arch/riscv/include/asm/vector.h ---- BPI-Router-Linux-kernel/arch/riscv/include/asm/vector.h 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/include/asm/vector.h 2025-10-22 13:53:56.379169797 -0400 -@@ -205,11 +205,11 @@ static inline void __riscv_v_vstate_save - THEAD_VSETVLI_T4X0E8M8D1 - THEAD_VSB_V_V0T0 - "add t0, t0, t4\n\t" -- THEAD_VSB_V_V0T0 -+ THEAD_VSB_V_V8T0 - "add t0, t0, t4\n\t" -- THEAD_VSB_V_V0T0 -+ THEAD_VSB_V_V16T0 - "add t0, t0, t4\n\t" -- THEAD_VSB_V_V0T0 -+ THEAD_VSB_V_V24T0 - : : "r" (datap) : "memory", "t0", "t4"); - } else { - asm volatile ( -@@ -241,11 +241,11 @@ static inline void __riscv_v_vstate_rest - THEAD_VSETVLI_T4X0E8M8D1 - THEAD_VLB_V_V0T0 - "add t0, t0, t4\n\t" -- THEAD_VLB_V_V0T0 -+ THEAD_VLB_V_V8T0 - "add t0, t0, t4\n\t" -- THEAD_VLB_V_V0T0 -+ THEAD_VLB_V_V16T0 - "add t0, t0, t4\n\t" -- THEAD_VLB_V_V0T0 -+ THEAD_VLB_V_V24T0 - : : "r" (datap) : "memory", "t0", "t4"); - } else { - asm volatile ( -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/Kconfig BPI-Router-Linux-kernel-6.16.12/arch/riscv/Kconfig ---- BPI-Router-Linux-kernel/arch/riscv/Kconfig 2025-10-22 13:53:23.119329585 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/Kconfig 2025-10-22 13:53:56.375169816 -0400 -@@ -63,12 +63,13 @@ config RISCV - select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT - select ARCH_STACKWALK - select ARCH_SUPPORTS_ATOMIC_RMW -- select ARCH_SUPPORTS_CFI_CLANG -+ # clang >= 17: https://github.com/llvm/llvm-project/commit/62fa708ceb027713b386c7e0efda994f8bdc27e2 -+ select ARCH_SUPPORTS_CFI_CLANG if CLANG_VERSION >= 170000 - select ARCH_SUPPORTS_DEBUG_PAGEALLOC if MMU - select ARCH_SUPPORTS_HUGE_PFNMAP if TRANSPARENT_HUGEPAGE - select ARCH_SUPPORTS_HUGETLBFS if MMU - # LLD >= 14: https://github.com/llvm/llvm-project/issues/50505 -- select ARCH_SUPPORTS_LTO_CLANG if LLD_VERSION >= 140000 -+ select ARCH_SUPPORTS_LTO_CLANG if LLD_VERSION >= 140000 && CMODEL_MEDANY - select ARCH_SUPPORTS_LTO_CLANG_THIN if LLD_VERSION >= 140000 - select ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS if 64BIT && MMU - select ARCH_SUPPORTS_PAGE_TABLE_CHECK if MMU -@@ -97,6 +98,7 @@ config RISCV - select CLONE_BACKWARDS - select COMMON_CLK - select CPU_PM if CPU_IDLE || HIBERNATION || SUSPEND -+ select DYNAMIC_FTRACE if FUNCTION_TRACER - select EDAC_SUPPORT - select FRAME_POINTER if PERF_EVENTS || (FUNCTION_TRACER && !DYNAMIC_FTRACE) - select FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY if DYNAMIC_FTRACE -@@ -161,7 +163,7 @@ config RISCV - select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL - select HAVE_FUNCTION_GRAPH_TRACER if HAVE_DYNAMIC_FTRACE_WITH_ARGS - select HAVE_FUNCTION_GRAPH_FREGS -- select HAVE_FUNCTION_TRACER if !XIP_KERNEL -+ select HAVE_FUNCTION_TRACER if !XIP_KERNEL && HAVE_DYNAMIC_FTRACE - select HAVE_EBPF_JIT if MMU - select HAVE_GUP_FAST if MMU - select HAVE_FUNCTION_ARG_ACCESS_API -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/kernel/cpu_ops_sbi.c BPI-Router-Linux-kernel-6.16.12/arch/riscv/kernel/cpu_ops_sbi.c ---- BPI-Router-Linux-kernel/arch/riscv/kernel/cpu_ops_sbi.c 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/kernel/cpu_ops_sbi.c 2025-10-22 13:53:56.379169797 -0400 -@@ -18,10 +18,10 @@ const struct cpu_operations cpu_ops_sbi; - - /* - * Ordered booting via HSM brings one cpu at a time. However, cpu hotplug can -- * be invoked from multiple threads in parallel. Define a per cpu data -+ * be invoked from multiple threads in parallel. Define an array of boot data - * to handle that. - */ --static DEFINE_PER_CPU(struct sbi_hart_boot_data, boot_data); -+static struct sbi_hart_boot_data boot_data[NR_CPUS]; - - static int sbi_hsm_hart_start(unsigned long hartid, unsigned long saddr, - unsigned long priv) -@@ -67,7 +67,7 @@ static int sbi_cpu_start(unsigned int cp - unsigned long boot_addr = __pa_symbol(secondary_start_sbi); - unsigned long hartid = cpuid_to_hartid_map(cpuid); - unsigned long hsm_data; -- struct sbi_hart_boot_data *bdata = &per_cpu(boot_data, cpuid); -+ struct sbi_hart_boot_data *bdata = &boot_data[cpuid]; - - /* Make sure tidle is updated */ - smp_mb(); -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/kernel/entry.S BPI-Router-Linux-kernel-6.16.12/arch/riscv/kernel/entry.S ---- BPI-Router-Linux-kernel/arch/riscv/kernel/entry.S 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/kernel/entry.S 2025-10-22 13:53:56.379169797 -0400 -@@ -46,7 +46,7 @@ - * a0 = &new_vmalloc[BIT_WORD(cpu)] - * a1 = BIT_MASK(cpu) - */ -- REG_L a2, TASK_TI_CPU(tp) -+ lw a2, TASK_TI_CPU(tp) - /* - * Compute the new_vmalloc element position: - * (cpu / 64) * 8 = (cpu >> 6) << 3 -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/kernel/ftrace.c BPI-Router-Linux-kernel-6.16.12/arch/riscv/kernel/ftrace.c ---- BPI-Router-Linux-kernel/arch/riscv/kernel/ftrace.c 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/kernel/ftrace.c 2025-10-22 13:53:56.379169797 -0400 -@@ -14,6 +14,18 @@ - #include - - #ifdef CONFIG_DYNAMIC_FTRACE -+void ftrace_arch_code_modify_prepare(void) -+ __acquires(&text_mutex) -+{ -+ mutex_lock(&text_mutex); -+} -+ -+void ftrace_arch_code_modify_post_process(void) -+ __releases(&text_mutex) -+{ -+ mutex_unlock(&text_mutex); -+} -+ - unsigned long ftrace_call_adjust(unsigned long addr) - { - if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS)) -@@ -29,10 +41,8 @@ unsigned long arch_ftrace_get_symaddr(un - - void arch_ftrace_update_code(int command) - { -- mutex_lock(&text_mutex); - command |= FTRACE_MAY_SLEEP; - ftrace_modify_all_code(command); -- mutex_unlock(&text_mutex); - flush_icache_all(); - } - -@@ -149,6 +159,8 @@ int ftrace_init_nop(struct module *mod, - unsigned int nops[2], offset; - int ret; - -+ guard(mutex)(&text_mutex); -+ - ret = ftrace_rec_set_nop_ops(rec); - if (ret) - return ret; -@@ -157,9 +169,7 @@ int ftrace_init_nop(struct module *mod, - nops[0] = to_auipc_t0(offset); - nops[1] = RISCV_INSN_NOP4; - -- mutex_lock(&text_mutex); - ret = patch_insn_write((void *)pc, nops, 2 * MCOUNT_INSN_SIZE); -- mutex_unlock(&text_mutex); - - return ret; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/kernel/kexec_elf.c BPI-Router-Linux-kernel-6.16.12/arch/riscv/kernel/kexec_elf.c ---- BPI-Router-Linux-kernel/arch/riscv/kernel/kexec_elf.c 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/kernel/kexec_elf.c 2025-10-22 13:53:56.379169797 -0400 -@@ -28,7 +28,7 @@ static int riscv_kexec_elf_load(struct k - int i; - int ret = 0; - size_t size; -- struct kexec_buf kbuf; -+ struct kexec_buf kbuf = {}; - const struct elf_phdr *phdr; - - kbuf.image = image; -@@ -66,7 +66,7 @@ static int elf_find_pbase(struct kimage - { - int i; - int ret; -- struct kexec_buf kbuf; -+ struct kexec_buf kbuf = {}; - const struct elf_phdr *phdr; - unsigned long lowest_paddr = ULONG_MAX; - unsigned long lowest_vaddr = ULONG_MAX; -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/kernel/kexec_image.c BPI-Router-Linux-kernel-6.16.12/arch/riscv/kernel/kexec_image.c ---- BPI-Router-Linux-kernel/arch/riscv/kernel/kexec_image.c 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/kernel/kexec_image.c 2025-10-22 13:53:56.379169797 -0400 -@@ -41,7 +41,7 @@ static void *image_load(struct kimage *i - struct riscv_image_header *h; - u64 flags; - bool be_image, be_kernel; -- struct kexec_buf kbuf; -+ struct kexec_buf kbuf = {}; - int ret; - - /* Check Image header */ -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/kernel/machine_kexec_file.c BPI-Router-Linux-kernel-6.16.12/arch/riscv/kernel/machine_kexec_file.c ---- BPI-Router-Linux-kernel/arch/riscv/kernel/machine_kexec_file.c 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/kernel/machine_kexec_file.c 2025-10-22 13:53:56.379169797 -0400 -@@ -261,7 +261,7 @@ int load_extra_segments(struct kimage *i - int ret; - void *fdt; - unsigned long initrd_pbase = 0UL; -- struct kexec_buf kbuf; -+ struct kexec_buf kbuf = {}; - char *modified_cmdline = NULL; - - kbuf.image = image; -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/kernel/setup.c BPI-Router-Linux-kernel-6.16.12/arch/riscv/kernel/setup.c ---- BPI-Router-Linux-kernel/arch/riscv/kernel/setup.c 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/kernel/setup.c 2025-10-22 13:53:56.379169797 -0400 -@@ -50,6 +50,7 @@ atomic_t hart_lottery __section(".sdata" - #endif - ; - unsigned long boot_cpu_hartid; -+EXPORT_SYMBOL_GPL(boot_cpu_hartid); - - /* - * Place kernel memory regions on the resource tree so that -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/kernel/traps.c BPI-Router-Linux-kernel-6.16.12/arch/riscv/kernel/traps.c ---- BPI-Router-Linux-kernel/arch/riscv/kernel/traps.c 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/kernel/traps.c 2025-10-22 13:53:56.379169797 -0400 -@@ -6,6 +6,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -151,7 +152,9 @@ asmlinkage __visible __trap_section void - { \ - if (user_mode(regs)) { \ - irqentry_enter_from_user_mode(regs); \ -+ local_irq_enable(); \ - do_trap_error(regs, signo, code, regs->epc, "Oops - " str); \ -+ local_irq_disable(); \ - irqentry_exit_to_user_mode(regs); \ - } else { \ - irqentry_state_t state = irqentry_nmi_enter(regs); \ -@@ -173,17 +176,14 @@ asmlinkage __visible __trap_section void - - if (user_mode(regs)) { - irqentry_enter_from_user_mode(regs); -- - local_irq_enable(); - - handled = riscv_v_first_use_handler(regs); -- -- local_irq_disable(); -- - if (!handled) - do_trap_error(regs, SIGILL, ILL_ILLOPC, regs->epc, - "Oops - illegal instruction"); - -+ local_irq_disable(); - irqentry_exit_to_user_mode(regs); - } else { - irqentry_state_t state = irqentry_nmi_enter(regs); -@@ -308,9 +308,11 @@ asmlinkage __visible __trap_section void - { - if (user_mode(regs)) { - irqentry_enter_from_user_mode(regs); -+ local_irq_enable(); - - handle_break(regs); - -+ local_irq_disable(); - irqentry_exit_to_user_mode(regs); - } else { - irqentry_state_t state = irqentry_nmi_enter(regs); -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/kernel/traps_misaligned.c BPI-Router-Linux-kernel-6.16.12/arch/riscv/kernel/traps_misaligned.c ---- BPI-Router-Linux-kernel/arch/riscv/kernel/traps_misaligned.c 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/kernel/traps_misaligned.c 2025-10-22 13:53:56.379169797 -0400 -@@ -454,14 +454,14 @@ static int handle_scalar_misaligned_load - - val.data_u64 = 0; - if (user_mode(regs)) { -- if (copy_from_user_nofault(&val, (u8 __user *)addr, len)) -+ if (copy_from_user(&val, (u8 __user *)addr, len)) - return -1; - } else { - memcpy(&val, (u8 *)addr, len); - } - - if (!fp) -- SET_RD(insn, regs, val.data_ulong << shift >> shift); -+ SET_RD(insn, regs, (long)(val.data_ulong << shift) >> shift); - else if (len == 8) - set_f64_rd(insn, regs, val.data_u64); - else -@@ -555,7 +555,7 @@ static int handle_scalar_misaligned_stor - return -EOPNOTSUPP; - - if (user_mode(regs)) { -- if (copy_to_user_nofault((u8 __user *)addr, &val, len)) -+ if (copy_to_user((u8 __user *)addr, &val, len)) - return -1; - } else { - memcpy((u8 *)addr, &val, len); -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/kernel/vdso/vdso.lds.S BPI-Router-Linux-kernel-6.16.12/arch/riscv/kernel/vdso/vdso.lds.S ---- BPI-Router-Linux-kernel/arch/riscv/kernel/vdso/vdso.lds.S 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/kernel/vdso/vdso.lds.S 2025-10-22 13:53:56.379169797 -0400 -@@ -30,7 +30,7 @@ SECTIONS - *(.data .data.* .gnu.linkonce.d.*) - *(.dynbss) - *(.bss .bss.* .gnu.linkonce.b.*) -- } -+ } :text - - .note : { *(.note.*) } :text :note - -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/kernel/vendor_extensions/sifive.c BPI-Router-Linux-kernel-6.16.12/arch/riscv/kernel/vendor_extensions/sifive.c ---- BPI-Router-Linux-kernel/arch/riscv/kernel/vendor_extensions/sifive.c 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/kernel/vendor_extensions/sifive.c 2025-10-22 13:53:56.379169797 -0400 -@@ -8,7 +8,7 @@ - #include - - /* All SiFive vendor extensions supported in Linux */ --const struct riscv_isa_ext_data riscv_isa_vendor_ext_sifive[] = { -+static const struct riscv_isa_ext_data riscv_isa_vendor_ext_sifive[] = { - __RISCV_ISA_EXT_DATA(xsfvfnrclipxfqf, RISCV_ISA_VENDOR_EXT_XSFVFNRCLIPXFQF), - __RISCV_ISA_EXT_DATA(xsfvfwmaccqqq, RISCV_ISA_VENDOR_EXT_XSFVFWMACCQQQ), - __RISCV_ISA_EXT_DATA(xsfvqmaccdod, RISCV_ISA_VENDOR_EXT_XSFVQMACCDOD), -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/kvm/aia.c BPI-Router-Linux-kernel-6.16.12/arch/riscv/kvm/aia.c ---- BPI-Router-Linux-kernel/arch/riscv/kvm/aia.c 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/kvm/aia.c 2025-10-22 13:53:56.379169797 -0400 -@@ -30,28 +30,6 @@ unsigned int kvm_riscv_aia_nr_hgei; - unsigned int kvm_riscv_aia_max_ids; - DEFINE_STATIC_KEY_FALSE(kvm_riscv_aia_available); - --static int aia_find_hgei(struct kvm_vcpu *owner) --{ -- int i, hgei; -- unsigned long flags; -- struct aia_hgei_control *hgctrl = get_cpu_ptr(&aia_hgei); -- -- raw_spin_lock_irqsave(&hgctrl->lock, flags); -- -- hgei = -1; -- for (i = 1; i <= kvm_riscv_aia_nr_hgei; i++) { -- if (hgctrl->owners[i] == owner) { -- hgei = i; -- break; -- } -- } -- -- raw_spin_unlock_irqrestore(&hgctrl->lock, flags); -- -- put_cpu_ptr(&aia_hgei); -- return hgei; --} -- - static inline unsigned long aia_hvictl_value(bool ext_irq_pending) - { - unsigned long hvictl; -@@ -95,7 +73,6 @@ void kvm_riscv_vcpu_aia_sync_interrupts( - - bool kvm_riscv_vcpu_aia_has_interrupts(struct kvm_vcpu *vcpu, u64 mask) - { -- int hgei; - unsigned long seip; - - if (!kvm_riscv_aia_available()) -@@ -114,11 +91,7 @@ bool kvm_riscv_vcpu_aia_has_interrupts(s - if (!kvm_riscv_aia_initialized(vcpu->kvm) || !seip) - return false; - -- hgei = aia_find_hgei(vcpu); -- if (hgei > 0) -- return !!(ncsr_read(CSR_HGEIP) & BIT(hgei)); -- -- return false; -+ return kvm_riscv_vcpu_aia_imsic_has_interrupt(vcpu); - } - - void kvm_riscv_vcpu_aia_update_hvip(struct kvm_vcpu *vcpu) -@@ -164,6 +137,9 @@ void kvm_riscv_vcpu_aia_load(struct kvm_ - csr_write(CSR_HVIPRIO2H, csr->hviprio2h); - #endif - } -+ -+ if (kvm_riscv_aia_initialized(vcpu->kvm)) -+ kvm_riscv_vcpu_aia_imsic_load(vcpu, cpu); - } - - void kvm_riscv_vcpu_aia_put(struct kvm_vcpu *vcpu) -@@ -174,6 +150,9 @@ void kvm_riscv_vcpu_aia_put(struct kvm_v - if (!kvm_riscv_aia_available()) - return; - -+ if (kvm_riscv_aia_initialized(vcpu->kvm)) -+ kvm_riscv_vcpu_aia_imsic_put(vcpu); -+ - if (kvm_riscv_nacl_available()) { - nsh = nacl_shmem(); - csr->vsiselect = nacl_csr_read(nsh, CSR_VSISELECT); -@@ -472,22 +451,6 @@ void kvm_riscv_aia_free_hgei(int cpu, in - raw_spin_unlock_irqrestore(&hgctrl->lock, flags); - } - --void kvm_riscv_aia_wakeon_hgei(struct kvm_vcpu *owner, bool enable) --{ -- int hgei; -- -- if (!kvm_riscv_aia_available()) -- return; -- -- hgei = aia_find_hgei(owner); -- if (hgei > 0) { -- if (enable) -- csr_set(CSR_HGEIE, BIT(hgei)); -- else -- csr_clear(CSR_HGEIE, BIT(hgei)); -- } --} -- - static irqreturn_t hgei_interrupt(int irq, void *dev_id) - { - int i; -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/kvm/aia_imsic.c BPI-Router-Linux-kernel-6.16.12/arch/riscv/kvm/aia_imsic.c ---- BPI-Router-Linux-kernel/arch/riscv/kvm/aia_imsic.c 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/kvm/aia_imsic.c 2025-10-22 13:53:56.379169797 -0400 -@@ -676,6 +676,48 @@ static void imsic_swfile_update(struct k - imsic_swfile_extirq_update(vcpu); - } - -+bool kvm_riscv_vcpu_aia_imsic_has_interrupt(struct kvm_vcpu *vcpu) -+{ -+ struct imsic *imsic = vcpu->arch.aia_context.imsic_state; -+ unsigned long flags; -+ bool ret = false; -+ -+ /* -+ * The IMSIC SW-file directly injects interrupt via hvip so -+ * only check for interrupt when IMSIC VS-file is being used. -+ */ -+ -+ read_lock_irqsave(&imsic->vsfile_lock, flags); -+ if (imsic->vsfile_cpu > -1) -+ ret = !!(csr_read(CSR_HGEIP) & BIT(imsic->vsfile_hgei)); -+ read_unlock_irqrestore(&imsic->vsfile_lock, flags); -+ -+ return ret; -+} -+ -+void kvm_riscv_vcpu_aia_imsic_load(struct kvm_vcpu *vcpu, int cpu) -+{ -+ /* -+ * No need to explicitly clear HGEIE CSR bits because the -+ * hgei interrupt handler (aka hgei_interrupt()) will always -+ * clear it for us. -+ */ -+} -+ -+void kvm_riscv_vcpu_aia_imsic_put(struct kvm_vcpu *vcpu) -+{ -+ struct imsic *imsic = vcpu->arch.aia_context.imsic_state; -+ unsigned long flags; -+ -+ if (!kvm_vcpu_is_blocking(vcpu)) -+ return; -+ -+ read_lock_irqsave(&imsic->vsfile_lock, flags); -+ if (imsic->vsfile_cpu > -1) -+ csr_set(CSR_HGEIE, BIT(imsic->vsfile_hgei)); -+ read_unlock_irqrestore(&imsic->vsfile_lock, flags); -+} -+ - void kvm_riscv_vcpu_aia_imsic_release(struct kvm_vcpu *vcpu) - { - unsigned long flags; -@@ -781,6 +823,9 @@ int kvm_riscv_vcpu_aia_imsic_update(stru - * producers to the new IMSIC VS-file. - */ - -+ /* Ensure HGEIE CSR bit is zero before using the new IMSIC VS-file */ -+ csr_clear(CSR_HGEIE, BIT(new_vsfile_hgei)); -+ - /* Zero-out new IMSIC VS-file */ - imsic_vsfile_local_clear(new_vsfile_hgei, imsic->nr_hw_eix); - -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/kvm/vcpu.c BPI-Router-Linux-kernel-6.16.12/arch/riscv/kvm/vcpu.c ---- BPI-Router-Linux-kernel/arch/riscv/kvm/vcpu.c 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/kvm/vcpu.c 2025-10-22 13:53:56.379169797 -0400 -@@ -207,16 +207,6 @@ int kvm_cpu_has_pending_timer(struct kvm - return kvm_riscv_vcpu_timer_pending(vcpu); - } - --void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu) --{ -- kvm_riscv_aia_wakeon_hgei(vcpu, true); --} -- --void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) --{ -- kvm_riscv_aia_wakeon_hgei(vcpu, false); --} -- - int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu) - { - return (kvm_riscv_vcpu_has_interrupts(vcpu, -1UL) && -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/kvm/vcpu_onereg.c BPI-Router-Linux-kernel-6.16.12/arch/riscv/kvm/vcpu_onereg.c ---- BPI-Router-Linux-kernel/arch/riscv/kvm/vcpu_onereg.c 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/kvm/vcpu_onereg.c 2025-10-22 13:53:56.379169797 -0400 -@@ -23,7 +23,7 @@ - #define KVM_ISA_EXT_ARR(ext) \ - [KVM_RISCV_ISA_EXT_##ext] = RISCV_ISA_EXT_##ext - --/* Mapping between KVM ISA Extension ID & Host ISA extension ID */ -+/* Mapping between KVM ISA Extension ID & guest ISA extension ID */ - static const unsigned long kvm_isa_ext_arr[] = { - /* Single letter extensions (alphabetically sorted) */ - [KVM_RISCV_ISA_EXT_A] = RISCV_ISA_EXT_a, -@@ -35,7 +35,7 @@ static const unsigned long kvm_isa_ext_a - [KVM_RISCV_ISA_EXT_M] = RISCV_ISA_EXT_m, - [KVM_RISCV_ISA_EXT_V] = RISCV_ISA_EXT_v, - /* Multi letter extensions (alphabetically sorted) */ -- [KVM_RISCV_ISA_EXT_SMNPM] = RISCV_ISA_EXT_SSNPM, -+ KVM_ISA_EXT_ARR(SMNPM), - KVM_ISA_EXT_ARR(SMSTATEEN), - KVM_ISA_EXT_ARR(SSAIA), - KVM_ISA_EXT_ARR(SSCOFPMF), -@@ -112,6 +112,36 @@ static unsigned long kvm_riscv_vcpu_base - return KVM_RISCV_ISA_EXT_MAX; - } - -+static int kvm_riscv_vcpu_isa_check_host(unsigned long kvm_ext, unsigned long *guest_ext) -+{ -+ unsigned long host_ext; -+ -+ if (kvm_ext >= KVM_RISCV_ISA_EXT_MAX || -+ kvm_ext >= ARRAY_SIZE(kvm_isa_ext_arr)) -+ return -ENOENT; -+ -+ *guest_ext = kvm_isa_ext_arr[kvm_ext]; -+ switch (*guest_ext) { -+ case RISCV_ISA_EXT_SMNPM: -+ /* -+ * Pointer masking effective in (H)S-mode is provided by the -+ * Smnpm extension, so that extension is reported to the guest, -+ * even though the CSR bits for configuring VS-mode pointer -+ * masking on the host side are part of the Ssnpm extension. -+ */ -+ host_ext = RISCV_ISA_EXT_SSNPM; -+ break; -+ default: -+ host_ext = *guest_ext; -+ break; -+ } -+ -+ if (!__riscv_isa_extension_available(NULL, host_ext)) -+ return -ENOENT; -+ -+ return 0; -+} -+ - static bool kvm_riscv_vcpu_isa_enable_allowed(unsigned long ext) - { - switch (ext) { -@@ -219,13 +249,13 @@ static bool kvm_riscv_vcpu_isa_disable_a - - void kvm_riscv_vcpu_setup_isa(struct kvm_vcpu *vcpu) - { -- unsigned long host_isa, i; -+ unsigned long guest_ext, i; - - for (i = 0; i < ARRAY_SIZE(kvm_isa_ext_arr); i++) { -- host_isa = kvm_isa_ext_arr[i]; -- if (__riscv_isa_extension_available(NULL, host_isa) && -- kvm_riscv_vcpu_isa_enable_allowed(i)) -- set_bit(host_isa, vcpu->arch.isa); -+ if (kvm_riscv_vcpu_isa_check_host(i, &guest_ext)) -+ continue; -+ if (kvm_riscv_vcpu_isa_enable_allowed(i)) -+ set_bit(guest_ext, vcpu->arch.isa); - } - } - -@@ -607,18 +637,15 @@ static int riscv_vcpu_get_isa_ext_single - unsigned long reg_num, - unsigned long *reg_val) - { -- unsigned long host_isa_ext; -+ unsigned long guest_ext; -+ int ret; - -- if (reg_num >= KVM_RISCV_ISA_EXT_MAX || -- reg_num >= ARRAY_SIZE(kvm_isa_ext_arr)) -- return -ENOENT; -- -- host_isa_ext = kvm_isa_ext_arr[reg_num]; -- if (!__riscv_isa_extension_available(NULL, host_isa_ext)) -- return -ENOENT; -+ ret = kvm_riscv_vcpu_isa_check_host(reg_num, &guest_ext); -+ if (ret) -+ return ret; - - *reg_val = 0; -- if (__riscv_isa_extension_available(vcpu->arch.isa, host_isa_ext)) -+ if (__riscv_isa_extension_available(vcpu->arch.isa, guest_ext)) - *reg_val = 1; /* Mark the given extension as available */ - - return 0; -@@ -628,17 +655,14 @@ static int riscv_vcpu_set_isa_ext_single - unsigned long reg_num, - unsigned long reg_val) - { -- unsigned long host_isa_ext; -+ unsigned long guest_ext; -+ int ret; - -- if (reg_num >= KVM_RISCV_ISA_EXT_MAX || -- reg_num >= ARRAY_SIZE(kvm_isa_ext_arr)) -- return -ENOENT; -- -- host_isa_ext = kvm_isa_ext_arr[reg_num]; -- if (!__riscv_isa_extension_available(NULL, host_isa_ext)) -- return -ENOENT; -+ ret = kvm_riscv_vcpu_isa_check_host(reg_num, &guest_ext); -+ if (ret) -+ return ret; - -- if (reg_val == test_bit(host_isa_ext, vcpu->arch.isa)) -+ if (reg_val == test_bit(guest_ext, vcpu->arch.isa)) - return 0; - - if (!vcpu->arch.ran_atleast_once) { -@@ -648,10 +672,10 @@ static int riscv_vcpu_set_isa_ext_single - */ - if (reg_val == 1 && - kvm_riscv_vcpu_isa_enable_allowed(reg_num)) -- set_bit(host_isa_ext, vcpu->arch.isa); -+ set_bit(guest_ext, vcpu->arch.isa); - else if (!reg_val && - kvm_riscv_vcpu_isa_disable_allowed(reg_num)) -- clear_bit(host_isa_ext, vcpu->arch.isa); -+ clear_bit(guest_ext, vcpu->arch.isa); - else - return -EINVAL; - kvm_riscv_vcpu_fp_reset(vcpu); -@@ -1009,16 +1033,15 @@ static int copy_fp_d_reg_indices(const s - static int copy_isa_ext_reg_indices(const struct kvm_vcpu *vcpu, - u64 __user *uindices) - { -+ unsigned long guest_ext; - unsigned int n = 0; -- unsigned long isa_ext; - - for (int i = 0; i < KVM_RISCV_ISA_EXT_MAX; i++) { - u64 size = IS_ENABLED(CONFIG_32BIT) ? - KVM_REG_SIZE_U32 : KVM_REG_SIZE_U64; - u64 reg = KVM_REG_RISCV | size | KVM_REG_RISCV_ISA_EXT | i; - -- isa_ext = kvm_isa_ext_arr[i]; -- if (!__riscv_isa_extension_available(NULL, isa_ext)) -+ if (kvm_riscv_vcpu_isa_check_host(i, &guest_ext)) - continue; - - if (uindices) { -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/kvm/vcpu_sbi_replace.c BPI-Router-Linux-kernel-6.16.12/arch/riscv/kvm/vcpu_sbi_replace.c ---- BPI-Router-Linux-kernel/arch/riscv/kvm/vcpu_sbi_replace.c 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/kvm/vcpu_sbi_replace.c 2025-10-22 13:53:56.379169797 -0400 -@@ -103,7 +103,7 @@ static int kvm_sbi_ext_rfence_handler(st - kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_FENCE_I_SENT); - break; - case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA: -- if (cp->a2 == 0 && cp->a3 == 0) -+ if ((cp->a2 == 0 && cp->a3 == 0) || cp->a3 == -1UL) - kvm_riscv_hfence_vvma_all(vcpu->kvm, hbase, hmask); - else - kvm_riscv_hfence_vvma_gva(vcpu->kvm, hbase, hmask, -@@ -111,7 +111,7 @@ static int kvm_sbi_ext_rfence_handler(st - kvm_riscv_vcpu_pmu_incr_fw(vcpu, SBI_PMU_FW_HFENCE_VVMA_SENT); - break; - case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID: -- if (cp->a2 == 0 && cp->a3 == 0) -+ if ((cp->a2 == 0 && cp->a3 == 0) || cp->a3 == -1UL) - kvm_riscv_hfence_vvma_asid_all(vcpu->kvm, - hbase, hmask, cp->a4); - else -@@ -127,9 +127,9 @@ static int kvm_sbi_ext_rfence_handler(st - case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID: - /* - * Until nested virtualization is implemented, the -- * SBI HFENCE calls should be treated as NOPs -+ * SBI HFENCE calls should return not supported -+ * hence fallthrough. - */ -- break; - default: - retdata->err_val = SBI_ERR_NOT_SUPPORTED; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/kvm/vcpu_timer.c BPI-Router-Linux-kernel-6.16.12/arch/riscv/kvm/vcpu_timer.c ---- BPI-Router-Linux-kernel/arch/riscv/kvm/vcpu_timer.c 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/kvm/vcpu_timer.c 2025-10-22 13:53:56.379169797 -0400 -@@ -345,8 +345,24 @@ void kvm_riscv_vcpu_timer_save(struct kv - /* - * The vstimecmp CSRs are saved by kvm_riscv_vcpu_timer_sync() - * upon every VM exit so no need to save here. -+ * -+ * If VS-timer expires when no VCPU running on a host CPU then -+ * WFI executed by such host CPU will be effective NOP resulting -+ * in no power savings. This is because as-per RISC-V Privileged -+ * specificaiton: "WFI is also required to resume execution for -+ * locally enabled interrupts pending at any privilege level, -+ * regardless of the global interrupt enable at each privilege -+ * level." -+ * -+ * To address the above issue, vstimecmp CSR must be set to -1UL -+ * over here when VCPU is scheduled-out or exits to user space. - */ - -+ csr_write(CSR_VSTIMECMP, -1UL); -+#if defined(CONFIG_32BIT) -+ csr_write(CSR_VSTIMECMPH, -1UL); -+#endif -+ - /* timer should be enabled for the remaining operations */ - if (unlikely(!t->init_done)) - return; -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/kvm/vcpu_vector.c BPI-Router-Linux-kernel-6.16.12/arch/riscv/kvm/vcpu_vector.c ---- BPI-Router-Linux-kernel/arch/riscv/kvm/vcpu_vector.c 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/kvm/vcpu_vector.c 2025-10-22 13:53:56.379169797 -0400 -@@ -182,6 +182,8 @@ int kvm_riscv_vcpu_set_reg_vector(struct - struct kvm_cpu_context *cntx = &vcpu->arch.guest_context; - unsigned long reg_val; - -+ if (reg_size != sizeof(reg_val)) -+ return -EINVAL; - if (copy_from_user(®_val, uaddr, reg_size)) - return -EFAULT; - if (reg_val != cntx->vector.vlenb) -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/mm/ptdump.c BPI-Router-Linux-kernel-6.16.12/arch/riscv/mm/ptdump.c ---- BPI-Router-Linux-kernel/arch/riscv/mm/ptdump.c 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/mm/ptdump.c 2025-10-22 13:53:56.379169797 -0400 -@@ -6,7 +6,6 @@ - #include - #include - #include --#include - #include - #include - -@@ -413,9 +412,7 @@ bool ptdump_check_wx(void) - - static int ptdump_show(struct seq_file *m, void *v) - { -- get_online_mems(); - ptdump_walk(m, m->private); -- put_online_mems(); - - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/net/bpf_jit_comp64.c BPI-Router-Linux-kernel-6.16.12/arch/riscv/net/bpf_jit_comp64.c ---- BPI-Router-Linux-kernel/arch/riscv/net/bpf_jit_comp64.c 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/net/bpf_jit_comp64.c 2025-10-22 13:53:56.379169797 -0400 -@@ -1356,7 +1356,7 @@ int bpf_jit_emit_insn(const struct bpf_i - emit_mv(rd, rs, ctx); - #ifdef CONFIG_SMP - /* Load current CPU number in T1 */ -- emit_ld(RV_REG_T1, offsetof(struct thread_info, cpu), -+ emit_lw(RV_REG_T1, offsetof(struct thread_info, cpu), - RV_REG_TP, ctx); - /* Load address of __per_cpu_offset array in T2 */ - emit_addr(RV_REG_T2, (u64)&__per_cpu_offset, extra_pass, ctx); -@@ -1763,7 +1763,7 @@ int bpf_jit_emit_insn(const struct bpf_i - */ - if (insn->src_reg == 0 && insn->imm == BPF_FUNC_get_smp_processor_id) { - /* Load current CPU number in R0 */ -- emit_ld(bpf_to_rv_reg(BPF_REG_0, ctx), offsetof(struct thread_info, cpu), -+ emit_lw(bpf_to_rv_reg(BPF_REG_0, ctx), offsetof(struct thread_info, cpu), - RV_REG_TP, ctx); - break; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/riscv/tools/relocs_check.sh BPI-Router-Linux-kernel-6.16.12/arch/riscv/tools/relocs_check.sh ---- BPI-Router-Linux-kernel/arch/riscv/tools/relocs_check.sh 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/riscv/tools/relocs_check.sh 2025-10-22 13:53:56.379169797 -0400 -@@ -14,7 +14,9 @@ bad_relocs=$( - ${srctree}/scripts/relocs_check.sh "$@" | - # These relocations are okay - # R_RISCV_RELATIVE -- grep -F -w -v 'R_RISCV_RELATIVE' -+ # R_RISCV_NONE -+ grep -F -w -v 'R_RISCV_RELATIVE -+R_RISCV_NONE' - ) - - if [ -z "$bad_relocs" ]; then -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/boot/startup.c BPI-Router-Linux-kernel-6.16.12/arch/s390/boot/startup.c ---- BPI-Router-Linux-kernel/arch/s390/boot/startup.c 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/boot/startup.c 2025-10-22 13:53:56.379169797 -0400 -@@ -384,7 +384,7 @@ static unsigned long setup_kernel_memory - kernel_start = round_down(kernel_end - kernel_size, THREAD_SIZE); - boot_debug("Randomization range: 0x%016lx-0x%016lx\n", vmax - kaslr_len, vmax); - boot_debug("kernel image: 0x%016lx-0x%016lx (kaslr)\n", kernel_start, -- kernel_size + kernel_size); -+ kernel_start + kernel_size); - } else if (vmax < __NO_KASLR_END_KERNEL || vsize > __NO_KASLR_END_KERNEL) { - kernel_start = round_down(vmax - kernel_size, THREAD_SIZE); - boot_debug("kernel image: 0x%016lx-0x%016lx (constrained)\n", kernel_start, -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/boot/vmem.c BPI-Router-Linux-kernel-6.16.12/arch/s390/boot/vmem.c ---- BPI-Router-Linux-kernel/arch/s390/boot/vmem.c 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/boot/vmem.c 2025-10-22 13:53:56.379169797 -0400 -@@ -530,6 +530,9 @@ void setup_vmem(unsigned long kernel_sta - lowcore_address + sizeof(struct lowcore), - POPULATE_LOWCORE); - for_each_physmem_usable_range(i, &start, &end) { -+ /* Do not map lowcore with identity mapping */ -+ if (!start) -+ start = sizeof(struct lowcore); - pgtable_populate((unsigned long)__identity_va(start), - (unsigned long)__identity_va(end), - POPULATE_IDENTITY); -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/crypto/hmac_s390.c BPI-Router-Linux-kernel-6.16.12/arch/s390/crypto/hmac_s390.c ---- BPI-Router-Linux-kernel/arch/s390/crypto/hmac_s390.c 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/crypto/hmac_s390.c 2025-10-22 13:53:56.379169797 -0400 -@@ -290,6 +290,7 @@ static int s390_hmac_export(struct shash - struct s390_kmac_sha2_ctx *ctx = shash_desc_ctx(desc); - unsigned int bs = crypto_shash_blocksize(desc->tfm); - unsigned int ds = bs / 2; -+ u64 lo = ctx->buflen[0]; - union { - u8 *u8; - u64 *u64; -@@ -301,9 +302,10 @@ static int s390_hmac_export(struct shash - else - memcpy(p.u8, ctx->param, ds); - p.u8 += ds; -- put_unaligned(ctx->buflen[0], p.u64++); -+ lo += bs; -+ put_unaligned(lo, p.u64++); - if (ds == SHA512_DIGEST_SIZE) -- put_unaligned(ctx->buflen[1], p.u64); -+ put_unaligned(ctx->buflen[1] + (lo < bs), p.u64); - return err; - } - -@@ -316,14 +318,16 @@ static int s390_hmac_import(struct shash - const u8 *u8; - const u64 *u64; - } p = { .u8 = in }; -+ u64 lo; - int err; - - err = s390_hmac_sha2_init(desc); - memcpy(ctx->param, p.u8, ds); - p.u8 += ds; -- ctx->buflen[0] = get_unaligned(p.u64++); -+ lo = get_unaligned(p.u64++); -+ ctx->buflen[0] = lo - bs; - if (ds == SHA512_DIGEST_SIZE) -- ctx->buflen[1] = get_unaligned(p.u64); -+ ctx->buflen[1] = get_unaligned(p.u64) - (lo < bs); - if (ctx->buflen[0] | ctx->buflen[1]) - ctx->gr0.ikp = 1; - return err; -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/crypto/sha1_s390.c BPI-Router-Linux-kernel-6.16.12/arch/s390/crypto/sha1_s390.c ---- BPI-Router-Linux-kernel/arch/s390/crypto/sha1_s390.c 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/crypto/sha1_s390.c 2025-10-22 13:53:56.379169797 -0400 -@@ -38,6 +38,7 @@ static int s390_sha1_init(struct shash_d - sctx->state[4] = SHA1_H4; - sctx->count = 0; - sctx->func = CPACF_KIMD_SHA_1; -+ sctx->first_message_part = 0; - - return 0; - } -@@ -60,6 +61,7 @@ static int s390_sha1_import(struct shash - sctx->count = ictx->count; - memcpy(sctx->state, ictx->state, sizeof(ictx->state)); - sctx->func = CPACF_KIMD_SHA_1; -+ sctx->first_message_part = 0; - return 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/crypto/sha3_256_s390.c BPI-Router-Linux-kernel-6.16.12/arch/s390/crypto/sha3_256_s390.c ---- BPI-Router-Linux-kernel/arch/s390/crypto/sha3_256_s390.c 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/crypto/sha3_256_s390.c 2025-10-22 13:53:56.379169797 -0400 -@@ -35,23 +35,33 @@ static int sha3_256_init(struct shash_de - static int sha3_256_export(struct shash_desc *desc, void *out) - { - struct s390_sha_ctx *sctx = shash_desc_ctx(desc); -- struct sha3_state *octx = out; -+ union { -+ u8 *u8; -+ u64 *u64; -+ } p = { .u8 = out }; -+ int i; - - if (sctx->first_message_part) { -- memset(sctx->state, 0, sizeof(sctx->state)); -- sctx->first_message_part = 0; -+ memset(out, 0, SHA3_STATE_SIZE); -+ return 0; - } -- memcpy(octx->st, sctx->state, sizeof(octx->st)); -+ for (i = 0; i < SHA3_STATE_SIZE / 8; i++) -+ put_unaligned(le64_to_cpu(sctx->sha3.state[i]), p.u64++); - return 0; - } - - static int sha3_256_import(struct shash_desc *desc, const void *in) - { - struct s390_sha_ctx *sctx = shash_desc_ctx(desc); -- const struct sha3_state *ictx = in; -+ union { -+ const u8 *u8; -+ const u64 *u64; -+ } p = { .u8 = in }; -+ int i; - -+ for (i = 0; i < SHA3_STATE_SIZE / 8; i++) -+ sctx->sha3.state[i] = cpu_to_le64(get_unaligned(p.u64++)); - sctx->count = 0; -- memcpy(sctx->state, ictx->st, sizeof(ictx->st)); - sctx->first_message_part = 0; - sctx->func = CPACF_KIMD_SHA3_256; - -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/crypto/sha3_512_s390.c BPI-Router-Linux-kernel-6.16.12/arch/s390/crypto/sha3_512_s390.c ---- BPI-Router-Linux-kernel/arch/s390/crypto/sha3_512_s390.c 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/crypto/sha3_512_s390.c 2025-10-22 13:53:56.379169797 -0400 -@@ -34,24 +34,33 @@ static int sha3_512_init(struct shash_de - static int sha3_512_export(struct shash_desc *desc, void *out) - { - struct s390_sha_ctx *sctx = shash_desc_ctx(desc); -- struct sha3_state *octx = out; -- -+ union { -+ u8 *u8; -+ u64 *u64; -+ } p = { .u8 = out }; -+ int i; - - if (sctx->first_message_part) { -- memset(sctx->state, 0, sizeof(sctx->state)); -- sctx->first_message_part = 0; -+ memset(out, 0, SHA3_STATE_SIZE); -+ return 0; - } -- memcpy(octx->st, sctx->state, sizeof(octx->st)); -+ for (i = 0; i < SHA3_STATE_SIZE / 8; i++) -+ put_unaligned(le64_to_cpu(sctx->sha3.state[i]), p.u64++); - return 0; - } - - static int sha3_512_import(struct shash_desc *desc, const void *in) - { - struct s390_sha_ctx *sctx = shash_desc_ctx(desc); -- const struct sha3_state *ictx = in; -+ union { -+ const u8 *u8; -+ const u64 *u64; -+ } p = { .u8 = in }; -+ int i; - -+ for (i = 0; i < SHA3_STATE_SIZE / 8; i++) -+ sctx->sha3.state[i] = cpu_to_le64(get_unaligned(p.u64++)); - sctx->count = 0; -- memcpy(sctx->state, ictx->st, sizeof(ictx->st)); - sctx->first_message_part = 0; - sctx->func = CPACF_KIMD_SHA3_512; - -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/crypto/sha512_s390.c BPI-Router-Linux-kernel-6.16.12/arch/s390/crypto/sha512_s390.c ---- BPI-Router-Linux-kernel/arch/s390/crypto/sha512_s390.c 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/crypto/sha512_s390.c 2025-10-22 13:53:56.379169797 -0400 -@@ -32,6 +32,7 @@ static int sha512_init(struct shash_desc - ctx->count = 0; - ctx->sha512.count_hi = 0; - ctx->func = CPACF_KIMD_SHA_512; -+ ctx->first_message_part = 0; - - return 0; - } -@@ -57,6 +58,7 @@ static int sha512_import(struct shash_de - - memcpy(sctx->state, ictx->state, sizeof(ictx->state)); - sctx->func = CPACF_KIMD_SHA_512; -+ sctx->first_message_part = 0; - return 0; - } - -@@ -97,6 +99,7 @@ static int sha384_init(struct shash_desc - ctx->count = 0; - ctx->sha512.count_hi = 0; - ctx->func = CPACF_KIMD_SHA_512; -+ ctx->first_message_part = 0; - - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/crypto/sha.h BPI-Router-Linux-kernel-6.16.12/arch/s390/crypto/sha.h ---- BPI-Router-Linux-kernel/arch/s390/crypto/sha.h 2025-10-22 13:53:23.123329565 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/crypto/sha.h 2025-10-22 13:53:56.379169797 -0400 -@@ -27,6 +27,9 @@ struct s390_sha_ctx { - u64 state[SHA512_DIGEST_SIZE / sizeof(u64)]; - u64 count_hi; - } sha512; -+ struct { -+ __le64 state[SHA3_STATE_SIZE / sizeof(u64)]; -+ } sha3; - }; - int func; /* KIMD function to use */ - bool first_message_part; -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/hypfs/hypfs_dbfs.c BPI-Router-Linux-kernel-6.16.12/arch/s390/hypfs/hypfs_dbfs.c ---- BPI-Router-Linux-kernel/arch/s390/hypfs/hypfs_dbfs.c 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/hypfs/hypfs_dbfs.c 2025-10-22 13:53:56.379169797 -0400 -@@ -6,6 +6,7 @@ - * Author(s): Michael Holzheu - */ - -+#include - #include - #include "hypfs.h" - -@@ -66,23 +67,27 @@ static long dbfs_ioctl(struct file *file - long rc; - - mutex_lock(&df->lock); -- if (df->unlocked_ioctl) -- rc = df->unlocked_ioctl(file, cmd, arg); -- else -- rc = -ENOTTY; -+ rc = df->unlocked_ioctl(file, cmd, arg); - mutex_unlock(&df->lock); - return rc; - } - --static const struct file_operations dbfs_ops = { -+static const struct file_operations dbfs_ops_ioctl = { - .read = dbfs_read, - .unlocked_ioctl = dbfs_ioctl, - }; - -+static const struct file_operations dbfs_ops = { -+ .read = dbfs_read, -+}; -+ - void hypfs_dbfs_create_file(struct hypfs_dbfs_file *df) - { -- df->dentry = debugfs_create_file(df->name, 0400, dbfs_dir, df, -- &dbfs_ops); -+ const struct file_operations *fops = &dbfs_ops; -+ -+ if (df->unlocked_ioctl && !security_locked_down(LOCKDOWN_DEBUGFS)) -+ fops = &dbfs_ops_ioctl; -+ df->dentry = debugfs_create_file(df->name, 0400, dbfs_dir, df, fops); - mutex_init(&df->lock); - } - -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/include/asm/ap.h BPI-Router-Linux-kernel-6.16.12/arch/s390/include/asm/ap.h ---- BPI-Router-Linux-kernel/arch/s390/include/asm/ap.h 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/include/asm/ap.h 2025-10-22 13:53:56.379169797 -0400 -@@ -103,7 +103,7 @@ struct ap_tapq_hwinfo { - unsigned int accel : 1; /* A */ - unsigned int ep11 : 1; /* X */ - unsigned int apxa : 1; /* APXA */ -- unsigned int : 1; -+ unsigned int slcf : 1; /* Cmd filtering avail. */ - unsigned int class : 8; - unsigned int bs : 2; /* SE bind/assoc */ - unsigned int : 14; -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/include/asm/pci_insn.h BPI-Router-Linux-kernel-6.16.12/arch/s390/include/asm/pci_insn.h ---- BPI-Router-Linux-kernel/arch/s390/include/asm/pci_insn.h 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/include/asm/pci_insn.h 2025-10-22 13:53:56.379169797 -0400 -@@ -16,11 +16,11 @@ - #define ZPCI_PCI_ST_FUNC_NOT_AVAIL 40 - #define ZPCI_PCI_ST_ALREADY_IN_RQ_STATE 44 - --/* Load/Store return codes */ --#define ZPCI_PCI_LS_OK 0 --#define ZPCI_PCI_LS_ERR 1 --#define ZPCI_PCI_LS_BUSY 2 --#define ZPCI_PCI_LS_INVAL_HANDLE 3 -+/* PCI instruction condition codes */ -+#define ZPCI_CC_OK 0 -+#define ZPCI_CC_ERR 1 -+#define ZPCI_CC_BUSY 2 -+#define ZPCI_CC_INVAL_HANDLE 3 - - /* Load/Store address space identifiers */ - #define ZPCI_PCIAS_MEMIO_0 0 -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/include/asm/pgtable.h BPI-Router-Linux-kernel-6.16.12/arch/s390/include/asm/pgtable.h ---- BPI-Router-Linux-kernel/arch/s390/include/asm/pgtable.h 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/include/asm/pgtable.h 2025-10-22 13:53:56.379169797 -0400 -@@ -915,7 +915,7 @@ static inline int pmd_protnone(pmd_t pmd - } - #endif - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/include/asm/ptrace.h BPI-Router-Linux-kernel-6.16.12/arch/s390/include/asm/ptrace.h ---- BPI-Router-Linux-kernel/arch/s390/include/asm/ptrace.h 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/include/asm/ptrace.h 2025-10-22 13:53:56.383169778 -0400 -@@ -265,7 +265,7 @@ static __always_inline unsigned long reg - addr = kernel_stack_pointer(regs) + n * sizeof(long); - if (!regs_within_kernel_stack(regs, addr)) - return 0; -- return READ_ONCE_NOCHECK(addr); -+ return READ_ONCE_NOCHECK(*(unsigned long *)addr); - } - - /** -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/include/asm/timex.h BPI-Router-Linux-kernel-6.16.12/arch/s390/include/asm/timex.h ---- BPI-Router-Linux-kernel/arch/s390/include/asm/timex.h 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/include/asm/timex.h 2025-10-22 13:53:56.383169778 -0400 -@@ -196,13 +196,6 @@ static inline unsigned long get_tod_cloc - asm volatile("stckf %0" : "=Q" (clk) : : "cc"); - return clk; - } -- --static inline cycles_t get_cycles(void) --{ -- return (cycles_t) get_tod_clock() >> 2; --} --#define get_cycles get_cycles -- - int get_phys_clock(unsigned long *clock); - void init_cpu_timer(void); - -@@ -230,6 +223,12 @@ static inline unsigned long get_tod_cloc - return tod; - } - -+static inline cycles_t get_cycles(void) -+{ -+ return (cycles_t)get_tod_clock_monotonic() >> 2; -+} -+#define get_cycles get_cycles -+ - /** - * tod_to_ns - convert a TOD format value to nanoseconds - * @todval: to be converted TOD format value -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/kernel/early.c BPI-Router-Linux-kernel-6.16.12/arch/s390/kernel/early.c ---- BPI-Router-Linux-kernel/arch/s390/kernel/early.c 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/kernel/early.c 2025-10-22 13:53:56.383169778 -0400 -@@ -154,6 +154,7 @@ void __init __do_early_pgm_check(struct - - regs->int_code = lc->pgm_int_code; - regs->int_parm_long = lc->trans_exc_code; -+ regs->last_break = lc->pgm_last_break; - ip = __rewind_psw(regs->psw, regs->int_code >> 16); - - /* Monitor Event? Might be a warning */ -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/kernel/kexec_elf.c BPI-Router-Linux-kernel-6.16.12/arch/s390/kernel/kexec_elf.c ---- BPI-Router-Linux-kernel/arch/s390/kernel/kexec_elf.c 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/kernel/kexec_elf.c 2025-10-22 13:53:56.383169778 -0400 -@@ -16,7 +16,7 @@ - static int kexec_file_add_kernel_elf(struct kimage *image, - struct s390_load_data *data) - { -- struct kexec_buf buf; -+ struct kexec_buf buf = {}; - const Elf_Ehdr *ehdr; - const Elf_Phdr *phdr; - Elf_Addr entry; -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/kernel/kexec_image.c BPI-Router-Linux-kernel-6.16.12/arch/s390/kernel/kexec_image.c ---- BPI-Router-Linux-kernel/arch/s390/kernel/kexec_image.c 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/kernel/kexec_image.c 2025-10-22 13:53:56.383169778 -0400 -@@ -16,7 +16,7 @@ - static int kexec_file_add_kernel_image(struct kimage *image, - struct s390_load_data *data) - { -- struct kexec_buf buf; -+ struct kexec_buf buf = {}; - - buf.image = image; - -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/kernel/machine_kexec_file.c BPI-Router-Linux-kernel-6.16.12/arch/s390/kernel/machine_kexec_file.c ---- BPI-Router-Linux-kernel/arch/s390/kernel/machine_kexec_file.c 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/kernel/machine_kexec_file.c 2025-10-22 13:53:56.383169778 -0400 -@@ -129,7 +129,7 @@ static int kexec_file_update_purgatory(s - static int kexec_file_add_purgatory(struct kimage *image, - struct s390_load_data *data) - { -- struct kexec_buf buf; -+ struct kexec_buf buf = {}; - int ret; - - buf.image = image; -@@ -152,7 +152,7 @@ static int kexec_file_add_purgatory(stru - static int kexec_file_add_initrd(struct kimage *image, - struct s390_load_data *data) - { -- struct kexec_buf buf; -+ struct kexec_buf buf = {}; - int ret; - - buf.image = image; -@@ -184,7 +184,7 @@ static int kexec_file_add_ipl_report(str - { - __u32 *lc_ipl_parmblock_ptr; - unsigned int len, ncerts; -- struct kexec_buf buf; -+ struct kexec_buf buf = {}; - unsigned long addr; - void *ptr, *end; - int ret; -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/kernel/perf_cpum_cf.c BPI-Router-Linux-kernel-6.16.12/arch/s390/kernel/perf_cpum_cf.c ---- BPI-Router-Linux-kernel/arch/s390/kernel/perf_cpum_cf.c 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/kernel/perf_cpum_cf.c 2025-10-22 13:53:56.383169778 -0400 -@@ -761,8 +761,6 @@ static int __hw_perf_event_init(struct p - break; - - case PERF_TYPE_HARDWARE: -- if (is_sampling_event(event)) /* No sampling support */ -- return -ENOENT; - ev = attr->config; - if (!attr->exclude_user && attr->exclude_kernel) { - /* -@@ -860,6 +858,8 @@ static int cpumf_pmu_event_init(struct p - unsigned int type = event->attr.type; - int err = -ENOENT; - -+ if (is_sampling_event(event)) /* No sampling support */ -+ return err; - if (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_RAW) - err = __hw_perf_event_init(event, type); - else if (event->pmu->type == type) -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/kernel/perf_pai_crypto.c BPI-Router-Linux-kernel-6.16.12/arch/s390/kernel/perf_pai_crypto.c ---- BPI-Router-Linux-kernel/arch/s390/kernel/perf_pai_crypto.c 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/kernel/perf_pai_crypto.c 2025-10-22 13:53:56.383169778 -0400 -@@ -286,10 +286,10 @@ static int paicrypt_event_init(struct pe - /* PAI crypto PMU registered as PERF_TYPE_RAW, check event type */ - if (a->type != PERF_TYPE_RAW && event->pmu->type != a->type) - return -ENOENT; -- /* PAI crypto event must be in valid range */ -+ /* PAI crypto event must be in valid range, try others if not */ - if (a->config < PAI_CRYPTO_BASE || - a->config > PAI_CRYPTO_BASE + paicrypt_cnt) -- return -EINVAL; -+ return -ENOENT; - /* Allow only CRYPTO_ALL for sampling */ - if (a->sample_period && a->config != PAI_CRYPTO_BASE) - return -EINVAL; -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/kernel/perf_pai_ext.c BPI-Router-Linux-kernel-6.16.12/arch/s390/kernel/perf_pai_ext.c ---- BPI-Router-Linux-kernel/arch/s390/kernel/perf_pai_ext.c 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/kernel/perf_pai_ext.c 2025-10-22 13:53:56.383169778 -0400 -@@ -266,7 +266,7 @@ static int paiext_event_valid(struct per - event->hw.config_base = offsetof(struct paiext_cb, acc); - return 0; - } -- return -EINVAL; -+ return -ENOENT; - } - - /* Might be called on different CPU than the one the event is intended for. */ -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/kernel/setup.c BPI-Router-Linux-kernel-6.16.12/arch/s390/kernel/setup.c ---- BPI-Router-Linux-kernel/arch/s390/kernel/setup.c 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/kernel/setup.c 2025-10-22 13:53:56.383169778 -0400 -@@ -719,6 +719,11 @@ static void __init memblock_add_physmem_ - memblock_set_node(0, ULONG_MAX, &memblock.memory, 0); - } - -+static void __init setup_high_memory(void) -+{ -+ high_memory = __va(ident_map_size); -+} -+ - /* - * Reserve memory used for lowcore. - */ -@@ -951,6 +956,7 @@ void __init setup_arch(char **cmdline_p) - - free_physmem_info(); - setup_memory_end(); -+ setup_high_memory(); - memblock_dump_all(); - setup_memory(); - -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/kernel/time.c BPI-Router-Linux-kernel-6.16.12/arch/s390/kernel/time.c ---- BPI-Router-Linux-kernel/arch/s390/kernel/time.c 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/kernel/time.c 2025-10-22 13:53:56.383169778 -0400 -@@ -580,7 +580,7 @@ static int stp_sync_clock(void *data) - atomic_dec(&sync->cpus); - /* Wait for in_sync to be set. */ - while (READ_ONCE(sync->in_sync) == 0) -- __udelay(1); -+ ; - } - if (sync->in_sync != 1) - /* Didn't work. Clear per-cpu in sync bit again. */ -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/mm/dump_pagetables.c BPI-Router-Linux-kernel-6.16.12/arch/s390/mm/dump_pagetables.c ---- BPI-Router-Linux-kernel/arch/s390/mm/dump_pagetables.c 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/mm/dump_pagetables.c 2025-10-22 13:53:56.383169778 -0400 -@@ -247,11 +247,9 @@ static int ptdump_show(struct seq_file * - .marker = markers, - }; - -- get_online_mems(); - mutex_lock(&cpa_mutex); - ptdump_walk_pgd(&st.ptdump, &init_mm, NULL); - mutex_unlock(&cpa_mutex); -- put_online_mems(); - return 0; - } - DEFINE_SHOW_ATTRIBUTE(ptdump); -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/mm/pgalloc.c BPI-Router-Linux-kernel-6.16.12/arch/s390/mm/pgalloc.c ---- BPI-Router-Linux-kernel/arch/s390/mm/pgalloc.c 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/mm/pgalloc.c 2025-10-22 13:53:56.383169778 -0400 -@@ -173,11 +173,6 @@ void pte_free_defer(struct mm_struct *mm - struct ptdesc *ptdesc = virt_to_ptdesc(pgtable); - - call_rcu(&ptdesc->pt_rcu_head, pte_free_now); -- /* -- * THPs are not allowed for KVM guests. Warn if pgste ever reaches here. -- * Turn to the generic pte_free_defer() version once gmap is removed. -- */ -- WARN_ON_ONCE(mm_has_pgste(mm)); - } - #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ - -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/mm/vmem.c BPI-Router-Linux-kernel-6.16.12/arch/s390/mm/vmem.c ---- BPI-Router-Linux-kernel/arch/s390/mm/vmem.c 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/mm/vmem.c 2025-10-22 13:53:56.383169778 -0400 -@@ -64,13 +64,12 @@ void *vmem_crst_alloc(unsigned long val) - - pte_t __ref *vmem_pte_alloc(void) - { -- unsigned long size = PTRS_PER_PTE * sizeof(pte_t); - pte_t *pte; - - if (slab_is_available()) -- pte = (pte_t *) page_table_alloc(&init_mm); -+ pte = (pte_t *)page_table_alloc(&init_mm); - else -- pte = (pte_t *) memblock_alloc(size, size); -+ pte = (pte_t *)memblock_alloc(PAGE_SIZE, PAGE_SIZE); - if (!pte) - return NULL; - memset64((u64 *)pte, _PAGE_INVALID, PTRS_PER_PTE); -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/net/bpf_jit_comp.c BPI-Router-Linux-kernel-6.16.12/arch/s390/net/bpf_jit_comp.c ---- BPI-Router-Linux-kernel/arch/s390/net/bpf_jit_comp.c 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/net/bpf_jit_comp.c 2025-10-22 13:53:56.383169778 -0400 -@@ -566,7 +566,15 @@ static void bpf_jit_plt(struct bpf_plt * - { - memcpy(plt, &bpf_plt, sizeof(*plt)); - plt->ret = ret; -- plt->target = target; -+ /* -+ * (target == NULL) implies that the branch to this PLT entry was -+ * patched and became a no-op. However, some CPU could have jumped -+ * to this PLT entry before patching and may be still executing it. -+ * -+ * Since the intention in this case is to make the PLT entry a no-op, -+ * make the target point to the return label instead of NULL. -+ */ -+ plt->target = target ?: ret; - } - - /* -diff -purNx .git BPI-Router-Linux-kernel/arch/s390/pci/pci_event.c BPI-Router-Linux-kernel-6.16.12/arch/s390/pci/pci_event.c ---- BPI-Router-Linux-kernel/arch/s390/pci/pci_event.c 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/s390/pci/pci_event.c 2025-10-22 13:53:56.383169778 -0400 -@@ -54,6 +54,7 @@ static inline bool ers_result_indicates_ - case PCI_ERS_RESULT_CAN_RECOVER: - case PCI_ERS_RESULT_RECOVERED: - case PCI_ERS_RESULT_NEED_RESET: -+ case PCI_ERS_RESULT_NONE: - return false; - default: - return true; -@@ -78,10 +79,6 @@ static bool is_driver_supported(struct p - return false; - if (!driver->err_handler->error_detected) - return false; -- if (!driver->err_handler->slot_reset) -- return false; -- if (!driver->err_handler->resume) -- return false; - return true; - } - -@@ -106,6 +103,10 @@ static pci_ers_result_t zpci_event_do_er - struct zpci_dev *zdev = to_zpci(pdev); - int rc; - -+ /* The underlying device may have been disabled by the event */ -+ if (!zdev_enabled(zdev)) -+ return PCI_ERS_RESULT_NEED_RESET; -+ - pr_info("%s: Unblocking device access for examination\n", pci_name(pdev)); - rc = zpci_reset_load_store_blocked(zdev); - if (rc) { -@@ -114,16 +115,18 @@ static pci_ers_result_t zpci_event_do_er - return PCI_ERS_RESULT_NEED_RESET; - } - -- if (driver->err_handler->mmio_enabled) { -+ if (driver->err_handler->mmio_enabled) - ers_res = driver->err_handler->mmio_enabled(pdev); -- if (ers_result_indicates_abort(ers_res)) { -- pr_info("%s: Automatic recovery failed after MMIO re-enable\n", -- pci_name(pdev)); -- return ers_res; -- } else if (ers_res == PCI_ERS_RESULT_NEED_RESET) { -- pr_debug("%s: Driver needs reset to recover\n", pci_name(pdev)); -- return ers_res; -- } -+ else -+ ers_res = PCI_ERS_RESULT_NONE; -+ -+ if (ers_result_indicates_abort(ers_res)) { -+ pr_info("%s: Automatic recovery failed after MMIO re-enable\n", -+ pci_name(pdev)); -+ return ers_res; -+ } else if (ers_res == PCI_ERS_RESULT_NEED_RESET) { -+ pr_debug("%s: Driver needs reset to recover\n", pci_name(pdev)); -+ return ers_res; - } - - pr_debug("%s: Unblocking DMA\n", pci_name(pdev)); -@@ -150,7 +153,12 @@ static pci_ers_result_t zpci_event_do_re - return ers_res; - } - pdev->error_state = pci_channel_io_normal; -- ers_res = driver->err_handler->slot_reset(pdev); -+ -+ if (driver->err_handler->slot_reset) -+ ers_res = driver->err_handler->slot_reset(pdev); -+ else -+ ers_res = PCI_ERS_RESULT_NONE; -+ - if (ers_result_indicates_abort(ers_res)) { - pr_info("%s: Automatic recovery failed after slot reset\n", pci_name(pdev)); - return ers_res; -@@ -214,7 +222,7 @@ static pci_ers_result_t zpci_event_attem - goto out_unlock; - } - -- if (ers_res == PCI_ERS_RESULT_CAN_RECOVER) { -+ if (ers_res != PCI_ERS_RESULT_NEED_RESET) { - ers_res = zpci_event_do_error_state_clear(pdev, driver); - if (ers_result_indicates_abort(ers_res)) { - status_str = "failed (abort on MMIO enable)"; -@@ -225,6 +233,16 @@ static pci_ers_result_t zpci_event_attem - if (ers_res == PCI_ERS_RESULT_NEED_RESET) - ers_res = zpci_event_do_reset(pdev, driver); - -+ /* -+ * ers_res can be PCI_ERS_RESULT_NONE either because the driver -+ * decided to return it, indicating that it abstains from voting -+ * on how to recover, or because it didn't implement the callback. -+ * Both cases assume, that if there is nothing else causing a -+ * disconnect, we recovered successfully. -+ */ -+ if (ers_res == PCI_ERS_RESULT_NONE) -+ ers_res = PCI_ERS_RESULT_RECOVERED; -+ - if (ers_res != PCI_ERS_RESULT_RECOVERED) { - pr_err("%s: Automatic recovery failed; operator intervention is required\n", - pci_name(pdev)); -@@ -273,6 +291,8 @@ static void __zpci_event_error(struct zp - struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); - struct pci_dev *pdev = NULL; - pci_ers_result_t ers_res; -+ u32 fh = 0; -+ int rc; - - zpci_dbg(3, "err fid:%x, fh:%x, pec:%x\n", - ccdf->fid, ccdf->fh, ccdf->pec); -@@ -281,6 +301,15 @@ static void __zpci_event_error(struct zp - - if (zdev) { - mutex_lock(&zdev->state_lock); -+ rc = clp_refresh_fh(zdev->fid, &fh); -+ if (rc) -+ goto no_pdev; -+ if (!fh || ccdf->fh != fh) { -+ /* Ignore events with stale handles */ -+ zpci_dbg(3, "err fid:%x, fh:%x (stale %x)\n", -+ ccdf->fid, fh, ccdf->fh); -+ goto no_pdev; -+ } - zpci_update_fh(zdev, ccdf->fh); - if (zdev->zbus->bus) - pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn); -diff -purNx .git BPI-Router-Linux-kernel/arch/sh/boot/compressed/Makefile BPI-Router-Linux-kernel-6.16.12/arch/sh/boot/compressed/Makefile ---- BPI-Router-Linux-kernel/arch/sh/boot/compressed/Makefile 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/sh/boot/compressed/Makefile 2025-10-22 13:53:56.383169778 -0400 -@@ -27,7 +27,7 @@ endif - - ccflags-remove-$(CONFIG_MCOUNT) += -pg - --LDFLAGS_vmlinux := --oformat $(ld-bfd) -Ttext $(IMAGE_OFFSET) -e startup \ -+LDFLAGS_vmlinux := --oformat $(ld_bfd) -Ttext $(IMAGE_OFFSET) -e startup \ - -T $(obj)/../../kernel/vmlinux.lds - - KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING -@@ -51,7 +51,7 @@ $(obj)/vmlinux.bin.lzo: $(obj)/vmlinux.b - - OBJCOPYFLAGS += -R .empty_zero_page - --LDFLAGS_piggy.o := -r --format binary --oformat $(ld-bfd) -T -+LDFLAGS_piggy.o := -r --format binary --oformat $(ld_bfd) -T - - $(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix_y) FORCE - $(call if_changed,ld) -diff -purNx .git BPI-Router-Linux-kernel/arch/sh/boot/romimage/Makefile BPI-Router-Linux-kernel-6.16.12/arch/sh/boot/romimage/Makefile ---- BPI-Router-Linux-kernel/arch/sh/boot/romimage/Makefile 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/sh/boot/romimage/Makefile 2025-10-22 13:53:56.383169778 -0400 -@@ -13,7 +13,7 @@ mmcif-obj-$(CONFIG_CPU_SUBTYPE_SH7724) : - load-$(CONFIG_ROMIMAGE_MMCIF) := $(mmcif-load-y) - obj-$(CONFIG_ROMIMAGE_MMCIF) := $(mmcif-obj-y) - --LDFLAGS_vmlinux := --oformat $(ld-bfd) -Ttext $(load-y) -e romstart \ -+LDFLAGS_vmlinux := --oformat $(ld_bfd) -Ttext $(load-y) -e romstart \ - -T $(obj)/../../kernel/vmlinux.lds - - $(obj)/vmlinux: $(obj)/head.o $(obj-y) $(obj)/piggy.o FORCE -@@ -24,7 +24,7 @@ OBJCOPYFLAGS += -j .empty_zero_page - $(obj)/zeropage.bin: vmlinux FORCE - $(call if_changed,objcopy) - --LDFLAGS_piggy.o := -r --format binary --oformat $(ld-bfd) -T -+LDFLAGS_piggy.o := -r --format binary --oformat $(ld_bfd) -T - - $(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/zeropage.bin arch/sh/boot/zImage FORCE - $(call if_changed,ld) -diff -purNx .git BPI-Router-Linux-kernel/arch/sh/include/asm/pgtable_32.h BPI-Router-Linux-kernel-6.16.12/arch/sh/include/asm/pgtable_32.h ---- BPI-Router-Linux-kernel/arch/sh/include/asm/pgtable_32.h 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/sh/include/asm/pgtable_32.h 2025-10-22 13:53:56.383169778 -0400 -@@ -470,7 +470,7 @@ static inline unsigned long pmd_page_vad - /* In both cases, we borrow bit 6 to store the exclusive marker in swap PTEs. */ - #define _PAGE_SWP_EXCLUSIVE _PAGE_USER - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte.pte_low & _PAGE_SWP_EXCLUSIVE; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/sh/Makefile BPI-Router-Linux-kernel-6.16.12/arch/sh/Makefile ---- BPI-Router-Linux-kernel/arch/sh/Makefile 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/sh/Makefile 2025-10-22 13:53:56.383169778 -0400 -@@ -103,16 +103,16 @@ UTS_MACHINE := sh - LDFLAGS_vmlinux += -e _stext - - ifdef CONFIG_CPU_LITTLE_ENDIAN --ld-bfd := elf32-sh-linux --LDFLAGS_vmlinux += --defsym jiffies=jiffies_64 --oformat $(ld-bfd) -+ld_bfd := elf32-sh-linux -+LDFLAGS_vmlinux += --defsym jiffies=jiffies_64 --oformat $(ld_bfd) - KBUILD_LDFLAGS += -EL - else --ld-bfd := elf32-shbig-linux --LDFLAGS_vmlinux += --defsym jiffies=jiffies_64+4 --oformat $(ld-bfd) -+ld_bfd := elf32-shbig-linux -+LDFLAGS_vmlinux += --defsym jiffies=jiffies_64+4 --oformat $(ld_bfd) - KBUILD_LDFLAGS += -EB - endif - --export ld-bfd -+export ld_bfd - - # Mach groups - machdir-$(CONFIG_SOLUTION_ENGINE) += mach-se -diff -purNx .git BPI-Router-Linux-kernel/arch/sparc/include/asm/pgtable_32.h BPI-Router-Linux-kernel-6.16.12/arch/sparc/include/asm/pgtable_32.h ---- BPI-Router-Linux-kernel/arch/sparc/include/asm/pgtable_32.h 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/sparc/include/asm/pgtable_32.h 2025-10-22 13:53:56.383169778 -0400 -@@ -348,7 +348,7 @@ static inline swp_entry_t __swp_entry(un - #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) - #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_val(pte) & SRMMU_SWP_EXCLUSIVE; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/sparc/include/asm/pgtable_64.h BPI-Router-Linux-kernel-6.16.12/arch/sparc/include/asm/pgtable_64.h ---- BPI-Router-Linux-kernel/arch/sparc/include/asm/pgtable_64.h 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/sparc/include/asm/pgtable_64.h 2025-10-22 13:53:56.383169778 -0400 -@@ -1023,7 +1023,7 @@ pgtable_t pgtable_trans_huge_withdraw(st - #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) - #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/um/drivers/rtc_user.c BPI-Router-Linux-kernel-6.16.12/arch/um/drivers/rtc_user.c ---- BPI-Router-Linux-kernel/arch/um/drivers/rtc_user.c 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/um/drivers/rtc_user.c 2025-10-22 13:53:56.383169778 -0400 -@@ -28,7 +28,7 @@ int uml_rtc_start(bool timetravel) - int err; - - if (timetravel) { -- int err = os_pipe(uml_rtc_irq_fds, 1, 1); -+ err = os_pipe(uml_rtc_irq_fds, 1, 1); - if (err) - goto fail; - } else { -diff -purNx .git BPI-Router-Linux-kernel/arch/um/drivers/ubd_user.c BPI-Router-Linux-kernel-6.16.12/arch/um/drivers/ubd_user.c ---- BPI-Router-Linux-kernel/arch/um/drivers/ubd_user.c 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/um/drivers/ubd_user.c 2025-10-22 13:53:56.383169778 -0400 -@@ -41,7 +41,7 @@ int start_io_thread(struct os_helper_thr - *fd_out = fds[1]; - - err = os_set_fd_block(*fd_out, 0); -- err = os_set_fd_block(kernel_fd, 0); -+ err |= os_set_fd_block(kernel_fd, 0); - if (err) { - printk("start_io_thread - failed to set nonblocking I/O.\n"); - goto out_close; -diff -purNx .git BPI-Router-Linux-kernel/arch/um/drivers/vector_kern.c BPI-Router-Linux-kernel-6.16.12/arch/um/drivers/vector_kern.c ---- BPI-Router-Linux-kernel/arch/um/drivers/vector_kern.c 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/um/drivers/vector_kern.c 2025-10-22 13:53:56.383169778 -0400 -@@ -1625,35 +1625,19 @@ static void vector_eth_configure( - - device->dev = dev; - -- *vp = ((struct vector_private) -- { -- .list = LIST_HEAD_INIT(vp->list), -- .dev = dev, -- .unit = n, -- .options = get_transport_options(def), -- .rx_irq = 0, -- .tx_irq = 0, -- .parsed = def, -- .max_packet = get_mtu(def) + ETH_HEADER_OTHER, -- /* TODO - we need to calculate headroom so that ip header -- * is 16 byte aligned all the time -- */ -- .headroom = get_headroom(def), -- .form_header = NULL, -- .verify_header = NULL, -- .header_rxbuffer = NULL, -- .header_txbuffer = NULL, -- .header_size = 0, -- .rx_header_size = 0, -- .rexmit_scheduled = false, -- .opened = false, -- .transport_data = NULL, -- .in_write_poll = false, -- .coalesce = 2, -- .req_size = get_req_size(def), -- .in_error = false, -- .bpf = NULL -- }); -+ INIT_LIST_HEAD(&vp->list); -+ vp->dev = dev; -+ vp->unit = n; -+ vp->options = get_transport_options(def); -+ vp->parsed = def; -+ vp->max_packet = get_mtu(def) + ETH_HEADER_OTHER; -+ /* -+ * TODO - we need to calculate headroom so that ip header -+ * is 16 byte aligned all the time -+ */ -+ vp->headroom = get_headroom(def); -+ vp->coalesce = 2; -+ vp->req_size = get_req_size(def); - - dev->features = dev->hw_features = (NETIF_F_SG | NETIF_F_FRAGLIST); - INIT_WORK(&vp->reset_tx, vector_reset_tx); -diff -purNx .git BPI-Router-Linux-kernel/arch/um/drivers/vfio_kern.c BPI-Router-Linux-kernel-6.16.12/arch/um/drivers/vfio_kern.c ---- BPI-Router-Linux-kernel/arch/um/drivers/vfio_kern.c 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/um/drivers/vfio_kern.c 2025-10-22 13:53:56.383169778 -0400 -@@ -570,6 +570,17 @@ static void uml_vfio_release_device(stru - kfree(dev); - } - -+static struct uml_vfio_device *uml_vfio_find_device(const char *device) -+{ -+ struct uml_vfio_device *dev; -+ -+ list_for_each_entry(dev, ¨_vfio_devices, list) { -+ if (!strcmp(dev->name, device)) -+ return dev; -+ } -+ return NULL; -+} -+ - static int uml_vfio_cmdline_set(const char *device, const struct kernel_param *kp) - { - struct uml_vfio_device *dev; -@@ -582,6 +593,9 @@ static int uml_vfio_cmdline_set(const ch - uml_vfio_container.fd = fd; - } - -+ if (uml_vfio_find_device(device)) -+ return -EEXIST; -+ - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return -ENOMEM; -diff -purNx .git BPI-Router-Linux-kernel/arch/um/drivers/virtio_uml.c BPI-Router-Linux-kernel-6.16.12/arch/um/drivers/virtio_uml.c ---- BPI-Router-Linux-kernel/arch/um/drivers/virtio_uml.c 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/um/drivers/virtio_uml.c 2025-10-22 13:53:56.383169778 -0400 -@@ -1250,10 +1250,12 @@ static int virtio_uml_probe(struct platf - device_set_wakeup_capable(&vu_dev->vdev.dev, true); - - rc = register_virtio_device(&vu_dev->vdev); -- if (rc) -+ if (rc) { - put_device(&vu_dev->vdev.dev); -+ return rc; -+ } - vu_dev->registered = 1; -- return rc; -+ return 0; - - error_init: - os_close_file(vu_dev->sock); -diff -purNx .git BPI-Router-Linux-kernel/arch/um/include/asm/pgtable.h BPI-Router-Linux-kernel-6.16.12/arch/um/include/asm/pgtable.h ---- BPI-Router-Linux-kernel/arch/um/include/asm/pgtable.h 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/um/include/asm/pgtable.h 2025-10-22 13:53:56.383169778 -0400 -@@ -314,7 +314,7 @@ extern pte_t *virt_to_pte(struct mm_stru - ((swp_entry_t) { pte_val(pte_mkuptodate(pte)) }) - #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_get_bits(pte, _PAGE_SWP_EXCLUSIVE); - } -diff -purNx .git BPI-Router-Linux-kernel/arch/um/include/asm/thread_info.h BPI-Router-Linux-kernel-6.16.12/arch/um/include/asm/thread_info.h ---- BPI-Router-Linux-kernel/arch/um/include/asm/thread_info.h 2025-10-22 13:53:23.127329546 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/um/include/asm/thread_info.h 2025-10-22 13:53:56.383169778 -0400 -@@ -50,7 +50,11 @@ struct thread_info { - #define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL) - #define _TIF_MEMDIE (1 << TIF_MEMDIE) - #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) -+#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) - #define _TIF_SECCOMP (1 << TIF_SECCOMP) - #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) - -+#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL | \ -+ _TIF_NOTIFY_RESUME) -+ - #endif -diff -purNx .git BPI-Router-Linux-kernel/arch/um/kernel/process.c BPI-Router-Linux-kernel-6.16.12/arch/um/kernel/process.c ---- BPI-Router-Linux-kernel/arch/um/kernel/process.c 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/um/kernel/process.c 2025-10-22 13:53:56.383169778 -0400 -@@ -82,14 +82,18 @@ struct task_struct *__switch_to(struct t - void interrupt_end(void) - { - struct pt_regs *regs = ¤t->thread.regs; -+ unsigned long thread_flags; - -- if (need_resched()) -- schedule(); -- if (test_thread_flag(TIF_SIGPENDING) || -- test_thread_flag(TIF_NOTIFY_SIGNAL)) -- do_signal(regs); -- if (test_thread_flag(TIF_NOTIFY_RESUME)) -- resume_user_mode_work(regs); -+ thread_flags = read_thread_flags(); -+ while (thread_flags & _TIF_WORK_MASK) { -+ if (thread_flags & _TIF_NEED_RESCHED) -+ schedule(); -+ if (thread_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)) -+ do_signal(regs); -+ if (thread_flags & _TIF_NOTIFY_RESUME) -+ resume_user_mode_work(regs); -+ thread_flags = read_thread_flags(); -+ } - } - - int get_current_pid(void) -diff -purNx .git BPI-Router-Linux-kernel/arch/um/os-Linux/file.c BPI-Router-Linux-kernel-6.16.12/arch/um/os-Linux/file.c ---- BPI-Router-Linux-kernel/arch/um/os-Linux/file.c 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/um/os-Linux/file.c 2025-10-22 13:53:56.387169758 -0400 -@@ -535,7 +535,7 @@ ssize_t os_rcv_fd_msg(int fd, int *fds, - cmsg->cmsg_type != SCM_RIGHTS) - return n; - -- memcpy(fds, CMSG_DATA(cmsg), cmsg->cmsg_len); -+ memcpy(fds, CMSG_DATA(cmsg), cmsg->cmsg_len - CMSG_LEN(0)); - return n; - } - -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/boot/cpuflags.c BPI-Router-Linux-kernel-6.16.12/arch/x86/boot/cpuflags.c ---- BPI-Router-Linux-kernel/arch/x86/boot/cpuflags.c 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/boot/cpuflags.c 2025-10-22 13:53:56.387169758 -0400 -@@ -106,5 +106,18 @@ void get_cpuflags(void) - cpuid(0x80000001, &ignored, &ignored, &cpu.flags[6], - &cpu.flags[1]); - } -+ -+ if (max_amd_level >= 0x8000001f) { -+ u32 ebx; -+ -+ /* -+ * The X86_FEATURE_COHERENCY_SFW_NO feature bit is in -+ * the virtualization flags entry (word 8) and set by -+ * scattered.c, so the bit needs to be explicitly set. -+ */ -+ cpuid(0x8000001f, &ignored, &ebx, &ignored, &ignored); -+ if (ebx & BIT(31)) -+ set_bit(X86_FEATURE_COHERENCY_SFW_NO, cpu.flags); -+ } - } - } -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/boot/startup/sev-shared.c BPI-Router-Linux-kernel-6.16.12/arch/x86/boot/startup/sev-shared.c ---- BPI-Router-Linux-kernel/arch/x86/boot/startup/sev-shared.c 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/boot/startup/sev-shared.c 2025-10-22 13:53:56.387169758 -0400 -@@ -785,6 +785,7 @@ static void __head svsm_pval_4k_page(uns - pc->entry[0].page_size = RMP_PG_SIZE_4K; - pc->entry[0].action = validate; - pc->entry[0].ignore_cf = 0; -+ pc->entry[0].rsvd = 0; - pc->entry[0].pfn = paddr >> PAGE_SHIFT; - - /* Protocol 0, Call ID 1 */ -@@ -810,6 +811,13 @@ static void __head pvalidate_4k_page(uns - if (ret) - sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PVALIDATE); - } -+ -+ /* -+ * If validating memory (making it private) and affected by the -+ * cache-coherency vulnerability, perform the cache eviction mitigation. -+ */ -+ if (validate && !has_cpuflag(X86_FEATURE_COHERENCY_SFW_NO)) -+ sev_evict_cache((void *)vaddr, 1); - } - - /* -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/coco/sev/core.c BPI-Router-Linux-kernel-6.16.12/arch/x86/coco/sev/core.c ---- BPI-Router-Linux-kernel/arch/x86/coco/sev/core.c 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/coco/sev/core.c 2025-10-22 13:53:56.387169758 -0400 -@@ -88,7 +88,7 @@ static const char * const sev_status_fea - */ - static u64 snp_tsc_scale __ro_after_init; - static u64 snp_tsc_offset __ro_after_init; --static u64 snp_tsc_freq_khz __ro_after_init; -+static unsigned long snp_tsc_freq_khz __ro_after_init; - - DEFINE_PER_CPU(struct sev_es_runtime_data*, runtime_data); - DEFINE_PER_CPU(struct sev_es_save_area *, sev_vmsa); -@@ -227,6 +227,7 @@ static u64 svsm_build_ca_from_pfn_range( - pe->page_size = RMP_PG_SIZE_4K; - pe->action = action; - pe->ignore_cf = 0; -+ pe->rsvd = 0; - pe->pfn = pfn; - - pe++; -@@ -257,6 +258,7 @@ static int svsm_build_ca_from_psc_desc(s - pe->page_size = e->pagesize ? RMP_PG_SIZE_2M : RMP_PG_SIZE_4K; - pe->action = e->operation == SNP_PAGE_STATE_PRIVATE; - pe->ignore_cf = 0; -+ pe->rsvd = 0; - pe->pfn = e->gfn; - - pe++; -@@ -358,10 +360,31 @@ static void svsm_pval_pages(struct snp_p - - static void pvalidate_pages(struct snp_psc_desc *desc) - { -+ struct psc_entry *e; -+ unsigned int i; -+ - if (snp_vmpl) - svsm_pval_pages(desc); - else - pval_pages(desc); -+ -+ /* -+ * If not affected by the cache-coherency vulnerability there is no need -+ * to perform the cache eviction mitigation. -+ */ -+ if (cpu_feature_enabled(X86_FEATURE_COHERENCY_SFW_NO)) -+ return; -+ -+ for (i = 0; i <= desc->hdr.end_entry; i++) { -+ e = &desc->entries[i]; -+ -+ /* -+ * If validating memory (making it private) perform the cache -+ * eviction mitigation. -+ */ -+ if (e->operation == SNP_PAGE_STATE_PRIVATE) -+ sev_evict_cache(pfn_to_kaddr(e->gfn), e->pagesize ? 512 : 1); -+ } - } - - static int vmgexit_psc(struct ghcb *ghcb, struct snp_psc_desc *desc) -@@ -2167,15 +2190,31 @@ static unsigned long securetsc_get_tsc_k - - void __init snp_secure_tsc_init(void) - { -- unsigned long long tsc_freq_mhz; -+ struct snp_secrets_page *secrets; -+ unsigned long tsc_freq_mhz; -+ void *mem; - - if (!cc_platform_has(CC_ATTR_GUEST_SNP_SECURE_TSC)) - return; - -+ mem = early_memremap_encrypted(sev_secrets_pa, PAGE_SIZE); -+ if (!mem) { -+ pr_err("Unable to get TSC_FACTOR: failed to map the SNP secrets page.\n"); -+ sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_SECURE_TSC); -+ } -+ -+ secrets = (__force struct snp_secrets_page *)mem; -+ - setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ); - rdmsrq(MSR_AMD64_GUEST_TSC_FREQ, tsc_freq_mhz); -- snp_tsc_freq_khz = (unsigned long)(tsc_freq_mhz * 1000); -+ -+ /* Extract the GUEST TSC MHZ from BIT[17:0], rest is reserved space */ -+ tsc_freq_mhz &= GENMASK_ULL(17, 0); -+ -+ snp_tsc_freq_khz = SNP_SCALE_TSC_FREQ(tsc_freq_mhz * 1000, secrets->tsc_factor); - - x86_platform.calibrate_cpu = securetsc_get_tsc_khz; - x86_platform.calibrate_tsc = securetsc_get_tsc_khz; -+ -+ early_memunmap(mem, PAGE_SIZE); - } -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/coco/sev/Makefile BPI-Router-Linux-kernel-6.16.12/arch/x86/coco/sev/Makefile ---- BPI-Router-Linux-kernel/arch/x86/coco/sev/Makefile 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/coco/sev/Makefile 2025-10-22 13:53:56.387169758 -0400 -@@ -5,5 +5,6 @@ obj-y += core.o sev-nmi.o vc-handle.o - # Clang 14 and older may fail to respect __no_sanitize_undefined when inlining - UBSAN_SANITIZE_sev-nmi.o := n - --# GCC may fail to respect __no_sanitize_address when inlining -+# GCC may fail to respect __no_sanitize_address or __no_kcsan when inlining - KASAN_SANITIZE_sev-nmi.o := n -+KCSAN_SANITIZE_sev-nmi.o := n -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/coco/sev/vc-handle.c BPI-Router-Linux-kernel-6.16.12/arch/x86/coco/sev/vc-handle.c ---- BPI-Router-Linux-kernel/arch/x86/coco/sev/vc-handle.c 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/coco/sev/vc-handle.c 2025-10-22 13:53:56.387169758 -0400 -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - #include - - #include -@@ -178,9 +179,15 @@ static enum es_result __vc_decode_kern_i - return ES_OK; - } - -+/* -+ * User instruction decoding is also required for the EFI runtime. Even though -+ * the EFI runtime is running in kernel mode, it uses special EFI virtual -+ * address mappings that require the use of efi_mm to properly address and -+ * decode. -+ */ - static enum es_result vc_decode_insn(struct es_em_ctxt *ctxt) - { -- if (user_mode(ctxt->regs)) -+ if (user_mode(ctxt->regs) || mm_is_efi(current->active_mm)) - return __vc_decode_user_insn(ctxt); - else - return __vc_decode_kern_insn(ctxt); -@@ -364,29 +371,30 @@ static enum es_result __vc_handle_msr_ca - * executing with Secure TSC enabled, so special handling is required for - * accesses of MSR_IA32_TSC and MSR_AMD64_GUEST_TSC_FREQ. - */ --static enum es_result __vc_handle_secure_tsc_msrs(struct pt_regs *regs, bool write) -+static enum es_result __vc_handle_secure_tsc_msrs(struct es_em_ctxt *ctxt, bool write) - { -+ struct pt_regs *regs = ctxt->regs; - u64 tsc; - - /* -- * GUEST_TSC_FREQ should not be intercepted when Secure TSC is enabled. -- * Terminate the SNP guest when the interception is enabled. -+ * Writing to MSR_IA32_TSC can cause subsequent reads of the TSC to -+ * return undefined values, and GUEST_TSC_FREQ is read-only. Generate -+ * a #GP on all writes. - */ -- if (regs->cx == MSR_AMD64_GUEST_TSC_FREQ) -- return ES_VMM_ERROR; -+ if (write) { -+ ctxt->fi.vector = X86_TRAP_GP; -+ ctxt->fi.error_code = 0; -+ return ES_EXCEPTION; -+ } - - /* -- * Writes: Writing to MSR_IA32_TSC can cause subsequent reads of the TSC -- * to return undefined values, so ignore all writes. -- * -- * Reads: Reads of MSR_IA32_TSC should return the current TSC value, use -- * the value returned by rdtsc_ordered(). -+ * GUEST_TSC_FREQ read should not be intercepted when Secure TSC is -+ * enabled. Terminate the guest if a read is attempted. - */ -- if (write) { -- WARN_ONCE(1, "TSC MSR writes are verboten!\n"); -- return ES_OK; -- } -+ if (regs->cx == MSR_AMD64_GUEST_TSC_FREQ) -+ return ES_VMM_ERROR; - -+ /* Reads of MSR_IA32_TSC should return the current TSC value. */ - tsc = rdtsc_ordered(); - regs->ax = lower_32_bits(tsc); - regs->dx = upper_32_bits(tsc); -@@ -409,7 +417,7 @@ static enum es_result vc_handle_msr(stru - case MSR_IA32_TSC: - case MSR_AMD64_GUEST_TSC_FREQ: - if (sev_status & MSR_AMD64_SNP_SECURE_TSC) -- return __vc_handle_secure_tsc_msrs(regs, write); -+ return __vc_handle_secure_tsc_msrs(ctxt, write); - break; - default: - break; -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/crypto/aegis128-aesni-glue.c BPI-Router-Linux-kernel-6.16.12/arch/x86/crypto/aegis128-aesni-glue.c ---- BPI-Router-Linux-kernel/arch/x86/crypto/aegis128-aesni-glue.c 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/crypto/aegis128-aesni-glue.c 2025-10-22 13:53:56.387169758 -0400 -@@ -104,10 +104,12 @@ static void crypto_aegis128_aesni_proces - } - } - --static __always_inline void -+static __always_inline int - crypto_aegis128_aesni_process_crypt(struct aegis_state *state, - struct skcipher_walk *walk, bool enc) - { -+ int err = 0; -+ - while (walk->nbytes >= AEGIS128_BLOCK_SIZE) { - if (enc) - aegis128_aesni_enc(state, walk->src.virt.addr, -@@ -119,7 +121,10 @@ crypto_aegis128_aesni_process_crypt(stru - walk->dst.virt.addr, - round_down(walk->nbytes, - AEGIS128_BLOCK_SIZE)); -- skcipher_walk_done(walk, walk->nbytes % AEGIS128_BLOCK_SIZE); -+ kernel_fpu_end(); -+ err = skcipher_walk_done(walk, -+ walk->nbytes % AEGIS128_BLOCK_SIZE); -+ kernel_fpu_begin(); - } - - if (walk->nbytes) { -@@ -131,8 +136,11 @@ crypto_aegis128_aesni_process_crypt(stru - aegis128_aesni_dec_tail(state, walk->src.virt.addr, - walk->dst.virt.addr, - walk->nbytes); -- skcipher_walk_done(walk, 0); -+ kernel_fpu_end(); -+ err = skcipher_walk_done(walk, 0); -+ kernel_fpu_begin(); - } -+ return err; - } - - static struct aegis_ctx *crypto_aegis128_aesni_ctx(struct crypto_aead *aead) -@@ -165,7 +173,7 @@ static int crypto_aegis128_aesni_setauth - return 0; - } - --static __always_inline void -+static __always_inline int - crypto_aegis128_aesni_crypt(struct aead_request *req, - struct aegis_block *tag_xor, - unsigned int cryptlen, bool enc) -@@ -174,20 +182,24 @@ crypto_aegis128_aesni_crypt(struct aead_ - struct aegis_ctx *ctx = crypto_aegis128_aesni_ctx(tfm); - struct skcipher_walk walk; - struct aegis_state state; -+ int err; - - if (enc) -- skcipher_walk_aead_encrypt(&walk, req, true); -+ err = skcipher_walk_aead_encrypt(&walk, req, false); - else -- skcipher_walk_aead_decrypt(&walk, req, true); -+ err = skcipher_walk_aead_decrypt(&walk, req, false); -+ if (err) -+ return err; - - kernel_fpu_begin(); - - aegis128_aesni_init(&state, &ctx->key, req->iv); - crypto_aegis128_aesni_process_ad(&state, req->src, req->assoclen); -- crypto_aegis128_aesni_process_crypt(&state, &walk, enc); -- aegis128_aesni_final(&state, tag_xor, req->assoclen, cryptlen); -- -+ err = crypto_aegis128_aesni_process_crypt(&state, &walk, enc); -+ if (err == 0) -+ aegis128_aesni_final(&state, tag_xor, req->assoclen, cryptlen); - kernel_fpu_end(); -+ return err; - } - - static int crypto_aegis128_aesni_encrypt(struct aead_request *req) -@@ -196,8 +208,11 @@ static int crypto_aegis128_aesni_encrypt - struct aegis_block tag = {}; - unsigned int authsize = crypto_aead_authsize(tfm); - unsigned int cryptlen = req->cryptlen; -+ int err; - -- crypto_aegis128_aesni_crypt(req, &tag, cryptlen, true); -+ err = crypto_aegis128_aesni_crypt(req, &tag, cryptlen, true); -+ if (err) -+ return err; - - scatterwalk_map_and_copy(tag.bytes, req->dst, - req->assoclen + cryptlen, authsize, 1); -@@ -212,11 +227,14 @@ static int crypto_aegis128_aesni_decrypt - struct aegis_block tag; - unsigned int authsize = crypto_aead_authsize(tfm); - unsigned int cryptlen = req->cryptlen - authsize; -+ int err; - - scatterwalk_map_and_copy(tag.bytes, req->src, - req->assoclen + cryptlen, authsize, 0); - -- crypto_aegis128_aesni_crypt(req, &tag, cryptlen, false); -+ err = crypto_aegis128_aesni_crypt(req, &tag, cryptlen, false); -+ if (err) -+ return err; - - return crypto_memneq(tag.bytes, zeros.bytes, authsize) ? -EBADMSG : 0; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/entry/entry.S BPI-Router-Linux-kernel-6.16.12/arch/x86/entry/entry.S ---- BPI-Router-Linux-kernel/arch/x86/entry/entry.S 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/entry/entry.S 2025-10-22 13:53:56.387169758 -0400 -@@ -36,20 +36,20 @@ EXPORT_SYMBOL_GPL(write_ibpb); - - /* - * Define the VERW operand that is disguised as entry code so that -- * it can be referenced with KPTI enabled. This ensure VERW can be -+ * it can be referenced with KPTI enabled. This ensures VERW can be - * used late in exit-to-user path after page tables are switched. - */ - .pushsection .entry.text, "ax" - - .align L1_CACHE_BYTES, 0xcc --SYM_CODE_START_NOALIGN(mds_verw_sel) -+SYM_CODE_START_NOALIGN(x86_verw_sel) - UNWIND_HINT_UNDEFINED - ANNOTATE_NOENDBR - .word __KERNEL_DS - .align L1_CACHE_BYTES, 0xcc --SYM_CODE_END(mds_verw_sel); -+SYM_CODE_END(x86_verw_sel); - /* For KVM */ --EXPORT_SYMBOL_GPL(mds_verw_sel); -+EXPORT_SYMBOL_GPL(x86_verw_sel); - - .popsection - -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/events/intel/core.c BPI-Router-Linux-kernel-6.16.12/arch/x86/events/intel/core.c ---- BPI-Router-Linux-kernel/arch/x86/events/intel/core.c 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/events/intel/core.c 2025-10-22 13:53:56.387169758 -0400 -@@ -2826,7 +2826,7 @@ static void intel_pmu_read_event(struct - * If the PEBS counters snapshotting is enabled, - * the topdown event is available in PEBS records. - */ -- if (is_topdown_event(event) && !is_pebs_counter_event_group(event)) -+ if (is_topdown_count(event) && !is_pebs_counter_event_group(event)) - static_call(intel_pmu_update_topdown_event)(event, NULL); - else - intel_pmu_drain_pebs_buffer(); -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/hyperv/hv_init.c BPI-Router-Linux-kernel-6.16.12/arch/x86/hyperv/hv_init.c ---- BPI-Router-Linux-kernel/arch/x86/hyperv/hv_init.c 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/hyperv/hv_init.c 2025-10-22 13:53:56.387169758 -0400 -@@ -34,6 +34,7 @@ - #include - #include - #include -+#include - - void *hv_hypercall_pg; - EXPORT_SYMBOL_GPL(hv_hypercall_pg); -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/hyperv/irqdomain.c BPI-Router-Linux-kernel-6.16.12/arch/x86/hyperv/irqdomain.c ---- BPI-Router-Linux-kernel/arch/x86/hyperv/irqdomain.c 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/hyperv/irqdomain.c 2025-10-22 13:53:56.387169758 -0400 -@@ -10,6 +10,7 @@ - - #include - #include -+#include - #include - - static int hv_map_interrupt(union hv_device_id device_id, bool level, -@@ -46,7 +47,7 @@ static int hv_map_interrupt(union hv_dev - if (nr_bank < 0) { - local_irq_restore(flags); - pr_err("%s: unable to generate VP set\n", __func__); -- return EINVAL; -+ return -EINVAL; - } - intr_desc->target.flags = HV_DEVICE_INTERRUPT_TARGET_PROCESSOR_SET; - -@@ -66,7 +67,7 @@ static int hv_map_interrupt(union hv_dev - if (!hv_result_success(status)) - hv_status_err(status, "\n"); - -- return hv_result(status); -+ return hv_result_to_errno(status); - } - - static int hv_unmap_interrupt(u64 id, struct hv_interrupt_entry *old_entry) -@@ -88,7 +89,10 @@ static int hv_unmap_interrupt(u64 id, st - status = hv_do_hypercall(HVCALL_UNMAP_DEVICE_INTERRUPT, input, NULL); - local_irq_restore(flags); - -- return hv_result(status); -+ if (!hv_result_success(status)) -+ hv_status_err(status, "\n"); -+ -+ return hv_result_to_errno(status); - } - - #ifdef CONFIG_PCI_MSI -@@ -169,13 +173,34 @@ static union hv_device_id hv_build_pci_d - return dev_id; - } - --static int hv_map_msi_interrupt(struct pci_dev *dev, int cpu, int vector, -- struct hv_interrupt_entry *entry) -+/** -+ * hv_map_msi_interrupt() - "Map" the MSI IRQ in the hypervisor. -+ * @data: Describes the IRQ -+ * @out_entry: Hypervisor (MSI) interrupt entry (can be NULL) -+ * -+ * Map the IRQ in the hypervisor by issuing a MAP_DEVICE_INTERRUPT hypercall. -+ * -+ * Return: 0 on success, -errno on failure -+ */ -+int hv_map_msi_interrupt(struct irq_data *data, -+ struct hv_interrupt_entry *out_entry) - { -- union hv_device_id device_id = hv_build_pci_dev_id(dev); -+ struct irq_cfg *cfg = irqd_cfg(data); -+ struct hv_interrupt_entry dummy; -+ union hv_device_id device_id; -+ struct msi_desc *msidesc; -+ struct pci_dev *dev; -+ int cpu; -+ -+ msidesc = irq_data_get_msi_desc(data); -+ dev = msi_desc_to_pci_dev(msidesc); -+ device_id = hv_build_pci_dev_id(dev); -+ cpu = cpumask_first(irq_data_get_effective_affinity_mask(data)); - -- return hv_map_interrupt(device_id, false, cpu, vector, entry); -+ return hv_map_interrupt(device_id, false, cpu, cfg->vector, -+ out_entry ? out_entry : &dummy); - } -+EXPORT_SYMBOL_GPL(hv_map_msi_interrupt); - - static inline void entry_to_msi_msg(struct hv_interrupt_entry *entry, struct msi_msg *msg) - { -@@ -188,13 +213,11 @@ static inline void entry_to_msi_msg(stru - static int hv_unmap_msi_interrupt(struct pci_dev *dev, struct hv_interrupt_entry *old_entry); - static void hv_irq_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) - { -+ struct hv_interrupt_entry *stored_entry; -+ struct irq_cfg *cfg = irqd_cfg(data); - struct msi_desc *msidesc; - struct pci_dev *dev; -- struct hv_interrupt_entry out_entry, *stored_entry; -- struct irq_cfg *cfg = irqd_cfg(data); -- const cpumask_t *affinity; -- int cpu; -- u64 status; -+ int ret; - - msidesc = irq_data_get_msi_desc(data); - dev = msi_desc_to_pci_dev(msidesc); -@@ -204,9 +227,6 @@ static void hv_irq_compose_msi_msg(struc - return; - } - -- affinity = irq_data_get_effective_affinity_mask(data); -- cpu = cpumask_first_and(affinity, cpu_online_mask); -- - if (data->chip_data) { - /* - * This interrupt is already mapped. Let's unmap first. -@@ -219,14 +239,12 @@ static void hv_irq_compose_msi_msg(struc - stored_entry = data->chip_data; - data->chip_data = NULL; - -- status = hv_unmap_msi_interrupt(dev, stored_entry); -+ ret = hv_unmap_msi_interrupt(dev, stored_entry); - - kfree(stored_entry); - -- if (status != HV_STATUS_SUCCESS) { -- hv_status_debug(status, "failed to unmap\n"); -+ if (ret) - return; -- } - } - - stored_entry = kzalloc(sizeof(*stored_entry), GFP_ATOMIC); -@@ -235,15 +253,14 @@ static void hv_irq_compose_msi_msg(struc - return; - } - -- status = hv_map_msi_interrupt(dev, cpu, cfg->vector, &out_entry); -- if (status != HV_STATUS_SUCCESS) { -+ ret = hv_map_msi_interrupt(data, stored_entry); -+ if (ret) { - kfree(stored_entry); - return; - } - -- *stored_entry = out_entry; - data->chip_data = stored_entry; -- entry_to_msi_msg(&out_entry, msg); -+ entry_to_msi_msg(data->chip_data, msg); - - return; - } -@@ -257,7 +274,6 @@ static void hv_teardown_msi_irq(struct p - { - struct hv_interrupt_entry old_entry; - struct msi_msg msg; -- u64 status; - - if (!irqd->chip_data) { - pr_debug("%s: no chip data\n!", __func__); -@@ -270,10 +286,7 @@ static void hv_teardown_msi_irq(struct p - kfree(irqd->chip_data); - irqd->chip_data = NULL; - -- status = hv_unmap_msi_interrupt(dev, &old_entry); -- -- if (status != HV_STATUS_SUCCESS) -- hv_status_err(status, "\n"); -+ (void)hv_unmap_msi_interrupt(dev, &old_entry); - } - - static void hv_msi_free_irq(struct irq_domain *domain, -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/hyperv/ivm.c BPI-Router-Linux-kernel-6.16.12/arch/x86/hyperv/ivm.c ---- BPI-Router-Linux-kernel/arch/x86/hyperv/ivm.c 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/hyperv/ivm.c 2025-10-22 13:53:56.387169758 -0400 -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - #include - #include - #include -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/hyperv/nested.c BPI-Router-Linux-kernel-6.16.12/arch/x86/hyperv/nested.c ---- BPI-Router-Linux-kernel/arch/x86/hyperv/nested.c 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/hyperv/nested.c 2025-10-22 13:53:56.387169758 -0400 -@@ -11,6 +11,7 @@ - - - #include -+#include - #include - #include - #include -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/include/asm/amd/fch.h BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/amd/fch.h ---- BPI-Router-Linux-kernel/arch/x86/include/asm/amd/fch.h 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/amd/fch.h 1969-12-31 19:00:00.000000000 -0500 -@@ -1,13 +0,0 @@ --/* SPDX-License-Identifier: GPL-2.0 */ --#ifndef _ASM_X86_AMD_FCH_H_ --#define _ASM_X86_AMD_FCH_H_ -- --#define FCH_PM_BASE 0xFED80300 -- --/* Register offsets from PM base: */ --#define FCH_PM_DECODEEN 0x00 --#define FCH_PM_DECODEEN_SMBUS0SEL GENMASK(20, 19) --#define FCH_PM_SCRATCH 0x80 --#define FCH_PM_S5_RESET_STATUS 0xC0 -- --#endif /* _ASM_X86_AMD_FCH_H_ */ -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/include/asm/cpufeatures.h BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/cpufeatures.h ---- BPI-Router-Linux-kernel/arch/x86/include/asm/cpufeatures.h 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/cpufeatures.h 2025-10-22 13:53:56.387169758 -0400 -@@ -218,6 +218,7 @@ - #define X86_FEATURE_FLEXPRIORITY ( 8*32+ 1) /* "flexpriority" Intel FlexPriority */ - #define X86_FEATURE_EPT ( 8*32+ 2) /* "ept" Intel Extended Page Table */ - #define X86_FEATURE_VPID ( 8*32+ 3) /* "vpid" Intel Virtual Processor ID */ -+#define X86_FEATURE_COHERENCY_SFW_NO ( 8*32+ 4) /* SNP cache coherency software work around not needed */ - - #define X86_FEATURE_VMMCALL ( 8*32+15) /* "vmmcall" Prefer VMMCALL to VMCALL */ - #define X86_FEATURE_XENPV ( 8*32+16) /* Xen paravirtual guest */ -@@ -456,6 +457,7 @@ - #define X86_FEATURE_NO_NESTED_DATA_BP (20*32+ 0) /* No Nested Data Breakpoints */ - #define X86_FEATURE_WRMSR_XX_BASE_NS (20*32+ 1) /* WRMSR to {FS,GS,KERNEL_GS}_BASE is non-serializing */ - #define X86_FEATURE_LFENCE_RDTSC (20*32+ 2) /* LFENCE always serializing / synchronizes RDTSC */ -+#define X86_FEATURE_VERW_CLEAR (20*32+ 5) /* The memory form of VERW mitigates TSA */ - #define X86_FEATURE_NULL_SEL_CLR_BASE (20*32+ 6) /* Null Selector Clears Base */ - #define X86_FEATURE_AUTOIBRS (20*32+ 8) /* Automatic IBRS */ - #define X86_FEATURE_NO_SMM_CTL_MSR (20*32+ 9) /* SMM_CTL MSR is not present */ -@@ -487,6 +489,10 @@ - #define X86_FEATURE_PREFER_YMM (21*32+ 8) /* Avoid ZMM registers due to downclocking */ - #define X86_FEATURE_APX (21*32+ 9) /* Advanced Performance Extensions */ - #define X86_FEATURE_INDIRECT_THUNK_ITS (21*32+10) /* Use thunk for indirect branches in lower half of cacheline */ -+#define X86_FEATURE_TSA_SQ_NO (21*32+11) /* AMD CPU not vulnerable to TSA-SQ */ -+#define X86_FEATURE_TSA_L1_NO (21*32+12) /* AMD CPU not vulnerable to TSA-L1 */ -+#define X86_FEATURE_CLEAR_CPU_BUF_VM (21*32+13) /* Clear CPU buffers using VERW before VMRUN */ -+#define X86_FEATURE_IBPB_EXIT_TO_USER (21*32+14) /* Use IBPB on exit-to-userspace, see VMSCAPE bug */ - - /* - * BUG word(s) -@@ -542,5 +548,6 @@ - #define X86_BUG_OLD_MICROCODE X86_BUG( 1*32+ 6) /* "old_microcode" CPU has old microcode, it is surely vulnerable to something */ - #define X86_BUG_ITS X86_BUG( 1*32+ 7) /* "its" CPU is affected by Indirect Target Selection */ - #define X86_BUG_ITS_NATIVE_ONLY X86_BUG( 1*32+ 8) /* "its_native_only" CPU is affected by ITS, VMX is not affected */ -- -+#define X86_BUG_TSA X86_BUG( 1*32+ 9) /* "tsa" CPU is affected by Transient Scheduler Attacks */ -+#define X86_BUG_VMSCAPE X86_BUG( 1*32+10) /* "vmscape" CPU is affected by VMSCAPE attacks from guests */ - #endif /* _ASM_X86_CPUFEATURES_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/include/asm/debugreg.h BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/debugreg.h ---- BPI-Router-Linux-kernel/arch/x86/include/asm/debugreg.h 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/debugreg.h 2025-10-22 13:53:56.387169758 -0400 -@@ -9,6 +9,14 @@ - #include - #include - -+/* -+ * Define bits that are always set to 1 in DR7, only bit 10 is -+ * architecturally reserved to '1'. -+ * -+ * This is also the init/reset value for DR7. -+ */ -+#define DR7_FIXED_1 0x00000400 -+ - DECLARE_PER_CPU(unsigned long, cpu_dr7); - - #ifndef CONFIG_PARAVIRT_XXL -@@ -100,8 +108,8 @@ static __always_inline void native_set_d - - static inline void hw_breakpoint_disable(void) - { -- /* Zero the control register for HW Breakpoint */ -- set_debugreg(0UL, 7); -+ /* Reset the control register for HW Breakpoint */ -+ set_debugreg(DR7_FIXED_1, 7); - - /* Zero-out the individual HW breakpoint address registers */ - set_debugreg(0UL, 0); -@@ -125,9 +133,12 @@ static __always_inline unsigned long loc - return 0; - - get_debugreg(dr7, 7); -- dr7 &= ~0x400; /* architecturally set bit */ -+ -+ /* Architecturally set bit */ -+ dr7 &= ~DR7_FIXED_1; - if (dr7) -- set_debugreg(0, 7); -+ set_debugreg(DR7_FIXED_1, 7); -+ - /* - * Ensure the compiler doesn't lower the above statements into - * the critical section; disabling breakpoints late would not -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/include/asm/entry-common.h BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/entry-common.h ---- BPI-Router-Linux-kernel/arch/x86/include/asm/entry-common.h 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/entry-common.h 2025-10-22 13:53:56.387169758 -0400 -@@ -93,6 +93,13 @@ static inline void arch_exit_to_user_mod - * 8 (ia32) bits. - */ - choose_random_kstack_offset(rdtsc()); -+ -+ /* Avoid unnecessary reads of 'x86_ibpb_exit_to_user' */ -+ if (cpu_feature_enabled(X86_FEATURE_IBPB_EXIT_TO_USER) && -+ this_cpu_read(x86_ibpb_exit_to_user)) { -+ indirect_branch_prediction_barrier(); -+ this_cpu_write(x86_ibpb_exit_to_user, false); -+ } - } - #define arch_exit_to_user_mode_prepare arch_exit_to_user_mode_prepare - -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/include/asm/hw_irq.h BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/hw_irq.h ---- BPI-Router-Linux-kernel/arch/x86/include/asm/hw_irq.h 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/hw_irq.h 2025-10-22 13:53:56.387169758 -0400 -@@ -92,8 +92,6 @@ struct irq_cfg { - - extern struct irq_cfg *irq_cfg(unsigned int irq); - extern struct irq_cfg *irqd_cfg(struct irq_data *irq_data); --extern void lock_vector_lock(void); --extern void unlock_vector_lock(void); - #ifdef CONFIG_SMP - extern void vector_schedule_cleanup(struct irq_cfg *); - extern void irq_complete_move(struct irq_cfg *cfg); -@@ -101,12 +99,16 @@ extern void irq_complete_move(struct irq - static inline void vector_schedule_cleanup(struct irq_cfg *c) { } - static inline void irq_complete_move(struct irq_cfg *c) { } - #endif -- - extern void apic_ack_edge(struct irq_data *data); --#else /* CONFIG_IRQ_DOMAIN_HIERARCHY */ -+#endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */ -+ -+#ifdef CONFIG_X86_LOCAL_APIC -+extern void lock_vector_lock(void); -+extern void unlock_vector_lock(void); -+#else - static inline void lock_vector_lock(void) {} - static inline void unlock_vector_lock(void) {} --#endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */ -+#endif - - /* Statistics */ - extern atomic_t irq_err_count; -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/include/asm/irqflags.h BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/irqflags.h ---- BPI-Router-Linux-kernel/arch/x86/include/asm/irqflags.h 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/irqflags.h 2025-10-22 13:53:56.387169758 -0400 -@@ -44,13 +44,13 @@ static __always_inline void native_irq_e - - static __always_inline void native_safe_halt(void) - { -- mds_idle_clear_cpu_buffers(); -+ x86_idle_clear_cpu_buffers(); - asm volatile("sti; hlt": : :"memory"); - } - - static __always_inline void native_halt(void) - { -- mds_idle_clear_cpu_buffers(); -+ x86_idle_clear_cpu_buffers(); - asm volatile("hlt": : :"memory"); - } - -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/include/asm/kvm_host.h BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/kvm_host.h ---- BPI-Router-Linux-kernel/arch/x86/include/asm/kvm_host.h 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/kvm_host.h 2025-10-22 13:53:56.387169758 -0400 -@@ -31,6 +31,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -249,7 +250,6 @@ enum x86_intercept_stage; - #define DR7_BP_EN_MASK 0x000000ff - #define DR7_GE (1 << 9) - #define DR7_GD (1 << 13) --#define DR7_FIXED_1 0x00000400 - #define DR7_VOLATILE 0xffff2bff - - #define KVM_GUESTDBG_VALID_MASK \ -@@ -700,8 +700,13 @@ struct kvm_vcpu_hv { - - struct kvm_vcpu_hv_tlb_flush_fifo tlb_flush_fifo[HV_NR_TLB_FLUSH_FIFOS]; - -- /* Preallocated buffer for handling hypercalls passing sparse vCPU set */ -+ /* -+ * Preallocated buffers for handling hypercalls that pass sparse vCPU -+ * sets (for high vCPU counts, they're too large to comfortably fit on -+ * the stack). -+ */ - u64 sparse_banks[HV_MAX_SPARSE_VCPU_BANKS]; -+ DECLARE_BITMAP(vcpu_mask, KVM_MAX_VCPUS); - - struct hv_vp_assist_page vp_assist_page; - -@@ -764,6 +769,7 @@ enum kvm_only_cpuid_leafs { - CPUID_8000_0022_EAX, - CPUID_7_2_EDX, - CPUID_24_0_EBX, -+ CPUID_8000_0021_ECX, - NR_KVM_CPU_CAPS, - - NKVMCAPINTS = NR_KVM_CPU_CAPS - NCAPINTS, -@@ -1674,6 +1680,12 @@ static inline u16 kvm_lapic_irq_dest_mod - return dest_mode_logical ? APIC_DEST_LOGICAL : APIC_DEST_PHYSICAL; - } - -+enum kvm_x86_run_flags { -+ KVM_RUN_FORCE_IMMEDIATE_EXIT = BIT(0), -+ KVM_RUN_LOAD_GUEST_DR6 = BIT(1), -+ KVM_RUN_LOAD_DEBUGCTL = BIT(2), -+}; -+ - struct kvm_x86_ops { - const char *name; - -@@ -1702,6 +1714,12 @@ struct kvm_x86_ops { - void (*vcpu_load)(struct kvm_vcpu *vcpu, int cpu); - void (*vcpu_put)(struct kvm_vcpu *vcpu); - -+ /* -+ * Mask of DEBUGCTL bits that are owned by the host, i.e. that need to -+ * match the host's value even while the guest is active. -+ */ -+ const u64 HOST_OWNED_DEBUGCTL; -+ - void (*update_exception_bitmap)(struct kvm_vcpu *vcpu); - int (*get_msr)(struct kvm_vcpu *vcpu, struct msr_data *msr); - int (*set_msr)(struct kvm_vcpu *vcpu, struct msr_data *msr); -@@ -1724,7 +1742,6 @@ struct kvm_x86_ops { - void (*get_gdt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt); - void (*set_gdt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt); - void (*sync_dirty_debug_regs)(struct kvm_vcpu *vcpu); -- void (*set_dr6)(struct kvm_vcpu *vcpu, unsigned long value); - void (*set_dr7)(struct kvm_vcpu *vcpu, unsigned long value); - void (*cache_reg)(struct kvm_vcpu *vcpu, enum kvm_reg reg); - unsigned long (*get_rflags)(struct kvm_vcpu *vcpu); -@@ -1755,7 +1772,7 @@ struct kvm_x86_ops { - - int (*vcpu_pre_run)(struct kvm_vcpu *vcpu); - enum exit_fastpath_completion (*vcpu_run)(struct kvm_vcpu *vcpu, -- bool force_immediate_exit); -+ u64 run_flags); - int (*handle_exit)(struct kvm_vcpu *vcpu, - enum exit_fastpath_completion exit_fastpath); - int (*skip_emulated_instruction)(struct kvm_vcpu *vcpu); -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/include/asm/kvm-x86-ops.h BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/kvm-x86-ops.h ---- BPI-Router-Linux-kernel/arch/x86/include/asm/kvm-x86-ops.h 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/kvm-x86-ops.h 2025-10-22 13:53:56.387169758 -0400 -@@ -49,7 +49,6 @@ KVM_X86_OP(set_idt) - KVM_X86_OP(get_gdt) - KVM_X86_OP(set_gdt) - KVM_X86_OP(sync_dirty_debug_regs) --KVM_X86_OP(set_dr6) - KVM_X86_OP(set_dr7) - KVM_X86_OP(cache_reg) - KVM_X86_OP(get_rflags) -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/include/asm/module.h BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/module.h ---- BPI-Router-Linux-kernel/arch/x86/include/asm/module.h 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/module.h 2025-10-22 13:53:56.387169758 -0400 -@@ -5,12 +5,20 @@ - #include - #include - -+struct its_array { -+#ifdef CONFIG_MITIGATION_ITS -+ void **pages; -+ int num; -+#endif -+}; -+ - struct mod_arch_specific { - #ifdef CONFIG_UNWINDER_ORC - unsigned int num_orcs; - int *orc_unwind_ip; - struct orc_entry *orc_unwind; - #endif -+ struct its_array its_pages; - }; - - #endif /* _ASM_X86_MODULE_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/include/asm/mshyperv.h BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/mshyperv.h ---- BPI-Router-Linux-kernel/arch/x86/include/asm/mshyperv.h 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/mshyperv.h 2025-10-22 13:53:56.387169758 -0400 -@@ -112,12 +112,6 @@ static inline u64 hv_do_hypercall(u64 co - return hv_status; - } - --/* Hypercall to the L0 hypervisor */ --static inline u64 hv_do_nested_hypercall(u64 control, void *input, void *output) --{ -- return hv_do_hypercall(control | HV_HYPERCALL_NESTED, input, output); --} -- - /* Fast hypercall with 8 bytes of input and no output */ - static inline u64 _hv_do_fast_hypercall8(u64 control, u64 input1) - { -@@ -165,13 +159,6 @@ static inline u64 hv_do_fast_hypercall8( - return _hv_do_fast_hypercall8(control, input1); - } - --static inline u64 hv_do_fast_nested_hypercall8(u16 code, u64 input1) --{ -- u64 control = (u64)code | HV_HYPERCALL_FAST_BIT | HV_HYPERCALL_NESTED; -- -- return _hv_do_fast_hypercall8(control, input1); --} -- - /* Fast hypercall with 16 bytes of input */ - static inline u64 _hv_do_fast_hypercall16(u64 control, u64 input1, u64 input2) - { -@@ -223,13 +210,6 @@ static inline u64 hv_do_fast_hypercall16 - return _hv_do_fast_hypercall16(control, input1, input2); - } - --static inline u64 hv_do_fast_nested_hypercall16(u16 code, u64 input1, u64 input2) --{ -- u64 control = (u64)code | HV_HYPERCALL_FAST_BIT | HV_HYPERCALL_NESTED; -- -- return _hv_do_fast_hypercall16(control, input1, input2); --} -- - extern struct hv_vp_assist_page **hv_vp_assist_page; - - static inline struct hv_vp_assist_page *hv_get_vp_assist_page(unsigned int cpu) -@@ -262,6 +242,8 @@ static inline void hv_apic_init(void) {} - - struct irq_domain *hv_create_pci_msi_domain(void); - -+int hv_map_msi_interrupt(struct irq_data *data, -+ struct hv_interrupt_entry *out_entry); - int hv_map_ioapic_interrupt(int ioapic_id, bool level, int vcpu, int vector, - struct hv_interrupt_entry *entry); - int hv_unmap_ioapic_interrupt(int ioapic_id, struct hv_interrupt_entry *entry); -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/include/asm/msr-index.h BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/msr-index.h ---- BPI-Router-Linux-kernel/arch/x86/include/asm/msr-index.h 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/msr-index.h 2025-10-22 13:53:56.387169758 -0400 -@@ -419,6 +419,7 @@ - #define DEBUGCTLMSR_FREEZE_PERFMON_ON_PMI (1UL << 12) - #define DEBUGCTLMSR_FREEZE_IN_SMM_BIT 14 - #define DEBUGCTLMSR_FREEZE_IN_SMM (1UL << DEBUGCTLMSR_FREEZE_IN_SMM_BIT) -+#define DEBUGCTLMSR_RTM_DEBUG BIT(15) - - #define MSR_PEBS_FRONTEND 0x000003f7 - -@@ -628,6 +629,7 @@ - #define MSR_AMD64_OSVW_STATUS 0xc0010141 - #define MSR_AMD_PPIN_CTL 0xc00102f0 - #define MSR_AMD_PPIN 0xc00102f1 -+#define MSR_AMD64_CPUID_FN_7 0xc0011002 - #define MSR_AMD64_CPUID_FN_1 0xc0011004 - #define MSR_AMD64_LS_CFG 0xc0011020 - #define MSR_AMD64_DC_CFG 0xc0011022 -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/include/asm/mwait.h BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/mwait.h ---- BPI-Router-Linux-kernel/arch/x86/include/asm/mwait.h 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/mwait.h 2025-10-22 13:53:56.387169758 -0400 -@@ -43,8 +43,6 @@ static __always_inline void __monitorx(c - - static __always_inline void __mwait(u32 eax, u32 ecx) - { -- mds_idle_clear_cpu_buffers(); -- - /* - * Use the instruction mnemonic with implicit operands, as the LLVM - * assembler fails to assemble the mnemonic with explicit operands: -@@ -80,7 +78,7 @@ static __always_inline void __mwait(u32 - */ - static __always_inline void __mwaitx(u32 eax, u32 ebx, u32 ecx) - { -- /* No MDS buffer clear as this is AMD/HYGON only */ -+ /* No need for TSA buffer clearing on AMD */ - - /* "mwaitx %eax, %ebx, %ecx" */ - asm volatile(".byte 0x0f, 0x01, 0xfb" -@@ -98,7 +96,6 @@ static __always_inline void __mwaitx(u32 - */ - static __always_inline void __sti_mwait(u32 eax, u32 ecx) - { -- mds_idle_clear_cpu_buffers(); - - asm volatile("sti; mwait" :: "a" (eax), "c" (ecx)); - } -@@ -115,21 +112,29 @@ static __always_inline void __sti_mwait( - */ - static __always_inline void mwait_idle_with_hints(u32 eax, u32 ecx) - { -+ if (need_resched()) -+ return; -+ -+ x86_idle_clear_cpu_buffers(); -+ - if (static_cpu_has_bug(X86_BUG_MONITOR) || !current_set_polling_and_test()) { - const void *addr = ¤t_thread_info()->flags; - - alternative_input("", "clflush (%[addr])", X86_BUG_CLFLUSH_MONITOR, [addr] "a" (addr)); - __monitor(addr, 0, 0); - -- if (!need_resched()) { -- if (ecx & 1) { -- __mwait(eax, ecx); -- } else { -- __sti_mwait(eax, ecx); -- raw_local_irq_disable(); -- } -+ if (need_resched()) -+ goto out; -+ -+ if (ecx & 1) { -+ __mwait(eax, ecx); -+ } else { -+ __sti_mwait(eax, ecx); -+ raw_local_irq_disable(); - } - } -+ -+out: - current_clr_polling(); - } - -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/include/asm/nospec-branch.h BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/nospec-branch.h ---- BPI-Router-Linux-kernel/arch/x86/include/asm/nospec-branch.h 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/nospec-branch.h 2025-10-22 13:53:56.387169758 -0400 -@@ -302,25 +302,31 @@ - .endm - - /* -- * Macro to execute VERW instruction that mitigate transient data sampling -- * attacks such as MDS. On affected systems a microcode update overloaded VERW -- * instruction to also clear the CPU buffers. VERW clobbers CFLAGS.ZF. -- * -+ * Macro to execute VERW insns that mitigate transient data sampling -+ * attacks such as MDS or TSA. On affected systems a microcode update -+ * overloaded VERW insns to also clear the CPU buffers. VERW clobbers -+ * CFLAGS.ZF. - * Note: Only the memory operand variant of VERW clears the CPU buffers. - */ --.macro CLEAR_CPU_BUFFERS -+.macro __CLEAR_CPU_BUFFERS feature - #ifdef CONFIG_X86_64 -- ALTERNATIVE "", "verw mds_verw_sel(%rip)", X86_FEATURE_CLEAR_CPU_BUF -+ ALTERNATIVE "", "verw x86_verw_sel(%rip)", \feature - #else - /* - * In 32bit mode, the memory operand must be a %cs reference. The data - * segments may not be usable (vm86 mode), and the stack segment may not - * be flat (ESPFIX32). - */ -- ALTERNATIVE "", "verw %cs:mds_verw_sel", X86_FEATURE_CLEAR_CPU_BUF -+ ALTERNATIVE "", "verw %cs:x86_verw_sel", \feature - #endif - .endm - -+#define CLEAR_CPU_BUFFERS \ -+ __CLEAR_CPU_BUFFERS X86_FEATURE_CLEAR_CPU_BUF -+ -+#define VM_CLEAR_CPU_BUFFERS \ -+ __CLEAR_CPU_BUFFERS X86_FEATURE_CLEAR_CPU_BUF_VM -+ - #ifdef CONFIG_X86_64 - .macro CLEAR_BRANCH_HISTORY - ALTERNATIVE "", "call clear_bhb_loop", X86_FEATURE_CLEAR_BHB_LOOP -@@ -524,6 +530,8 @@ void alternative_msr_write(unsigned int - : "memory"); - } - -+DECLARE_PER_CPU(bool, x86_ibpb_exit_to_user); -+ - static inline void indirect_branch_prediction_barrier(void) - { - asm_inline volatile(ALTERNATIVE("", "call write_ibpb", X86_FEATURE_IBPB) -@@ -567,24 +575,24 @@ DECLARE_STATIC_KEY_FALSE(switch_mm_alway - - DECLARE_STATIC_KEY_FALSE(switch_vcpu_ibpb); - --DECLARE_STATIC_KEY_FALSE(mds_idle_clear); -+DECLARE_STATIC_KEY_FALSE(cpu_buf_idle_clear); - - DECLARE_STATIC_KEY_FALSE(switch_mm_cond_l1d_flush); - - DECLARE_STATIC_KEY_FALSE(cpu_buf_vm_clear); - --extern u16 mds_verw_sel; -+extern u16 x86_verw_sel; - - #include - - /** -- * mds_clear_cpu_buffers - Mitigation for MDS and TAA vulnerability -+ * x86_clear_cpu_buffers - Buffer clearing support for different x86 CPU vulns - * - * This uses the otherwise unused and obsolete VERW instruction in - * combination with microcode which triggers a CPU buffer flush when the - * instruction is executed. - */ --static __always_inline void mds_clear_cpu_buffers(void) -+static __always_inline void x86_clear_cpu_buffers(void) - { - static const u16 ds = __KERNEL_DS; - -@@ -601,14 +609,15 @@ static __always_inline void mds_clear_cp - } - - /** -- * mds_idle_clear_cpu_buffers - Mitigation for MDS vulnerability -+ * x86_idle_clear_cpu_buffers - Buffer clearing support in idle for the MDS -+ * and TSA vulnerabilities. - * - * Clear CPU buffers if the corresponding static key is enabled - */ --static __always_inline void mds_idle_clear_cpu_buffers(void) -+static __always_inline void x86_idle_clear_cpu_buffers(void) - { -- if (static_branch_likely(&mds_idle_clear)) -- mds_clear_cpu_buffers(); -+ if (static_branch_likely(&cpu_buf_idle_clear)) -+ x86_clear_cpu_buffers(); - } - - #endif /* __ASSEMBLER__ */ -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/include/asm/pgtable_64_types.h BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/pgtable_64_types.h ---- BPI-Router-Linux-kernel/arch/x86/include/asm/pgtable_64_types.h 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/pgtable_64_types.h 2025-10-22 13:53:56.387169758 -0400 -@@ -36,6 +36,9 @@ static inline bool pgtable_l5_enabled(vo - #define pgtable_l5_enabled() cpu_feature_enabled(X86_FEATURE_LA57) - #endif /* USE_EARLY_PGTABLE_L5 */ - -+#define ARCH_PAGE_TABLE_SYNC_MASK \ -+ (pgtable_l5_enabled() ? PGTBL_PGD_MODIFIED : PGTBL_P4D_MODIFIED) -+ - extern unsigned int pgdir_shift; - extern unsigned int ptrs_per_p4d; - -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/include/asm/pgtable.h BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/pgtable.h ---- BPI-Router-Linux-kernel/arch/x86/include/asm/pgtable.h 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/pgtable.h 2025-10-22 13:53:56.387169758 -0400 -@@ -1561,7 +1561,7 @@ static inline pte_t pte_swp_mkexclusive( - return pte_set_flags(pte, _PAGE_SWP_EXCLUSIVE); - } - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_flags(pte) & _PAGE_SWP_EXCLUSIVE; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/include/asm/sev.h BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/sev.h ---- BPI-Router-Linux-kernel/arch/x86/include/asm/sev.h 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/sev.h 2025-10-22 13:53:56.387169758 -0400 -@@ -223,6 +223,18 @@ struct snp_tsc_info_resp { - u8 rsvd2[100]; - } __packed; - -+/* -+ * Obtain the mean TSC frequency by decreasing the nominal TSC frequency with -+ * TSC_FACTOR as documented in the SNP Firmware ABI specification: -+ * -+ * GUEST_TSC_FREQ * (1 - (TSC_FACTOR * 0.00001)) -+ * -+ * which is equivalent to: -+ * -+ * GUEST_TSC_FREQ -= (GUEST_TSC_FREQ * TSC_FACTOR) / 100000; -+ */ -+#define SNP_SCALE_TSC_FREQ(freq, factor) ((freq) - (freq) * (factor) / 100000) -+ - struct snp_guest_req { - void *req_buf; - size_t req_sz; -@@ -282,8 +294,11 @@ struct snp_secrets_page { - u8 svsm_guest_vmpl; - u8 rsvd3[3]; - -+ /* The percentage decrease from nominal to mean TSC frequency. */ -+ u32 tsc_factor; -+ - /* Remainder of page */ -- u8 rsvd4[3744]; -+ u8 rsvd4[3740]; - } __packed; - - struct snp_msg_desc { -@@ -549,6 +564,24 @@ enum es_result sev_es_ghcb_hv_call(struc - - extern struct ghcb *boot_ghcb; - -+static inline void sev_evict_cache(void *va, int npages) -+{ -+ volatile u8 val __always_unused; -+ u8 *bytes = va; -+ int page_idx; -+ -+ /* -+ * For SEV guests, a read from the first/last cache-lines of a 4K page -+ * using the guest key is sufficient to cause a flush of all cache-lines -+ * associated with that 4K page without incurring all the overhead of a -+ * full CLFLUSH sequence. -+ */ -+ for (page_idx = 0; page_idx < npages; page_idx++) { -+ val = bytes[page_idx * PAGE_SIZE]; -+ val = bytes[page_idx * PAGE_SIZE + PAGE_SIZE - 1]; -+ } -+} -+ - #else /* !CONFIG_AMD_MEM_ENCRYPT */ - - #define snp_vmpl 0 -@@ -592,6 +625,7 @@ static inline int snp_send_guest_request - static inline int snp_svsm_vtpm_send_command(u8 *buffer) { return -ENODEV; } - static inline void __init snp_secure_tsc_prepare(void) { } - static inline void __init snp_secure_tsc_init(void) { } -+static inline void sev_evict_cache(void *va, int npages) {} - - #endif /* CONFIG_AMD_MEM_ENCRYPT */ - -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/include/asm/shared/tdx.h BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/shared/tdx.h ---- BPI-Router-Linux-kernel/arch/x86/include/asm/shared/tdx.h 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/shared/tdx.h 2025-10-22 13:53:56.387169758 -0400 -@@ -72,6 +72,7 @@ - #define TDVMCALL_MAP_GPA 0x10001 - #define TDVMCALL_GET_QUOTE 0x10002 - #define TDVMCALL_REPORT_FATAL_ERROR 0x10003 -+#define TDVMCALL_SETUP_EVENT_NOTIFY_INTERRUPT 0x10004ULL - - /* - * TDG.VP.VMCALL Status Codes (returned in R10) -@@ -80,6 +81,7 @@ - #define TDVMCALL_STATUS_RETRY 0x0000000000000001ULL - #define TDVMCALL_STATUS_INVALID_OPERAND 0x8000000000000000ULL - #define TDVMCALL_STATUS_ALIGN_ERROR 0x8000000000000002ULL -+#define TDVMCALL_STATUS_SUBFUNC_UNSUPPORTED 0x8000000000000003ULL - - /* - * Bitmasks of exposed registers (with VMM). -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/include/asm/sighandling.h BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/sighandling.h ---- BPI-Router-Linux-kernel/arch/x86/include/asm/sighandling.h 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/sighandling.h 2025-10-22 13:53:56.387169758 -0400 -@@ -24,4 +24,26 @@ int ia32_setup_rt_frame(struct ksignal * - int x64_setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs); - int x32_setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs); - -+/* -+ * To prevent immediate repeat of single step trap on return from SIGTRAP -+ * handler if the trap flag (TF) is set without an external debugger attached, -+ * clear the software event flag in the augmented SS, ensuring no single-step -+ * trap is pending upon ERETU completion. -+ * -+ * Note, this function should be called in sigreturn() before the original -+ * state is restored to make sure the TF is read from the entry frame. -+ */ -+static __always_inline void prevent_single_step_upon_eretu(struct pt_regs *regs) -+{ -+ /* -+ * If the trap flag (TF) is set, i.e., the sigreturn() SYSCALL instruction -+ * is being single-stepped, do not clear the software event flag in the -+ * augmented SS, thus a debugger won't skip over the following instruction. -+ */ -+#ifdef CONFIG_X86_FRED -+ if (!(regs->flags & X86_EFLAGS_TF)) -+ regs->fred_ss.swevent = 0; -+#endif -+} -+ - #endif /* _ASM_X86_SIGHANDLING_H */ -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/include/asm/tdx.h BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/tdx.h ---- BPI-Router-Linux-kernel/arch/x86/include/asm/tdx.h 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/tdx.h 2025-10-22 13:53:56.387169758 -0400 -@@ -106,7 +106,7 @@ void tdx_init(void); - - typedef u64 (*sc_func_t)(u64 fn, struct tdx_module_args *args); - --static inline u64 sc_retry(sc_func_t func, u64 fn, -+static __always_inline u64 sc_retry(sc_func_t func, u64 fn, - struct tdx_module_args *args) - { - int retry = RDRAND_RETRY_LOOPS; -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/include/asm/topology.h BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/topology.h ---- BPI-Router-Linux-kernel/arch/x86/include/asm/topology.h 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/topology.h 2025-10-22 13:53:56.387169758 -0400 -@@ -231,6 +231,16 @@ static inline bool topology_is_primary_t - } - #define topology_is_primary_thread topology_is_primary_thread - -+int topology_get_primary_thread(unsigned int cpu); -+ -+static inline bool topology_is_core_online(unsigned int cpu) -+{ -+ int pcpu = topology_get_primary_thread(cpu); -+ -+ return pcpu >= 0 ? cpu_online(pcpu) : false; -+} -+#define topology_is_core_online topology_is_core_online -+ - #else /* CONFIG_SMP */ - static inline int topology_phys_to_logical_pkg(unsigned int pkg) { return 0; } - static inline int topology_max_smt_threads(void) { return 1; } -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/include/asm/xen/hypercall.h BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/xen/hypercall.h ---- BPI-Router-Linux-kernel/arch/x86/include/asm/xen/hypercall.h 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/include/asm/xen/hypercall.h 2025-10-22 13:53:56.387169758 -0400 -@@ -94,12 +94,13 @@ DECLARE_STATIC_CALL(xen_hypercall, xen_h - #ifdef MODULE - #define __ADDRESSABLE_xen_hypercall - #else --#define __ADDRESSABLE_xen_hypercall __ADDRESSABLE_ASM_STR(__SCK__xen_hypercall) -+#define __ADDRESSABLE_xen_hypercall \ -+ __stringify(.global STATIC_CALL_KEY(xen_hypercall);) - #endif - - #define __HYPERCALL \ - __ADDRESSABLE_xen_hypercall \ -- "call __SCT__xen_hypercall" -+ __stringify(call STATIC_CALL_TRAMP(xen_hypercall)) - - #define __HYPERCALL_ENTRY(x) "a" (x) - -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/include/uapi/asm/debugreg.h BPI-Router-Linux-kernel-6.16.12/arch/x86/include/uapi/asm/debugreg.h ---- BPI-Router-Linux-kernel/arch/x86/include/uapi/asm/debugreg.h 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/include/uapi/asm/debugreg.h 2025-10-22 13:53:56.387169758 -0400 -@@ -15,7 +15,26 @@ - which debugging register was responsible for the trap. The other bits - are either reserved or not of interest to us. */ - --/* Define reserved bits in DR6 which are always set to 1 */ -+/* -+ * Define bits in DR6 which are set to 1 by default. -+ * -+ * This is also the DR6 architectural value following Power-up, Reset or INIT. -+ * -+ * Note, with the introduction of Bus Lock Detection (BLD) and Restricted -+ * Transactional Memory (RTM), the DR6 register has been modified: -+ * -+ * 1) BLD flag (bit 11) is no longer reserved to 1 if the CPU supports -+ * Bus Lock Detection. The assertion of a bus lock could clear it. -+ * -+ * 2) RTM flag (bit 16) is no longer reserved to 1 if the CPU supports -+ * restricted transactional memory. #DB occurred inside an RTM region -+ * could clear it. -+ * -+ * Apparently, DR6.BLD and DR6.RTM are active low bits. -+ * -+ * As a result, DR6_RESERVED is an incorrect name now, but it is kept for -+ * compatibility. -+ */ - #define DR6_RESERVED (0xFFFF0FF0) - - #define DR_TRAP0 (0x1) /* db0 */ -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/include/uapi/asm/kvm.h BPI-Router-Linux-kernel-6.16.12/arch/x86/include/uapi/asm/kvm.h ---- BPI-Router-Linux-kernel/arch/x86/include/uapi/asm/kvm.h 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/include/uapi/asm/kvm.h 2025-10-22 13:53:56.387169758 -0400 -@@ -965,7 +965,13 @@ struct kvm_tdx_cmd { - struct kvm_tdx_capabilities { - __u64 supported_attrs; - __u64 supported_xfam; -- __u64 reserved[254]; -+ -+ __u64 kernel_tdvmcallinfo_1_r11; -+ __u64 user_tdvmcallinfo_1_r11; -+ __u64 kernel_tdvmcallinfo_1_r12; -+ __u64 user_tdvmcallinfo_1_r12; -+ -+ __u64 reserved[250]; - - /* Configurable CPUID bits for userspace */ - struct kvm_cpuid2 cpuid; -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/Kconfig BPI-Router-Linux-kernel-6.16.12/arch/x86/Kconfig ---- BPI-Router-Linux-kernel/arch/x86/Kconfig 2025-10-22 13:53:23.131329527 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/Kconfig 2025-10-22 13:53:56.387169758 -0400 -@@ -26,7 +26,6 @@ config X86_64 - depends on 64BIT - # Options that are inherently 64-bit kernel only: - select ARCH_HAS_GIGANTIC_PAGE -- select ARCH_HAS_PTDUMP - select ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS - select ARCH_SUPPORTS_INT128 if CC_HAS_INT128 - select ARCH_SUPPORTS_PER_VMA_LOCK -@@ -89,7 +88,7 @@ config X86 - select ARCH_HAS_DMA_OPS if GART_IOMMU || XEN - select ARCH_HAS_EARLY_DEBUG if KGDB - select ARCH_HAS_ELF_RANDOMIZE -- select ARCH_HAS_EXECMEM_ROX if X86_64 -+ select ARCH_HAS_EXECMEM_ROX if X86_64 && STRICT_MODULE_RWX - select ARCH_HAS_FAST_MULTIPLIER - select ARCH_HAS_FORTIFY_SOURCE - select ARCH_HAS_GCOV_PROFILE_ALL -@@ -101,6 +100,7 @@ config X86 - select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE - select ARCH_HAS_PMEM_API if X86_64 - select ARCH_HAS_PREEMPT_LAZY -+ select ARCH_HAS_PTDUMP - select ARCH_HAS_PTE_DEVMAP if X86_64 - select ARCH_HAS_PTE_SPECIAL - select ARCH_HAS_HW_PTE_YOUNG -@@ -147,7 +147,7 @@ config X86 - select ARCH_WANTS_DYNAMIC_TASK_STRUCT - select ARCH_WANTS_NO_INSTR - select ARCH_WANT_GENERAL_HUGETLB -- select ARCH_WANT_HUGE_PMD_SHARE -+ select ARCH_WANT_HUGE_PMD_SHARE if X86_64 - select ARCH_WANT_LD_ORPHAN_WARN - select ARCH_WANT_OPTIMIZE_DAX_VMEMMAP if X86_64 - select ARCH_WANT_OPTIMIZE_HUGETLB_VMEMMAP if X86_64 -@@ -2695,6 +2695,24 @@ config MITIGATION_ITS - disabled, mitigation cannot be enabled via cmdline. - See - -+config MITIGATION_TSA -+ bool "Mitigate Transient Scheduler Attacks" -+ depends on CPU_SUP_AMD -+ default y -+ help -+ Enable mitigation for Transient Scheduler Attacks. TSA is a hardware -+ security vulnerability on AMD CPUs which can lead to forwarding of -+ invalid info to subsequent instructions and thus can affect their -+ timing and thereby cause a leakage. -+ -+config MITIGATION_VMSCAPE -+ bool "Mitigate VMSCAPE" -+ depends on KVM -+ default y -+ help -+ Enable mitigation for VMSCAPE attacks. VMSCAPE is a hardware security -+ vulnerability on Intel and AMD CPUs that may allow a guest to do -+ Spectre v2 style attacks on userspace hypervisor. - endif - - config ARCH_HAS_ADD_PAGES -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/alternative.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/alternative.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/alternative.c 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/alternative.c 2025-10-22 13:53:56.387169758 -0400 -@@ -116,6 +116,24 @@ static struct module *its_mod; - #endif - static void *its_page; - static unsigned int its_offset; -+struct its_array its_pages; -+ -+static void *__its_alloc(struct its_array *pages) -+{ -+ void *page __free(execmem) = execmem_alloc(EXECMEM_MODULE_TEXT, PAGE_SIZE); -+ if (!page) -+ return NULL; -+ -+ void *tmp = krealloc(pages->pages, (pages->num+1) * sizeof(void *), -+ GFP_KERNEL); -+ if (!tmp) -+ return NULL; -+ -+ pages->pages = tmp; -+ pages->pages[pages->num++] = page; -+ -+ return no_free_ptr(page); -+} - - /* Initialize a thunk with the "jmp *reg; int3" instructions. */ - static void *its_init_thunk(void *thunk, int reg) -@@ -151,6 +169,21 @@ static void *its_init_thunk(void *thunk, - return thunk + offset; - } - -+static void its_pages_protect(struct its_array *pages) -+{ -+ for (int i = 0; i < pages->num; i++) { -+ void *page = pages->pages[i]; -+ execmem_restore_rox(page, PAGE_SIZE); -+ } -+} -+ -+static void its_fini_core(void) -+{ -+ if (IS_ENABLED(CONFIG_STRICT_KERNEL_RWX)) -+ its_pages_protect(&its_pages); -+ kfree(its_pages.pages); -+} -+ - #ifdef CONFIG_MODULES - void its_init_mod(struct module *mod) - { -@@ -173,10 +206,8 @@ void its_fini_mod(struct module *mod) - its_page = NULL; - mutex_unlock(&text_mutex); - -- for (int i = 0; i < mod->its_num_pages; i++) { -- void *page = mod->its_page_array[i]; -- execmem_restore_rox(page, PAGE_SIZE); -- } -+ if (IS_ENABLED(CONFIG_STRICT_MODULE_RWX)) -+ its_pages_protect(&mod->arch.its_pages); - } - - void its_free_mod(struct module *mod) -@@ -184,37 +215,33 @@ void its_free_mod(struct module *mod) - if (!cpu_feature_enabled(X86_FEATURE_INDIRECT_THUNK_ITS)) - return; - -- for (int i = 0; i < mod->its_num_pages; i++) { -- void *page = mod->its_page_array[i]; -+ for (int i = 0; i < mod->arch.its_pages.num; i++) { -+ void *page = mod->arch.its_pages.pages[i]; - execmem_free(page); - } -- kfree(mod->its_page_array); -+ kfree(mod->arch.its_pages.pages); - } - #endif /* CONFIG_MODULES */ - - static void *its_alloc(void) - { -- void *page __free(execmem) = execmem_alloc(EXECMEM_MODULE_TEXT, PAGE_SIZE); -- -- if (!page) -- return NULL; -+ struct its_array *pages = &its_pages; -+ void *page; - - #ifdef CONFIG_MODULES -- if (its_mod) { -- void *tmp = krealloc(its_mod->its_page_array, -- (its_mod->its_num_pages+1) * sizeof(void *), -- GFP_KERNEL); -- if (!tmp) -- return NULL; -+ if (its_mod) -+ pages = &its_mod->arch.its_pages; -+#endif - -- its_mod->its_page_array = tmp; -- its_mod->its_page_array[its_mod->its_num_pages++] = page; -+ page = __its_alloc(pages); -+ if (!page) -+ return NULL; - -- execmem_make_temp_rw(page, PAGE_SIZE); -- } --#endif /* CONFIG_MODULES */ -+ execmem_make_temp_rw(page, PAGE_SIZE); -+ if (pages == &its_pages) -+ set_memory_x((unsigned long)page, 1); - -- return no_free_ptr(page); -+ return page; - } - - static void *its_allocate_thunk(int reg) -@@ -268,7 +295,9 @@ u8 *its_static_thunk(int reg) - return thunk; - } - --#endif -+#else -+static inline void its_fini_core(void) {} -+#endif /* CONFIG_MITIGATION_ITS */ - - /* - * Nomenclature for variable names to simplify and clarify this code and ease -@@ -2338,6 +2367,8 @@ void __init alternative_instructions(voi - apply_retpolines(__retpoline_sites, __retpoline_sites_end); - apply_returns(__return_sites, __return_sites_end); - -+ its_fini_core(); -+ - /* - * Adjust all CALL instructions to point to func()-10, including - * those in .altinstr_replacement. -@@ -3107,6 +3138,6 @@ void __ref smp_text_poke_batch_add(void - */ - void __ref smp_text_poke_single(void *addr, const void *opcode, size_t len, const void *emulate) - { -- __smp_text_poke_batch_add(addr, opcode, len, emulate); -+ smp_text_poke_batch_add(addr, opcode, len, emulate); - smp_text_poke_batch_finish(); - } -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/cpu/amd.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/amd.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/cpu/amd.c 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/amd.c 2025-10-22 13:53:56.391169739 -0400 -@@ -9,7 +9,7 @@ - #include - #include - #include --#include -+#include - #include - #include - #include -@@ -31,7 +31,7 @@ - - #include "cpu.h" - --u16 invlpgb_count_max __ro_after_init; -+u16 invlpgb_count_max __ro_after_init = 1; - - static inline int rdmsrq_amd_safe(unsigned msr, u64 *p) - { -@@ -377,6 +377,47 @@ static void bsp_determine_snp(struct cpu - #endif - } - -+#define ZEN_MODEL_STEP_UCODE(fam, model, step, ucode) \ -+ X86_MATCH_VFM_STEPS(VFM_MAKE(X86_VENDOR_AMD, fam, model), \ -+ step, step, ucode) -+ -+static const struct x86_cpu_id amd_tsa_microcode[] = { -+ ZEN_MODEL_STEP_UCODE(0x19, 0x01, 0x1, 0x0a0011d7), -+ ZEN_MODEL_STEP_UCODE(0x19, 0x01, 0x2, 0x0a00123b), -+ ZEN_MODEL_STEP_UCODE(0x19, 0x08, 0x2, 0x0a00820d), -+ ZEN_MODEL_STEP_UCODE(0x19, 0x11, 0x1, 0x0a10114c), -+ ZEN_MODEL_STEP_UCODE(0x19, 0x11, 0x2, 0x0a10124c), -+ ZEN_MODEL_STEP_UCODE(0x19, 0x18, 0x1, 0x0a108109), -+ ZEN_MODEL_STEP_UCODE(0x19, 0x21, 0x0, 0x0a20102e), -+ ZEN_MODEL_STEP_UCODE(0x19, 0x21, 0x2, 0x0a201211), -+ ZEN_MODEL_STEP_UCODE(0x19, 0x44, 0x1, 0x0a404108), -+ ZEN_MODEL_STEP_UCODE(0x19, 0x50, 0x0, 0x0a500012), -+ ZEN_MODEL_STEP_UCODE(0x19, 0x61, 0x2, 0x0a60120a), -+ ZEN_MODEL_STEP_UCODE(0x19, 0x74, 0x1, 0x0a704108), -+ ZEN_MODEL_STEP_UCODE(0x19, 0x75, 0x2, 0x0a705208), -+ ZEN_MODEL_STEP_UCODE(0x19, 0x78, 0x0, 0x0a708008), -+ ZEN_MODEL_STEP_UCODE(0x19, 0x7c, 0x0, 0x0a70c008), -+ ZEN_MODEL_STEP_UCODE(0x19, 0xa0, 0x2, 0x0aa00216), -+ {}, -+}; -+ -+static void tsa_init(struct cpuinfo_x86 *c) -+{ -+ if (cpu_has(c, X86_FEATURE_HYPERVISOR)) -+ return; -+ -+ if (cpu_has(c, X86_FEATURE_ZEN3) || -+ cpu_has(c, X86_FEATURE_ZEN4)) { -+ if (x86_match_min_microcode_rev(amd_tsa_microcode)) -+ setup_force_cpu_cap(X86_FEATURE_VERW_CLEAR); -+ else -+ pr_debug("%s: current revision: 0x%x\n", __func__, c->microcode); -+ } else { -+ setup_force_cpu_cap(X86_FEATURE_TSA_SQ_NO); -+ setup_force_cpu_cap(X86_FEATURE_TSA_L1_NO); -+ } -+} -+ - static void bsp_init_amd(struct cpuinfo_x86 *c) - { - if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) { -@@ -489,6 +530,9 @@ static void bsp_init_amd(struct cpuinfo_ - } - - bsp_determine_snp(c); -+ -+ tsa_init(c); -+ - return; - - warn: -@@ -930,6 +974,16 @@ static void init_amd_zen2(struct cpuinfo - init_spectral_chicken(c); - fix_erratum_1386(c); - zen2_zenbleed_check(c); -+ -+ /* Disable RDSEED on AMD Cyan Skillfish because of an error. */ -+ if (c->x86_model == 0x47 && c->x86_stepping == 0x0) { -+ clear_cpu_cap(c, X86_FEATURE_RDSEED); -+ msr_clear_bit(MSR_AMD64_CPUID_FN_7, 18); -+ pr_emerg("RDSEED is not reliable on this platform; disabling.\n"); -+ } -+ -+ /* Correct misconfigured CPUID on some clients. */ -+ clear_cpu_cap(c, X86_FEATURE_INVLPGB); - } - - static void init_amd_zen3(struct cpuinfo_x86 *c) -@@ -1270,8 +1324,8 @@ static const char * const s5_reset_reaso - - static __init int print_s5_reset_status_mmio(void) - { -- unsigned long value; - void __iomem *addr; -+ u32 value; - int i; - - if (!cpu_feature_enabled(X86_FEATURE_ZEN)) -@@ -1284,12 +1338,16 @@ static __init int print_s5_reset_status_ - value = ioread32(addr); - iounmap(addr); - -+ /* Value with "all bits set" is an error response and should be ignored. */ -+ if (value == U32_MAX) -+ return 0; -+ - for (i = 0; i < ARRAY_SIZE(s5_reset_reason_txt); i++) { - if (!(value & BIT(i))) - continue; - - if (s5_reset_reason_txt[i]) { -- pr_info("x86/amd: Previous system reset reason [0x%08lx]: %s\n", -+ pr_info("x86/amd: Previous system reset reason [0x%08x]: %s\n", - value, s5_reset_reason_txt[i]); - } - } -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/cpu/bugs.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/bugs.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/cpu/bugs.c 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/bugs.c 2025-10-22 13:53:56.391169739 -0400 -@@ -94,6 +94,11 @@ static void __init bhi_apply_mitigation( - static void __init its_select_mitigation(void); - static void __init its_update_mitigation(void); - static void __init its_apply_mitigation(void); -+static void __init tsa_select_mitigation(void); -+static void __init tsa_apply_mitigation(void); -+static void __init vmscape_select_mitigation(void); -+static void __init vmscape_update_mitigation(void); -+static void __init vmscape_apply_mitigation(void); - - /* The base value of the SPEC_CTRL MSR without task-specific bits set */ - u64 x86_spec_ctrl_base; -@@ -103,6 +108,14 @@ EXPORT_SYMBOL_GPL(x86_spec_ctrl_base); - DEFINE_PER_CPU(u64, x86_spec_ctrl_current); - EXPORT_PER_CPU_SYMBOL_GPL(x86_spec_ctrl_current); - -+/* -+ * Set when the CPU has run a potentially malicious guest. An IBPB will -+ * be needed to before running userspace. That IBPB will flush the branch -+ * predictor content. -+ */ -+DEFINE_PER_CPU(bool, x86_ibpb_exit_to_user); -+EXPORT_PER_CPU_SYMBOL_GPL(x86_ibpb_exit_to_user); -+ - u64 x86_pred_cmd __ro_after_init = PRED_CMD_IBPB; - - static u64 __ro_after_init x86_arch_cap_msr; -@@ -113,10 +126,9 @@ void (*x86_return_thunk)(void) __ro_afte - - static void __init set_return_thunk(void *thunk) - { -- if (x86_return_thunk != __x86_return_thunk) -- pr_warn("x86/bugs: return thunk changed\n"); -- - x86_return_thunk = thunk; -+ -+ pr_info("active return thunk: %ps\n", thunk); - } - - /* Update SPEC_CTRL MSR and its cached copy unconditionally */ -@@ -169,9 +181,9 @@ DEFINE_STATIC_KEY_FALSE(switch_mm_always - DEFINE_STATIC_KEY_FALSE(switch_vcpu_ibpb); - EXPORT_SYMBOL_GPL(switch_vcpu_ibpb); - --/* Control MDS CPU buffer clear before idling (halt, mwait) */ --DEFINE_STATIC_KEY_FALSE(mds_idle_clear); --EXPORT_SYMBOL_GPL(mds_idle_clear); -+/* Control CPU buffer clear before idling (halt, mwait) */ -+DEFINE_STATIC_KEY_FALSE(cpu_buf_idle_clear); -+EXPORT_SYMBOL_GPL(cpu_buf_idle_clear); - - /* - * Controls whether l1d flush based mitigations are enabled, -@@ -225,6 +237,8 @@ void __init cpu_select_mitigations(void) - gds_select_mitigation(); - its_select_mitigation(); - bhi_select_mitigation(); -+ tsa_select_mitigation(); -+ vmscape_select_mitigation(); - - /* - * After mitigations are selected, some may need to update their -@@ -256,6 +270,7 @@ void __init cpu_select_mitigations(void) - bhi_update_mitigation(); - /* srso_update_mitigation() depends on retbleed_update_mitigation(). */ - srso_update_mitigation(); -+ vmscape_update_mitigation(); - - spectre_v1_apply_mitigation(); - spectre_v2_apply_mitigation(); -@@ -272,6 +287,8 @@ void __init cpu_select_mitigations(void) - gds_apply_mitigation(); - its_apply_mitigation(); - bhi_apply_mitigation(); -+ tsa_apply_mitigation(); -+ vmscape_apply_mitigation(); - } - - /* -@@ -637,7 +654,7 @@ static void __init mmio_apply_mitigation - * is required irrespective of SMT state. - */ - if (!(x86_arch_cap_msr & ARCH_CAP_FBSDP_NO)) -- static_branch_enable(&mds_idle_clear); -+ static_branch_enable(&cpu_buf_idle_clear); - - if (mmio_nosmt || cpu_mitigations_auto_nosmt()) - cpu_smt_disable(false); -@@ -1120,6 +1137,20 @@ early_param("nospectre_v1", nospectre_v1 - - enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init = SPECTRE_V2_NONE; - -+/* Depends on spectre_v2 mitigation selected already */ -+static inline bool cdt_possible(enum spectre_v2_mitigation mode) -+{ -+ if (!IS_ENABLED(CONFIG_MITIGATION_CALL_DEPTH_TRACKING) || -+ !IS_ENABLED(CONFIG_MITIGATION_RETPOLINE)) -+ return false; -+ -+ if (mode == SPECTRE_V2_RETPOLINE || -+ mode == SPECTRE_V2_EIBRS_RETPOLINE) -+ return true; -+ -+ return false; -+} -+ - #undef pr_fmt - #define pr_fmt(fmt) "RETBleed: " fmt - -@@ -1247,6 +1278,14 @@ static void __init retbleed_select_mitig - retbleed_mitigation = RETBLEED_MITIGATION_IBPB; - else - retbleed_mitigation = RETBLEED_MITIGATION_NONE; -+ } else if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) { -+ /* Final mitigation depends on spectre-v2 selection */ -+ if (boot_cpu_has(X86_FEATURE_IBRS_ENHANCED)) -+ retbleed_mitigation = RETBLEED_MITIGATION_EIBRS; -+ else if (boot_cpu_has(X86_FEATURE_IBRS)) -+ retbleed_mitigation = RETBLEED_MITIGATION_IBRS; -+ else -+ retbleed_mitigation = RETBLEED_MITIGATION_NONE; - } - } - -@@ -1255,27 +1294,16 @@ static void __init retbleed_update_mitig - if (!boot_cpu_has_bug(X86_BUG_RETBLEED) || cpu_mitigations_off()) - return; - -- if (retbleed_mitigation == RETBLEED_MITIGATION_NONE) -- goto out; -- -- /* -- * retbleed=stuff is only allowed on Intel. If stuffing can't be used -- * then a different mitigation will be selected below. -- * -- * its=stuff will also attempt to enable stuffing. -- */ -- if (retbleed_mitigation == RETBLEED_MITIGATION_STUFF || -- its_mitigation == ITS_MITIGATION_RETPOLINE_STUFF) { -- if (spectre_v2_enabled != SPECTRE_V2_RETPOLINE) { -- pr_err("WARNING: retbleed=stuff depends on spectre_v2=retpoline\n"); -- retbleed_mitigation = RETBLEED_MITIGATION_AUTO; -- } else { -- if (retbleed_mitigation != RETBLEED_MITIGATION_STUFF) -- pr_info("Retbleed mitigation updated to stuffing\n"); -- -- retbleed_mitigation = RETBLEED_MITIGATION_STUFF; -- } -+ /* ITS can also enable stuffing */ -+ if (its_mitigation == ITS_MITIGATION_RETPOLINE_STUFF) -+ retbleed_mitigation = RETBLEED_MITIGATION_STUFF; -+ -+ if (retbleed_mitigation == RETBLEED_MITIGATION_STUFF && -+ !cdt_possible(spectre_v2_enabled)) { -+ pr_err("WARNING: retbleed=stuff depends on retpoline\n"); -+ retbleed_mitigation = RETBLEED_MITIGATION_NONE; - } -+ - /* - * Let IBRS trump all on Intel without affecting the effects of the - * retbleed= cmdline option except for call depth based stuffing -@@ -1294,15 +1322,11 @@ static void __init retbleed_update_mitig - if (retbleed_mitigation != RETBLEED_MITIGATION_STUFF) - pr_err(RETBLEED_INTEL_MSG); - } -- /* If nothing has set the mitigation yet, default to NONE. */ -- if (retbleed_mitigation == RETBLEED_MITIGATION_AUTO) -- retbleed_mitigation = RETBLEED_MITIGATION_NONE; - } --out: -+ - pr_info("%s\n", retbleed_strings[retbleed_mitigation]); - } - -- - static void __init retbleed_apply_mitigation(void) - { - bool mitigate_smt = false; -@@ -1449,6 +1473,7 @@ static void __init its_update_mitigation - its_mitigation = ITS_MITIGATION_OFF; - break; - case SPECTRE_V2_RETPOLINE: -+ case SPECTRE_V2_EIBRS_RETPOLINE: - /* Retpoline+CDT mitigates ITS */ - if (retbleed_mitigation == RETBLEED_MITIGATION_STUFF) - its_mitigation = ITS_MITIGATION_RETPOLINE_STUFF; -@@ -1488,6 +1513,94 @@ static void __init its_apply_mitigation( - } - - #undef pr_fmt -+#define pr_fmt(fmt) "Transient Scheduler Attacks: " fmt -+ -+enum tsa_mitigations { -+ TSA_MITIGATION_NONE, -+ TSA_MITIGATION_AUTO, -+ TSA_MITIGATION_UCODE_NEEDED, -+ TSA_MITIGATION_USER_KERNEL, -+ TSA_MITIGATION_VM, -+ TSA_MITIGATION_FULL, -+}; -+ -+static const char * const tsa_strings[] = { -+ [TSA_MITIGATION_NONE] = "Vulnerable", -+ [TSA_MITIGATION_UCODE_NEEDED] = "Vulnerable: No microcode", -+ [TSA_MITIGATION_USER_KERNEL] = "Mitigation: Clear CPU buffers: user/kernel boundary", -+ [TSA_MITIGATION_VM] = "Mitigation: Clear CPU buffers: VM", -+ [TSA_MITIGATION_FULL] = "Mitigation: Clear CPU buffers", -+}; -+ -+static enum tsa_mitigations tsa_mitigation __ro_after_init = -+ IS_ENABLED(CONFIG_MITIGATION_TSA) ? TSA_MITIGATION_AUTO : TSA_MITIGATION_NONE; -+ -+static int __init tsa_parse_cmdline(char *str) -+{ -+ if (!str) -+ return -EINVAL; -+ -+ if (!strcmp(str, "off")) -+ tsa_mitigation = TSA_MITIGATION_NONE; -+ else if (!strcmp(str, "on")) -+ tsa_mitigation = TSA_MITIGATION_FULL; -+ else if (!strcmp(str, "user")) -+ tsa_mitigation = TSA_MITIGATION_USER_KERNEL; -+ else if (!strcmp(str, "vm")) -+ tsa_mitigation = TSA_MITIGATION_VM; -+ else -+ pr_err("Ignoring unknown tsa=%s option.\n", str); -+ -+ return 0; -+} -+early_param("tsa", tsa_parse_cmdline); -+ -+static void __init tsa_select_mitigation(void) -+{ -+ if (cpu_mitigations_off() || !boot_cpu_has_bug(X86_BUG_TSA)) { -+ tsa_mitigation = TSA_MITIGATION_NONE; -+ return; -+ } -+ -+ if (tsa_mitigation == TSA_MITIGATION_NONE) -+ return; -+ -+ if (!boot_cpu_has(X86_FEATURE_VERW_CLEAR)) { -+ tsa_mitigation = TSA_MITIGATION_UCODE_NEEDED; -+ goto out; -+ } -+ -+ if (tsa_mitigation == TSA_MITIGATION_AUTO) -+ tsa_mitigation = TSA_MITIGATION_FULL; -+ -+ /* -+ * No need to set verw_clear_cpu_buf_mitigation_selected - it -+ * doesn't fit all cases here and it is not needed because this -+ * is the only VERW-based mitigation on AMD. -+ */ -+out: -+ pr_info("%s\n", tsa_strings[tsa_mitigation]); -+} -+ -+static void __init tsa_apply_mitigation(void) -+{ -+ switch (tsa_mitigation) { -+ case TSA_MITIGATION_USER_KERNEL: -+ setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF); -+ break; -+ case TSA_MITIGATION_VM: -+ setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF_VM); -+ break; -+ case TSA_MITIGATION_FULL: -+ setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF); -+ setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF_VM); -+ break; -+ default: -+ break; -+ } -+} -+ -+#undef pr_fmt - #define pr_fmt(fmt) "Spectre V2 : " fmt - - static enum spectre_v2_user_mitigation spectre_v2_user_stibp __ro_after_init = -@@ -2249,74 +2362,11 @@ static void update_mds_branch_idle(void) - return; - - if (sched_smt_active()) { -- static_branch_enable(&mds_idle_clear); -+ static_branch_enable(&cpu_buf_idle_clear); - } else if (mmio_mitigation == MMIO_MITIGATION_OFF || - (x86_arch_cap_msr & ARCH_CAP_FBSDP_NO)) { -- static_branch_disable(&mds_idle_clear); -- } --} -- --#define MDS_MSG_SMT "MDS CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/mds.html for more details.\n" --#define TAA_MSG_SMT "TAA CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/tsx_async_abort.html for more details.\n" --#define MMIO_MSG_SMT "MMIO Stale Data CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/processor_mmio_stale_data.html for more details.\n" -- --void cpu_bugs_smt_update(void) --{ -- mutex_lock(&spec_ctrl_mutex); -- -- if (sched_smt_active() && unprivileged_ebpf_enabled() && -- spectre_v2_enabled == SPECTRE_V2_EIBRS_LFENCE) -- pr_warn_once(SPECTRE_V2_EIBRS_LFENCE_EBPF_SMT_MSG); -- -- switch (spectre_v2_user_stibp) { -- case SPECTRE_V2_USER_NONE: -- break; -- case SPECTRE_V2_USER_STRICT: -- case SPECTRE_V2_USER_STRICT_PREFERRED: -- update_stibp_strict(); -- break; -- case SPECTRE_V2_USER_PRCTL: -- case SPECTRE_V2_USER_SECCOMP: -- update_indir_branch_cond(); -- break; -- } -- -- switch (mds_mitigation) { -- case MDS_MITIGATION_FULL: -- case MDS_MITIGATION_AUTO: -- case MDS_MITIGATION_VMWERV: -- if (sched_smt_active() && !boot_cpu_has(X86_BUG_MSBDS_ONLY)) -- pr_warn_once(MDS_MSG_SMT); -- update_mds_branch_idle(); -- break; -- case MDS_MITIGATION_OFF: -- break; -- } -- -- switch (taa_mitigation) { -- case TAA_MITIGATION_VERW: -- case TAA_MITIGATION_AUTO: -- case TAA_MITIGATION_UCODE_NEEDED: -- if (sched_smt_active()) -- pr_warn_once(TAA_MSG_SMT); -- break; -- case TAA_MITIGATION_TSX_DISABLED: -- case TAA_MITIGATION_OFF: -- break; -- } -- -- switch (mmio_mitigation) { -- case MMIO_MITIGATION_VERW: -- case MMIO_MITIGATION_AUTO: -- case MMIO_MITIGATION_UCODE_NEEDED: -- if (sched_smt_active()) -- pr_warn_once(MMIO_MSG_SMT); -- break; -- case MMIO_MITIGATION_OFF: -- break; -+ static_branch_disable(&cpu_buf_idle_clear); - } -- -- mutex_unlock(&spec_ctrl_mutex); - } - - #undef pr_fmt -@@ -3020,8 +3070,184 @@ static void __init srso_apply_mitigation - } - - #undef pr_fmt -+#define pr_fmt(fmt) "VMSCAPE: " fmt -+ -+enum vmscape_mitigations { -+ VMSCAPE_MITIGATION_NONE, -+ VMSCAPE_MITIGATION_AUTO, -+ VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER, -+ VMSCAPE_MITIGATION_IBPB_ON_VMEXIT, -+}; -+ -+static const char * const vmscape_strings[] = { -+ [VMSCAPE_MITIGATION_NONE] = "Vulnerable", -+ /* [VMSCAPE_MITIGATION_AUTO] */ -+ [VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER] = "Mitigation: IBPB before exit to userspace", -+ [VMSCAPE_MITIGATION_IBPB_ON_VMEXIT] = "Mitigation: IBPB on VMEXIT", -+}; -+ -+static enum vmscape_mitigations vmscape_mitigation __ro_after_init = -+ IS_ENABLED(CONFIG_MITIGATION_VMSCAPE) ? VMSCAPE_MITIGATION_AUTO : VMSCAPE_MITIGATION_NONE; -+ -+static int __init vmscape_parse_cmdline(char *str) -+{ -+ if (!str) -+ return -EINVAL; -+ -+ if (!strcmp(str, "off")) { -+ vmscape_mitigation = VMSCAPE_MITIGATION_NONE; -+ } else if (!strcmp(str, "ibpb")) { -+ vmscape_mitigation = VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER; -+ } else if (!strcmp(str, "force")) { -+ setup_force_cpu_bug(X86_BUG_VMSCAPE); -+ vmscape_mitigation = VMSCAPE_MITIGATION_AUTO; -+ } else { -+ pr_err("Ignoring unknown vmscape=%s option.\n", str); -+ } -+ -+ return 0; -+} -+early_param("vmscape", vmscape_parse_cmdline); -+ -+static void __init vmscape_select_mitigation(void) -+{ -+ if (cpu_mitigations_off() || -+ !boot_cpu_has_bug(X86_BUG_VMSCAPE) || -+ !boot_cpu_has(X86_FEATURE_IBPB)) { -+ vmscape_mitigation = VMSCAPE_MITIGATION_NONE; -+ return; -+ } -+ -+ if (vmscape_mitigation == VMSCAPE_MITIGATION_AUTO) -+ vmscape_mitigation = VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER; -+} -+ -+static void __init vmscape_update_mitigation(void) -+{ -+ if (!boot_cpu_has_bug(X86_BUG_VMSCAPE)) -+ return; -+ -+ if (retbleed_mitigation == RETBLEED_MITIGATION_IBPB || -+ srso_mitigation == SRSO_MITIGATION_IBPB_ON_VMEXIT) -+ vmscape_mitigation = VMSCAPE_MITIGATION_IBPB_ON_VMEXIT; -+ -+ pr_info("%s\n", vmscape_strings[vmscape_mitigation]); -+} -+ -+static void __init vmscape_apply_mitigation(void) -+{ -+ if (vmscape_mitigation == VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER) -+ setup_force_cpu_cap(X86_FEATURE_IBPB_EXIT_TO_USER); -+} -+ -+#undef pr_fmt - #define pr_fmt(fmt) fmt - -+#define MDS_MSG_SMT "MDS CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/mds.html for more details.\n" -+#define TAA_MSG_SMT "TAA CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/tsx_async_abort.html for more details.\n" -+#define MMIO_MSG_SMT "MMIO Stale Data CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/processor_mmio_stale_data.html for more details.\n" -+#define VMSCAPE_MSG_SMT "VMSCAPE: SMT on, STIBP is required for full protection. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/vmscape.html for more details.\n" -+ -+void cpu_bugs_smt_update(void) -+{ -+ mutex_lock(&spec_ctrl_mutex); -+ -+ if (sched_smt_active() && unprivileged_ebpf_enabled() && -+ spectre_v2_enabled == SPECTRE_V2_EIBRS_LFENCE) -+ pr_warn_once(SPECTRE_V2_EIBRS_LFENCE_EBPF_SMT_MSG); -+ -+ switch (spectre_v2_user_stibp) { -+ case SPECTRE_V2_USER_NONE: -+ break; -+ case SPECTRE_V2_USER_STRICT: -+ case SPECTRE_V2_USER_STRICT_PREFERRED: -+ update_stibp_strict(); -+ break; -+ case SPECTRE_V2_USER_PRCTL: -+ case SPECTRE_V2_USER_SECCOMP: -+ update_indir_branch_cond(); -+ break; -+ } -+ -+ switch (mds_mitigation) { -+ case MDS_MITIGATION_FULL: -+ case MDS_MITIGATION_AUTO: -+ case MDS_MITIGATION_VMWERV: -+ if (sched_smt_active() && !boot_cpu_has(X86_BUG_MSBDS_ONLY)) -+ pr_warn_once(MDS_MSG_SMT); -+ update_mds_branch_idle(); -+ break; -+ case MDS_MITIGATION_OFF: -+ break; -+ } -+ -+ switch (taa_mitigation) { -+ case TAA_MITIGATION_VERW: -+ case TAA_MITIGATION_AUTO: -+ case TAA_MITIGATION_UCODE_NEEDED: -+ if (sched_smt_active()) -+ pr_warn_once(TAA_MSG_SMT); -+ break; -+ case TAA_MITIGATION_TSX_DISABLED: -+ case TAA_MITIGATION_OFF: -+ break; -+ } -+ -+ switch (mmio_mitigation) { -+ case MMIO_MITIGATION_VERW: -+ case MMIO_MITIGATION_AUTO: -+ case MMIO_MITIGATION_UCODE_NEEDED: -+ if (sched_smt_active()) -+ pr_warn_once(MMIO_MSG_SMT); -+ break; -+ case MMIO_MITIGATION_OFF: -+ break; -+ } -+ -+ switch (tsa_mitigation) { -+ case TSA_MITIGATION_USER_KERNEL: -+ case TSA_MITIGATION_VM: -+ case TSA_MITIGATION_AUTO: -+ case TSA_MITIGATION_FULL: -+ /* -+ * TSA-SQ can potentially lead to info leakage between -+ * SMT threads. -+ */ -+ if (sched_smt_active()) -+ static_branch_enable(&cpu_buf_idle_clear); -+ else -+ static_branch_disable(&cpu_buf_idle_clear); -+ break; -+ case TSA_MITIGATION_NONE: -+ case TSA_MITIGATION_UCODE_NEEDED: -+ break; -+ } -+ -+ switch (vmscape_mitigation) { -+ case VMSCAPE_MITIGATION_NONE: -+ case VMSCAPE_MITIGATION_AUTO: -+ break; -+ case VMSCAPE_MITIGATION_IBPB_ON_VMEXIT: -+ case VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER: -+ /* -+ * Hypervisors can be attacked across-threads, warn for SMT when -+ * STIBP is not already enabled system-wide. -+ * -+ * Intel eIBRS (!AUTOIBRS) implies STIBP on. -+ */ -+ if (!sched_smt_active() || -+ spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT || -+ spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED || -+ (spectre_v2_in_eibrs_mode(spectre_v2_enabled) && -+ !boot_cpu_has(X86_FEATURE_AUTOIBRS))) -+ break; -+ pr_warn_once(VMSCAPE_MSG_SMT); -+ break; -+ } -+ -+ mutex_unlock(&spec_ctrl_mutex); -+} -+ - #ifdef CONFIG_SYSFS - - #define L1TF_DEFAULT_MSG "Mitigation: PTE Inversion" -@@ -3265,6 +3491,16 @@ static ssize_t gds_show_state(char *buf) - return sysfs_emit(buf, "%s\n", gds_strings[gds_mitigation]); - } - -+static ssize_t tsa_show_state(char *buf) -+{ -+ return sysfs_emit(buf, "%s\n", tsa_strings[tsa_mitigation]); -+} -+ -+static ssize_t vmscape_show_state(char *buf) -+{ -+ return sysfs_emit(buf, "%s\n", vmscape_strings[vmscape_mitigation]); -+} -+ - static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr, - char *buf, unsigned int bug) - { -@@ -3328,6 +3564,12 @@ static ssize_t cpu_show_common(struct de - case X86_BUG_ITS: - return its_show_state(buf); - -+ case X86_BUG_TSA: -+ return tsa_show_state(buf); -+ -+ case X86_BUG_VMSCAPE: -+ return vmscape_show_state(buf); -+ - default: - break; - } -@@ -3414,6 +3656,16 @@ ssize_t cpu_show_indirect_target_selecti - { - return cpu_show_common(dev, attr, buf, X86_BUG_ITS); - } -+ -+ssize_t cpu_show_tsa(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ return cpu_show_common(dev, attr, buf, X86_BUG_TSA); -+} -+ -+ssize_t cpu_show_vmscape(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ return cpu_show_common(dev, attr, buf, X86_BUG_VMSCAPE); -+} - #endif - - void __warn_thunk(void) -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/cpu/common.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/common.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/cpu/common.c 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/common.c 2025-10-22 13:53:56.391169739 -0400 -@@ -1233,55 +1233,73 @@ static const __initconst struct x86_cpu_ - #define ITS BIT(8) - /* CPU is affected by Indirect Target Selection, but guest-host isolation is not affected */ - #define ITS_NATIVE_ONLY BIT(9) -+/* CPU is affected by Transient Scheduler Attacks */ -+#define TSA BIT(10) -+/* CPU is affected by VMSCAPE */ -+#define VMSCAPE BIT(11) - - static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = { -- VULNBL_INTEL_STEPS(INTEL_IVYBRIDGE, X86_STEP_MAX, SRBDS), -- VULNBL_INTEL_STEPS(INTEL_HASWELL, X86_STEP_MAX, SRBDS), -- VULNBL_INTEL_STEPS(INTEL_HASWELL_L, X86_STEP_MAX, SRBDS), -- VULNBL_INTEL_STEPS(INTEL_HASWELL_G, X86_STEP_MAX, SRBDS), -- VULNBL_INTEL_STEPS(INTEL_HASWELL_X, X86_STEP_MAX, MMIO), -- VULNBL_INTEL_STEPS(INTEL_BROADWELL_D, X86_STEP_MAX, MMIO), -- VULNBL_INTEL_STEPS(INTEL_BROADWELL_G, X86_STEP_MAX, SRBDS), -- VULNBL_INTEL_STEPS(INTEL_BROADWELL_X, X86_STEP_MAX, MMIO), -- VULNBL_INTEL_STEPS(INTEL_BROADWELL, X86_STEP_MAX, SRBDS), -- VULNBL_INTEL_STEPS(INTEL_SKYLAKE_X, 0x5, MMIO | RETBLEED | GDS), -- VULNBL_INTEL_STEPS(INTEL_SKYLAKE_X, X86_STEP_MAX, MMIO | RETBLEED | GDS | ITS), -- VULNBL_INTEL_STEPS(INTEL_SKYLAKE_L, X86_STEP_MAX, MMIO | RETBLEED | GDS | SRBDS), -- VULNBL_INTEL_STEPS(INTEL_SKYLAKE, X86_STEP_MAX, MMIO | RETBLEED | GDS | SRBDS), -- VULNBL_INTEL_STEPS(INTEL_KABYLAKE_L, 0xb, MMIO | RETBLEED | GDS | SRBDS), -- VULNBL_INTEL_STEPS(INTEL_KABYLAKE_L, X86_STEP_MAX, MMIO | RETBLEED | GDS | SRBDS | ITS), -- VULNBL_INTEL_STEPS(INTEL_KABYLAKE, 0xc, MMIO | RETBLEED | GDS | SRBDS), -- VULNBL_INTEL_STEPS(INTEL_KABYLAKE, X86_STEP_MAX, MMIO | RETBLEED | GDS | SRBDS | ITS), -- VULNBL_INTEL_STEPS(INTEL_CANNONLAKE_L, X86_STEP_MAX, RETBLEED), -+ VULNBL_INTEL_STEPS(INTEL_SANDYBRIDGE_X, X86_STEP_MAX, VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_SANDYBRIDGE, X86_STEP_MAX, VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_IVYBRIDGE_X, X86_STEP_MAX, VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_IVYBRIDGE, X86_STEP_MAX, SRBDS | VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_HASWELL, X86_STEP_MAX, SRBDS | VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_HASWELL_L, X86_STEP_MAX, SRBDS | VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_HASWELL_G, X86_STEP_MAX, SRBDS | VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_HASWELL_X, X86_STEP_MAX, MMIO | VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_BROADWELL_D, X86_STEP_MAX, MMIO | VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_BROADWELL_X, X86_STEP_MAX, MMIO | VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_BROADWELL_G, X86_STEP_MAX, SRBDS | VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_BROADWELL, X86_STEP_MAX, SRBDS | VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_SKYLAKE_X, 0x5, MMIO | RETBLEED | GDS | VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_SKYLAKE_X, X86_STEP_MAX, MMIO | RETBLEED | GDS | ITS | VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_SKYLAKE_L, X86_STEP_MAX, MMIO | RETBLEED | GDS | SRBDS | VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_SKYLAKE, X86_STEP_MAX, MMIO | RETBLEED | GDS | SRBDS | VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_KABYLAKE_L, 0xb, MMIO | RETBLEED | GDS | SRBDS | VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_KABYLAKE_L, X86_STEP_MAX, MMIO | RETBLEED | GDS | SRBDS | ITS | VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_KABYLAKE, 0xc, MMIO | RETBLEED | GDS | SRBDS | VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_KABYLAKE, X86_STEP_MAX, MMIO | RETBLEED | GDS | SRBDS | ITS | VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_CANNONLAKE_L, X86_STEP_MAX, RETBLEED | VMSCAPE), - VULNBL_INTEL_STEPS(INTEL_ICELAKE_L, X86_STEP_MAX, MMIO | MMIO_SBDS | RETBLEED | GDS | ITS | ITS_NATIVE_ONLY), - VULNBL_INTEL_STEPS(INTEL_ICELAKE_D, X86_STEP_MAX, MMIO | GDS | ITS | ITS_NATIVE_ONLY), - VULNBL_INTEL_STEPS(INTEL_ICELAKE_X, X86_STEP_MAX, MMIO | GDS | ITS | ITS_NATIVE_ONLY), -- VULNBL_INTEL_STEPS(INTEL_COMETLAKE, X86_STEP_MAX, MMIO | MMIO_SBDS | RETBLEED | GDS | ITS), -- VULNBL_INTEL_STEPS(INTEL_COMETLAKE_L, 0x0, MMIO | RETBLEED | ITS), -- VULNBL_INTEL_STEPS(INTEL_COMETLAKE_L, X86_STEP_MAX, MMIO | MMIO_SBDS | RETBLEED | GDS | ITS), -+ VULNBL_INTEL_STEPS(INTEL_COMETLAKE, X86_STEP_MAX, MMIO | MMIO_SBDS | RETBLEED | GDS | ITS | VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_COMETLAKE_L, 0x0, MMIO | RETBLEED | ITS | VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_COMETLAKE_L, X86_STEP_MAX, MMIO | MMIO_SBDS | RETBLEED | GDS | ITS | VMSCAPE), - VULNBL_INTEL_STEPS(INTEL_TIGERLAKE_L, X86_STEP_MAX, GDS | ITS | ITS_NATIVE_ONLY), - VULNBL_INTEL_STEPS(INTEL_TIGERLAKE, X86_STEP_MAX, GDS | ITS | ITS_NATIVE_ONLY), - VULNBL_INTEL_STEPS(INTEL_LAKEFIELD, X86_STEP_MAX, MMIO | MMIO_SBDS | RETBLEED), - VULNBL_INTEL_STEPS(INTEL_ROCKETLAKE, X86_STEP_MAX, MMIO | RETBLEED | GDS | ITS | ITS_NATIVE_ONLY), -- VULNBL_INTEL_TYPE(INTEL_ALDERLAKE, ATOM, RFDS), -- VULNBL_INTEL_STEPS(INTEL_ALDERLAKE_L, X86_STEP_MAX, RFDS), -- VULNBL_INTEL_TYPE(INTEL_RAPTORLAKE, ATOM, RFDS), -- VULNBL_INTEL_STEPS(INTEL_RAPTORLAKE_P, X86_STEP_MAX, RFDS), -- VULNBL_INTEL_STEPS(INTEL_RAPTORLAKE_S, X86_STEP_MAX, RFDS), -- VULNBL_INTEL_STEPS(INTEL_ATOM_GRACEMONT, X86_STEP_MAX, RFDS), -+ VULNBL_INTEL_TYPE(INTEL_ALDERLAKE, ATOM, RFDS | VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_ALDERLAKE, X86_STEP_MAX, VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_ALDERLAKE_L, X86_STEP_MAX, RFDS | VMSCAPE), -+ VULNBL_INTEL_TYPE(INTEL_RAPTORLAKE, ATOM, RFDS | VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_RAPTORLAKE, X86_STEP_MAX, VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_RAPTORLAKE_P, X86_STEP_MAX, RFDS | VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_RAPTORLAKE_S, X86_STEP_MAX, RFDS | VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_METEORLAKE_L, X86_STEP_MAX, VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_ARROWLAKE_H, X86_STEP_MAX, VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_ARROWLAKE, X86_STEP_MAX, VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_ARROWLAKE_U, X86_STEP_MAX, VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_LUNARLAKE_M, X86_STEP_MAX, VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_SAPPHIRERAPIDS_X, X86_STEP_MAX, VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_GRANITERAPIDS_X, X86_STEP_MAX, VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_EMERALDRAPIDS_X, X86_STEP_MAX, VMSCAPE), -+ VULNBL_INTEL_STEPS(INTEL_ATOM_GRACEMONT, X86_STEP_MAX, RFDS | VMSCAPE), - VULNBL_INTEL_STEPS(INTEL_ATOM_TREMONT, X86_STEP_MAX, MMIO | MMIO_SBDS | RFDS), - VULNBL_INTEL_STEPS(INTEL_ATOM_TREMONT_D, X86_STEP_MAX, MMIO | RFDS), - VULNBL_INTEL_STEPS(INTEL_ATOM_TREMONT_L, X86_STEP_MAX, MMIO | MMIO_SBDS | RFDS), - VULNBL_INTEL_STEPS(INTEL_ATOM_GOLDMONT, X86_STEP_MAX, RFDS), - VULNBL_INTEL_STEPS(INTEL_ATOM_GOLDMONT_D, X86_STEP_MAX, RFDS), - VULNBL_INTEL_STEPS(INTEL_ATOM_GOLDMONT_PLUS, X86_STEP_MAX, RFDS), -+ VULNBL_INTEL_STEPS(INTEL_ATOM_CRESTMONT_X, X86_STEP_MAX, VMSCAPE), - - VULNBL_AMD(0x15, RETBLEED), - VULNBL_AMD(0x16, RETBLEED), -- VULNBL_AMD(0x17, RETBLEED | SMT_RSB | SRSO), -- VULNBL_HYGON(0x18, RETBLEED | SMT_RSB | SRSO), -- VULNBL_AMD(0x19, SRSO), -- VULNBL_AMD(0x1a, SRSO), -+ VULNBL_AMD(0x17, RETBLEED | SMT_RSB | SRSO | VMSCAPE), -+ VULNBL_HYGON(0x18, RETBLEED | SMT_RSB | SRSO | VMSCAPE), -+ VULNBL_AMD(0x19, SRSO | TSA | VMSCAPE), -+ VULNBL_AMD(0x1a, SRSO | VMSCAPE), - {} - }; - -@@ -1530,6 +1548,24 @@ static void __init cpu_set_bug_bits(stru - setup_force_cpu_bug(X86_BUG_ITS_NATIVE_ONLY); - } - -+ if (c->x86_vendor == X86_VENDOR_AMD) { -+ if (!cpu_has(c, X86_FEATURE_TSA_SQ_NO) || -+ !cpu_has(c, X86_FEATURE_TSA_L1_NO)) { -+ if (cpu_matches(cpu_vuln_blacklist, TSA) || -+ /* Enable bug on Zen guests to allow for live migration. */ -+ (cpu_has(c, X86_FEATURE_HYPERVISOR) && cpu_has(c, X86_FEATURE_ZEN))) -+ setup_force_cpu_bug(X86_BUG_TSA); -+ } -+ } -+ -+ /* -+ * Set the bug only on bare-metal. A nested hypervisor should already be -+ * deploying IBPB to isolate itself from nested guests. -+ */ -+ if (cpu_matches(cpu_vuln_blacklist, VMSCAPE) && -+ !boot_cpu_has(X86_FEATURE_HYPERVISOR)) -+ setup_force_cpu_bug(X86_BUG_VMSCAPE); -+ - if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN)) - return; - -@@ -2243,20 +2279,16 @@ EXPORT_PER_CPU_SYMBOL(__stack_chk_guard) - #endif - #endif - --/* -- * Clear all 6 debug registers: -- */ --static void clear_all_debug_regs(void) -+static void initialize_debug_regs(void) - { -- int i; -- -- for (i = 0; i < 8; i++) { -- /* Ignore db4, db5 */ -- if ((i == 4) || (i == 5)) -- continue; -- -- set_debugreg(0, i); -- } -+ /* Control register first -- to make sure everything is disabled. */ -+ set_debugreg(DR7_FIXED_1, 7); -+ set_debugreg(DR6_RESERVED, 6); -+ /* dr5 and dr4 don't exist */ -+ set_debugreg(0, 3); -+ set_debugreg(0, 2); -+ set_debugreg(0, 1); -+ set_debugreg(0, 0); - } - - #ifdef CONFIG_KGDB -@@ -2417,7 +2449,7 @@ void cpu_init(void) - - load_mm_ldt(&init_mm); - -- clear_all_debug_regs(); -+ initialize_debug_regs(); - dbg_restore_debug_regs(); - - doublefault_init_cpu_tss(); -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/cpu/hygon.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/hygon.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/cpu/hygon.c 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/hygon.c 2025-10-22 13:53:56.391169739 -0400 -@@ -16,6 +16,7 @@ - #include - #include - #include -+#include - - #include "cpu.h" - -@@ -117,6 +118,8 @@ static void bsp_init_hygon(struct cpuinf - x86_amd_ls_cfg_ssbd_mask = 1ULL << 10; - } - } -+ -+ resctrl_cpu_detect(c); - } - - static void early_init_hygon(struct cpuinfo_x86 *c) -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/cpu/intel.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/intel.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/cpu/intel.c 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/intel.c 2025-10-22 13:53:56.391169739 -0400 -@@ -262,7 +262,7 @@ static void early_init_intel(struct cpui - if (c->x86_power & (1 << 8)) { - set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); - set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC); -- } else if ((c->x86_vfm >= INTEL_P4_PRESCOTT && c->x86_vfm <= INTEL_P4_WILLAMETTE) || -+ } else if ((c->x86_vfm >= INTEL_P4_PRESCOTT && c->x86_vfm <= INTEL_P4_CEDARMILL) || - (c->x86_vfm >= INTEL_CORE_YONAH && c->x86_vfm <= INTEL_IVYBRIDGE)) { - set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); - } -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/cpu/mce/amd.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/mce/amd.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/cpu/mce/amd.c 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/mce/amd.c 2025-10-22 13:53:56.391169739 -0400 -@@ -350,7 +350,6 @@ static void smca_configure(unsigned int - - struct thresh_restart { - struct threshold_block *b; -- int reset; - int set_lvt_off; - int lvt_off; - u16 old_limit; -@@ -432,13 +431,13 @@ static void threshold_restart_bank(void - - rdmsr(tr->b->address, lo, hi); - -- if (tr->b->threshold_limit < (hi & THRESHOLD_MAX)) -- tr->reset = 1; /* limit cannot be lower than err count */ -- -- if (tr->reset) { /* reset err count and overflow bit */ -- hi = -- (hi & ~(MASK_ERR_COUNT_HI | MASK_OVERFLOW_HI)) | -- (THRESHOLD_MAX - tr->b->threshold_limit); -+ /* -+ * Reset error count and overflow bit. -+ * This is done during init or after handling an interrupt. -+ */ -+ if (hi & MASK_OVERFLOW_HI || tr->set_lvt_off) { -+ hi &= ~(MASK_ERR_COUNT_HI | MASK_OVERFLOW_HI); -+ hi |= THRESHOLD_MAX - tr->b->threshold_limit; - } else if (tr->old_limit) { /* change limit w/o reset */ - int new_count = (hi & THRESHOLD_MAX) + - (tr->old_limit - tr->b->threshold_limit); -@@ -1113,13 +1112,20 @@ static const char *get_name(unsigned int - } - - bank_type = smca_get_bank_type(cpu, bank); -- if (bank_type >= N_SMCA_BANK_TYPES) -- return NULL; - - if (b && (bank_type == SMCA_UMC || bank_type == SMCA_UMC_V2)) { - if (b->block < ARRAY_SIZE(smca_umc_block_names)) - return smca_umc_block_names[b->block]; -- return NULL; -+ } -+ -+ if (b && b->block) { -+ snprintf(buf_mcatype, MAX_MCATYPE_NAME_LEN, "th_block_%u", b->block); -+ return buf_mcatype; -+ } -+ -+ if (bank_type >= N_SMCA_BANK_TYPES) { -+ snprintf(buf_mcatype, MAX_MCATYPE_NAME_LEN, "th_bank_%u", bank); -+ return buf_mcatype; - } - - if (per_cpu(smca_bank_counts, cpu)[bank_type] == 1) -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/cpu/mce/core.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/mce/core.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/cpu/mce/core.c 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/mce/core.c 2025-10-22 13:53:56.391169739 -0400 -@@ -1740,6 +1740,11 @@ static void mc_poll_banks_default(void) - - void (*mc_poll_banks)(void) = mc_poll_banks_default; - -+static bool should_enable_timer(unsigned long iv) -+{ -+ return !mca_cfg.ignore_ce && iv; -+} -+ - static void mce_timer_fn(struct timer_list *t) - { - struct timer_list *cpu_t = this_cpu_ptr(&mce_timer); -@@ -1763,7 +1768,7 @@ static void mce_timer_fn(struct timer_li - - if (mce_get_storm_mode()) { - __start_timer(t, HZ); -- } else { -+ } else if (should_enable_timer(iv)) { - __this_cpu_write(mce_next_interval, iv); - __start_timer(t, iv); - } -@@ -2156,11 +2161,10 @@ static void mce_start_timer(struct timer - { - unsigned long iv = check_interval * HZ; - -- if (mca_cfg.ignore_ce || !iv) -- return; -- -- this_cpu_write(mce_next_interval, iv); -- __start_timer(t, iv); -+ if (should_enable_timer(iv)) { -+ this_cpu_write(mce_next_interval, iv); -+ __start_timer(t, iv); -+ } - } - - static void __mcheck_cpu_setup_timer(void) -@@ -2801,15 +2805,9 @@ static int mce_cpu_dead(unsigned int cpu - static int mce_cpu_online(unsigned int cpu) - { - struct timer_list *t = this_cpu_ptr(&mce_timer); -- int ret; - - mce_device_create(cpu); -- -- ret = mce_threshold_create_device(cpu); -- if (ret) { -- mce_device_remove(cpu); -- return ret; -- } -+ mce_threshold_create_device(cpu); - mce_reenable_cpu(); - mce_start_timer(t); - return 0; -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/cpu/mce/intel.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/mce/intel.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/cpu/mce/intel.c 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/mce/intel.c 2025-10-22 13:53:56.391169739 -0400 -@@ -478,6 +478,7 @@ void mce_intel_feature_init(struct cpuin - void mce_intel_feature_clear(struct cpuinfo_x86 *c) - { - intel_clear_lmce(); -+ cmci_clear(); - } - - bool intel_filter_mce(struct mce *m) -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/cpu/microcode/amd.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/microcode/amd.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/cpu/microcode/amd.c 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/microcode/amd.c 2025-10-22 13:53:56.391169739 -0400 -@@ -171,8 +171,28 @@ static int cmp_id(const void *key, const - return 1; - } - -+static u32 cpuid_to_ucode_rev(unsigned int val) -+{ -+ union zen_patch_rev p = {}; -+ union cpuid_1_eax c; -+ -+ c.full = val; -+ -+ p.stepping = c.stepping; -+ p.model = c.model; -+ p.ext_model = c.ext_model; -+ p.ext_fam = c.ext_fam; -+ -+ return p.ucode_rev; -+} -+ - static bool need_sha_check(u32 cur_rev) - { -+ if (!cur_rev) { -+ cur_rev = cpuid_to_ucode_rev(bsp_cpuid_1_eax); -+ pr_info_once("No current revision, generating the lowest one: 0x%x\n", cur_rev); -+ } -+ - switch (cur_rev >> 8) { - case 0x80012: return cur_rev <= 0x800126f; break; - case 0x80082: return cur_rev <= 0x800820f; break; -@@ -749,8 +769,6 @@ static struct ucode_patch *cache_find_pa - n.equiv_cpu = equiv_cpu; - n.patch_id = uci->cpu_sig.rev; - -- WARN_ON_ONCE(!n.patch_id); -- - list_for_each_entry(p, µcode_cache, plist) - if (patch_cpus_equivalent(p, &n, false)) - return p; -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/cpu/microcode/amd_shas.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/microcode/amd_shas.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/cpu/microcode/amd_shas.c 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/microcode/amd_shas.c 2025-10-22 13:53:56.391169739 -0400 -@@ -231,6 +231,13 @@ static const struct patch_digest phashes - 0x0d,0x5b,0x65,0x34,0x69,0xb2,0x62,0x21, - } - }, -+ { 0xa0011d7, { -+ 0x35,0x07,0xcd,0x40,0x94,0xbc,0x81,0x6b, -+ 0xfc,0x61,0x56,0x1a,0xe2,0xdb,0x96,0x12, -+ 0x1c,0x1c,0x31,0xb1,0x02,0x6f,0xe5,0xd2, -+ 0xfe,0x1b,0x04,0x03,0x2c,0x8f,0x4c,0x36, -+ } -+ }, - { 0xa001223, { - 0xfb,0x32,0x5f,0xc6,0x83,0x4f,0x8c,0xb8, - 0xa4,0x05,0xf9,0x71,0x53,0x01,0x16,0xc4, -@@ -294,6 +301,13 @@ static const struct patch_digest phashes - 0xc0,0xcd,0x33,0xf2,0x8d,0xf9,0xef,0x59, - } - }, -+ { 0xa00123b, { -+ 0xef,0xa1,0x1e,0x71,0xf1,0xc3,0x2c,0xe2, -+ 0xc3,0xef,0x69,0x41,0x7a,0x54,0xca,0xc3, -+ 0x8f,0x62,0x84,0xee,0xc2,0x39,0xd9,0x28, -+ 0x95,0xa7,0x12,0x49,0x1e,0x30,0x71,0x72, -+ } -+ }, - { 0xa00820c, { - 0xa8,0x0c,0x81,0xc0,0xa6,0x00,0xe7,0xf3, - 0x5f,0x65,0xd3,0xb9,0x6f,0xea,0x93,0x63, -@@ -301,6 +315,13 @@ static const struct patch_digest phashes - 0xe1,0x3b,0x8d,0xb2,0xf8,0x22,0x03,0xe2, - } - }, -+ { 0xa00820d, { -+ 0xf9,0x2a,0xc0,0xf4,0x9e,0xa4,0x87,0xa4, -+ 0x7d,0x87,0x00,0xfd,0xab,0xda,0x19,0xca, -+ 0x26,0x51,0x32,0xc1,0x57,0x91,0xdf,0xc1, -+ 0x05,0xeb,0x01,0x7c,0x5a,0x95,0x21,0xb7, -+ } -+ }, - { 0xa10113e, { - 0x05,0x3c,0x66,0xd7,0xa9,0x5a,0x33,0x10, - 0x1b,0xf8,0x9c,0x8f,0xed,0xfc,0xa7,0xa0, -@@ -322,6 +343,13 @@ static const struct patch_digest phashes - 0xf1,0x5e,0xb0,0xde,0xb4,0x98,0xae,0xc4, - } - }, -+ { 0xa10114c, { -+ 0x9e,0xb6,0xa2,0xd9,0x87,0x38,0xc5,0x64, -+ 0xd8,0x88,0xfa,0x78,0x98,0xf9,0x6f,0x74, -+ 0x39,0x90,0x1b,0xa5,0xcf,0x5e,0xb4,0x2a, -+ 0x02,0xff,0xd4,0x8c,0x71,0x8b,0xe2,0xc0, -+ } -+ }, - { 0xa10123e, { - 0x03,0xb9,0x2c,0x76,0x48,0x93,0xc9,0x18, - 0xfb,0x56,0xfd,0xf7,0xe2,0x1d,0xca,0x4d, -@@ -343,6 +371,13 @@ static const struct patch_digest phashes - 0x1b,0x7d,0x64,0x9d,0x4b,0x53,0x13,0x75, - } - }, -+ { 0xa10124c, { -+ 0x29,0xea,0xf1,0x2c,0xb2,0xe4,0xef,0x90, -+ 0xa4,0xcd,0x1d,0x86,0x97,0x17,0x61,0x46, -+ 0xfc,0x22,0xcb,0x57,0x75,0x19,0xc8,0xcc, -+ 0x0c,0xf5,0xbc,0xac,0x81,0x9d,0x9a,0xd2, -+ } -+ }, - { 0xa108108, { - 0xed,0xc2,0xec,0xa1,0x15,0xc6,0x65,0xe9, - 0xd0,0xef,0x39,0xaa,0x7f,0x55,0x06,0xc6, -@@ -350,6 +385,13 @@ static const struct patch_digest phashes - 0x28,0x1e,0x9c,0x59,0x69,0x99,0x4d,0x16, - } - }, -+ { 0xa108109, { -+ 0x85,0xb4,0xbd,0x7c,0x49,0xa7,0xbd,0xfa, -+ 0x49,0x36,0x80,0x81,0xc5,0xb7,0x39,0x1b, -+ 0x9a,0xaa,0x50,0xde,0x9b,0xe9,0x32,0x35, -+ 0x42,0x7e,0x51,0x4f,0x52,0x2c,0x28,0x59, -+ } -+ }, - { 0xa20102d, { - 0xf9,0x6e,0xf2,0x32,0xd3,0x0f,0x5f,0x11, - 0x59,0xa1,0xfe,0xcc,0xcd,0x9b,0x42,0x89, -@@ -357,6 +399,13 @@ static const struct patch_digest phashes - 0x8c,0xe9,0x19,0x3e,0xcc,0x3f,0x7b,0xb4, - } - }, -+ { 0xa20102e, { -+ 0xbe,0x1f,0x32,0x04,0x0d,0x3c,0x9c,0xdd, -+ 0xe1,0xa4,0xbf,0x76,0x3a,0xec,0xc2,0xf6, -+ 0x11,0x00,0xa7,0xaf,0x0f,0xe5,0x02,0xc5, -+ 0x54,0x3a,0x1f,0x8c,0x16,0xb5,0xff,0xbe, -+ } -+ }, - { 0xa201210, { - 0xe8,0x6d,0x51,0x6a,0x8e,0x72,0xf3,0xfe, - 0x6e,0x16,0xbc,0x62,0x59,0x40,0x17,0xe9, -@@ -364,6 +413,13 @@ static const struct patch_digest phashes - 0xf7,0x55,0xf0,0x13,0xbb,0x22,0xf6,0x41, - } - }, -+ { 0xa201211, { -+ 0x69,0xa1,0x17,0xec,0xd0,0xf6,0x6c,0x95, -+ 0xe2,0x1e,0xc5,0x59,0x1a,0x52,0x0a,0x27, -+ 0xc4,0xed,0xd5,0x59,0x1f,0xbf,0x00,0xff, -+ 0x08,0x88,0xb5,0xe1,0x12,0xb6,0xcc,0x27, -+ } -+ }, - { 0xa404107, { - 0xbb,0x04,0x4e,0x47,0xdd,0x5e,0x26,0x45, - 0x1a,0xc9,0x56,0x24,0xa4,0x4c,0x82,0xb0, -@@ -371,6 +427,13 @@ static const struct patch_digest phashes - 0x13,0xbc,0xc5,0x25,0xe4,0xc5,0xc3,0x99, - } - }, -+ { 0xa404108, { -+ 0x69,0x67,0x43,0x06,0xf8,0x0c,0x62,0xdc, -+ 0xa4,0x21,0x30,0x4f,0x0f,0x21,0x2c,0xcb, -+ 0xcc,0x37,0xf1,0x1c,0xc3,0xf8,0x2f,0x19, -+ 0xdf,0x53,0x53,0x46,0xb1,0x15,0xea,0x00, -+ } -+ }, - { 0xa500011, { - 0x23,0x3d,0x70,0x7d,0x03,0xc3,0xc4,0xf4, - 0x2b,0x82,0xc6,0x05,0xda,0x80,0x0a,0xf1, -@@ -378,6 +441,13 @@ static const struct patch_digest phashes - 0x11,0x5e,0x96,0x7e,0x71,0xe9,0xfc,0x74, - } - }, -+ { 0xa500012, { -+ 0xeb,0x74,0x0d,0x47,0xa1,0x8e,0x09,0xe4, -+ 0x93,0x4c,0xad,0x03,0x32,0x4c,0x38,0x16, -+ 0x10,0x39,0xdd,0x06,0xaa,0xce,0xd6,0x0f, -+ 0x62,0x83,0x9d,0x8e,0x64,0x55,0xbe,0x63, -+ } -+ }, - { 0xa601209, { - 0x66,0x48,0xd4,0x09,0x05,0xcb,0x29,0x32, - 0x66,0xb7,0x9a,0x76,0xcd,0x11,0xf3,0x30, -@@ -385,6 +455,13 @@ static const struct patch_digest phashes - 0xe8,0x73,0xe2,0xd6,0xdb,0xd2,0x77,0x1d, - } - }, -+ { 0xa60120a, { -+ 0x0c,0x8b,0x3d,0xfd,0x52,0x52,0x85,0x7d, -+ 0x20,0x3a,0xe1,0x7e,0xa4,0x21,0x3b,0x7b, -+ 0x17,0x86,0xae,0xac,0x13,0xb8,0x63,0x9d, -+ 0x06,0x01,0xd0,0xa0,0x51,0x9a,0x91,0x2c, -+ } -+ }, - { 0xa704107, { - 0xf3,0xc6,0x58,0x26,0xee,0xac,0x3f,0xd6, - 0xce,0xa1,0x72,0x47,0x3b,0xba,0x2b,0x93, -@@ -392,6 +469,13 @@ static const struct patch_digest phashes - 0x64,0x39,0x71,0x8c,0xce,0xe7,0x41,0x39, - } - }, -+ { 0xa704108, { -+ 0xd7,0x55,0x15,0x2b,0xfe,0xc4,0xbc,0x93, -+ 0xec,0x91,0xa0,0xae,0x45,0xb7,0xc3,0x98, -+ 0x4e,0xff,0x61,0x77,0x88,0xc2,0x70,0x49, -+ 0xe0,0x3a,0x1d,0x84,0x38,0x52,0xbf,0x5a, -+ } -+ }, - { 0xa705206, { - 0x8d,0xc0,0x76,0xbd,0x58,0x9f,0x8f,0xa4, - 0x12,0x9d,0x21,0xfb,0x48,0x21,0xbc,0xe7, -@@ -399,6 +483,13 @@ static const struct patch_digest phashes - 0x03,0x35,0xe9,0xbe,0xfb,0x06,0xdf,0xfc, - } - }, -+ { 0xa705208, { -+ 0x30,0x1d,0x55,0x24,0xbc,0x6b,0x5a,0x19, -+ 0x0c,0x7d,0x1d,0x74,0xaa,0xd1,0xeb,0xd2, -+ 0x16,0x62,0xf7,0x5b,0xe1,0x1f,0x18,0x11, -+ 0x5c,0xf0,0x94,0x90,0x26,0xec,0x69,0xff, -+ } -+ }, - { 0xa708007, { - 0x6b,0x76,0xcc,0x78,0xc5,0x8a,0xa3,0xe3, - 0x32,0x2d,0x79,0xe4,0xc3,0x80,0xdb,0xb2, -@@ -406,6 +497,13 @@ static const struct patch_digest phashes - 0xdf,0x92,0x73,0x84,0x87,0x3c,0x73,0x93, - } - }, -+ { 0xa708008, { -+ 0x08,0x6e,0xf0,0x22,0x4b,0x8e,0xc4,0x46, -+ 0x58,0x34,0xe6,0x47,0xa2,0x28,0xfd,0xab, -+ 0x22,0x3d,0xdd,0xd8,0x52,0x9e,0x1d,0x16, -+ 0xfa,0x01,0x68,0x14,0x79,0x3e,0xe8,0x6b, -+ } -+ }, - { 0xa70c005, { - 0x88,0x5d,0xfb,0x79,0x64,0xd8,0x46,0x3b, - 0x4a,0x83,0x8e,0x77,0x7e,0xcf,0xb3,0x0f, -@@ -413,6 +511,13 @@ static const struct patch_digest phashes - 0xee,0x49,0xac,0xe1,0x8b,0x13,0xc5,0x13, - } - }, -+ { 0xa70c008, { -+ 0x0f,0xdb,0x37,0xa1,0x10,0xaf,0xd4,0x21, -+ 0x94,0x0d,0xa4,0xa2,0xe9,0x86,0x6c,0x0e, -+ 0x85,0x7c,0x36,0x30,0xa3,0x3a,0x78,0x66, -+ 0x18,0x10,0x60,0x0d,0x78,0x3d,0x44,0xd0, -+ } -+ }, - { 0xaa00116, { - 0xe8,0x4c,0x2c,0x88,0xa1,0xac,0x24,0x63, - 0x65,0xe5,0xaa,0x2d,0x16,0xa9,0xc3,0xf5, -@@ -441,4 +546,11 @@ static const struct patch_digest phashes - 0x68,0x2f,0x46,0xee,0xfe,0xc6,0x6d,0xef, - } - }, -+ { 0xaa00216, { -+ 0x79,0xfb,0x5b,0x9f,0xb6,0xe6,0xa8,0xf5, -+ 0x4e,0x7c,0x4f,0x8e,0x1d,0xad,0xd0,0x08, -+ 0xc2,0x43,0x7c,0x8b,0xe6,0xdb,0xd0,0xd2, -+ 0xe8,0x39,0x26,0xc1,0xe5,0x5a,0x48,0xf1, -+ } -+ }, - }; -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/cpu/resctrl/core.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/resctrl/core.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/cpu/resctrl/core.c 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/resctrl/core.c 2025-10-22 13:53:56.391169739 -0400 -@@ -498,6 +498,7 @@ static void domain_add_cpu_mon(int cpu, - struct rdt_hw_mon_domain *hw_dom; - struct rdt_domain_hdr *hdr; - struct rdt_mon_domain *d; -+ struct cacheinfo *ci; - int err; - - lockdep_assert_held(&domain_list_lock); -@@ -525,12 +526,13 @@ static void domain_add_cpu_mon(int cpu, - d = &hw_dom->d_resctrl; - d->hdr.id = id; - d->hdr.type = RESCTRL_MON_DOMAIN; -- d->ci = get_cpu_cacheinfo_level(cpu, RESCTRL_L3_CACHE); -- if (!d->ci) { -+ ci = get_cpu_cacheinfo_level(cpu, RESCTRL_L3_CACHE); -+ if (!ci) { - pr_warn_once("Can't find L3 cache for CPU:%d resource %s\n", cpu, r->name); - mon_domain_free(hw_dom); - return; - } -+ d->ci_id = ci->id; - cpumask_set_cpu(cpu, &d->hdr.cpu_mask); - - arch_mon_domain_online(r, d); -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/cpu/scattered.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/scattered.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/cpu/scattered.c 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/scattered.c 2025-10-22 13:53:56.391169739 -0400 -@@ -48,8 +48,11 @@ static const struct cpuid_bit cpuid_bits - { X86_FEATURE_PROC_FEEDBACK, CPUID_EDX, 11, 0x80000007, 0 }, - { X86_FEATURE_AMD_FAST_CPPC, CPUID_EDX, 15, 0x80000007, 0 }, - { X86_FEATURE_MBA, CPUID_EBX, 6, 0x80000008, 0 }, -+ { X86_FEATURE_COHERENCY_SFW_NO, CPUID_EBX, 31, 0x8000001f, 0 }, - { X86_FEATURE_SMBA, CPUID_EBX, 2, 0x80000020, 0 }, - { X86_FEATURE_BMEC, CPUID_EBX, 3, 0x80000020, 0 }, -+ { X86_FEATURE_TSA_SQ_NO, CPUID_ECX, 1, 0x80000021, 0 }, -+ { X86_FEATURE_TSA_L1_NO, CPUID_ECX, 2, 0x80000021, 0 }, - { X86_FEATURE_AMD_WORKLOAD_CLASS, CPUID_EAX, 22, 0x80000021, 0 }, - { X86_FEATURE_PERFMON_V2, CPUID_EAX, 0, 0x80000022, 0 }, - { X86_FEATURE_AMD_LBR_V2, CPUID_EAX, 1, 0x80000022, 0 }, -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/cpu/topology_amd.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/topology_amd.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/cpu/topology_amd.c 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/topology_amd.c 2025-10-22 13:53:56.391169739 -0400 -@@ -81,20 +81,25 @@ static bool parse_8000_001e(struct topo_ - - cpuid_leaf(0x8000001e, &leaf); - -- tscan->c->topo.initial_apicid = leaf.ext_apic_id; -- - /* -- * If leaf 0xb is available, then the domain shifts are set -- * already and nothing to do here. Only valid for family >= 0x17. -+ * If leaf 0xb/0x26 is available, then the APIC ID and the domain -+ * shifts are set already. - */ -- if (!has_topoext && tscan->c->x86 >= 0x17) { -+ if (!has_topoext) { -+ tscan->c->topo.initial_apicid = leaf.ext_apic_id; -+ - /* -- * Leaf 0x80000008 set the CORE domain shift already. -- * Update the SMT domain, but do not propagate it. -+ * Leaf 0x8000008 sets the CORE domain shift but not the -+ * SMT domain shift. On CPUs with family >= 0x17, there -+ * might be hyperthreads. - */ -- unsigned int nthreads = leaf.core_nthreads + 1; -+ if (tscan->c->x86 >= 0x17) { -+ /* Update the SMT domain, but do not propagate it. */ -+ unsigned int nthreads = leaf.core_nthreads + 1; - -- topology_update_dom(tscan, TOPO_SMT_DOMAIN, get_count_order(nthreads), nthreads); -+ topology_update_dom(tscan, TOPO_SMT_DOMAIN, -+ get_count_order(nthreads), nthreads); -+ } - } - - store_node(tscan, leaf.nnodes_per_socket + 1, leaf.node_id); -@@ -170,27 +175,30 @@ static void topoext_fixup(struct topo_sc - - static void parse_topology_amd(struct topo_scan *tscan) - { -- bool has_topoext = false; -- - /* -- * If the extended topology leaf 0x8000_001e is available -- * try to get SMT, CORE, TILE, and DIE shifts from extended -+ * Try to get SMT, CORE, TILE, and DIE shifts from extended - * CPUID leaf 0x8000_0026 on supported processors first. If - * extended CPUID leaf 0x8000_0026 is not supported, try to -- * get SMT and CORE shift from leaf 0xb first, then try to -- * get the CORE shift from leaf 0x8000_0008. -+ * get SMT and CORE shift from leaf 0xb. If either leaf is -+ * available, cpu_parse_topology_ext() will return true. - */ -- if (cpu_feature_enabled(X86_FEATURE_TOPOEXT)) -- has_topoext = cpu_parse_topology_ext(tscan); -+ bool has_xtopology = cpu_parse_topology_ext(tscan); - - if (cpu_feature_enabled(X86_FEATURE_AMD_HTR_CORES)) - tscan->c->topo.cpu_type = cpuid_ebx(0x80000026); - -- if (!has_topoext && !parse_8000_0008(tscan)) -+ /* -+ * If XTOPOLOGY leaves (0x26/0xb) are not available, try to -+ * get the CORE shift from leaf 0x8000_0008 first. -+ */ -+ if (!has_xtopology && !parse_8000_0008(tscan)) - return; - -- /* Prefer leaf 0x8000001e if available */ -- if (parse_8000_001e(tscan, has_topoext)) -+ /* -+ * Prefer leaf 0x8000001e if available to get the SMT shift and -+ * the initial APIC ID if XTOPOLOGY leaves are not available. -+ */ -+ if (parse_8000_001e(tscan, has_xtopology)) - return; - - /* Try the NODEID MSR */ -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/cpu/topology.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/topology.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/cpu/topology.c 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/cpu/topology.c 2025-10-22 13:53:56.391169739 -0400 -@@ -372,6 +372,19 @@ unsigned int topology_unit_count(u32 api - return topo_unit_count(lvlid, at_level, apic_maps[which_units].map); - } - -+#ifdef CONFIG_SMP -+int topology_get_primary_thread(unsigned int cpu) -+{ -+ u32 apic_id = cpuid_to_apicid[cpu]; -+ -+ /* -+ * Get the core domain level APIC id, which is the primary thread -+ * and return the CPU number assigned to it. -+ */ -+ return topo_lookup_cpuid(topo_apicid(apic_id, TOPO_CORE_DOMAIN)); -+} -+#endif -+ - #ifdef CONFIG_ACPI_HOTPLUG_CPU - /** - * topology_hotplug_apic - Handle a physical hotplugged APIC after boot -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/fpu/xstate.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/fpu/xstate.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/fpu/xstate.c 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/fpu/xstate.c 2025-10-22 13:53:56.391169739 -0400 -@@ -1855,19 +1855,20 @@ long fpu_xstate_prctl(int option, unsign - #ifdef CONFIG_PROC_PID_ARCH_STATUS - /* - * Report the amount of time elapsed in millisecond since last AVX512 -- * use in the task. -+ * use in the task. Report -1 if no AVX-512 usage. - */ - static void avx512_status(struct seq_file *m, struct task_struct *task) - { -- unsigned long timestamp = READ_ONCE(x86_task_fpu(task)->avx512_timestamp); -- long delta; -+ unsigned long timestamp; -+ long delta = -1; - -- if (!timestamp) { -- /* -- * Report -1 if no AVX512 usage -- */ -- delta = -1; -- } else { -+ /* AVX-512 usage is not tracked for kernel threads. Don't report anything. */ -+ if (task->flags & (PF_KTHREAD | PF_USER_WORKER)) -+ return; -+ -+ timestamp = READ_ONCE(x86_task_fpu(task)->avx512_timestamp); -+ -+ if (timestamp) { - delta = (long)(jiffies - timestamp); - /* - * Cap to LONG_MAX if time difference > LONG_MAX -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/irq.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/irq.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/irq.c 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/irq.c 2025-10-22 13:53:56.391169739 -0400 -@@ -256,26 +256,59 @@ static __always_inline void handle_irq(s - __handle_irq(desc, regs); - } - --static __always_inline int call_irq_handler(int vector, struct pt_regs *regs) -+static struct irq_desc *reevaluate_vector(int vector) - { -- struct irq_desc *desc; -- int ret = 0; -+ struct irq_desc *desc = __this_cpu_read(vector_irq[vector]); -+ -+ if (!IS_ERR_OR_NULL(desc)) -+ return desc; -+ -+ if (desc == VECTOR_UNUSED) -+ pr_emerg_ratelimited("No irq handler for %d.%u\n", smp_processor_id(), vector); -+ else -+ __this_cpu_write(vector_irq[vector], VECTOR_UNUSED); -+ return NULL; -+} -+ -+static __always_inline bool call_irq_handler(int vector, struct pt_regs *regs) -+{ -+ struct irq_desc *desc = __this_cpu_read(vector_irq[vector]); - -- desc = __this_cpu_read(vector_irq[vector]); - if (likely(!IS_ERR_OR_NULL(desc))) { - handle_irq(desc, regs); -- } else { -- ret = -EINVAL; -- if (desc == VECTOR_UNUSED) { -- pr_emerg_ratelimited("%s: %d.%u No irq handler for vector\n", -- __func__, smp_processor_id(), -- vector); -- } else { -- __this_cpu_write(vector_irq[vector], VECTOR_UNUSED); -- } -+ return true; - } - -- return ret; -+ /* -+ * Reevaluate with vector_lock held to prevent a race against -+ * request_irq() setting up the vector: -+ * -+ * CPU0 CPU1 -+ * interrupt is raised in APIC IRR -+ * but not handled -+ * free_irq() -+ * per_cpu(vector_irq, CPU1)[vector] = VECTOR_SHUTDOWN; -+ * -+ * request_irq() common_interrupt() -+ * d = this_cpu_read(vector_irq[vector]); -+ * -+ * per_cpu(vector_irq, CPU1)[vector] = desc; -+ * -+ * if (d == VECTOR_SHUTDOWN) -+ * this_cpu_write(vector_irq[vector], VECTOR_UNUSED); -+ * -+ * This requires that the same vector on the same target CPU is -+ * handed out or that a spurious interrupt hits that CPU/vector. -+ */ -+ lock_vector_lock(); -+ desc = reevaluate_vector(vector); -+ unlock_vector_lock(); -+ -+ if (!desc) -+ return false; -+ -+ handle_irq(desc, regs); -+ return true; - } - - /* -@@ -289,7 +322,7 @@ DEFINE_IDTENTRY_IRQ(common_interrupt) - /* entry code tells RCU that we're not quiescent. Check it. */ - RCU_LOCKDEP_WARN(!rcu_is_watching(), "IRQ failed to wake up RCU"); - -- if (unlikely(call_irq_handler(vector, regs))) -+ if (unlikely(!call_irq_handler(vector, regs))) - apic_eoi(); - - set_irq_regs(old_regs); -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/kgdb.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/kgdb.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/kgdb.c 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/kgdb.c 2025-10-22 13:53:56.391169739 -0400 -@@ -385,7 +385,7 @@ static void kgdb_disable_hw_debug(struct - struct perf_event *bp; - - /* Disable hardware debugging while we are in kgdb: */ -- set_debugreg(0UL, 7); -+ set_debugreg(DR7_FIXED_1, 7); - for (i = 0; i < HBP_NUM; i++) { - if (!breakinfo[i].enabled) - continue; -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/process_32.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/process_32.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/process_32.c 2025-10-22 13:53:23.139329489 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/process_32.c 2025-10-22 13:53:56.391169739 -0400 -@@ -93,7 +93,7 @@ void __show_regs(struct pt_regs *regs, e - - /* Only print out debug registers if they are in their non-default state. */ - if ((d0 == 0) && (d1 == 0) && (d2 == 0) && (d3 == 0) && -- (d6 == DR6_RESERVED) && (d7 == 0x400)) -+ (d6 == DR6_RESERVED) && (d7 == DR7_FIXED_1)) - return; - - printk("%sDR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n", -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/process_64.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/process_64.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/process_64.c 2025-10-22 13:53:23.139329489 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/process_64.c 2025-10-22 13:53:56.391169739 -0400 -@@ -133,7 +133,7 @@ void __show_regs(struct pt_regs *regs, e - - /* Only print out debug registers if they are in their non-default state. */ - if (!((d0 == 0) && (d1 == 0) && (d2 == 0) && (d3 == 0) && -- (d6 == DR6_RESERVED) && (d7 == 0x400))) { -+ (d6 == DR6_RESERVED) && (d7 == DR7_FIXED_1))) { - printk("%sDR0: %016lx DR1: %016lx DR2: %016lx\n", - log_lvl, d0, d1, d2); - printk("%sDR3: %016lx DR6: %016lx DR7: %016lx\n", -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/process.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/process.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/process.c 2025-10-22 13:53:23.135329508 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/process.c 2025-10-22 13:53:56.391169739 -0400 -@@ -907,16 +907,24 @@ static __init bool prefer_mwait_c1_over_ - */ - static __cpuidle void mwait_idle(void) - { -+ if (need_resched()) -+ return; -+ -+ x86_idle_clear_cpu_buffers(); -+ - if (!current_set_polling_and_test()) { - const void *addr = ¤t_thread_info()->flags; - - alternative_input("", "clflush (%[addr])", X86_BUG_CLFLUSH_MONITOR, [addr] "a" (addr)); - __monitor(addr, 0, 0); -- if (!need_resched()) { -- __sti_mwait(0, 0); -- raw_local_irq_disable(); -- } -+ if (need_resched()) -+ goto out; -+ -+ __sti_mwait(0, 0); -+ raw_local_irq_disable(); - } -+ -+out: - __current_clr_polling(); - } - -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/signal_32.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/signal_32.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/signal_32.c 2025-10-22 13:53:23.139329489 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/signal_32.c 2025-10-22 13:53:56.391169739 -0400 -@@ -152,6 +152,8 @@ SYSCALL32_DEFINE0(sigreturn) - struct sigframe_ia32 __user *frame = (struct sigframe_ia32 __user *)(regs->sp-8); - sigset_t set; - -+ prevent_single_step_upon_eretu(regs); -+ - if (!access_ok(frame, sizeof(*frame))) - goto badframe; - if (__get_user(set.sig[0], &frame->sc.oldmask) -@@ -175,6 +177,8 @@ SYSCALL32_DEFINE0(rt_sigreturn) - struct rt_sigframe_ia32 __user *frame; - sigset_t set; - -+ prevent_single_step_upon_eretu(regs); -+ - frame = (struct rt_sigframe_ia32 __user *)(regs->sp - 4); - - if (!access_ok(frame, sizeof(*frame))) -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/signal_64.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/signal_64.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/signal_64.c 2025-10-22 13:53:23.139329489 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/signal_64.c 2025-10-22 13:53:56.391169739 -0400 -@@ -250,6 +250,8 @@ SYSCALL_DEFINE0(rt_sigreturn) - sigset_t set; - unsigned long uc_flags; - -+ prevent_single_step_upon_eretu(regs); -+ - frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long)); - if (!access_ok(frame, sizeof(*frame))) - goto badframe; -@@ -366,6 +368,8 @@ COMPAT_SYSCALL_DEFINE0(x32_rt_sigreturn) - sigset_t set; - unsigned long uc_flags; - -+ prevent_single_step_upon_eretu(regs); -+ - frame = (struct rt_sigframe_x32 __user *)(regs->sp - 8); - - if (!access_ok(frame, sizeof(*frame))) -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/smpboot.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/smpboot.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/smpboot.c 2025-10-22 13:53:23.139329489 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/smpboot.c 2025-10-22 13:53:56.391169739 -0400 -@@ -1244,6 +1244,10 @@ void play_dead_common(void) - local_irq_disable(); - } - -+/* -+ * We need to flush the caches before going to sleep, lest we have -+ * dirty data in our caches when we come back up. -+ */ - void __noreturn mwait_play_dead(unsigned int eax_hint) - { - struct mwait_cpu_dead *md = this_cpu_ptr(&mwait_cpu_dead); -@@ -1290,50 +1294,6 @@ void __noreturn mwait_play_dead(unsigned - } - - /* -- * We need to flush the caches before going to sleep, lest we have -- * dirty data in our caches when we come back up. -- */ --static inline void mwait_play_dead_cpuid_hint(void) --{ -- unsigned int eax, ebx, ecx, edx; -- unsigned int highest_cstate = 0; -- unsigned int highest_subcstate = 0; -- int i; -- -- if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD || -- boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) -- return; -- if (!this_cpu_has(X86_FEATURE_MWAIT)) -- return; -- if (!this_cpu_has(X86_FEATURE_CLFLUSH)) -- return; -- -- eax = CPUID_LEAF_MWAIT; -- ecx = 0; -- native_cpuid(&eax, &ebx, &ecx, &edx); -- -- /* -- * eax will be 0 if EDX enumeration is not valid. -- * Initialized below to cstate, sub_cstate value when EDX is valid. -- */ -- if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED)) { -- eax = 0; -- } else { -- edx >>= MWAIT_SUBSTATE_SIZE; -- for (i = 0; i < 7 && edx; i++, edx >>= MWAIT_SUBSTATE_SIZE) { -- if (edx & MWAIT_SUBSTATE_MASK) { -- highest_cstate = i; -- highest_subcstate = edx & MWAIT_SUBSTATE_MASK; -- } -- } -- eax = (highest_cstate << MWAIT_SUBSTATE_SIZE) | -- (highest_subcstate - 1); -- } -- -- mwait_play_dead(eax); --} -- --/* - * Kick all "offline" CPUs out of mwait on kexec(). See comment in - * mwait_play_dead(). - */ -@@ -1383,9 +1343,9 @@ void native_play_dead(void) - play_dead_common(); - tboot_shutdown(TB_SHUTDOWN_WFS); - -- mwait_play_dead_cpuid_hint(); -- if (cpuidle_play_dead()) -- hlt_play_dead(); -+ /* Below returns only on error. */ -+ cpuidle_play_dead(); -+ hlt_play_dead(); - } - - #else /* ... !CONFIG_HOTPLUG_CPU */ -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/smp.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/smp.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/smp.c 2025-10-22 13:53:23.139329489 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/smp.c 2025-10-22 13:53:56.391169739 -0400 -@@ -299,3 +299,27 @@ struct smp_ops smp_ops = { - .send_call_func_single_ipi = native_send_call_func_single_ipi, - }; - EXPORT_SYMBOL_GPL(smp_ops); -+ -+int arch_cpu_rescan_dead_smt_siblings(void) -+{ -+ enum cpuhp_smt_control old = cpu_smt_control; -+ int ret; -+ -+ /* -+ * If SMT has been disabled and SMT siblings are in HLT, bring them back -+ * online and offline them again so that they end up in MWAIT proper. -+ * -+ * Called with hotplug enabled. -+ */ -+ if (old != CPU_SMT_DISABLED && old != CPU_SMT_FORCE_DISABLED) -+ return 0; -+ -+ ret = cpuhp_smt_enable(); -+ if (ret) -+ return ret; -+ -+ ret = cpuhp_smt_disable(old); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(arch_cpu_rescan_dead_smt_siblings); -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kernel/traps.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/traps.c ---- BPI-Router-Linux-kernel/arch/x86/kernel/traps.c 2025-10-22 13:53:23.139329489 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kernel/traps.c 2025-10-22 13:53:56.391169739 -0400 -@@ -1022,24 +1022,32 @@ static bool is_sysenter_singlestep(struc - #endif - } - --static __always_inline unsigned long debug_read_clear_dr6(void) -+static __always_inline unsigned long debug_read_reset_dr6(void) - { - unsigned long dr6; - -+ get_debugreg(dr6, 6); -+ dr6 ^= DR6_RESERVED; /* Flip to positive polarity */ -+ - /* - * The Intel SDM says: - * -- * Certain debug exceptions may clear bits 0-3. The remaining -- * contents of the DR6 register are never cleared by the -- * processor. To avoid confusion in identifying debug -- * exceptions, debug handlers should clear the register before -- * returning to the interrupted task. -+ * Certain debug exceptions may clear bits 0-3 of DR6. -+ * -+ * BLD induced #DB clears DR6.BLD and any other debug -+ * exception doesn't modify DR6.BLD. - * -- * Keep it simple: clear DR6 immediately. -+ * RTM induced #DB clears DR6.RTM and any other debug -+ * exception sets DR6.RTM. -+ * -+ * To avoid confusion in identifying debug exceptions, -+ * debug handlers should set DR6.BLD and DR6.RTM, and -+ * clear other DR6 bits before returning. -+ * -+ * Keep it simple: write DR6 with its architectural reset -+ * value 0xFFFF0FF0, defined as DR6_RESERVED, immediately. - */ -- get_debugreg(dr6, 6); - set_debugreg(DR6_RESERVED, 6); -- dr6 ^= DR6_RESERVED; /* Flip to positive polarity */ - - return dr6; - } -@@ -1239,13 +1247,13 @@ out: - /* IST stack entry */ - DEFINE_IDTENTRY_DEBUG(exc_debug) - { -- exc_debug_kernel(regs, debug_read_clear_dr6()); -+ exc_debug_kernel(regs, debug_read_reset_dr6()); - } - - /* User entry, runs on regular task stack */ - DEFINE_IDTENTRY_DEBUG_USER(exc_debug) - { -- exc_debug_user(regs, debug_read_clear_dr6()); -+ exc_debug_user(regs, debug_read_reset_dr6()); - } - - #ifdef CONFIG_X86_FRED -@@ -1264,7 +1272,7 @@ DEFINE_FREDENTRY_DEBUG(exc_debug) - { - /* - * FRED #DB stores DR6 on the stack in the format which -- * debug_read_clear_dr6() returns for the IDT entry points. -+ * debug_read_reset_dr6() returns for the IDT entry points. - */ - unsigned long dr6 = fred_event_data(regs); - -@@ -1279,7 +1287,7 @@ DEFINE_FREDENTRY_DEBUG(exc_debug) - /* 32 bit does not have separate entry points. */ - DEFINE_IDTENTRY_RAW(exc_debug) - { -- unsigned long dr6 = debug_read_clear_dr6(); -+ unsigned long dr6 = debug_read_reset_dr6(); - - if (user_mode(regs)) - exc_debug_user(regs, dr6); -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kvm/cpuid.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/cpuid.c ---- BPI-Router-Linux-kernel/arch/x86/kvm/cpuid.c 2025-10-22 13:53:23.139329489 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/cpuid.c 2025-10-22 13:53:56.391169739 -0400 -@@ -1165,6 +1165,8 @@ void kvm_set_cpu_caps(void) - */ - SYNTHESIZED_F(LFENCE_RDTSC), - /* SmmPgCfgLock */ -+ /* 4: Resv */ -+ SYNTHESIZED_F(VERW_CLEAR), - F(NULL_SEL_CLR_BASE), - /* UpperAddressIgnore */ - F(AUTOIBRS), -@@ -1179,6 +1181,11 @@ void kvm_set_cpu_caps(void) - F(SRSO_USER_KERNEL_NO), - ); - -+ kvm_cpu_cap_init(CPUID_8000_0021_ECX, -+ SYNTHESIZED_F(TSA_SQ_NO), -+ SYNTHESIZED_F(TSA_L1_NO), -+ ); -+ - kvm_cpu_cap_init(CPUID_8000_0022_EAX, - F(PERFMON_V2), - ); -@@ -1748,8 +1755,9 @@ static inline int __do_cpuid_func(struct - entry->eax = entry->ebx = entry->ecx = entry->edx = 0; - break; - case 0x80000021: -- entry->ebx = entry->ecx = entry->edx = 0; -+ entry->ebx = entry->edx = 0; - cpuid_entry_override(entry, CPUID_8000_0021_EAX); -+ cpuid_entry_override(entry, CPUID_8000_0021_ECX); - break; - /* AMD Extended Performance Monitoring and Debug */ - case 0x80000022: { -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kvm/emulate.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/emulate.c ---- BPI-Router-Linux-kernel/arch/x86/kvm/emulate.c 2025-10-22 13:53:23.139329489 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/emulate.c 2025-10-22 13:53:56.391169739 -0400 -@@ -5107,12 +5107,11 @@ void init_decode_cache(struct x86_emulat - ctxt->mem_read.end = 0; - } - --int x86_emulate_insn(struct x86_emulate_ctxt *ctxt) -+int x86_emulate_insn(struct x86_emulate_ctxt *ctxt, bool check_intercepts) - { - const struct x86_emulate_ops *ops = ctxt->ops; - int rc = X86EMUL_CONTINUE; - int saved_dst_type = ctxt->dst.type; -- bool is_guest_mode = ctxt->ops->is_guest_mode(ctxt); - - ctxt->mem_read.pos = 0; - -@@ -5160,7 +5159,7 @@ int x86_emulate_insn(struct x86_emulate_ - fetch_possible_mmx_operand(&ctxt->dst); - } - -- if (unlikely(is_guest_mode) && ctxt->intercept) { -+ if (unlikely(check_intercepts) && ctxt->intercept) { - rc = emulator_check_intercept(ctxt, ctxt->intercept, - X86_ICPT_PRE_EXCEPT); - if (rc != X86EMUL_CONTINUE) -@@ -5189,7 +5188,7 @@ int x86_emulate_insn(struct x86_emulate_ - goto done; - } - -- if (unlikely(is_guest_mode) && (ctxt->d & Intercept)) { -+ if (unlikely(check_intercepts) && (ctxt->d & Intercept)) { - rc = emulator_check_intercept(ctxt, ctxt->intercept, - X86_ICPT_POST_EXCEPT); - if (rc != X86EMUL_CONTINUE) -@@ -5243,7 +5242,7 @@ int x86_emulate_insn(struct x86_emulate_ - - special_insn: - -- if (unlikely(is_guest_mode) && (ctxt->d & Intercept)) { -+ if (unlikely(check_intercepts) && (ctxt->d & Intercept)) { - rc = emulator_check_intercept(ctxt, ctxt->intercept, - X86_ICPT_POST_MEMACCESS); - if (rc != X86EMUL_CONTINUE) -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kvm/hyperv.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/hyperv.c ---- BPI-Router-Linux-kernel/arch/x86/kvm/hyperv.c 2025-10-22 13:53:23.139329489 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/hyperv.c 2025-10-22 13:53:56.391169739 -0400 -@@ -1979,6 +1979,9 @@ int kvm_hv_vcpu_flush_tlb(struct kvm_vcp - if (entries[i] == KVM_HV_TLB_FLUSHALL_ENTRY) - goto out_flush_all; - -+ if (is_noncanonical_invlpg_address(entries[i], vcpu)) -+ continue; -+ - /* - * Lower 12 bits of 'address' encode the number of additional - * pages to flush. -@@ -2001,11 +2004,11 @@ out_flush_all: - static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc) - { - struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu); -+ unsigned long *vcpu_mask = hv_vcpu->vcpu_mask; - u64 *sparse_banks = hv_vcpu->sparse_banks; - struct kvm *kvm = vcpu->kvm; - struct hv_tlb_flush_ex flush_ex; - struct hv_tlb_flush flush; -- DECLARE_BITMAP(vcpu_mask, KVM_MAX_VCPUS); - struct kvm_vcpu_hv_tlb_flush_fifo *tlb_flush_fifo; - /* - * Normally, there can be no more than 'KVM_HV_TLB_FLUSH_FIFO_SIZE' -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kvm/kvm_emulate.h BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/kvm_emulate.h ---- BPI-Router-Linux-kernel/arch/x86/kvm/kvm_emulate.h 2025-10-22 13:53:23.139329489 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/kvm_emulate.h 2025-10-22 13:53:56.391169739 -0400 -@@ -235,7 +235,6 @@ struct x86_emulate_ops { - void (*set_nmi_mask)(struct x86_emulate_ctxt *ctxt, bool masked); - - bool (*is_smm)(struct x86_emulate_ctxt *ctxt); -- bool (*is_guest_mode)(struct x86_emulate_ctxt *ctxt); - int (*leave_smm)(struct x86_emulate_ctxt *ctxt); - void (*triple_fault)(struct x86_emulate_ctxt *ctxt); - int (*set_xcr)(struct x86_emulate_ctxt *ctxt, u32 index, u64 xcr); -@@ -521,7 +520,7 @@ bool x86_page_table_writing_insn(struct - #define EMULATION_RESTART 1 - #define EMULATION_INTERCEPTED 2 - void init_decode_cache(struct x86_emulate_ctxt *ctxt); --int x86_emulate_insn(struct x86_emulate_ctxt *ctxt); -+int x86_emulate_insn(struct x86_emulate_ctxt *ctxt, bool check_intercepts); - int emulator_task_switch(struct x86_emulate_ctxt *ctxt, - u16 tss_selector, int idt_index, int reason, - bool has_error_code, u32 error_code); -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kvm/lapic.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/lapic.c ---- BPI-Router-Linux-kernel/arch/x86/kvm/lapic.c 2025-10-22 13:53:23.139329489 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/lapic.c 2025-10-22 13:53:56.395169720 -0400 -@@ -852,6 +852,8 @@ static int __pv_send_ipi(unsigned long * - if (min > map->max_apic_id) - return 0; - -+ min = array_index_nospec(min, map->max_apic_id + 1); -+ - for_each_set_bit(i, ipi_bitmap, - min((u32)BITS_PER_LONG, (map->max_apic_id - min + 1))) { - if (map->phys_map[min + i]) { -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kvm/mmu/mmu.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/mmu/mmu.c ---- BPI-Router-Linux-kernel/arch/x86/kvm/mmu/mmu.c 2025-10-22 13:53:23.139329489 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/mmu/mmu.c 2025-10-22 13:53:56.395169720 -0400 -@@ -4896,12 +4896,16 @@ long kvm_arch_vcpu_pre_fault_memory(stru - { - u64 error_code = PFERR_GUEST_FINAL_MASK; - u8 level = PG_LEVEL_4K; -+ u64 direct_bits; - u64 end; - int r; - - if (!vcpu->kvm->arch.pre_fault_allowed) - return -EOPNOTSUPP; - -+ if (kvm_is_gfn_alias(vcpu->kvm, gpa_to_gfn(range->gpa))) -+ return -EINVAL; -+ - /* - * reload is efficient when called repeatedly, so we can do it on - * every iteration. -@@ -4910,15 +4914,18 @@ long kvm_arch_vcpu_pre_fault_memory(stru - if (r) - return r; - -+ direct_bits = 0; - if (kvm_arch_has_private_mem(vcpu->kvm) && - kvm_mem_is_private(vcpu->kvm, gpa_to_gfn(range->gpa))) - error_code |= PFERR_PRIVATE_ACCESS; -+ else -+ direct_bits = gfn_to_gpa(kvm_gfn_direct_bits(vcpu->kvm)); - - /* - * Shadow paging uses GVA for kvm page fault, so restrict to - * two-dimensional paging. - */ -- r = kvm_tdp_map_page(vcpu, range->gpa, error_code, &level); -+ r = kvm_tdp_map_page(vcpu, range->gpa | direct_bits, error_code, &level); - if (r < 0) - return r; - -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kvm/reverse_cpuid.h BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/reverse_cpuid.h ---- BPI-Router-Linux-kernel/arch/x86/kvm/reverse_cpuid.h 2025-10-22 13:53:23.139329489 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/reverse_cpuid.h 2025-10-22 13:53:56.395169720 -0400 -@@ -52,6 +52,10 @@ - /* CPUID level 0x80000022 (EAX) */ - #define KVM_X86_FEATURE_PERFMON_V2 KVM_X86_FEATURE(CPUID_8000_0022_EAX, 0) - -+/* CPUID level 0x80000021 (ECX) */ -+#define KVM_X86_FEATURE_TSA_SQ_NO KVM_X86_FEATURE(CPUID_8000_0021_ECX, 1) -+#define KVM_X86_FEATURE_TSA_L1_NO KVM_X86_FEATURE(CPUID_8000_0021_ECX, 2) -+ - struct cpuid_reg { - u32 function; - u32 index; -@@ -82,6 +86,7 @@ static const struct cpuid_reg reverse_cp - [CPUID_8000_0022_EAX] = {0x80000022, 0, CPUID_EAX}, - [CPUID_7_2_EDX] = { 7, 2, CPUID_EDX}, - [CPUID_24_0_EBX] = { 0x24, 0, CPUID_EBX}, -+ [CPUID_8000_0021_ECX] = {0x80000021, 0, CPUID_ECX}, - }; - - /* -@@ -121,6 +126,8 @@ static __always_inline u32 __feature_tra - KVM_X86_TRANSLATE_FEATURE(PERFMON_V2); - KVM_X86_TRANSLATE_FEATURE(RRSBA_CTRL); - KVM_X86_TRANSLATE_FEATURE(BHI_CTRL); -+ KVM_X86_TRANSLATE_FEATURE(TSA_SQ_NO); -+ KVM_X86_TRANSLATE_FEATURE(TSA_L1_NO); - default: - return x86_feature; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kvm/svm/sev.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/svm/sev.c ---- BPI-Router-Linux-kernel/arch/x86/kvm/svm/sev.c 2025-10-22 13:53:23.143329470 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/svm/sev.c 2025-10-22 13:53:56.395169720 -0400 -@@ -1971,6 +1971,10 @@ static int sev_check_source_vcpus(struct - struct kvm_vcpu *src_vcpu; - unsigned long i; - -+ if (src->created_vcpus != atomic_read(&src->online_vcpus) || -+ dst->created_vcpus != atomic_read(&dst->online_vcpus)) -+ return -EBUSY; -+ - if (!sev_es_guest(src)) - return 0; - -@@ -2871,6 +2875,33 @@ void __init sev_set_cpu_caps(void) - } - } - -+static bool is_sev_snp_initialized(void) -+{ -+ struct sev_user_data_snp_status *status; -+ struct sev_data_snp_addr buf; -+ bool initialized = false; -+ int ret, error = 0; -+ -+ status = snp_alloc_firmware_page(GFP_KERNEL | __GFP_ZERO); -+ if (!status) -+ return false; -+ -+ buf.address = __psp_pa(status); -+ ret = sev_do_cmd(SEV_CMD_SNP_PLATFORM_STATUS, &buf, &error); -+ if (ret) { -+ pr_err("SEV: SNP_PLATFORM_STATUS failed ret=%d, fw_error=%d (%#x)\n", -+ ret, error, error); -+ goto out; -+ } -+ -+ initialized = !!status->state; -+ -+out: -+ snp_free_firmware_page(status); -+ -+ return initialized; -+} -+ - void __init sev_hardware_setup(void) - { - unsigned int eax, ebx, ecx, edx, sev_asid_count, sev_es_asid_count; -@@ -2975,6 +3006,14 @@ void __init sev_hardware_setup(void) - sev_snp_supported = sev_snp_enabled && cc_platform_has(CC_ATTR_HOST_SEV_SNP); - - out: -+ if (sev_enabled) { -+ init_args.probe = true; -+ if (sev_platform_init(&init_args)) -+ sev_supported = sev_es_supported = sev_snp_supported = false; -+ else if (sev_snp_supported) -+ sev_snp_supported = is_sev_snp_initialized(); -+ } -+ - if (boot_cpu_has(X86_FEATURE_SEV)) - pr_info("SEV %s (ASIDs %u - %u)\n", - sev_supported ? min_sev_asid <= max_sev_asid ? "enabled" : -@@ -3001,15 +3040,6 @@ out: - sev_supported_vmsa_features = 0; - if (sev_es_debug_swap_enabled) - sev_supported_vmsa_features |= SVM_SEV_FEAT_DEBUG_SWAP; -- -- if (!sev_enabled) -- return; -- -- /* -- * Do both SNP and SEV initialization at KVM module load. -- */ -- init_args.probe = true; -- sev_platform_init(&init_args); - } - - void sev_hardware_unsetup(void) -@@ -4419,8 +4449,12 @@ static void sev_es_init_vmcb(struct vcpu - * the VMSA will be NULL if this vCPU is the destination for intrahost - * migration, and will be copied later. - */ -- if (svm->sev_es.vmsa && !svm->sev_es.snp_has_guest_vmsa) -- svm->vmcb->control.vmsa_pa = __pa(svm->sev_es.vmsa); -+ if (!svm->sev_es.snp_has_guest_vmsa) { -+ if (svm->sev_es.vmsa) -+ svm->vmcb->control.vmsa_pa = __pa(svm->sev_es.vmsa); -+ else -+ svm->vmcb->control.vmsa_pa = INVALID_PAGE; -+ } - - if (cpu_feature_enabled(X86_FEATURE_ALLOWED_SEV_FEATURES)) - svm->vmcb->control.allowed_sev_features = sev->vmsa_features | -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kvm/svm/svm.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/svm/svm.c ---- BPI-Router-Linux-kernel/arch/x86/kvm/svm/svm.c 2025-10-22 13:53:23.143329470 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/svm/svm.c 2025-10-22 13:53:56.395169720 -0400 -@@ -4204,8 +4204,7 @@ static inline void sync_lapic_to_cr8(str - struct vcpu_svm *svm = to_svm(vcpu); - u64 cr8; - -- if (nested_svm_virtualize_tpr(vcpu) || -- kvm_vcpu_apicv_active(vcpu)) -+ if (nested_svm_virtualize_tpr(vcpu)) - return; - - cr8 = kvm_get_cr8(vcpu); -@@ -4389,9 +4388,9 @@ static noinstr void svm_vcpu_enter_exit( - guest_state_exit_irqoff(); - } - --static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu, -- bool force_immediate_exit) -+static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags) - { -+ bool force_immediate_exit = run_flags & KVM_RUN_FORCE_IMMEDIATE_EXIT; - struct vcpu_svm *svm = to_svm(vcpu); - bool spec_ctrl_intercepted = msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL); - -@@ -4438,10 +4437,13 @@ static __no_kcsan fastpath_t svm_vcpu_ru - svm_hv_update_vp_id(svm->vmcb, vcpu); - - /* -- * Run with all-zero DR6 unless needed, so that we can get the exact cause -- * of a #DB. -- */ -- if (likely(!(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT))) -+ * Run with all-zero DR6 unless the guest can write DR6 freely, so that -+ * KVM can get the exact cause of a #DB. Note, loading guest DR6 from -+ * KVM's snapshot is only necessary when DR accesses won't exit. -+ */ -+ if (unlikely(run_flags & KVM_RUN_LOAD_GUEST_DR6)) -+ svm_set_dr6(vcpu, vcpu->arch.dr6); -+ else if (likely(!(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT))) - svm_set_dr6(vcpu, DR6_ACTIVE_LOW); - - clgi(); -@@ -5252,7 +5254,6 @@ static struct kvm_x86_ops svm_x86_ops __ - .set_idt = svm_set_idt, - .get_gdt = svm_get_gdt, - .set_gdt = svm_set_gdt, -- .set_dr6 = svm_set_dr6, - .set_dr7 = svm_set_dr7, - .sync_dirty_debug_regs = svm_sync_dirty_debug_regs, - .cache_reg = svm_cache_reg, -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kvm/svm/vmenter.S BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/svm/vmenter.S ---- BPI-Router-Linux-kernel/arch/x86/kvm/svm/vmenter.S 2025-10-22 13:53:23.143329470 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/svm/vmenter.S 2025-10-22 13:53:56.395169720 -0400 -@@ -169,6 +169,9 @@ SYM_FUNC_START(__svm_vcpu_run) - #endif - mov VCPU_RDI(%_ASM_DI), %_ASM_DI - -+ /* Clobbers EFLAGS.ZF */ -+ VM_CLEAR_CPU_BUFFERS -+ - /* Enter guest mode */ - 3: vmrun %_ASM_AX - 4: -@@ -335,6 +338,9 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run) - mov SVM_current_vmcb(%rdi), %rax - mov KVM_VMCB_pa(%rax), %rax - -+ /* Clobbers EFLAGS.ZF */ -+ VM_CLEAR_CPU_BUFFERS -+ - /* Enter guest mode */ - 1: vmrun %rax - 2: -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kvm/vmx/main.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/vmx/main.c ---- BPI-Router-Linux-kernel/arch/x86/kvm/vmx/main.c 2025-10-22 13:53:23.143329470 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/vmx/main.c 2025-10-22 13:53:56.395169720 -0400 -@@ -175,12 +175,12 @@ static int vt_vcpu_pre_run(struct kvm_vc - return vmx_vcpu_pre_run(vcpu); - } - --static fastpath_t vt_vcpu_run(struct kvm_vcpu *vcpu, bool force_immediate_exit) -+static fastpath_t vt_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags) - { - if (is_td_vcpu(vcpu)) -- return tdx_vcpu_run(vcpu, force_immediate_exit); -+ return tdx_vcpu_run(vcpu, run_flags); - -- return vmx_vcpu_run(vcpu, force_immediate_exit); -+ return vmx_vcpu_run(vcpu, run_flags); - } - - static int vt_handle_exit(struct kvm_vcpu *vcpu, -@@ -489,14 +489,6 @@ static void vt_set_gdt(struct kvm_vcpu * - vmx_set_gdt(vcpu, dt); - } - --static void vt_set_dr6(struct kvm_vcpu *vcpu, unsigned long val) --{ -- if (is_td_vcpu(vcpu)) -- return; -- -- vmx_set_dr6(vcpu, val); --} -- - static void vt_set_dr7(struct kvm_vcpu *vcpu, unsigned long val) - { - if (is_td_vcpu(vcpu)) -@@ -923,6 +915,8 @@ struct kvm_x86_ops vt_x86_ops __initdata - .vcpu_load = vt_op(vcpu_load), - .vcpu_put = vt_op(vcpu_put), - -+ .HOST_OWNED_DEBUGCTL = DEBUGCTLMSR_FREEZE_IN_SMM, -+ - .update_exception_bitmap = vt_op(update_exception_bitmap), - .get_feature_msr = vmx_get_feature_msr, - .get_msr = vt_op(get_msr), -@@ -943,7 +937,6 @@ struct kvm_x86_ops vt_x86_ops __initdata - .set_idt = vt_op(set_idt), - .get_gdt = vt_op(get_gdt), - .set_gdt = vt_op(set_gdt), -- .set_dr6 = vt_op(set_dr6), - .set_dr7 = vt_op(set_dr7), - .sync_dirty_debug_regs = vt_op(sync_dirty_debug_regs), - .cache_reg = vt_op(cache_reg), -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kvm/vmx/nested.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/vmx/nested.c ---- BPI-Router-Linux-kernel/arch/x86/kvm/vmx/nested.c 2025-10-22 13:53:23.143329470 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/vmx/nested.c 2025-10-22 13:53:56.395169720 -0400 -@@ -2663,10 +2663,11 @@ static int prepare_vmcs02(struct kvm_vcp - if (vmx->nested.nested_run_pending && - (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS)) { - kvm_set_dr(vcpu, 7, vmcs12->guest_dr7); -- vmcs_write64(GUEST_IA32_DEBUGCTL, vmcs12->guest_ia32_debugctl); -+ vmx_guest_debugctl_write(vcpu, vmcs12->guest_ia32_debugctl & -+ vmx_get_supported_debugctl(vcpu, false)); - } else { - kvm_set_dr(vcpu, 7, vcpu->arch.dr7); -- vmcs_write64(GUEST_IA32_DEBUGCTL, vmx->nested.pre_vmenter_debugctl); -+ vmx_guest_debugctl_write(vcpu, vmx->nested.pre_vmenter_debugctl); - } - if (kvm_mpx_supported() && (!vmx->nested.nested_run_pending || - !(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS))) -@@ -3156,7 +3157,8 @@ static int nested_vmx_check_guest_state( - return -EINVAL; - - if ((vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS) && -- CC(!kvm_dr7_valid(vmcs12->guest_dr7))) -+ (CC(!kvm_dr7_valid(vmcs12->guest_dr7)) || -+ CC(!vmx_is_valid_debugctl(vcpu, vmcs12->guest_ia32_debugctl, false)))) - return -EINVAL; - - if ((vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_PAT) && -@@ -3530,7 +3532,7 @@ enum nvmx_vmentry_status nested_vmx_ente - - if (!vmx->nested.nested_run_pending || - !(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS)) -- vmx->nested.pre_vmenter_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL); -+ vmx->nested.pre_vmenter_debugctl = vmx_guest_debugctl_read(); - if (kvm_mpx_supported() && - (!vmx->nested.nested_run_pending || - !(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS))) -@@ -4608,6 +4610,12 @@ static void sync_vmcs02_to_vmcs12(struct - (vmcs12->vm_entry_controls & ~VM_ENTRY_IA32E_MODE) | - (vm_entry_controls_get(to_vmx(vcpu)) & VM_ENTRY_IA32E_MODE); - -+ /* -+ * Note! Save DR7, but intentionally don't grab DEBUGCTL from vmcs02. -+ * Writes to DEBUGCTL that aren't intercepted by L1 are immediately -+ * propagated to vmcs12 (see vmx_set_msr()), as the value loaded into -+ * vmcs02 doesn't strictly track vmcs12. -+ */ - if (vmcs12->vm_exit_controls & VM_EXIT_SAVE_DEBUG_CONTROLS) - vmcs12->guest_dr7 = vcpu->arch.dr7; - -@@ -4798,7 +4806,7 @@ static void load_vmcs12_host_state(struc - __vmx_set_segment(vcpu, &seg, VCPU_SREG_LDTR); - - kvm_set_dr(vcpu, 7, 0x400); -- vmcs_write64(GUEST_IA32_DEBUGCTL, 0); -+ vmx_guest_debugctl_write(vcpu, 0); - - if (nested_vmx_load_msr(vcpu, vmcs12->vm_exit_msr_load_addr, - vmcs12->vm_exit_msr_load_count)) -@@ -4853,6 +4861,9 @@ static void nested_vmx_restore_host_stat - WARN_ON(kvm_set_dr(vcpu, 7, vmcs_readl(GUEST_DR7))); - } - -+ /* Reload DEBUGCTL to ensure vmcs01 has a fresh FREEZE_IN_SMM value. */ -+ vmx_reload_guest_debugctl(vcpu); -+ - /* - * Note that calling vmx_set_{efer,cr0,cr4} is important as they - * handle a variety of side effects to KVM's software model. -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kvm/vmx/pmu_intel.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/vmx/pmu_intel.c ---- BPI-Router-Linux-kernel/arch/x86/kvm/vmx/pmu_intel.c 2025-10-22 13:53:23.143329470 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/vmx/pmu_intel.c 2025-10-22 13:53:56.395169720 -0400 -@@ -653,11 +653,11 @@ static void intel_pmu_reset(struct kvm_v - */ - static void intel_pmu_legacy_freezing_lbrs_on_pmi(struct kvm_vcpu *vcpu) - { -- u64 data = vmcs_read64(GUEST_IA32_DEBUGCTL); -+ u64 data = vmx_guest_debugctl_read(); - - if (data & DEBUGCTLMSR_FREEZE_LBRS_ON_PMI) { - data &= ~DEBUGCTLMSR_LBR; -- vmcs_write64(GUEST_IA32_DEBUGCTL, data); -+ vmx_guest_debugctl_write(vcpu, data); - } - } - -@@ -730,7 +730,7 @@ void vmx_passthrough_lbr_msrs(struct kvm - - if (!lbr_desc->event) { - vmx_disable_lbr_msrs_passthrough(vcpu); -- if (vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR) -+ if (vmx_guest_debugctl_read() & DEBUGCTLMSR_LBR) - goto warn; - if (test_bit(INTEL_PMC_IDX_FIXED_VLBR, pmu->pmc_in_use)) - goto warn; -@@ -752,7 +752,7 @@ warn: - - static void intel_pmu_cleanup(struct kvm_vcpu *vcpu) - { -- if (!(vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR)) -+ if (!(vmx_guest_debugctl_read() & DEBUGCTLMSR_LBR)) - intel_pmu_release_guest_lbr_event(vcpu); - } - -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kvm/vmx/tdx.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/vmx/tdx.c ---- BPI-Router-Linux-kernel/arch/x86/kvm/vmx/tdx.c 2025-10-22 13:53:23.143329470 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/vmx/tdx.c 2025-10-22 13:53:56.395169720 -0400 -@@ -173,6 +173,8 @@ static void td_init_cpuid_entry2(struct - tdx_clear_unsupported_cpuid(entry); - } - -+#define TDVMCALLINFO_SETUP_EVENT_NOTIFY_INTERRUPT BIT(1) -+ - static int init_kvm_tdx_caps(const struct tdx_sys_info_td_conf *td_conf, - struct kvm_tdx_capabilities *caps) - { -@@ -188,6 +190,9 @@ static int init_kvm_tdx_caps(const struc - - caps->cpuid.nent = td_conf->num_cpuid_config; - -+ caps->user_tdvmcallinfo_1_r11 = -+ TDVMCALLINFO_SETUP_EVENT_NOTIFY_INTERRUPT; -+ - for (i = 0; i < td_conf->num_cpuid_config; i++) - td_init_cpuid_entry2(&caps->cpuid.entries[i], i); - -@@ -1020,20 +1025,20 @@ static void tdx_load_host_xsave_state(st - DEBUGCTLMSR_FREEZE_PERFMON_ON_PMI | \ - DEBUGCTLMSR_FREEZE_IN_SMM) - --fastpath_t tdx_vcpu_run(struct kvm_vcpu *vcpu, bool force_immediate_exit) -+fastpath_t tdx_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags) - { - struct vcpu_tdx *tdx = to_tdx(vcpu); - struct vcpu_vt *vt = to_vt(vcpu); - - /* -- * force_immediate_exit requires vCPU entering for events injection with -- * an immediately exit followed. But The TDX module doesn't guarantee -- * entry, it's already possible for KVM to _think_ it completely entry -- * to the guest without actually having done so. -- * Since KVM never needs to force an immediate exit for TDX, and can't -- * do direct injection, just warn on force_immediate_exit. -+ * WARN if KVM wants to force an immediate exit, as the TDX module does -+ * not guarantee entry into the guest, i.e. it's possible for KVM to -+ * _think_ it completed entry to the guest and forced an immediate exit -+ * without actually having done so. Luckily, KVM never needs to force -+ * an immediate exit for TDX (KVM can't do direct event injection, so -+ * just WARN and continue on. - */ -- WARN_ON_ONCE(force_immediate_exit); -+ WARN_ON_ONCE(run_flags); - - /* - * Wait until retry of SEPT-zap-related SEAMCALL completes before -@@ -1043,7 +1048,7 @@ fastpath_t tdx_vcpu_run(struct kvm_vcpu - if (unlikely(READ_ONCE(to_kvm_tdx(vcpu->kvm)->wait_for_sept_zap))) - return EXIT_FASTPATH_EXIT_HANDLED; - -- trace_kvm_entry(vcpu, force_immediate_exit); -+ trace_kvm_entry(vcpu, run_flags & KVM_RUN_FORCE_IMMEDIATE_EXIT); - - if (pi_test_on(&vt->pi_desc)) { - apic->send_IPI_self(POSTED_INTR_VECTOR); -@@ -1212,11 +1217,13 @@ static int tdx_map_gpa(struct kvm_vcpu * - /* - * Converting TDVMCALL_MAP_GPA to KVM_HC_MAP_GPA_RANGE requires - * userspace to enable KVM_CAP_EXIT_HYPERCALL with KVM_HC_MAP_GPA_RANGE -- * bit set. If not, the error code is not defined in GHCI for TDX, use -- * TDVMCALL_STATUS_INVALID_OPERAND for this case. -+ * bit set. This is a base call so it should always be supported, but -+ * KVM has no way to ensure that userspace implements the GHCI correctly. -+ * So if KVM_HC_MAP_GPA_RANGE does not cause a VMEXIT, return an error -+ * to the guest. - */ - if (!user_exit_on_hypercall(vcpu->kvm, KVM_HC_MAP_GPA_RANGE)) { -- ret = TDVMCALL_STATUS_INVALID_OPERAND; -+ ret = TDVMCALL_STATUS_SUBFUNC_UNSUPPORTED; - goto error; - } - -@@ -1449,20 +1456,106 @@ error: - return 1; - } - -+static int tdx_complete_get_td_vm_call_info(struct kvm_vcpu *vcpu) -+{ -+ struct vcpu_tdx *tdx = to_tdx(vcpu); -+ -+ tdvmcall_set_return_code(vcpu, vcpu->run->tdx.get_tdvmcall_info.ret); -+ -+ /* -+ * For now, there is no TDVMCALL beyond GHCI base API supported by KVM -+ * directly without the support from userspace, just set the value -+ * returned from userspace. -+ */ -+ tdx->vp_enter_args.r11 = vcpu->run->tdx.get_tdvmcall_info.r11; -+ tdx->vp_enter_args.r12 = vcpu->run->tdx.get_tdvmcall_info.r12; -+ tdx->vp_enter_args.r13 = vcpu->run->tdx.get_tdvmcall_info.r13; -+ tdx->vp_enter_args.r14 = vcpu->run->tdx.get_tdvmcall_info.r14; -+ -+ return 1; -+} -+ - static int tdx_get_td_vm_call_info(struct kvm_vcpu *vcpu) - { - struct vcpu_tdx *tdx = to_tdx(vcpu); - -- if (tdx->vp_enter_args.r12) -- tdvmcall_set_return_code(vcpu, TDVMCALL_STATUS_INVALID_OPERAND); -- else { -+ switch (tdx->vp_enter_args.r12) { -+ case 0: - tdx->vp_enter_args.r11 = 0; -+ tdx->vp_enter_args.r12 = 0; - tdx->vp_enter_args.r13 = 0; - tdx->vp_enter_args.r14 = 0; -+ tdvmcall_set_return_code(vcpu, TDVMCALL_STATUS_SUCCESS); -+ return 1; -+ case 1: -+ vcpu->run->tdx.get_tdvmcall_info.leaf = tdx->vp_enter_args.r12; -+ vcpu->run->exit_reason = KVM_EXIT_TDX; -+ vcpu->run->tdx.flags = 0; -+ vcpu->run->tdx.nr = TDVMCALL_GET_TD_VM_CALL_INFO; -+ vcpu->run->tdx.get_tdvmcall_info.ret = TDVMCALL_STATUS_SUCCESS; -+ vcpu->run->tdx.get_tdvmcall_info.r11 = 0; -+ vcpu->run->tdx.get_tdvmcall_info.r12 = 0; -+ vcpu->run->tdx.get_tdvmcall_info.r13 = 0; -+ vcpu->run->tdx.get_tdvmcall_info.r14 = 0; -+ vcpu->arch.complete_userspace_io = tdx_complete_get_td_vm_call_info; -+ return 0; -+ default: -+ tdvmcall_set_return_code(vcpu, TDVMCALL_STATUS_INVALID_OPERAND); -+ return 1; - } -+} -+ -+static int tdx_complete_simple(struct kvm_vcpu *vcpu) -+{ -+ tdvmcall_set_return_code(vcpu, vcpu->run->tdx.unknown.ret); - return 1; - } - -+static int tdx_get_quote(struct kvm_vcpu *vcpu) -+{ -+ struct vcpu_tdx *tdx = to_tdx(vcpu); -+ u64 gpa = tdx->vp_enter_args.r12; -+ u64 size = tdx->vp_enter_args.r13; -+ -+ /* The gpa of buffer must have shared bit set. */ -+ if (vt_is_tdx_private_gpa(vcpu->kvm, gpa)) { -+ tdvmcall_set_return_code(vcpu, TDVMCALL_STATUS_INVALID_OPERAND); -+ return 1; -+ } -+ -+ vcpu->run->exit_reason = KVM_EXIT_TDX; -+ vcpu->run->tdx.flags = 0; -+ vcpu->run->tdx.nr = TDVMCALL_GET_QUOTE; -+ vcpu->run->tdx.get_quote.ret = TDVMCALL_STATUS_SUBFUNC_UNSUPPORTED; -+ vcpu->run->tdx.get_quote.gpa = gpa & ~gfn_to_gpa(kvm_gfn_direct_bits(tdx->vcpu.kvm)); -+ vcpu->run->tdx.get_quote.size = size; -+ -+ vcpu->arch.complete_userspace_io = tdx_complete_simple; -+ -+ return 0; -+} -+ -+static int tdx_setup_event_notify_interrupt(struct kvm_vcpu *vcpu) -+{ -+ struct vcpu_tdx *tdx = to_tdx(vcpu); -+ u64 vector = tdx->vp_enter_args.r12; -+ -+ if (vector < 32 || vector > 255) { -+ tdvmcall_set_return_code(vcpu, TDVMCALL_STATUS_INVALID_OPERAND); -+ return 1; -+ } -+ -+ vcpu->run->exit_reason = KVM_EXIT_TDX; -+ vcpu->run->tdx.flags = 0; -+ vcpu->run->tdx.nr = TDVMCALL_SETUP_EVENT_NOTIFY_INTERRUPT; -+ vcpu->run->tdx.setup_event_notify.ret = TDVMCALL_STATUS_SUBFUNC_UNSUPPORTED; -+ vcpu->run->tdx.setup_event_notify.vector = vector; -+ -+ vcpu->arch.complete_userspace_io = tdx_complete_simple; -+ -+ return 0; -+} -+ - static int handle_tdvmcall(struct kvm_vcpu *vcpu) - { - switch (tdvmcall_leaf(vcpu)) { -@@ -1472,11 +1565,15 @@ static int handle_tdvmcall(struct kvm_vc - return tdx_report_fatal_error(vcpu); - case TDVMCALL_GET_TD_VM_CALL_INFO: - return tdx_get_td_vm_call_info(vcpu); -+ case TDVMCALL_GET_QUOTE: -+ return tdx_get_quote(vcpu); -+ case TDVMCALL_SETUP_EVENT_NOTIFY_INTERRUPT: -+ return tdx_setup_event_notify_interrupt(vcpu); - default: - break; - } - -- tdvmcall_set_return_code(vcpu, TDVMCALL_STATUS_INVALID_OPERAND); -+ tdvmcall_set_return_code(vcpu, TDVMCALL_STATUS_SUBFUNC_UNSUPPORTED); - return 1; - } - -@@ -2172,25 +2269,26 @@ static int tdx_get_capabilities(struct k - const struct tdx_sys_info_td_conf *td_conf = &tdx_sysinfo->td_conf; - struct kvm_tdx_capabilities __user *user_caps; - struct kvm_tdx_capabilities *caps = NULL; -+ u32 nr_user_entries; - int ret = 0; - - /* flags is reserved for future use */ - if (cmd->flags) - return -EINVAL; - -- caps = kmalloc(sizeof(*caps) + -+ caps = kzalloc(sizeof(*caps) + - sizeof(struct kvm_cpuid_entry2) * td_conf->num_cpuid_config, - GFP_KERNEL); - if (!caps) - return -ENOMEM; - - user_caps = u64_to_user_ptr(cmd->data); -- if (copy_from_user(caps, user_caps, sizeof(*caps))) { -+ if (get_user(nr_user_entries, &user_caps->cpuid.nent)) { - ret = -EFAULT; - goto out; - } - -- if (caps->cpuid.nent < td_conf->num_cpuid_config) { -+ if (nr_user_entries < td_conf->num_cpuid_config) { - ret = -E2BIG; - goto out; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kvm/vmx/vmx.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/vmx/vmx.c ---- BPI-Router-Linux-kernel/arch/x86/kvm/vmx/vmx.c 2025-10-22 13:53:23.147329450 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/vmx/vmx.c 2025-10-22 13:53:56.395169720 -0400 -@@ -2149,7 +2149,7 @@ int vmx_get_msr(struct kvm_vcpu *vcpu, s - msr_info->data = vmx->pt_desc.guest.addr_a[index / 2]; - break; - case MSR_IA32_DEBUGCTLMSR: -- msr_info->data = vmcs_read64(GUEST_IA32_DEBUGCTL); -+ msr_info->data = vmx_guest_debugctl_read(); - break; - default: - find_uret_msr: -@@ -2174,7 +2174,7 @@ static u64 nested_vmx_truncate_sysenter_ - return (unsigned long)data; - } - --static u64 vmx_get_supported_debugctl(struct kvm_vcpu *vcpu, bool host_initiated) -+u64 vmx_get_supported_debugctl(struct kvm_vcpu *vcpu, bool host_initiated) - { - u64 debugctl = 0; - -@@ -2186,9 +2186,25 @@ static u64 vmx_get_supported_debugctl(st - (host_initiated || intel_pmu_lbr_is_enabled(vcpu))) - debugctl |= DEBUGCTLMSR_LBR | DEBUGCTLMSR_FREEZE_LBRS_ON_PMI; - -+ if (boot_cpu_has(X86_FEATURE_RTM) && -+ (host_initiated || guest_cpu_cap_has(vcpu, X86_FEATURE_RTM))) -+ debugctl |= DEBUGCTLMSR_RTM_DEBUG; -+ - return debugctl; - } - -+bool vmx_is_valid_debugctl(struct kvm_vcpu *vcpu, u64 data, bool host_initiated) -+{ -+ u64 invalid; -+ -+ invalid = data & ~vmx_get_supported_debugctl(vcpu, host_initiated); -+ if (invalid & (DEBUGCTLMSR_BTF | DEBUGCTLMSR_LBR)) { -+ kvm_pr_unimpl_wrmsr(vcpu, MSR_IA32_DEBUGCTLMSR, data); -+ invalid &= ~(DEBUGCTLMSR_BTF | DEBUGCTLMSR_LBR); -+ } -+ return !invalid; -+} -+ - /* - * Writes msr value into the appropriate "register". - * Returns 0 on success, non-0 otherwise. -@@ -2257,29 +2273,22 @@ int vmx_set_msr(struct kvm_vcpu *vcpu, s - } - vmcs_writel(GUEST_SYSENTER_ESP, data); - break; -- case MSR_IA32_DEBUGCTLMSR: { -- u64 invalid; -- -- invalid = data & ~vmx_get_supported_debugctl(vcpu, msr_info->host_initiated); -- if (invalid & (DEBUGCTLMSR_BTF|DEBUGCTLMSR_LBR)) { -- kvm_pr_unimpl_wrmsr(vcpu, msr_index, data); -- data &= ~(DEBUGCTLMSR_BTF|DEBUGCTLMSR_LBR); -- invalid &= ~(DEBUGCTLMSR_BTF|DEBUGCTLMSR_LBR); -- } -- -- if (invalid) -+ case MSR_IA32_DEBUGCTLMSR: -+ if (!vmx_is_valid_debugctl(vcpu, data, msr_info->host_initiated)) - return 1; - -+ data &= vmx_get_supported_debugctl(vcpu, msr_info->host_initiated); -+ - if (is_guest_mode(vcpu) && get_vmcs12(vcpu)->vm_exit_controls & - VM_EXIT_SAVE_DEBUG_CONTROLS) - get_vmcs12(vcpu)->guest_ia32_debugctl = data; - -- vmcs_write64(GUEST_IA32_DEBUGCTL, data); -+ vmx_guest_debugctl_write(vcpu, data); -+ - if (intel_pmu_lbr_is_enabled(vcpu) && !to_vmx(vcpu)->lbr_desc.event && - (data & DEBUGCTLMSR_LBR)) - intel_pmu_create_guest_lbr_event(vcpu); - return 0; -- } - case MSR_IA32_BNDCFGS: - if (!kvm_mpx_supported() || - (!msr_info->host_initiated && -@@ -4790,7 +4799,8 @@ static void init_vmcs(struct vcpu_vmx *v - vmcs_write32(GUEST_SYSENTER_CS, 0); - vmcs_writel(GUEST_SYSENTER_ESP, 0); - vmcs_writel(GUEST_SYSENTER_EIP, 0); -- vmcs_write64(GUEST_IA32_DEBUGCTL, 0); -+ -+ vmx_guest_debugctl_write(&vmx->vcpu, 0); - - if (cpu_has_vmx_tpr_shadow()) { - vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, 0); -@@ -5606,12 +5616,6 @@ void vmx_sync_dirty_debug_regs(struct kv - set_debugreg(DR6_RESERVED, 6); - } - --void vmx_set_dr6(struct kvm_vcpu *vcpu, unsigned long val) --{ -- lockdep_assert_irqs_disabled(); -- set_debugreg(vcpu->arch.dr6, 6); --} -- - void vmx_set_dr7(struct kvm_vcpu *vcpu, unsigned long val) - { - vmcs_writel(GUEST_DR7, val); -@@ -7291,7 +7295,7 @@ static noinstr void vmx_vcpu_enter_exit( - vmx_l1d_flush(vcpu); - else if (static_branch_unlikely(&cpu_buf_vm_clear) && - kvm_arch_has_assigned_device(vcpu->kvm)) -- mds_clear_cpu_buffers(); -+ x86_clear_cpu_buffers(); - - vmx_disable_fb_clear(vmx); - -@@ -7323,8 +7327,9 @@ out: - guest_state_exit_irqoff(); - } - --fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu, bool force_immediate_exit) -+fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags) - { -+ bool force_immediate_exit = run_flags & KVM_RUN_FORCE_IMMEDIATE_EXIT; - struct vcpu_vmx *vmx = to_vmx(vcpu); - unsigned long cr3, cr4; - -@@ -7369,6 +7374,12 @@ fastpath_t vmx_vcpu_run(struct kvm_vcpu - vmcs_writel(GUEST_RIP, vcpu->arch.regs[VCPU_REGS_RIP]); - vcpu->arch.regs_dirty = 0; - -+ if (run_flags & KVM_RUN_LOAD_GUEST_DR6) -+ set_debugreg(vcpu->arch.dr6, 6); -+ -+ if (run_flags & KVM_RUN_LOAD_DEBUGCTL) -+ vmx_reload_guest_debugctl(vcpu); -+ - /* - * Refresh vmcs.HOST_CR3 if necessary. This must be done immediately - * prior to VM-Enter, as the kernel may load a new ASID (PCID) any time -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kvm/vmx/vmx.h BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/vmx/vmx.h ---- BPI-Router-Linux-kernel/arch/x86/kvm/vmx/vmx.h 2025-10-22 13:53:23.147329450 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/vmx/vmx.h 2025-10-22 13:53:56.395169720 -0400 -@@ -414,6 +414,32 @@ static inline void vmx_set_intercept_for - - void vmx_update_cpu_dirty_logging(struct kvm_vcpu *vcpu); - -+u64 vmx_get_supported_debugctl(struct kvm_vcpu *vcpu, bool host_initiated); -+bool vmx_is_valid_debugctl(struct kvm_vcpu *vcpu, u64 data, bool host_initiated); -+ -+static inline void vmx_guest_debugctl_write(struct kvm_vcpu *vcpu, u64 val) -+{ -+ WARN_ON_ONCE(val & DEBUGCTLMSR_FREEZE_IN_SMM); -+ -+ val |= vcpu->arch.host_debugctl & DEBUGCTLMSR_FREEZE_IN_SMM; -+ vmcs_write64(GUEST_IA32_DEBUGCTL, val); -+} -+ -+static inline u64 vmx_guest_debugctl_read(void) -+{ -+ return vmcs_read64(GUEST_IA32_DEBUGCTL) & ~DEBUGCTLMSR_FREEZE_IN_SMM; -+} -+ -+static inline void vmx_reload_guest_debugctl(struct kvm_vcpu *vcpu) -+{ -+ u64 val = vmcs_read64(GUEST_IA32_DEBUGCTL); -+ -+ if (!((val ^ vcpu->arch.host_debugctl) & DEBUGCTLMSR_FREEZE_IN_SMM)) -+ return; -+ -+ vmx_guest_debugctl_write(vcpu, val & ~DEBUGCTLMSR_FREEZE_IN_SMM); -+} -+ - /* - * Note, early Intel manuals have the write-low and read-high bitmap offsets - * the wrong way round. The bitmaps control MSRs 0x00000000-0x00001fff and -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kvm/vmx/x86_ops.h BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/vmx/x86_ops.h ---- BPI-Router-Linux-kernel/arch/x86/kvm/vmx/x86_ops.h 2025-10-22 13:53:23.147329450 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/vmx/x86_ops.h 2025-10-22 13:53:56.395169720 -0400 -@@ -21,7 +21,7 @@ void vmx_vm_destroy(struct kvm *kvm); - int vmx_vcpu_precreate(struct kvm *kvm); - int vmx_vcpu_create(struct kvm_vcpu *vcpu); - int vmx_vcpu_pre_run(struct kvm_vcpu *vcpu); --fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu, bool force_immediate_exit); -+fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags); - void vmx_vcpu_free(struct kvm_vcpu *vcpu); - void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event); - void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu); -@@ -133,7 +133,7 @@ void tdx_vcpu_reset(struct kvm_vcpu *vcp - void tdx_vcpu_free(struct kvm_vcpu *vcpu); - void tdx_vcpu_load(struct kvm_vcpu *vcpu, int cpu); - int tdx_vcpu_pre_run(struct kvm_vcpu *vcpu); --fastpath_t tdx_vcpu_run(struct kvm_vcpu *vcpu, bool force_immediate_exit); -+fastpath_t tdx_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags); - void tdx_prepare_switch_to_guest(struct kvm_vcpu *vcpu); - void tdx_vcpu_put(struct kvm_vcpu *vcpu); - bool tdx_protected_apic_has_interrupt(struct kvm_vcpu *vcpu); -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kvm/x86.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/x86.c ---- BPI-Router-Linux-kernel/arch/x86/kvm/x86.c 2025-10-22 13:53:23.147329450 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/x86.c 2025-10-22 13:53:56.399169700 -0400 -@@ -3258,9 +3258,11 @@ int kvm_guest_time_update(struct kvm_vcp - - /* With all the info we got, fill in the values */ - -- if (kvm_caps.has_tsc_control) -+ if (kvm_caps.has_tsc_control) { - tgt_tsc_khz = kvm_scale_tsc(tgt_tsc_khz, - v->arch.l1_tsc_scaling_ratio); -+ tgt_tsc_khz = tgt_tsc_khz ? : 1; -+ } - - if (unlikely(vcpu->hw_tsc_khz != tgt_tsc_khz)) { - kvm_get_time_scale(NSEC_PER_SEC, tgt_tsc_khz * 1000LL, -@@ -6186,6 +6188,10 @@ long kvm_arch_vcpu_ioctl(struct file *fi - u32 user_tsc_khz; - - r = -EINVAL; -+ -+ if (vcpu->arch.guest_tsc_protected) -+ goto out; -+ - user_tsc_khz = (u32)arg; - - if (kvm_caps.has_tsc_control && -@@ -8607,11 +8613,6 @@ static bool emulator_is_smm(struct x86_e - return is_smm(emul_to_vcpu(ctxt)); - } - --static bool emulator_is_guest_mode(struct x86_emulate_ctxt *ctxt) --{ -- return is_guest_mode(emul_to_vcpu(ctxt)); --} -- - #ifndef CONFIG_KVM_SMM - static int emulator_leave_smm(struct x86_emulate_ctxt *ctxt) - { -@@ -8695,7 +8696,6 @@ static const struct x86_emulate_ops emul - .guest_cpuid_is_intel_compatible = emulator_guest_cpuid_is_intel_compatible, - .set_nmi_mask = emulator_set_nmi_mask, - .is_smm = emulator_is_smm, -- .is_guest_mode = emulator_is_guest_mode, - .leave_smm = emulator_leave_smm, - .triple_fault = emulator_triple_fault, - .set_xcr = emulator_set_xcr, -@@ -9280,7 +9280,14 @@ restart: - ctxt->exception.address = 0; - } - -- r = x86_emulate_insn(ctxt); -+ /* -+ * Check L1's instruction intercepts when emulating instructions for -+ * L2, unless KVM is re-emulating a previously decoded instruction, -+ * e.g. to complete userspace I/O, in which case KVM has already -+ * checked the intercepts. -+ */ -+ r = x86_emulate_insn(ctxt, is_guest_mode(vcpu) && -+ !(emulation_type & EMULTYPE_NO_DECODE)); - - if (r == EMULATION_INTERCEPTED) - return 1; -@@ -10045,8 +10052,11 @@ static void kvm_sched_yield(struct kvm_v - rcu_read_lock(); - map = rcu_dereference(vcpu->kvm->arch.apic_map); - -- if (likely(map) && dest_id <= map->max_apic_id && map->phys_map[dest_id]) -- target = map->phys_map[dest_id]->vcpu; -+ if (likely(map) && dest_id <= map->max_apic_id) { -+ dest_id = array_index_nospec(dest_id, map->max_apic_id + 1); -+ if (map->phys_map[dest_id]) -+ target = map->phys_map[dest_id]->vcpu; -+ } - - rcu_read_unlock(); - -@@ -10779,6 +10789,7 @@ static int vcpu_enter_guest(struct kvm_v - dm_request_for_irq_injection(vcpu) && - kvm_cpu_accept_dm_intr(vcpu); - fastpath_t exit_fastpath; -+ u64 run_flags, debug_ctl; - - bool req_immediate_exit = false; - -@@ -11023,8 +11034,11 @@ static int vcpu_enter_guest(struct kvm_v - goto cancel_injection; - } - -- if (req_immediate_exit) -+ run_flags = 0; -+ if (req_immediate_exit) { -+ run_flags |= KVM_RUN_FORCE_IMMEDIATE_EXIT; - kvm_make_request(KVM_REQ_EVENT, vcpu); -+ } - - fpregs_assert_state_consistent(); - if (test_thread_flag(TIF_NEED_FPU_LOAD)) -@@ -11035,19 +11049,29 @@ static int vcpu_enter_guest(struct kvm_v - - if (unlikely(vcpu->arch.switch_db_regs && - !(vcpu->arch.switch_db_regs & KVM_DEBUGREG_AUTO_SWITCH))) { -- set_debugreg(0, 7); -+ set_debugreg(DR7_FIXED_1, 7); - set_debugreg(vcpu->arch.eff_db[0], 0); - set_debugreg(vcpu->arch.eff_db[1], 1); - set_debugreg(vcpu->arch.eff_db[2], 2); - set_debugreg(vcpu->arch.eff_db[3], 3); - /* When KVM_DEBUGREG_WONT_EXIT, dr6 is accessible in guest. */ - if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)) -- kvm_x86_call(set_dr6)(vcpu, vcpu->arch.dr6); -+ run_flags |= KVM_RUN_LOAD_GUEST_DR6; - } else if (unlikely(hw_breakpoint_active())) { -- set_debugreg(0, 7); -+ set_debugreg(DR7_FIXED_1, 7); - } - -- vcpu->arch.host_debugctl = get_debugctlmsr(); -+ /* -+ * Refresh the host DEBUGCTL snapshot after disabling IRQs, as DEBUGCTL -+ * can be modified in IRQ context, e.g. via SMP function calls. Inform -+ * vendor code if any host-owned bits were changed, e.g. so that the -+ * value loaded into hardware while running the guest can be updated. -+ */ -+ debug_ctl = get_debugctlmsr(); -+ if ((debug_ctl ^ vcpu->arch.host_debugctl) & kvm_x86_ops.HOST_OWNED_DEBUGCTL && -+ !vcpu->arch.guest_state_protected) -+ run_flags |= KVM_RUN_LOAD_DEBUGCTL; -+ vcpu->arch.host_debugctl = debug_ctl; - - guest_timing_enter_irqoff(); - -@@ -11061,8 +11085,7 @@ static int vcpu_enter_guest(struct kvm_v - WARN_ON_ONCE((kvm_vcpu_apicv_activated(vcpu) != kvm_vcpu_apicv_active(vcpu)) && - (kvm_get_apic_mode(vcpu) != LAPIC_MODE_DISABLED)); - -- exit_fastpath = kvm_x86_call(vcpu_run)(vcpu, -- req_immediate_exit); -+ exit_fastpath = kvm_x86_call(vcpu_run)(vcpu, run_flags); - if (likely(exit_fastpath != EXIT_FASTPATH_REENTER_GUEST)) - break; - -@@ -11074,6 +11097,8 @@ static int vcpu_enter_guest(struct kvm_v - break; - } - -+ run_flags = 0; -+ - /* Note, VM-Exits that go down the "slow" path are accounted below. */ - ++vcpu->stat.exits; - } -@@ -11122,6 +11147,15 @@ static int vcpu_enter_guest(struct kvm_v - wrmsrq(MSR_IA32_XFD_ERR, 0); - - /* -+ * Mark this CPU as needing a branch predictor flush before running -+ * userspace. Must be done before enabling preemption to ensure it gets -+ * set for the CPU that actually ran the guest, and not the CPU that it -+ * may migrate to. -+ */ -+ if (cpu_feature_enabled(X86_FEATURE_IBPB_EXIT_TO_USER)) -+ this_cpu_write(x86_ibpb_exit_to_user, true); -+ -+ /* - * Consume any pending interrupts, including the possible source of - * VM-Exit on SVM and any ticks that occur between VM-Exit and now. - * An instruction is required after local_irq_enable() to fully unblock -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/kvm/xen.c BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/xen.c ---- BPI-Router-Linux-kernel/arch/x86/kvm/xen.c 2025-10-22 13:53:23.147329450 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/kvm/xen.c 2025-10-22 13:53:56.399169700 -0400 -@@ -1526,7 +1526,7 @@ static bool kvm_xen_schedop_poll(struct - if (kvm_read_guest_virt(vcpu, (gva_t)sched_poll.ports, ports, - sched_poll.nr_ports * sizeof(*ports), &e)) { - *r = -EFAULT; -- return true; -+ goto out; - } - - for (i = 0; i < sched_poll.nr_ports; i++) { -@@ -1971,8 +1971,19 @@ int kvm_xen_setup_evtchn(struct kvm *kvm - { - struct kvm_vcpu *vcpu; - -- if (ue->u.xen_evtchn.port >= max_evtchn_port(kvm)) -- return -EINVAL; -+ /* -+ * Don't check for the port being within range of max_evtchn_port(). -+ * Userspace can configure what ever targets it likes; events just won't -+ * be delivered if/while the target is invalid, just like userspace can -+ * configure MSIs which target non-existent APICs. -+ * -+ * This allow on Live Migration and Live Update, the IRQ routing table -+ * can be restored *independently* of other things like creating vCPUs, -+ * without imposing an ordering dependency on userspace. In this -+ * particular case, the problematic ordering would be with setting the -+ * Xen 'long mode' flag, which changes max_evtchn_port() to allow 4096 -+ * instead of 1024 event channels. -+ */ - - /* We only support 2 level event channels for now */ - if (ue->u.xen_evtchn.priority != KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVEL) -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/lib/crypto/poly1305_glue.c BPI-Router-Linux-kernel-6.16.12/arch/x86/lib/crypto/poly1305_glue.c ---- BPI-Router-Linux-kernel/arch/x86/lib/crypto/poly1305_glue.c 2025-10-22 13:53:23.147329450 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/lib/crypto/poly1305_glue.c 2025-10-22 13:53:56.399169700 -0400 -@@ -25,6 +25,42 @@ struct poly1305_arch_internal { - struct { u32 r2, r1, r4, r3; } rn[9]; - }; - -+/* -+ * The AVX code uses base 2^26, while the scalar code uses base 2^64. If we hit -+ * the unfortunate situation of using AVX and then having to go back to scalar -+ * -- because the user is silly and has called the update function from two -+ * separate contexts -- then we need to convert back to the original base before -+ * proceeding. It is possible to reason that the initial reduction below is -+ * sufficient given the implementation invariants. However, for an avoidance of -+ * doubt and because this is not performance critical, we do the full reduction -+ * anyway. Z3 proof of below function: https://xn--4db.cc/ltPtHCKN/py -+ */ -+static void convert_to_base2_64(void *ctx) -+{ -+ struct poly1305_arch_internal *state = ctx; -+ u32 cy; -+ -+ if (!state->is_base2_26) -+ return; -+ -+ cy = state->h[0] >> 26; state->h[0] &= 0x3ffffff; state->h[1] += cy; -+ cy = state->h[1] >> 26; state->h[1] &= 0x3ffffff; state->h[2] += cy; -+ cy = state->h[2] >> 26; state->h[2] &= 0x3ffffff; state->h[3] += cy; -+ cy = state->h[3] >> 26; state->h[3] &= 0x3ffffff; state->h[4] += cy; -+ state->hs[0] = ((u64)state->h[2] << 52) | ((u64)state->h[1] << 26) | state->h[0]; -+ state->hs[1] = ((u64)state->h[4] << 40) | ((u64)state->h[3] << 14) | (state->h[2] >> 12); -+ state->hs[2] = state->h[4] >> 24; -+ /* Unsigned Less Than: branchlessly produces 1 if a < b, else 0. */ -+#define ULT(a, b) ((a ^ ((a ^ b) | ((a - b) ^ b))) >> (sizeof(a) * 8 - 1)) -+ cy = (state->hs[2] >> 2) + (state->hs[2] & ~3ULL); -+ state->hs[2] &= 3; -+ state->hs[0] += cy; -+ state->hs[1] += (cy = ULT(state->hs[0], cy)); -+ state->hs[2] += ULT(state->hs[1], cy); -+#undef ULT -+ state->is_base2_26 = 0; -+} -+ - asmlinkage void poly1305_block_init_arch( - struct poly1305_block_state *state, - const u8 raw_key[POLY1305_BLOCK_SIZE]); -@@ -62,7 +98,17 @@ void poly1305_blocks_arch(struct poly130 - BUILD_BUG_ON(SZ_4K < POLY1305_BLOCK_SIZE || - SZ_4K % POLY1305_BLOCK_SIZE); - -- if (!static_branch_likely(&poly1305_use_avx)) { -+ /* -+ * The AVX implementations have significant setup overhead (e.g. key -+ * power computation, kernel FPU enabling) which makes them slower for -+ * short messages. Fall back to the scalar implementation for messages -+ * shorter than 288 bytes, unless the AVX-specific key setup has already -+ * been performed (indicated by ctx->is_base2_26). -+ */ -+ if (!static_branch_likely(&poly1305_use_avx) || -+ (len < POLY1305_BLOCK_SIZE * 18 && !ctx->is_base2_26) || -+ unlikely(!irq_fpu_usable())) { -+ convert_to_base2_64(ctx); - poly1305_blocks_x86_64(ctx, inp, len, padbit); - return; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/mm/extable.c BPI-Router-Linux-kernel-6.16.12/arch/x86/mm/extable.c ---- BPI-Router-Linux-kernel/arch/x86/mm/extable.c 2025-10-22 13:53:23.147329450 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/mm/extable.c 2025-10-22 13:53:56.399169700 -0400 -@@ -122,13 +122,12 @@ static bool ex_handler_sgx(const struct - static bool ex_handler_fprestore(const struct exception_table_entry *fixup, - struct pt_regs *regs) - { -- regs->ip = ex_fixup_addr(fixup); -- - WARN_ONCE(1, "Bad FPU state detected at %pB, reinitializing FPU registers.", - (void *)instruction_pointer(regs)); - - fpu_reset_from_exception_fixup(); -- return true; -+ -+ return ex_handler_default(fixup, regs); - } - - /* -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/mm/init_32.c BPI-Router-Linux-kernel-6.16.12/arch/x86/mm/init_32.c ---- BPI-Router-Linux-kernel/arch/x86/mm/init_32.c 2025-10-22 13:53:23.147329450 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/mm/init_32.c 2025-10-22 13:53:56.399169700 -0400 -@@ -30,7 +30,6 @@ - #include - #include - #include --#include - - #include - #include -@@ -749,8 +748,6 @@ void mark_rodata_ro(void) - pr_info("Write protecting kernel text and read-only data: %luk\n", - size >> 10); - -- execmem_cache_make_ro(); -- - kernel_set_to_readonly = 1; - - #ifdef CONFIG_CPA_DEBUG -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/mm/init_64.c BPI-Router-Linux-kernel-6.16.12/arch/x86/mm/init_64.c ---- BPI-Router-Linux-kernel/arch/x86/mm/init_64.c 2025-10-22 13:53:23.147329450 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/mm/init_64.c 2025-10-22 13:53:56.399169700 -0400 -@@ -34,7 +34,6 @@ - #include - #include - #include --#include - - #include - #include -@@ -225,6 +224,24 @@ static void sync_global_pgds(unsigned lo - } - - /* -+ * Make kernel mappings visible in all page tables in the system. -+ * This is necessary except when the init task populates kernel mappings -+ * during the boot process. In that case, all processes originating from -+ * the init task copies the kernel mappings, so there is no issue. -+ * Otherwise, missing synchronization could lead to kernel crashes due -+ * to missing page table entries for certain kernel mappings. -+ * -+ * Synchronization is performed at the top level, which is the PGD in -+ * 5-level paging systems. But in 4-level paging systems, however, -+ * pgd_populate() is a no-op, so synchronization is done at the P4D level. -+ * sync_global_pgds() handles this difference between paging levels. -+ */ -+void arch_sync_kernel_mappings(unsigned long start, unsigned long end) -+{ -+ sync_global_pgds(start, end); -+} -+ -+/* - * NOTE: This function is marked __ref because it calls __init function - * (alloc_bootmem_pages). It's safe to do it ONLY when after_bootmem == 0. - */ -@@ -1392,8 +1409,6 @@ void mark_rodata_ro(void) - (end - start) >> 10); - set_memory_ro(start, (end - start) >> PAGE_SHIFT); - -- execmem_cache_make_ro(); -- - kernel_set_to_readonly = 1; - - /* -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/mm/pat/set_memory.c BPI-Router-Linux-kernel-6.16.12/arch/x86/mm/pat/set_memory.c ---- BPI-Router-Linux-kernel/arch/x86/mm/pat/set_memory.c 2025-10-22 13:53:23.147329450 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/mm/pat/set_memory.c 2025-10-22 13:53:56.399169700 -0400 -@@ -1257,6 +1257,9 @@ static int collapse_pmd_page(pmd_t *pmd, - pgprot_t pgprot; - int i = 0; - -+ if (!cpu_feature_enabled(X86_FEATURE_PSE)) -+ return 0; -+ - addr &= PMD_MASK; - pte = pte_offset_kernel(pmd, addr); - first = *pte; -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/mm/pti.c BPI-Router-Linux-kernel-6.16.12/arch/x86/mm/pti.c ---- BPI-Router-Linux-kernel/arch/x86/mm/pti.c 2025-10-22 13:53:23.147329450 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/mm/pti.c 2025-10-22 13:53:56.399169700 -0400 -@@ -98,6 +98,11 @@ void __init pti_check_boottime_disable(v - return; - - setup_force_cpu_cap(X86_FEATURE_PTI); -+ -+ if (cpu_feature_enabled(X86_FEATURE_INVLPGB)) { -+ pr_debug("PTI enabled, disabling INVLPGB\n"); -+ setup_clear_cpu_cap(X86_FEATURE_INVLPGB); -+ } - } - - static int __init pti_parse_cmdline(char *arg) -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/power/hibernate.c BPI-Router-Linux-kernel-6.16.12/arch/x86/power/hibernate.c ---- BPI-Router-Linux-kernel/arch/x86/power/hibernate.c 2025-10-22 13:53:23.147329450 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/power/hibernate.c 2025-10-22 13:53:56.399169700 -0400 -@@ -192,7 +192,8 @@ out: - - int arch_resume_nosmt(void) - { -- int ret = 0; -+ int ret; -+ - /* - * We reached this while coming out of hibernation. This means - * that SMT siblings are sleeping in hlt, as mwait is not safe -@@ -206,18 +207,10 @@ int arch_resume_nosmt(void) - * Called with hotplug disabled. - */ - cpu_hotplug_enable(); -- if (cpu_smt_control == CPU_SMT_DISABLED || -- cpu_smt_control == CPU_SMT_FORCE_DISABLED) { -- enum cpuhp_smt_control old = cpu_smt_control; - -- ret = cpuhp_smt_enable(); -- if (ret) -- goto out; -- ret = cpuhp_smt_disable(old); -- if (ret) -- goto out; -- } --out: -+ ret = arch_cpu_rescan_dead_smt_siblings(); -+ - cpu_hotplug_disable(); -+ - return ret; - } -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/um/ptrace.c BPI-Router-Linux-kernel-6.16.12/arch/x86/um/ptrace.c ---- BPI-Router-Linux-kernel/arch/x86/um/ptrace.c 2025-10-22 13:53:23.147329450 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/um/ptrace.c 2025-10-22 13:53:56.399169700 -0400 -@@ -161,7 +161,7 @@ static int fpregs_legacy_set(struct task - from = kbuf; - } - -- return um_fxsr_from_i387(fxsave, &buf); -+ return um_fxsr_from_i387(fxsave, from); - } - #endif - -diff -purNx .git BPI-Router-Linux-kernel/arch/x86/virt/vmx/tdx/tdx.c BPI-Router-Linux-kernel-6.16.12/arch/x86/virt/vmx/tdx/tdx.c ---- BPI-Router-Linux-kernel/arch/x86/virt/vmx/tdx/tdx.c 2025-10-22 13:53:23.147329450 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/x86/virt/vmx/tdx/tdx.c 2025-10-22 13:53:56.399169700 -0400 -@@ -75,8 +75,9 @@ static inline void seamcall_err_ret(u64 - args->r9, args->r10, args->r11); - } - --static inline int sc_retry_prerr(sc_func_t func, sc_err_func_t err_func, -- u64 fn, struct tdx_module_args *args) -+static __always_inline int sc_retry_prerr(sc_func_t func, -+ sc_err_func_t err_func, -+ u64 fn, struct tdx_module_args *args) - { - u64 sret = sc_retry(func, fn, args); - -diff -purNx .git BPI-Router-Linux-kernel/arch/xtensa/include/asm/pgtable.h BPI-Router-Linux-kernel-6.16.12/arch/xtensa/include/asm/pgtable.h ---- BPI-Router-Linux-kernel/arch/xtensa/include/asm/pgtable.h 2025-10-22 13:53:23.147329450 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/arch/xtensa/include/asm/pgtable.h 2025-10-22 13:53:56.399169700 -0400 -@@ -349,7 +349,7 @@ ptep_set_wrprotect(struct mm_struct *mm, - #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) - #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) - --static inline int pte_swp_exclusive(pte_t pte) -+static inline bool pte_swp_exclusive(pte_t pte) - { - return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; - } -diff -purNx .git BPI-Router-Linux-kernel/block/bfq-iosched.c BPI-Router-Linux-kernel-6.16.12/block/bfq-iosched.c ---- BPI-Router-Linux-kernel/block/bfq-iosched.c 2025-10-22 13:53:23.151329431 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/block/bfq-iosched.c 2025-10-22 13:53:56.399169700 -0400 -@@ -701,17 +701,13 @@ static void bfq_limit_depth(blk_opf_t op - { - struct bfq_data *bfqd = data->q->elevator->elevator_data; - struct bfq_io_cq *bic = bfq_bic_lookup(data->q); -- int depth; -- unsigned limit = data->q->nr_requests; -- unsigned int act_idx; -+ unsigned int limit, act_idx; - - /* Sync reads have full depth available */ -- if (op_is_sync(opf) && !op_is_write(opf)) { -- depth = 0; -- } else { -- depth = bfqd->word_depths[!!bfqd->wr_busy_queues][op_is_sync(opf)]; -- limit = (limit * depth) >> bfqd->full_depth_shift; -- } -+ if (op_is_sync(opf) && !op_is_write(opf)) -+ limit = data->q->nr_requests; -+ else -+ limit = bfqd->async_depths[!!bfqd->wr_busy_queues][op_is_sync(opf)]; - - for (act_idx = 0; bic && act_idx < bfqd->num_actuators; act_idx++) { - /* Fast path to check if bfqq is already allocated. */ -@@ -725,14 +721,16 @@ static void bfq_limit_depth(blk_opf_t op - * available requests and thus starve other entities. - */ - if (bfqq_request_over_limit(bfqd, bic, opf, act_idx, limit)) { -- depth = 1; -+ limit = 1; - break; - } - } -+ - bfq_log(bfqd, "[%s] wr_busy %d sync %d depth %u", -- __func__, bfqd->wr_busy_queues, op_is_sync(opf), depth); -- if (depth) -- data->shallow_depth = depth; -+ __func__, bfqd->wr_busy_queues, op_is_sync(opf), limit); -+ -+ if (limit < data->q->nr_requests) -+ data->shallow_depth = limit; - } - - static struct bfq_queue * -@@ -7128,9 +7126,8 @@ void bfq_put_async_queues(struct bfq_dat - */ - static void bfq_update_depths(struct bfq_data *bfqd, struct sbitmap_queue *bt) - { -- unsigned int depth = 1U << bt->sb.shift; -+ unsigned int nr_requests = bfqd->queue->nr_requests; - -- bfqd->full_depth_shift = bt->sb.shift; - /* - * In-word depths if no bfq_queue is being weight-raised: - * leaving 25% of tags only for sync reads. -@@ -7142,13 +7139,13 @@ static void bfq_update_depths(struct bfq - * limit 'something'. - */ - /* no more than 50% of tags for async I/O */ -- bfqd->word_depths[0][0] = max(depth >> 1, 1U); -+ bfqd->async_depths[0][0] = max(nr_requests >> 1, 1U); - /* - * no more than 75% of tags for sync writes (25% extra tags - * w.r.t. async I/O, to prevent async I/O from starving sync - * writes) - */ -- bfqd->word_depths[0][1] = max((depth * 3) >> 2, 1U); -+ bfqd->async_depths[0][1] = max((nr_requests * 3) >> 2, 1U); - - /* - * In-word depths in case some bfq_queue is being weight- -@@ -7158,9 +7155,9 @@ static void bfq_update_depths(struct bfq - * shortage. - */ - /* no more than ~18% of tags for async I/O */ -- bfqd->word_depths[1][0] = max((depth * 3) >> 4, 1U); -+ bfqd->async_depths[1][0] = max((nr_requests * 3) >> 4, 1U); - /* no more than ~37% of tags for sync writes (~20% extra tags) */ -- bfqd->word_depths[1][1] = max((depth * 6) >> 4, 1U); -+ bfqd->async_depths[1][1] = max((nr_requests * 6) >> 4, 1U); - } - - static void bfq_depth_updated(struct blk_mq_hw_ctx *hctx) -@@ -7232,22 +7229,16 @@ static void bfq_init_root_group(struct b - root_group->sched_data.bfq_class_idle_last_service = jiffies; - } - --static int bfq_init_queue(struct request_queue *q, struct elevator_type *e) -+static int bfq_init_queue(struct request_queue *q, struct elevator_queue *eq) - { - struct bfq_data *bfqd; -- struct elevator_queue *eq; - unsigned int i; - struct blk_independent_access_ranges *ia_ranges = q->disk->ia_ranges; - -- eq = elevator_alloc(q, e); -- if (!eq) -- return -ENOMEM; -- - bfqd = kzalloc_node(sizeof(*bfqd), GFP_KERNEL, q->node); -- if (!bfqd) { -- kobject_put(&eq->kobj); -+ if (!bfqd) - return -ENOMEM; -- } -+ - eq->elevator_data = bfqd; - - spin_lock_irq(&q->queue_lock); -@@ -7405,7 +7396,6 @@ static int bfq_init_queue(struct request - - out_free: - kfree(bfqd); -- kobject_put(&eq->kobj); - return -ENOMEM; - } - -diff -purNx .git BPI-Router-Linux-kernel/block/bfq-iosched.h BPI-Router-Linux-kernel-6.16.12/block/bfq-iosched.h ---- BPI-Router-Linux-kernel/block/bfq-iosched.h 2025-10-22 13:53:23.151329431 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/block/bfq-iosched.h 2025-10-22 13:53:56.399169700 -0400 -@@ -813,8 +813,7 @@ struct bfq_data { - * Depth limits used in bfq_limit_depth (see comments on the - * function) - */ -- unsigned int word_depths[2][2]; -- unsigned int full_depth_shift; -+ unsigned int async_depths[2][2]; - - /* - * Number of independent actuators. This is equal to 1 in -diff -purNx .git BPI-Router-Linux-kernel/block/blk.h BPI-Router-Linux-kernel-6.16.12/block/blk.h ---- BPI-Router-Linux-kernel/block/blk.h 2025-10-22 13:53:23.151329431 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/block/blk.h 2025-10-22 13:53:56.403169681 -0400 -@@ -12,6 +12,7 @@ - #include "blk-crypto-internal.h" - - struct elevator_type; -+struct elevator_tags; - - #define BLK_DEV_MAX_SECTORS (LLONG_MAX >> 9) - #define BLK_MIN_SEGMENT_SIZE 4096 -@@ -19,6 +20,7 @@ struct elevator_type; - /* Max future timer expiry for timeouts */ - #define BLK_MAX_TIMEOUT (5 * HZ) - -+extern const struct kobj_type blk_queue_ktype; - extern struct dentry *blk_debugfs_root; - - struct blk_flush_queue { -@@ -321,7 +323,8 @@ bool blk_bio_list_merge(struct request_q - - bool blk_insert_flush(struct request *rq); - --void elv_update_nr_hw_queues(struct request_queue *q); -+void elv_update_nr_hw_queues(struct request_queue *q, struct elevator_type *e, -+ struct elevator_tags *t); - void elevator_set_default(struct request_queue *q); - void elevator_set_none(struct request_queue *q); - -diff -purNx .git BPI-Router-Linux-kernel/block/blk-merge.c BPI-Router-Linux-kernel-6.16.12/block/blk-merge.c ---- BPI-Router-Linux-kernel/block/blk-merge.c 2025-10-22 13:53:23.151329431 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/block/blk-merge.c 2025-10-22 13:53:56.399169700 -0400 -@@ -998,20 +998,20 @@ bool blk_attempt_plug_merge(struct reque - if (!plug || rq_list_empty(&plug->mq_list)) - return false; - -- rq_list_for_each(&plug->mq_list, rq) { -- if (rq->q == q) { -- if (blk_attempt_bio_merge(q, rq, bio, nr_segs, false) == -- BIO_MERGE_OK) -- return true; -- break; -- } -+ rq = plug->mq_list.tail; -+ if (rq->q == q) -+ return blk_attempt_bio_merge(q, rq, bio, nr_segs, false) == -+ BIO_MERGE_OK; -+ else if (!plug->multiple_queues) -+ return false; - -- /* -- * Only keep iterating plug list for merges if we have multiple -- * queues -- */ -- if (!plug->multiple_queues) -- break; -+ rq_list_for_each(&plug->mq_list, rq) { -+ if (rq->q != q) -+ continue; -+ if (blk_attempt_bio_merge(q, rq, bio, nr_segs, false) == -+ BIO_MERGE_OK) -+ return true; -+ break; - } - return false; - } -diff -purNx .git BPI-Router-Linux-kernel/block/blk-mq.c BPI-Router-Linux-kernel-6.16.12/block/blk-mq.c ---- BPI-Router-Linux-kernel/block/blk-mq.c 2025-10-22 13:53:23.151329431 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/block/blk-mq.c 2025-10-22 13:53:56.403169681 -0400 -@@ -3169,8 +3169,10 @@ void blk_mq_submit_bio(struct bio *bio) - if (blk_mq_attempt_bio_merge(q, bio, nr_segs)) - goto queue_exit; - -- if (blk_queue_is_zoned(q) && blk_zone_plug_bio(bio, nr_segs)) -- goto queue_exit; -+ if (bio_needs_zone_write_plugging(bio)) { -+ if (blk_zone_plug_bio(bio, nr_segs)) -+ goto queue_exit; -+ } - - new_request: - if (rq) { -@@ -4966,6 +4968,61 @@ int blk_mq_update_nr_requests(struct req - return ret; - } - -+/* -+ * Switch back to the elevator type stored in the xarray. -+ */ -+static void blk_mq_elv_switch_back(struct request_queue *q, -+ struct xarray *elv_tbl, struct xarray *et_tbl) -+{ -+ struct elevator_type *e = xa_load(elv_tbl, q->id); -+ struct elevator_tags *t = xa_load(et_tbl, q->id); -+ -+ /* The elv_update_nr_hw_queues unfreezes the queue. */ -+ elv_update_nr_hw_queues(q, e, t); -+ -+ /* Drop the reference acquired in blk_mq_elv_switch_none. */ -+ if (e) -+ elevator_put(e); -+} -+ -+/* -+ * Stores elevator type in xarray and set current elevator to none. It uses -+ * q->id as an index to store the elevator type into the xarray. -+ */ -+static int blk_mq_elv_switch_none(struct request_queue *q, -+ struct xarray *elv_tbl) -+{ -+ int ret = 0; -+ -+ lockdep_assert_held_write(&q->tag_set->update_nr_hwq_lock); -+ -+ /* -+ * Accessing q->elevator without holding q->elevator_lock is safe here -+ * because we're called from nr_hw_queue update which is protected by -+ * set->update_nr_hwq_lock in the writer context. So, scheduler update/ -+ * switch code (which acquires the same lock in the reader context) -+ * can't run concurrently. -+ */ -+ if (q->elevator) { -+ -+ ret = xa_insert(elv_tbl, q->id, q->elevator->type, GFP_KERNEL); -+ if (WARN_ON_ONCE(ret)) -+ return ret; -+ -+ /* -+ * Before we switch elevator to 'none', take a reference to -+ * the elevator module so that while nr_hw_queue update is -+ * running, no one can remove elevator module. We'd put the -+ * reference to elevator module later when we switch back -+ * elevator. -+ */ -+ __elevator_get(q->elevator->type); -+ -+ elevator_set_none(q); -+ } -+ return ret; -+} -+ - static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, - int nr_hw_queues) - { -@@ -4973,6 +5030,8 @@ static void __blk_mq_update_nr_hw_queues - int prev_nr_hw_queues = set->nr_hw_queues; - unsigned int memflags; - int i; -+ struct xarray elv_tbl, et_tbl; -+ bool queues_frozen = false; - - lockdep_assert_held(&set->tag_list_lock); - -@@ -4984,19 +5043,32 @@ static void __blk_mq_update_nr_hw_queues - return; - - memflags = memalloc_noio_save(); -+ -+ xa_init(&et_tbl); -+ if (blk_mq_alloc_sched_tags_batch(&et_tbl, set, nr_hw_queues) < 0) -+ goto out_memalloc_restore; -+ -+ xa_init(&elv_tbl); -+ - list_for_each_entry(q, &set->tag_list, tag_set_list) { - blk_mq_debugfs_unregister_hctxs(q); - blk_mq_sysfs_unregister_hctxs(q); - } - -+ /* -+ * Switch IO scheduler to 'none', cleaning up the data associated -+ * with the previous scheduler. We will switch back once we are done -+ * updating the new sw to hw queue mappings. -+ */ -+ list_for_each_entry(q, &set->tag_list, tag_set_list) -+ if (blk_mq_elv_switch_none(q, &elv_tbl)) -+ goto switch_back; -+ - list_for_each_entry(q, &set->tag_list, tag_set_list) - blk_mq_freeze_queue_nomemsave(q); -- -- if (blk_mq_realloc_tag_set_tags(set, nr_hw_queues) < 0) { -- list_for_each_entry(q, &set->tag_list, tag_set_list) -- blk_mq_unfreeze_queue_nomemrestore(q); -- goto reregister; -- } -+ queues_frozen = true; -+ if (blk_mq_realloc_tag_set_tags(set, nr_hw_queues) < 0) -+ goto switch_back; - - fallback: - blk_mq_update_queue_map(set); -@@ -5016,12 +5088,15 @@ fallback: - } - blk_mq_map_swqueue(q); - } -+switch_back: -+ /* The blk_mq_elv_switch_back unfreezes queue for us. */ -+ list_for_each_entry(q, &set->tag_list, tag_set_list) { -+ /* switch_back expects queue to be frozen */ -+ if (!queues_frozen) -+ blk_mq_freeze_queue_nomemsave(q); -+ blk_mq_elv_switch_back(q, &elv_tbl, &et_tbl); -+ } - -- /* elv_update_nr_hw_queues() unfreeze queue for us */ -- list_for_each_entry(q, &set->tag_list, tag_set_list) -- elv_update_nr_hw_queues(q); -- --reregister: - list_for_each_entry(q, &set->tag_list, tag_set_list) { - blk_mq_sysfs_register_hctxs(q); - blk_mq_debugfs_register_hctxs(q); -@@ -5029,6 +5104,10 @@ reregister: - blk_mq_remove_hw_queues_cpuhp(q); - blk_mq_add_hw_queues_cpuhp(q); - } -+ -+ xa_destroy(&elv_tbl); -+ xa_destroy(&et_tbl); -+out_memalloc_restore: - memalloc_noio_restore(memflags); - - /* Free the excess tags when nr_hw_queues shrink. */ -diff -purNx .git BPI-Router-Linux-kernel/block/blk-mq-debugfs.c BPI-Router-Linux-kernel-6.16.12/block/blk-mq-debugfs.c ---- BPI-Router-Linux-kernel/block/blk-mq-debugfs.c 2025-10-22 13:53:23.151329431 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/block/blk-mq-debugfs.c 2025-10-22 13:53:56.399169700 -0400 -@@ -95,6 +95,7 @@ static const char *const blk_queue_flag_ - QUEUE_FLAG_NAME(SQ_SCHED), - QUEUE_FLAG_NAME(DISABLE_WBT_DEF), - QUEUE_FLAG_NAME(NO_ELV_SWITCH), -+ QUEUE_FLAG_NAME(QOS_ENABLED), - }; - #undef QUEUE_FLAG_NAME - -diff -purNx .git BPI-Router-Linux-kernel/block/blk-mq-sched.c BPI-Router-Linux-kernel-6.16.12/block/blk-mq-sched.c ---- BPI-Router-Linux-kernel/block/blk-mq-sched.c 2025-10-22 13:53:23.151329431 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/block/blk-mq-sched.c 2025-10-22 13:53:56.399169700 -0400 -@@ -374,64 +374,17 @@ bool blk_mq_sched_try_insert_merge(struc - } - EXPORT_SYMBOL_GPL(blk_mq_sched_try_insert_merge); - --static int blk_mq_sched_alloc_map_and_rqs(struct request_queue *q, -- struct blk_mq_hw_ctx *hctx, -- unsigned int hctx_idx) --{ -- if (blk_mq_is_shared_tags(q->tag_set->flags)) { -- hctx->sched_tags = q->sched_shared_tags; -- return 0; -- } -- -- hctx->sched_tags = blk_mq_alloc_map_and_rqs(q->tag_set, hctx_idx, -- q->nr_requests); -- -- if (!hctx->sched_tags) -- return -ENOMEM; -- return 0; --} -- --static void blk_mq_exit_sched_shared_tags(struct request_queue *queue) --{ -- blk_mq_free_rq_map(queue->sched_shared_tags); -- queue->sched_shared_tags = NULL; --} -- - /* called in queue's release handler, tagset has gone away */ - static void blk_mq_sched_tags_teardown(struct request_queue *q, unsigned int flags) - { - struct blk_mq_hw_ctx *hctx; - unsigned long i; - -- queue_for_each_hw_ctx(q, hctx, i) { -- if (hctx->sched_tags) { -- if (!blk_mq_is_shared_tags(flags)) -- blk_mq_free_rq_map(hctx->sched_tags); -- hctx->sched_tags = NULL; -- } -- } -+ queue_for_each_hw_ctx(q, hctx, i) -+ hctx->sched_tags = NULL; - - if (blk_mq_is_shared_tags(flags)) -- blk_mq_exit_sched_shared_tags(q); --} -- --static int blk_mq_init_sched_shared_tags(struct request_queue *queue) --{ -- struct blk_mq_tag_set *set = queue->tag_set; -- -- /* -- * Set initial depth at max so that we don't need to reallocate for -- * updating nr_requests. -- */ -- queue->sched_shared_tags = blk_mq_alloc_map_and_rqs(set, -- BLK_MQ_NO_HCTX_IDX, -- MAX_SCHED_RQ); -- if (!queue->sched_shared_tags) -- return -ENOMEM; -- -- blk_mq_tag_update_sched_shared_tags(queue); -- -- return 0; -+ q->sched_shared_tags = NULL; - } - - void blk_mq_sched_reg_debugfs(struct request_queue *q) -@@ -458,8 +411,140 @@ void blk_mq_sched_unreg_debugfs(struct r - mutex_unlock(&q->debugfs_mutex); - } - -+void blk_mq_free_sched_tags(struct elevator_tags *et, -+ struct blk_mq_tag_set *set) -+{ -+ unsigned long i; -+ -+ /* Shared tags are stored at index 0 in @tags. */ -+ if (blk_mq_is_shared_tags(set->flags)) -+ blk_mq_free_map_and_rqs(set, et->tags[0], BLK_MQ_NO_HCTX_IDX); -+ else { -+ for (i = 0; i < et->nr_hw_queues; i++) -+ blk_mq_free_map_and_rqs(set, et->tags[i], i); -+ } -+ -+ kfree(et); -+} -+ -+void blk_mq_free_sched_tags_batch(struct xarray *et_table, -+ struct blk_mq_tag_set *set) -+{ -+ struct request_queue *q; -+ struct elevator_tags *et; -+ -+ lockdep_assert_held_write(&set->update_nr_hwq_lock); -+ -+ list_for_each_entry(q, &set->tag_list, tag_set_list) { -+ /* -+ * Accessing q->elevator without holding q->elevator_lock is -+ * safe because we're holding here set->update_nr_hwq_lock in -+ * the writer context. So, scheduler update/switch code (which -+ * acquires the same lock but in the reader context) can't run -+ * concurrently. -+ */ -+ if (q->elevator) { -+ et = xa_load(et_table, q->id); -+ if (unlikely(!et)) -+ WARN_ON_ONCE(1); -+ else -+ blk_mq_free_sched_tags(et, set); -+ } -+ } -+} -+ -+struct elevator_tags *blk_mq_alloc_sched_tags(struct blk_mq_tag_set *set, -+ unsigned int nr_hw_queues) -+{ -+ unsigned int nr_tags; -+ int i; -+ struct elevator_tags *et; -+ gfp_t gfp = GFP_NOIO | __GFP_ZERO | __GFP_NOWARN | __GFP_NORETRY; -+ -+ if (blk_mq_is_shared_tags(set->flags)) -+ nr_tags = 1; -+ else -+ nr_tags = nr_hw_queues; -+ -+ et = kmalloc(sizeof(struct elevator_tags) + -+ nr_tags * sizeof(struct blk_mq_tags *), gfp); -+ if (!et) -+ return NULL; -+ /* -+ * Default to double of smaller one between hw queue_depth and -+ * 128, since we don't split into sync/async like the old code -+ * did. Additionally, this is a per-hw queue depth. -+ */ -+ et->nr_requests = 2 * min_t(unsigned int, set->queue_depth, -+ BLKDEV_DEFAULT_RQ); -+ et->nr_hw_queues = nr_hw_queues; -+ -+ if (blk_mq_is_shared_tags(set->flags)) { -+ /* Shared tags are stored at index 0 in @tags. */ -+ et->tags[0] = blk_mq_alloc_map_and_rqs(set, BLK_MQ_NO_HCTX_IDX, -+ MAX_SCHED_RQ); -+ if (!et->tags[0]) -+ goto out; -+ } else { -+ for (i = 0; i < et->nr_hw_queues; i++) { -+ et->tags[i] = blk_mq_alloc_map_and_rqs(set, i, -+ et->nr_requests); -+ if (!et->tags[i]) -+ goto out_unwind; -+ } -+ } -+ -+ return et; -+out_unwind: -+ while (--i >= 0) -+ blk_mq_free_map_and_rqs(set, et->tags[i], i); -+out: -+ kfree(et); -+ return NULL; -+} -+ -+int blk_mq_alloc_sched_tags_batch(struct xarray *et_table, -+ struct blk_mq_tag_set *set, unsigned int nr_hw_queues) -+{ -+ struct request_queue *q; -+ struct elevator_tags *et; -+ gfp_t gfp = GFP_NOIO | __GFP_ZERO | __GFP_NOWARN | __GFP_NORETRY; -+ -+ lockdep_assert_held_write(&set->update_nr_hwq_lock); -+ -+ list_for_each_entry(q, &set->tag_list, tag_set_list) { -+ /* -+ * Accessing q->elevator without holding q->elevator_lock is -+ * safe because we're holding here set->update_nr_hwq_lock in -+ * the writer context. So, scheduler update/switch code (which -+ * acquires the same lock but in the reader context) can't run -+ * concurrently. -+ */ -+ if (q->elevator) { -+ et = blk_mq_alloc_sched_tags(set, nr_hw_queues); -+ if (!et) -+ goto out_unwind; -+ if (xa_insert(et_table, q->id, et, gfp)) -+ goto out_free_tags; -+ } -+ } -+ return 0; -+out_free_tags: -+ blk_mq_free_sched_tags(et, set); -+out_unwind: -+ list_for_each_entry_continue_reverse(q, &set->tag_list, tag_set_list) { -+ if (q->elevator) { -+ et = xa_load(et_table, q->id); -+ if (et) -+ blk_mq_free_sched_tags(et, set); -+ } -+ } -+ return -ENOMEM; -+} -+ - /* caller must have a reference to @e, will grab another one if successful */ --int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e) -+int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e, -+ struct elevator_tags *et) - { - unsigned int flags = q->tag_set->flags; - struct blk_mq_hw_ctx *hctx; -@@ -467,36 +552,33 @@ int blk_mq_init_sched(struct request_que - unsigned long i; - int ret; - -- /* -- * Default to double of smaller one between hw queue_depth and 128, -- * since we don't split into sync/async like the old code did. -- * Additionally, this is a per-hw queue depth. -- */ -- q->nr_requests = 2 * min_t(unsigned int, q->tag_set->queue_depth, -- BLKDEV_DEFAULT_RQ); -+ eq = elevator_alloc(q, e, et); -+ if (!eq) -+ return -ENOMEM; -+ -+ q->nr_requests = et->nr_requests; - - if (blk_mq_is_shared_tags(flags)) { -- ret = blk_mq_init_sched_shared_tags(q); -- if (ret) -- return ret; -+ /* Shared tags are stored at index 0 in @et->tags. */ -+ q->sched_shared_tags = et->tags[0]; -+ blk_mq_tag_update_sched_shared_tags(q); - } - - queue_for_each_hw_ctx(q, hctx, i) { -- ret = blk_mq_sched_alloc_map_and_rqs(q, hctx, i); -- if (ret) -- goto err_free_map_and_rqs; -+ if (blk_mq_is_shared_tags(flags)) -+ hctx->sched_tags = q->sched_shared_tags; -+ else -+ hctx->sched_tags = et->tags[i]; - } - -- ret = e->ops.init_sched(q, e); -+ ret = e->ops.init_sched(q, eq); - if (ret) -- goto err_free_map_and_rqs; -+ goto out; - - queue_for_each_hw_ctx(q, hctx, i) { - if (e->ops.init_hctx) { - ret = e->ops.init_hctx(hctx, i); - if (ret) { -- eq = q->elevator; -- blk_mq_sched_free_rqs(q); - blk_mq_exit_sched(q, eq); - kobject_put(&eq->kobj); - return ret; -@@ -505,10 +587,9 @@ int blk_mq_init_sched(struct request_que - } - return 0; - --err_free_map_and_rqs: -- blk_mq_sched_free_rqs(q); -+out: - blk_mq_sched_tags_teardown(q, flags); -- -+ kobject_put(&eq->kobj); - q->elevator = NULL; - return ret; - } -diff -purNx .git BPI-Router-Linux-kernel/block/blk-mq-sched.h BPI-Router-Linux-kernel-6.16.12/block/blk-mq-sched.h ---- BPI-Router-Linux-kernel/block/blk-mq-sched.h 2025-10-22 13:53:23.151329431 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/block/blk-mq-sched.h 2025-10-22 13:53:56.399169700 -0400 -@@ -18,10 +18,20 @@ void __blk_mq_sched_restart(struct blk_m - - void blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx); - --int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e); -+int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e, -+ struct elevator_tags *et); - void blk_mq_exit_sched(struct request_queue *q, struct elevator_queue *e); - void blk_mq_sched_free_rqs(struct request_queue *q); - -+struct elevator_tags *blk_mq_alloc_sched_tags(struct blk_mq_tag_set *set, -+ unsigned int nr_hw_queues); -+int blk_mq_alloc_sched_tags_batch(struct xarray *et_table, -+ struct blk_mq_tag_set *set, unsigned int nr_hw_queues); -+void blk_mq_free_sched_tags(struct elevator_tags *et, -+ struct blk_mq_tag_set *set); -+void blk_mq_free_sched_tags_batch(struct xarray *et_table, -+ struct blk_mq_tag_set *set); -+ - static inline void blk_mq_sched_restart(struct blk_mq_hw_ctx *hctx) - { - if (test_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state)) -diff -purNx .git BPI-Router-Linux-kernel/block/blk-mq-tag.c BPI-Router-Linux-kernel-6.16.12/block/blk-mq-tag.c ---- BPI-Router-Linux-kernel/block/blk-mq-tag.c 2025-10-22 13:53:23.151329431 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/block/blk-mq-tag.c 2025-10-22 13:53:56.399169700 -0400 -@@ -622,6 +622,7 @@ int blk_mq_tag_update_depth(struct blk_m - return -ENOMEM; - - blk_mq_free_map_and_rqs(set, *tagsptr, hctx->queue_num); -+ hctx->queue->elevator->et->tags[hctx->queue_num] = new; - *tagsptr = new; - } else { - /* -diff -purNx .git BPI-Router-Linux-kernel/block/blk-rq-qos.c BPI-Router-Linux-kernel-6.16.12/block/blk-rq-qos.c ---- BPI-Router-Linux-kernel/block/blk-rq-qos.c 2025-10-22 13:53:23.151329431 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/block/blk-rq-qos.c 2025-10-22 13:53:56.403169681 -0400 -@@ -2,8 +2,6 @@ - - #include "blk-rq-qos.h" - --__read_mostly DEFINE_STATIC_KEY_FALSE(block_rq_qos); -- - /* - * Increment 'v', if 'v' is below 'below'. Returns true if we succeeded, - * false if 'v' + 1 would be bigger than 'below'. -@@ -319,8 +317,8 @@ void rq_qos_exit(struct request_queue *q - struct rq_qos *rqos = q->rq_qos; - q->rq_qos = rqos->next; - rqos->ops->exit(rqos); -- static_branch_dec(&block_rq_qos); - } -+ blk_queue_flag_clear(QUEUE_FLAG_QOS_ENABLED, q); - mutex_unlock(&q->rq_qos_mutex); - } - -@@ -346,7 +344,7 @@ int rq_qos_add(struct rq_qos *rqos, stru - goto ebusy; - rqos->next = q->rq_qos; - q->rq_qos = rqos; -- static_branch_inc(&block_rq_qos); -+ blk_queue_flag_set(QUEUE_FLAG_QOS_ENABLED, q); - - blk_mq_unfreeze_queue(q, memflags); - -@@ -377,6 +375,8 @@ void rq_qos_del(struct rq_qos *rqos) - break; - } - } -+ if (!q->rq_qos) -+ blk_queue_flag_clear(QUEUE_FLAG_QOS_ENABLED, q); - blk_mq_unfreeze_queue(q, memflags); - - mutex_lock(&q->debugfs_mutex); -diff -purNx .git BPI-Router-Linux-kernel/block/blk-rq-qos.h BPI-Router-Linux-kernel-6.16.12/block/blk-rq-qos.h ---- BPI-Router-Linux-kernel/block/blk-rq-qos.h 2025-10-22 13:53:23.151329431 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/block/blk-rq-qos.h 2025-10-22 13:53:56.403169681 -0400 -@@ -12,7 +12,6 @@ - #include "blk-mq-debugfs.h" - - struct blk_mq_debugfs_attr; --extern struct static_key_false block_rq_qos; - - enum rq_qos_id { - RQ_QOS_WBT, -@@ -113,43 +112,58 @@ void __rq_qos_queue_depth_changed(struct - - static inline void rq_qos_cleanup(struct request_queue *q, struct bio *bio) - { -- if (static_branch_unlikely(&block_rq_qos) && q->rq_qos) -+ if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && -+ q->rq_qos) - __rq_qos_cleanup(q->rq_qos, bio); - } - - static inline void rq_qos_done(struct request_queue *q, struct request *rq) - { -- if (static_branch_unlikely(&block_rq_qos) && q->rq_qos && -- !blk_rq_is_passthrough(rq)) -+ if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && -+ q->rq_qos && !blk_rq_is_passthrough(rq)) - __rq_qos_done(q->rq_qos, rq); - } - - static inline void rq_qos_issue(struct request_queue *q, struct request *rq) - { -- if (static_branch_unlikely(&block_rq_qos) && q->rq_qos) -+ if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && -+ q->rq_qos) - __rq_qos_issue(q->rq_qos, rq); - } - - static inline void rq_qos_requeue(struct request_queue *q, struct request *rq) - { -- if (static_branch_unlikely(&block_rq_qos) && q->rq_qos) -+ if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && -+ q->rq_qos) - __rq_qos_requeue(q->rq_qos, rq); - } - - static inline void rq_qos_done_bio(struct bio *bio) - { -- if (static_branch_unlikely(&block_rq_qos) && -- bio->bi_bdev && (bio_flagged(bio, BIO_QOS_THROTTLED) || -- bio_flagged(bio, BIO_QOS_MERGED))) { -- struct request_queue *q = bdev_get_queue(bio->bi_bdev); -- if (q->rq_qos) -- __rq_qos_done_bio(q->rq_qos, bio); -- } -+ struct request_queue *q; -+ -+ if (!bio->bi_bdev || (!bio_flagged(bio, BIO_QOS_THROTTLED) && -+ !bio_flagged(bio, BIO_QOS_MERGED))) -+ return; -+ -+ q = bdev_get_queue(bio->bi_bdev); -+ -+ /* -+ * A BIO may carry BIO_QOS_* flags even if the associated request_queue -+ * does not have rq_qos enabled. This can happen with stacked block -+ * devices — for example, NVMe multipath, where it's possible that the -+ * bottom device has QoS enabled but the top device does not. Therefore, -+ * always verify that q->rq_qos is present and QoS is enabled before -+ * calling __rq_qos_done_bio(). -+ */ -+ if (test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags) && q->rq_qos) -+ __rq_qos_done_bio(q->rq_qos, bio); - } - - static inline void rq_qos_throttle(struct request_queue *q, struct bio *bio) - { -- if (static_branch_unlikely(&block_rq_qos) && q->rq_qos) { -+ if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && -+ q->rq_qos) { - bio_set_flag(bio, BIO_QOS_THROTTLED); - __rq_qos_throttle(q->rq_qos, bio); - } -@@ -158,14 +172,16 @@ static inline void rq_qos_throttle(struc - static inline void rq_qos_track(struct request_queue *q, struct request *rq, - struct bio *bio) - { -- if (static_branch_unlikely(&block_rq_qos) && q->rq_qos) -+ if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && -+ q->rq_qos) - __rq_qos_track(q->rq_qos, rq, bio); - } - - static inline void rq_qos_merge(struct request_queue *q, struct request *rq, - struct bio *bio) - { -- if (static_branch_unlikely(&block_rq_qos) && q->rq_qos) { -+ if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && -+ q->rq_qos) { - bio_set_flag(bio, BIO_QOS_MERGED); - __rq_qos_merge(q->rq_qos, rq, bio); - } -@@ -173,7 +189,8 @@ static inline void rq_qos_merge(struct r - - static inline void rq_qos_queue_depth_changed(struct request_queue *q) - { -- if (static_branch_unlikely(&block_rq_qos) && q->rq_qos) -+ if (unlikely(test_bit(QUEUE_FLAG_QOS_ENABLED, &q->queue_flags)) && -+ q->rq_qos) - __rq_qos_queue_depth_changed(q->rq_qos); - } - -diff -purNx .git BPI-Router-Linux-kernel/block/blk-settings.c BPI-Router-Linux-kernel-6.16.12/block/blk-settings.c ---- BPI-Router-Linux-kernel/block/blk-settings.c 2025-10-22 13:53:23.151329431 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/block/blk-settings.c 2025-10-22 13:53:56.403169681 -0400 -@@ -181,6 +181,8 @@ static void blk_atomic_writes_update_lim - static void blk_validate_atomic_write_limits(struct queue_limits *lim) - { - unsigned int boundary_sectors; -+ unsigned int atomic_write_hw_max_sectors = -+ lim->atomic_write_hw_max >> SECTOR_SHIFT; - - if (!(lim->features & BLK_FEAT_ATOMIC_WRITES)) - goto unsupported; -@@ -202,6 +204,10 @@ static void blk_validate_atomic_write_li - lim->atomic_write_hw_max)) - goto unsupported; - -+ if (WARN_ON_ONCE(lim->chunk_sectors && -+ atomic_write_hw_max_sectors > lim->chunk_sectors)) -+ goto unsupported; -+ - boundary_sectors = lim->atomic_write_hw_boundary >> SECTOR_SHIFT; - - if (boundary_sectors) { -@@ -336,12 +342,19 @@ int blk_validate_limits(struct queue_lim - lim->max_discard_sectors = - min(lim->max_hw_discard_sectors, lim->max_user_discard_sectors); - -+ /* -+ * When discard is not supported, discard_granularity should be reported -+ * as 0 to userspace. -+ */ -+ if (lim->max_discard_sectors) -+ lim->discard_granularity = -+ max(lim->discard_granularity, lim->physical_block_size); -+ else -+ lim->discard_granularity = 0; -+ - if (!lim->max_discard_segments) - lim->max_discard_segments = 1; - -- if (lim->discard_granularity < lim->physical_block_size) -- lim->discard_granularity = lim->physical_block_size; -- - /* - * By default there is no limit on the segment boundary alignment, - * but if there is one it can't be smaller than the page size as -@@ -779,7 +792,7 @@ int blk_stack_limits(struct queue_limits - } - - /* chunk_sectors a multiple of the physical block size? */ -- if ((t->chunk_sectors << 9) & (t->physical_block_size - 1)) { -+ if (t->chunk_sectors % (t->physical_block_size >> SECTOR_SHIFT)) { - t->chunk_sectors = 0; - t->flags |= BLK_FLAG_MISALIGNED; - ret = -1; -diff -purNx .git BPI-Router-Linux-kernel/block/blk-sysfs.c BPI-Router-Linux-kernel-6.16.12/block/blk-sysfs.c ---- BPI-Router-Linux-kernel/block/blk-sysfs.c 2025-10-22 13:53:23.151329431 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/block/blk-sysfs.c 2025-10-22 13:53:56.403169681 -0400 -@@ -821,7 +821,7 @@ static void blk_queue_release(struct kob - /* nothing to do here, all data is associated with the parent gendisk */ - } - --static const struct kobj_type blk_queue_ktype = { -+const struct kobj_type blk_queue_ktype = { - .default_groups = blk_queue_attr_groups, - .sysfs_ops = &queue_sysfs_ops, - .release = blk_queue_release, -@@ -849,15 +849,14 @@ int blk_register_queue(struct gendisk *d - struct request_queue *q = disk->queue; - int ret; - -- kobject_init(&disk->queue_kobj, &blk_queue_ktype); - ret = kobject_add(&disk->queue_kobj, &disk_to_dev(disk)->kobj, "queue"); - if (ret < 0) -- goto out_put_queue_kobj; -+ return ret; - - if (queue_is_mq(q)) { - ret = blk_mq_sysfs_register(disk); - if (ret) -- goto out_put_queue_kobj; -+ goto out_del_queue_kobj; - } - mutex_lock(&q->sysfs_lock); - -@@ -877,9 +876,9 @@ int blk_register_queue(struct gendisk *d - - if (queue_is_mq(q)) - elevator_set_default(q); -- wbt_enable_default(disk); - - blk_queue_flag_set(QUEUE_FLAG_REGISTERED, q); -+ wbt_enable_default(disk); - - /* Now everything is ready and send out KOBJ_ADD uevent */ - kobject_uevent(&disk->queue_kobj, KOBJ_ADD); -@@ -908,8 +907,8 @@ out_debugfs_remove: - mutex_unlock(&q->sysfs_lock); - if (queue_is_mq(q)) - blk_mq_sysfs_unregister(disk); --out_put_queue_kobj: -- kobject_put(&disk->queue_kobj); -+out_del_queue_kobj: -+ kobject_del(&disk->queue_kobj); - return ret; - } - -diff -purNx .git BPI-Router-Linux-kernel/block/blk-zoned.c BPI-Router-Linux-kernel-6.16.12/block/blk-zoned.c ---- BPI-Router-Linux-kernel/block/blk-zoned.c 2025-10-22 13:53:23.151329431 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/block/blk-zoned.c 2025-10-22 13:53:56.403169681 -0400 -@@ -1116,25 +1116,7 @@ bool blk_zone_plug_bio(struct bio *bio, - { - struct block_device *bdev = bio->bi_bdev; - -- if (!bdev->bd_disk->zone_wplugs_hash) -- return false; -- -- /* -- * If the BIO already has the plugging flag set, then it was already -- * handled through this path and this is a submission from the zone -- * plug bio submit work. -- */ -- if (bio_flagged(bio, BIO_ZONE_WRITE_PLUGGING)) -- return false; -- -- /* -- * We do not need to do anything special for empty flush BIOs, e.g -- * BIOs such as issued by blkdev_issue_flush(). The is because it is -- * the responsibility of the user to first wait for the completion of -- * write operations for flush to have any effect on the persistence of -- * the written data. -- */ -- if (op_is_flush(bio->bi_opf) && !bio_sectors(bio)) -+ if (WARN_ON_ONCE(!bdev->bd_disk->zone_wplugs_hash)) - return false; - - /* -@@ -1225,6 +1207,7 @@ void blk_zone_write_plug_bio_endio(struc - if (bio_flagged(bio, BIO_EMULATES_ZONE_APPEND)) { - bio->bi_opf &= ~REQ_OP_MASK; - bio->bi_opf |= REQ_OP_ZONE_APPEND; -+ bio_clear_flag(bio, BIO_EMULATES_ZONE_APPEND); - } - - /* -@@ -1283,14 +1266,14 @@ static void blk_zone_wplug_bio_work(stru - struct block_device *bdev; - unsigned long flags; - struct bio *bio; -+ bool prepared; - - /* - * Submit the next plugged BIO. If we do not have any, clear - * the plugged flag. - */ -- spin_lock_irqsave(&zwplug->lock, flags); -- - again: -+ spin_lock_irqsave(&zwplug->lock, flags); - bio = bio_list_pop(&zwplug->bio_list); - if (!bio) { - zwplug->flags &= ~BLK_ZONE_WPLUG_PLUGGED; -@@ -1298,15 +1281,15 @@ again: - goto put_zwplug; - } - -- if (!blk_zone_wplug_prepare_bio(zwplug, bio)) { -+ prepared = blk_zone_wplug_prepare_bio(zwplug, bio); -+ spin_unlock_irqrestore(&zwplug->lock, flags); -+ -+ if (!prepared) { - blk_zone_wplug_bio_io_error(zwplug, bio); - goto again; - } - -- spin_unlock_irqrestore(&zwplug->lock, flags); -- - bdev = bio->bi_bdev; -- submit_bio_noacct_nocheck(bio); - - /* - * blk-mq devices will reuse the extra reference on the request queue -@@ -1314,8 +1297,12 @@ again: - * path for BIO-based devices will not do that. So drop this extra - * reference here. - */ -- if (bdev_test_flag(bdev, BD_HAS_SUBMIT_BIO)) -+ if (bdev_test_flag(bdev, BD_HAS_SUBMIT_BIO)) { -+ bdev->bd_disk->fops->submit_bio(bio); - blk_queue_exit(bdev->bd_disk->queue); -+ } else { -+ blk_mq_submit_bio(bio); -+ } - - put_zwplug: - /* Drop the reference we took in disk_zone_wplug_schedule_bio_work(). */ -diff -purNx .git BPI-Router-Linux-kernel/block/elevator.c BPI-Router-Linux-kernel-6.16.12/block/elevator.c ---- BPI-Router-Linux-kernel/block/elevator.c 2025-10-22 13:53:23.151329431 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/block/elevator.c 2025-10-22 13:53:56.403169681 -0400 -@@ -54,6 +54,8 @@ struct elv_change_ctx { - struct elevator_queue *old; - /* for registering new elevator */ - struct elevator_queue *new; -+ /* holds sched tags data */ -+ struct elevator_tags *et; - }; - - static DEFINE_SPINLOCK(elv_list_lock); -@@ -132,7 +134,7 @@ static struct elevator_type *elevator_fi - static const struct kobj_type elv_ktype; - - struct elevator_queue *elevator_alloc(struct request_queue *q, -- struct elevator_type *e) -+ struct elevator_type *e, struct elevator_tags *et) - { - struct elevator_queue *eq; - -@@ -145,10 +147,10 @@ struct elevator_queue *elevator_alloc(st - kobject_init(&eq->kobj, &elv_ktype); - mutex_init(&eq->sysfs_lock); - hash_init(eq->hash); -+ eq->et = et; - - return eq; - } --EXPORT_SYMBOL(elevator_alloc); - - static void elevator_release(struct kobject *kobj) - { -@@ -166,7 +168,6 @@ static void elevator_exit(struct request - lockdep_assert_held(&q->elevator_lock); - - ioc_clear_queue(q); -- blk_mq_sched_free_rqs(q); - - mutex_lock(&e->sysfs_lock); - blk_mq_exit_sched(q, e); -@@ -592,7 +593,7 @@ static int elevator_switch(struct reques - } - - if (new_e) { -- ret = blk_mq_init_sched(q, new_e); -+ ret = blk_mq_init_sched(q, new_e, ctx->et); - if (ret) - goto out_unfreeze; - ctx->new = q->elevator; -@@ -627,8 +628,10 @@ static void elv_exit_and_release(struct - elevator_exit(q); - mutex_unlock(&q->elevator_lock); - blk_mq_unfreeze_queue(q, memflags); -- if (e) -+ if (e) { -+ blk_mq_free_sched_tags(e->et, q->tag_set); - kobject_put(&e->kobj); -+ } - } - - static int elevator_change_done(struct request_queue *q, -@@ -641,6 +644,7 @@ static int elevator_change_done(struct r - &ctx->old->flags); - - elv_unregister_queue(q, ctx->old); -+ blk_mq_free_sched_tags(ctx->old->et, q->tag_set); - kobject_put(&ctx->old->kobj); - if (enable_wbt) - wbt_enable_default(q->disk); -@@ -659,9 +663,16 @@ static int elevator_change_done(struct r - static int elevator_change(struct request_queue *q, struct elv_change_ctx *ctx) - { - unsigned int memflags; -+ struct blk_mq_tag_set *set = q->tag_set; - int ret = 0; - -- lockdep_assert_held(&q->tag_set->update_nr_hwq_lock); -+ lockdep_assert_held(&set->update_nr_hwq_lock); -+ -+ if (strncmp(ctx->name, "none", 4)) { -+ ctx->et = blk_mq_alloc_sched_tags(set, set->nr_hw_queues); -+ if (!ctx->et) -+ return -ENOMEM; -+ } - - memflags = blk_mq_freeze_queue(q); - /* -@@ -681,6 +692,11 @@ static int elevator_change(struct reques - blk_mq_unfreeze_queue(q, memflags); - if (!ret) - ret = elevator_change_done(q, ctx); -+ /* -+ * Free sched tags if it's allocated but we couldn't switch elevator. -+ */ -+ if (ctx->et && !ctx->new) -+ blk_mq_free_sched_tags(ctx->et, set); - - return ret; - } -@@ -689,24 +705,32 @@ static int elevator_change(struct reques - * The I/O scheduler depends on the number of hardware queues, this forces a - * reattachment when nr_hw_queues changes. - */ --void elv_update_nr_hw_queues(struct request_queue *q) -+void elv_update_nr_hw_queues(struct request_queue *q, struct elevator_type *e, -+ struct elevator_tags *t) - { -+ struct blk_mq_tag_set *set = q->tag_set; - struct elv_change_ctx ctx = {}; - int ret = -ENODEV; - - WARN_ON_ONCE(q->mq_freeze_depth == 0); - -- mutex_lock(&q->elevator_lock); -- if (q->elevator && !blk_queue_dying(q) && blk_queue_registered(q)) { -- ctx.name = q->elevator->type->elevator_name; -+ if (e && !blk_queue_dying(q) && blk_queue_registered(q)) { -+ ctx.name = e->elevator_name; -+ ctx.et = t; - -+ mutex_lock(&q->elevator_lock); - /* force to reattach elevator after nr_hw_queue is updated */ - ret = elevator_switch(q, &ctx); -+ mutex_unlock(&q->elevator_lock); - } -- mutex_unlock(&q->elevator_lock); - blk_mq_unfreeze_queue_nomemrestore(q); - if (!ret) - WARN_ON_ONCE(elevator_change_done(q, &ctx)); -+ /* -+ * Free sched tags if it's allocated but we couldn't switch elevator. -+ */ -+ if (t && !ctx.new) -+ blk_mq_free_sched_tags(t, set); - } - - /* -@@ -719,7 +743,8 @@ void elevator_set_default(struct request - .name = "mq-deadline", - .no_uevent = true, - }; -- int err = 0; -+ int err; -+ struct elevator_type *e; - - /* now we allow to switch elevator */ - blk_queue_flag_clear(QUEUE_FLAG_NO_ELV_SWITCH, q); -@@ -732,12 +757,18 @@ void elevator_set_default(struct request - * have multiple queues or mq-deadline is not available, default - * to "none". - */ -- if (elevator_find_get(ctx.name) && (q->nr_hw_queues == 1 || -- blk_mq_is_shared_tags(q->tag_set->flags))) -+ e = elevator_find_get(ctx.name); -+ if (!e) -+ return; -+ -+ if ((q->nr_hw_queues == 1 || -+ blk_mq_is_shared_tags(q->tag_set->flags))) { - err = elevator_change(q, &ctx); -- if (err < 0) -- pr_warn("\"%s\" elevator initialization, failed %d, " -- "falling back to \"none\"\n", ctx.name, err); -+ if (err < 0) -+ pr_warn("\"%s\" elevator initialization, failed %d, falling back to \"none\"\n", -+ ctx.name, err); -+ } -+ elevator_put(e); - } - - void elevator_set_none(struct request_queue *q) -diff -purNx .git BPI-Router-Linux-kernel/block/elevator.h BPI-Router-Linux-kernel-6.16.12/block/elevator.h ---- BPI-Router-Linux-kernel/block/elevator.h 2025-10-22 13:53:23.151329431 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/block/elevator.h 2025-10-22 13:53:56.403169681 -0400 -@@ -23,8 +23,17 @@ enum elv_merge { - struct blk_mq_alloc_data; - struct blk_mq_hw_ctx; - -+struct elevator_tags { -+ /* num. of hardware queues for which tags are allocated */ -+ unsigned int nr_hw_queues; -+ /* depth used while allocating tags */ -+ unsigned int nr_requests; -+ /* shared tag is stored at index 0 */ -+ struct blk_mq_tags *tags[]; -+}; -+ - struct elevator_mq_ops { -- int (*init_sched)(struct request_queue *, struct elevator_type *); -+ int (*init_sched)(struct request_queue *, struct elevator_queue *); - void (*exit_sched)(struct elevator_queue *); - int (*init_hctx)(struct blk_mq_hw_ctx *, unsigned int); - void (*exit_hctx)(struct blk_mq_hw_ctx *, unsigned int); -@@ -113,6 +122,7 @@ struct request *elv_rqhash_find(struct r - struct elevator_queue - { - struct elevator_type *type; -+ struct elevator_tags *et; - void *elevator_data; - struct kobject kobj; - struct mutex sysfs_lock; -@@ -152,8 +162,8 @@ ssize_t elv_iosched_show(struct gendisk - ssize_t elv_iosched_store(struct gendisk *disk, const char *page, size_t count); - - extern bool elv_bio_merge_ok(struct request *, struct bio *); --extern struct elevator_queue *elevator_alloc(struct request_queue *, -- struct elevator_type *); -+struct elevator_queue *elevator_alloc(struct request_queue *, -+ struct elevator_type *, struct elevator_tags *); - - /* - * Helper functions. -diff -purNx .git BPI-Router-Linux-kernel/block/fops.c BPI-Router-Linux-kernel-6.16.12/block/fops.c ---- BPI-Router-Linux-kernel/block/fops.c 2025-10-22 13:53:23.151329431 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/block/fops.c 2025-10-22 13:53:56.403169681 -0400 -@@ -7,6 +7,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -54,7 +55,6 @@ static ssize_t __blkdev_direct_IO_simple - struct bio bio; - ssize_t ret; - -- WARN_ON_ONCE(iocb->ki_flags & IOCB_HAS_METADATA); - if (nr_pages <= DIO_INLINE_BIO_VECS) - vecs = inline_vecs; - else { -@@ -131,7 +131,7 @@ static void blkdev_bio_end_io(struct bio - if (bio->bi_status && !dio->bio.bi_status) - dio->bio.bi_status = bio->bi_status; - -- if (!is_sync && (dio->iocb->ki_flags & IOCB_HAS_METADATA)) -+ if (bio_integrity(bio)) - bio_integrity_unmap_user(bio); - - if (atomic_dec_and_test(&dio->ref)) { -@@ -233,7 +233,7 @@ static ssize_t __blkdev_direct_IO(struct - } - bio->bi_opf |= REQ_NOWAIT; - } -- if (!is_sync && (iocb->ki_flags & IOCB_HAS_METADATA)) { -+ if (iocb->ki_flags & IOCB_HAS_METADATA) { - ret = bio_integrity_map_iter(bio, iocb->private); - if (unlikely(ret)) - goto fail; -@@ -301,7 +301,7 @@ static void blkdev_bio_end_io_async(stru - ret = blk_status_to_errno(bio->bi_status); - } - -- if (iocb->ki_flags & IOCB_HAS_METADATA) -+ if (bio_integrity(bio)) - bio_integrity_unmap_user(bio); - - iocb->ki_complete(iocb, ret); -@@ -422,7 +422,8 @@ static ssize_t blkdev_direct_IO(struct k - } - - nr_pages = bio_iov_vecs_to_alloc(iter, BIO_MAX_VECS + 1); -- if (likely(nr_pages <= BIO_MAX_VECS)) { -+ if (likely(nr_pages <= BIO_MAX_VECS && -+ !(iocb->ki_flags & IOCB_HAS_METADATA))) { - if (is_sync_kiocb(iocb)) - return __blkdev_direct_IO_simple(iocb, iter, bdev, - nr_pages); -@@ -672,6 +673,8 @@ static int blkdev_open(struct inode *ino - - if (bdev_can_atomic_write(bdev)) - filp->f_mode |= FMODE_CAN_ATOMIC_WRITE; -+ if (blk_get_integrity(bdev->bd_disk)) -+ filp->f_mode |= FMODE_HAS_METADATA; - - ret = bdev_open(bdev, mode, filp->private_data, NULL, filp); - if (ret) -diff -purNx .git BPI-Router-Linux-kernel/block/genhd.c BPI-Router-Linux-kernel-6.16.12/block/genhd.c ---- BPI-Router-Linux-kernel/block/genhd.c 2025-10-22 13:53:23.151329431 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/block/genhd.c 2025-10-22 13:53:56.403169681 -0400 -@@ -128,23 +128,27 @@ static void part_stat_read_all(struct bl - static void bdev_count_inflight_rw(struct block_device *part, - unsigned int inflight[2], bool mq_driver) - { -+ int write = 0; -+ int read = 0; - int cpu; - - if (mq_driver) { - blk_mq_in_driver_rw(part, inflight); -- } else { -- for_each_possible_cpu(cpu) { -- inflight[READ] += part_stat_local_read_cpu( -- part, in_flight[READ], cpu); -- inflight[WRITE] += part_stat_local_read_cpu( -- part, in_flight[WRITE], cpu); -- } -+ return; - } - -- if (WARN_ON_ONCE((int)inflight[READ] < 0)) -- inflight[READ] = 0; -- if (WARN_ON_ONCE((int)inflight[WRITE] < 0)) -- inflight[WRITE] = 0; -+ for_each_possible_cpu(cpu) { -+ read += part_stat_local_read_cpu(part, in_flight[READ], cpu); -+ write += part_stat_local_read_cpu(part, in_flight[WRITE], cpu); -+ } -+ -+ /* -+ * While iterating all CPUs, some IOs may be issued from a CPU already -+ * traversed and complete on a CPU that has not yet been traversed, -+ * causing the inflight number to be negative. -+ */ -+ inflight[READ] = read > 0 ? read : 0; -+ inflight[WRITE] = write > 0 ? write : 0; - } - - /** -@@ -1299,6 +1303,7 @@ static void disk_release(struct device * - disk_free_zone_resources(disk); - xa_destroy(&disk->part_tbl); - -+ kobject_put(&disk->queue_kobj); - disk->queue->disk = NULL; - blk_put_queue(disk->queue); - -@@ -1482,6 +1487,7 @@ struct gendisk *__alloc_disk_node(struct - INIT_LIST_HEAD(&disk->slave_bdevs); - #endif - mutex_init(&disk->rqos_state_mutex); -+ kobject_init(&disk->queue_kobj, &blk_queue_ktype); - return disk; - - out_erase_part0: -diff -purNx .git BPI-Router-Linux-kernel/block/kyber-iosched.c BPI-Router-Linux-kernel-6.16.12/block/kyber-iosched.c ---- BPI-Router-Linux-kernel/block/kyber-iosched.c 2025-10-22 13:53:23.151329431 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/block/kyber-iosched.c 2025-10-22 13:53:56.403169681 -0400 -@@ -157,10 +157,7 @@ struct kyber_queue_data { - */ - struct sbitmap_queue domain_tokens[KYBER_NUM_DOMAINS]; - -- /* -- * Async request percentage, converted to per-word depth for -- * sbitmap_get_shallow(). -- */ -+ /* Number of allowed async requests. */ - unsigned int async_depth; - - struct kyber_cpu_latency __percpu *cpu_latency; -@@ -402,20 +399,13 @@ err: - return ERR_PTR(ret); - } - --static int kyber_init_sched(struct request_queue *q, struct elevator_type *e) -+static int kyber_init_sched(struct request_queue *q, struct elevator_queue *eq) - { - struct kyber_queue_data *kqd; -- struct elevator_queue *eq; -- -- eq = elevator_alloc(q, e); -- if (!eq) -- return -ENOMEM; - - kqd = kyber_queue_data_alloc(q); -- if (IS_ERR(kqd)) { -- kobject_put(&eq->kobj); -+ if (IS_ERR(kqd)) - return PTR_ERR(kqd); -- } - - blk_stat_enable_accounting(q); - -@@ -454,10 +444,8 @@ static void kyber_depth_updated(struct b - { - struct kyber_queue_data *kqd = hctx->queue->elevator->elevator_data; - struct blk_mq_tags *tags = hctx->sched_tags; -- unsigned int shift = tags->bitmap_tags.sb.shift; -- -- kqd->async_depth = (1U << shift) * KYBER_ASYNC_PERCENT / 100U; - -+ kqd->async_depth = hctx->queue->nr_requests * KYBER_ASYNC_PERCENT / 100U; - sbitmap_queue_min_shallow_depth(&tags->bitmap_tags, kqd->async_depth); - } - -diff -purNx .git BPI-Router-Linux-kernel/block/mq-deadline.c BPI-Router-Linux-kernel-6.16.12/block/mq-deadline.c ---- BPI-Router-Linux-kernel/block/mq-deadline.c 2025-10-22 13:53:23.151329431 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/block/mq-deadline.c 2025-10-22 13:53:56.403169681 -0400 -@@ -488,20 +488,6 @@ unlock: - } - - /* -- * 'depth' is a number in the range 1..INT_MAX representing a number of -- * requests. Scale it with a factor (1 << bt->sb.shift) / q->nr_requests since -- * 1..(1 << bt->sb.shift) is the range expected by sbitmap_get_shallow(). -- * Values larger than q->nr_requests have the same effect as q->nr_requests. -- */ --static int dd_to_word_depth(struct blk_mq_hw_ctx *hctx, unsigned int qdepth) --{ -- struct sbitmap_queue *bt = &hctx->sched_tags->bitmap_tags; -- const unsigned int nrr = hctx->queue->nr_requests; -- -- return ((qdepth << bt->sb.shift) + nrr - 1) / nrr; --} -- --/* - * Called by __blk_mq_alloc_request(). The shallow_depth value set by this - * function is used by __blk_mq_get_tag(). - */ -@@ -517,7 +503,7 @@ static void dd_limit_depth(blk_opf_t opf - * Throttle asynchronous requests and writes such that these requests - * do not block the allocation of synchronous requests. - */ -- data->shallow_depth = dd_to_word_depth(data->hctx, dd->async_depth); -+ data->shallow_depth = dd->async_depth; - } - - /* Called by blk_mq_update_nr_requests(). */ -@@ -568,20 +554,14 @@ static void dd_exit_sched(struct elevato - /* - * initialize elevator private data (deadline_data). - */ --static int dd_init_sched(struct request_queue *q, struct elevator_type *e) -+static int dd_init_sched(struct request_queue *q, struct elevator_queue *eq) - { - struct deadline_data *dd; -- struct elevator_queue *eq; - enum dd_prio prio; -- int ret = -ENOMEM; -- -- eq = elevator_alloc(q, e); -- if (!eq) -- return ret; - - dd = kzalloc_node(sizeof(*dd), GFP_KERNEL, q->node); - if (!dd) -- goto put_eq; -+ return -ENOMEM; - - eq->elevator_data = dd; - -@@ -608,10 +588,6 @@ static int dd_init_sched(struct request_ - - q->elevator = eq; - return 0; -- --put_eq: -- kobject_put(&eq->kobj); -- return ret; - } - - /* -diff -purNx .git BPI-Router-Linux-kernel/CREDITS BPI-Router-Linux-kernel-6.16.12/CREDITS ---- BPI-Router-Linux-kernel/CREDITS 2025-10-22 13:53:23.031330005 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/CREDITS 2025-10-22 13:53:56.267170337 -0400 -@@ -1397,6 +1397,10 @@ N: Thomas Gleixner - E: tglx@linutronix.de - D: NAND flash hardware support, JFFS2 on NAND flash - -+N: Jérôme Glisse -+E: jglisse@redhat.com -+D: HMM - Heterogeneous Memory Management -+ - N: Richard E. Gooch - E: rgooch@atnf.csiro.au - D: parent process death signal to children -@@ -2981,6 +2985,11 @@ S: 521 Pleasant Valley Road - S: Potsdam, New York 13676 - S: USA - -+N: Shannon Nelson -+E: sln@onemain.com -+D: Worked on several network drivers including -+D: ixgbe, i40e, ionic, pds_core, pds_vdpa, pds_fwctl -+ - N: Dave Neuer - E: dave.neuer@pobox.com - D: Helped implement support for Compaq's H31xx series iPAQs -diff -purNx .git BPI-Router-Linux-kernel/crypto/af_alg.c BPI-Router-Linux-kernel-6.16.12/crypto/af_alg.c ---- BPI-Router-Linux-kernel/crypto/af_alg.c 2025-10-22 13:53:23.155329412 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/crypto/af_alg.c 2025-10-22 13:53:56.403169681 -0400 -@@ -970,6 +970,12 @@ int af_alg_sendmsg(struct socket *sock, - } - - lock_sock(sk); -+ if (ctx->write) { -+ release_sock(sk); -+ return -EBUSY; -+ } -+ ctx->write = true; -+ - if (ctx->init && !ctx->more) { - if (ctx->used) { - err = -EINVAL; -@@ -1019,6 +1025,8 @@ int af_alg_sendmsg(struct socket *sock, - continue; - } - -+ ctx->merge = 0; -+ - if (!af_alg_writable(sk)) { - err = af_alg_wait_for_wmem(sk, msg->msg_flags); - if (err) -@@ -1058,7 +1066,6 @@ int af_alg_sendmsg(struct socket *sock, - ctx->used += plen; - copied += plen; - size -= plen; -- ctx->merge = 0; - } else { - do { - struct page *pg; -@@ -1104,6 +1111,7 @@ int af_alg_sendmsg(struct socket *sock, - - unlock: - af_alg_data_wakeup(sk); -+ ctx->write = false; - release_sock(sk); - - return copied ?: err; -diff -purNx .git BPI-Router-Linux-kernel/crypto/ahash.c BPI-Router-Linux-kernel-6.16.12/crypto/ahash.c ---- BPI-Router-Linux-kernel/crypto/ahash.c 2025-10-22 13:53:23.155329412 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/crypto/ahash.c 2025-10-22 13:53:56.403169681 -0400 -@@ -347,6 +347,12 @@ static int ahash_do_req_chain(struct aha - if (crypto_ahash_statesize(tfm) > HASH_MAX_STATESIZE) - return -ENOSYS; - -+ if (!crypto_ahash_need_fallback(tfm)) -+ return -ENOSYS; -+ -+ if (crypto_hash_no_export_core(tfm)) -+ return -ENOSYS; -+ - { - u8 state[HASH_MAX_STATESIZE]; - -@@ -600,12 +606,14 @@ static void ahash_def_finup_done2(void * - - static int ahash_def_finup_finish1(struct ahash_request *req, int err) - { -+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); -+ - if (err) - goto out; - - req->base.complete = ahash_def_finup_done2; - -- err = crypto_ahash_final(req); -+ err = crypto_ahash_alg(tfm)->final(req); - if (err == -EINPROGRESS || err == -EBUSY) - return err; - -@@ -952,6 +960,10 @@ static int ahash_prepare_alg(struct ahas - base->cra_reqsize > MAX_SYNC_HASH_REQSIZE) - return -EINVAL; - -+ if (base->cra_flags & CRYPTO_ALG_NEED_FALLBACK && -+ base->cra_flags & CRYPTO_ALG_NO_FALLBACK) -+ return -EINVAL; -+ - err = hash_prepare_alg(&alg->halg); - if (err) - return err; -@@ -960,7 +972,8 @@ static int ahash_prepare_alg(struct ahas - base->cra_flags |= CRYPTO_ALG_TYPE_AHASH; - - if ((base->cra_flags ^ CRYPTO_ALG_REQ_VIRT) & -- (CRYPTO_ALG_ASYNC | CRYPTO_ALG_REQ_VIRT)) -+ (CRYPTO_ALG_ASYNC | CRYPTO_ALG_REQ_VIRT) && -+ !(base->cra_flags & CRYPTO_ALG_NO_FALLBACK)) - base->cra_flags |= CRYPTO_ALG_NEED_FALLBACK; - - if (!alg->setkey) -diff -purNx .git BPI-Router-Linux-kernel/crypto/deflate.c BPI-Router-Linux-kernel-6.16.12/crypto/deflate.c ---- BPI-Router-Linux-kernel/crypto/deflate.c 2025-10-22 13:53:23.155329412 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/crypto/deflate.c 2025-10-22 13:53:56.403169681 -0400 -@@ -48,9 +48,14 @@ static void *deflate_alloc_stream(void) - return ctx; - } - -+static void deflate_free_stream(void *ctx) -+{ -+ kvfree(ctx); -+} -+ - static struct crypto_acomp_streams deflate_streams = { - .alloc_ctx = deflate_alloc_stream, -- .cfree_ctx = kvfree, -+ .free_ctx = deflate_free_stream, - }; - - static int deflate_compress_one(struct acomp_req *req, -diff -purNx .git BPI-Router-Linux-kernel/crypto/hkdf.c BPI-Router-Linux-kernel-6.16.12/crypto/hkdf.c ---- BPI-Router-Linux-kernel/crypto/hkdf.c 2025-10-22 13:53:23.155329412 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/crypto/hkdf.c 2025-10-22 13:53:56.403169681 -0400 -@@ -566,7 +566,7 @@ static int __init crypto_hkdf_module_ini - - static void __exit crypto_hkdf_module_exit(void) {} - --module_init(crypto_hkdf_module_init); -+late_initcall(crypto_hkdf_module_init); - module_exit(crypto_hkdf_module_exit); - - MODULE_LICENSE("GPL"); -diff -purNx .git BPI-Router-Linux-kernel/crypto/jitterentropy-kcapi.c BPI-Router-Linux-kernel-6.16.12/crypto/jitterentropy-kcapi.c ---- BPI-Router-Linux-kernel/crypto/jitterentropy-kcapi.c 2025-10-22 13:53:23.155329412 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/crypto/jitterentropy-kcapi.c 2025-10-22 13:53:56.403169681 -0400 -@@ -144,7 +144,7 @@ int jent_hash_time(void *hash_state, __u - * Inject the data from the previous loop into the pool. This data is - * not considered to contain any entropy, but it stirs the pool a bit. - */ -- ret = crypto_shash_update(desc, intermediary, sizeof(intermediary)); -+ ret = crypto_shash_update(hash_state_desc, intermediary, sizeof(intermediary)); - if (ret) - goto err; - -@@ -157,11 +157,12 @@ int jent_hash_time(void *hash_state, __u - * conditioning operation to have an identical amount of input data - * according to section 3.1.5. - */ -- if (!stuck) { -- ret = crypto_shash_update(hash_state_desc, (u8 *)&time, -- sizeof(__u64)); -+ if (stuck) { -+ time = 0; - } - -+ ret = crypto_shash_update(hash_state_desc, (u8 *)&time, sizeof(__u64)); -+ - err: - shash_desc_zero(desc); - memzero_explicit(intermediary, sizeof(intermediary)); -diff -purNx .git BPI-Router-Linux-kernel/crypto/Kconfig BPI-Router-Linux-kernel-6.16.12/crypto/Kconfig ---- BPI-Router-Linux-kernel/crypto/Kconfig 2025-10-22 13:53:23.155329412 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/crypto/Kconfig 2025-10-22 13:53:56.403169681 -0400 -@@ -176,16 +176,33 @@ config CRYPTO_USER - - config CRYPTO_SELFTESTS - bool "Enable cryptographic self-tests" -- depends on DEBUG_KERNEL -+ depends on EXPERT - help - Enable the cryptographic self-tests. - - The cryptographic self-tests run at boot time, or at algorithm - registration time if algorithms are dynamically loaded later. - -- This is primarily intended for developer use. It should not be -- enabled in production kernels, unless you are trying to use these -- tests to fulfill a FIPS testing requirement. -+ There are two main use cases for these tests: -+ -+ - Development and pre-release testing. In this case, also enable -+ CRYPTO_SELFTESTS_FULL to get the full set of tests. All crypto code -+ in the kernel is expected to pass the full set of tests. -+ -+ - Production kernels, to help prevent buggy drivers from being used -+ and/or meet FIPS 140-3 pre-operational testing requirements. In -+ this case, enable CRYPTO_SELFTESTS but not CRYPTO_SELFTESTS_FULL. -+ -+config CRYPTO_SELFTESTS_FULL -+ bool "Enable the full set of cryptographic self-tests" -+ depends on CRYPTO_SELFTESTS -+ help -+ Enable the full set of cryptographic self-tests for each algorithm. -+ -+ The full set of tests should be enabled for development and -+ pre-release testing, but not in production kernels. -+ -+ All crypto code in the kernel is expected to pass the full tests. - - config CRYPTO_NULL - tristate "Null algorithms" -diff -purNx .git BPI-Router-Linux-kernel/crypto/krb5/selftest.c BPI-Router-Linux-kernel-6.16.12/crypto/krb5/selftest.c ---- BPI-Router-Linux-kernel/crypto/krb5/selftest.c 2025-10-22 13:53:23.155329412 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/crypto/krb5/selftest.c 2025-10-22 13:53:56.403169681 -0400 -@@ -152,6 +152,7 @@ static int krb5_test_one_prf(const struc - - out: - clear_buf(&result); -+ clear_buf(&prf); - clear_buf(&octet); - clear_buf(&key); - return ret; -diff -purNx .git BPI-Router-Linux-kernel/crypto/rng.c BPI-Router-Linux-kernel-6.16.12/crypto/rng.c ---- BPI-Router-Linux-kernel/crypto/rng.c 2025-10-22 13:53:23.155329412 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/crypto/rng.c 2025-10-22 13:53:56.403169681 -0400 -@@ -168,6 +168,11 @@ out: - EXPORT_SYMBOL_GPL(crypto_del_default_rng); - #endif - -+static void rng_default_set_ent(struct crypto_rng *tfm, const u8 *data, -+ unsigned int len) -+{ -+} -+ - int crypto_register_rng(struct rng_alg *alg) - { - struct crypto_alg *base = &alg->base; -@@ -179,6 +184,9 @@ int crypto_register_rng(struct rng_alg * - base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK; - base->cra_flags |= CRYPTO_ALG_TYPE_RNG; - -+ if (!alg->set_ent) -+ alg->set_ent = rng_default_set_ent; -+ - return crypto_register_alg(base); - } - EXPORT_SYMBOL_GPL(crypto_register_rng); -diff -purNx .git BPI-Router-Linux-kernel/crypto/testmgr.c BPI-Router-Linux-kernel-6.16.12/crypto/testmgr.c ---- BPI-Router-Linux-kernel/crypto/testmgr.c 2025-10-22 13:53:23.155329412 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/crypto/testmgr.c 2025-10-22 13:53:56.403169681 -0400 -@@ -45,6 +45,7 @@ static bool notests; - module_param(notests, bool, 0644); - MODULE_PARM_DESC(notests, "disable all crypto self-tests"); - -+#ifdef CONFIG_CRYPTO_SELFTESTS_FULL - static bool noslowtests; - module_param(noslowtests, bool, 0644); - MODULE_PARM_DESC(noslowtests, "disable slow crypto self-tests"); -@@ -52,6 +53,10 @@ MODULE_PARM_DESC(noslowtests, "disable s - static unsigned int fuzz_iterations = 100; - module_param(fuzz_iterations, uint, 0644); - MODULE_PARM_DESC(fuzz_iterations, "number of fuzz test iterations"); -+#else -+#define noslowtests 1 -+#define fuzz_iterations 0 -+#endif - - #ifndef CONFIG_CRYPTO_SELFTESTS - -@@ -319,9 +324,9 @@ struct testvec_config { - - /* - * The following are the lists of testvec_configs to test for each algorithm -- * type when the fast crypto self-tests are enabled. They aim to provide good -- * test coverage, while keeping the test time much shorter than the full tests -- * so that the fast tests can be used to fulfill FIPS 140 testing requirements. -+ * type when the "fast" crypto self-tests are enabled. They aim to provide good -+ * test coverage, while keeping the test time much shorter than the "full" tests -+ * so that the "fast" tests can be enabled in a wider range of circumstances. - */ - - /* Configs for skciphers and aeads */ -@@ -1183,14 +1188,18 @@ static void generate_random_testvec_conf - - static void crypto_disable_simd_for_test(void) - { -+#ifdef CONFIG_CRYPTO_SELFTESTS_FULL - migrate_disable(); - __this_cpu_write(crypto_simd_disabled_for_test, true); -+#endif - } - - static void crypto_reenable_simd_for_test(void) - { -+#ifdef CONFIG_CRYPTO_SELFTESTS_FULL - __this_cpu_write(crypto_simd_disabled_for_test, false); - migrate_enable(); -+#endif - } - - /* -diff -purNx .git BPI-Router-Linux-kernel/crypto/wp512.c BPI-Router-Linux-kernel-6.16.12/crypto/wp512.c ---- BPI-Router-Linux-kernel/crypto/wp512.c 2025-10-22 13:53:23.155329412 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/crypto/wp512.c 2025-10-22 13:53:56.403169681 -0400 -@@ -21,10 +21,10 @@ - */ - #include - #include -+#include - #include --#include --#include --#include -+#include -+#include - - #define WP512_DIGEST_SIZE 64 - #define WP384_DIGEST_SIZE 48 -@@ -37,9 +37,6 @@ - - struct wp512_ctx { - u8 bitLength[WP512_LENGTHBYTES]; -- u8 buffer[WP512_BLOCK_SIZE]; -- int bufferBits; -- int bufferPos; - u64 hash[WP512_DIGEST_SIZE/8]; - }; - -@@ -779,16 +776,16 @@ static const u64 rc[WHIRLPOOL_ROUNDS] = - * The core Whirlpool transform. - */ - --static __no_kmsan_checks void wp512_process_buffer(struct wp512_ctx *wctx) { -+static __no_kmsan_checks void wp512_process_buffer(struct wp512_ctx *wctx, -+ const u8 *buffer) { - int i, r; - u64 K[8]; /* the round key */ - u64 block[8]; /* mu(buffer) */ - u64 state[8]; /* the cipher state */ - u64 L[8]; -- const __be64 *buffer = (const __be64 *)wctx->buffer; - - for (i = 0; i < 8; i++) -- block[i] = be64_to_cpu(buffer[i]); -+ block[i] = get_unaligned_be64(buffer + i * 8); - - state[0] = block[0] ^ (K[0] = wctx->hash[0]); - state[1] = block[1] ^ (K[1] = wctx->hash[1]); -@@ -991,8 +988,6 @@ static int wp512_init(struct shash_desc - int i; - - memset(wctx->bitLength, 0, 32); -- wctx->bufferBits = wctx->bufferPos = 0; -- wctx->buffer[0] = 0; - for (i = 0; i < 8; i++) { - wctx->hash[i] = 0L; - } -@@ -1000,84 +995,54 @@ static int wp512_init(struct shash_desc - return 0; - } - --static int wp512_update(struct shash_desc *desc, const u8 *source, -- unsigned int len) -+static void wp512_add_length(u8 *bitLength, u64 value) - { -- struct wp512_ctx *wctx = shash_desc_ctx(desc); -- int sourcePos = 0; -- unsigned int bits_len = len * 8; // convert to number of bits -- int sourceGap = (8 - ((int)bits_len & 7)) & 7; -- int bufferRem = wctx->bufferBits & 7; -+ u32 carry; - int i; -- u32 b, carry; -- u8 *buffer = wctx->buffer; -- u8 *bitLength = wctx->bitLength; -- int bufferBits = wctx->bufferBits; -- int bufferPos = wctx->bufferPos; - -- u64 value = bits_len; - for (i = 31, carry = 0; i >= 0 && (carry != 0 || value != 0ULL); i--) { - carry += bitLength[i] + ((u32)value & 0xff); - bitLength[i] = (u8)carry; - carry >>= 8; - value >>= 8; - } -- while (bits_len > 8) { -- b = ((source[sourcePos] << sourceGap) & 0xff) | -- ((source[sourcePos + 1] & 0xff) >> (8 - sourceGap)); -- buffer[bufferPos++] |= (u8)(b >> bufferRem); -- bufferBits += 8 - bufferRem; -- if (bufferBits == WP512_BLOCK_SIZE * 8) { -- wp512_process_buffer(wctx); -- bufferBits = bufferPos = 0; -- } -- buffer[bufferPos] = b << (8 - bufferRem); -- bufferBits += bufferRem; -- bits_len -= 8; -- sourcePos++; -- } -- if (bits_len > 0) { -- b = (source[sourcePos] << sourceGap) & 0xff; -- buffer[bufferPos] |= b >> bufferRem; -- } else { -- b = 0; -- } -- if (bufferRem + bits_len < 8) { -- bufferBits += bits_len; -- } else { -- bufferPos++; -- bufferBits += 8 - bufferRem; -- bits_len -= 8 - bufferRem; -- if (bufferBits == WP512_BLOCK_SIZE * 8) { -- wp512_process_buffer(wctx); -- bufferBits = bufferPos = 0; -- } -- buffer[bufferPos] = b << (8 - bufferRem); -- bufferBits += (int)bits_len; -- } -+} - -- wctx->bufferBits = bufferBits; -- wctx->bufferPos = bufferPos; -+static int wp512_update(struct shash_desc *desc, const u8 *source, -+ unsigned int len) -+{ -+ struct wp512_ctx *wctx = shash_desc_ctx(desc); -+ unsigned int remain = len % WP512_BLOCK_SIZE; -+ u64 bits_len = (len - remain) * 8ull; -+ u8 *bitLength = wctx->bitLength; - -- return 0; -+ wp512_add_length(bitLength, bits_len); -+ do { -+ wp512_process_buffer(wctx, source); -+ source += WP512_BLOCK_SIZE; -+ bits_len -= WP512_BLOCK_SIZE * 8; -+ } while (bits_len); -+ -+ return remain; - } - --static int wp512_final(struct shash_desc *desc, u8 *out) -+static int wp512_finup(struct shash_desc *desc, const u8 *src, -+ unsigned int bufferPos, u8 *out) - { - struct wp512_ctx *wctx = shash_desc_ctx(desc); - int i; -- u8 *buffer = wctx->buffer; - u8 *bitLength = wctx->bitLength; -- int bufferBits = wctx->bufferBits; -- int bufferPos = wctx->bufferPos; - __be64 *digest = (__be64 *)out; -+ u8 buffer[WP512_BLOCK_SIZE]; - -- buffer[bufferPos] |= 0x80U >> (bufferBits & 7); -+ wp512_add_length(bitLength, bufferPos * 8); -+ memcpy(buffer, src, bufferPos); -+ buffer[bufferPos] = 0x80U; - bufferPos++; - if (bufferPos > WP512_BLOCK_SIZE - WP512_LENGTHBYTES) { - if (bufferPos < WP512_BLOCK_SIZE) - memset(&buffer[bufferPos], 0, WP512_BLOCK_SIZE - bufferPos); -- wp512_process_buffer(wctx); -+ wp512_process_buffer(wctx, buffer); - bufferPos = 0; - } - if (bufferPos < WP512_BLOCK_SIZE - WP512_LENGTHBYTES) -@@ -1086,31 +1051,32 @@ static int wp512_final(struct shash_desc - bufferPos = WP512_BLOCK_SIZE - WP512_LENGTHBYTES; - memcpy(&buffer[WP512_BLOCK_SIZE - WP512_LENGTHBYTES], - bitLength, WP512_LENGTHBYTES); -- wp512_process_buffer(wctx); -+ wp512_process_buffer(wctx, buffer); -+ memzero_explicit(buffer, sizeof(buffer)); - for (i = 0; i < WP512_DIGEST_SIZE/8; i++) - digest[i] = cpu_to_be64(wctx->hash[i]); -- wctx->bufferBits = bufferBits; -- wctx->bufferPos = bufferPos; - - return 0; - } - --static int wp384_final(struct shash_desc *desc, u8 *out) -+static int wp384_finup(struct shash_desc *desc, const u8 *src, -+ unsigned int len, u8 *out) - { - u8 D[64]; - -- wp512_final(desc, D); -+ wp512_finup(desc, src, len, D); - memcpy(out, D, WP384_DIGEST_SIZE); - memzero_explicit(D, WP512_DIGEST_SIZE); - - return 0; - } - --static int wp256_final(struct shash_desc *desc, u8 *out) -+static int wp256_finup(struct shash_desc *desc, const u8 *src, -+ unsigned int len, u8 *out) - { - u8 D[64]; - -- wp512_final(desc, D); -+ wp512_finup(desc, src, len, D); - memcpy(out, D, WP256_DIGEST_SIZE); - memzero_explicit(D, WP512_DIGEST_SIZE); - -@@ -1121,11 +1087,12 @@ static struct shash_alg wp_algs[3] = { { - .digestsize = WP512_DIGEST_SIZE, - .init = wp512_init, - .update = wp512_update, -- .final = wp512_final, -+ .finup = wp512_finup, - .descsize = sizeof(struct wp512_ctx), - .base = { - .cra_name = "wp512", - .cra_driver_name = "wp512-generic", -+ .cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY, - .cra_blocksize = WP512_BLOCK_SIZE, - .cra_module = THIS_MODULE, - } -@@ -1133,11 +1100,12 @@ static struct shash_alg wp_algs[3] = { { - .digestsize = WP384_DIGEST_SIZE, - .init = wp512_init, - .update = wp512_update, -- .final = wp384_final, -+ .finup = wp384_finup, - .descsize = sizeof(struct wp512_ctx), - .base = { - .cra_name = "wp384", - .cra_driver_name = "wp384-generic", -+ .cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY, - .cra_blocksize = WP512_BLOCK_SIZE, - .cra_module = THIS_MODULE, - } -@@ -1145,11 +1113,12 @@ static struct shash_alg wp_algs[3] = { { - .digestsize = WP256_DIGEST_SIZE, - .init = wp512_init, - .update = wp512_update, -- .final = wp256_final, -+ .finup = wp256_finup, - .descsize = sizeof(struct wp512_ctx), - .base = { - .cra_name = "wp256", - .cra_driver_name = "wp256-generic", -+ .cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY, - .cra_blocksize = WP512_BLOCK_SIZE, - .cra_module = THIS_MODULE, - } -diff -purNx .git BPI-Router-Linux-kernel/Documentation/ABI/testing/sysfs-devices-power BPI-Router-Linux-kernel-6.16.12/Documentation/ABI/testing/sysfs-devices-power ---- BPI-Router-Linux-kernel/Documentation/ABI/testing/sysfs-devices-power 2025-10-22 13:53:23.031330005 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/ABI/testing/sysfs-devices-power 2025-10-22 13:53:56.267170337 -0400 -@@ -56,7 +56,7 @@ Date: January 2009 - Contact: Rafael J. Wysocki - Description: - The /sys/devices/.../async attribute allows the user space to -- enable or diasble the device's suspend and resume callbacks to -+ enable or disable the device's suspend and resume callbacks to - be executed asynchronously (ie. in separate threads, in parallel - with the main suspend/resume thread) during system-wide power - transitions (eg. suspend to RAM, hibernation). -diff -purNx .git BPI-Router-Linux-kernel/Documentation/ABI/testing/sysfs-devices-system-cpu BPI-Router-Linux-kernel-6.16.12/Documentation/ABI/testing/sysfs-devices-system-cpu ---- BPI-Router-Linux-kernel/Documentation/ABI/testing/sysfs-devices-system-cpu 2025-10-22 13:53:23.031330005 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/ABI/testing/sysfs-devices-system-cpu 2025-10-22 13:53:56.267170337 -0400 -@@ -584,7 +584,9 @@ What: /sys/devices/system/cpu/vulnerabi - /sys/devices/system/cpu/vulnerabilities/spectre_v1 - /sys/devices/system/cpu/vulnerabilities/spectre_v2 - /sys/devices/system/cpu/vulnerabilities/srbds -+ /sys/devices/system/cpu/vulnerabilities/tsa - /sys/devices/system/cpu/vulnerabilities/tsx_async_abort -+ /sys/devices/system/cpu/vulnerabilities/vmscape - Date: January 2018 - Contact: Linux kernel mailing list - Description: Information about CPU vulnerabilities -diff -purNx .git BPI-Router-Linux-kernel/Documentation/ABI/testing/sysfs-driver-ufs BPI-Router-Linux-kernel-6.16.12/Documentation/ABI/testing/sysfs-driver-ufs ---- BPI-Router-Linux-kernel/Documentation/ABI/testing/sysfs-driver-ufs 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/ABI/testing/sysfs-driver-ufs 2025-10-22 13:53:56.267170337 -0400 -@@ -711,7 +711,7 @@ Description: This file shows the thin pr - - The file is read only. - --What: /sys/class/scsi_device/*/device/unit_descriptor/physical_memory_resourse_count -+What: /sys/class/scsi_device/*/device/unit_descriptor/physical_memory_resource_count - Date: February 2018 - Contact: Stanislav Nijnikov - Description: This file shows the total physical memory resources. This is -diff -purNx .git BPI-Router-Linux-kernel/Documentation/ABI/testing/sysfs-edac-scrub BPI-Router-Linux-kernel-6.16.12/Documentation/ABI/testing/sysfs-edac-scrub ---- BPI-Router-Linux-kernel/Documentation/ABI/testing/sysfs-edac-scrub 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/ABI/testing/sysfs-edac-scrub 2025-10-22 13:53:56.267170337 -0400 -@@ -49,6 +49,12 @@ Description: - (RO) Supported minimum scrub cycle duration in seconds - by the memory scrubber. - -+ Device-based scrub: returns the minimum scrub cycle -+ supported by the memory device. -+ -+ Region-based scrub: returns the max of minimum scrub cycles -+ supported by individual memory devices that back the region. -+ - What: /sys/bus/edac/devices//scrubX/max_cycle_duration - Date: March 2025 - KernelVersion: 6.15 -@@ -57,6 +63,16 @@ Description: - (RO) Supported maximum scrub cycle duration in seconds - by the memory scrubber. - -+ Device-based scrub: returns the maximum scrub cycle supported -+ by the memory device. -+ -+ Region-based scrub: returns the min of maximum scrub cycles -+ supported by individual memory devices that back the region. -+ -+ If the memory device does not provide maximum scrub cycle -+ information, return the maximum supported value of the scrub -+ cycle field. -+ - What: /sys/bus/edac/devices//scrubX/current_cycle_duration - Date: March 2025 - KernelVersion: 6.15 -diff -purNx .git BPI-Router-Linux-kernel/Documentation/admin-guide/cgroup-v2.rst BPI-Router-Linux-kernel-6.16.12/Documentation/admin-guide/cgroup-v2.rst ---- BPI-Router-Linux-kernel/Documentation/admin-guide/cgroup-v2.rst 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/admin-guide/cgroup-v2.rst 2025-10-22 13:53:56.267170337 -0400 -@@ -1732,12 +1732,6 @@ The following nested keys are defined. - numa_hint_faults (npn) - Number of NUMA hinting faults. - -- numa_task_migrated (npn) -- Number of task migration by NUMA balancing. -- -- numa_task_swapped (npn) -- Number of task swap by NUMA balancing. -- - pgdemote_kswapd - Number of pages demoted by kswapd. - -diff -purNx .git BPI-Router-Linux-kernel/Documentation/admin-guide/cifs/usage.rst BPI-Router-Linux-kernel-6.16.12/Documentation/admin-guide/cifs/usage.rst ---- BPI-Router-Linux-kernel/Documentation/admin-guide/cifs/usage.rst 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/admin-guide/cifs/usage.rst 2025-10-22 13:53:56.267170337 -0400 -@@ -270,6 +270,8 @@ configured for Unix Extensions (and the - illegal Windows/NTFS/SMB characters to a remap range (this mount parameter - is the default for SMB3). This remap (``mapposix``) range is also - compatible with Mac (and "Services for Mac" on some older Windows). -+When POSIX Extensions for SMB 3.1.1 are negotiated, remapping is automatically -+disabled. - - CIFS VFS Mount Options - ====================== -diff -purNx .git BPI-Router-Linux-kernel/Documentation/admin-guide/hw-vuln/index.rst BPI-Router-Linux-kernel-6.16.12/Documentation/admin-guide/hw-vuln/index.rst ---- BPI-Router-Linux-kernel/Documentation/admin-guide/hw-vuln/index.rst 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/admin-guide/hw-vuln/index.rst 2025-10-22 13:53:56.267170337 -0400 -@@ -25,3 +25,4 @@ are configurable at compile, boot or run - rsb - old_microcode - indirect-target-selection -+ vmscape -diff -purNx .git BPI-Router-Linux-kernel/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst BPI-Router-Linux-kernel-6.16.12/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst ---- BPI-Router-Linux-kernel/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst 2025-10-22 13:53:56.267170337 -0400 -@@ -157,9 +157,7 @@ This is achieved by using the otherwise - combination with a microcode update. The microcode clears the affected CPU - buffers when the VERW instruction is executed. - --Kernel reuses the MDS function to invoke the buffer clearing: -- -- mds_clear_cpu_buffers() -+Kernel does the buffer clearing with x86_clear_cpu_buffers(). - - On MDS affected CPUs, the kernel already invokes CPU buffer clear on - kernel/userspace, hypervisor/guest and C-state (idle) transitions. No -diff -purNx .git BPI-Router-Linux-kernel/Documentation/admin-guide/hw-vuln/vmscape.rst BPI-Router-Linux-kernel-6.16.12/Documentation/admin-guide/hw-vuln/vmscape.rst ---- BPI-Router-Linux-kernel/Documentation/admin-guide/hw-vuln/vmscape.rst 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/admin-guide/hw-vuln/vmscape.rst 2025-10-22 13:53:56.267170337 -0400 -@@ -0,0 +1,110 @@ -+.. SPDX-License-Identifier: GPL-2.0 -+ -+VMSCAPE -+======= -+ -+VMSCAPE is a vulnerability that may allow a guest to influence the branch -+prediction in host userspace. It particularly affects hypervisors like QEMU. -+ -+Even if a hypervisor may not have any sensitive data like disk encryption keys, -+guest-userspace may be able to attack the guest-kernel using the hypervisor as -+a confused deputy. -+ -+Affected processors -+------------------- -+ -+The following CPU families are affected by VMSCAPE: -+ -+**Intel processors:** -+ - Skylake generation (Parts without Enhanced-IBRS) -+ - Cascade Lake generation - (Parts affected by ITS guest/host separation) -+ - Alder Lake and newer (Parts affected by BHI) -+ -+Note that, BHI affected parts that use BHB clearing software mitigation e.g. -+Icelake are not vulnerable to VMSCAPE. -+ -+**AMD processors:** -+ - Zen series (families 0x17, 0x19, 0x1a) -+ -+** Hygon processors:** -+ - Family 0x18 -+ -+Mitigation -+---------- -+ -+Conditional IBPB -+---------------- -+ -+Kernel tracks when a CPU has run a potentially malicious guest and issues an -+IBPB before the first exit to userspace after VM-exit. If userspace did not run -+between VM-exit and the next VM-entry, no IBPB is issued. -+ -+Note that the existing userspace mitigation against Spectre-v2 is effective in -+protecting the userspace. They are insufficient to protect the userspace VMMs -+from a malicious guest. This is because Spectre-v2 mitigations are applied at -+context switch time, while the userspace VMM can run after a VM-exit without a -+context switch. -+ -+Vulnerability enumeration and mitigation is not applied inside a guest. This is -+because nested hypervisors should already be deploying IBPB to isolate -+themselves from nested guests. -+ -+SMT considerations -+------------------ -+ -+When Simultaneous Multi-Threading (SMT) is enabled, hypervisors can be -+vulnerable to cross-thread attacks. For complete protection against VMSCAPE -+attacks in SMT environments, STIBP should be enabled. -+ -+The kernel will issue a warning if SMT is enabled without adequate STIBP -+protection. Warning is not issued when: -+ -+- SMT is disabled -+- STIBP is enabled system-wide -+- Intel eIBRS is enabled (which implies STIBP protection) -+ -+System information and options -+------------------------------ -+ -+The sysfs file showing VMSCAPE mitigation status is: -+ -+ /sys/devices/system/cpu/vulnerabilities/vmscape -+ -+The possible values in this file are: -+ -+ * 'Not affected': -+ -+ The processor is not vulnerable to VMSCAPE attacks. -+ -+ * 'Vulnerable': -+ -+ The processor is vulnerable and no mitigation has been applied. -+ -+ * 'Mitigation: IBPB before exit to userspace': -+ -+ Conditional IBPB mitigation is enabled. The kernel tracks when a CPU has -+ run a potentially malicious guest and issues an IBPB before the first -+ exit to userspace after VM-exit. -+ -+ * 'Mitigation: IBPB on VMEXIT': -+ -+ IBPB is issued on every VM-exit. This occurs when other mitigations like -+ RETBLEED or SRSO are already issuing IBPB on VM-exit. -+ -+Mitigation control on the kernel command line -+---------------------------------------------- -+ -+The mitigation can be controlled via the ``vmscape=`` command line parameter: -+ -+ * ``vmscape=off``: -+ -+ Disable the VMSCAPE mitigation. -+ -+ * ``vmscape=ibpb``: -+ -+ Enable conditional IBPB mitigation (default when CONFIG_MITIGATION_VMSCAPE=y). -+ -+ * ``vmscape=force``: -+ -+ Force vulnerability detection and mitigation even on processors that are -+ not known to be affected. -diff -purNx .git BPI-Router-Linux-kernel/Documentation/admin-guide/kernel-parameters.txt BPI-Router-Linux-kernel-6.16.12/Documentation/admin-guide/kernel-parameters.txt ---- BPI-Router-Linux-kernel/Documentation/admin-guide/kernel-parameters.txt 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/admin-guide/kernel-parameters.txt 2025-10-22 13:53:56.267170337 -0400 -@@ -633,6 +633,14 @@ - named mounts. Specifying both "all" and "named" disables - all v1 hierarchies. - -+ cgroup_v1_proc= [KNL] Show also missing controllers in /proc/cgroups -+ Format: { "true" | "false" } -+ /proc/cgroups lists only v1 controllers by default. -+ This compatibility option enables listing also v2 -+ controllers (whose v1 code is not compiled!), so that -+ semi-legacy software can check this file to decide -+ about usage of v2 (sic) controllers. -+ - cgroup_favordynmods= [KNL] Enable or Disable favordynmods. - Format: { "true" | "false" } - Defaults to the value of CONFIG_CGROUP_FAVOR_DYNMODS. -@@ -3766,6 +3774,7 @@ - srbds=off [X86,INTEL] - ssbd=force-off [ARM64] - tsx_async_abort=off [X86] -+ vmscape=off [X86] - - Exceptions: - This does not have any effect on -@@ -7488,6 +7497,19 @@ - having this key zero'ed is acceptable. E.g. in testing - scenarios. - -+ tsa= [X86] Control mitigation for Transient Scheduler -+ Attacks on AMD CPUs. Search the following in your -+ favourite search engine for more details: -+ -+ "Technical guidance for mitigating transient scheduler -+ attacks". -+ -+ off - disable the mitigation -+ on - enable the mitigation (default) -+ user - mitigate only user/kernel transitions -+ vm - mitigate only guest/host transitions -+ -+ - tsc= Disable clocksource stability checks for TSC. - Format: - [x86] reliable: mark tsc clocksource as reliable, this -@@ -7916,6 +7938,16 @@ - vmpoff= [KNL,S390] Perform z/VM CP command after power off. - Format: - -+ vmscape= [X86] Controls mitigation for VMscape attacks. -+ VMscape attacks can leak information from a userspace -+ hypervisor to a guest via speculative side-channels. -+ -+ off - disable the mitigation -+ ibpb - use Indirect Branch Prediction Barrier -+ (IBPB) mitigation (default) -+ force - force vulnerability detection even on -+ unaffected processors -+ - vsyscall= [X86-64,EARLY] - Controls the behavior of vsyscalls (i.e. calls to - fixed addresses of 0xffffffffff600x00 from legacy -diff -purNx .git BPI-Router-Linux-kernel/Documentation/admin-guide/laptops/lg-laptop.rst BPI-Router-Linux-kernel-6.16.12/Documentation/admin-guide/laptops/lg-laptop.rst ---- BPI-Router-Linux-kernel/Documentation/admin-guide/laptops/lg-laptop.rst 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/admin-guide/laptops/lg-laptop.rst 2025-10-22 13:53:56.267170337 -0400 -@@ -48,8 +48,8 @@ This value is reset to 100 when the kern - Fan mode - -------- - --Writing 1/0 to /sys/devices/platform/lg-laptop/fan_mode disables/enables --the fan silent mode. -+Writing 0/1/2 to /sys/devices/platform/lg-laptop/fan_mode sets fan mode to -+Optimal/Silent/Performance respectively. - - - USB charge -diff -purNx .git BPI-Router-Linux-kernel/Documentation/arch/arm64/booting.rst BPI-Router-Linux-kernel-6.16.12/Documentation/arch/arm64/booting.rst ---- BPI-Router-Linux-kernel/Documentation/arch/arm64/booting.rst 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/arch/arm64/booting.rst 2025-10-22 13:53:56.267170337 -0400 -@@ -234,7 +234,7 @@ Before jumping into the kernel, the foll - - - If the kernel is entered at EL1: - -- - ICC.SRE_EL2.Enable (bit 3) must be initialised to 0b1 -+ - ICC_SRE_EL2.Enable (bit 3) must be initialised to 0b1 - - ICC_SRE_EL2.SRE (bit 0) must be initialised to 0b1. - - - The DT or ACPI tables must describe a GICv3 interrupt controller. -diff -purNx .git BPI-Router-Linux-kernel/Documentation/arch/x86/mds.rst BPI-Router-Linux-kernel-6.16.12/Documentation/arch/x86/mds.rst ---- BPI-Router-Linux-kernel/Documentation/arch/x86/mds.rst 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/arch/x86/mds.rst 2025-10-22 13:53:56.267170337 -0400 -@@ -93,7 +93,7 @@ enters a C-state. - - The kernel provides a function to invoke the buffer clearing: - -- mds_clear_cpu_buffers() -+ x86_clear_cpu_buffers() - - Also macro CLEAR_CPU_BUFFERS can be used in ASM late in exit-to-user path. - Other than CFLAGS.ZF, this macro doesn't clobber any registers. -@@ -185,9 +185,9 @@ Mitigation points - idle clearing would be a window dressing exercise and is therefore not - activated. - -- The invocation is controlled by the static key mds_idle_clear which is -- switched depending on the chosen mitigation mode and the SMT state of -- the system. -+ The invocation is controlled by the static key cpu_buf_idle_clear which is -+ switched depending on the chosen mitigation mode and the SMT state of the -+ system. - - The buffer clear is only invoked before entering the C-State to prevent - that stale data from the idling CPU from spilling to the Hyper-Thread -diff -purNx .git BPI-Router-Linux-kernel/Documentation/block/ublk.rst BPI-Router-Linux-kernel-6.16.12/Documentation/block/ublk.rst ---- BPI-Router-Linux-kernel/Documentation/block/ublk.rst 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/block/ublk.rst 2025-10-22 13:53:56.267170337 -0400 -@@ -352,6 +352,83 @@ For reaching best IO performance, ublk s - parameter of `struct ublk_param_segment` with backend for avoiding - unnecessary IO split, which usually hurts io_uring performance. - -+Auto Buffer Registration -+------------------------ -+ -+The ``UBLK_F_AUTO_BUF_REG`` feature automatically handles buffer registration -+and unregistration for I/O requests, which simplifies the buffer management -+process and reduces overhead in the ublk server implementation. -+ -+This is another feature flag for using zero copy, and it is compatible with -+``UBLK_F_SUPPORT_ZERO_COPY``. -+ -+Feature Overview -+~~~~~~~~~~~~~~~~ -+ -+This feature automatically registers request buffers to the io_uring context -+before delivering I/O commands to the ublk server and unregisters them when -+completing I/O commands. This eliminates the need for manual buffer -+registration/unregistration via ``UBLK_IO_REGISTER_IO_BUF`` and -+``UBLK_IO_UNREGISTER_IO_BUF`` commands, then IO handling in ublk server -+can avoid dependency on the two uring_cmd operations. -+ -+IOs can't be issued concurrently to io_uring if there is any dependency -+among these IOs. So this way not only simplifies ublk server implementation, -+but also makes concurrent IO handling becomes possible by removing the -+dependency on buffer registration & unregistration commands. -+ -+Usage Requirements -+~~~~~~~~~~~~~~~~~~ -+ -+1. The ublk server must create a sparse buffer table on the same ``io_ring_ctx`` -+ used for ``UBLK_IO_FETCH_REQ`` and ``UBLK_IO_COMMIT_AND_FETCH_REQ``. If -+ uring_cmd is issued on a different ``io_ring_ctx``, manual buffer -+ unregistration is required. -+ -+2. Buffer registration data must be passed via uring_cmd's ``sqe->addr`` with the -+ following structure:: -+ -+ struct ublk_auto_buf_reg { -+ __u16 index; /* Buffer index for registration */ -+ __u8 flags; /* Registration flags */ -+ __u8 reserved0; /* Reserved for future use */ -+ __u32 reserved1; /* Reserved for future use */ -+ }; -+ -+ ublk_auto_buf_reg_to_sqe_addr() is for converting the above structure into -+ ``sqe->addr``. -+ -+3. All reserved fields in ``ublk_auto_buf_reg`` must be zeroed. -+ -+4. Optional flags can be passed via ``ublk_auto_buf_reg.flags``. -+ -+Fallback Behavior -+~~~~~~~~~~~~~~~~~ -+ -+If auto buffer registration fails: -+ -+1. When ``UBLK_AUTO_BUF_REG_FALLBACK`` is enabled: -+ -+ - The uring_cmd is completed -+ - ``UBLK_IO_F_NEED_REG_BUF`` is set in ``ublksrv_io_desc.op_flags`` -+ - The ublk server must manually deal with the failure, such as, register -+ the buffer manually, or using user copy feature for retrieving the data -+ for handling ublk IO -+ -+2. If fallback is not enabled: -+ -+ - The ublk I/O request fails silently -+ - The uring_cmd won't be completed -+ -+Limitations -+~~~~~~~~~~~ -+ -+- Requires same ``io_ring_ctx`` for all operations -+- May require manual buffer management in fallback cases -+- io_ring_ctx buffer table has a max size of 16K, which may not be enough -+ in case that too many ublk devices are handled by this single io_ring_ctx -+ and each one has very large queue depth -+ - References - ========== - -diff -purNx .git BPI-Router-Linux-kernel/Documentation/bpf/map_hash.rst BPI-Router-Linux-kernel-6.16.12/Documentation/bpf/map_hash.rst ---- BPI-Router-Linux-kernel/Documentation/bpf/map_hash.rst 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/bpf/map_hash.rst 2025-10-22 13:53:56.267170337 -0400 -@@ -233,10 +233,16 @@ attempts in order to enforce the LRU pro - other CPUs involved in the following operation attempts: - - - Attempt to use CPU-local state to batch operations --- Attempt to fetch free nodes from global lists -+- Attempt to fetch ``target_free`` free nodes from global lists - - Attempt to pull any node from a global list and remove it from the hashmap - - Attempt to pull any node from any CPU's list and remove it from the hashmap - -+The number of nodes to borrow from the global list in a batch, ``target_free``, -+depends on the size of the map. Larger batch size reduces lock contention, but -+may also exhaust the global structure. The value is computed at map init to -+avoid exhaustion, by limiting aggregate reservation by all CPUs to half the map -+size. With a minimum of a single element and maximum budget of 128 at a time. -+ - This algorithm is described visually in the following diagram. See the - description in commit 3a08c2fd7634 ("bpf: LRU List") for a full explanation of - the corresponding operations: -diff -purNx .git BPI-Router-Linux-kernel/Documentation/bpf/map_lru_hash_update.dot BPI-Router-Linux-kernel-6.16.12/Documentation/bpf/map_lru_hash_update.dot ---- BPI-Router-Linux-kernel/Documentation/bpf/map_lru_hash_update.dot 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/bpf/map_lru_hash_update.dot 2025-10-22 13:53:56.267170337 -0400 -@@ -35,18 +35,18 @@ digraph { - fn_bpf_lru_list_pop_free_to_local [shape=rectangle,fillcolor=2, - label="Flush local pending, - Rotate Global list, move -- LOCAL_FREE_TARGET -+ target_free - from global -> local"] - // Also corresponds to: - // fn__local_list_flush() - // fn_bpf_lru_list_rotate() - fn___bpf_lru_node_move_to_free[shape=diamond,fillcolor=2, -- label="Able to free\nLOCAL_FREE_TARGET\nnodes?"] -+ label="Able to free\ntarget_free\nnodes?"] - - fn___bpf_lru_list_shrink_inactive [shape=rectangle,fillcolor=3, - label="Shrink inactive list - up to remaining -- LOCAL_FREE_TARGET -+ target_free - (global LRU -> local)"] - fn___bpf_lru_list_shrink [shape=diamond,fillcolor=2, - label="> 0 entries in\nlocal free list?"] -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/clock/mediatek,mt8188-clock.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/clock/mediatek,mt8188-clock.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/clock/mediatek,mt8188-clock.yaml 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/clock/mediatek,mt8188-clock.yaml 2025-10-22 13:53:56.267170337 -0400 -@@ -52,6 +52,9 @@ properties: - '#clock-cells': - const: 1 - -+ '#reset-cells': -+ const: 1 -+ - required: - - compatible - - reg -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/display/bridge/ti,sn65dsi83.yaml 2025-10-22 13:53:56.267170337 -0400 -@@ -118,15 +118,11 @@ $defs: - ti,lvds-vod-swing-clock-microvolt: - description: LVDS diferential output voltage for clock - lanes in microvolts. -- $ref: /schemas/types.yaml#/definitions/uint32-array -- minItems: 2 - maxItems: 2 - - ti,lvds-vod-swing-data-microvolt: - description: LVDS diferential output voltage for data - lanes in microvolts. -- $ref: /schemas/types.yaml#/definitions/uint32-array -- minItems: 2 - maxItems: 2 - - allOf: -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/display/msm/qcom,mdp5.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/display/msm/qcom,mdp5.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/display/msm/qcom,mdp5.yaml 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/display/msm/qcom,mdp5.yaml 2025-10-22 13:53:56.267170337 -0400 -@@ -60,7 +60,6 @@ properties: - - const: bus - - const: core - - const: vsync -- - const: lut - - const: tbu - - const: tbu_rt - # MSM8996 has additional iommu clock -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/display/rockchip/rockchip-vop2.yaml 2025-10-22 13:53:56.267170337 -0400 -@@ -64,10 +64,10 @@ properties: - - description: Pixel clock for video port 0. - - description: Pixel clock for video port 1. - - description: Pixel clock for video port 2. -- - description: Pixel clock for video port 3. -- - description: Peripheral(vop grf/dsi) clock. -- - description: Alternative pixel clock provided by HDMI0 PHY PLL. -- - description: Alternative pixel clock provided by HDMI1 PHY PLL. -+ - {} -+ - {} -+ - {} -+ - {} - - clock-names: - minItems: 5 -@@ -77,10 +77,10 @@ properties: - - const: dclk_vp0 - - const: dclk_vp1 - - const: dclk_vp2 -- - const: dclk_vp3 -- - const: pclk_vop -- - const: pll_hdmiphy0 -- - const: pll_hdmiphy1 -+ - {} -+ - {} -+ - {} -+ - {} - - rockchip,grf: - $ref: /schemas/types.yaml#/definitions/phandle -@@ -175,10 +175,24 @@ allOf: - then: - properties: - clocks: -- maxItems: 5 -+ minItems: 5 -+ items: -+ - {} -+ - {} -+ - {} -+ - {} -+ - {} -+ - description: Alternative pixel clock provided by HDMI PHY PLL. - - clock-names: -- maxItems: 5 -+ minItems: 5 -+ items: -+ - {} -+ - {} -+ - {} -+ - {} -+ - {} -+ - const: pll_hdmiphy0 - - interrupts: - minItems: 4 -@@ -208,11 +222,29 @@ allOf: - properties: - clocks: - minItems: 7 -- maxItems: 9 -+ items: -+ - {} -+ - {} -+ - {} -+ - {} -+ - {} -+ - description: Pixel clock for video port 3. -+ - description: Peripheral(vop grf/dsi) clock. -+ - description: Alternative pixel clock provided by HDMI0 PHY PLL. -+ - description: Alternative pixel clock provided by HDMI1 PHY PLL. - - clock-names: - minItems: 7 -- maxItems: 9 -+ items: -+ - {} -+ - {} -+ - {} -+ - {} -+ - {} -+ - const: dclk_vp3 -+ - const: pclk_vop -+ - const: pll_hdmiphy0 -+ - const: pll_hdmiphy1 - - interrupts: - maxItems: 1 -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dpu.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dpu.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dpu.yaml 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dpu.yaml 2025-10-22 13:53:56.267170337 -0400 -@@ -25,7 +25,7 @@ properties: - maxItems: 1 - - clocks: -- minItems: 2 -+ maxItems: 2 - - clock-names: - items: -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dsi-host.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dsi-host.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dsi-host.yaml 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/display/sprd/sprd,sharkl3-dsi-host.yaml 2025-10-22 13:53:56.267170337 -0400 -@@ -20,7 +20,7 @@ properties: - maxItems: 2 - - clocks: -- minItems: 1 -+ maxItems: 1 - - clock-names: - items: -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/i2c/nvidia,tegra20-i2c.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/i2c/nvidia,tegra20-i2c.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/i2c/nvidia,tegra20-i2c.yaml 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/i2c/nvidia,tegra20-i2c.yaml 2025-10-22 13:53:56.267170337 -0400 -@@ -97,7 +97,10 @@ properties: - - resets: - items: -- - description: module reset -+ - description: -+ Module reset. This property is optional for controllers in Tegra194, -+ Tegra234 etc where an internal software reset is available as an -+ alternative. - - reset-names: - items: -@@ -116,6 +119,13 @@ properties: - - const: rx - - const: tx - -+required: -+ - compatible -+ - reg -+ - interrupts -+ - clocks -+ - clock-names -+ - allOf: - - $ref: /schemas/i2c/i2c-controller.yaml - - if: -@@ -169,6 +179,18 @@ allOf: - properties: - power-domains: false - -+ - if: -+ not: -+ properties: -+ compatible: -+ contains: -+ enum: -+ - nvidia,tegra194-i2c -+ then: -+ required: -+ - resets -+ - reset-names -+ - unevaluatedProperties: false - - examples: -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/i2c/realtek,rtl9301-i2c.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/i2c/realtek,rtl9301-i2c.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/i2c/realtek,rtl9301-i2c.yaml 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/i2c/realtek,rtl9301-i2c.yaml 2025-10-22 13:53:56.267170337 -0400 -@@ -26,7 +26,8 @@ properties: - - const: realtek,rtl9301-i2c - - reg: -- description: Register offset and size this I2C controller. -+ items: -+ - description: Register offset and size this I2C controller. - - "#address-cells": - const: 1 -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -223,12 +223,6 @@ allOf: - - required: - - pwms - -- - oneOf: -- - required: -- - interrupts -- - required: -- - io-backends -- - - if: - properties: - compatible: -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.yaml 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -21,7 +21,7 @@ properties: - vlogic-supply: true - - interrupts: -- minItems: 1 -+ maxItems: 1 - description: - Interrupt mapping for the trigger interrupt from the internal oscillator. - -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/input/elan,ekth6915.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/input/elan,ekth6915.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/input/elan,ekth6915.yaml 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/input/elan,ekth6915.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -4,14 +4,14 @@ - $id: http://devicetree.org/schemas/input/elan,ekth6915.yaml# - $schema: http://devicetree.org/meta-schemas/core.yaml# - --title: Elan eKTH6915 touchscreen controller -+title: Elan I2C-HID touchscreen controllers - - maintainers: - - Douglas Anderson - - description: -- Supports the Elan eKTH6915 touchscreen controller. -- This touchscreen controller uses the i2c-hid protocol with a reset GPIO. -+ Supports the Elan eKTH6915 and other I2C-HID touchscreen controllers. -+ These touchscreen controller use the i2c-hid protocol with a reset GPIO. - - allOf: - - $ref: /schemas/input/touchscreen/touchscreen.yaml# -@@ -23,12 +23,14 @@ properties: - - enum: - - elan,ekth5015m - - const: elan,ekth6915 -+ - items: -+ - const: elan,ekth8d18 -+ - const: elan,ekth6a12nay - - enum: - - elan,ekth6915 - - elan,ekth6a12nay - -- reg: -- const: 0x10 -+ reg: true - - interrupts: - maxItems: 1 -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-csi.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-csi.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-csi.yaml 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-csi.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -110,7 +110,7 @@ examples: - reg = <0x01cb4000 0x1000>; - interrupts = ; - clocks = <&ccu CLK_BUS_CSI>, -- <&ccu CLK_CSI1_SCLK>, -+ <&ccu CLK_CSI_SCLK>, - <&ccu CLK_DRAM_CSI>; - clock-names = "bus", - "mod", -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-isp.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-isp.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-isp.yaml 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-isp.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -79,7 +79,7 @@ examples: - reg = <0x01cb8000 0x1000>; - interrupts = ; - clocks = <&ccu CLK_BUS_CSI>, -- <&ccu CLK_CSI1_SCLK>, -+ <&ccu CLK_CSI_SCLK>, - <&ccu CLK_DRAM_CSI>; - clock-names = "bus", "mod", "ram"; - resets = <&ccu RST_BUS_CSI>; -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-mipi-csi2.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-mipi-csi2.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-mipi-csi2.yaml 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-mipi-csi2.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -103,7 +103,7 @@ examples: - reg = <0x01cb1000 0x1000>; - interrupts = ; - clocks = <&ccu CLK_BUS_CSI>, -- <&ccu CLK_CSI1_SCLK>; -+ <&ccu CLK_CSI_SCLK>; - clock-names = "bus", "mod"; - resets = <&ccu RST_BUS_CSI>; - -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -23,7 +23,7 @@ properties: - - allwinner,sun20i-d1-emac - - allwinner,sun50i-h6-emac - - allwinner,sun50i-h616-emac0 -- - allwinner,sun55i-a523-emac0 -+ - allwinner,sun55i-a523-gmac0 - - const: allwinner,sun50i-a64-emac - - reg: -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/net/sophgo,sg2044-dwmac.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/net/sophgo,sg2044-dwmac.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/net/sophgo,sg2044-dwmac.yaml 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/net/sophgo,sg2044-dwmac.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -80,6 +80,8 @@ examples: - interrupt-parent = <&intc>; - interrupts = <296 IRQ_TYPE_LEVEL_HIGH>; - interrupt-names = "macirq"; -+ phy-handle = <&phy0>; -+ phy-mode = "rgmii-id"; - resets = <&rst 30>; - reset-names = "stmmaceth"; - snps,multicast-filter-bins = <0>; -@@ -91,7 +93,6 @@ examples: - snps,mtl-rx-config = <&gmac0_mtl_rx_setup>; - snps,mtl-tx-config = <&gmac0_mtl_tx_setup>; - snps,axi-config = <&gmac0_stmmac_axi_setup>; -- status = "disabled"; - - gmac0_mtl_rx_setup: rx-queues-config { - snps,rx-queues-to-use = <8>; -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-aon-pinctrl.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-aon-pinctrl.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-aon-pinctrl.yaml 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-aon-pinctrl.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -15,7 +15,7 @@ description: | - Some peripherals such as PWM have their I/O go through the 4 "GPIOs". - - maintainers: -- - Jianlong Huang -+ - Hal Feng - - properties: - compatible: -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-sys-pinctrl.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-sys-pinctrl.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-sys-pinctrl.yaml 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-sys-pinctrl.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -18,7 +18,7 @@ description: | - any GPIO can be set up to be controlled by any of the peripherals. - - maintainers: -- - Jianlong Huang -+ - Hal Feng - - properties: - compatible: -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/pmem/pmem-region.txt BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/pmem/pmem-region.txt ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/pmem/pmem-region.txt 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/pmem/pmem-region.txt 1969-12-31 19:00:00.000000000 -0500 -@@ -1,65 +0,0 @@ --Device-tree bindings for persistent memory regions ------------------------------------------------------- -- --Persistent memory refers to a class of memory devices that are: -- -- a) Usable as main system memory (i.e. cacheable), and -- b) Retain their contents across power failure. -- --Given b) it is best to think of persistent memory as a kind of memory mapped --storage device. To ensure data integrity the operating system needs to manage --persistent regions separately to the normal memory pool. To aid with that this --binding provides a standardised interface for discovering where persistent --memory regions exist inside the physical address space. -- --Bindings for the region nodes: ------------------------------- -- --Required properties: -- - compatible = "pmem-region" -- -- - reg = ; -- The reg property should specify an address range that is -- translatable to a system physical address range. This address -- range should be mappable as normal system memory would be -- (i.e cacheable). -- -- If the reg property contains multiple address ranges -- each address range will be treated as though it was specified -- in a separate device node. Having multiple address ranges in a -- node implies no special relationship between the two ranges. -- --Optional properties: -- - Any relevant NUMA associativity properties for the target platform. -- -- - volatile; This property indicates that this region is actually -- backed by non-persistent memory. This lets the OS know that it -- may skip the cache flushes required to ensure data is made -- persistent after a write. -- -- If this property is absent then the OS must assume that the region -- is backed by non-volatile memory. -- --Examples: ---------------------- -- -- /* -- * This node specifies one 4KB region spanning from -- * 0x5000 to 0x5fff that is backed by non-volatile memory. -- */ -- pmem@5000 { -- compatible = "pmem-region"; -- reg = <0x00005000 0x00001000>; -- }; -- -- /* -- * This node specifies two 4KB regions that are backed by -- * volatile (normal) memory. -- */ -- pmem@6000 { -- compatible = "pmem-region"; -- reg = < 0x00006000 0x00001000 -- 0x00008000 0x00001000 >; -- volatile; -- }; -- -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/pmem/pmem-region.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/pmem/pmem-region.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/pmem/pmem-region.yaml 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/pmem/pmem-region.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -0,0 +1,48 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/pmem-region.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+maintainers: -+ - Oliver O'Halloran -+ -+title: Persistent Memory Regions -+ -+description: | -+ Persistent memory refers to a class of memory devices that are: -+ -+ a) Usable as main system memory (i.e. cacheable), and -+ b) Retain their contents across power failure. -+ -+ Given b) it is best to think of persistent memory as a kind of memory mapped -+ storage device. To ensure data integrity the operating system needs to manage -+ persistent regions separately to the normal memory pool. To aid with that this -+ binding provides a standardised interface for discovering where persistent -+ memory regions exist inside the physical address space. -+ -+properties: -+ compatible: -+ const: pmem-region -+ -+ reg: -+ maxItems: 1 -+ -+ volatile: -+ description: -+ Indicates the region is volatile (non-persistent) and the OS can skip -+ cache flushes for writes -+ type: boolean -+ -+required: -+ - compatible -+ - reg -+ -+additionalProperties: false -+ -+examples: -+ - | -+ pmem@5000 { -+ compatible = "pmem-region"; -+ reg = <0x00005000 0x00001000>; -+ }; -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/serial/8250.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/serial/8250.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/serial/8250.yaml 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/serial/8250.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -45,9 +45,48 @@ allOf: - - ns16550 - - ns16550a - then: -- anyOf: -+ oneOf: - - required: [ clock-frequency ] - - required: [ clocks ] -+ - if: -+ properties: -+ compatible: -+ contains: -+ const: nxp,lpc1850-uart -+ then: -+ properties: -+ clock-names: -+ items: -+ - const: uartclk -+ - const: reg -+ else: -+ properties: -+ clock-names: -+ items: -+ - const: core -+ - const: bus -+ - if: -+ properties: -+ compatible: -+ contains: -+ enum: -+ - spacemit,k1-uart -+ - nxp,lpc1850-uart -+ then: -+ required: -+ - clocks -+ - clock-names -+ properties: -+ clocks: -+ minItems: 2 -+ clock-names: -+ minItems: 2 -+ else: -+ properties: -+ clocks: -+ maxItems: 1 -+ clock-names: -+ maxItems: 1 - - properties: - compatible: -@@ -142,9 +181,22 @@ properties: - - clock-names: - minItems: 1 -- items: -- - const: core -- - const: bus -+ maxItems: 2 -+ oneOf: -+ - items: -+ - const: core -+ - const: bus -+ - items: -+ - const: uartclk -+ - const: reg -+ -+ dmas: -+ minItems: 1 -+ maxItems: 4 -+ -+ dma-names: -+ minItems: 1 -+ maxItems: 4 - - resets: - maxItems: 1 -@@ -233,25 +285,6 @@ required: - - reg - - interrupts - --if: -- properties: -- compatible: -- contains: -- const: spacemit,k1-uart --then: -- required: [clock-names] -- properties: -- clocks: -- minItems: 2 -- clock-names: -- minItems: 2 --else: -- properties: -- clocks: -- maxItems: 1 -- clock-names: -- maxItems: 1 -- - unevaluatedProperties: false - - examples: -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/serial/altera_jtaguart.txt BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/serial/altera_jtaguart.txt ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/serial/altera_jtaguart.txt 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/serial/altera_jtaguart.txt 1969-12-31 19:00:00.000000000 -0500 -@@ -1,5 +0,0 @@ --Altera JTAG UART -- --Required properties: --- compatible : should be "ALTR,juart-1.0" --- compatible : should be "altr,juart-1.0" -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/serial/altera_uart.txt BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/serial/altera_uart.txt ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/serial/altera_uart.txt 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/serial/altera_uart.txt 1969-12-31 19:00:00.000000000 -0500 -@@ -1,8 +0,0 @@ --Altera UART -- --Required properties: --- compatible : should be "ALTR,uart-1.0" --- compatible : should be "altr,uart-1.0" -- --Optional properties: --- clock-frequency : frequency of the clock input to the UART -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/serial/altr,juart-1.0.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/serial/altr,juart-1.0.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/serial/altr,juart-1.0.yaml 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/serial/altr,juart-1.0.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -0,0 +1,19 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/serial/altr,juart-1.0.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Altera JTAG UART -+ -+maintainers: -+ - Dinh Nguyen -+ -+properties: -+ compatible: -+ const: altr,juart-1.0 -+ -+required: -+ - compatible -+ -+additionalProperties: false -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/serial/altr,uart-1.0.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/serial/altr,uart-1.0.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/serial/altr,uart-1.0.yaml 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/serial/altr,uart-1.0.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -0,0 +1,25 @@ -+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -+%YAML 1.2 -+--- -+$id: http://devicetree.org/schemas/serial/altr,uart-1.0.yaml# -+$schema: http://devicetree.org/meta-schemas/core.yaml# -+ -+title: Altera UART -+ -+maintainers: -+ - Dinh Nguyen -+ -+allOf: -+ - $ref: /schemas/serial/serial.yaml# -+ -+properties: -+ compatible: -+ const: altr,uart-1.0 -+ -+ clock-frequency: -+ description: Frequency of the clock input to the UART. -+ -+required: -+ - compatible -+ -+unevaluatedProperties: false -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/serial/brcm,bcm7271-uart.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/serial/brcm,bcm7271-uart.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/serial/brcm,bcm7271-uart.yaml 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/serial/brcm,bcm7271-uart.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -41,7 +41,7 @@ properties: - - const: dma_intr2 - - clocks: -- minItems: 1 -+ maxItems: 1 - - clock-names: - const: sw_baud -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/soc/fsl/fsl,ls1028a-reset.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/soc/fsl/fsl,ls1028a-reset.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/soc/fsl/fsl,ls1028a-reset.yaml 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/soc/fsl/fsl,ls1028a-reset.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -1,7 +1,7 @@ - # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) - %YAML 1.2 - --- --$id: http://devicetree.org/schemas//soc/fsl/fsl,ls1028a-reset.yaml# -+$id: http://devicetree.org/schemas/soc/fsl/fsl,ls1028a-reset.yaml# - $schema: http://devicetree.org/meta-schemas/core.yaml# - - title: Freescale Layerscape Reset Registers Module -diff -purNx .git BPI-Router-Linux-kernel/Documentation/devicetree/bindings/ufs/mediatek,ufs.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/ufs/mediatek,ufs.yaml ---- BPI-Router-Linux-kernel/Documentation/devicetree/bindings/ufs/mediatek,ufs.yaml 2025-10-22 13:53:23.035329987 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/devicetree/bindings/ufs/mediatek,ufs.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -33,6 +33,10 @@ properties: - - vcc-supply: true - -+ mediatek,ufs-disable-mcq: -+ $ref: /schemas/types.yaml#/definitions/flag -+ description: The mask to disable MCQ (Multi-Circular Queue) for UFS host. -+ - required: - - compatible - - clocks -diff -purNx .git BPI-Router-Linux-kernel/Documentation/filesystems/f2fs.rst BPI-Router-Linux-kernel-6.16.12/Documentation/filesystems/f2fs.rst ---- BPI-Router-Linux-kernel/Documentation/filesystems/f2fs.rst 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/filesystems/f2fs.rst 2025-10-22 13:53:56.271170318 -0400 -@@ -238,9 +238,9 @@ usrjquota= Appoint specified file - grpjquota= information can be properly updated during recovery flow, - prjjquota= : must be in root directory; - jqfmt= : [vfsold,vfsv0,vfsv1]. --offusrjquota Turn off user journalled quota. --offgrpjquota Turn off group journalled quota. --offprjjquota Turn off project journalled quota. -+usrjquota= Turn off user journalled quota. -+grpjquota= Turn off group journalled quota. -+prjjquota= Turn off project journalled quota. - quota Enable plain user disk quota accounting. - noquota Disable all plain disk quota option. - alloc_mode=%s Adjust block allocation policy, which supports "reuse" -diff -purNx .git BPI-Router-Linux-kernel/Documentation/filesystems/fscrypt.rst BPI-Router-Linux-kernel-6.16.12/Documentation/filesystems/fscrypt.rst ---- BPI-Router-Linux-kernel/Documentation/filesystems/fscrypt.rst 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/filesystems/fscrypt.rst 2025-10-22 13:53:56.271170318 -0400 -@@ -147,9 +147,8 @@ However, these ioctls have some limitati - were wiped. To partially solve this, you can add init_on_free=1 to - your kernel command line. However, this has a performance cost. - --- Secret keys might still exist in CPU registers, in crypto -- accelerator hardware (if used by the crypto API to implement any of -- the algorithms), or in other places not explicitly considered here. -+- Secret keys might still exist in CPU registers or in other places -+ not explicitly considered here. - - Full system compromise - ~~~~~~~~~~~~~~~~~~~~~~ -@@ -406,9 +405,12 @@ the work is done by XChaCha12, which is - acceleration is unavailable. For more information about Adiantum, see - `the Adiantum paper `_. - --The (AES-128-CBC-ESSIV, AES-128-CBC-CTS) pair exists only to support --systems whose only form of AES acceleration is an off-CPU crypto --accelerator such as CAAM or CESA that does not support XTS. -+The (AES-128-CBC-ESSIV, AES-128-CBC-CTS) pair was added to try to -+provide a more efficient option for systems that lack AES instructions -+in the CPU but do have a non-inline crypto engine such as CAAM or CESA -+that supports AES-CBC (and not AES-XTS). This is deprecated. It has -+been shown that just doing AES on the CPU is actually faster. -+Moreover, Adiantum is faster still and is recommended on such systems. - - The remaining mode pairs are the "national pride ciphers": - -@@ -1326,22 +1328,13 @@ this by validating all top-level encrypt - Inline encryption support - ========================= - --By default, fscrypt uses the kernel crypto API for all cryptographic --operations (other than HKDF, which fscrypt partially implements --itself). The kernel crypto API supports hardware crypto accelerators, --but only ones that work in the traditional way where all inputs and --outputs (e.g. plaintexts and ciphertexts) are in memory. fscrypt can --take advantage of such hardware, but the traditional acceleration --model isn't particularly efficient and fscrypt hasn't been optimized --for it. -- --Instead, many newer systems (especially mobile SoCs) have *inline --encryption hardware* that can encrypt/decrypt data while it is on its --way to/from the storage device. Linux supports inline encryption --through a set of extensions to the block layer called *blk-crypto*. --blk-crypto allows filesystems to attach encryption contexts to bios --(I/O requests) to specify how the data will be encrypted or decrypted --in-line. For more information about blk-crypto, see -+Many newer systems (especially mobile SoCs) have *inline encryption -+hardware* that can encrypt/decrypt data while it is on its way to/from -+the storage device. Linux supports inline encryption through a set of -+extensions to the block layer called *blk-crypto*. blk-crypto allows -+filesystems to attach encryption contexts to bios (I/O requests) to -+specify how the data will be encrypted or decrypted in-line. For more -+information about blk-crypto, see - :ref:`Documentation/block/inline-encryption.rst `. - - On supported filesystems (currently ext4 and f2fs), fscrypt can use -diff -purNx .git BPI-Router-Linux-kernel/Documentation/filesystems/porting.rst BPI-Router-Linux-kernel-6.16.12/Documentation/filesystems/porting.rst ---- BPI-Router-Linux-kernel/Documentation/filesystems/porting.rst 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/filesystems/porting.rst 2025-10-22 13:53:56.271170318 -0400 -@@ -1249,3 +1249,12 @@ Using try_lookup_noperm() will require l - - Calling conventions for ->d_automount() have changed; we should *not* grab - an extra reference to new mount - it should be returned with refcount 1. -+ -+--- -+ -+collect_mounts()/drop_collected_mounts()/iterate_mounts() are gone now. -+Replacement is collect_paths()/drop_collected_path(), with no special -+iterator needed. Instead of a cloned mount tree, the new interface returns -+an array of struct path, one for each mount collect_mounts() would've -+created. These struct path point to locations in the caller's namespace -+that would be roots of the cloned mounts. -diff -purNx .git BPI-Router-Linux-kernel/Documentation/filesystems/proc.rst BPI-Router-Linux-kernel-6.16.12/Documentation/filesystems/proc.rst ---- BPI-Router-Linux-kernel/Documentation/filesystems/proc.rst 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/filesystems/proc.rst 2025-10-22 13:53:56.271170318 -0400 -@@ -584,7 +584,6 @@ encoded manner. The codes are the follow - ms may share - gd stack segment growns down - pf pure PFN range -- dw disabled write to the mapped file - lo pages are locked in memory - io memory mapped I/O area - sr sequential read advise provided -@@ -607,8 +606,11 @@ encoded manner. The codes are the follow - mt arm64 MTE allocation tags are enabled - um userfaultfd missing tracking - uw userfaultfd wr-protect tracking -+ ui userfaultfd minor fault - ss shadow/guarded control stack page - sl sealed -+ lf lock on fault pages -+ dp always lazily freeable mapping - == ======================================= - - Note that there is no guarantee that every flag and associated mnemonic will -diff -purNx .git BPI-Router-Linux-kernel/Documentation/firmware-guide/acpi/i2c-muxes.rst BPI-Router-Linux-kernel-6.16.12/Documentation/firmware-guide/acpi/i2c-muxes.rst ---- BPI-Router-Linux-kernel/Documentation/firmware-guide/acpi/i2c-muxes.rst 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/firmware-guide/acpi/i2c-muxes.rst 2025-10-22 13:53:56.271170318 -0400 -@@ -14,7 +14,7 @@ Consider this topology:: - | | | 0x70 |--CH01--> i2c client B (0x50) - +------+ +------+ - --which corresponds to the following ASL:: -+which corresponds to the following ASL (in the scope of \_SB):: - - Device (SMB1) - { -@@ -24,7 +24,7 @@ which corresponds to the following ASL:: - Name (_HID, ...) - Name (_CRS, ResourceTemplate () { - I2cSerialBus (0x70, ControllerInitiated, I2C_SPEED, -- AddressingMode7Bit, "^SMB1", 0x00, -+ AddressingMode7Bit, "\\_SB.SMB1", 0x00, - ResourceConsumer,,) - } - -@@ -37,7 +37,7 @@ which corresponds to the following ASL:: - Name (_HID, ...) - Name (_CRS, ResourceTemplate () { - I2cSerialBus (0x50, ControllerInitiated, I2C_SPEED, -- AddressingMode7Bit, "^CH00", 0x00, -+ AddressingMode7Bit, "\\_SB.SMB1.CH00", 0x00, - ResourceConsumer,,) - } - } -@@ -52,7 +52,7 @@ which corresponds to the following ASL:: - Name (_HID, ...) - Name (_CRS, ResourceTemplate () { - I2cSerialBus (0x50, ControllerInitiated, I2C_SPEED, -- AddressingMode7Bit, "^CH01", 0x00, -+ AddressingMode7Bit, "\\_SB.SMB1.CH01", 0x00, - ResourceConsumer,,) - } - } -diff -purNx .git BPI-Router-Linux-kernel/Documentation/gpu/nouveau.rst BPI-Router-Linux-kernel-6.16.12/Documentation/gpu/nouveau.rst ---- BPI-Router-Linux-kernel/Documentation/gpu/nouveau.rst 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/gpu/nouveau.rst 2025-10-22 13:53:56.271170318 -0400 -@@ -25,7 +25,7 @@ providing a consistent API to upper laye - GSP Support - ------------------------ - --.. kernel-doc:: drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c -+.. kernel-doc:: drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c - :doc: GSP message queue element - - .. kernel-doc:: drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h -diff -purNx .git BPI-Router-Linux-kernel/Documentation/hwmon/ina238.rst BPI-Router-Linux-kernel-6.16.12/Documentation/hwmon/ina238.rst ---- BPI-Router-Linux-kernel/Documentation/hwmon/ina238.rst 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/hwmon/ina238.rst 2025-10-22 13:53:56.271170318 -0400 -@@ -65,7 +65,7 @@ Additional sysfs entries for sq52206 - ------------------------------------ - - ======================= ======================================================= --energy1_input Energy measurement (mJ) -+energy1_input Energy measurement (uJ) - - power1_input_highest Peak Power (uW) - ======================= ======================================================= -diff -purNx .git BPI-Router-Linux-kernel/Documentation/netlink/genetlink-legacy.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/genetlink-legacy.yaml ---- BPI-Router-Linux-kernel/Documentation/netlink/genetlink-legacy.yaml 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/genetlink-legacy.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -6,6 +6,9 @@ $schema: https://json-schema.org/draft-0 - - # Common defines - $defs: -+ name: -+ type: string -+ pattern: ^[0-9a-z-]+$ - uint: - type: integer - minimum: 0 -@@ -76,7 +79,7 @@ properties: - additionalProperties: False - properties: - name: -- type: string -+ $ref: '#/$defs/name' - header: - description: For C-compatible languages, header which already defines this value. - type: string -@@ -103,7 +106,7 @@ properties: - additionalProperties: False - properties: - name: -- type: string -+ $ref: '#/$defs/name' - value: - type: integer - doc: -@@ -132,7 +135,7 @@ properties: - additionalProperties: False - properties: - name: -- type: string -+ $ref: '#/$defs/name' - type: - description: The netlink attribute type - enum: [ u8, u16, u32, u64, s8, s16, s32, s64, string, binary ] -@@ -169,7 +172,7 @@ properties: - name: - description: | - Name used when referring to this space in other definitions, not used outside of the spec. -- type: string -+ $ref: '#/$defs/name' - name-prefix: - description: | - Prefix for the C enum name of the attributes. Default family[name]-set[name]-a- -@@ -206,7 +209,7 @@ properties: - additionalProperties: False - properties: - name: -- type: string -+ $ref: '#/$defs/name' - type: &attr-type - description: The netlink attribute type - enum: [ unused, pad, flag, binary, bitfield32, -@@ -348,7 +351,7 @@ properties: - properties: - name: - description: Name of the operation, also defining its C enum value in uAPI. -- type: string -+ $ref: '#/$defs/name' - doc: - description: Documentation for the command. - type: string -diff -purNx .git BPI-Router-Linux-kernel/Documentation/netlink/genetlink.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/genetlink.yaml ---- BPI-Router-Linux-kernel/Documentation/netlink/genetlink.yaml 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/genetlink.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -6,6 +6,9 @@ $schema: https://json-schema.org/draft-0 - - # Common defines - $defs: -+ name: -+ type: string -+ pattern: ^[0-9a-z-]+$ - uint: - type: integer - minimum: 0 -@@ -29,7 +32,7 @@ additionalProperties: False - properties: - name: - description: Name of the genetlink family. -- type: string -+ $ref: '#/$defs/name' - doc: - type: string - protocol: -@@ -48,7 +51,7 @@ properties: - additionalProperties: False - properties: - name: -- type: string -+ $ref: '#/$defs/name' - header: - description: For C-compatible languages, header which already defines this value. - type: string -@@ -75,7 +78,7 @@ properties: - additionalProperties: False - properties: - name: -- type: string -+ $ref: '#/$defs/name' - value: - type: integer - doc: -@@ -96,7 +99,7 @@ properties: - name: - description: | - Name used when referring to this space in other definitions, not used outside of the spec. -- type: string -+ $ref: '#/$defs/name' - name-prefix: - description: | - Prefix for the C enum name of the attributes. Default family[name]-set[name]-a- -@@ -121,7 +124,7 @@ properties: - additionalProperties: False - properties: - name: -- type: string -+ $ref: '#/$defs/name' - type: &attr-type - enum: [ unused, pad, flag, binary, - uint, sint, u8, u16, u32, u64, s8, s16, s32, s64, -@@ -243,7 +246,7 @@ properties: - properties: - name: - description: Name of the operation, also defining its C enum value in uAPI. -- type: string -+ $ref: '#/$defs/name' - doc: - description: Documentation for the command. - type: string -@@ -327,7 +330,7 @@ properties: - name: - description: | - The name for the group, used to form the define and the value of the define. -- type: string -+ $ref: '#/$defs/name' - flags: *cmd_flags - - kernel-family: -diff -purNx .git BPI-Router-Linux-kernel/Documentation/netlink/netlink-raw.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/netlink-raw.yaml ---- BPI-Router-Linux-kernel/Documentation/netlink/netlink-raw.yaml 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/netlink-raw.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -6,6 +6,12 @@ $schema: https://json-schema.org/draft-0 - - # Common defines - $defs: -+ name: -+ type: string -+ pattern: ^[0-9a-z-]+$ -+ name-cap: -+ type: string -+ pattern: ^[0-9a-zA-Z-]+$ - uint: - type: integer - minimum: 0 -@@ -71,7 +77,7 @@ properties: - additionalProperties: False - properties: - name: -- type: string -+ $ref: '#/$defs/name' - header: - description: For C-compatible languages, header which already defines this value. - type: string -@@ -98,7 +104,7 @@ properties: - additionalProperties: False - properties: - name: -- type: string -+ $ref: '#/$defs/name' - value: - type: integer - doc: -@@ -124,7 +130,7 @@ properties: - additionalProperties: False - properties: - name: -- type: string -+ $ref: '#/$defs/name-cap' - type: - description: | - The netlink attribute type. Members of type 'binary' or 'pad' -@@ -183,7 +189,7 @@ properties: - name: - description: | - Name used when referring to this space in other definitions, not used outside of the spec. -- type: string -+ $ref: '#/$defs/name' - name-prefix: - description: | - Prefix for the C enum name of the attributes. Default family[name]-set[name]-a- -@@ -220,7 +226,7 @@ properties: - additionalProperties: False - properties: - name: -- type: string -+ $ref: '#/$defs/name' - type: &attr-type - description: The netlink attribute type - enum: [ unused, pad, flag, binary, bitfield32, -@@ -408,7 +414,7 @@ properties: - properties: - name: - description: Name of the operation, also defining its C enum value in uAPI. -- type: string -+ $ref: '#/$defs/name' - doc: - description: Documentation for the command. - type: string -diff -purNx .git BPI-Router-Linux-kernel/Documentation/netlink/specs/conntrack.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/specs/conntrack.yaml ---- BPI-Router-Linux-kernel/Documentation/netlink/specs/conntrack.yaml 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/specs/conntrack.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -575,8 +575,8 @@ operations: - - nat-dst - - timeout - - mark -- - counter-orig -- - counter-reply -+ - counters-orig -+ - counters-reply - - use - - id - - nat-dst -@@ -591,7 +591,6 @@ operations: - request: - value: 0x101 - attributes: -- - nfgen-family - - mark - - filter - - status -@@ -608,8 +607,8 @@ operations: - - nat-dst - - timeout - - mark -- - counter-orig -- - counter-reply -+ - counters-orig -+ - counters-reply - - use - - id - - nat-dst -diff -purNx .git BPI-Router-Linux-kernel/Documentation/netlink/specs/devlink.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/specs/devlink.yaml ---- BPI-Router-Linux-kernel/Documentation/netlink/specs/devlink.yaml 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/specs/devlink.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -38,15 +38,15 @@ definitions: - - - name: dsa - - -- name: pci_pf -+ name: pci-pf - - -- name: pci_vf -+ name: pci-vf - - - name: virtual - - - name: unused - - -- name: pci_sf -+ name: pci-sf - - - type: enum - name: port-fn-state -@@ -220,7 +220,7 @@ definitions: - - - name: flag - - -- name: nul_string -+ name: nul-string - value: 10 - - - name: binary -diff -purNx .git BPI-Router-Linux-kernel/Documentation/netlink/specs/dpll.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/specs/dpll.yaml ---- BPI-Router-Linux-kernel/Documentation/netlink/specs/dpll.yaml 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/specs/dpll.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -188,7 +188,7 @@ definitions: - value: 10000 - - - type: const -- name: pin-frequency-77_5-khz -+ name: pin-frequency-77-5-khz - value: 77500 - - - type: const -diff -purNx .git BPI-Router-Linux-kernel/Documentation/netlink/specs/ethtool.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/specs/ethtool.yaml ---- BPI-Router-Linux-kernel/Documentation/netlink/specs/ethtool.yaml 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/specs/ethtool.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -7,6 +7,9 @@ protocol: genetlink-legacy - doc: Partial family for Ethtool Netlink. - uapi-header: linux/ethtool_netlink_generated.h - -+c-family-name: ethtool-genl-name -+c-version-name: ethtool-genl-version -+ - definitions: - - - name: udp-tunnel-type -@@ -45,7 +48,7 @@ definitions: - name: started - doc: The firmware flashing process has started. - - -- name: in_progress -+ name: in-progress - doc: The firmware flashing process is in progress. - - - name: completed -@@ -1419,7 +1422,7 @@ attribute-sets: - name: hkey - type: binary - - -- name: input_xfrm -+ name: input-xfrm - type: u32 - - - name: start-context -@@ -2106,14 +2109,14 @@ operations: - request: - attributes: - - header -- reply: -- attributes: -- - header - - offset - - length - - page - - bank - - i2c-address -+ reply: -+ attributes: -+ - header - - data - dump: *module-eeprom-get-op - - -@@ -2235,7 +2238,7 @@ operations: - - hfunc - - indir - - hkey -- - input_xfrm -+ - input-xfrm - dump: - request: - attributes: -diff -purNx .git BPI-Router-Linux-kernel/Documentation/netlink/specs/fou.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/specs/fou.yaml ---- BPI-Router-Linux-kernel/Documentation/netlink/specs/fou.yaml 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/specs/fou.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -15,7 +15,7 @@ kernel-policy: global - definitions: - - - type: enum -- name: encap_type -+ name: encap-type - name-prefix: fou-encap- - enum-name: - entries: [ unspec, direct, gue ] -@@ -43,26 +43,26 @@ attribute-sets: - name: type - type: u8 - - -- name: remcsum_nopartial -+ name: remcsum-nopartial - type: flag - - -- name: local_v4 -+ name: local-v4 - type: u32 - - -- name: local_v6 -+ name: local-v6 - type: binary - checks: - min-len: 16 - - -- name: peer_v4 -+ name: peer-v4 - type: u32 - - -- name: peer_v6 -+ name: peer-v6 - type: binary - checks: - min-len: 16 - - -- name: peer_port -+ name: peer-port - type: u16 - byte-order: big-endian - - -@@ -90,12 +90,12 @@ operations: - - port - - ipproto - - type -- - remcsum_nopartial -- - local_v4 -- - peer_v4 -- - local_v6 -- - peer_v6 -- - peer_port -+ - remcsum-nopartial -+ - local-v4 -+ - peer-v4 -+ - local-v6 -+ - peer-v6 -+ - peer-port - - ifindex - - - -@@ -112,11 +112,11 @@ operations: - - af - - ifindex - - port -- - peer_port -- - local_v4 -- - peer_v4 -- - local_v6 -- - peer_v6 -+ - peer-port -+ - local-v4 -+ - peer-v4 -+ - local-v6 -+ - peer-v6 - - - - name: get -diff -purNx .git BPI-Router-Linux-kernel/Documentation/netlink/specs/mptcp_pm.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/specs/mptcp_pm.yaml ---- BPI-Router-Linux-kernel/Documentation/netlink/specs/mptcp_pm.yaml 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/specs/mptcp_pm.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -28,13 +28,13 @@ definitions: - traffic-patterns it can take a long time until the - MPTCP_EVENT_ESTABLISHED is sent. - Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6, sport, -- dport, server-side. -+ dport, server-side, [flags]. - - - name: established - doc: >- - A MPTCP connection is established (can start new subflows). - Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6, sport, -- dport, server-side. -+ dport, server-side, [flags]. - - - name: closed - doc: >- -@@ -57,21 +57,21 @@ definitions: - doc: >- - A new subflow has been established. 'error' should not be set. - Attributes: token, family, loc_id, rem_id, saddr4 | saddr6, daddr4 | -- daddr6, sport, dport, backup, if_idx [, error]. -+ daddr6, sport, dport, backup, if-idx [, error]. - - - name: sub-closed - doc: >- - A subflow has been closed. An error (copy of sk_err) could be set if an - error has been detected for this subflow. - Attributes: token, family, loc_id, rem_id, saddr4 | saddr6, daddr4 | -- daddr6, sport, dport, backup, if_idx [, error]. -+ daddr6, sport, dport, backup, if-idx [, error]. - - - name: sub-priority - value: 13 - doc: >- - The priority of a subflow has changed. 'error' should not be set. - Attributes: token, family, loc_id, rem_id, saddr4 | saddr6, daddr4 | -- daddr6, sport, dport, backup, if_idx [, error]. -+ daddr6, sport, dport, backup, if-idx [, error]. - - - name: listener-created - value: 15 -@@ -255,8 +255,8 @@ attribute-sets: - name: timeout - type: u32 - - -- name: if_idx -- type: u32 -+ name: if-idx -+ type: s32 - - - name: reset-reason - type: u32 -diff -purNx .git BPI-Router-Linux-kernel/Documentation/netlink/specs/nfsd.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/specs/nfsd.yaml ---- BPI-Router-Linux-kernel/Documentation/netlink/specs/nfsd.yaml 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/specs/nfsd.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -27,7 +27,7 @@ attribute-sets: - name: proc - type: u32 - - -- name: service_time -+ name: service-time - type: s64 - - - name: pad -@@ -139,7 +139,7 @@ operations: - - prog - - version - - proc -- - service_time -+ - service-time - - saddr4 - - daddr4 - - saddr6 -diff -purNx .git BPI-Router-Linux-kernel/Documentation/netlink/specs/ovpn.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/specs/ovpn.yaml ---- BPI-Router-Linux-kernel/Documentation/netlink/specs/ovpn.yaml 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/specs/ovpn.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -161,6 +161,66 @@ attribute-sets: - type: uint - doc: Number of packets transmitted at the transport level - - -+ name: peer-new-input -+ subset-of: peer -+ attributes: -+ - -+ name: id -+ - -+ name: remote-ipv4 -+ - -+ name: remote-ipv6 -+ - -+ name: remote-ipv6-scope-id -+ - -+ name: remote-port -+ - -+ name: socket -+ - -+ name: vpn-ipv4 -+ - -+ name: vpn-ipv6 -+ - -+ name: local-ipv4 -+ - -+ name: local-ipv6 -+ - -+ name: keepalive-interval -+ - -+ name: keepalive-timeout -+ - -+ name: peer-set-input -+ subset-of: peer -+ attributes: -+ - -+ name: id -+ - -+ name: remote-ipv4 -+ - -+ name: remote-ipv6 -+ - -+ name: remote-ipv6-scope-id -+ - -+ name: remote-port -+ - -+ name: vpn-ipv4 -+ - -+ name: vpn-ipv6 -+ - -+ name: local-ipv4 -+ - -+ name: local-ipv6 -+ - -+ name: keepalive-interval -+ - -+ name: keepalive-timeout -+ - -+ name: peer-del-input -+ subset-of: peer -+ attributes: -+ - -+ name: id -+ - - name: keyconf - attributes: - - -@@ -216,6 +276,33 @@ attribute-sets: - obtain the actual cipher IV - checks: - exact-len: nonce-tail-size -+ -+ - -+ name: keyconf-get -+ subset-of: keyconf -+ attributes: -+ - -+ name: peer-id -+ - -+ name: slot -+ - -+ name: key-id -+ - -+ name: cipher-alg -+ - -+ name: keyconf-swap-input -+ subset-of: keyconf -+ attributes: -+ - -+ name: peer-id -+ - -+ name: keyconf-del-input -+ subset-of: keyconf -+ attributes: -+ - -+ name: peer-id -+ - -+ name: slot - - - name: ovpn - attributes: -@@ -235,12 +322,66 @@ attribute-sets: - type: nest - doc: Peer specific cipher configuration - nested-attributes: keyconf -+ - -+ name: ovpn-peer-new-input -+ subset-of: ovpn -+ attributes: -+ - -+ name: ifindex -+ - -+ name: peer -+ nested-attributes: peer-new-input -+ - -+ name: ovpn-peer-set-input -+ subset-of: ovpn -+ attributes: -+ - -+ name: ifindex -+ - -+ name: peer -+ nested-attributes: peer-set-input -+ - -+ name: ovpn-peer-del-input -+ subset-of: ovpn -+ attributes: -+ - -+ name: ifindex -+ - -+ name: peer -+ nested-attributes: peer-del-input -+ - -+ name: ovpn-keyconf-get -+ subset-of: ovpn -+ attributes: -+ - -+ name: ifindex -+ - -+ name: keyconf -+ nested-attributes: keyconf-get -+ - -+ name: ovpn-keyconf-swap-input -+ subset-of: ovpn -+ attributes: -+ - -+ name: ifindex -+ - -+ name: keyconf -+ nested-attributes: keyconf-swap-input -+ - -+ name: ovpn-keyconf-del-input -+ subset-of: ovpn -+ attributes: -+ - -+ name: ifindex -+ - -+ name: keyconf -+ nested-attributes: keyconf-del-input - - operations: - list: - - - name: peer-new -- attribute-set: ovpn -+ attribute-set: ovpn-peer-new-input - flags: [ admin-perm ] - doc: Add a remote peer - do: -@@ -252,7 +393,7 @@ operations: - - peer - - - name: peer-set -- attribute-set: ovpn -+ attribute-set: ovpn-peer-set-input - flags: [ admin-perm ] - doc: modify a remote peer - do: -@@ -286,7 +427,7 @@ operations: - - peer - - - name: peer-del -- attribute-set: ovpn -+ attribute-set: ovpn-peer-del-input - flags: [ admin-perm ] - doc: Delete existing remote peer - do: -@@ -316,7 +457,7 @@ operations: - - keyconf - - - name: key-get -- attribute-set: ovpn -+ attribute-set: ovpn-keyconf-get - flags: [ admin-perm ] - doc: Retrieve non-sensitive data about peer key and cipher - do: -@@ -331,7 +472,7 @@ operations: - - keyconf - - - name: key-swap -- attribute-set: ovpn -+ attribute-set: ovpn-keyconf-swap-input - flags: [ admin-perm ] - doc: Swap primary and secondary session keys for a specific peer - do: -@@ -350,7 +491,7 @@ operations: - mcgrp: peers - - - name: key-del -- attribute-set: ovpn -+ attribute-set: ovpn-keyconf-del-input - flags: [ admin-perm ] - doc: Delete cipher key for a specific peer - do: -diff -purNx .git BPI-Router-Linux-kernel/Documentation/netlink/specs/ovs_flow.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/specs/ovs_flow.yaml ---- BPI-Router-Linux-kernel/Documentation/netlink/specs/ovs_flow.yaml 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/specs/ovs_flow.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -216,7 +216,7 @@ definitions: - type: struct - members: - - -- name: nd_target -+ name: nd-target - type: binary - len: 16 - byte-order: big-endian -@@ -258,12 +258,12 @@ definitions: - type: struct - members: - - -- name: vlan_tpid -+ name: vlan-tpid - type: u16 - byte-order: big-endian - doc: Tag protocol identifier (TPID) to push. - - -- name: vlan_tci -+ name: vlan-tci - type: u16 - byte-order: big-endian - doc: Tag control identifier (TCI) to push. -diff -purNx .git BPI-Router-Linux-kernel/Documentation/netlink/specs/rt-link.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/specs/rt-link.yaml ---- BPI-Router-Linux-kernel/Documentation/netlink/specs/rt-link.yaml 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/specs/rt-link.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -603,7 +603,7 @@ definitions: - name: optmask - type: u32 - - -- name: if_stats_msg -+ name: if-stats-msg - type: struct - members: - - -@@ -2486,7 +2486,7 @@ operations: - name: getstats - doc: Get / dump link stats. - attribute-set: stats-attrs -- fixed-header: if_stats_msg -+ fixed-header: if-stats-msg - do: - request: - value: 94 -diff -purNx .git BPI-Router-Linux-kernel/Documentation/netlink/specs/tc.yaml BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/specs/tc.yaml ---- BPI-Router-Linux-kernel/Documentation/netlink/specs/tc.yaml 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/netlink/specs/tc.yaml 2025-10-22 13:53:56.271170318 -0400 -@@ -232,7 +232,7 @@ definitions: - type: u8 - doc: log(P_max / (qth-max - qth-min)) - - -- name: Scell_log -+ name: Scell-log - type: u8 - doc: cell size for idle damping - - -@@ -253,7 +253,7 @@ definitions: - name: DPs - type: u32 - - -- name: def_DP -+ name: def-DP - type: u32 - - - name: grio -diff -purNx .git BPI-Router-Linux-kernel/Documentation/networking/can.rst BPI-Router-Linux-kernel-6.16.12/Documentation/networking/can.rst ---- BPI-Router-Linux-kernel/Documentation/networking/can.rst 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/networking/can.rst 2025-10-22 13:53:56.271170318 -0400 -@@ -742,7 +742,7 @@ The broadcast manager sends responses to - struct timeval ival1, ival2; /* count and subsequent interval */ - canid_t can_id; /* unique can_id for task */ - __u32 nframes; /* number of can_frames following */ -- struct can_frame frames[0]; -+ struct can_frame frames[]; - }; - - The aligned payload 'frames' uses the same basic CAN frame structure defined -diff -purNx .git BPI-Router-Linux-kernel/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst BPI-Router-Linux-kernel-6.16.12/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst ---- BPI-Router-Linux-kernel/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst 2025-10-22 13:53:56.271170318 -0400 -@@ -66,7 +66,7 @@ Admin Function driver - As mentioned above RVU PF0 is called the admin function (AF), this driver - supports resource provisioning and configuration of functional blocks. - Doesn't handle any I/O. It sets up few basic stuff but most of the --funcionality is achieved via configuration requests from PFs and VFs. -+functionality is achieved via configuration requests from PFs and VFs. - - PF/VFs communicates with AF via a shared memory region (mailbox). Upon - receiving requests AF does resource provisioning and other HW configuration. -diff -purNx .git BPI-Router-Linux-kernel/Documentation/networking/mptcp.rst BPI-Router-Linux-kernel-6.16.12/Documentation/networking/mptcp.rst ---- BPI-Router-Linux-kernel/Documentation/networking/mptcp.rst 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/networking/mptcp.rst 2025-10-22 13:53:56.271170318 -0400 -@@ -60,10 +60,10 @@ address announcements. Typically, it is - and the server side that announces additional addresses via the ``ADD_ADDR`` and - ``REMOVE_ADDR`` options. - --Path managers are controlled by the ``net.mptcp.pm_type`` sysctl knob -- see --mptcp-sysctl.rst. There are two types: the in-kernel one (type ``0``) where the --same rules are applied for all the connections (see: ``ip mptcp``) ; and the --userspace one (type ``1``), controlled by a userspace daemon (i.e. `mptcpd -+Path managers are controlled by the ``net.mptcp.path_manager`` sysctl knob -- -+see mptcp-sysctl.rst. There are two types: the in-kernel one (``kernel``) where -+the same rules are applied for all the connections (see: ``ip mptcp``) ; and the -+userspace one (``userspace``), controlled by a userspace daemon (i.e. `mptcpd - `_) where different rules can be applied for each - connection. The path managers can be controlled via a Netlink API; see - netlink_spec/mptcp_pm.rst. -diff -purNx .git BPI-Router-Linux-kernel/Documentation/networking/mptcp-sysctl.rst BPI-Router-Linux-kernel-6.16.12/Documentation/networking/mptcp-sysctl.rst ---- BPI-Router-Linux-kernel/Documentation/networking/mptcp-sysctl.rst 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/networking/mptcp-sysctl.rst 2025-10-22 13:53:56.271170318 -0400 -@@ -12,6 +12,8 @@ add_addr_timeout - INTEGER (seconds) - resent to an MPTCP peer that has not acknowledged a previous - ADD_ADDR message. - -+ Do not retransmit if set to 0. -+ - The default value matches TCP_RTO_MAX. This is a per-namespace - sysctl. - -diff -purNx .git BPI-Router-Linux-kernel/Documentation/networking/tls.rst BPI-Router-Linux-kernel-6.16.12/Documentation/networking/tls.rst ---- BPI-Router-Linux-kernel/Documentation/networking/tls.rst 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/networking/tls.rst 2025-10-22 13:53:56.271170318 -0400 -@@ -16,11 +16,13 @@ User interface - Creating a TLS connection - ------------------------- - --First create a new TCP socket and set the TLS ULP. -+First create a new TCP socket and once the connection is established set the -+TLS ULP. - - .. code-block:: c - - sock = socket(AF_INET, SOCK_STREAM, 0); -+ connect(sock, addr, addrlen); - setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls")); - - Setting the TLS ULP allows us to set/get TLS socket options. Currently -diff -purNx .git BPI-Router-Linux-kernel/Documentation/process/embargoed-hardware-issues.rst BPI-Router-Linux-kernel-6.16.12/Documentation/process/embargoed-hardware-issues.rst ---- BPI-Router-Linux-kernel/Documentation/process/embargoed-hardware-issues.rst 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/process/embargoed-hardware-issues.rst 2025-10-22 13:53:56.271170318 -0400 -@@ -290,6 +290,7 @@ an involved disclosed party. The current - AMD Tom Lendacky - Ampere Darren Hart - ARM Catalin Marinas -+ IBM Power Madhavan Srinivasan - IBM Z Christian Borntraeger - Intel Tony Luck - Qualcomm Trilok Soni -diff -purNx .git BPI-Router-Linux-kernel/Documentation/process/maintainer-netdev.rst BPI-Router-Linux-kernel-6.16.12/Documentation/process/maintainer-netdev.rst ---- BPI-Router-Linux-kernel/Documentation/process/maintainer-netdev.rst 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/process/maintainer-netdev.rst 2025-10-22 13:53:56.271170318 -0400 -@@ -312,7 +312,7 @@ Posting as one thread is discouraged bec - (as of patchwork 2.2.2). - - Co-posting selftests ---------------------- -+~~~~~~~~~~~~~~~~~~~~ - - Selftests should be part of the same series as the code changes. - Specifically for fixes both code change and related test should go into -diff -purNx .git BPI-Router-Linux-kernel/Documentation/sound/codecs/cs35l56.rst BPI-Router-Linux-kernel-6.16.12/Documentation/sound/codecs/cs35l56.rst ---- BPI-Router-Linux-kernel/Documentation/sound/codecs/cs35l56.rst 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/sound/codecs/cs35l56.rst 2025-10-22 13:53:56.271170318 -0400 -@@ -1,8 +1,8 @@ - .. SPDX-License-Identifier: GPL-2.0-only - --===================================================================== --Audio drivers for Cirrus Logic CS35L54/56/57 Boosted Smart Amplifiers --===================================================================== -+======================================================================== -+Audio drivers for Cirrus Logic CS35L54/56/57/63 Boosted Smart Amplifiers -+======================================================================== - :Copyright: 2025 Cirrus Logic, Inc. and - Cirrus Logic International Semiconductor Ltd. - -@@ -13,11 +13,11 @@ Summary - - The high-level summary of this document is: - --**If you have a laptop that uses CS35L54/56/57 amplifiers but audio is not -+**If you have a laptop that uses CS35L54/56/57/63 amplifiers but audio is not - working, DO NOT ATTEMPT TO USE FIRMWARE AND SETTINGS FROM ANOTHER LAPTOP, - EVEN IF THAT LAPTOP SEEMS SIMILAR.** - --The CS35L54/56/57 amplifiers must be correctly configured for the power -+The CS35L54/56/57/63 amplifiers must be correctly configured for the power - supply voltage, speaker impedance, maximum speaker voltage/current, and - other external hardware connections. - -@@ -34,6 +34,7 @@ The cs35l56 drivers support: - * CS35L54 - * CS35L56 - * CS35L57 -+* CS35L63 - - There are two drivers in the kernel - -@@ -104,6 +105,13 @@ In this example the SSID is 10280c63. - - The format of the firmware file names is: - -+SoundWire (except CS35L56 Rev B0): -+ cs35lxx-b0-dsp1-misc-SSID[-spkidX]-l?u? -+ -+SoundWire CS35L56 Rev B0: -+ cs35lxx-b0-dsp1-misc-SSID[-spkidX]-ampN -+ -+Non-SoundWire (HDA and I2S): - cs35lxx-b0-dsp1-misc-SSID[-spkidX]-ampN - - Where: -@@ -111,12 +119,18 @@ Where: - * cs35lxx-b0 is the amplifier model and silicon revision. This information - is logged by the driver during initialization. - * SSID is the 8-digit hexadecimal SSID value. -+ * l?u? is the physical address on the SoundWire bus of the amp this -+ file applies to. - * ampN is the amplifier number (for example amp1). This is the same as - the prefix on the ALSA control names except that it is always lower-case - in the file name. - * spkidX is an optional part, used for laptops that have firmware - configurations for different makes and models of internal speakers. - -+The CS35L56 Rev B0 continues to use the old filename scheme because a -+large number of firmware files have already been published with these -+names. -+ - Sound Open Firmware and ALSA topology files - ------------------------------------------- - -diff -purNx .git BPI-Router-Linux-kernel/Documentation/sphinx/kernel_abi.py BPI-Router-Linux-kernel-6.16.12/Documentation/sphinx/kernel_abi.py ---- BPI-Router-Linux-kernel/Documentation/sphinx/kernel_abi.py 2025-10-22 13:53:23.039329968 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/sphinx/kernel_abi.py 2025-10-22 13:53:56.271170318 -0400 -@@ -146,8 +146,10 @@ class KernelCmd(Directive): - n += 1 - - if f != old_f: -- # Add the file to Sphinx build dependencies -- env.note_dependency(os.path.abspath(f)) -+ # Add the file to Sphinx build dependencies if the file exists -+ fname = os.path.join(srctree, f) -+ if os.path.isfile(fname): -+ env.note_dependency(fname) - - old_f = f - -diff -purNx .git BPI-Router-Linux-kernel/Documentation/virt/kvm/api.rst BPI-Router-Linux-kernel-6.16.12/Documentation/virt/kvm/api.rst ---- BPI-Router-Linux-kernel/Documentation/virt/kvm/api.rst 2025-10-22 13:53:23.043329948 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/virt/kvm/api.rst 2025-10-22 13:53:56.275170298 -0400 -@@ -2008,6 +2008,13 @@ If the KVM_CAP_VM_TSC_CONTROL capability - be used as a vm ioctl to set the initial tsc frequency of subsequently - created vCPUs. - -+For TSC protected Confidential Computing (CoCo) VMs where TSC frequency -+is configured once at VM scope and remains unchanged during VM's -+lifetime, the vm ioctl should be used to configure the TSC frequency -+and the vcpu ioctl is not supported. -+ -+Example of such CoCo VMs: TDX guests. -+ - 4.56 KVM_GET_TSC_KHZ - -------------------- - -@@ -6645,7 +6652,8 @@ to the byte array. - .. note:: - - For KVM_EXIT_IO, KVM_EXIT_MMIO, KVM_EXIT_OSI, KVM_EXIT_PAPR, KVM_EXIT_XEN, -- KVM_EXIT_EPR, KVM_EXIT_X86_RDMSR and KVM_EXIT_X86_WRMSR the corresponding -+ KVM_EXIT_EPR, KVM_EXIT_HYPERCALL, KVM_EXIT_TDX, -+ KVM_EXIT_X86_RDMSR and KVM_EXIT_X86_WRMSR the corresponding - operations are complete (and guest state is consistent) only after userspace - has re-entered the kernel with KVM_RUN. The kernel side will first finish - incomplete operations and then check for pending signals. -@@ -7176,6 +7184,69 @@ The valid value for 'flags' is: - - :: - -+ /* KVM_EXIT_TDX */ -+ struct { -+ __u64 flags; -+ __u64 nr; -+ union { -+ struct { -+ u64 ret; -+ u64 data[5]; -+ } unknown; -+ struct { -+ u64 ret; -+ u64 gpa; -+ u64 size; -+ } get_quote; -+ struct { -+ u64 ret; -+ u64 leaf; -+ u64 r11, r12, r13, r14; -+ } get_tdvmcall_info; -+ struct { -+ u64 ret; -+ u64 vector; -+ } setup_event_notify; -+ }; -+ } tdx; -+ -+Process a TDVMCALL from the guest. KVM forwards select TDVMCALL based -+on the Guest-Hypervisor Communication Interface (GHCI) specification; -+KVM bridges these requests to the userspace VMM with minimal changes, -+placing the inputs in the union and copying them back to the guest -+on re-entry. -+ -+Flags are currently always zero, whereas ``nr`` contains the TDVMCALL -+number from register R11. The remaining field of the union provide the -+inputs and outputs of the TDVMCALL. Currently the following values of -+``nr`` are defined: -+ -+ * ``TDVMCALL_GET_QUOTE``: the guest has requested to generate a TD-Quote -+ signed by a service hosting TD-Quoting Enclave operating on the host. -+ Parameters and return value are in the ``get_quote`` field of the union. -+ The ``gpa`` field and ``size`` specify the guest physical address -+ (without the shared bit set) and the size of a shared-memory buffer, in -+ which the TDX guest passes a TD Report. The ``ret`` field represents -+ the return value of the GetQuote request. When the request has been -+ queued successfully, the TDX guest can poll the status field in the -+ shared-memory area to check whether the Quote generation is completed or -+ not. When completed, the generated Quote is returned via the same buffer. -+ -+ * ``TDVMCALL_GET_TD_VM_CALL_INFO``: the guest has requested the support -+ status of TDVMCALLs. The output values for the given leaf should be -+ placed in fields from ``r11`` to ``r14`` of the ``get_tdvmcall_info`` -+ field of the union. -+ -+ * ``TDVMCALL_SETUP_EVENT_NOTIFY_INTERRUPT``: the guest has requested to -+ set up a notification interrupt for vector ``vector``. -+ -+KVM may add support for more values in the future that may cause a userspace -+exit, even without calls to ``KVM_ENABLE_CAP`` or similar. In this case, -+it will enter with output fields already valid; in the common case, the -+``unknown.ret`` field of the union will be ``TDVMCALL_STATUS_SUBFUNC_UNSUPPORTED``. -+Userspace need not do anything if it does not wish to support a TDVMCALL. -+:: -+ - /* Fix the size of the union. */ - char padding[256]; - }; -diff -purNx .git BPI-Router-Linux-kernel/Documentation/virt/kvm/review-checklist.rst BPI-Router-Linux-kernel-6.16.12/Documentation/virt/kvm/review-checklist.rst ---- BPI-Router-Linux-kernel/Documentation/virt/kvm/review-checklist.rst 2025-10-22 13:53:23.043329948 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/virt/kvm/review-checklist.rst 2025-10-22 13:53:56.275170298 -0400 -@@ -7,7 +7,7 @@ Review checklist for kvm patches - 1. The patch must follow Documentation/process/coding-style.rst and - Documentation/process/submitting-patches.rst. - --2. Patches should be against kvm.git master branch. -+2. Patches should be against kvm.git master or next branches. - - 3. If the patch introduces or modifies a new userspace API: - - the API must be documented in Documentation/virt/kvm/api.rst -@@ -18,10 +18,10 @@ Review checklist for kvm patches - 5. New features must default to off (userspace should explicitly request them). - Performance improvements can and should default to on. - --6. New cpu features should be exposed via KVM_GET_SUPPORTED_CPUID2 -+6. New cpu features should be exposed via KVM_GET_SUPPORTED_CPUID2, -+ or its equivalent for non-x86 architectures - --7. Emulator changes should be accompanied by unit tests for qemu-kvm.git -- kvm/test directory. -+7. The feature should be testable (see below). - - 8. Changes should be vendor neutral when possible. Changes to common code - are better than duplicating changes to vendor code. -@@ -36,6 +36,87 @@ Review checklist for kvm patches - 11. New guest visible features must either be documented in a hardware manual - or be accompanied by documentation. - --12. Features must be robust against reset and kexec - for example, shared -- host/guest memory must be unshared to prevent the host from writing to -- guest memory that the guest has not reserved for this purpose. -+Testing of KVM code -+------------------- -+ -+All features contributed to KVM, and in many cases bugfixes too, should be -+accompanied by some kind of tests and/or enablement in open source guests -+and VMMs. KVM is covered by multiple test suites: -+ -+*Selftests* -+ These are low level tests that allow granular testing of kernel APIs. -+ This includes API failure scenarios, invoking APIs after specific -+ guest instructions, and testing multiple calls to ``KVM_CREATE_VM`` -+ within a single test. They are included in the kernel tree at -+ ``tools/testing/selftests/kvm``. -+ -+``kvm-unit-tests`` -+ A collection of small guests that test CPU and emulated device features -+ from a guest's perspective. They run under QEMU or ``kvmtool``, and -+ are generally not KVM-specific: they can be run with any accelerator -+ that QEMU support or even on bare metal, making it possible to compare -+ behavior across hypervisors and processor families. -+ -+Functional test suites -+ Various sets of functional tests exist, such as QEMU's ``tests/functional`` -+ suite and `avocado-vt `__. -+ These typically involve running a full operating system in a virtual -+ machine. -+ -+The best testing approach depends on the feature's complexity and -+operation. Here are some examples and guidelines: -+ -+New instructions (no new registers or APIs) -+ The corresponding CPU features (if applicable) should be made available -+ in QEMU. If the instructions require emulation support or other code in -+ KVM, it is worth adding coverage to ``kvm-unit-tests`` or selftests; -+ the latter can be a better choice if the instructions relate to an API -+ that already has good selftest coverage. -+ -+New hardware features (new registers, no new APIs) -+ These should be tested via ``kvm-unit-tests``; this more or less implies -+ supporting them in QEMU and/or ``kvmtool``. In some cases selftests -+ can be used instead, similar to the previous case, or specifically to -+ test corner cases in guest state save/restore. -+ -+Bug fixes and performance improvements -+ These usually do not introduce new APIs, but it's worth sharing -+ any benchmarks and tests that will validate your contribution, -+ ideally in the form of regression tests. Tests and benchmarks -+ can be included in either ``kvm-unit-tests`` or selftests, depending -+ on the specifics of your change. Selftests are especially useful for -+ regression tests because they are included directly in Linux's tree. -+ -+Large scale internal changes -+ While it's difficult to provide a single policy, you should ensure that -+ the changed code is covered by either ``kvm-unit-tests`` or selftests. -+ In some cases the affected code is run for any guests and functional -+ tests suffice. Explain your testing process in the cover letter, -+ as that can help identify gaps in existing test suites. -+ -+New APIs -+ It is important to demonstrate your use case. This can be as simple as -+ explaining that the feature is already in use on bare metal, or it can be -+ a proof-of-concept implementation in userspace. The latter need not be -+ open source, though that is of course preferrable for easier testing. -+ Selftests should test corner cases of the APIs, and should also cover -+ basic host and guest operation if no open source VMM uses the feature. -+ -+Bigger features, usually spanning host and guest -+ These should be supported by Linux guests, with limited exceptions for -+ Hyper-V features that are testable on Windows guests. It is strongly -+ suggested that the feature be usable with an open source host VMM, such -+ as at least one of QEMU or crosvm, and guest firmware. Selftests should -+ test at least API error cases. Guest operation can be covered by -+ either selftests of ``kvm-unit-tests`` (this is especially important for -+ paravirtualized and Windows-only features). Strong selftest coverage -+ can also be a replacement for implementation in an open source VMM, -+ but this is generally not recommended. -+ -+Following the above suggestions for testing in selftests and -+``kvm-unit-tests`` will make it easier for the maintainers to review -+and accept your code. In fact, even before you contribute your changes -+upstream it will make it easier for you to develop for KVM. -+ -+Of course, the KVM maintainers reserve the right to require more tests, -+though they may also waive the requirement from time to time. -diff -purNx .git BPI-Router-Linux-kernel/Documentation/virt/kvm/x86/intel-tdx.rst BPI-Router-Linux-kernel-6.16.12/Documentation/virt/kvm/x86/intel-tdx.rst ---- BPI-Router-Linux-kernel/Documentation/virt/kvm/x86/intel-tdx.rst 2025-10-22 13:53:23.043329948 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/virt/kvm/x86/intel-tdx.rst 2025-10-22 13:53:56.275170298 -0400 -@@ -79,7 +79,20 @@ to be configured to the TDX guest. - struct kvm_tdx_capabilities { - __u64 supported_attrs; - __u64 supported_xfam; -- __u64 reserved[254]; -+ -+ /* TDG.VP.VMCALL hypercalls executed in kernel and forwarded to -+ * userspace, respectively -+ */ -+ __u64 kernel_tdvmcallinfo_1_r11; -+ __u64 user_tdvmcallinfo_1_r11; -+ -+ /* TDG.VP.VMCALL instruction executions subfunctions executed in kernel -+ * and forwarded to userspace, respectively -+ */ -+ __u64 kernel_tdvmcallinfo_1_r12; -+ __u64 user_tdvmcallinfo_1_r12; -+ -+ __u64 reserved[250]; - - /* Configurable CPUID bits for userspace */ - struct kvm_cpuid2 cpuid; -diff -purNx .git BPI-Router-Linux-kernel/Documentation/wmi/acpi-interface.rst BPI-Router-Linux-kernel-6.16.12/Documentation/wmi/acpi-interface.rst ---- BPI-Router-Linux-kernel/Documentation/wmi/acpi-interface.rst 2025-10-22 13:53:23.043329948 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Documentation/wmi/acpi-interface.rst 2025-10-22 13:53:56.275170298 -0400 -@@ -36,7 +36,7 @@ Offset Size (in bytes) Content - - The WMI object flags control whether the method or notification ID is used: - --- 0x1: Data block usage is expensive and must be explicitly enabled/disabled. -+- 0x1: Data block is expensive to collect. - - 0x2: Data block contains WMI methods. - - 0x4: Data block contains ASCIZ string. - - 0x8: Data block describes a WMI event, use notification ID instead -@@ -83,14 +83,18 @@ event as hexadecimal value. Their first - of 0 if the WMI event should be disabled, other values will enable - the WMI event. - -+Those ACPI methods are always called even for WMI events not registered as -+being expensive to collect to match the behavior of the Windows driver. -+ - WCxx ACPI methods - ----------------- --Similar to the ``WExx`` ACPI methods, except that it controls data collection --instead of events and thus the last two characters of the ACPI method name are --the method ID of the data block to enable/disable. -+Similar to the ``WExx`` ACPI methods, except that instead of WMI events it controls -+data collection of data blocks registered as being expensive to collect. Thus the -+last two characters of the ACPI method name are the method ID of the data block -+to enable/disable. - - Those ACPI methods are also called before setting data blocks to match the --behaviour of the Windows driver. -+behavior of the Windows driver. - - _WED ACPI method - ---------------- -diff -purNx .git BPI-Router-Linux-kernel/drivers/accel/amdxdna/aie2_psp.c BPI-Router-Linux-kernel-6.16.12/drivers/accel/amdxdna/aie2_psp.c ---- BPI-Router-Linux-kernel/drivers/accel/amdxdna/aie2_psp.c 2025-10-22 13:53:23.155329412 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/accel/amdxdna/aie2_psp.c 2025-10-22 13:53:56.403169681 -0400 -@@ -126,8 +126,8 @@ struct psp_device *aie2m_psp_create(stru - psp->ddev = ddev; - memcpy(psp->psp_regs, conf->psp_regs, sizeof(psp->psp_regs)); - -- psp->fw_buf_sz = ALIGN(conf->fw_size, PSP_FW_ALIGN) + PSP_FW_ALIGN; -- psp->fw_buffer = drmm_kmalloc(ddev, psp->fw_buf_sz, GFP_KERNEL); -+ psp->fw_buf_sz = ALIGN(conf->fw_size, PSP_FW_ALIGN); -+ psp->fw_buffer = drmm_kmalloc(ddev, psp->fw_buf_sz + PSP_FW_ALIGN, GFP_KERNEL); - if (!psp->fw_buffer) { - drm_err(ddev, "no memory for fw buffer"); - return NULL; -diff -purNx .git BPI-Router-Linux-kernel/drivers/accel/habanalabs/common/memory.c BPI-Router-Linux-kernel-6.16.12/drivers/accel/habanalabs/common/memory.c ---- BPI-Router-Linux-kernel/drivers/accel/habanalabs/common/memory.c 2025-10-22 13:53:23.155329412 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/accel/habanalabs/common/memory.c 2025-10-22 13:53:56.403169681 -0400 -@@ -1829,9 +1829,6 @@ static void hl_release_dmabuf(struct dma - struct hl_dmabuf_priv *hl_dmabuf = dmabuf->priv; - struct hl_ctx *ctx; - -- if (!hl_dmabuf) -- return; -- - ctx = hl_dmabuf->ctx; - - if (hl_dmabuf->memhash_hnode) -@@ -1859,7 +1856,12 @@ static int export_dmabuf(struct hl_ctx * - { - DEFINE_DMA_BUF_EXPORT_INFO(exp_info); - struct hl_device *hdev = ctx->hdev; -- int rc, fd; -+ CLASS(get_unused_fd, fd)(flags); -+ -+ if (fd < 0) { -+ dev_err(hdev->dev, "failed to get a file descriptor for a dma-buf, %d\n", fd); -+ return fd; -+ } - - exp_info.ops = &habanalabs_dmabuf_ops; - exp_info.size = total_size; -@@ -1872,13 +1874,6 @@ static int export_dmabuf(struct hl_ctx * - return PTR_ERR(hl_dmabuf->dmabuf); - } - -- fd = dma_buf_fd(hl_dmabuf->dmabuf, flags); -- if (fd < 0) { -- dev_err(hdev->dev, "failed to get a file descriptor for a dma-buf, %d\n", fd); -- rc = fd; -- goto err_dma_buf_put; -- } -- - hl_dmabuf->ctx = ctx; - hl_ctx_get(hl_dmabuf->ctx); - atomic_inc(&ctx->hdev->dmabuf_export_cnt); -@@ -1890,13 +1885,9 @@ static int export_dmabuf(struct hl_ctx * - get_file(ctx->hpriv->file_priv->filp); - - *dmabuf_fd = fd; -+ fd_install(take_fd(fd), hl_dmabuf->dmabuf->file); - - return 0; -- --err_dma_buf_put: -- hl_dmabuf->dmabuf->priv = NULL; -- dma_buf_put(hl_dmabuf->dmabuf); -- return rc; - } - - static int validate_export_params_common(struct hl_device *hdev, u64 addr, u64 size, u64 offset) -diff -purNx .git BPI-Router-Linux-kernel/drivers/accel/habanalabs/gaudi2/gaudi2.c BPI-Router-Linux-kernel-6.16.12/drivers/accel/habanalabs/gaudi2/gaudi2.c ---- BPI-Router-Linux-kernel/drivers/accel/habanalabs/gaudi2/gaudi2.c 2025-10-22 13:53:23.155329412 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/accel/habanalabs/gaudi2/gaudi2.c 2025-10-22 13:53:56.407169662 -0400 -@@ -10437,7 +10437,7 @@ end: - (u64 *)(lin_dma_pkts_arr), DEBUGFS_WRITE64); - WREG32(sob_addr, 0); - -- kfree(lin_dma_pkts_arr); -+ kvfree(lin_dma_pkts_arr); - - return rc; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/accel/ivpu/ivpu_drv.c BPI-Router-Linux-kernel-6.16.12/drivers/accel/ivpu/ivpu_drv.c ---- BPI-Router-Linux-kernel/drivers/accel/ivpu/ivpu_drv.c 2025-10-22 13:53:23.155329412 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/accel/ivpu/ivpu_drv.c 2025-10-22 13:53:56.407169662 -0400 -@@ -677,7 +677,7 @@ static void ivpu_bo_unbind_all_user_cont - static void ivpu_dev_fini(struct ivpu_device *vdev) - { - ivpu_jobs_abort_all(vdev); -- ivpu_pm_cancel_recovery(vdev); -+ ivpu_pm_disable_recovery(vdev); - ivpu_pm_disable(vdev); - ivpu_prepare_for_reset(vdev); - ivpu_shutdown(vdev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/accel/ivpu/ivpu_pm.c BPI-Router-Linux-kernel-6.16.12/drivers/accel/ivpu/ivpu_pm.c ---- BPI-Router-Linux-kernel/drivers/accel/ivpu/ivpu_pm.c 2025-10-22 13:53:23.155329412 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/accel/ivpu/ivpu_pm.c 2025-10-22 13:53:56.407169662 -0400 -@@ -408,10 +408,10 @@ void ivpu_pm_init(struct ivpu_device *vd - ivpu_dbg(vdev, PM, "Autosuspend delay = %d\n", delay); - } - --void ivpu_pm_cancel_recovery(struct ivpu_device *vdev) -+void ivpu_pm_disable_recovery(struct ivpu_device *vdev) - { - drm_WARN_ON(&vdev->drm, delayed_work_pending(&vdev->pm->job_timeout_work)); -- cancel_work_sync(&vdev->pm->recovery_work); -+ disable_work_sync(&vdev->pm->recovery_work); - } - - void ivpu_pm_enable(struct ivpu_device *vdev) -diff -purNx .git BPI-Router-Linux-kernel/drivers/accel/ivpu/ivpu_pm.h BPI-Router-Linux-kernel-6.16.12/drivers/accel/ivpu/ivpu_pm.h ---- BPI-Router-Linux-kernel/drivers/accel/ivpu/ivpu_pm.h 2025-10-22 13:53:23.155329412 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/accel/ivpu/ivpu_pm.h 2025-10-22 13:53:56.407169662 -0400 -@@ -25,7 +25,7 @@ struct ivpu_pm_info { - void ivpu_pm_init(struct ivpu_device *vdev); - void ivpu_pm_enable(struct ivpu_device *vdev); - void ivpu_pm_disable(struct ivpu_device *vdev); --void ivpu_pm_cancel_recovery(struct ivpu_device *vdev); -+void ivpu_pm_disable_recovery(struct ivpu_device *vdev); - - int ivpu_pm_suspend_cb(struct device *dev); - int ivpu_pm_resume_cb(struct device *dev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/acpi/acpica/dsmethod.c BPI-Router-Linux-kernel-6.16.12/drivers/acpi/acpica/dsmethod.c ---- BPI-Router-Linux-kernel/drivers/acpi/acpica/dsmethod.c 2025-10-22 13:53:23.155329412 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/acpi/acpica/dsmethod.c 2025-10-22 13:53:56.407169662 -0400 -@@ -483,6 +483,13 @@ acpi_ds_call_control_method(struct acpi_ - return_ACPI_STATUS(AE_NULL_OBJECT); - } - -+ if (this_walk_state->num_operands < obj_desc->method.param_count) { -+ ACPI_ERROR((AE_INFO, "Missing argument for method [%4.4s]", -+ acpi_ut_get_node_name(method_node))); -+ -+ return_ACPI_STATUS(AE_AML_UNINITIALIZED_ARG); -+ } -+ - /* Init for new method, possibly wait on method mutex */ - - status = -diff -purNx .git BPI-Router-Linux-kernel/drivers/acpi/acpi_pad.c BPI-Router-Linux-kernel-6.16.12/drivers/acpi/acpi_pad.c ---- BPI-Router-Linux-kernel/drivers/acpi/acpi_pad.c 2025-10-22 13:53:23.155329412 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/acpi/acpi_pad.c 2025-10-22 13:53:56.407169662 -0400 -@@ -33,7 +33,7 @@ - static DEFINE_MUTEX(isolated_cpus_lock); - static DEFINE_MUTEX(round_robin_lock); - --static unsigned long power_saving_mwait_eax; -+static unsigned int power_saving_mwait_eax; - - static unsigned char tsc_detected_unstable; - static unsigned char tsc_marked_unstable; -diff -purNx .git BPI-Router-Linux-kernel/drivers/acpi/acpi_processor.c BPI-Router-Linux-kernel-6.16.12/drivers/acpi/acpi_processor.c ---- BPI-Router-Linux-kernel/drivers/acpi/acpi_processor.c 2025-10-22 13:53:23.155329412 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/acpi/acpi_processor.c 2025-10-22 13:53:56.407169662 -0400 -@@ -275,7 +275,7 @@ static inline int acpi_processor_hotadd_ - - static int acpi_processor_get_info(struct acpi_device *device) - { -- union acpi_object object = { 0 }; -+ union acpi_object object = { .processor = { 0 } }; - struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; - struct acpi_processor *pr = acpi_driver_data(device); - int device_declaration = 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/acpi/apei/einj-core.c BPI-Router-Linux-kernel-6.16.12/drivers/acpi/apei/einj-core.c ---- BPI-Router-Linux-kernel/drivers/acpi/apei/einj-core.c 2025-10-22 13:53:23.155329412 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/acpi/apei/einj-core.c 2025-10-22 13:53:56.407169662 -0400 -@@ -842,7 +842,7 @@ err_put_table: - return rc; - } - --static void __exit einj_remove(struct faux_device *fdev) -+static void einj_remove(struct faux_device *fdev) - { - struct apei_exec_context ctx; - -@@ -864,15 +864,9 @@ static void __exit einj_remove(struct fa - } - - static struct faux_device *einj_dev; --/* -- * einj_remove() lives in .exit.text. For drivers registered via -- * platform_driver_probe() this is ok because they cannot get unbound at -- * runtime. So mark the driver struct with __refdata to prevent modpost -- * triggering a section mismatch warning. -- */ --static struct faux_device_ops einj_device_ops __refdata = { -+static struct faux_device_ops einj_device_ops = { - .probe = einj_probe, -- .remove = __exit_p(einj_remove), -+ .remove = einj_remove, - }; - - static int __init einj_init(void) -@@ -883,19 +877,16 @@ static int __init einj_init(void) - } - - einj_dev = faux_device_create("acpi-einj", NULL, &einj_device_ops); -- if (!einj_dev) -- return -ENODEV; - -- einj_initialized = true; -+ if (einj_dev) -+ einj_initialized = true; - - return 0; - } - - static void __exit einj_exit(void) - { -- if (einj_initialized) -- faux_device_destroy(einj_dev); -- -+ faux_device_destroy(einj_dev); - } - - module_init(einj_init); -diff -purNx .git BPI-Router-Linux-kernel/drivers/acpi/apei/ghes.c BPI-Router-Linux-kernel-6.16.12/drivers/acpi/apei/ghes.c ---- BPI-Router-Linux-kernel/drivers/acpi/apei/ghes.c 2025-10-22 13:53:23.159329393 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/acpi/apei/ghes.c 2025-10-22 13:53:56.407169662 -0400 -@@ -902,6 +902,17 @@ static bool ghes_do_proc(struct ghes *gh - } - } - -+ /* -+ * If no memory failure work is queued for abnormal synchronous -+ * errors, do a force kill. -+ */ -+ if (sync && !queued) { -+ dev_err(ghes->dev, -+ HW_ERR GHES_PFX "%s:%d: synchronous unrecoverable error (SIGBUS)\n", -+ current->comm, task_pid_nr(current)); -+ force_sig(SIGBUS); -+ } -+ - return queued; - } - -@@ -1088,6 +1099,8 @@ static void __ghes_panic(struct ghes *gh - - __ghes_print_estatus(KERN_EMERG, ghes->generic, estatus); - -+ add_taint(TAINT_MACHINE_CHECK, LOCKDEP_STILL_OK); -+ - ghes_clear_estatus(ghes, estatus, buf_paddr, fixmap_idx); - - if (!panic_timeout) -diff -purNx .git BPI-Router-Linux-kernel/drivers/acpi/arm64/iort.c BPI-Router-Linux-kernel-6.16.12/drivers/acpi/arm64/iort.c ---- BPI-Router-Linux-kernel/drivers/acpi/arm64/iort.c 2025-10-22 13:53:23.159329393 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/acpi/arm64/iort.c 2025-10-22 13:53:56.407169662 -0400 -@@ -937,8 +937,10 @@ static u32 *iort_rmr_alloc_sids(u32 *sid - - new_sids = krealloc_array(sids, count + new_count, - sizeof(*new_sids), GFP_KERNEL); -- if (!new_sids) -+ if (!new_sids) { -+ kfree(sids); - return NULL; -+ } - - for (i = count; i < total_count; i++) - new_sids[i] = id_start++; -diff -purNx .git BPI-Router-Linux-kernel/drivers/acpi/battery.c BPI-Router-Linux-kernel-6.16.12/drivers/acpi/battery.c ---- BPI-Router-Linux-kernel/drivers/acpi/battery.c 2025-10-22 13:53:23.159329393 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/acpi/battery.c 2025-10-22 13:53:56.407169662 -0400 -@@ -243,23 +243,10 @@ static int acpi_battery_get_property(str - break; - case POWER_SUPPLY_PROP_CURRENT_NOW: - case POWER_SUPPLY_PROP_POWER_NOW: -- if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN) { -+ if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN) - ret = -ENODEV; -- break; -- } -- -- val->intval = battery->rate_now * 1000; -- /* -- * When discharging, the current should be reported as a -- * negative number as per the power supply class interface -- * definition. -- */ -- if (psp == POWER_SUPPLY_PROP_CURRENT_NOW && -- (battery->state & ACPI_BATTERY_STATE_DISCHARGING) && -- acpi_battery_handle_discharging(battery) -- == POWER_SUPPLY_STATUS_DISCHARGING) -- val->intval = -val->intval; -- -+ else -+ val->intval = battery->rate_now * 1000; - break; - case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: - case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: -diff -purNx .git BPI-Router-Linux-kernel/drivers/acpi/cppc_acpi.c BPI-Router-Linux-kernel-6.16.12/drivers/acpi/cppc_acpi.c ---- BPI-Router-Linux-kernel/drivers/acpi/cppc_acpi.c 2025-10-22 13:53:23.159329393 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/acpi/cppc_acpi.c 2025-10-22 13:53:56.407169662 -0400 -@@ -476,7 +476,7 @@ bool cppc_allow_fast_switch(void) - struct cpc_desc *cpc_ptr; - int cpu; - -- for_each_possible_cpu(cpu) { -+ for_each_present_cpu(cpu) { - cpc_ptr = per_cpu(cpc_desc_ptr, cpu); - desired_reg = &cpc_ptr->cpc_regs[DESIRED_PERF]; - if (!CPC_IN_SYSTEM_MEMORY(desired_reg) && -diff -purNx .git BPI-Router-Linux-kernel/drivers/acpi/ec.c BPI-Router-Linux-kernel-6.16.12/drivers/acpi/ec.c ---- BPI-Router-Linux-kernel/drivers/acpi/ec.c 2025-10-22 13:53:23.159329393 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/acpi/ec.c 2025-10-22 13:53:56.407169662 -0400 -@@ -23,8 +23,10 @@ - #include - #include - #include -+#include - #include - #include -+#include - #include - #include - #include -@@ -2031,6 +2033,25 @@ void __init acpi_ec_ecdt_probe(void) - goto out; - } - -+ if (!strlen(ecdt_ptr->id)) { -+ /* -+ * The ECDT table on some MSI notebooks contains invalid data, together -+ * with an empty ID string (""). -+ * -+ * Section 5.2.15 of the ACPI specification requires the ID string to be -+ * a "fully qualified reference to the (...) embedded controller device", -+ * so this string always has to start with a backslash. -+ * -+ * However some ThinkBook machines have a ECDT table with a valid EC -+ * description but an invalid ID string ("_SB.PC00.LPCB.EC0"). -+ * -+ * Because of this we only check if the ID string is empty in order to -+ * avoid the obvious cases. -+ */ -+ pr_err(FW_BUG "Ignoring ECDT due to empty ID string\n"); -+ goto out; -+ } -+ - ec = acpi_ec_alloc(); - if (!ec) - goto out; -diff -purNx .git BPI-Router-Linux-kernel/drivers/acpi/internal.h BPI-Router-Linux-kernel-6.16.12/drivers/acpi/internal.h ---- BPI-Router-Linux-kernel/drivers/acpi/internal.h 2025-10-22 13:53:23.159329393 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/acpi/internal.h 2025-10-22 13:53:56.407169662 -0400 -@@ -175,6 +175,12 @@ bool processor_physically_present(acpi_h - static inline void acpi_early_processor_control_setup(void) {} - #endif - -+#ifdef CONFIG_ACPI_PROCESSOR_CSTATE -+void acpi_idle_rescan_dead_smt_siblings(void); -+#else -+static inline void acpi_idle_rescan_dead_smt_siblings(void) {} -+#endif -+ - /* -------------------------------------------------------------------------- - Embedded Controller - -------------------------------------------------------------------------- */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/acpi/pfr_update.c BPI-Router-Linux-kernel-6.16.12/drivers/acpi/pfr_update.c ---- BPI-Router-Linux-kernel/drivers/acpi/pfr_update.c 2025-10-22 13:53:23.159329393 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/acpi/pfr_update.c 2025-10-22 13:53:56.407169662 -0400 -@@ -310,7 +310,7 @@ static bool applicable_image(const void - if (type == PFRU_CODE_INJECT_TYPE) - return payload_hdr->rt_ver >= cap->code_rt_version; - -- return payload_hdr->rt_ver >= cap->drv_rt_version; -+ return payload_hdr->svn_ver >= cap->drv_svn; - } - - static void print_update_debug_info(struct pfru_updated_result *result, -diff -purNx .git BPI-Router-Linux-kernel/drivers/acpi/prmt.c BPI-Router-Linux-kernel-6.16.12/drivers/acpi/prmt.c ---- BPI-Router-Linux-kernel/drivers/acpi/prmt.c 2025-10-22 13:53:23.159329393 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/acpi/prmt.c 2025-10-22 13:53:56.407169662 -0400 -@@ -85,8 +85,6 @@ static u64 efi_pa_va_lookup(efi_guid_t * - } - } - -- pr_warn("Failed to find VA for GUID: %pUL, PA: 0x%llx", guid, pa); -- - return 0; - } - -@@ -154,13 +152,37 @@ acpi_parse_prmt(union acpi_subtable_head - guid_copy(&th->guid, (guid_t *)handler_info->handler_guid); - th->handler_addr = - (void *)efi_pa_va_lookup(&th->guid, handler_info->handler_address); -+ /* -+ * Print a warning message if handler_addr is zero which is not expected to -+ * ever happen. -+ */ -+ if (unlikely(!th->handler_addr)) -+ pr_warn("Failed to find VA of handler for GUID: %pUL, PA: 0x%llx", -+ &th->guid, handler_info->handler_address); - - th->static_data_buffer_addr = - efi_pa_va_lookup(&th->guid, handler_info->static_data_buffer_address); -+ /* -+ * According to the PRM specification, static_data_buffer_address can be zero, -+ * so avoid printing a warning message in that case. Otherwise, if the -+ * return value of efi_pa_va_lookup() is zero, print the message. -+ */ -+ if (unlikely(!th->static_data_buffer_addr && handler_info->static_data_buffer_address)) -+ pr_warn("Failed to find VA of static data buffer for GUID: %pUL, PA: 0x%llx", -+ &th->guid, handler_info->static_data_buffer_address); - - th->acpi_param_buffer_addr = - efi_pa_va_lookup(&th->guid, handler_info->acpi_param_buffer_address); - -+ /* -+ * According to the PRM specification, acpi_param_buffer_address can be zero, -+ * so avoid printing a warning message in that case. Otherwise, if the -+ * return value of efi_pa_va_lookup() is zero, print the message. -+ */ -+ if (unlikely(!th->acpi_param_buffer_addr && handler_info->acpi_param_buffer_address)) -+ pr_warn("Failed to find VA of acpi param buffer for GUID: %pUL, PA: 0x%llx", -+ &th->guid, handler_info->acpi_param_buffer_address); -+ - } while (++cur_handler < tm->handler_count && (handler_info = get_next_handler(handler_info))); - - return 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/acpi/processor_driver.c BPI-Router-Linux-kernel-6.16.12/drivers/acpi/processor_driver.c ---- BPI-Router-Linux-kernel/drivers/acpi/processor_driver.c 2025-10-22 13:53:23.159329393 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/acpi/processor_driver.c 2025-10-22 13:53:56.407169662 -0400 -@@ -279,6 +279,9 @@ static int __init acpi_processor_driver_ - * after acpi_cppc_processor_probe() has been called for all online CPUs - */ - acpi_processor_init_invariance_cppc(); -+ -+ acpi_idle_rescan_dead_smt_siblings(); -+ - return 0; - err: - driver_unregister(&acpi_processor_driver); -diff -purNx .git BPI-Router-Linux-kernel/drivers/acpi/processor_idle.c BPI-Router-Linux-kernel-6.16.12/drivers/acpi/processor_idle.c ---- BPI-Router-Linux-kernel/drivers/acpi/processor_idle.c 2025-10-22 13:53:23.159329393 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/acpi/processor_idle.c 2025-10-22 13:53:56.407169662 -0400 -@@ -24,6 +24,8 @@ - #include - #include - -+#include "internal.h" -+ - /* - * Include the apic definitions for x86 to have the APIC timer related defines - * available also for UP (on SMP it gets magically included via linux/smp.h). -@@ -55,6 +57,12 @@ struct cpuidle_driver acpi_idle_driver = - }; - - #ifdef CONFIG_ACPI_PROCESSOR_CSTATE -+void acpi_idle_rescan_dead_smt_siblings(void) -+{ -+ if (cpuidle_get_driver() == &acpi_idle_driver) -+ arch_cpu_rescan_dead_smt_siblings(); -+} -+ - static - DEFINE_PER_CPU(struct acpi_processor_cx * [CPUIDLE_STATE_MAX], acpi_cstate); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/acpi/processor_perflib.c BPI-Router-Linux-kernel-6.16.12/drivers/acpi/processor_perflib.c ---- BPI-Router-Linux-kernel/drivers/acpi/processor_perflib.c 2025-10-22 13:53:23.159329393 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/acpi/processor_perflib.c 2025-10-22 13:53:56.407169662 -0400 -@@ -173,6 +173,9 @@ void acpi_processor_ppc_init(struct cpuf - { - unsigned int cpu; - -+ if (ignore_ppc == 1) -+ return; -+ - for_each_cpu(cpu, policy->related_cpus) { - struct acpi_processor *pr = per_cpu(processors, cpu); - int ret; -@@ -193,6 +196,14 @@ void acpi_processor_ppc_init(struct cpuf - if (ret < 0) - pr_err("Failed to add freq constraint for CPU%d (%d)\n", - cpu, ret); -+ -+ if (!pr->performance) -+ continue; -+ -+ ret = acpi_processor_get_platform_limit(pr); -+ if (ret) -+ pr_err("Failed to update freq constraint for CPU%d (%d)\n", -+ cpu, ret); - } - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/acpi/resource.c BPI-Router-Linux-kernel-6.16.12/drivers/acpi/resource.c ---- BPI-Router-Linux-kernel/drivers/acpi/resource.c 2025-10-22 13:53:23.159329393 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/acpi/resource.c 2025-10-22 13:53:56.407169662 -0400 -@@ -667,6 +667,13 @@ static const struct dmi_system_id irq1_e - }, - }, - { -+ /* MACHENIKE L16P/L16P */ -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "MACHENIKE"), -+ DMI_MATCH(DMI_BOARD_NAME, "L16P"), -+ }, -+ }, -+ { - /* - * TongFang GM5HG0A in case of the SKIKK Vanaheim relabel the - * board-name is changed, so check OEM strings instead. Note -diff -purNx .git BPI-Router-Linux-kernel/drivers/acpi/riscv/cppc.c BPI-Router-Linux-kernel-6.16.12/drivers/acpi/riscv/cppc.c ---- BPI-Router-Linux-kernel/drivers/acpi/riscv/cppc.c 2025-10-22 13:53:23.159329393 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/acpi/riscv/cppc.c 2025-10-22 13:53:56.407169662 -0400 -@@ -37,10 +37,8 @@ static int __init sbi_cppc_init(void) - { - if (sbi_spec_version >= sbi_mk_version(2, 0) && - sbi_probe_extension(SBI_EXT_CPPC) > 0) { -- pr_info("SBI CPPC extension detected\n"); - cppc_ext_present = true; - } else { -- pr_info("SBI CPPC extension NOT detected!!\n"); - cppc_ext_present = false; - } - -@@ -121,7 +119,7 @@ int cpc_read_ffh(int cpu, struct cpc_reg - - *val = data.ret.value; - -- return (data.ret.error) ? sbi_err_map_linux_errno(data.ret.error) : 0; -+ return data.ret.error; - } - - return -EINVAL; -@@ -150,7 +148,7 @@ int cpc_write_ffh(int cpu, struct cpc_re - - smp_call_function_single(cpu, cppc_ffh_csr_write, &data, 1); - -- return (data.ret.error) ? sbi_err_map_linux_errno(data.ret.error) : 0; -+ return data.ret.error; - } - - return -EINVAL; -diff -purNx .git BPI-Router-Linux-kernel/drivers/android/binder_alloc_selftest.c BPI-Router-Linux-kernel-6.16.12/drivers/android/binder_alloc_selftest.c ---- BPI-Router-Linux-kernel/drivers/android/binder_alloc_selftest.c 2025-10-22 13:53:23.159329393 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/android/binder_alloc_selftest.c 2025-10-22 13:53:56.407169662 -0400 -@@ -142,12 +142,12 @@ static void binder_selftest_free_buf(str - for (i = 0; i < BUFFER_NUM; i++) - binder_alloc_free_buf(alloc, buffers[seq[i]]); - -- for (i = 0; i < end / PAGE_SIZE; i++) { - /** - * Error message on a free page can be false positive - * if binder shrinker ran during binder_alloc_free_buf - * calls above. - */ -+ for (i = 0; i <= (end - 1) / PAGE_SIZE; i++) { - if (list_empty(page_to_lru(alloc->pages[i]))) { - pr_err_size_seq(sizes, seq); - pr_err("expect lru but is %s at page index %d\n", -diff -purNx .git BPI-Router-Linux-kernel/drivers/android/dbitmap.h BPI-Router-Linux-kernel-6.16.12/drivers/android/dbitmap.h ---- BPI-Router-Linux-kernel/drivers/android/dbitmap.h 2025-10-22 13:53:23.159329393 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/android/dbitmap.h 2025-10-22 13:53:56.407169662 -0400 -@@ -37,6 +37,7 @@ static inline void dbitmap_free(struct d - { - dmap->nbits = 0; - kfree(dmap->map); -+ dmap->map = NULL; - } - - /* Returns the nbits that a dbitmap can shrink to, 0 if not possible. */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/ata/ahci.c BPI-Router-Linux-kernel-6.16.12/drivers/ata/ahci.c ---- BPI-Router-Linux-kernel/drivers/ata/ahci.c 2025-10-22 13:53:23.159329393 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/ata/ahci.c 2025-10-22 13:53:56.407169662 -0400 -@@ -1410,8 +1410,15 @@ static bool ahci_broken_suspend(struct p - - static bool ahci_broken_lpm(struct pci_dev *pdev) - { -+ /* -+ * Platforms with LPM problems. -+ * If driver_data is NULL, there is no existing BIOS version with -+ * functioning LPM. -+ * If driver_data is non-NULL, then driver_data contains the DMI BIOS -+ * build date of the first BIOS version with functioning LPM (i.e. older -+ * BIOS versions have broken LPM). -+ */ - static const struct dmi_system_id sysids[] = { -- /* Various Lenovo 50 series have LPM issues with older BIOSen */ - { - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), -@@ -1438,13 +1445,30 @@ static bool ahci_broken_lpm(struct pci_d - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W541"), - }, -+ .driver_data = "20180409", /* 2.35 */ -+ }, -+ { -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), -+ DMI_MATCH(DMI_PRODUCT_NAME, "ASUSPRO D840MB_M840SA"), -+ }, -+ /* 320 is broken, there is no known good version. */ -+ }, -+ { - /* -- * Note date based on release notes, 2.35 has been -- * reported to be good, but I've been unable to get -- * a hold of the reporter to get the DMI BIOS date. -- * TODO: fix this. -+ * AMD 500 Series Chipset SATA Controller [1022:43eb] -+ * on this motherboard timeouts on ports 5 and 6 when -+ * LPM is enabled, at least with WDC WD20EFAX-68FB5N0 -+ * hard drives. LPM with the same drive works fine on -+ * all other ports on the same controller. - */ -- .driver_data = "20180310", /* 2.35 */ -+ .matches = { -+ DMI_MATCH(DMI_BOARD_VENDOR, -+ "ASUSTeK COMPUTER INC."), -+ DMI_MATCH(DMI_BOARD_NAME, -+ "ROG STRIX B550-F GAMING (WI-FI)"), -+ }, -+ /* 3621 is broken, there is no known good version. */ - }, - { } /* terminate list */ - }; -@@ -1455,6 +1479,9 @@ static bool ahci_broken_lpm(struct pci_d - if (!dmi) - return false; - -+ if (!dmi->driver_data) -+ return true; -+ - dmi_get_date(DMI_BIOS_DATE, &year, &month, &date); - snprintf(buf, sizeof(buf), "%04d%02d%02d", year, month, date); - -@@ -1751,11 +1778,21 @@ static void ahci_update_initial_lpm_poli - return; - } - -+ /* If no Partial or no Slumber, we cannot support DIPM. */ -+ if ((ap->host->flags & ATA_HOST_NO_PART) || -+ (ap->host->flags & ATA_HOST_NO_SSC)) { -+ ata_port_dbg(ap, "Host does not support DIPM\n"); -+ ap->flags |= ATA_FLAG_NO_DIPM; -+ } -+ - /* If no LPM states are supported by the HBA, do not bother with LPM */ - if ((ap->host->flags & ATA_HOST_NO_PART) && - (ap->host->flags & ATA_HOST_NO_SSC) && - (ap->host->flags & ATA_HOST_NO_DEVSLP)) { -- ata_port_dbg(ap, "no LPM states supported, not enabling LPM\n"); -+ ata_port_dbg(ap, -+ "No LPM states supported, forcing LPM max_power\n"); -+ ap->flags |= ATA_FLAG_NO_LPM; -+ ap->target_lpm_policy = ATA_LPM_MAX_POWER; - return; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/ata/ata_piix.c BPI-Router-Linux-kernel-6.16.12/drivers/ata/ata_piix.c ---- BPI-Router-Linux-kernel/drivers/ata/ata_piix.c 2025-10-22 13:53:23.159329393 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/ata/ata_piix.c 2025-10-22 13:53:56.407169662 -0400 -@@ -1089,6 +1089,7 @@ static struct ata_port_operations ich_pa - }; - - static struct attribute *piix_sidpr_shost_attrs[] = { -+ &dev_attr_link_power_management_supported.attr, - &dev_attr_link_power_management_policy.attr, - NULL - }; -diff -purNx .git BPI-Router-Linux-kernel/drivers/ata/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/ata/Kconfig ---- BPI-Router-Linux-kernel/drivers/ata/Kconfig 2025-10-22 13:53:23.159329393 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/ata/Kconfig 2025-10-22 13:53:56.407169662 -0400 -@@ -117,23 +117,39 @@ config SATA_AHCI - - config SATA_MOBILE_LPM_POLICY - int "Default SATA Link Power Management policy" -- range 0 4 -+ range 0 5 - default 3 - depends on SATA_AHCI - help - Select the Default SATA Link Power Management (LPM) policy to use - for chipsets / "South Bridges" supporting low-power modes. Such - chipsets are ubiquitous across laptops, desktops and servers. -+ Each policy combines power saving states and features: -+ - Partial: The Phy logic is powered but is in a reduced power -+ state. The exit latency from this state is no longer than -+ 10us). -+ - Slumber: The Phy logic is powered but is in an even lower power -+ state. The exit latency from this state is potentially -+ longer, but no longer than 10ms. -+ - DevSleep: The Phy logic may be powered down. The exit latency from -+ this state is no longer than 20 ms, unless otherwise -+ specified by DETO in the device Identify Device Data log. -+ - HIPM: Host Initiated Power Management (host automatically -+ transitions to partial and slumber). -+ - DIPM: Device Initiated Power Management (device automatically -+ transitions to partial and slumber). - -- The value set has the following meanings: -+ The possible values for the default SATA link power management -+ policies are: - 0 => Keep firmware settings -- 1 => Maximum performance -- 2 => Medium power -- 3 => Medium power with Device Initiated PM enabled -- 4 => Minimum power -+ 1 => No power savings (maximum performance) -+ 2 => HIPM (Partial) -+ 3 => HIPM (Partial) and DIPM (Partial and Slumber) -+ 4 => HIPM (Partial and DevSleep) and DIPM (Partial and Slumber) -+ 5 => HIPM (Slumber and DevSleep) and DIPM (Partial and Slumber) - -- Note "Minimum power" is known to cause issues, including disk -- corruption, with some disks and should not be used. -+ Excluding the value 0, higher values represent policies with higher -+ power savings. - - config SATA_AHCI_PLATFORM - tristate "Platform AHCI SATA support" -diff -purNx .git BPI-Router-Linux-kernel/drivers/ata/libahci.c BPI-Router-Linux-kernel-6.16.12/drivers/ata/libahci.c ---- BPI-Router-Linux-kernel/drivers/ata/libahci.c 2025-10-22 13:53:23.159329393 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/ata/libahci.c 2025-10-22 13:53:56.407169662 -0400 -@@ -111,6 +111,7 @@ static DEVICE_ATTR(em_buffer, S_IWUSR | - static DEVICE_ATTR(em_message_supported, S_IRUGO, ahci_show_em_supported, NULL); - - static struct attribute *ahci_shost_attrs[] = { -+ &dev_attr_link_power_management_supported.attr, - &dev_attr_link_power_management_policy.attr, - &dev_attr_em_message_type.attr, - &dev_attr_em_message.attr, -diff -purNx .git BPI-Router-Linux-kernel/drivers/ata/libata-acpi.c BPI-Router-Linux-kernel-6.16.12/drivers/ata/libata-acpi.c ---- BPI-Router-Linux-kernel/drivers/ata/libata-acpi.c 2025-10-22 13:53:23.159329393 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/ata/libata-acpi.c 2025-10-22 13:53:56.407169662 -0400 -@@ -514,15 +514,19 @@ unsigned int ata_acpi_gtm_xfermask(struc - EXPORT_SYMBOL_GPL(ata_acpi_gtm_xfermask); - - /** -- * ata_acpi_cbl_80wire - Check for 80 wire cable -+ * ata_acpi_cbl_pata_type - Return PATA cable type - * @ap: Port to check -- * @gtm: GTM data to use - * -- * Return 1 if the @gtm indicates the BIOS selected an 80wire mode. -+ * Return ATA_CBL_PATA* according to the transfer mode selected by BIOS - */ --int ata_acpi_cbl_80wire(struct ata_port *ap, const struct ata_acpi_gtm *gtm) -+int ata_acpi_cbl_pata_type(struct ata_port *ap) - { - struct ata_device *dev; -+ int ret = ATA_CBL_PATA_UNK; -+ const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap); -+ -+ if (!gtm) -+ return ATA_CBL_PATA40; - - ata_for_each_dev(dev, &ap->link, ENABLED) { - unsigned int xfer_mask, udma_mask; -@@ -530,13 +534,17 @@ int ata_acpi_cbl_80wire(struct ata_port - xfer_mask = ata_acpi_gtm_xfermask(dev, gtm); - ata_unpack_xfermask(xfer_mask, NULL, NULL, &udma_mask); - -- if (udma_mask & ~ATA_UDMA_MASK_40C) -- return 1; -+ ret = ATA_CBL_PATA40; -+ -+ if (udma_mask & ~ATA_UDMA_MASK_40C) { -+ ret = ATA_CBL_PATA80; -+ break; -+ } - } - -- return 0; -+ return ret; - } --EXPORT_SYMBOL_GPL(ata_acpi_cbl_80wire); -+EXPORT_SYMBOL_GPL(ata_acpi_cbl_pata_type); - - static void ata_acpi_gtf_to_tf(struct ata_device *dev, - const struct ata_acpi_gtf *gtf, -diff -purNx .git BPI-Router-Linux-kernel/drivers/ata/libata-sata.c BPI-Router-Linux-kernel-6.16.12/drivers/ata/libata-sata.c ---- BPI-Router-Linux-kernel/drivers/ata/libata-sata.c 2025-10-22 13:53:23.159329393 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/ata/libata-sata.c 2025-10-22 13:53:56.407169662 -0400 -@@ -900,14 +900,52 @@ static const char *ata_lpm_policy_names[ - [ATA_LPM_MIN_POWER] = "min_power", - }; - -+/* -+ * Check if a port supports link power management. -+ * Must be called with the port locked. -+ */ -+static bool ata_scsi_lpm_supported(struct ata_port *ap) -+{ -+ struct ata_link *link; -+ struct ata_device *dev; -+ -+ if (ap->flags & ATA_FLAG_NO_LPM) -+ return false; -+ -+ ata_for_each_link(link, ap, EDGE) { -+ ata_for_each_dev(dev, &ap->link, ENABLED) { -+ if (dev->quirks & ATA_QUIRK_NOLPM) -+ return false; -+ } -+ } -+ -+ return true; -+} -+ -+static ssize_t ata_scsi_lpm_supported_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct Scsi_Host *shost = class_to_shost(dev); -+ struct ata_port *ap = ata_shost_to_port(shost); -+ unsigned long flags; -+ bool supported; -+ -+ spin_lock_irqsave(ap->lock, flags); -+ supported = ata_scsi_lpm_supported(ap); -+ spin_unlock_irqrestore(ap->lock, flags); -+ -+ return sysfs_emit(buf, "%d\n", supported); -+} -+DEVICE_ATTR(link_power_management_supported, S_IRUGO, -+ ata_scsi_lpm_supported_show, NULL); -+EXPORT_SYMBOL_GPL(dev_attr_link_power_management_supported); -+ - static ssize_t ata_scsi_lpm_store(struct device *device, - struct device_attribute *attr, - const char *buf, size_t count) - { - struct Scsi_Host *shost = class_to_shost(device); - struct ata_port *ap = ata_shost_to_port(shost); -- struct ata_link *link; -- struct ata_device *dev; - enum ata_lpm_policy policy; - unsigned long flags; - -@@ -924,13 +962,9 @@ static ssize_t ata_scsi_lpm_store(struct - - spin_lock_irqsave(ap->lock, flags); - -- ata_for_each_link(link, ap, EDGE) { -- ata_for_each_dev(dev, &ap->link, ENABLED) { -- if (dev->quirks & ATA_QUIRK_NOLPM) { -- count = -EOPNOTSUPP; -- goto out_unlock; -- } -- } -+ if (!ata_scsi_lpm_supported(ap)) { -+ count = -EOPNOTSUPP; -+ goto out_unlock; - } - - ap->target_lpm_policy = policy; -diff -purNx .git BPI-Router-Linux-kernel/drivers/ata/libata-scsi.c BPI-Router-Linux-kernel-6.16.12/drivers/ata/libata-scsi.c ---- BPI-Router-Linux-kernel/drivers/ata/libata-scsi.c 2025-10-22 13:53:23.159329393 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/ata/libata-scsi.c 2025-10-22 13:53:56.411169643 -0400 -@@ -859,18 +859,14 @@ static void ata_to_sense_error(u8 drv_st - {0xFF, 0xFF, 0xFF, 0xFF}, // END mark - }; - static const unsigned char stat_table[][4] = { -- /* Must be first because BUSY means no other bits valid */ -- {0x80, ABORTED_COMMAND, 0x47, 0x00}, -- // Busy, fake parity for now -- {0x40, ILLEGAL_REQUEST, 0x21, 0x04}, -- // Device ready, unaligned write command -- {0x20, HARDWARE_ERROR, 0x44, 0x00}, -- // Device fault, internal target failure -- {0x08, ABORTED_COMMAND, 0x47, 0x00}, -- // Timed out in xfer, fake parity for now -- {0x04, RECOVERED_ERROR, 0x11, 0x00}, -- // Recovered ECC error Medium error, recovered -- {0xFF, 0xFF, 0xFF, 0xFF}, // END mark -+ /* Busy: must be first because BUSY means no other bits valid */ -+ { ATA_BUSY, ABORTED_COMMAND, 0x00, 0x00 }, -+ /* Device fault: INTERNAL TARGET FAILURE */ -+ { ATA_DF, HARDWARE_ERROR, 0x44, 0x00 }, -+ /* Corrected data error */ -+ { ATA_CORR, RECOVERED_ERROR, 0x00, 0x00 }, -+ -+ { 0xFF, 0xFF, 0xFF, 0xFF }, /* END mark */ - }; - - /* -@@ -942,6 +938,8 @@ static void ata_gen_passthru_sense(struc - if (!(qc->flags & ATA_QCFLAG_RTF_FILLED)) { - ata_dev_dbg(dev, - "missing result TF: can't generate ATA PT sense data\n"); -+ if (qc->err_mask) -+ ata_scsi_set_sense(dev, cmd, ABORTED_COMMAND, 0, 0); - return; - } - -@@ -996,8 +994,8 @@ static void ata_gen_ata_sense(struct ata - - if (!(qc->flags & ATA_QCFLAG_RTF_FILLED)) { - ata_dev_dbg(dev, -- "missing result TF: can't generate sense data\n"); -- return; -+ "Missing result TF: reporting aborted command\n"); -+ goto aborted; - } - - /* Use ata_to_sense_error() to map status register bits -@@ -1008,13 +1006,15 @@ static void ata_gen_ata_sense(struct ata - ata_to_sense_error(tf->status, tf->error, - &sense_key, &asc, &ascq); - ata_scsi_set_sense(dev, cmd, sense_key, asc, ascq); -- } else { -- /* Could not decode error */ -- ata_dev_warn(dev, "could not decode error status 0x%x err_mask 0x%x\n", -- tf->status, qc->err_mask); -- ata_scsi_set_sense(dev, cmd, ABORTED_COMMAND, 0, 0); - return; - } -+ -+ /* Could not decode error */ -+ ata_dev_warn(dev, -+ "Could not decode error 0x%x, status 0x%x (err_mask=0x%x)\n", -+ tf->error, tf->status, qc->err_mask); -+aborted: -+ ata_scsi_set_sense(dev, cmd, ABORTED_COMMAND, 0, 0); - } - - void ata_scsi_sdev_config(struct scsi_device *sdev) -@@ -3905,21 +3905,16 @@ static int ata_mselect_control_ata_featu - /* Check cdl_ctrl */ - switch (buf[0] & 0x03) { - case 0: -- /* Disable CDL if it is enabled */ -- if (!(dev->flags & ATA_DFLAG_CDL_ENABLED)) -- return 0; -+ /* Disable CDL */ - ata_dev_dbg(dev, "Disabling CDL\n"); - cdl_action = 0; - dev->flags &= ~ATA_DFLAG_CDL_ENABLED; - break; - case 0x02: - /* -- * Enable CDL if not already enabled. Since this is mutually -- * exclusive with NCQ priority, allow this only if NCQ priority -- * is disabled. -+ * Enable CDL. Since CDL is mutually exclusive with NCQ -+ * priority, allow this only if NCQ priority is disabled. - */ -- if (dev->flags & ATA_DFLAG_CDL_ENABLED) -- return 0; - if (dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLED) { - ata_dev_err(dev, - "NCQ priority must be disabled to enable CDL\n"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/ata/pata_cs5536.c BPI-Router-Linux-kernel-6.16.12/drivers/ata/pata_cs5536.c ---- BPI-Router-Linux-kernel/drivers/ata/pata_cs5536.c 2025-10-22 13:53:23.159329393 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/ata/pata_cs5536.c 2025-10-22 13:53:56.411169643 -0400 -@@ -27,7 +27,7 @@ - #include - #include - --#ifdef CONFIG_X86_32 -+#if defined(CONFIG_X86) && defined(CONFIG_X86_32) - #include - static int use_msr; - module_param_named(msr, use_msr, int, 0644); -diff -purNx .git BPI-Router-Linux-kernel/drivers/ata/pata_macio.c BPI-Router-Linux-kernel-6.16.12/drivers/ata/pata_macio.c ---- BPI-Router-Linux-kernel/drivers/ata/pata_macio.c 2025-10-22 13:53:23.163329374 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/ata/pata_macio.c 2025-10-22 13:53:56.411169643 -0400 -@@ -1298,7 +1298,7 @@ static int pata_macio_pci_attach(struct - priv->dev = &pdev->dev; - - /* Get MMIO regions */ -- if (pci_request_regions(pdev, "pata-macio")) { -+ if (pcim_request_all_regions(pdev, "pata-macio")) { - dev_err(&pdev->dev, - "Cannot obtain PCI resources\n"); - return -EBUSY; -diff -purNx .git BPI-Router-Linux-kernel/drivers/ata/pata_via.c BPI-Router-Linux-kernel-6.16.12/drivers/ata/pata_via.c ---- BPI-Router-Linux-kernel/drivers/ata/pata_via.c 2025-10-22 13:53:23.163329374 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/ata/pata_via.c 2025-10-22 13:53:56.411169643 -0400 -@@ -201,11 +201,9 @@ static int via_cable_detect(struct ata_p - two drives */ - if (ata66 & (0x10100000 >> (16 * ap->port_no))) - return ATA_CBL_PATA80; -+ - /* Check with ACPI so we can spot BIOS reported SATA bridges */ -- if (ata_acpi_init_gtm(ap) && -- ata_acpi_cbl_80wire(ap, ata_acpi_init_gtm(ap))) -- return ATA_CBL_PATA80; -- return ATA_CBL_PATA40; -+ return ata_acpi_cbl_pata_type(ap); - } - - static int via_pre_reset(struct ata_link *link, unsigned long deadline) -@@ -368,7 +366,8 @@ static unsigned int via_mode_filter(stru - } - - if (dev->class == ATA_DEV_ATAPI && -- dmi_check_system(no_atapi_dma_dmi_table)) { -+ (dmi_check_system(no_atapi_dma_dmi_table) || -+ config->id == PCI_DEVICE_ID_VIA_6415)) { - ata_dev_warn(dev, "controller locks up on ATAPI DMA, forcing PIO\n"); - mask &= ATA_MASK_PIO; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/atm/atmtcp.c BPI-Router-Linux-kernel-6.16.12/drivers/atm/atmtcp.c ---- BPI-Router-Linux-kernel/drivers/atm/atmtcp.c 2025-10-22 13:53:23.163329374 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/atm/atmtcp.c 2025-10-22 13:53:56.411169643 -0400 -@@ -279,6 +279,19 @@ static struct atm_vcc *find_vcc(struct a - return NULL; - } - -+static int atmtcp_c_pre_send(struct atm_vcc *vcc, struct sk_buff *skb) -+{ -+ struct atmtcp_hdr *hdr; -+ -+ if (skb->len < sizeof(struct atmtcp_hdr)) -+ return -EINVAL; -+ -+ hdr = (struct atmtcp_hdr *)skb->data; -+ if (hdr->length == ATMTCP_HDR_MAGIC) -+ return -EINVAL; -+ -+ return 0; -+} - - static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) - { -@@ -288,7 +301,6 @@ static int atmtcp_c_send(struct atm_vcc - struct sk_buff *new_skb; - int result = 0; - -- if (!skb->len) return 0; - dev = vcc->dev_data; - hdr = (struct atmtcp_hdr *) skb->data; - if (hdr->length == ATMTCP_HDR_MAGIC) { -@@ -345,6 +357,7 @@ static const struct atmdev_ops atmtcp_v_ - - static const struct atmdev_ops atmtcp_c_dev_ops = { - .close = atmtcp_c_close, -+ .pre_send = atmtcp_c_pre_send, - .send = atmtcp_c_send - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/atm/idt77252.c BPI-Router-Linux-kernel-6.16.12/drivers/atm/idt77252.c ---- BPI-Router-Linux-kernel/drivers/atm/idt77252.c 2025-10-22 13:53:23.163329374 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/atm/idt77252.c 2025-10-22 13:53:56.411169643 -0400 -@@ -852,6 +852,8 @@ queue_skb(struct idt77252_dev *card, str - - IDT77252_PRV_PADDR(skb) = dma_map_single(&card->pcidev->dev, skb->data, - skb->len, DMA_TO_DEVICE); -+ if (dma_mapping_error(&card->pcidev->dev, IDT77252_PRV_PADDR(skb))) -+ return -ENOMEM; - - error = -EINVAL; - -@@ -1857,6 +1859,8 @@ add_rx_skb(struct idt77252_dev *card, in - paddr = dma_map_single(&card->pcidev->dev, skb->data, - skb_end_pointer(skb) - skb->data, - DMA_FROM_DEVICE); -+ if (dma_mapping_error(&card->pcidev->dev, paddr)) -+ goto outpoolrm; - IDT77252_PRV_PADDR(skb) = paddr; - - if (push_rx_skb(card, skb, queue)) { -@@ -1871,6 +1875,7 @@ outunmap: - dma_unmap_single(&card->pcidev->dev, IDT77252_PRV_PADDR(skb), - skb_end_pointer(skb) - skb->data, DMA_FROM_DEVICE); - -+outpoolrm: - handle = IDT77252_PRV_POOL(skb); - card->sbpool[POOL_QUEUE(handle)].skb[POOL_INDEX(handle)] = NULL; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/base/auxiliary.c BPI-Router-Linux-kernel-6.16.12/drivers/base/auxiliary.c ---- BPI-Router-Linux-kernel/drivers/base/auxiliary.c 2025-10-22 13:53:23.163329374 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/base/auxiliary.c 2025-10-22 13:53:56.411169643 -0400 -@@ -399,6 +399,7 @@ static void auxiliary_device_release(str - { - struct auxiliary_device *auxdev = to_auxiliary_dev(dev); - -+ of_node_put(dev->of_node); - kfree(auxdev); - } - -@@ -435,6 +436,7 @@ struct auxiliary_device *auxiliary_devic - - ret = auxiliary_device_init(auxdev); - if (ret) { -+ of_node_put(auxdev->dev.of_node); - kfree(auxdev); - return NULL; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/base/cpu.c BPI-Router-Linux-kernel-6.16.12/drivers/base/cpu.c ---- BPI-Router-Linux-kernel/drivers/base/cpu.c 2025-10-22 13:53:23.163329374 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/base/cpu.c 2025-10-22 13:53:56.411169643 -0400 -@@ -602,6 +602,8 @@ CPU_SHOW_VULN_FALLBACK(reg_file_data_sam - CPU_SHOW_VULN_FALLBACK(ghostwrite); - CPU_SHOW_VULN_FALLBACK(old_microcode); - CPU_SHOW_VULN_FALLBACK(indirect_target_selection); -+CPU_SHOW_VULN_FALLBACK(tsa); -+CPU_SHOW_VULN_FALLBACK(vmscape); - - static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL); - static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL); -@@ -620,6 +622,8 @@ static DEVICE_ATTR(reg_file_data_samplin - static DEVICE_ATTR(ghostwrite, 0444, cpu_show_ghostwrite, NULL); - static DEVICE_ATTR(old_microcode, 0444, cpu_show_old_microcode, NULL); - static DEVICE_ATTR(indirect_target_selection, 0444, cpu_show_indirect_target_selection, NULL); -+static DEVICE_ATTR(tsa, 0444, cpu_show_tsa, NULL); -+static DEVICE_ATTR(vmscape, 0444, cpu_show_vmscape, NULL); - - static struct attribute *cpu_root_vulnerabilities_attrs[] = { - &dev_attr_meltdown.attr, -@@ -639,6 +643,8 @@ static struct attribute *cpu_root_vulner - &dev_attr_ghostwrite.attr, - &dev_attr_old_microcode.attr, - &dev_attr_indirect_target_selection.attr, -+ &dev_attr_tsa.attr, -+ &dev_attr_vmscape.attr, - NULL - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/base/faux.c BPI-Router-Linux-kernel-6.16.12/drivers/base/faux.c ---- BPI-Router-Linux-kernel/drivers/base/faux.c 2025-10-22 13:53:23.163329374 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/base/faux.c 2025-10-22 13:53:56.411169643 -0400 -@@ -86,6 +86,7 @@ static struct device_driver faux_driver - .name = "faux_driver", - .bus = &faux_bus_type, - .probe_type = PROBE_FORCE_SYNCHRONOUS, -+ .suppress_bind_attrs = true, - }; - - static void faux_device_release(struct device *dev) -@@ -154,6 +155,7 @@ struct faux_device *faux_device_create_w - dev->parent = &faux_bus_root; - dev->bus = &faux_bus_type; - dev_set_name(dev, "%s", name); -+ device_set_pm_not_required(dev); - - ret = device_add(dev); - if (ret) { -@@ -169,7 +171,7 @@ struct faux_device *faux_device_create_w - * successful is almost impossible to determine by the caller. - */ - if (!dev->driver) { -- dev_err(dev, "probe did not succeed, tearing down the device\n"); -+ dev_dbg(dev, "probe did not succeed, tearing down the device\n"); - faux_device_destroy(faux_dev); - faux_dev = NULL; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/base/power/main.c BPI-Router-Linux-kernel-6.16.12/drivers/base/power/main.c ---- BPI-Router-Linux-kernel/drivers/base/power/main.c 2025-10-22 13:53:23.163329374 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/base/power/main.c 2025-10-22 13:53:56.411169643 -0400 -@@ -1237,6 +1237,7 @@ void dpm_complete(pm_message_t state) - void dpm_resume_end(pm_message_t state) - { - dpm_resume(state); -+ pm_restore_gfp_mask(); - dpm_complete(state); - } - EXPORT_SYMBOL_GPL(dpm_resume_end); -@@ -1279,6 +1280,22 @@ static void dpm_async_suspend_parent(str - dpm_async_with_cleanup(dev->parent, func); - } - -+static void dpm_async_suspend_complete_all(struct list_head *device_list) -+{ -+ struct device *dev; -+ -+ guard(mutex)(&async_wip_mtx); -+ -+ list_for_each_entry_reverse(dev, device_list, power.entry) { -+ /* -+ * In case the device is being waited for and async processing -+ * has not started for it yet, let the waiters make progress. -+ */ -+ if (!dev->power.work_in_progress) -+ complete_all(&dev->power.completion); -+ } -+} -+ - /** - * resume_event - Return a "resume" message for given "suspend" sleep state. - * @sleep_state: PM message representing a sleep state. -@@ -1455,6 +1472,7 @@ static int dpm_noirq_suspend_devices(pm_ - mutex_lock(&dpm_list_mtx); - - if (error || async_error) { -+ dpm_async_suspend_complete_all(&dpm_late_early_list); - /* - * Move all devices to the target list to resume them - * properly. -@@ -1657,6 +1675,7 @@ int dpm_suspend_late(pm_message_t state) - mutex_lock(&dpm_list_mtx); - - if (error || async_error) { -+ dpm_async_suspend_complete_all(&dpm_suspended_list); - /* - * Move all devices to the target list to resume them - * properly. -@@ -1950,6 +1969,7 @@ int dpm_suspend(pm_message_t state) - mutex_lock(&dpm_list_mtx); - - if (error || async_error) { -+ dpm_async_suspend_complete_all(&dpm_prepared_list); - /* - * Move all devices to the target list to resume them - * properly. -@@ -2176,8 +2196,10 @@ int dpm_suspend_start(pm_message_t state - error = dpm_prepare(state); - if (error) - dpm_save_failed_step(SUSPEND_PREPARE); -- else -+ else { -+ pm_restrict_gfp_mask(); - error = dpm_suspend(state); -+ } - - dpm_show_time(starttime, state, error, "start"); - return error; -diff -purNx .git BPI-Router-Linux-kernel/drivers/base/power/runtime.c BPI-Router-Linux-kernel-6.16.12/drivers/base/power/runtime.c ---- BPI-Router-Linux-kernel/drivers/base/power/runtime.c 2025-10-22 13:53:23.163329374 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/base/power/runtime.c 2025-10-22 13:53:56.411169643 -0400 -@@ -1191,10 +1191,12 @@ EXPORT_SYMBOL_GPL(__pm_runtime_resume); - * - * Return -EINVAL if runtime PM is disabled for @dev. - * -- * Otherwise, if the runtime PM status of @dev is %RPM_ACTIVE and either -- * @ign_usage_count is %true or the runtime PM usage counter of @dev is not -- * zero, increment the usage counter of @dev and return 1. Otherwise, return 0 -- * without changing the usage counter. -+ * Otherwise, if its runtime PM status is %RPM_ACTIVE and (1) @ign_usage_count -+ * is set, or (2) @dev is not ignoring children and its active child count is -+ * nonero, or (3) the runtime PM usage counter of @dev is not zero, increment -+ * the usage counter of @dev and return 1. -+ * -+ * Otherwise, return 0 without changing the usage counter. - * - * If @ign_usage_count is %true, this function can be used to prevent suspending - * the device when its runtime PM status is %RPM_ACTIVE. -@@ -1216,7 +1218,8 @@ static int pm_runtime_get_conditional(st - retval = -EINVAL; - } else if (dev->power.runtime_status != RPM_ACTIVE) { - retval = 0; -- } else if (ign_usage_count) { -+ } else if (ign_usage_count || (!dev->power.ignore_children && -+ atomic_read(&dev->power.child_count) > 0)) { - retval = 1; - atomic_inc(&dev->power.usage_count); - } else { -@@ -1249,10 +1252,16 @@ EXPORT_SYMBOL_GPL(pm_runtime_get_if_acti - * @dev: Target device. - * - * Increment the runtime PM usage counter of @dev if its runtime PM status is -- * %RPM_ACTIVE and its runtime PM usage counter is greater than 0, in which case -- * it returns 1. If the device is in a different state or its usage_count is 0, -- * 0 is returned. -EINVAL is returned if runtime PM is disabled for the device, -- * in which case also the usage_count will remain unmodified. -+ * %RPM_ACTIVE and its runtime PM usage counter is greater than 0 or it is not -+ * ignoring children and its active child count is nonzero. 1 is returned in -+ * this case. -+ * -+ * If @dev is in a different state or it is not in use (that is, its usage -+ * counter is 0, or it is ignoring children, or its active child count is 0), -+ * 0 is returned. -+ * -+ * -EINVAL is returned if runtime PM is disabled for the device, in which case -+ * also the usage counter of @dev is not updated. - */ - int pm_runtime_get_if_in_use(struct device *dev) - { -@@ -1854,6 +1863,11 @@ void pm_runtime_reinit(struct device *de - pm_runtime_put(dev->parent); - } - } -+ /* -+ * Clear power.needs_force_resume in case it has been set by -+ * pm_runtime_force_suspend() invoked from a driver remove callback. -+ */ -+ dev->power.needs_force_resume = false; - } - - /** -diff -purNx .git BPI-Router-Linux-kernel/drivers/base/regmap/regmap.c BPI-Router-Linux-kernel-6.16.12/drivers/base/regmap/regmap.c ---- BPI-Router-Linux-kernel/drivers/base/regmap/regmap.c 2025-10-22 13:53:23.163329374 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/base/regmap/regmap.c 2025-10-22 13:53:56.411169643 -0400 -@@ -1173,6 +1173,8 @@ err_name: - err_map: - kfree(map); - err: -+ if (bus && bus->free_on_exit) -+ kfree(bus); - return ERR_PTR(ret); - } - EXPORT_SYMBOL_GPL(__regmap_init); -diff -purNx .git BPI-Router-Linux-kernel/drivers/base/regmap/regmap-irq.c BPI-Router-Linux-kernel-6.16.12/drivers/base/regmap/regmap-irq.c ---- BPI-Router-Linux-kernel/drivers/base/regmap/regmap-irq.c 2025-10-22 13:53:23.163329374 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/base/regmap/regmap-irq.c 2025-10-22 13:53:56.411169643 -0400 -@@ -816,7 +816,7 @@ int regmap_add_irq_chip_fwnode(struct fw - d->mask_buf[i], - chip->irq_drv_data); - if (ret) -- goto err_alloc; -+ goto err_mutex; - } - - if (chip->mask_base && !chip->handle_mask_sync) { -@@ -827,7 +827,7 @@ int regmap_add_irq_chip_fwnode(struct fw - if (ret) { - dev_err(map->dev, "Failed to set masks in 0x%x: %d\n", - reg, ret); -- goto err_alloc; -+ goto err_mutex; - } - } - -@@ -838,7 +838,7 @@ int regmap_add_irq_chip_fwnode(struct fw - if (ret) { - dev_err(map->dev, "Failed to set masks in 0x%x: %d\n", - reg, ret); -- goto err_alloc; -+ goto err_mutex; - } - } - -@@ -855,7 +855,7 @@ int regmap_add_irq_chip_fwnode(struct fw - if (ret != 0) { - dev_err(map->dev, "Failed to read IRQ status: %d\n", - ret); -- goto err_alloc; -+ goto err_mutex; - } - } - -@@ -879,7 +879,7 @@ int regmap_add_irq_chip_fwnode(struct fw - if (ret != 0) { - dev_err(map->dev, "Failed to ack 0x%x: %d\n", - reg, ret); -- goto err_alloc; -+ goto err_mutex; - } - } - } -@@ -901,7 +901,7 @@ int regmap_add_irq_chip_fwnode(struct fw - if (ret != 0) { - dev_err(map->dev, "Failed to set masks in 0x%x: %d\n", - reg, ret); -- goto err_alloc; -+ goto err_mutex; - } - } - } -@@ -910,7 +910,7 @@ int regmap_add_irq_chip_fwnode(struct fw - if (chip->status_is_level) { - ret = read_irq_data(d); - if (ret < 0) -- goto err_alloc; -+ goto err_mutex; - - memcpy(d->prev_status_buf, d->status_buf, - array_size(d->chip->num_regs, sizeof(d->prev_status_buf[0]))); -@@ -918,7 +918,7 @@ int regmap_add_irq_chip_fwnode(struct fw - - ret = regmap_irq_create_domain(fwnode, irq_base, chip, d); - if (ret) -- goto err_alloc; -+ goto err_mutex; - - ret = request_threaded_irq(irq, NULL, regmap_irq_thread, - irq_flags | IRQF_ONESHOT, -@@ -935,6 +935,8 @@ int regmap_add_irq_chip_fwnode(struct fw - - err_domain: - /* Should really dispose of the domain but... */ -+err_mutex: -+ mutex_destroy(&d->lock); - err_alloc: - kfree(d->type_buf); - kfree(d->type_buf_def); -@@ -1027,6 +1029,7 @@ void regmap_del_irq_chip(int irq, struct - kfree(d->config_buf[i]); - kfree(d->config_buf); - } -+ mutex_destroy(&d->lock); - kfree(d); - } - EXPORT_SYMBOL_GPL(regmap_del_irq_chip); -diff -purNx .git BPI-Router-Linux-kernel/drivers/block/aoe/aoecmd.c BPI-Router-Linux-kernel-6.16.12/drivers/block/aoe/aoecmd.c ---- BPI-Router-Linux-kernel/drivers/block/aoe/aoecmd.c 2025-10-22 13:53:23.163329374 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/block/aoe/aoecmd.c 2025-10-22 13:53:56.411169643 -0400 -@@ -754,7 +754,7 @@ rexmit_timer(struct timer_list *timer) - - utgts = count_targets(d, NULL); - -- if (d->flags & DEVFL_TKILL) { -+ if (d->flags & (DEVFL_TKILL | DEVFL_DEAD)) { - spin_unlock_irqrestore(&d->lock, flags); - return; - } -@@ -786,7 +786,8 @@ rexmit_timer(struct timer_list *timer) - * to clean up. - */ - list_splice(&flist, &d->factive[0]); -- aoedev_downdev(d); -+ d->flags |= DEVFL_DEAD; -+ queue_work(aoe_wq, &d->work); - goto out; - } - -@@ -898,6 +899,9 @@ aoecmd_sleepwork(struct work_struct *wor - { - struct aoedev *d = container_of(work, struct aoedev, work); - -+ if (d->flags & DEVFL_DEAD) -+ aoedev_downdev(d); -+ - if (d->flags & DEVFL_GDALLOC) - aoeblk_gdalloc(d); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/block/aoe/aoedev.c BPI-Router-Linux-kernel-6.16.12/drivers/block/aoe/aoedev.c ---- BPI-Router-Linux-kernel/drivers/block/aoe/aoedev.c 2025-10-22 13:53:23.163329374 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/block/aoe/aoedev.c 2025-10-22 13:53:56.411169643 -0400 -@@ -198,9 +198,13 @@ aoedev_downdev(struct aoedev *d) - { - struct aoetgt *t, **tt, **te; - struct list_head *head, *pos, *nx; -+ struct request *rq, *rqnext; - int i; -+ unsigned long flags; - -- d->flags &= ~DEVFL_UP; -+ spin_lock_irqsave(&d->lock, flags); -+ d->flags &= ~(DEVFL_UP | DEVFL_DEAD); -+ spin_unlock_irqrestore(&d->lock, flags); - - /* clean out active and to-be-retransmitted buffers */ - for (i = 0; i < NFACTIVE; i++) { -@@ -223,6 +227,13 @@ aoedev_downdev(struct aoedev *d) - /* clean out the in-process request (if any) */ - aoe_failip(d); - -+ /* clean out any queued block requests */ -+ list_for_each_entry_safe(rq, rqnext, &d->rq_list, queuelist) { -+ list_del_init(&rq->queuelist); -+ blk_mq_start_request(rq); -+ blk_mq_end_request(rq, BLK_STS_IOERR); -+ } -+ - /* fast fail all pending I/O */ - if (d->blkq) { - /* UP is cleared, freeze+quiesce to insure all are errored */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/block/aoe/aoe.h BPI-Router-Linux-kernel-6.16.12/drivers/block/aoe/aoe.h ---- BPI-Router-Linux-kernel/drivers/block/aoe/aoe.h 2025-10-22 13:53:23.163329374 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/block/aoe/aoe.h 2025-10-22 13:53:56.411169643 -0400 -@@ -80,6 +80,7 @@ enum { - DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */ - DEVFL_FREEING = (1<<7), /* set when device is being cleaned up */ - DEVFL_FREED = (1<<8), /* device has been cleaned up */ -+ DEVFL_DEAD = (1<<9), /* device has timed out of aoe_deadsecs */ - }; - - enum { -diff -purNx .git BPI-Router-Linux-kernel/drivers/block/brd.c BPI-Router-Linux-kernel-6.16.12/drivers/block/brd.c ---- BPI-Router-Linux-kernel/drivers/block/brd.c 2025-10-22 13:53:23.163329374 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/block/brd.c 2025-10-22 13:53:56.411169643 -0400 -@@ -64,13 +64,15 @@ static struct page *brd_insert_page(stru - - rcu_read_unlock(); - page = alloc_page(gfp | __GFP_ZERO | __GFP_HIGHMEM); -- rcu_read_lock(); -- if (!page) -+ if (!page) { -+ rcu_read_lock(); - return ERR_PTR(-ENOMEM); -+ } - - xa_lock(&brd->brd_pages); - ret = __xa_cmpxchg(&brd->brd_pages, sector >> PAGE_SECTORS_SHIFT, NULL, - page, gfp); -+ rcu_read_lock(); - if (ret) { - xa_unlock(&brd->brd_pages); - __free_page(page); -diff -purNx .git BPI-Router-Linux-kernel/drivers/block/drbd/drbd_receiver.c BPI-Router-Linux-kernel-6.16.12/drivers/block/drbd/drbd_receiver.c ---- BPI-Router-Linux-kernel/drivers/block/drbd/drbd_receiver.c 2025-10-22 13:53:23.163329374 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/block/drbd/drbd_receiver.c 2025-10-22 13:53:56.411169643 -0400 -@@ -2500,7 +2500,11 @@ static int handle_write_conflicts(struct - peer_req->w.cb = superseded ? e_send_superseded : - e_send_retry_write; - list_add_tail(&peer_req->w.list, &device->done_ee); -- queue_work(connection->ack_sender, &peer_req->peer_device->send_acks_work); -+ /* put is in drbd_send_acks_wf() */ -+ kref_get(&device->kref); -+ if (!queue_work(connection->ack_sender, -+ &peer_req->peer_device->send_acks_work)) -+ kref_put(&device->kref, drbd_destroy_device); - - err = -ENOENT; - goto out; -diff -purNx .git BPI-Router-Linux-kernel/drivers/block/loop.c BPI-Router-Linux-kernel-6.16.12/drivers/block/loop.c ---- BPI-Router-Linux-kernel/drivers/block/loop.c 2025-10-22 13:53:23.163329374 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/block/loop.c 2025-10-22 13:53:56.411169643 -0400 -@@ -308,14 +308,13 @@ end_io: - static void lo_rw_aio_do_completion(struct loop_cmd *cmd) - { - struct request *rq = blk_mq_rq_from_pdu(cmd); -- struct loop_device *lo = rq->q->queuedata; - - if (!atomic_dec_and_test(&cmd->ref)) - return; - kfree(cmd->bvec); - cmd->bvec = NULL; - if (req_op(rq) == REQ_OP_WRITE) -- file_end_write(lo->lo_backing_file); -+ kiocb_end_write(&cmd->iocb); - if (likely(!blk_should_fake_timeout(rq->q))) - blk_mq_complete_request(rq); - } -@@ -391,7 +390,7 @@ static int lo_rw_aio(struct loop_device - } - - if (rw == ITER_SOURCE) { -- file_start_write(lo->lo_backing_file); -+ kiocb_start_write(&cmd->iocb); - ret = file->f_op->write_iter(&cmd->iocb, &iter); - } else - ret = file->f_op->read_iter(&cmd->iocb, &iter); -@@ -1248,12 +1247,6 @@ loop_set_status(struct loop_device *lo, - lo->lo_flags &= ~LOOP_SET_STATUS_CLEARABLE_FLAGS; - lo->lo_flags |= (info->lo_flags & LOOP_SET_STATUS_SETTABLE_FLAGS); - -- if (size_changed) { -- loff_t new_size = get_size(lo->lo_offset, lo->lo_sizelimit, -- lo->lo_backing_file); -- loop_set_size(lo, new_size); -- } -- - /* update the direct I/O flag if lo_offset changed */ - loop_update_dio(lo); - -@@ -1261,6 +1254,11 @@ out_unfreeze: - blk_mq_unfreeze_queue(lo->lo_queue, memflags); - if (partscan) - clear_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state); -+ if (!err && size_changed) { -+ loff_t new_size = get_size(lo->lo_offset, lo->lo_sizelimit, -+ lo->lo_backing_file); -+ loop_set_size(lo, new_size); -+ } - out_unlock: - mutex_unlock(&lo->lo_mutex); - if (partscan) -@@ -1433,17 +1431,34 @@ static int loop_set_dio(struct loop_devi - return 0; - } - --static int loop_set_block_size(struct loop_device *lo, unsigned long arg) -+static int loop_set_block_size(struct loop_device *lo, blk_mode_t mode, -+ struct block_device *bdev, unsigned long arg) - { - struct queue_limits lim; - unsigned int memflags; - int err = 0; - -- if (lo->lo_state != Lo_bound) -- return -ENXIO; -+ /* -+ * If we don't hold exclusive handle for the device, upgrade to it -+ * here to avoid changing device under exclusive owner. -+ */ -+ if (!(mode & BLK_OPEN_EXCL)) { -+ err = bd_prepare_to_claim(bdev, loop_set_block_size, NULL); -+ if (err) -+ return err; -+ } -+ -+ err = mutex_lock_killable(&lo->lo_mutex); -+ if (err) -+ goto abort_claim; -+ -+ if (lo->lo_state != Lo_bound) { -+ err = -ENXIO; -+ goto unlock; -+ } - - if (lo->lo_queue->limits.logical_block_size == arg) -- return 0; -+ goto unlock; - - sync_blockdev(lo->lo_device); - invalidate_bdev(lo->lo_device); -@@ -1456,6 +1471,11 @@ static int loop_set_block_size(struct lo - loop_update_dio(lo); - blk_mq_unfreeze_queue(lo->lo_queue, memflags); - -+unlock: -+ mutex_unlock(&lo->lo_mutex); -+abort_claim: -+ if (!(mode & BLK_OPEN_EXCL)) -+ bd_abort_claiming(bdev, loop_set_block_size); - return err; - } - -@@ -1474,9 +1494,6 @@ static int lo_simple_ioctl(struct loop_d - case LOOP_SET_DIRECT_IO: - err = loop_set_dio(lo, arg); - break; -- case LOOP_SET_BLOCK_SIZE: -- err = loop_set_block_size(lo, arg); -- break; - default: - err = -EINVAL; - } -@@ -1531,9 +1548,12 @@ static int lo_ioctl(struct block_device - break; - case LOOP_GET_STATUS64: - return loop_get_status64(lo, argp); -+ case LOOP_SET_BLOCK_SIZE: -+ if (!(mode & BLK_OPEN_WRITE) && !capable(CAP_SYS_ADMIN)) -+ return -EPERM; -+ return loop_set_block_size(lo, mode, bdev, arg); - case LOOP_SET_CAPACITY: - case LOOP_SET_DIRECT_IO: -- case LOOP_SET_BLOCK_SIZE: - if (!(mode & BLK_OPEN_WRITE) && !capable(CAP_SYS_ADMIN)) - return -EPERM; - fallthrough; -diff -purNx .git BPI-Router-Linux-kernel/drivers/block/mtip32xx/mtip32xx.c BPI-Router-Linux-kernel-6.16.12/drivers/block/mtip32xx/mtip32xx.c ---- BPI-Router-Linux-kernel/drivers/block/mtip32xx/mtip32xx.c 2025-10-22 13:53:23.167329355 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/block/mtip32xx/mtip32xx.c 2025-10-22 13:53:56.415169623 -0400 -@@ -2040,11 +2040,12 @@ static int mtip_hw_ioctl(struct driver_d - * @dir Direction (read or write) - * - * return value -- * None -+ * 0 The IO completed successfully. -+ * -ENOMEM The DMA mapping failed. - */ --static void mtip_hw_submit_io(struct driver_data *dd, struct request *rq, -- struct mtip_cmd *command, -- struct blk_mq_hw_ctx *hctx) -+static int mtip_hw_submit_io(struct driver_data *dd, struct request *rq, -+ struct mtip_cmd *command, -+ struct blk_mq_hw_ctx *hctx) - { - struct mtip_cmd_hdr *hdr = - dd->port->command_list + sizeof(struct mtip_cmd_hdr) * rq->tag; -@@ -2056,12 +2057,14 @@ static void mtip_hw_submit_io(struct dri - unsigned int nents; - - /* Map the scatter list for DMA access */ -- nents = blk_rq_map_sg(rq, command->sg); -- nents = dma_map_sg(&dd->pdev->dev, command->sg, nents, dma_dir); -+ command->scatter_ents = blk_rq_map_sg(rq, command->sg); -+ nents = dma_map_sg(&dd->pdev->dev, command->sg, -+ command->scatter_ents, dma_dir); -+ if (!nents) -+ return -ENOMEM; - -- prefetch(&port->flags); - -- command->scatter_ents = nents; -+ prefetch(&port->flags); - - /* - * The number of retries for this command before it is -@@ -2112,11 +2115,13 @@ static void mtip_hw_submit_io(struct dri - if (unlikely(port->flags & MTIP_PF_PAUSE_IO)) { - set_bit(rq->tag, port->cmds_to_issue); - set_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags); -- return; -+ return 0; - } - - /* Issue the command to the hardware */ - mtip_issue_ncq_command(port, rq->tag); -+ -+ return 0; - } - - /* -@@ -3315,7 +3320,9 @@ static blk_status_t mtip_queue_rq(struct - - blk_mq_start_request(rq); - -- mtip_hw_submit_io(dd, rq, cmd, hctx); -+ if (mtip_hw_submit_io(dd, rq, cmd, hctx)) -+ return BLK_STS_IOERR; -+ - return BLK_STS_OK; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/block/nbd.c BPI-Router-Linux-kernel-6.16.12/drivers/block/nbd.c ---- BPI-Router-Linux-kernel/drivers/block/nbd.c 2025-10-22 13:53:23.167329355 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/block/nbd.c 2025-10-22 13:53:56.415169623 -0400 -@@ -1473,7 +1473,17 @@ static int nbd_start_device(struct nbd_d - return -EINVAL; - } - -- blk_mq_update_nr_hw_queues(&nbd->tag_set, config->num_connections); -+retry: -+ mutex_unlock(&nbd->config_lock); -+ blk_mq_update_nr_hw_queues(&nbd->tag_set, num_connections); -+ mutex_lock(&nbd->config_lock); -+ -+ /* if another code path updated nr_hw_queues, retry until succeed */ -+ if (num_connections != config->num_connections) { -+ num_connections = config->num_connections; -+ goto retry; -+ } -+ - nbd->pid = task_pid_nr(current); - - nbd_parse_flags(nbd); -@@ -2198,9 +2208,7 @@ again: - goto out; - } - } -- ret = nbd_start_device(nbd); -- if (ret) -- goto out; -+ - if (info->attrs[NBD_ATTR_BACKEND_IDENTIFIER]) { - nbd->backend = nla_strdup(info->attrs[NBD_ATTR_BACKEND_IDENTIFIER], - GFP_KERNEL); -@@ -2216,6 +2224,8 @@ again: - goto out; - } - set_bit(NBD_RT_HAS_BACKEND_FILE, &config->runtime_flags); -+ -+ ret = nbd_start_device(nbd); - out: - mutex_unlock(&nbd->config_lock); - if (!ret) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/block/sunvdc.c BPI-Router-Linux-kernel-6.16.12/drivers/block/sunvdc.c ---- BPI-Router-Linux-kernel/drivers/block/sunvdc.c 2025-10-22 13:53:23.167329355 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/block/sunvdc.c 2025-10-22 13:53:56.415169623 -0400 -@@ -957,8 +957,10 @@ static bool vdc_port_mpgroup_check(struc - dev = device_find_child(vdev->dev.parent, &port_data, - vdc_device_probed); - -- if (dev) -+ if (dev) { -+ put_device(dev); - return true; -+ } - - return false; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/block/ublk_drv.c BPI-Router-Linux-kernel-6.16.12/drivers/block/ublk_drv.c ---- BPI-Router-Linux-kernel/drivers/block/ublk_drv.c 2025-10-22 13:53:23.167329355 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/block/ublk_drv.c 2025-10-22 13:53:56.415169623 -0400 -@@ -215,7 +215,10 @@ struct ublk_device { - - struct completion completion; - unsigned int nr_queues_ready; -- unsigned int nr_privileged_daemon; -+ bool unprivileged_daemons; -+ struct mutex cancel_mutex; -+ bool canceling; -+ pid_t ublksrv_tgid; - }; - - /* header of ublk_params */ -@@ -1148,8 +1151,8 @@ exit: - blk_mq_end_request(req, res); - } - --static void ublk_complete_io_cmd(struct ublk_io *io, struct request *req, -- int res, unsigned issue_flags) -+static struct io_uring_cmd *__ublk_prep_compl_io_cmd(struct ublk_io *io, -+ struct request *req) - { - /* read cmd first because req will overwrite it */ - struct io_uring_cmd *cmd = io->cmd; -@@ -1164,6 +1167,13 @@ static void ublk_complete_io_cmd(struct - io->flags &= ~UBLK_IO_FLAG_ACTIVE; - - io->req = req; -+ return cmd; -+} -+ -+static void ublk_complete_io_cmd(struct ublk_io *io, struct request *req, -+ int res, unsigned issue_flags) -+{ -+ struct io_uring_cmd *cmd = __ublk_prep_compl_io_cmd(io, req); - - /* tell ublksrv one io request is coming */ - io_uring_cmd_done(cmd, res, 0, issue_flags); -@@ -1416,6 +1426,14 @@ static blk_status_t ublk_queue_rq(struct - return BLK_STS_OK; - } - -+static inline bool ublk_belong_to_same_batch(const struct ublk_io *io, -+ const struct ublk_io *io2) -+{ -+ return (io_uring_cmd_ctx_handle(io->cmd) == -+ io_uring_cmd_ctx_handle(io2->cmd)) && -+ (io->task == io2->task); -+} -+ - static void ublk_queue_rqs(struct rq_list *rqlist) - { - struct rq_list requeue_list = { }; -@@ -1427,14 +1445,16 @@ static void ublk_queue_rqs(struct rq_lis - struct ublk_queue *this_q = req->mq_hctx->driver_data; - struct ublk_io *this_io = &this_q->ios[req->tag]; - -- if (io && io->task != this_io->task && !rq_list_empty(&submit_list)) -+ if (ublk_prep_req(this_q, req, true) != BLK_STS_OK) { -+ rq_list_add_tail(&requeue_list, req); -+ continue; -+ } -+ -+ if (io && !ublk_belong_to_same_batch(io, this_io) && -+ !rq_list_empty(&submit_list)) - ublk_queue_cmd_list(io, &submit_list); - io = this_io; -- -- if (ublk_prep_req(this_q, req, true) == BLK_STS_OK) -- rq_list_add_tail(&submit_list, req); -- else -- rq_list_add_tail(&requeue_list, req); -+ rq_list_add_tail(&submit_list, req); - } - - if (!rq_list_empty(&submit_list)) -@@ -1498,6 +1518,7 @@ static int ublk_ch_open(struct inode *in - if (test_and_set_bit(UB_STATE_OPEN, &ub->state)) - return -EBUSY; - filp->private_data = ub; -+ ub->ublksrv_tgid = current->tgid; - return 0; - } - -@@ -1511,7 +1532,8 @@ static void ublk_reset_ch_dev(struct ubl - /* set to NULL, otherwise new tasks cannot mmap io_cmd_buf */ - ub->mm = NULL; - ub->nr_queues_ready = 0; -- ub->nr_privileged_daemon = 0; -+ ub->unprivileged_daemons = false; -+ ub->ublksrv_tgid = -1; - } - - static struct gendisk *ublk_get_disk(struct ublk_device *ub) -@@ -1561,6 +1583,7 @@ static int ublk_ch_release(struct inode - * All requests may be inflight, so ->canceling may not be set, set - * it now. - */ -+ ub->canceling = true; - for (i = 0; i < ub->dev_info.nr_hw_queues; i++) { - struct ublk_queue *ubq = ublk_get_queue(ub, i); - -@@ -1689,23 +1712,18 @@ static void ublk_abort_queue(struct ublk - } - } - --/* Must be called when queue is frozen */ --static void ublk_mark_queue_canceling(struct ublk_queue *ubq) -+static void ublk_start_cancel(struct ublk_device *ub) - { -- spin_lock(&ubq->cancel_lock); -- if (!ubq->canceling) -- ubq->canceling = true; -- spin_unlock(&ubq->cancel_lock); --} -- --static void ublk_start_cancel(struct ublk_queue *ubq) --{ -- struct ublk_device *ub = ubq->dev; - struct gendisk *disk = ublk_get_disk(ub); -+ int i; - - /* Our disk has been dead */ - if (!disk) - return; -+ -+ mutex_lock(&ub->cancel_mutex); -+ if (ub->canceling) -+ goto out; - /* - * Now we are serialized with ublk_queue_rq() - * -@@ -1714,8 +1732,12 @@ static void ublk_start_cancel(struct ubl - * touch completed uring_cmd - */ - blk_mq_quiesce_queue(disk->queue); -- ublk_mark_queue_canceling(ubq); -+ ub->canceling = true; -+ for (i = 0; i < ub->dev_info.nr_hw_queues; i++) -+ ublk_get_queue(ub, i)->canceling = true; - blk_mq_unquiesce_queue(disk->queue); -+out: -+ mutex_unlock(&ub->cancel_mutex); - ublk_put_disk(disk); - } - -@@ -1788,8 +1810,7 @@ static void ublk_uring_cmd_cancel_fn(str - if (WARN_ON_ONCE(task && task != io->task)) - return; - -- if (!ubq->canceling) -- ublk_start_cancel(ubq); -+ ublk_start_cancel(ubq->dev); - - WARN_ON_ONCE(io->cmd != cmd); - ublk_cancel_cmd(ubq, pdu->tag, issue_flags); -@@ -1916,6 +1937,7 @@ static void ublk_reset_io_flags(struct u - ubq->canceling = false; - ubq->fail_io = false; - } -+ ub->canceling = false; - } - - /* device can only be started after all IOs are ready */ -@@ -1923,12 +1945,10 @@ static void ublk_mark_io_ready(struct ub - __must_hold(&ub->mutex) - { - ubq->nr_io_ready++; -- if (ublk_queue_ready(ubq)) { -+ if (ublk_queue_ready(ubq)) - ub->nr_queues_ready++; -- -- if (capable(CAP_SYS_ADMIN)) -- ub->nr_privileged_daemon++; -- } -+ if (!ub->unprivileged_daemons && !capable(CAP_SYS_ADMIN)) -+ ub->unprivileged_daemons = true; - - if (ub->nr_queues_ready == ub->dev_info.nr_hw_queues) { - /* now we are ready for handling ublk io request */ -@@ -2148,10 +2168,9 @@ static int ublk_commit_and_fetch(const s - return 0; - } - --static bool ublk_get_data(const struct ublk_queue *ubq, struct ublk_io *io) -+static bool ublk_get_data(const struct ublk_queue *ubq, struct ublk_io *io, -+ struct request *req) - { -- struct request *req = io->req; -- - /* - * We have handled UBLK_IO_NEED_GET_DATA command, - * so clear UBLK_IO_FLAG_NEED_GET_DATA now and just -@@ -2178,6 +2197,7 @@ static int __ublk_ch_uring_cmd(struct io - u32 cmd_op = cmd->cmd_op; - unsigned tag = ub_cmd->tag; - int ret = -EINVAL; -+ struct request *req; - - pr_devel("%s: received: cmd op %d queue %d tag %d result %d\n", - __func__, cmd->cmd_op, ub_cmd->q_id, tag, -@@ -2236,11 +2256,19 @@ static int __ublk_ch_uring_cmd(struct io - goto out; - break; - case UBLK_IO_NEED_GET_DATA: -- io->addr = ub_cmd->addr; -- if (!ublk_get_data(ubq, io)) -- return -EIOCBQUEUED; -- -- return UBLK_IO_RES_OK; -+ /* -+ * ublk_get_data() may fail and fallback to requeue, so keep -+ * uring_cmd active first and prepare for handling new requeued -+ * request -+ */ -+ req = io->req; -+ ublk_fill_io_cmd(io, cmd, ub_cmd->addr); -+ io->flags &= ~UBLK_IO_FLAG_OWNED_BY_SRV; -+ if (likely(ublk_get_data(ubq, io, req))) { -+ __ublk_prep_compl_io_cmd(io, req); -+ return UBLK_IO_RES_OK; -+ } -+ break; - default: - goto out; - } -@@ -2488,7 +2516,7 @@ static void ublk_deinit_queues(struct ub - - for (i = 0; i < nr_queues; i++) - ublk_deinit_queue(ub, i); -- kfree(ub->__queues); -+ kvfree(ub->__queues); - } - - static int ublk_init_queues(struct ublk_device *ub) -@@ -2499,7 +2527,7 @@ static int ublk_init_queues(struct ublk_ - int i, ret = -ENOMEM; - - ub->queue_size = ubq_size; -- ub->__queues = kcalloc(nr_queues, ubq_size, GFP_KERNEL); -+ ub->__queues = kvcalloc(nr_queues, ubq_size, GFP_KERNEL); - if (!ub->__queues) - return ret; - -@@ -2555,6 +2583,7 @@ static void ublk_cdev_rel(struct device - ublk_deinit_queues(ub); - ublk_free_dev_number(ub); - mutex_destroy(&ub->mutex); -+ mutex_destroy(&ub->cancel_mutex); - kfree(ub); - } - -@@ -2704,6 +2733,9 @@ static int ublk_ctrl_start_dev(struct ub - if (wait_for_completion_interruptible(&ub->completion) != 0) - return -EINTR; - -+ if (ub->ublksrv_tgid != ublksrv_pid) -+ return -EINVAL; -+ - mutex_lock(&ub->mutex); - if (ub->dev_info.state == UBLK_S_DEV_LIVE || - test_bit(UB_STATE_USED, &ub->state)) { -@@ -2725,8 +2757,8 @@ static int ublk_ctrl_start_dev(struct ub - - ublk_apply_params(ub); - -- /* don't probe partitions if any one ubq daemon is un-trusted */ -- if (ub->nr_privileged_daemon != ub->nr_queues_ready) -+ /* don't probe partitions if any daemon task is un-trusted */ -+ if (ub->unprivileged_daemons) - set_bit(GD_SUPPRESS_PART_SCAN, &disk->state); - - ublk_get_device(ub); -@@ -2825,6 +2857,10 @@ static int ublk_ctrl_add_dev(const struc - if (copy_from_user(&info, argp, sizeof(info))) - return -EFAULT; - -+ if (info.queue_depth > UBLK_MAX_QUEUE_DEPTH || !info.queue_depth || -+ info.nr_hw_queues > UBLK_MAX_NR_QUEUES || !info.nr_hw_queues) -+ return -EINVAL; -+ - if (capable(CAP_SYS_ADMIN)) - info.flags &= ~UBLK_F_UNPRIVILEGED_DEV; - else if (!(info.flags & UBLK_F_UNPRIVILEGED_DEV)) -@@ -2904,6 +2940,7 @@ static int ublk_ctrl_add_dev(const struc - goto out_unlock; - mutex_init(&ub->mutex); - spin_lock_init(&ub->lock); -+ mutex_init(&ub->cancel_mutex); - - ret = ublk_alloc_dev_number(ub, header->dev_id); - if (ret < 0) -@@ -2974,6 +3011,7 @@ out_free_dev_number: - ublk_free_dev_number(ub); - out_free_ub: - mutex_destroy(&ub->mutex); -+ mutex_destroy(&ub->cancel_mutex); - kfree(ub); - out_unlock: - mutex_unlock(&ublk_ctl_mutex); -@@ -3198,6 +3236,9 @@ static int ublk_ctrl_end_recovery(struct - pr_devel("%s: All FETCH_REQs received, dev id %d\n", __func__, - header->dev_id); - -+ if (ub->ublksrv_tgid != ublksrv_pid) -+ return -EINVAL; -+ - mutex_lock(&ub->mutex); - if (ublk_nosrv_should_stop_dev(ub)) - goto out_unlock; -@@ -3328,8 +3369,9 @@ static int ublk_ctrl_quiesce_dev(struct - if (ub->dev_info.state != UBLK_S_DEV_LIVE) - goto put_disk; - -- /* Mark all queues as canceling */ -+ /* Mark the device as canceling */ - blk_mq_quiesce_queue(disk->queue); -+ ub->canceling = true; - for (i = 0; i < ub->dev_info.nr_hw_queues; i++) { - struct ublk_queue *ubq = ublk_get_queue(ub, i); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/block/zloop.c BPI-Router-Linux-kernel-6.16.12/drivers/block/zloop.c ---- BPI-Router-Linux-kernel/drivers/block/zloop.c 2025-10-22 13:53:23.167329355 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/block/zloop.c 2025-10-22 13:53:56.415169623 -0400 -@@ -700,6 +700,8 @@ static void zloop_free_disk(struct gendi - struct zloop_device *zlo = disk->private_data; - unsigned int i; - -+ blk_mq_free_tag_set(&zlo->tag_set); -+ - for (i = 0; i < zlo->nr_zones; i++) { - struct zloop_zone *zone = &zlo->zones[i]; - -@@ -1080,7 +1082,6 @@ static int zloop_ctl_remove(struct zloop - - del_gendisk(zlo->disk); - put_disk(zlo->disk); -- blk_mq_free_tag_set(&zlo->tag_set); - - pr_info("Removed device %d\n", opts->id); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/block/zram/zram_drv.c BPI-Router-Linux-kernel-6.16.12/drivers/block/zram/zram_drv.c ---- BPI-Router-Linux-kernel/drivers/block/zram/zram_drv.c 2025-10-22 13:53:23.167329355 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/block/zram/zram_drv.c 2025-10-22 13:53:56.415169623 -0400 -@@ -1794,6 +1794,7 @@ static int write_same_filled_page(struct - u32 index) - { - zram_slot_lock(zram, index); -+ zram_free_page(zram, index); - zram_set_flag(zram, index, ZRAM_SAME); - zram_set_handle(zram, index, fill); - zram_slot_unlock(zram, index); -@@ -1831,6 +1832,7 @@ static int write_incompressible_page(str - kunmap_local(src); - - zram_slot_lock(zram, index); -+ zram_free_page(zram, index); - zram_set_flag(zram, index, ZRAM_HUGE); - zram_set_handle(zram, index, handle); - zram_set_obj_size(zram, index, PAGE_SIZE); -@@ -1854,11 +1856,6 @@ static int zram_write_page(struct zram * - unsigned long element; - bool same_filled; - -- /* First, free memory allocated to this slot (if any) */ -- zram_slot_lock(zram, index); -- zram_free_page(zram, index); -- zram_slot_unlock(zram, index); -- - mem = kmap_local_page(page); - same_filled = page_same_filled(mem, &element); - kunmap_local(mem); -@@ -1900,6 +1897,7 @@ static int zram_write_page(struct zram * - zcomp_stream_put(zstrm); - - zram_slot_lock(zram, index); -+ zram_free_page(zram, index); - zram_set_handle(zram, index, handle); - zram_set_obj_size(zram, index, comp_len); - zram_slot_unlock(zram, index); -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/bfusb.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/bfusb.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/bfusb.c 2025-10-22 13:53:23.167329355 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/bfusb.c 2025-10-22 13:53:56.415169623 -0400 -@@ -670,7 +670,7 @@ static int bfusb_probe(struct usb_interf - hdev->flush = bfusb_flush; - hdev->send = bfusb_send_frame; - -- set_bit(HCI_QUIRK_BROKEN_LOCAL_COMMANDS, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_LOCAL_COMMANDS); - - if (hci_register_dev(hdev) < 0) { - BT_ERR("Can't register HCI device"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/bpa10x.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/bpa10x.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/bpa10x.c 2025-10-22 13:53:23.167329355 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/bpa10x.c 2025-10-22 13:53:56.415169623 -0400 -@@ -398,7 +398,7 @@ static int bpa10x_probe(struct usb_inter - hdev->send = bpa10x_send_frame; - hdev->set_diag = bpa10x_set_diag; - -- set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE); - - err = hci_register_dev(hdev); - if (err < 0) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/btbcm.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btbcm.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/btbcm.c 2025-10-22 13:53:23.167329355 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btbcm.c 2025-10-22 13:53:56.415169623 -0400 -@@ -135,7 +135,7 @@ int btbcm_check_bdaddr(struct hci_dev *h - if (btbcm_set_bdaddr_from_efi(hdev) != 0) { - bt_dev_info(hdev, "BCM: Using default device address (%pMR)", - &bda->bdaddr); -- set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_INVALID_BDADDR); - } - } - -@@ -467,7 +467,7 @@ static int btbcm_print_controller_featur - - /* Read DMI and disable broken Read LE Min/Max Tx Power */ - if (dmi_first_match(disable_broken_read_transmit_power)) -- set_bit(HCI_QUIRK_BROKEN_READ_TRANSMIT_POWER, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_READ_TRANSMIT_POWER); - - return 0; - } -@@ -706,7 +706,7 @@ int btbcm_finalize(struct hci_dev *hdev, - - btbcm_check_bdaddr(hdev); - -- set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_STRICT_DUPLICATE_FILTER); - - return 0; - } -@@ -769,7 +769,7 @@ int btbcm_setup_apple(struct hci_dev *hd - kfree_skb(skb); - } - -- set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_STRICT_DUPLICATE_FILTER); - - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/btintel.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btintel.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/btintel.c 2025-10-22 13:53:23.167329355 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btintel.c 2025-10-22 13:53:56.415169623 -0400 -@@ -88,7 +88,7 @@ int btintel_check_bdaddr(struct hci_dev - if (!bacmp(&bda->bdaddr, BDADDR_INTEL)) { - bt_dev_err(hdev, "Found Intel default device address (%pMR)", - &bda->bdaddr); -- set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_INVALID_BDADDR); - } - - kfree_skb(skb); -@@ -889,7 +889,7 @@ int btintel_send_intel_reset(struct hci_ - - params.boot_param = cpu_to_le32(boot_param); - -- skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(params), ¶ms, -+ skb = __hci_cmd_sync(hdev, BTINTEL_HCI_OP_RESET, sizeof(params), ¶ms, - HCI_INIT_TIMEOUT); - if (IS_ERR(skb)) { - bt_dev_err(hdev, "Failed to send Intel Reset command"); -@@ -1287,7 +1287,7 @@ static void btintel_reset_to_bootloader( - params.boot_option = 0x00; - params.boot_param = cpu_to_le32(0x00000000); - -- skb = __hci_cmd_sync(hdev, 0xfc01, sizeof(params), -+ skb = __hci_cmd_sync(hdev, BTINTEL_HCI_OP_RESET, sizeof(params), - ¶ms, HCI_INIT_TIMEOUT); - if (IS_ERR(skb)) { - bt_dev_err(hdev, "FW download error recovery failed (%ld)", -@@ -2027,7 +2027,7 @@ static int btintel_download_fw(struct hc - */ - if (!bacmp(¶ms->otp_bdaddr, BDADDR_ANY)) { - bt_dev_info(hdev, "No device address configured"); -- set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_INVALID_BDADDR); - } - - download: -@@ -2295,7 +2295,7 @@ static int btintel_prepare_fw_download_t - */ - if (!bacmp(&ver->otp_bd_addr, BDADDR_ANY)) { - bt_dev_info(hdev, "No device address configured"); -- set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_INVALID_BDADDR); - } - } - -@@ -2670,7 +2670,7 @@ static u8 btintel_classify_pkt_type(stru - * Distinguish ISO data packets form ACL data packets - * based on their connection handle value range. - */ -- if (hci_skb_pkt_type(skb) == HCI_ACLDATA_PKT) { -+ if (iso_capable(hdev) && hci_skb_pkt_type(skb) == HCI_ACLDATA_PKT) { - __u16 handle = __le16_to_cpu(hci_acl_hdr(skb)->handle); - - if (hci_handle(handle) >= BTINTEL_ISODATA_HANDLE_BASE) -@@ -3435,9 +3435,9 @@ static int btintel_setup_combined(struct - } - - /* Apply the common HCI quirks for Intel device */ -- set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); -- set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); -- set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_STRICT_DUPLICATE_FILTER); -+ hci_set_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY); -+ hci_set_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_DIAG); - - /* Set up the quality report callback for Intel devices */ - hdev->set_quality_report = btintel_set_quality_report; -@@ -3475,8 +3475,8 @@ static int btintel_setup_combined(struct - */ - if (!btintel_test_flag(hdev, - INTEL_ROM_LEGACY_NO_WBS_SUPPORT)) -- set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, -- &hdev->quirks); -+ hci_set_quirk(hdev, -+ HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); - - err = btintel_legacy_rom_setup(hdev, &ver); - break; -@@ -3491,11 +3491,11 @@ static int btintel_setup_combined(struct - * - * All Legacy bootloader devices support WBS - */ -- set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, -- &hdev->quirks); -+ hci_set_quirk(hdev, -+ HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); - - /* These variants don't seem to support LE Coded PHY */ -- set_bit(HCI_QUIRK_BROKEN_LE_CODED, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_LE_CODED); - - /* Setup MSFT Extension support */ - btintel_set_msft_opcode(hdev, ver.hw_variant); -@@ -3571,10 +3571,10 @@ static int btintel_setup_combined(struct - * - * All Legacy bootloader devices support WBS - */ -- set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); - - /* These variants don't seem to support LE Coded PHY */ -- set_bit(HCI_QUIRK_BROKEN_LE_CODED, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_LE_CODED); - - /* Setup MSFT Extension support */ - btintel_set_msft_opcode(hdev, ver.hw_variant); -@@ -3600,7 +3600,7 @@ static int btintel_setup_combined(struct - * - * All TLV based devices support WBS - */ -- set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); - - /* Setup MSFT Extension support */ - btintel_set_msft_opcode(hdev, -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/btintel.h BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btintel.h ---- BPI-Router-Linux-kernel/drivers/bluetooth/btintel.h 2025-10-22 13:53:23.167329355 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btintel.h 2025-10-22 13:53:56.415169623 -0400 -@@ -52,6 +52,8 @@ struct intel_tlv { - u8 val[]; - } __packed; - -+#define BTINTEL_HCI_OP_RESET 0xfc01 -+ - #define BTINTEL_CNVI_BLAZARI 0x900 - #define BTINTEL_CNVI_BLAZARIW 0x901 - #define BTINTEL_CNVI_GAP 0x910 -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/btintel_pcie.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btintel_pcie.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/btintel_pcie.c 2025-10-22 13:53:23.167329355 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btintel_pcie.c 2025-10-22 13:53:56.415169623 -0400 -@@ -396,8 +396,13 @@ static int btintel_pcie_submit_rx(struct - static int btintel_pcie_start_rx(struct btintel_pcie_data *data) - { - int i, ret; -+ struct rxq *rxq = &data->rxq; - -- for (i = 0; i < BTINTEL_PCIE_RX_MAX_QUEUE; i++) { -+ /* Post (BTINTEL_PCIE_RX_DESCS_COUNT - 3) buffers to overcome the -+ * hardware issues leading to race condition at the firmware. -+ */ -+ -+ for (i = 0; i < rxq->count - 3; i++) { - ret = btintel_pcie_submit_rx(data); - if (ret) - return ret; -@@ -923,11 +928,13 @@ static void btintel_pcie_msix_gp0_handle - case BTINTEL_PCIE_INTEL_HCI_RESET1: - if (btintel_pcie_in_op(data)) { - submit_rx = true; -+ signal_waitq = true; - break; - } - - if (btintel_pcie_in_iml(data)) { - submit_rx = true; -+ signal_waitq = true; - data->alive_intr_ctxt = BTINTEL_PCIE_FW_DL; - break; - } -@@ -1782,8 +1789,8 @@ static int btintel_pcie_alloc(struct bti - * + size of index * Number of queues(2) * type of index array(4) - * + size of context information - */ -- total = (sizeof(struct tfd) + sizeof(struct urbd0) + sizeof(struct frbd) -- + sizeof(struct urbd1)) * BTINTEL_DESCS_COUNT; -+ total = (sizeof(struct tfd) + sizeof(struct urbd0)) * BTINTEL_PCIE_TX_DESCS_COUNT; -+ total += (sizeof(struct frbd) + sizeof(struct urbd1)) * BTINTEL_PCIE_RX_DESCS_COUNT; - - /* Add the sum of size of index array and size of ci struct */ - total += (sizeof(u16) * BTINTEL_PCIE_NUM_QUEUES * 4) + sizeof(struct ctx_info); -@@ -1808,36 +1815,36 @@ static int btintel_pcie_alloc(struct bti - data->dma_v_addr = v_addr; - - /* Setup descriptor count */ -- data->txq.count = BTINTEL_DESCS_COUNT; -- data->rxq.count = BTINTEL_DESCS_COUNT; -+ data->txq.count = BTINTEL_PCIE_TX_DESCS_COUNT; -+ data->rxq.count = BTINTEL_PCIE_RX_DESCS_COUNT; - - /* Setup tfds */ - data->txq.tfds_p_addr = p_addr; - data->txq.tfds = v_addr; - -- p_addr += (sizeof(struct tfd) * BTINTEL_DESCS_COUNT); -- v_addr += (sizeof(struct tfd) * BTINTEL_DESCS_COUNT); -+ p_addr += (sizeof(struct tfd) * BTINTEL_PCIE_TX_DESCS_COUNT); -+ v_addr += (sizeof(struct tfd) * BTINTEL_PCIE_TX_DESCS_COUNT); - - /* Setup urbd0 */ - data->txq.urbd0s_p_addr = p_addr; - data->txq.urbd0s = v_addr; - -- p_addr += (sizeof(struct urbd0) * BTINTEL_DESCS_COUNT); -- v_addr += (sizeof(struct urbd0) * BTINTEL_DESCS_COUNT); -+ p_addr += (sizeof(struct urbd0) * BTINTEL_PCIE_TX_DESCS_COUNT); -+ v_addr += (sizeof(struct urbd0) * BTINTEL_PCIE_TX_DESCS_COUNT); - - /* Setup FRBD*/ - data->rxq.frbds_p_addr = p_addr; - data->rxq.frbds = v_addr; - -- p_addr += (sizeof(struct frbd) * BTINTEL_DESCS_COUNT); -- v_addr += (sizeof(struct frbd) * BTINTEL_DESCS_COUNT); -+ p_addr += (sizeof(struct frbd) * BTINTEL_PCIE_RX_DESCS_COUNT); -+ v_addr += (sizeof(struct frbd) * BTINTEL_PCIE_RX_DESCS_COUNT); - - /* Setup urbd1 */ - data->rxq.urbd1s_p_addr = p_addr; - data->rxq.urbd1s = v_addr; - -- p_addr += (sizeof(struct urbd1) * BTINTEL_DESCS_COUNT); -- v_addr += (sizeof(struct urbd1) * BTINTEL_DESCS_COUNT); -+ p_addr += (sizeof(struct urbd1) * BTINTEL_PCIE_RX_DESCS_COUNT); -+ v_addr += (sizeof(struct urbd1) * BTINTEL_PCIE_RX_DESCS_COUNT); - - /* Setup data buffers for txq */ - err = btintel_pcie_setup_txq_bufs(data, &data->txq); -@@ -1950,16 +1957,19 @@ static int btintel_pcie_send_frame(struc - struct hci_command_hdr *cmd = (void *)skb->data; - __u16 opcode = le16_to_cpu(cmd->opcode); - -- /* When the 0xfc01 command is issued to boot into -- * the operational firmware, it will actually not -- * send a command complete event. To keep the flow -+ /* When the BTINTEL_HCI_OP_RESET command is issued to -+ * boot into the operational firmware, it will actually -+ * not send a command complete event. To keep the flow - * control working inject that event here. - */ -- if (opcode == 0xfc01) -+ if (opcode == BTINTEL_HCI_OP_RESET) - btintel_pcie_inject_cmd_complete(hdev, opcode); - } -- /* Firmware raises alive interrupt on HCI_OP_RESET */ -- if (opcode == HCI_OP_RESET) -+ -+ /* Firmware raises alive interrupt on HCI_OP_RESET or -+ * BTINTEL_HCI_OP_RESET -+ */ -+ if (opcode == HCI_OP_RESET || opcode == BTINTEL_HCI_OP_RESET) - data->gp0_received = false; - - hdev->stat.cmd_tx++; -@@ -1990,25 +2000,24 @@ static int btintel_pcie_send_frame(struc - } - - if (type == BTINTEL_PCIE_HCI_CMD_PKT && -- (opcode == HCI_OP_RESET || opcode == 0xfc01)) { -+ (opcode == HCI_OP_RESET || opcode == BTINTEL_HCI_OP_RESET)) { - old_ctxt = data->alive_intr_ctxt; - data->alive_intr_ctxt = -- (opcode == 0xfc01 ? BTINTEL_PCIE_INTEL_HCI_RESET1 : -+ (opcode == BTINTEL_HCI_OP_RESET ? BTINTEL_PCIE_INTEL_HCI_RESET1 : - BTINTEL_PCIE_HCI_RESET); - bt_dev_dbg(data->hdev, "sent cmd: 0x%4.4x alive context changed: %s -> %s", - opcode, btintel_pcie_alivectxt_state2str(old_ctxt), - btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt)); -- if (opcode == HCI_OP_RESET) { -- ret = wait_event_timeout(data->gp0_wait_q, -- data->gp0_received, -- msecs_to_jiffies(BTINTEL_DEFAULT_INTR_TIMEOUT_MS)); -- if (!ret) { -- hdev->stat.err_tx++; -- bt_dev_err(hdev, "No alive interrupt received for %s", -- btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt)); -- ret = -ETIME; -- goto exit_error; -- } -+ ret = wait_event_timeout(data->gp0_wait_q, -+ data->gp0_received, -+ msecs_to_jiffies(BTINTEL_DEFAULT_INTR_TIMEOUT_MS)); -+ if (!ret) { -+ hdev->stat.err_tx++; -+ bt_dev_err(hdev, "Timeout on alive interrupt (%u ms). Alive context: %s", -+ BTINTEL_DEFAULT_INTR_TIMEOUT_MS, -+ btintel_pcie_alivectxt_state2str(data->alive_intr_ctxt)); -+ ret = -ETIME; -+ goto exit_error; - } - } - hdev->stat.byte_tx += skb->len; -@@ -2028,6 +2037,28 @@ static void btintel_pcie_release_hdev(st - data->hdev = NULL; - } - -+static void btintel_pcie_disable_interrupts(struct btintel_pcie_data *data) -+{ -+ spin_lock(&data->irq_lock); -+ btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_MSIX_FH_INT_MASK, data->fh_init_mask); -+ btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_MSIX_HW_INT_MASK, data->hw_init_mask); -+ spin_unlock(&data->irq_lock); -+} -+ -+static void btintel_pcie_enable_interrupts(struct btintel_pcie_data *data) -+{ -+ spin_lock(&data->irq_lock); -+ btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_MSIX_FH_INT_MASK, ~data->fh_init_mask); -+ btintel_pcie_wr_reg32(data, BTINTEL_PCIE_CSR_MSIX_HW_INT_MASK, ~data->hw_init_mask); -+ spin_unlock(&data->irq_lock); -+} -+ -+static void btintel_pcie_synchronize_irqs(struct btintel_pcie_data *data) -+{ -+ for (int i = 0; i < data->alloc_vecs; i++) -+ synchronize_irq(data->msix_entries[i].vector); -+} -+ - static int btintel_pcie_setup_internal(struct hci_dev *hdev) - { - struct btintel_pcie_data *data = hci_get_drvdata(hdev); -@@ -2054,9 +2085,9 @@ static int btintel_pcie_setup_internal(s - } - - /* Apply the common HCI quirks for Intel device */ -- set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); -- set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); -- set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_STRICT_DUPLICATE_FILTER); -+ hci_set_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY); -+ hci_set_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_DIAG); - - /* Set up the quality report callback for Intel devices */ - hdev->set_quality_report = btintel_set_quality_report; -@@ -2096,7 +2127,7 @@ static int btintel_pcie_setup_internal(s - * - * All TLV based devices support WBS - */ -- set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); - - /* Setup MSFT Extension support */ - btintel_set_msft_opcode(hdev, -@@ -2147,6 +2178,8 @@ static int btintel_pcie_setup(struct hci - bt_dev_err(hdev, "Firmware download retry count: %d", - fw_dl_retry); - btintel_pcie_dump_debug_registers(hdev); -+ btintel_pcie_disable_interrupts(data); -+ btintel_pcie_synchronize_irqs(data); - err = btintel_pcie_reset_bt(data); - if (err) { - bt_dev_err(hdev, "Failed to do shr reset: %d", err); -@@ -2154,6 +2187,7 @@ static int btintel_pcie_setup(struct hci - } - usleep_range(10000, 12000); - btintel_pcie_reset_ia(data); -+ btintel_pcie_enable_interrupts(data); - btintel_pcie_config_msix(data); - err = btintel_pcie_enable_bt(data); - if (err) { -@@ -2286,6 +2320,12 @@ static void btintel_pcie_remove(struct p - - data = pci_get_drvdata(pdev); - -+ btintel_pcie_disable_interrupts(data); -+ -+ btintel_pcie_synchronize_irqs(data); -+ -+ flush_work(&data->rx_work); -+ - btintel_pcie_reset_bt(data); - for (int i = 0; i < data->alloc_vecs; i++) { - struct msix_entry *msix_entry; -@@ -2298,8 +2338,6 @@ static void btintel_pcie_remove(struct p - - btintel_pcie_release_hdev(data); - -- flush_work(&data->rx_work); -- - destroy_workqueue(data->workqueue); - - btintel_pcie_free(data); -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/btintel_pcie.h BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btintel_pcie.h ---- BPI-Router-Linux-kernel/drivers/bluetooth/btintel_pcie.h 2025-10-22 13:53:23.167329355 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btintel_pcie.h 2025-10-22 13:53:56.415169623 -0400 -@@ -154,8 +154,11 @@ enum msix_mbox_int_causes { - /* Default interrupt timeout in msec */ - #define BTINTEL_DEFAULT_INTR_TIMEOUT_MS 3000 - --/* The number of descriptors in TX/RX queues */ --#define BTINTEL_DESCS_COUNT 16 -+/* The number of descriptors in TX queues */ -+#define BTINTEL_PCIE_TX_DESCS_COUNT 32 -+ -+/* The number of descriptors in RX queues */ -+#define BTINTEL_PCIE_RX_DESCS_COUNT 64 - - /* Number of Queue for TX and RX - * It indicates the index of the IA(Index Array) -@@ -177,9 +180,6 @@ enum { - /* Doorbell vector for TFD */ - #define BTINTEL_PCIE_TX_DB_VEC 0 - --/* Number of pending RX requests for downlink */ --#define BTINTEL_PCIE_RX_MAX_QUEUE 6 -- - /* Doorbell vector for FRBD */ - #define BTINTEL_PCIE_RX_DB_VEC 513 - -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/btmtk.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btmtk.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/btmtk.c 2025-10-22 13:53:23.167329355 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btmtk.c 2025-10-22 13:53:56.415169623 -0400 -@@ -642,12 +642,7 @@ static int btmtk_usb_hci_wmt_sync(struct - * WMT command. - */ - err = wait_on_bit_timeout(&data->flags, BTMTK_TX_WAIT_VND_EVT, -- TASK_INTERRUPTIBLE, HCI_INIT_TIMEOUT); -- if (err == -EINTR) { -- bt_dev_err(hdev, "Execution of wmt command interrupted"); -- clear_bit(BTMTK_TX_WAIT_VND_EVT, &data->flags); -- goto err_free_wc; -- } -+ TASK_UNINTERRUPTIBLE, HCI_INIT_TIMEOUT); - - if (err) { - bt_dev_err(hdev, "Execution of wmt command timed out"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/btmtksdio.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btmtksdio.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/btmtksdio.c 2025-10-22 13:53:23.167329355 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btmtksdio.c 2025-10-22 13:53:56.415169623 -0400 -@@ -1141,7 +1141,7 @@ static int btmtksdio_setup(struct hci_de - } - - /* Enable WBS with mSBC codec */ -- set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); - - /* Enable GPIO reset mechanism */ - if (bdev->reset) { -@@ -1384,7 +1384,7 @@ static int btmtksdio_probe(struct sdio_f - SET_HCIDEV_DEV(hdev, &func->dev); - - hdev->manufacturer = 70; -- set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP); - - sdio_set_drvdata(func, bdev); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/btmtkuart.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btmtkuart.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/btmtkuart.c 2025-10-22 13:53:23.167329355 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btmtkuart.c 2025-10-22 13:53:56.415169623 -0400 -@@ -872,7 +872,7 @@ static int btmtkuart_probe(struct serdev - SET_HCIDEV_DEV(hdev, &serdev->dev); - - hdev->manufacturer = 70; -- set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP); - - if (btmtkuart_is_standalone(bdev)) { - err = clk_prepare_enable(bdev->osc); -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/btnxpuart.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btnxpuart.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/btnxpuart.c 2025-10-22 13:53:23.167329355 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btnxpuart.c 2025-10-22 13:53:56.415169623 -0400 -@@ -1807,7 +1807,7 @@ static int nxp_serdev_probe(struct serde - "local-bd-address", - (u8 *)&ba, sizeof(ba)); - if (bacmp(&ba, BDADDR_ANY)) -- set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_USE_BDADDR_PROPERTY); - - if (hci_register_dev(hdev) < 0) { - dev_err(&serdev->dev, "Can't register HCI device\n"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/btqca.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btqca.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/btqca.c 2025-10-22 13:53:23.167329355 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btqca.c 2025-10-22 13:53:56.415169623 -0400 -@@ -739,7 +739,7 @@ static int qca_check_bdaddr(struct hci_d - - bda = (struct hci_rp_read_bd_addr *)skb->data; - if (!bacmp(&bda->bdaddr, &config->bdaddr)) -- set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_USE_BDADDR_PROPERTY); - - kfree_skb(skb); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/btqcomsmd.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btqcomsmd.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/btqcomsmd.c 2025-10-22 13:53:23.167329355 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btqcomsmd.c 2025-10-22 13:53:56.415169623 -0400 -@@ -117,7 +117,7 @@ static int btqcomsmd_setup(struct hci_de - /* Devices do not have persistent storage for BD address. Retrieve - * it from the firmware node property. - */ -- set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_USE_BDADDR_PROPERTY); - - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/btrtl.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btrtl.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/btrtl.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btrtl.c 2025-10-22 13:53:56.415169623 -0400 -@@ -1287,7 +1287,7 @@ void btrtl_set_quirks(struct hci_dev *hd - /* Enable controller to do both LE scan and BR/EDR inquiry - * simultaneously. - */ -- set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY); - - /* Enable central-peripheral role (able to create new connections with - * an existing connection in slave role). -@@ -1301,7 +1301,7 @@ void btrtl_set_quirks(struct hci_dev *hd - case CHIP_ID_8851B: - case CHIP_ID_8922A: - case CHIP_ID_8852BT: -- set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); - - /* RTL8852C needs to transmit mSBC data continuously without - * the zero length of USB packets for the ALT 6 supported chips -@@ -1312,7 +1312,8 @@ void btrtl_set_quirks(struct hci_dev *hd - if (btrtl_dev->project_id == CHIP_ID_8852A || - btrtl_dev->project_id == CHIP_ID_8852B || - btrtl_dev->project_id == CHIP_ID_8852C) -- set_bit(HCI_QUIRK_USE_MSFT_EXT_ADDRESS_FILTER, &hdev->quirks); -+ hci_set_quirk(hdev, -+ HCI_QUIRK_USE_MSFT_EXT_ADDRESS_FILTER); - - hci_set_aosp_capable(hdev); - break; -@@ -1331,8 +1332,7 @@ void btrtl_set_quirks(struct hci_dev *hd - * but it doesn't support any features from page 2 - - * it either responds with garbage or with error status - */ -- set_bit(HCI_QUIRK_BROKEN_LOCAL_EXT_FEATURES_PAGE_2, -- &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_LOCAL_EXT_FEATURES_PAGE_2); - break; - default: - break; -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/btsdio.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btsdio.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/btsdio.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btsdio.c 2025-10-22 13:53:56.415169623 -0400 -@@ -327,7 +327,7 @@ static int btsdio_probe(struct sdio_func - hdev->send = btsdio_send_frame; - - if (func->vendor == 0x0104 && func->device == 0x00c5) -- set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE); - - err = hci_register_dev(hdev); - if (err < 0) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/btusb.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btusb.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/btusb.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/btusb.c 2025-10-22 13:53:56.419169604 -0400 -@@ -515,6 +515,13 @@ static const struct usb_device_id quirks - /* Realtek 8851BE Bluetooth devices */ - { USB_DEVICE(0x0bda, 0xb850), .driver_info = BTUSB_REALTEK }, - { USB_DEVICE(0x13d3, 0x3600), .driver_info = BTUSB_REALTEK }, -+ { USB_DEVICE(0x13d3, 0x3601), .driver_info = BTUSB_REALTEK }, -+ -+ /* Realtek 8851BU Bluetooth devices */ -+ { USB_DEVICE(0x3625, 0x010b), .driver_info = BTUSB_REALTEK | -+ BTUSB_WIDEBAND_SPEECH }, -+ { USB_DEVICE(0x2001, 0x332a), .driver_info = BTUSB_REALTEK | -+ BTUSB_WIDEBAND_SPEECH }, - - /* Realtek 8852AE Bluetooth devices */ - { USB_DEVICE(0x0bda, 0x2852), .driver_info = BTUSB_REALTEK | -@@ -705,6 +712,8 @@ static const struct usb_device_id quirks - BTUSB_WIDEBAND_SPEECH }, - { USB_DEVICE(0x0489, 0xe139), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH }, -+ { USB_DEVICE(0x0489, 0xe14e), .driver_info = BTUSB_MEDIATEK | -+ BTUSB_WIDEBAND_SPEECH }, - { USB_DEVICE(0x0489, 0xe14f), .driver_info = BTUSB_MEDIATEK | - BTUSB_WIDEBAND_SPEECH }, - { USB_DEVICE(0x0489, 0xe150), .driver_info = BTUSB_MEDIATEK | -@@ -2472,18 +2481,18 @@ static int btusb_setup_csr(struct hci_de - * Probably will need to be expanded in the future; - * without these the controller will lock up. - */ -- set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks); -- set_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks); -- set_bit(HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL, &hdev->quirks); -- set_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks); -- set_bit(HCI_QUIRK_BROKEN_READ_VOICE_SETTING, &hdev->quirks); -- set_bit(HCI_QUIRK_BROKEN_READ_PAGE_SCAN_TYPE, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_STORED_LINK_KEY); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_ERR_DATA_REPORTING); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL); -+ hci_set_quirk(hdev, HCI_QUIRK_NO_SUSPEND_NOTIFIER); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_READ_VOICE_SETTING); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_READ_PAGE_SCAN_TYPE); - - /* Clear the reset quirk since this is not an actual - * early Bluetooth 1.1 device from CSR. - */ -- clear_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); -- clear_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); -+ hci_clear_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE); -+ hci_clear_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY); - - /* - * Special workaround for these BT 4.0 chip clones, and potentially more: -@@ -2594,12 +2603,12 @@ static int btusb_send_frame_intel(struct - else - urb = alloc_ctrl_urb(hdev, skb); - -- /* When the 0xfc01 command is issued to boot into -- * the operational firmware, it will actually not -- * send a command complete event. To keep the flow -+ /* When the BTINTEL_HCI_OP_RESET command is issued to -+ * boot into the operational firmware, it will actually -+ * not send a command complete event. To keep the flow - * control working inject that event here. - */ -- if (opcode == 0xfc01) -+ if (opcode == BTINTEL_HCI_OP_RESET) - inject_cmd_complete(hdev, opcode); - } else { - urb = alloc_ctrl_urb(hdev, skb); -@@ -3192,6 +3201,32 @@ static const struct qca_device_info qca_ - { 0x00190200, 40, 4, 16 }, /* WCN785x 2.0 */ - }; - -+static u16 qca_extract_board_id(const struct qca_version *ver) -+{ -+ u16 flag = le16_to_cpu(ver->flag); -+ u16 board_id = 0; -+ -+ if (((flag >> 8) & 0xff) == QCA_FLAG_MULTI_NVM) { -+ /* The board_id should be split into two bytes -+ * The 1st byte is chip ID, and the 2nd byte is platform ID -+ * For example, board ID 0x010A, 0x01 is platform ID. 0x0A is chip ID -+ * we have several platforms, and platform IDs are continuously added -+ * Platform ID: -+ * 0x00 is for Mobile -+ * 0x01 is for X86 -+ * 0x02 is for Automotive -+ * 0x03 is for Consumer electronic -+ */ -+ board_id = (ver->chip_id << 8) + ver->platform_id; -+ } -+ -+ /* Take 0xffff as invalid board ID */ -+ if (board_id == 0xffff) -+ board_id = 0; -+ -+ return board_id; -+} -+ - static int btusb_qca_send_vendor_req(struct usb_device *udev, u8 request, - void *data, u16 size) - { -@@ -3348,44 +3383,28 @@ static void btusb_generate_qca_nvm_name( - const struct qca_version *ver) - { - u32 rom_version = le32_to_cpu(ver->rom_version); -- u16 flag = le16_to_cpu(ver->flag); -- -- if (((flag >> 8) & 0xff) == QCA_FLAG_MULTI_NVM) { -- /* The board_id should be split into two bytes -- * The 1st byte is chip ID, and the 2nd byte is platform ID -- * For example, board ID 0x010A, 0x01 is platform ID. 0x0A is chip ID -- * we have several platforms, and platform IDs are continuously added -- * Platform ID: -- * 0x00 is for Mobile -- * 0x01 is for X86 -- * 0x02 is for Automotive -- * 0x03 is for Consumer electronic -- */ -- u16 board_id = (ver->chip_id << 8) + ver->platform_id; -- const char *variant; -- -- switch (le32_to_cpu(ver->ram_version)) { -- case WCN6855_2_0_RAM_VERSION_GF: -- case WCN6855_2_1_RAM_VERSION_GF: -- variant = "_gf"; -- break; -- default: -- variant = ""; -- break; -- } -- -- if (board_id == 0) { -- snprintf(fwname, max_size, "qca/nvm_usb_%08x%s.bin", -- rom_version, variant); -- } else { -- snprintf(fwname, max_size, "qca/nvm_usb_%08x%s_%04x.bin", -- rom_version, variant, board_id); -- } -- } else { -- snprintf(fwname, max_size, "qca/nvm_usb_%08x.bin", -- rom_version); -+ const char *variant; -+ int len; -+ u16 board_id; -+ -+ board_id = qca_extract_board_id(ver); -+ -+ switch (le32_to_cpu(ver->ram_version)) { -+ case WCN6855_2_0_RAM_VERSION_GF: -+ case WCN6855_2_1_RAM_VERSION_GF: -+ variant = "_gf"; -+ break; -+ default: -+ variant = NULL; -+ break; - } - -+ len = snprintf(fwname, max_size, "qca/nvm_usb_%08x", rom_version); -+ if (variant) -+ len += snprintf(fwname + len, max_size - len, "%s", variant); -+ if (board_id) -+ len += snprintf(fwname + len, max_size - len, "_%04x", board_id); -+ len += snprintf(fwname + len, max_size - len, ".bin"); - } - - static int btusb_setup_qca_load_nvm(struct hci_dev *hdev, -@@ -3494,7 +3513,7 @@ static int btusb_setup_qca(struct hci_de - /* Mark HCI_OP_ENHANCED_SETUP_SYNC_CONN as broken as it doesn't seem to - * work with the likes of HSP/HFP mSBC. - */ -- set_bit(HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN); - - return 0; - } -@@ -3792,6 +3811,8 @@ static int btusb_hci_drv_supported_altse - - /* There are at most 7 alt (0 - 6) */ - rp = kmalloc(sizeof(*rp) + 7, GFP_KERNEL); -+ if (!rp) -+ return -ENOMEM; - - rp->num = 0; - if (!drvdata->isoc) -@@ -4008,10 +4029,10 @@ static int btusb_probe(struct usb_interf - } - #endif - if (id->driver_info & BTUSB_CW6622) -- set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_STORED_LINK_KEY); - - if (id->driver_info & BTUSB_BCM2045) -- set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_STORED_LINK_KEY); - - if (id->driver_info & BTUSB_BCM92035) - hdev->setup = btusb_setup_bcm92035; -@@ -4068,8 +4089,8 @@ static int btusb_probe(struct usb_interf - hdev->reset = btmtk_reset_sync; - hdev->set_bdaddr = btmtk_set_bdaddr; - hdev->send = btusb_send_frame_mtk; -- set_bit(HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN, &hdev->quirks); -- set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN); -+ hci_set_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP); - data->recv_acl = btmtk_usb_recv_acl; - data->suspend = btmtk_usb_suspend; - data->resume = btmtk_usb_resume; -@@ -4077,20 +4098,20 @@ static int btusb_probe(struct usb_interf - } - - if (id->driver_info & BTUSB_SWAVE) { -- set_bit(HCI_QUIRK_FIXUP_INQUIRY_MODE, &hdev->quirks); -- set_bit(HCI_QUIRK_BROKEN_LOCAL_COMMANDS, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_FIXUP_INQUIRY_MODE); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_LOCAL_COMMANDS); - } - - if (id->driver_info & BTUSB_INTEL_BOOT) { - hdev->manufacturer = 2; -- set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_RAW_DEVICE); - } - - if (id->driver_info & BTUSB_ATH3012) { - data->setup_on_usb = btusb_setup_qca; - hdev->set_bdaddr = btusb_set_bdaddr_ath3012; -- set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); -- set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY); -+ hci_set_quirk(hdev, HCI_QUIRK_STRICT_DUPLICATE_FILTER); - } - - if (id->driver_info & BTUSB_QCA_ROME) { -@@ -4098,7 +4119,7 @@ static int btusb_probe(struct usb_interf - hdev->shutdown = btusb_shutdown_qca; - hdev->set_bdaddr = btusb_set_bdaddr_ath3012; - hdev->reset = btusb_qca_reset; -- set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY); - btusb_check_needs_reset_resume(intf); - } - -@@ -4112,7 +4133,7 @@ static int btusb_probe(struct usb_interf - hdev->shutdown = btusb_shutdown_qca; - hdev->set_bdaddr = btusb_set_bdaddr_wcn6855; - hdev->reset = btusb_qca_reset; -- set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY); - hci_set_msft_opcode(hdev, 0xFD70); - } - -@@ -4140,35 +4161,35 @@ static int btusb_probe(struct usb_interf - - if (id->driver_info & BTUSB_ACTIONS_SEMI) { - /* Support is advertised, but not implemented */ -- set_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks); -- set_bit(HCI_QUIRK_BROKEN_READ_TRANSMIT_POWER, &hdev->quirks); -- set_bit(HCI_QUIRK_BROKEN_SET_RPA_TIMEOUT, &hdev->quirks); -- set_bit(HCI_QUIRK_BROKEN_EXT_SCAN, &hdev->quirks); -- set_bit(HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, &hdev->quirks); -- set_bit(HCI_QUIRK_BROKEN_EXT_CREATE_CONN, &hdev->quirks); -- set_bit(HCI_QUIRK_BROKEN_WRITE_AUTH_PAYLOAD_TIMEOUT, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_ERR_DATA_REPORTING); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_READ_TRANSMIT_POWER); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_SET_RPA_TIMEOUT); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_EXT_SCAN); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_EXT_CREATE_CONN); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_WRITE_AUTH_PAYLOAD_TIMEOUT); - } - - if (!reset) -- set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE); - - if (force_scofix || id->driver_info & BTUSB_WRONG_SCO_MTU) { - if (!disable_scofix) -- set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_FIXUP_BUFFER_SIZE); - } - - if (id->driver_info & BTUSB_BROKEN_ISOC) - data->isoc = NULL; - - if (id->driver_info & BTUSB_WIDEBAND_SPEECH) -- set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); - - if (id->driver_info & BTUSB_INVALID_LE_STATES) -- set_bit(HCI_QUIRK_BROKEN_LE_STATES, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_LE_STATES); - - if (id->driver_info & BTUSB_DIGIANSWER) { - data->cmdreq_type = USB_TYPE_VENDOR; -- set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE); - } - - if (id->driver_info & BTUSB_CSR) { -@@ -4177,10 +4198,10 @@ static int btusb_probe(struct usb_interf - - /* Old firmware would otherwise execute USB reset */ - if (bcdDevice < 0x117) -- set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE); - - /* This must be set first in case we disable it for fakes */ -- set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY); - - /* Fake CSR devices with broken commands */ - if (le16_to_cpu(udev->descriptor.idVendor) == 0x0a12 && -@@ -4193,7 +4214,7 @@ static int btusb_probe(struct usb_interf - - /* New sniffer firmware has crippled HCI interface */ - if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997) -- set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_RAW_DEVICE); - } - - if (id->driver_info & BTUSB_INTEL_BOOT) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/hci_aml.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/hci_aml.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/hci_aml.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/hci_aml.c 2025-10-22 13:53:56.419169604 -0400 -@@ -424,7 +424,7 @@ static int aml_check_bdaddr(struct hci_d - - if (!bacmp(&paddr->bdaddr, AML_BDADDR_DEFAULT)) { - bt_dev_info(hdev, "amlbt using default bdaddr (%pM)", &paddr->bdaddr); -- set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_INVALID_BDADDR); - } - - exit: -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/hci_bcm4377.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/hci_bcm4377.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/hci_bcm4377.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/hci_bcm4377.c 2025-10-22 13:53:56.419169604 -0400 -@@ -1435,7 +1435,7 @@ static int bcm4377_check_bdaddr(struct b - - bda = (struct hci_rp_read_bd_addr *)skb->data; - if (!bcm4377_is_valid_bdaddr(bcm4377, &bda->bdaddr)) -- set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &bcm4377->hdev->quirks); -+ hci_set_quirk(bcm4377->hdev, HCI_QUIRK_USE_BDADDR_PROPERTY); - - kfree_skb(skb); - return 0; -@@ -2389,13 +2389,13 @@ static int bcm4377_probe(struct pci_dev - hdev->setup = bcm4377_hci_setup; - - if (bcm4377->hw->broken_mws_transport_config) -- set_bit(HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG); - if (bcm4377->hw->broken_ext_scan) -- set_bit(HCI_QUIRK_BROKEN_EXT_SCAN, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_EXT_SCAN); - if (bcm4377->hw->broken_le_coded) -- set_bit(HCI_QUIRK_BROKEN_LE_CODED, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_LE_CODED); - if (bcm4377->hw->broken_le_ext_adv_report_phy) -- set_bit(HCI_QUIRK_FIXUP_LE_EXT_ADV_REPORT_PHY, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_FIXUP_LE_EXT_ADV_REPORT_PHY); - - pci_set_drvdata(pdev, bcm4377); - hci_set_drvdata(hdev, bcm4377); -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/hci_bcm.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/hci_bcm.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/hci_bcm.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/hci_bcm.c 2025-10-22 13:53:56.419169604 -0400 -@@ -643,8 +643,8 @@ static int bcm_setup(struct hci_uart *hu - * Allow the bootloader to set a valid address through the - * device tree. - */ -- if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hu->hdev->quirks)) -- set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hu->hdev->quirks); -+ if (hci_test_quirk(hu->hdev, HCI_QUIRK_INVALID_BDADDR)) -+ hci_set_quirk(hu->hdev, HCI_QUIRK_USE_BDADDR_PROPERTY); - - if (!bcm_request_irq(bcm)) - err = bcm_setup_sleep(hu); -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/hci_intel.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/hci_intel.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/hci_intel.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/hci_intel.c 2025-10-22 13:53:56.419169604 -0400 -@@ -660,7 +660,7 @@ static int intel_setup(struct hci_uart * - */ - if (!bacmp(¶ms.otp_bdaddr, BDADDR_ANY)) { - bt_dev_info(hdev, "No device address configured"); -- set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_INVALID_BDADDR); - } - - /* With this Intel bootloader only the hardware variant and device -@@ -1029,12 +1029,12 @@ static struct sk_buff *intel_dequeue(str - struct hci_command_hdr *cmd = (void *)skb->data; - __u16 opcode = le16_to_cpu(cmd->opcode); - -- /* When the 0xfc01 command is issued to boot into -- * the operational firmware, it will actually not -- * send a command complete event. To keep the flow -- * control working inject that event here. -+ /* When the BTINTEL_HCI_OP_RESET command is issued to boot into -+ * the operational firmware, it will actually not send a command -+ * complete event. To keep the flow control working inject that -+ * event here. - */ -- if (opcode == 0xfc01) -+ if (opcode == BTINTEL_HCI_OP_RESET) - inject_cmd_complete(hu->hdev, opcode); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/hci_ldisc.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/hci_ldisc.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/hci_ldisc.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/hci_ldisc.c 2025-10-22 13:53:56.419169604 -0400 -@@ -667,13 +667,13 @@ static int hci_uart_register_dev(struct - SET_HCIDEV_DEV(hdev, hu->tty->dev); - - if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags)) -- set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_RAW_DEVICE); - - if (test_bit(HCI_UART_EXT_CONFIG, &hu->hdev_flags)) -- set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_EXTERNAL_CONFIG); - - if (!test_bit(HCI_UART_RESET_ON_INIT, &hu->hdev_flags)) -- set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE); - - /* Only call open() for the protocol after hdev is fully initialized as - * open() (or a timer/workqueue it starts) may attempt to reference it. -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/hci_ll.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/hci_ll.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/hci_ll.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/hci_ll.c 2025-10-22 13:53:56.419169604 -0400 -@@ -649,11 +649,11 @@ static int ll_setup(struct hci_uart *hu) - /* This means that there was an error getting the BD address - * during probe, so mark the device as having a bad address. - */ -- set_bit(HCI_QUIRK_INVALID_BDADDR, &hu->hdev->quirks); -+ hci_set_quirk(hu->hdev, HCI_QUIRK_INVALID_BDADDR); - } else if (bacmp(&lldev->bdaddr, BDADDR_ANY)) { - err = ll_set_bdaddr(hu->hdev, &lldev->bdaddr); - if (err) -- set_bit(HCI_QUIRK_INVALID_BDADDR, &hu->hdev->quirks); -+ hci_set_quirk(hu->hdev, HCI_QUIRK_INVALID_BDADDR); - } - - /* Operational speed if any */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/hci_nokia.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/hci_nokia.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/hci_nokia.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/hci_nokia.c 2025-10-22 13:53:56.419169604 -0400 -@@ -439,7 +439,7 @@ static int nokia_setup(struct hci_uart * - - if (btdev->man_id == NOKIA_ID_BCM2048) { - hu->hdev->set_bdaddr = btbcm_set_bdaddr; -- set_bit(HCI_QUIRK_INVALID_BDADDR, &hu->hdev->quirks); -+ hci_set_quirk(hu->hdev, HCI_QUIRK_INVALID_BDADDR); - dev_dbg(dev, "bcm2048 has invalid bluetooth address!"); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/hci_qca.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/hci_qca.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/hci_qca.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/hci_qca.c 2025-10-22 13:53:56.419169604 -0400 -@@ -1892,7 +1892,7 @@ static int qca_setup(struct hci_uart *hu - /* Enable controller to do both LE scan and BR/EDR inquiry - * simultaneously. - */ -- set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY); - - switch (soc_type) { - case QCA_QCA2066: -@@ -1944,7 +1944,7 @@ retry: - case QCA_WCN7850: - qcadev = serdev_device_get_drvdata(hu->serdev); - if (qcadev->bdaddr_property_broken) -- set_bit(HCI_QUIRK_BDADDR_PROPERTY_BROKEN, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_BDADDR_PROPERTY_BROKEN); - - hci_set_aosp_capable(hdev); - -@@ -2392,10 +2392,17 @@ static int qca_serdev_probe(struct serde - */ - qcadev->bt_power->pwrseq = devm_pwrseq_get(&serdev->dev, - "bluetooth"); -- if (IS_ERR(qcadev->bt_power->pwrseq)) -- return PTR_ERR(qcadev->bt_power->pwrseq); - -- break; -+ /* -+ * Some modules have BT_EN enabled via a hardware pull-up, -+ * meaning it is not defined in the DTS and is not controlled -+ * through the power sequence. In such cases, fall through -+ * to follow the legacy flow. -+ */ -+ if (IS_ERR(qcadev->bt_power->pwrseq)) -+ qcadev->bt_power->pwrseq = NULL; -+ else -+ break; - } - fallthrough; - case QCA_WCN3950: -@@ -2480,7 +2487,7 @@ static int qca_serdev_probe(struct serde - hdev = qcadev->serdev_hu.hdev; - - if (power_ctrl_enabled) { -- set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP); - hdev->shutdown = qca_power_off; - } - -@@ -2489,11 +2496,11 @@ static int qca_serdev_probe(struct serde - * be queried via hci. Same with the valid le states quirk. - */ - if (data->capabilities & QCA_CAP_WIDEBAND_SPEECH) -- set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, -- &hdev->quirks); -+ hci_set_quirk(hdev, -+ HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); - - if (!(data->capabilities & QCA_CAP_VALID_LE_STATES)) -- set_bit(HCI_QUIRK_BROKEN_LE_STATES, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_BROKEN_LE_STATES); - } - - return 0; -@@ -2543,7 +2550,7 @@ static void qca_serdev_shutdown(struct d - * invoked and the SOC is already in the initial state, so - * don't also need to send the VSC. - */ -- if (test_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks) || -+ if (hci_test_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP) || - hci_dev_test_flag(hdev, HCI_SETUP)) - return; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/hci_serdev.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/hci_serdev.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/hci_serdev.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/hci_serdev.c 2025-10-22 13:53:56.419169604 -0400 -@@ -152,7 +152,7 @@ static int hci_uart_close(struct hci_dev - * BT SOC is completely powered OFF during BT OFF, holding port - * open may drain the battery. - */ -- if (test_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks)) { -+ if (hci_test_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP)) { - clear_bit(HCI_UART_PROTO_READY, &hu->flags); - serdev_device_close(hu->serdev); - } -@@ -358,13 +358,13 @@ int hci_uart_register_device_priv(struct - SET_HCIDEV_DEV(hdev, &hu->serdev->dev); - - if (test_bit(HCI_UART_NO_SUSPEND_NOTIFIER, &hu->flags)) -- set_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_NO_SUSPEND_NOTIFIER); - - if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags)) -- set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_RAW_DEVICE); - - if (test_bit(HCI_UART_EXT_CONFIG, &hu->hdev_flags)) -- set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_EXTERNAL_CONFIG); - - if (test_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags)) - return 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/hci_vhci.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/hci_vhci.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/hci_vhci.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/hci_vhci.c 2025-10-22 13:53:56.419169604 -0400 -@@ -380,6 +380,28 @@ static const struct file_operations forc - .write = force_devcd_write, - }; - -+static void vhci_debugfs_init(struct vhci_data *data) -+{ -+ struct hci_dev *hdev = data->hdev; -+ -+ debugfs_create_file("force_suspend", 0644, hdev->debugfs, data, -+ &force_suspend_fops); -+ -+ debugfs_create_file("force_wakeup", 0644, hdev->debugfs, data, -+ &force_wakeup_fops); -+ -+ if (IS_ENABLED(CONFIG_BT_MSFTEXT)) -+ debugfs_create_file("msft_opcode", 0644, hdev->debugfs, data, -+ &msft_opcode_fops); -+ -+ if (IS_ENABLED(CONFIG_BT_AOSPEXT)) -+ debugfs_create_file("aosp_capable", 0644, hdev->debugfs, data, -+ &aosp_capable_fops); -+ -+ debugfs_create_file("force_devcoredump", 0644, hdev->debugfs, data, -+ &force_devcoredump_fops); -+} -+ - static int __vhci_create_device(struct vhci_data *data, __u8 opcode) - { - struct hci_dev *hdev; -@@ -415,16 +437,16 @@ static int __vhci_create_device(struct v - hdev->get_codec_config_data = vhci_get_codec_config_data; - hdev->wakeup = vhci_wakeup; - hdev->setup = vhci_setup; -- set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks); -- set_bit(HCI_QUIRK_SYNC_FLOWCTL_SUPPORTED, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP); -+ hci_set_quirk(hdev, HCI_QUIRK_SYNC_FLOWCTL_SUPPORTED); - - /* bit 6 is for external configuration */ - if (opcode & 0x40) -- set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_EXTERNAL_CONFIG); - - /* bit 7 is for raw device */ - if (opcode & 0x80) -- set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_RAW_DEVICE); - - if (hci_register_dev(hdev) < 0) { - BT_ERR("Can't register HCI device"); -@@ -434,22 +456,8 @@ static int __vhci_create_device(struct v - return -EBUSY; - } - -- debugfs_create_file("force_suspend", 0644, hdev->debugfs, data, -- &force_suspend_fops); -- -- debugfs_create_file("force_wakeup", 0644, hdev->debugfs, data, -- &force_wakeup_fops); -- -- if (IS_ENABLED(CONFIG_BT_MSFTEXT)) -- debugfs_create_file("msft_opcode", 0644, hdev->debugfs, data, -- &msft_opcode_fops); -- -- if (IS_ENABLED(CONFIG_BT_AOSPEXT)) -- debugfs_create_file("aosp_capable", 0644, hdev->debugfs, data, -- &aosp_capable_fops); -- -- debugfs_create_file("force_devcoredump", 0644, hdev->debugfs, data, -- &force_devcoredump_fops); -+ if (!IS_ERR_OR_NULL(hdev->debugfs)) -+ vhci_debugfs_init(data); - - hci_skb_pkt_type(skb) = HCI_VENDOR_PKT; - -@@ -651,6 +659,21 @@ static int vhci_open(struct inode *inode - return 0; - } - -+static void vhci_debugfs_remove(struct hci_dev *hdev) -+{ -+ debugfs_lookup_and_remove("force_suspend", hdev->debugfs); -+ -+ debugfs_lookup_and_remove("force_wakeup", hdev->debugfs); -+ -+ if (IS_ENABLED(CONFIG_BT_MSFTEXT)) -+ debugfs_lookup_and_remove("msft_opcode", hdev->debugfs); -+ -+ if (IS_ENABLED(CONFIG_BT_AOSPEXT)) -+ debugfs_lookup_and_remove("aosp_capable", hdev->debugfs); -+ -+ debugfs_lookup_and_remove("force_devcoredump", hdev->debugfs); -+} -+ - static int vhci_release(struct inode *inode, struct file *file) - { - struct vhci_data *data = file->private_data; -@@ -662,6 +685,8 @@ static int vhci_release(struct inode *in - hdev = data->hdev; - - if (hdev) { -+ if (!IS_ERR_OR_NULL(hdev->debugfs)) -+ vhci_debugfs_remove(hdev); - hci_unregister_dev(hdev); - hci_free_dev(hdev); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/bluetooth/virtio_bt.c BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/virtio_bt.c ---- BPI-Router-Linux-kernel/drivers/bluetooth/virtio_bt.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bluetooth/virtio_bt.c 2025-10-22 13:53:56.419169604 -0400 -@@ -327,17 +327,17 @@ static int virtbt_probe(struct virtio_de - hdev->setup = virtbt_setup_intel; - hdev->shutdown = virtbt_shutdown_generic; - hdev->set_bdaddr = virtbt_set_bdaddr_intel; -- set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); -- set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); -- set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_STRICT_DUPLICATE_FILTER); -+ hci_set_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY); -+ hci_set_quirk(hdev, HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); - break; - - case VIRTIO_BT_CONFIG_VENDOR_REALTEK: - hdev->manufacturer = 93; - hdev->setup = virtbt_setup_realtek; - hdev->shutdown = virtbt_shutdown_generic; -- set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); -- set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); -+ hci_set_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY); -+ hci_set_quirk(hdev, HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED); - break; - } - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/bus/fsl-mc/fsl-mc-bus.c BPI-Router-Linux-kernel-6.16.12/drivers/bus/fsl-mc/fsl-mc-bus.c ---- BPI-Router-Linux-kernel/drivers/bus/fsl-mc/fsl-mc-bus.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bus/fsl-mc/fsl-mc-bus.c 2025-10-22 13:53:56.419169604 -0400 -@@ -943,6 +943,7 @@ struct fsl_mc_device *fsl_mc_get_endpoin - struct fsl_mc_obj_desc endpoint_desc = {{ 0 }}; - struct dprc_endpoint endpoint1 = {{ 0 }}; - struct dprc_endpoint endpoint2 = {{ 0 }}; -+ struct fsl_mc_bus *mc_bus; - int state, err; - - mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent); -@@ -966,6 +967,8 @@ struct fsl_mc_device *fsl_mc_get_endpoin - strcpy(endpoint_desc.type, endpoint2.type); - endpoint_desc.id = endpoint2.id; - endpoint = fsl_mc_device_lookup(&endpoint_desc, mc_bus_dev); -+ if (endpoint) -+ return endpoint; - - /* - * We know that the device has an endpoint because we verified by -@@ -973,17 +976,13 @@ struct fsl_mc_device *fsl_mc_get_endpoin - * yet discovered by the fsl-mc bus, thus the lookup returned NULL. - * Force a rescan of the devices in this container and retry the lookup. - */ -- if (!endpoint) { -- struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); -- -- if (mutex_trylock(&mc_bus->scan_mutex)) { -- err = dprc_scan_objects(mc_bus_dev, true); -- mutex_unlock(&mc_bus->scan_mutex); -- } -- -- if (err < 0) -- return ERR_PTR(err); -+ mc_bus = to_fsl_mc_bus(mc_bus_dev); -+ if (mutex_trylock(&mc_bus->scan_mutex)) { -+ err = dprc_scan_objects(mc_bus_dev, true); -+ mutex_unlock(&mc_bus->scan_mutex); - } -+ if (err < 0) -+ return ERR_PTR(err); - - endpoint = fsl_mc_device_lookup(&endpoint_desc, mc_bus_dev); - /* -diff -purNx .git BPI-Router-Linux-kernel/drivers/bus/mhi/host/boot.c BPI-Router-Linux-kernel-6.16.12/drivers/bus/mhi/host/boot.c ---- BPI-Router-Linux-kernel/drivers/bus/mhi/host/boot.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bus/mhi/host/boot.c 2025-10-22 13:53:56.419169604 -0400 -@@ -31,8 +31,8 @@ int mhi_rddm_prepare(struct mhi_controll - int ret; - - for (i = 0; i < img_info->entries - 1; i++, mhi_buf++, bhi_vec++) { -- bhi_vec->dma_addr = mhi_buf->dma_addr; -- bhi_vec->size = mhi_buf->len; -+ bhi_vec->dma_addr = cpu_to_le64(mhi_buf->dma_addr); -+ bhi_vec->size = cpu_to_le64(mhi_buf->len); - } - - dev_dbg(dev, "BHIe programming for RDDM\n"); -@@ -431,8 +431,8 @@ static void mhi_firmware_copy_bhie(struc - while (remainder) { - to_cpy = min(remainder, mhi_buf->len); - memcpy(mhi_buf->buf, buf, to_cpy); -- bhi_vec->dma_addr = mhi_buf->dma_addr; -- bhi_vec->size = to_cpy; -+ bhi_vec->dma_addr = cpu_to_le64(mhi_buf->dma_addr); -+ bhi_vec->size = cpu_to_le64(to_cpy); - - buf += to_cpy; - remainder -= to_cpy; -diff -purNx .git BPI-Router-Linux-kernel/drivers/bus/mhi/host/internal.h BPI-Router-Linux-kernel-6.16.12/drivers/bus/mhi/host/internal.h ---- BPI-Router-Linux-kernel/drivers/bus/mhi/host/internal.h 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bus/mhi/host/internal.h 2025-10-22 13:53:56.419169604 -0400 -@@ -25,8 +25,8 @@ struct mhi_ctxt { - }; - - struct bhi_vec_entry { -- u64 dma_addr; -- u64 size; -+ __le64 dma_addr; -+ __le64 size; - }; - - enum mhi_fw_load_type { -diff -purNx .git BPI-Router-Linux-kernel/drivers/bus/mhi/host/main.c BPI-Router-Linux-kernel-6.16.12/drivers/bus/mhi/host/main.c ---- BPI-Router-Linux-kernel/drivers/bus/mhi/host/main.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bus/mhi/host/main.c 2025-10-22 13:53:56.419169604 -0400 -@@ -602,7 +602,7 @@ static int parse_xfer_event(struct mhi_c - { - dma_addr_t ptr = MHI_TRE_GET_EV_PTR(event); - struct mhi_ring_element *local_rp, *ev_tre; -- void *dev_rp; -+ void *dev_rp, *next_rp; - struct mhi_buf_info *buf_info; - u16 xfer_len; - -@@ -621,6 +621,16 @@ static int parse_xfer_event(struct mhi_c - result.dir = mhi_chan->dir; - - local_rp = tre_ring->rp; -+ -+ next_rp = local_rp + 1; -+ if (next_rp >= tre_ring->base + tre_ring->len) -+ next_rp = tre_ring->base; -+ if (dev_rp != next_rp && !MHI_TRE_DATA_GET_CHAIN(local_rp)) { -+ dev_err(&mhi_cntrl->mhi_dev->dev, -+ "Event element points to an unexpected TRE\n"); -+ break; -+ } -+ - while (local_rp != dev_rp) { - buf_info = buf_ring->rp; - /* If it's the last TRE, get length from the event */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/bus/mhi/host/pci_generic.c BPI-Router-Linux-kernel-6.16.12/drivers/bus/mhi/host/pci_generic.c ---- BPI-Router-Linux-kernel/drivers/bus/mhi/host/pci_generic.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/bus/mhi/host/pci_generic.c 2025-10-22 13:53:56.419169604 -0400 -@@ -43,6 +43,7 @@ - * @mru_default: default MRU size for MBIM network packets - * @sideband_wake: Devices using dedicated sideband GPIO for wakeup instead - * of inband wake support (such as sdx24) -+ * @no_m3: M3 not supported - */ - struct mhi_pci_dev_info { - const struct mhi_controller_config *config; -@@ -54,6 +55,7 @@ struct mhi_pci_dev_info { - unsigned int dma_data_width; - unsigned int mru_default; - bool sideband_wake; -+ bool no_m3; - }; - - #define MHI_CHANNEL_CONFIG_UL(ch_num, ch_name, el_count, ev_ring) \ -@@ -295,6 +297,7 @@ static const struct mhi_pci_dev_info mhi - .bar_num = MHI_PCI_DEFAULT_BAR_NUM, - .dma_data_width = 32, - .sideband_wake = false, -+ .no_m3 = true, - }; - - static const struct mhi_channel_config mhi_qcom_sa8775p_channels[] = { -@@ -593,8 +596,8 @@ static const struct mhi_pci_dev_info mhi - .sideband_wake = false, - }; - --static const struct mhi_pci_dev_info mhi_foxconn_t99w515_info = { -- .name = "foxconn-t99w515", -+static const struct mhi_pci_dev_info mhi_foxconn_t99w640_info = { -+ .name = "foxconn-t99w640", - .edl = "qcom/sdx72m/foxconn/edl.mbn", - .edl_trigger = true, - .config = &modem_foxconn_sdx72_config, -@@ -818,6 +821,16 @@ static const struct mhi_pci_dev_info mhi - .edl_trigger = true, - }; - -+static const struct mhi_pci_dev_info mhi_telit_fn990b40_info = { -+ .name = "telit-fn990b40", -+ .config = &modem_telit_fn920c04_config, -+ .bar_num = MHI_PCI_DEFAULT_BAR_NUM, -+ .dma_data_width = 32, -+ .sideband_wake = false, -+ .mru_default = 32768, -+ .edl_trigger = true, -+}; -+ - static const struct mhi_pci_dev_info mhi_netprisma_lcur57_info = { - .name = "netprisma-lcur57", - .edl = "qcom/prog_firehose_sdx24.mbn", -@@ -865,6 +878,9 @@ static const struct pci_device_id mhi_pc - .driver_data = (kernel_ulong_t) &mhi_telit_fe990a_info }, - { PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0308), - .driver_data = (kernel_ulong_t) &mhi_qcom_sdx65_info }, -+ /* Telit FN990B40 (sdx72) */ -+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0309, 0x1c5d, 0x201a), -+ .driver_data = (kernel_ulong_t) &mhi_telit_fn990b40_info }, - { PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0309), - .driver_data = (kernel_ulong_t) &mhi_qcom_sdx75_info }, - /* QDU100, x100-DU */ -@@ -920,9 +936,9 @@ static const struct pci_device_id mhi_pc - /* DW5932e (sdx62), Non-eSIM */ - { PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe0f9), - .driver_data = (kernel_ulong_t) &mhi_foxconn_dw5932e_info }, -- /* T99W515 (sdx72) */ -+ /* T99W640 (sdx72) */ - { PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe118), -- .driver_data = (kernel_ulong_t) &mhi_foxconn_t99w515_info }, -+ .driver_data = (kernel_ulong_t) &mhi_foxconn_t99w640_info }, - /* DW5934e(sdx72), With eSIM */ - { PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe11d), - .driver_data = (kernel_ulong_t) &mhi_foxconn_dw5934e_info }, -@@ -1306,8 +1322,8 @@ static int mhi_pci_probe(struct pci_dev - /* start health check */ - mod_timer(&mhi_pdev->health_check_timer, jiffies + HEALTH_CHECK_PERIOD); - -- /* Only allow runtime-suspend if PME capable (for wakeup) */ -- if (pci_pme_capable(pdev, PCI_D3hot)) { -+ /* Allow runtime suspend only if both PME from D3Hot and M3 are supported */ -+ if (pci_pme_capable(pdev, PCI_D3hot) && !(info->no_m3)) { - pm_runtime_set_autosuspend_delay(&pdev->dev, 2000); - pm_runtime_use_autosuspend(&pdev->dev); - pm_runtime_mark_last_busy(&pdev->dev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/cdx/controller/cdx_rpmsg.c BPI-Router-Linux-kernel-6.16.12/drivers/cdx/controller/cdx_rpmsg.c ---- BPI-Router-Linux-kernel/drivers/cdx/controller/cdx_rpmsg.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/cdx/controller/cdx_rpmsg.c 2025-10-22 13:53:56.419169604 -0400 -@@ -129,8 +129,7 @@ static int cdx_rpmsg_probe(struct rpmsg_ - - chinfo.src = RPMSG_ADDR_ANY; - chinfo.dst = rpdev->dst; -- strscpy(chinfo.name, cdx_rpmsg_id_table[0].name, -- strlen(cdx_rpmsg_id_table[0].name)); -+ strscpy(chinfo.name, cdx_rpmsg_id_table[0].name, sizeof(chinfo.name)); - - cdx_mcdi->ept = rpmsg_create_ept(rpdev, cdx_rpmsg_cb, NULL, chinfo); - if (!cdx_mcdi->ept) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/char/agp/amd64-agp.c BPI-Router-Linux-kernel-6.16.12/drivers/char/agp/amd64-agp.c ---- BPI-Router-Linux-kernel/drivers/char/agp/amd64-agp.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/char/agp/amd64-agp.c 2025-10-22 13:53:56.419169604 -0400 -@@ -720,11 +720,6 @@ static const struct pci_device_id agp_am - - MODULE_DEVICE_TABLE(pci, agp_amd64_pci_table); - --static const struct pci_device_id agp_amd64_pci_promisc_table[] = { -- { PCI_DEVICE_CLASS(0, 0) }, -- { } --}; -- - static DEFINE_SIMPLE_DEV_PM_OPS(agp_amd64_pm_ops, NULL, agp_amd64_resume); - - static struct pci_driver agp_amd64_pci_driver = { -@@ -739,6 +734,7 @@ static struct pci_driver agp_amd64_pci_d - /* Not static due to IOMMU code calling it early. */ - int __init agp_amd64_init(void) - { -+ struct pci_dev *pdev = NULL; - int err = 0; - - if (agp_off) -@@ -767,9 +763,13 @@ int __init agp_amd64_init(void) - } - - /* Look for any AGP bridge */ -- agp_amd64_pci_driver.id_table = agp_amd64_pci_promisc_table; -- err = driver_attach(&agp_amd64_pci_driver.driver); -- if (err == 0 && agp_bridges_found == 0) { -+ for_each_pci_dev(pdev) -+ if (pci_find_capability(pdev, PCI_CAP_ID_AGP)) -+ pci_add_dynid(&agp_amd64_pci_driver, -+ pdev->vendor, pdev->device, -+ pdev->subsystem_vendor, -+ pdev->subsystem_device, 0, 0, 0); -+ if (agp_bridges_found == 0) { - pci_unregister_driver(&agp_amd64_pci_driver); - err = -ENODEV; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/char/hw_random/mtk-rng.c BPI-Router-Linux-kernel-6.16.12/drivers/char/hw_random/mtk-rng.c ---- BPI-Router-Linux-kernel/drivers/char/hw_random/mtk-rng.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/char/hw_random/mtk-rng.c 2025-10-22 13:53:56.419169604 -0400 -@@ -143,7 +143,9 @@ static int mtk_rng_probe(struct platform - dev_set_drvdata(&pdev->dev, priv); - pm_runtime_set_autosuspend_delay(&pdev->dev, RNG_AUTOSUSPEND_TIMEOUT); - pm_runtime_use_autosuspend(&pdev->dev); -- devm_pm_runtime_enable(&pdev->dev); -+ ret = devm_pm_runtime_enable(&pdev->dev); -+ if (ret) -+ return ret; - - dev_info(&pdev->dev, "registered RNG driver\n"); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/char/ipmi/ipmi_msghandler.c BPI-Router-Linux-kernel-6.16.12/drivers/char/ipmi/ipmi_msghandler.c ---- BPI-Router-Linux-kernel/drivers/char/ipmi/ipmi_msghandler.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/char/ipmi/ipmi_msghandler.c 2025-10-22 13:53:56.419169604 -0400 -@@ -4607,10 +4607,10 @@ return_unspecified: - * The NetFN and Command in the response is not even - * marginally correct. - */ -- dev_warn(intf->si_dev, -- "BMC returned incorrect response, expected netfn %x cmd %x, got netfn %x cmd %x\n", -- (msg->data[0] >> 2) | 1, msg->data[1], -- msg->rsp[0] >> 2, msg->rsp[1]); -+ dev_warn_ratelimited(intf->si_dev, -+ "BMC returned incorrect response, expected netfn %x cmd %x, got netfn %x cmd %x\n", -+ (msg->data[0] >> 2) | 1, msg->data[1], -+ msg->rsp[0] >> 2, msg->rsp[1]); - - goto return_unspecified; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/char/ipmi/ipmi_watchdog.c BPI-Router-Linux-kernel-6.16.12/drivers/char/ipmi/ipmi_watchdog.c ---- BPI-Router-Linux-kernel/drivers/char/ipmi/ipmi_watchdog.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/char/ipmi/ipmi_watchdog.c 2025-10-22 13:53:56.419169604 -0400 -@@ -1146,14 +1146,8 @@ static struct ipmi_smi_watcher smi_watch - .smi_gone = ipmi_smi_gone - }; - --static int action_op(const char *inval, char *outval) -+static int action_op_set_val(const char *inval) - { -- if (outval) -- strcpy(outval, action); -- -- if (!inval) -- return 0; -- - if (strcmp(inval, "reset") == 0) - action_val = WDOG_TIMEOUT_RESET; - else if (strcmp(inval, "none") == 0) -@@ -1164,18 +1158,26 @@ static int action_op(const char *inval, - action_val = WDOG_TIMEOUT_POWER_DOWN; - else - return -EINVAL; -- strcpy(action, inval); - return 0; - } - --static int preaction_op(const char *inval, char *outval) -+static int action_op(const char *inval, char *outval) - { -+ int rv; -+ - if (outval) -- strcpy(outval, preaction); -+ strcpy(outval, action); - - if (!inval) - return 0; -+ rv = action_op_set_val(inval); -+ if (!rv) -+ strcpy(action, inval); -+ return rv; -+} - -+static int preaction_op_set_val(const char *inval) -+{ - if (strcmp(inval, "pre_none") == 0) - preaction_val = WDOG_PRETIMEOUT_NONE; - else if (strcmp(inval, "pre_smi") == 0) -@@ -1188,18 +1190,26 @@ static int preaction_op(const char *inva - preaction_val = WDOG_PRETIMEOUT_MSG_INT; - else - return -EINVAL; -- strcpy(preaction, inval); - return 0; - } - --static int preop_op(const char *inval, char *outval) -+static int preaction_op(const char *inval, char *outval) - { -+ int rv; -+ - if (outval) -- strcpy(outval, preop); -+ strcpy(outval, preaction); - - if (!inval) - return 0; -+ rv = preaction_op_set_val(inval); -+ if (!rv) -+ strcpy(preaction, inval); -+ return 0; -+} - -+static int preop_op_set_val(const char *inval) -+{ - if (strcmp(inval, "preop_none") == 0) - preop_val = WDOG_PREOP_NONE; - else if (strcmp(inval, "preop_panic") == 0) -@@ -1208,7 +1218,22 @@ static int preop_op(const char *inval, c - preop_val = WDOG_PREOP_GIVE_DATA; - else - return -EINVAL; -- strcpy(preop, inval); -+ return 0; -+} -+ -+static int preop_op(const char *inval, char *outval) -+{ -+ int rv; -+ -+ if (outval) -+ strcpy(outval, preop); -+ -+ if (!inval) -+ return 0; -+ -+ rv = preop_op_set_val(inval); -+ if (!rv) -+ strcpy(preop, inval); - return 0; - } - -@@ -1245,18 +1270,18 @@ static int __init ipmi_wdog_init(void) - { - int rv; - -- if (action_op(action, NULL)) { -+ if (action_op_set_val(action)) { - action_op("reset", NULL); - pr_info("Unknown action '%s', defaulting to reset\n", action); - } - -- if (preaction_op(preaction, NULL)) { -+ if (preaction_op_set_val(preaction)) { - preaction_op("pre_none", NULL); - pr_info("Unknown preaction '%s', defaulting to none\n", - preaction); - } - -- if (preop_op(preop, NULL)) { -+ if (preop_op_set_val(preop)) { - preop_op("preop_none", NULL); - pr_info("Unknown preop '%s', defaulting to none\n", preop); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/char/misc.c BPI-Router-Linux-kernel-6.16.12/drivers/char/misc.c ---- BPI-Router-Linux-kernel/drivers/char/misc.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/char/misc.c 2025-10-22 13:53:56.419169604 -0400 -@@ -296,8 +296,8 @@ static int __init misc_init(void) - if (err) - goto fail_remove; - -- err = -EIO; -- if (__register_chrdev(MISC_MAJOR, 0, MINORMASK + 1, "misc", &misc_fops)) -+ err = __register_chrdev(MISC_MAJOR, 0, MINORMASK + 1, "misc", &misc_fops); -+ if (err < 0) - goto fail_printk; - return 0; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/char/tpm/tpm_crb_ffa.c BPI-Router-Linux-kernel-6.16.12/drivers/char/tpm/tpm_crb_ffa.c ---- BPI-Router-Linux-kernel/drivers/char/tpm/tpm_crb_ffa.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/char/tpm/tpm_crb_ffa.c 2025-10-22 13:53:56.419169604 -0400 -@@ -115,6 +115,7 @@ struct tpm_crb_ffa { - }; - - static struct tpm_crb_ffa *tpm_crb_ffa; -+static struct ffa_driver tpm_crb_ffa_driver; - - static int tpm_crb_ffa_to_linux_errno(int errno) - { -@@ -168,13 +169,23 @@ static int tpm_crb_ffa_to_linux_errno(in - */ - int tpm_crb_ffa_init(void) - { -+ int ret = 0; -+ -+ if (!IS_MODULE(CONFIG_TCG_ARM_CRB_FFA)) { -+ ret = ffa_register(&tpm_crb_ffa_driver); -+ if (ret) { -+ tpm_crb_ffa = ERR_PTR(-ENODEV); -+ return ret; -+ } -+ } -+ - if (!tpm_crb_ffa) -- return -ENOENT; -+ ret = -ENOENT; - - if (IS_ERR_VALUE(tpm_crb_ffa)) -- return -ENODEV; -+ ret = -ENODEV; - -- return 0; -+ return ret; - } - EXPORT_SYMBOL_GPL(tpm_crb_ffa_init); - -@@ -369,7 +380,9 @@ static struct ffa_driver tpm_crb_ffa_dri - .id_table = tpm_crb_ffa_device_id, - }; - -+#ifdef MODULE - module_ffa_driver(tpm_crb_ffa_driver); -+#endif - - MODULE_AUTHOR("Arm"); - MODULE_DESCRIPTION("TPM CRB FFA driver"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/char/tpm/tpm-interface.c BPI-Router-Linux-kernel-6.16.12/drivers/char/tpm/tpm-interface.c ---- BPI-Router-Linux-kernel/drivers/char/tpm/tpm-interface.c 2025-10-22 13:53:23.171329336 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/char/tpm/tpm-interface.c 2025-10-22 13:53:56.419169604 -0400 -@@ -82,6 +82,13 @@ static bool tpm_chip_req_canceled(struct - return chip->ops->req_canceled(chip, status); - } - -+static bool tpm_transmit_completed(u8 status, struct tpm_chip *chip) -+{ -+ u8 status_masked = status & chip->ops->req_complete_mask; -+ -+ return status_masked == chip->ops->req_complete_val; -+} -+ - static ssize_t tpm_try_transmit(struct tpm_chip *chip, void *buf, size_t bufsiz) - { - struct tpm_header *header = buf; -@@ -129,8 +136,7 @@ static ssize_t tpm_try_transmit(struct t - stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal); - do { - u8 status = tpm_chip_status(chip); -- if ((status & chip->ops->req_complete_mask) == -- chip->ops->req_complete_val) -+ if (tpm_transmit_completed(status, chip)) - goto out_recv; - - if (tpm_chip_req_canceled(chip, status)) { -@@ -142,6 +148,13 @@ static ssize_t tpm_try_transmit(struct t - rmb(); - } while (time_before(jiffies, stop)); - -+ /* -+ * Check for completion one more time, just in case the device reported -+ * it while the driver was sleeping in the busy loop above. -+ */ -+ if (tpm_transmit_completed(tpm_chip_status(chip), chip)) -+ goto out_recv; -+ - tpm_chip_cancel(chip); - dev_err(&chip->dev, "Operation Timed out\n"); - return -ETIME; -diff -purNx .git BPI-Router-Linux-kernel/drivers/clk/at91/sam9x7.c BPI-Router-Linux-kernel-6.16.12/drivers/clk/at91/sam9x7.c ---- BPI-Router-Linux-kernel/drivers/clk/at91/sam9x7.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/clk/at91/sam9x7.c 2025-10-22 13:53:56.419169604 -0400 -@@ -61,44 +61,44 @@ static const struct clk_master_layout sa - - /* Fractional PLL core output range. */ - static const struct clk_range plla_core_outputs[] = { -- { .min = 375000000, .max = 1600000000 }, -+ { .min = 800000000, .max = 1600000000 }, - }; - - static const struct clk_range upll_core_outputs[] = { -- { .min = 600000000, .max = 1200000000 }, -+ { .min = 600000000, .max = 960000000 }, - }; - - static const struct clk_range lvdspll_core_outputs[] = { -- { .min = 400000000, .max = 800000000 }, -+ { .min = 600000000, .max = 1200000000 }, - }; - - static const struct clk_range audiopll_core_outputs[] = { -- { .min = 400000000, .max = 800000000 }, -+ { .min = 600000000, .max = 1200000000 }, - }; - - static const struct clk_range plladiv2_core_outputs[] = { -- { .min = 375000000, .max = 1600000000 }, -+ { .min = 800000000, .max = 1600000000 }, - }; - - /* Fractional PLL output range. */ - static const struct clk_range plla_outputs[] = { -- { .min = 732421, .max = 800000000 }, -+ { .min = 400000000, .max = 800000000 }, - }; - - static const struct clk_range upll_outputs[] = { -- { .min = 300000000, .max = 600000000 }, -+ { .min = 300000000, .max = 480000000 }, - }; - - static const struct clk_range lvdspll_outputs[] = { -- { .min = 10000000, .max = 800000000 }, -+ { .min = 175000000, .max = 550000000 }, - }; - - static const struct clk_range audiopll_outputs[] = { -- { .min = 10000000, .max = 800000000 }, -+ { .min = 0, .max = 300000000 }, - }; - - static const struct clk_range plladiv2_outputs[] = { -- { .min = 366210, .max = 400000000 }, -+ { .min = 200000000, .max = 400000000 }, - }; - - /* PLL characteristics. */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/clk/clk-axi-clkgen.c BPI-Router-Linux-kernel-6.16.12/drivers/clk/clk-axi-clkgen.c ---- BPI-Router-Linux-kernel/drivers/clk/clk-axi-clkgen.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/clk/clk-axi-clkgen.c 2025-10-22 13:53:56.419169604 -0400 -@@ -118,7 +118,7 @@ static const struct axi_clkgen_limits ax - - static const struct axi_clkgen_limits axi_clkgen_zynq_default_limits = { - .fpfd_min = 10000, -- .fpfd_max = 300000, -+ .fpfd_max = 450000, - .fvco_min = 600000, - .fvco_max = 1200000, - }; -diff -purNx .git BPI-Router-Linux-kernel/drivers/clk/clk-scmi.c BPI-Router-Linux-kernel-6.16.12/drivers/clk/clk-scmi.c ---- BPI-Router-Linux-kernel/drivers/clk/clk-scmi.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/clk/clk-scmi.c 2025-10-22 13:53:56.419169604 -0400 -@@ -404,6 +404,7 @@ static int scmi_clocks_probe(struct scmi - const struct scmi_handle *handle = sdev->handle; - struct scmi_protocol_handle *ph; - const struct clk_ops *scmi_clk_ops_db[SCMI_MAX_CLK_OPS] = {}; -+ struct scmi_clk *sclks; - - if (!handle) - return -ENODEV; -@@ -430,18 +431,21 @@ static int scmi_clocks_probe(struct scmi - transport_is_atomic = handle->is_transport_atomic(handle, - &atomic_threshold_us); - -+ sclks = devm_kcalloc(dev, count, sizeof(*sclks), GFP_KERNEL); -+ if (!sclks) -+ return -ENOMEM; -+ -+ for (idx = 0; idx < count; idx++) -+ hws[idx] = &sclks[idx].hw; -+ - for (idx = 0; idx < count; idx++) { -- struct scmi_clk *sclk; -+ struct scmi_clk *sclk = &sclks[idx]; - const struct clk_ops *scmi_ops; - -- sclk = devm_kzalloc(dev, sizeof(*sclk), GFP_KERNEL); -- if (!sclk) -- return -ENOMEM; -- - sclk->info = scmi_proto_clk_ops->info_get(ph, idx); - if (!sclk->info) { - dev_dbg(dev, "invalid clock info for idx %d\n", idx); -- devm_kfree(dev, sclk); -+ hws[idx] = NULL; - continue; - } - -@@ -479,13 +483,11 @@ static int scmi_clocks_probe(struct scmi - if (err) { - dev_err(dev, "failed to register clock %d\n", idx); - devm_kfree(dev, sclk->parent_data); -- devm_kfree(dev, sclk); - hws[idx] = NULL; - } else { - dev_dbg(dev, "Registered clock:%s%s\n", - sclk->info->name, - scmi_ops->enable ? " (atomic ops)" : ""); -- hws[idx] = &sclk->hw; - } - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/clk/davinci/psc.c BPI-Router-Linux-kernel-6.16.12/drivers/clk/davinci/psc.c ---- BPI-Router-Linux-kernel/drivers/clk/davinci/psc.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/clk/davinci/psc.c 2025-10-22 13:53:56.419169604 -0400 -@@ -277,6 +277,11 @@ davinci_lpsc_clk_register(struct device - - lpsc->pm_domain.name = devm_kasprintf(dev, GFP_KERNEL, "%s: %s", - best_dev_name(dev), name); -+ if (!lpsc->pm_domain.name) { -+ clk_hw_unregister(&lpsc->hw); -+ kfree(lpsc); -+ return ERR_PTR(-ENOMEM); -+ } - lpsc->pm_domain.attach_dev = davinci_psc_genpd_attach_dev; - lpsc->pm_domain.detach_dev = davinci_psc_genpd_detach_dev; - lpsc->pm_domain.flags = GENPD_FLAG_PM_CLK; -diff -purNx .git BPI-Router-Linux-kernel/drivers/clk/imx/clk-imx95-blk-ctl.c BPI-Router-Linux-kernel-6.16.12/drivers/clk/imx/clk-imx95-blk-ctl.c ---- BPI-Router-Linux-kernel/drivers/clk/imx/clk-imx95-blk-ctl.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/clk/imx/clk-imx95-blk-ctl.c 2025-10-22 13:53:56.419169604 -0400 -@@ -219,11 +219,15 @@ static const struct imx95_blk_ctl_dev_da - .clk_reg_offset = 0, - }; - -+static const char * const disp_engine_parents[] = { -+ "videopll1", "dsi_pll", "ldb_pll_div7" -+}; -+ - static const struct imx95_blk_ctl_clk_dev_data dispmix_csr_clk_dev_data[] = { - [IMX95_CLK_DISPMIX_ENG0_SEL] = { - .name = "disp_engine0_sel", -- .parent_names = (const char *[]){"videopll1", "dsi_pll", "ldb_pll_div7", }, -- .num_parents = 4, -+ .parent_names = disp_engine_parents, -+ .num_parents = ARRAY_SIZE(disp_engine_parents), - .reg = 0, - .bit_idx = 0, - .bit_width = 2, -@@ -232,8 +236,8 @@ static const struct imx95_blk_ctl_clk_de - }, - [IMX95_CLK_DISPMIX_ENG1_SEL] = { - .name = "disp_engine1_sel", -- .parent_names = (const char *[]){"videopll1", "dsi_pll", "ldb_pll_div7", }, -- .num_parents = 4, -+ .parent_names = disp_engine_parents, -+ .num_parents = ARRAY_SIZE(disp_engine_parents), - .reg = 0, - .bit_idx = 2, - .bit_width = 2, -@@ -338,8 +342,10 @@ static int imx95_bc_probe(struct platfor - if (!clk_hw_data) - return -ENOMEM; - -- if (bc_data->rpm_enabled) -- pm_runtime_enable(&pdev->dev); -+ if (bc_data->rpm_enabled) { -+ devm_pm_runtime_enable(&pdev->dev); -+ pm_runtime_resume_and_get(&pdev->dev); -+ } - - clk_hw_data->num = bc_data->num_clks; - hws = clk_hw_data->hws; -@@ -379,8 +385,10 @@ static int imx95_bc_probe(struct platfor - goto cleanup; - } - -- if (pm_runtime_enabled(bc->dev)) -+ if (pm_runtime_enabled(bc->dev)) { -+ pm_runtime_put_sync(&pdev->dev); - clk_disable_unprepare(bc->clk_apb); -+ } - - return 0; - -@@ -391,9 +399,6 @@ cleanup: - clk_hw_unregister(hws[i]); - } - -- if (bc_data->rpm_enabled) -- pm_runtime_disable(&pdev->dev); -- - return ret; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/clk/qcom/dispcc-sm8750.c BPI-Router-Linux-kernel-6.16.12/drivers/clk/qcom/dispcc-sm8750.c ---- BPI-Router-Linux-kernel/drivers/clk/qcom/dispcc-sm8750.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/clk/qcom/dispcc-sm8750.c 2025-10-22 13:53:56.419169604 -0400 -@@ -393,7 +393,7 @@ static struct clk_rcg2 disp_cc_mdss_byte - .name = "disp_cc_mdss_byte0_clk_src", - .parent_data = disp_cc_parent_data_1, - .num_parents = ARRAY_SIZE(disp_cc_parent_data_1), -- .flags = CLK_SET_RATE_PARENT, -+ .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, - .ops = &clk_byte2_ops, - }, - }; -@@ -408,7 +408,7 @@ static struct clk_rcg2 disp_cc_mdss_byte - .name = "disp_cc_mdss_byte1_clk_src", - .parent_data = disp_cc_parent_data_1, - .num_parents = ARRAY_SIZE(disp_cc_parent_data_1), -- .flags = CLK_SET_RATE_PARENT, -+ .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, - .ops = &clk_byte2_ops, - }, - }; -@@ -712,7 +712,7 @@ static struct clk_rcg2 disp_cc_mdss_pclk - .name = "disp_cc_mdss_pclk0_clk_src", - .parent_data = disp_cc_parent_data_1, - .num_parents = ARRAY_SIZE(disp_cc_parent_data_1), -- .flags = CLK_SET_RATE_PARENT, -+ .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, - .ops = &clk_pixel_ops, - }, - }; -@@ -727,7 +727,7 @@ static struct clk_rcg2 disp_cc_mdss_pclk - .name = "disp_cc_mdss_pclk1_clk_src", - .parent_data = disp_cc_parent_data_1, - .num_parents = ARRAY_SIZE(disp_cc_parent_data_1), -- .flags = CLK_SET_RATE_PARENT, -+ .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, - .ops = &clk_pixel_ops, - }, - }; -@@ -742,7 +742,7 @@ static struct clk_rcg2 disp_cc_mdss_pclk - .name = "disp_cc_mdss_pclk2_clk_src", - .parent_data = disp_cc_parent_data_1, - .num_parents = ARRAY_SIZE(disp_cc_parent_data_1), -- .flags = CLK_SET_RATE_PARENT, -+ .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, - .ops = &clk_pixel_ops, - }, - }; -diff -purNx .git BPI-Router-Linux-kernel/drivers/clk/qcom/gcc-ipq5018.c BPI-Router-Linux-kernel-6.16.12/drivers/clk/qcom/gcc-ipq5018.c ---- BPI-Router-Linux-kernel/drivers/clk/qcom/gcc-ipq5018.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/clk/qcom/gcc-ipq5018.c 2025-10-22 13:53:56.419169604 -0400 -@@ -1371,7 +1371,7 @@ static struct clk_branch gcc_xo_clk = { - &gcc_xo_clk_src.clkr.hw, - }, - .num_parents = 1, -- .flags = CLK_SET_RATE_PARENT, -+ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, - .ops = &clk_branch2_ops, - }, - }, -diff -purNx .git BPI-Router-Linux-kernel/drivers/clk/qcom/gcc-ipq8074.c BPI-Router-Linux-kernel-6.16.12/drivers/clk/qcom/gcc-ipq8074.c ---- BPI-Router-Linux-kernel/drivers/clk/qcom/gcc-ipq8074.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/clk/qcom/gcc-ipq8074.c 2025-10-22 13:53:56.419169604 -0400 -@@ -1895,10 +1895,10 @@ static const struct freq_conf ftbl_nss_p - static const struct freq_multi_tbl ftbl_nss_port6_tx_clk_src[] = { - FMS(19200000, P_XO, 1, 0, 0), - FM(25000000, ftbl_nss_port6_tx_clk_src_25), -- FMS(78125000, P_UNIPHY1_RX, 4, 0, 0), -+ FMS(78125000, P_UNIPHY2_TX, 4, 0, 0), - FM(125000000, ftbl_nss_port6_tx_clk_src_125), -- FMS(156250000, P_UNIPHY1_RX, 2, 0, 0), -- FMS(312500000, P_UNIPHY1_RX, 1, 0, 0), -+ FMS(156250000, P_UNIPHY2_TX, 2, 0, 0), -+ FMS(312500000, P_UNIPHY2_TX, 1, 0, 0), - { } - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/clk/renesas/rzg2l-cpg.c BPI-Router-Linux-kernel-6.16.12/drivers/clk/renesas/rzg2l-cpg.c ---- BPI-Router-Linux-kernel/drivers/clk/renesas/rzg2l-cpg.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/clk/renesas/rzg2l-cpg.c 2025-10-22 13:53:56.423169585 -0400 -@@ -1389,10 +1389,6 @@ rzg2l_cpg_register_mod_clk(const struct - goto fail; - } - -- clk = clock->hw.clk; -- dev_dbg(dev, "Module clock %pC at %lu Hz\n", clk, clk_get_rate(clk)); -- priv->clks[id] = clk; -- - if (mod->is_coupled) { - struct mstp_clock *sibling; - -@@ -1404,6 +1400,10 @@ rzg2l_cpg_register_mod_clk(const struct - } - } - -+ clk = clock->hw.clk; -+ dev_dbg(dev, "Module clock %pC at %lu Hz\n", clk, clk_get_rate(clk)); -+ priv->clks[id] = clk; -+ - return; - - fail: -diff -purNx .git BPI-Router-Linux-kernel/drivers/clk/renesas/rzv2h-cpg.c BPI-Router-Linux-kernel-6.16.12/drivers/clk/renesas/rzv2h-cpg.c ---- BPI-Router-Linux-kernel/drivers/clk/renesas/rzv2h-cpg.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/clk/renesas/rzv2h-cpg.c 2025-10-22 13:53:56.423169585 -0400 -@@ -381,6 +381,7 @@ rzv2h_cpg_ddiv_clk_register(const struct - init.ops = &rzv2h_ddiv_clk_divider_ops; - init.parent_names = &parent_name; - init.num_parents = 1; -+ init.flags = CLK_SET_RATE_PARENT; - - ddiv->priv = priv; - ddiv->mon = cfg_ddiv.monbit; -diff -purNx .git BPI-Router-Linux-kernel/drivers/clk/samsung/clk-exynos850.c BPI-Router-Linux-kernel-6.16.12/drivers/clk/samsung/clk-exynos850.c ---- BPI-Router-Linux-kernel/drivers/clk/samsung/clk-exynos850.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/clk/samsung/clk-exynos850.c 2025-10-22 13:53:56.423169585 -0400 -@@ -1360,7 +1360,7 @@ static const unsigned long cpucl1_clk_re - CLK_CON_GAT_GATE_CLK_CPUCL1_CPU, - }; - --/* List of parent clocks for Muxes in CMU_CPUCL0 */ -+/* List of parent clocks for Muxes in CMU_CPUCL1 */ - PNAME(mout_pll_cpucl1_p) = { "oscclk", "fout_cpucl1_pll" }; - PNAME(mout_cpucl1_switch_user_p) = { "oscclk", "dout_cpucl1_switch" }; - PNAME(mout_cpucl1_dbg_user_p) = { "oscclk", "dout_cpucl1_dbg" }; -diff -purNx .git BPI-Router-Linux-kernel/drivers/clk/samsung/clk-gs101.c BPI-Router-Linux-kernel-6.16.12/drivers/clk/samsung/clk-gs101.c ---- BPI-Router-Linux-kernel/drivers/clk/samsung/clk-gs101.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/clk/samsung/clk-gs101.c 2025-10-22 13:53:56.423169585 -0400 -@@ -1154,7 +1154,7 @@ static const struct samsung_div_clock cm - CLK_CON_DIV_CLKCMU_G2D_MSCL, 0, 4), - DIV(CLK_DOUT_CMU_G3AA_G3AA, "dout_cmu_g3aa_g3aa", "gout_cmu_g3aa_g3aa", - CLK_CON_DIV_CLKCMU_G3AA_G3AA, 0, 4), -- DIV(CLK_DOUT_CMU_G3D_SWITCH, "dout_cmu_g3d_busd", "gout_cmu_g3d_busd", -+ DIV(CLK_DOUT_CMU_G3D_BUSD, "dout_cmu_g3d_busd", "gout_cmu_g3d_busd", - CLK_CON_DIV_CLKCMU_G3D_BUSD, 0, 4), - DIV(CLK_DOUT_CMU_G3D_GLB, "dout_cmu_g3d_glb", "gout_cmu_g3d_glb", - CLK_CON_DIV_CLKCMU_G3D_GLB, 0, 4), -@@ -2129,7 +2129,7 @@ PNAME(mout_hsi0_usbdpdbg_user_p) = { "os - "dout_cmu_hsi0_usbdpdbg" }; - PNAME(mout_hsi0_bus_p) = { "mout_hsi0_bus_user", - "mout_hsi0_alt_user" }; --PNAME(mout_hsi0_usb20_ref_p) = { "fout_usb_pll", -+PNAME(mout_hsi0_usb20_ref_p) = { "mout_pll_usb", - "mout_hsi0_tcxo_user" }; - PNAME(mout_hsi0_usb31drd_p) = { "fout_usb_pll", - "mout_hsi0_usb31drd_user", -diff -purNx .git BPI-Router-Linux-kernel/drivers/clk/spacemit/ccu-k1.c BPI-Router-Linux-kernel-6.16.12/drivers/clk/spacemit/ccu-k1.c ---- BPI-Router-Linux-kernel/drivers/clk/spacemit/ccu-k1.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/clk/spacemit/ccu-k1.c 2025-10-22 13:53:56.423169585 -0400 -@@ -170,7 +170,8 @@ CCU_FACTOR_GATE_DEFINE(pll1_d4, CCU_PARE - CCU_FACTOR_GATE_DEFINE(pll1_d5, CCU_PARENT_HW(pll1), APBS_PLL1_SWCR2, BIT(4), 5, 1); - CCU_FACTOR_GATE_DEFINE(pll1_d6, CCU_PARENT_HW(pll1), APBS_PLL1_SWCR2, BIT(5), 6, 1); - CCU_FACTOR_GATE_DEFINE(pll1_d7, CCU_PARENT_HW(pll1), APBS_PLL1_SWCR2, BIT(6), 7, 1); --CCU_FACTOR_GATE_DEFINE(pll1_d8, CCU_PARENT_HW(pll1), APBS_PLL1_SWCR2, BIT(7), 8, 1); -+CCU_FACTOR_GATE_FLAGS_DEFINE(pll1_d8, CCU_PARENT_HW(pll1), APBS_PLL1_SWCR2, BIT(7), 8, 1, -+ CLK_IS_CRITICAL); - CCU_FACTOR_GATE_DEFINE(pll1_d11_223p4, CCU_PARENT_HW(pll1), APBS_PLL1_SWCR2, BIT(15), 11, 1); - CCU_FACTOR_GATE_DEFINE(pll1_d13_189, CCU_PARENT_HW(pll1), APBS_PLL1_SWCR2, BIT(16), 13, 1); - CCU_FACTOR_GATE_DEFINE(pll1_d23_106p8, CCU_PARENT_HW(pll1), APBS_PLL1_SWCR2, BIT(20), 23, 1); -diff -purNx .git BPI-Router-Linux-kernel/drivers/clk/spacemit/ccu_mix.h BPI-Router-Linux-kernel-6.16.12/drivers/clk/spacemit/ccu_mix.h ---- BPI-Router-Linux-kernel/drivers/clk/spacemit/ccu_mix.h 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/clk/spacemit/ccu_mix.h 2025-10-22 13:53:56.423169585 -0400 -@@ -101,17 +101,22 @@ static struct ccu_mix _name = { \ - } \ - } - --#define CCU_FACTOR_GATE_DEFINE(_name, _parent, _reg_ctrl, _mask_gate, _div, \ -- _mul) \ -+#define CCU_FACTOR_GATE_FLAGS_DEFINE(_name, _parent, _reg_ctrl, _mask_gate, _div, \ -+ _mul, _flags) \ - static struct ccu_mix _name = { \ - .gate = CCU_GATE_INIT(_mask_gate), \ - .factor = CCU_FACTOR_INIT(_div, _mul), \ - .common = { \ - .reg_ctrl = _reg_ctrl, \ -- CCU_MIX_INITHW(_name, _parent, spacemit_ccu_factor_gate_ops, 0) \ -+ CCU_MIX_INITHW(_name, _parent, spacemit_ccu_factor_gate_ops, _flags) \ - } \ - } - -+#define CCU_FACTOR_GATE_DEFINE(_name, _parent, _reg_ctrl, _mask_gate, _div, \ -+ _mul) \ -+ CCU_FACTOR_GATE_FLAGS_DEFINE(_name, _parent, _reg_ctrl, _mask_gate, _div, \ -+ _mul, 0) -+ - #define CCU_MUX_GATE_DEFINE(_name, _parents, _reg_ctrl, _shift, _width, \ - _mask_gate, _flags) \ - static struct ccu_mix _name = { \ -diff -purNx .git BPI-Router-Linux-kernel/drivers/clk/spacemit/ccu_pll.c BPI-Router-Linux-kernel-6.16.12/drivers/clk/spacemit/ccu_pll.c ---- BPI-Router-Linux-kernel/drivers/clk/spacemit/ccu_pll.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/clk/spacemit/ccu_pll.c 2025-10-22 13:53:56.423169585 -0400 -@@ -122,7 +122,7 @@ static unsigned long ccu_pll_recalc_rate - - WARN_ON_ONCE(!entry); - -- return entry ? entry->rate : -EINVAL; -+ return entry ? entry->rate : 0; - } - - static long ccu_pll_round_rate(struct clk_hw *hw, unsigned long rate, -diff -purNx .git BPI-Router-Linux-kernel/drivers/clk/sunxi-ng/ccu_mp.c BPI-Router-Linux-kernel-6.16.12/drivers/clk/sunxi-ng/ccu_mp.c ---- BPI-Router-Linux-kernel/drivers/clk/sunxi-ng/ccu_mp.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/clk/sunxi-ng/ccu_mp.c 2025-10-22 13:53:56.423169585 -0400 -@@ -185,7 +185,7 @@ static unsigned long ccu_mp_recalc_rate( - p &= (1 << cmp->p.width) - 1; - - if (cmp->common.features & CCU_FEATURE_DUAL_DIV) -- rate = (parent_rate / p) / m; -+ rate = (parent_rate / (p + cmp->p.offset)) / m; - else - rate = (parent_rate >> p) / m; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/clk/sunxi-ng/ccu-sun55i-a523.c BPI-Router-Linux-kernel-6.16.12/drivers/clk/sunxi-ng/ccu-sun55i-a523.c ---- BPI-Router-Linux-kernel/drivers/clk/sunxi-ng/ccu-sun55i-a523.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/clk/sunxi-ng/ccu-sun55i-a523.c 2025-10-22 13:53:56.423169585 -0400 -@@ -385,7 +385,8 @@ static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_F - 0, 0, /* no P */ - 24, 3, /* mux */ - BIT(31), /* gate */ -- 0, CCU_FEATURE_UPDATE_BIT); -+ CLK_IS_CRITICAL, -+ CCU_FEATURE_UPDATE_BIT); - - static const struct clk_hw *mbus_hws[] = { &mbus_clk.common.hw }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c BPI-Router-Linux-kernel-6.16.12/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c ---- BPI-Router-Linux-kernel/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c 2025-10-22 13:53:56.423169585 -0400 -@@ -347,10 +347,9 @@ static SUNXI_CCU_GATE(dram_ohci_clk, "dr - - static const char * const de_parents[] = { "pll-video", "pll-periph0" }; - static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, -- 0x104, 0, 4, 24, 2, BIT(31), -- CLK_SET_RATE_PARENT); -+ 0x104, 0, 4, 24, 3, BIT(31), 0); - --static const char * const tcon_parents[] = { "pll-video" }; -+static const char * const tcon_parents[] = { "pll-video", "pll-periph0" }; - static SUNXI_CCU_M_WITH_MUX_GATE(tcon_clk, "tcon", tcon_parents, - 0x118, 0, 4, 24, 3, BIT(31), 0); - -@@ -362,11 +361,11 @@ static const char * const csi_mclk_paren - static SUNXI_CCU_M_WITH_MUX_GATE(csi0_mclk_clk, "csi0-mclk", csi_mclk_parents, - 0x130, 0, 5, 8, 3, BIT(15), 0); - --static const char * const csi1_sclk_parents[] = { "pll-video", "pll-isp" }; --static SUNXI_CCU_M_WITH_MUX_GATE(csi1_sclk_clk, "csi-sclk", csi1_sclk_parents, -+static const char * const csi_sclk_parents[] = { "pll-video", "pll-isp" }; -+static SUNXI_CCU_M_WITH_MUX_GATE(csi_sclk_clk, "csi-sclk", csi_sclk_parents, - 0x134, 16, 4, 24, 3, BIT(31), 0); - --static SUNXI_CCU_M_WITH_MUX_GATE(csi1_mclk_clk, "csi-mclk", csi_mclk_parents, -+static SUNXI_CCU_M_WITH_MUX_GATE(csi1_mclk_clk, "csi1-mclk", csi_mclk_parents, - 0x134, 0, 5, 8, 3, BIT(15), 0); - - static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve", -@@ -452,7 +451,7 @@ static struct ccu_common *sun8i_v3s_ccu_ - &tcon_clk.common, - &csi_misc_clk.common, - &csi0_mclk_clk.common, -- &csi1_sclk_clk.common, -+ &csi_sclk_clk.common, - &csi1_mclk_clk.common, - &ve_clk.common, - &ac_dig_clk.common, -@@ -551,7 +550,7 @@ static struct clk_hw_onecell_data sun8i_ - [CLK_TCON0] = &tcon_clk.common.hw, - [CLK_CSI_MISC] = &csi_misc_clk.common.hw, - [CLK_CSI0_MCLK] = &csi0_mclk_clk.common.hw, -- [CLK_CSI1_SCLK] = &csi1_sclk_clk.common.hw, -+ [CLK_CSI_SCLK] = &csi_sclk_clk.common.hw, - [CLK_CSI1_MCLK] = &csi1_mclk_clk.common.hw, - [CLK_VE] = &ve_clk.common.hw, - [CLK_AC_DIG] = &ac_dig_clk.common.hw, -@@ -633,7 +632,7 @@ static struct clk_hw_onecell_data sun8i_ - [CLK_TCON0] = &tcon_clk.common.hw, - [CLK_CSI_MISC] = &csi_misc_clk.common.hw, - [CLK_CSI0_MCLK] = &csi0_mclk_clk.common.hw, -- [CLK_CSI1_SCLK] = &csi1_sclk_clk.common.hw, -+ [CLK_CSI_SCLK] = &csi_sclk_clk.common.hw, - [CLK_CSI1_MCLK] = &csi1_mclk_clk.common.hw, - [CLK_VE] = &ve_clk.common.hw, - [CLK_AC_DIG] = &ac_dig_clk.common.hw, -diff -purNx .git BPI-Router-Linux-kernel/drivers/clk/tegra/clk-periph.c BPI-Router-Linux-kernel-6.16.12/drivers/clk/tegra/clk-periph.c ---- BPI-Router-Linux-kernel/drivers/clk/tegra/clk-periph.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/clk/tegra/clk-periph.c 2025-10-22 13:53:56.423169585 -0400 -@@ -51,7 +51,7 @@ static int clk_periph_determine_rate(str - struct tegra_clk_periph *periph = to_clk_periph(hw); - const struct clk_ops *div_ops = periph->div_ops; - struct clk_hw *div_hw = &periph->divider.hw; -- unsigned long rate; -+ long rate; - - __clk_hw_set_clk(div_hw, hw); - -@@ -59,7 +59,7 @@ static int clk_periph_determine_rate(str - if (rate < 0) - return rate; - -- req->rate = rate; -+ req->rate = (unsigned long)rate; - return 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/clk/thead/clk-th1520-ap.c BPI-Router-Linux-kernel-6.16.12/drivers/clk/thead/clk-th1520-ap.c ---- BPI-Router-Linux-kernel/drivers/clk/thead/clk-th1520-ap.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/clk/thead/clk-th1520-ap.c 2025-10-22 13:53:56.423169585 -0400 -@@ -42,8 +42,9 @@ struct ccu_common { - }; - - struct ccu_mux { -- struct ccu_internal mux; -- struct ccu_common common; -+ int clkid; -+ u32 reg; -+ struct clk_mux mux; - }; - - struct ccu_gate { -@@ -75,6 +76,17 @@ struct ccu_pll { - .flags = _flags, \ - } - -+#define TH_CCU_MUX(_name, _parents, _shift, _width) \ -+ { \ -+ .mask = GENMASK(_width - 1, 0), \ -+ .shift = _shift, \ -+ .hw.init = CLK_HW_INIT_PARENTS_DATA( \ -+ _name, \ -+ _parents, \ -+ &clk_mux_ops, \ -+ 0), \ -+ } -+ - #define CCU_GATE(_clkid, _struct, _name, _parent, _reg, _gate, _flags) \ - struct ccu_gate _struct = { \ - .enable = _gate, \ -@@ -94,13 +106,6 @@ static inline struct ccu_common *hw_to_c - return container_of(hw, struct ccu_common, hw); - } - --static inline struct ccu_mux *hw_to_ccu_mux(struct clk_hw *hw) --{ -- struct ccu_common *common = hw_to_ccu_common(hw); -- -- return container_of(common, struct ccu_mux, common); --} -- - static inline struct ccu_pll *hw_to_ccu_pll(struct clk_hw *hw) - { - struct ccu_common *common = hw_to_ccu_common(hw); -@@ -415,32 +420,20 @@ static const struct clk_parent_data c910 - }; - - static struct ccu_mux c910_i0_clk = { -- .mux = TH_CCU_ARG(1, 1), -- .common = { -- .clkid = CLK_C910_I0, -- .cfg0 = 0x100, -- .hw.init = CLK_HW_INIT_PARENTS_DATA("c910-i0", -- c910_i0_parents, -- &clk_mux_ops, -- 0), -- } -+ .clkid = CLK_C910_I0, -+ .reg = 0x100, -+ .mux = TH_CCU_MUX("c910-i0", c910_i0_parents, 1, 1), - }; - - static const struct clk_parent_data c910_parents[] = { -- { .hw = &c910_i0_clk.common.hw }, -+ { .hw = &c910_i0_clk.mux.hw }, - { .hw = &cpu_pll1_clk.common.hw } - }; - - static struct ccu_mux c910_clk = { -- .mux = TH_CCU_ARG(0, 1), -- .common = { -- .clkid = CLK_C910, -- .cfg0 = 0x100, -- .hw.init = CLK_HW_INIT_PARENTS_DATA("c910", -- c910_parents, -- &clk_mux_ops, -- 0), -- } -+ .clkid = CLK_C910, -+ .reg = 0x100, -+ .mux = TH_CCU_MUX("c910", c910_parents, 0, 1), - }; - - static const struct clk_parent_data ahb2_cpusys_parents[] = { -@@ -582,7 +575,14 @@ static const struct clk_parent_data peri - { .hw = &peri2sys_apb_pclk.common.hw } - }; - --static CLK_FIXED_FACTOR_FW_NAME(osc12m_clk, "osc_12m", "osc_24m", 2, 1, 0); -+static struct clk_fixed_factor osc12m_clk = { -+ .div = 2, -+ .mult = 1, -+ .hw.init = CLK_HW_INIT_PARENTS_DATA("osc_12m", -+ osc_24m_clk, -+ &clk_fixed_factor_ops, -+ 0), -+}; - - static const char * const out_parents[] = { "osc_24m", "osc_12m" }; - -@@ -792,11 +792,12 @@ static CCU_GATE(CLK_AON2CPU_A2X, aon2cpu - 0x134, BIT(8), 0); - static CCU_GATE(CLK_X2X_CPUSYS, x2x_cpusys_clk, "x2x-cpusys", axi4_cpusys2_aclk_pd, - 0x134, BIT(7), 0); --static CCU_GATE(CLK_CPU2AON_X2H, cpu2aon_x2h_clk, "cpu2aon-x2h", axi_aclk_pd, 0x138, BIT(8), 0); -+static CCU_GATE(CLK_CPU2AON_X2H, cpu2aon_x2h_clk, "cpu2aon-x2h", axi_aclk_pd, -+ 0x138, BIT(8), CLK_IGNORE_UNUSED); - static CCU_GATE(CLK_CPU2PERI_X2H, cpu2peri_x2h_clk, "cpu2peri-x2h", axi4_cpusys2_aclk_pd, - 0x140, BIT(9), CLK_IGNORE_UNUSED); - static CCU_GATE(CLK_PERISYS_APB1_HCLK, perisys_apb1_hclk, "perisys-apb1-hclk", perisys_ahb_hclk_pd, -- 0x150, BIT(9), 0); -+ 0x150, BIT(9), CLK_IGNORE_UNUSED); - static CCU_GATE(CLK_PERISYS_APB2_HCLK, perisys_apb2_hclk, "perisys-apb2-hclk", perisys_ahb_hclk_pd, - 0x150, BIT(10), CLK_IGNORE_UNUSED); - static CCU_GATE(CLK_PERISYS_APB3_HCLK, perisys_apb3_hclk, "perisys-apb3-hclk", perisys_ahb_hclk_pd, -@@ -917,15 +918,9 @@ static const struct clk_parent_data uart - }; - - static struct ccu_mux uart_sclk = { -- .mux = TH_CCU_ARG(0, 1), -- .common = { -- .clkid = CLK_UART_SCLK, -- .cfg0 = 0x210, -- .hw.init = CLK_HW_INIT_PARENTS_DATA("uart-sclk", -- uart_sclk_parents, -- &clk_mux_ops, -- 0), -- } -+ .clkid = CLK_UART_SCLK, -+ .reg = 0x210, -+ .mux = TH_CCU_MUX("uart-sclk", uart_sclk_parents, 0, 1), - }; - - static struct ccu_common *th1520_pll_clks[] = { -@@ -962,10 +957,10 @@ static struct ccu_common *th1520_div_clk - &dpu1_clk.common, - }; - --static struct ccu_common *th1520_mux_clks[] = { -- &c910_i0_clk.common, -- &c910_clk.common, -- &uart_sclk.common, -+static struct ccu_mux *th1520_mux_clks[] = { -+ &c910_i0_clk, -+ &c910_clk, -+ &uart_sclk, - }; - - static struct ccu_common *th1520_gate_clks[] = { -@@ -1067,7 +1062,7 @@ static const struct regmap_config th1520 - struct th1520_plat_data { - struct ccu_common **th1520_pll_clks; - struct ccu_common **th1520_div_clks; -- struct ccu_common **th1520_mux_clks; -+ struct ccu_mux **th1520_mux_clks; - struct ccu_common **th1520_gate_clks; - - int nr_clks; -@@ -1154,23 +1149,15 @@ static int th1520_clk_probe(struct platf - } - - for (i = 0; i < plat_data->nr_mux_clks; i++) { -- struct ccu_mux *cm = hw_to_ccu_mux(&plat_data->th1520_mux_clks[i]->hw); -- const struct clk_init_data *init = cm->common.hw.init; -+ struct ccu_mux *cm = plat_data->th1520_mux_clks[i]; -+ -+ cm->mux.reg = base + cm->reg; - -- plat_data->th1520_mux_clks[i]->map = map; -- hw = devm_clk_hw_register_mux_parent_data_table(dev, -- init->name, -- init->parent_data, -- init->num_parents, -- 0, -- base + cm->common.cfg0, -- cm->mux.shift, -- cm->mux.width, -- 0, NULL, NULL); -- if (IS_ERR(hw)) -- return PTR_ERR(hw); -+ ret = devm_clk_hw_register(dev, &cm->mux.hw); -+ if (ret) -+ return ret; - -- priv->hws[cm->common.clkid] = hw; -+ priv->hws[cm->clkid] = &cm->mux.hw; - } - - for (i = 0; i < plat_data->nr_gate_clks; i++) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/clk/xilinx/clk-xlnx-clock-wizard.c BPI-Router-Linux-kernel-6.16.12/drivers/clk/xilinx/clk-xlnx-clock-wizard.c ---- BPI-Router-Linux-kernel/drivers/clk/xilinx/clk-xlnx-clock-wizard.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/clk/xilinx/clk-xlnx-clock-wizard.c 2025-10-22 13:53:56.423169585 -0400 -@@ -669,7 +669,7 @@ static long clk_wzrd_ver_round_rate_all( - u32 m, d, o, div, f; - int err; - -- err = clk_wzrd_get_divisors(hw, rate, *prate); -+ err = clk_wzrd_get_divisors_ver(hw, rate, *prate); - if (err) - return err; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/clk/xilinx/xlnx_vcu.c BPI-Router-Linux-kernel-6.16.12/drivers/clk/xilinx/xlnx_vcu.c ---- BPI-Router-Linux-kernel/drivers/clk/xilinx/xlnx_vcu.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/clk/xilinx/xlnx_vcu.c 2025-10-22 13:53:56.423169585 -0400 -@@ -587,8 +587,8 @@ static void xvcu_unregister_clock_provid - xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_ENC_MCU]); - if (!IS_ERR_OR_NULL(hws[CLK_XVCU_ENC_CORE])) - xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_ENC_CORE]); -- -- clk_hw_unregister_fixed_factor(xvcu->pll_post); -+ if (!IS_ERR_OR_NULL(xvcu->pll_post)) -+ clk_hw_unregister_fixed_factor(xvcu->pll_post); - } - - /** -diff -purNx .git BPI-Router-Linux-kernel/drivers/clocksource/hyperv_timer.c BPI-Router-Linux-kernel-6.16.12/drivers/clocksource/hyperv_timer.c ---- BPI-Router-Linux-kernel/drivers/clocksource/hyperv_timer.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/clocksource/hyperv_timer.c 2025-10-22 13:53:56.423169585 -0400 -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - #include - #include - #include -diff -purNx .git BPI-Router-Linux-kernel/drivers/comedi/comedi_fops.c BPI-Router-Linux-kernel-6.16.12/drivers/comedi/comedi_fops.c ---- BPI-Router-Linux-kernel/drivers/comedi/comedi_fops.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/comedi/comedi_fops.c 2025-10-22 13:53:56.423169585 -0400 -@@ -787,6 +787,7 @@ static int is_device_busy(struct comedi_ - struct comedi_subdevice *s; - int i; - -+ lockdep_assert_held_write(&dev->attach_lock); - lockdep_assert_held(&dev->mutex); - if (!dev->attached) - return 0; -@@ -795,7 +796,16 @@ static int is_device_busy(struct comedi_ - s = &dev->subdevices[i]; - if (s->busy) - return 1; -- if (s->async && comedi_buf_is_mmapped(s)) -+ if (!s->async) -+ continue; -+ if (comedi_buf_is_mmapped(s)) -+ return 1; -+ /* -+ * There may be tasks still waiting on the subdevice's wait -+ * queue, although they should already be about to be removed -+ * from it since the subdevice has no active async command. -+ */ -+ if (wq_has_sleeper(&s->async->wait_head)) - return 1; - } - -@@ -825,15 +835,22 @@ static int do_devconfig_ioctl(struct com - return -EPERM; - - if (!arg) { -- if (is_device_busy(dev)) -- return -EBUSY; -+ int rc = 0; -+ - if (dev->attached) { -- struct module *driver_module = dev->driver->module; -+ down_write(&dev->attach_lock); -+ if (is_device_busy(dev)) { -+ rc = -EBUSY; -+ } else { -+ struct module *driver_module = -+ dev->driver->module; - -- comedi_device_detach(dev); -- module_put(driver_module); -+ comedi_device_detach_locked(dev); -+ module_put(driver_module); -+ } -+ up_write(&dev->attach_lock); - } -- return 0; -+ return rc; - } - - if (copy_from_user(&it, arg, sizeof(it))) -@@ -1556,21 +1573,30 @@ static int do_insnlist_ioctl(struct come - } - - for (i = 0; i < n_insns; ++i) { -+ unsigned int n = insns[i].n; -+ - if (insns[i].insn & INSN_MASK_WRITE) { - if (copy_from_user(data, insns[i].data, -- insns[i].n * sizeof(unsigned int))) { -+ n * sizeof(unsigned int))) { - dev_dbg(dev->class_dev, - "copy_from_user failed\n"); - ret = -EFAULT; - goto error; - } -+ if (n < MIN_SAMPLES) { -+ memset(&data[n], 0, (MIN_SAMPLES - n) * -+ sizeof(unsigned int)); -+ } -+ } else { -+ memset(data, 0, max_t(unsigned int, n, MIN_SAMPLES) * -+ sizeof(unsigned int)); - } - ret = parse_insn(dev, insns + i, data, file); - if (ret < 0) - goto error; - if (insns[i].insn & INSN_MASK_READ) { - if (copy_to_user(insns[i].data, data, -- insns[i].n * sizeof(unsigned int))) { -+ n * sizeof(unsigned int))) { - dev_dbg(dev->class_dev, - "copy_to_user failed\n"); - ret = -EFAULT; -@@ -1589,6 +1615,16 @@ error: - return i; - } - -+#define MAX_INSNS MAX_SAMPLES -+static int check_insnlist_len(struct comedi_device *dev, unsigned int n_insns) -+{ -+ if (n_insns > MAX_INSNS) { -+ dev_dbg(dev->class_dev, "insnlist length too large\n"); -+ return -EINVAL; -+ } -+ return 0; -+} -+ - /* - * COMEDI_INSN ioctl - * synchronous instruction -@@ -1633,6 +1669,12 @@ static int do_insn_ioctl(struct comedi_d - ret = -EFAULT; - goto error; - } -+ if (insn->n < MIN_SAMPLES) { -+ memset(&data[insn->n], 0, -+ (MIN_SAMPLES - insn->n) * sizeof(unsigned int)); -+ } -+ } else { -+ memset(data, 0, n_data * sizeof(unsigned int)); - } - ret = parse_insn(dev, insn, data, file); - if (ret < 0) -@@ -2239,6 +2281,9 @@ static long comedi_unlocked_ioctl(struct - rc = -EFAULT; - break; - } -+ rc = check_insnlist_len(dev, insnlist.n_insns); -+ if (rc) -+ break; - insns = kcalloc(insnlist.n_insns, sizeof(*insns), GFP_KERNEL); - if (!insns) { - rc = -ENOMEM; -@@ -3142,6 +3187,9 @@ static int compat_insnlist(struct file * - if (copy_from_user(&insnlist32, compat_ptr(arg), sizeof(insnlist32))) - return -EFAULT; - -+ rc = check_insnlist_len(dev, insnlist32.n_insns); -+ if (rc) -+ return rc; - insns = kcalloc(insnlist32.n_insns, sizeof(*insns), GFP_KERNEL); - if (!insns) - return -ENOMEM; -diff -purNx .git BPI-Router-Linux-kernel/drivers/comedi/comedi_internal.h BPI-Router-Linux-kernel-6.16.12/drivers/comedi/comedi_internal.h ---- BPI-Router-Linux-kernel/drivers/comedi/comedi_internal.h 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/comedi/comedi_internal.h 2025-10-22 13:53:56.423169585 -0400 -@@ -50,6 +50,7 @@ extern struct mutex comedi_drivers_list_ - int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); - -+void comedi_device_detach_locked(struct comedi_device *dev); - void comedi_device_detach(struct comedi_device *dev); - int comedi_device_attach(struct comedi_device *dev, - struct comedi_devconfig *it); -diff -purNx .git BPI-Router-Linux-kernel/drivers/comedi/drivers/aio_iiro_16.c BPI-Router-Linux-kernel-6.16.12/drivers/comedi/drivers/aio_iiro_16.c ---- BPI-Router-Linux-kernel/drivers/comedi/drivers/aio_iiro_16.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/comedi/drivers/aio_iiro_16.c 2025-10-22 13:53:56.423169585 -0400 -@@ -177,7 +177,8 @@ static int aio_iiro_16_attach(struct com - * Digital input change of state interrupts are optionally supported - * using IRQ 2-7, 10-12, 14, or 15. - */ -- if ((1 << it->options[1]) & 0xdcfc) { -+ if (it->options[1] > 0 && it->options[1] < 16 && -+ (1 << it->options[1]) & 0xdcfc) { - ret = request_irq(it->options[1], aio_iiro_16_cos, 0, - dev->board_name, dev); - if (ret == 0) -diff -purNx .git BPI-Router-Linux-kernel/drivers/comedi/drivers/comedi_test.c BPI-Router-Linux-kernel-6.16.12/drivers/comedi/drivers/comedi_test.c ---- BPI-Router-Linux-kernel/drivers/comedi/drivers/comedi_test.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/comedi/drivers/comedi_test.c 2025-10-22 13:53:56.423169585 -0400 -@@ -792,7 +792,7 @@ static void waveform_detach(struct comed - { - struct waveform_private *devpriv = dev->private; - -- if (devpriv) { -+ if (devpriv && dev->n_subdevices) { - timer_delete_sync(&devpriv->ai_timer); - timer_delete_sync(&devpriv->ao_timer); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/comedi/drivers/das16m1.c BPI-Router-Linux-kernel-6.16.12/drivers/comedi/drivers/das16m1.c ---- BPI-Router-Linux-kernel/drivers/comedi/drivers/das16m1.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/comedi/drivers/das16m1.c 2025-10-22 13:53:56.423169585 -0400 -@@ -522,7 +522,8 @@ static int das16m1_attach(struct comedi_ - devpriv->extra_iobase = dev->iobase + DAS16M1_8255_IOBASE; - - /* only irqs 2, 3, 4, 5, 6, 7, 10, 11, 12, 14, and 15 are valid */ -- if ((1 << it->options[1]) & 0xdcfc) { -+ if (it->options[1] >= 2 && it->options[1] <= 15 && -+ (1 << it->options[1]) & 0xdcfc) { - ret = request_irq(it->options[1], das16m1_interrupt, 0, - dev->board_name, dev); - if (ret == 0) -diff -purNx .git BPI-Router-Linux-kernel/drivers/comedi/drivers/das6402.c BPI-Router-Linux-kernel-6.16.12/drivers/comedi/drivers/das6402.c ---- BPI-Router-Linux-kernel/drivers/comedi/drivers/das6402.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/comedi/drivers/das6402.c 2025-10-22 13:53:56.423169585 -0400 -@@ -567,7 +567,8 @@ static int das6402_attach(struct comedi_ - das6402_reset(dev); - - /* IRQs 2,3,5,6,7, 10,11,15 are valid for "enhanced" mode */ -- if ((1 << it->options[1]) & 0x8cec) { -+ if (it->options[1] > 0 && it->options[1] < 16 && -+ (1 << it->options[1]) & 0x8cec) { - ret = request_irq(it->options[1], das6402_interrupt, 0, - dev->board_name, dev); - if (ret == 0) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/comedi/drivers/pcl726.c BPI-Router-Linux-kernel-6.16.12/drivers/comedi/drivers/pcl726.c ---- BPI-Router-Linux-kernel/drivers/comedi/drivers/pcl726.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/comedi/drivers/pcl726.c 2025-10-22 13:53:56.423169585 -0400 -@@ -328,7 +328,8 @@ static int pcl726_attach(struct comedi_d - * Hook up the external trigger source interrupt only if the - * user config option is valid and the board supports interrupts. - */ -- if (it->options[1] && (board->irq_mask & (1 << it->options[1]))) { -+ if (it->options[1] > 0 && it->options[1] < 16 && -+ (board->irq_mask & (1U << it->options[1]))) { - ret = request_irq(it->options[1], pcl726_interrupt, 0, - dev->board_name, dev); - if (ret == 0) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/comedi/drivers/pcl812.c BPI-Router-Linux-kernel-6.16.12/drivers/comedi/drivers/pcl812.c ---- BPI-Router-Linux-kernel/drivers/comedi/drivers/pcl812.c 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/comedi/drivers/pcl812.c 2025-10-22 13:53:56.423169585 -0400 -@@ -1149,7 +1149,8 @@ static int pcl812_attach(struct comedi_d - if (IS_ERR(dev->pacer)) - return PTR_ERR(dev->pacer); - -- if ((1 << it->options[1]) & board->irq_bits) { -+ if (it->options[1] > 0 && it->options[1] < 16 && -+ (1 << it->options[1]) & board->irq_bits) { - ret = request_irq(it->options[1], pcl812_interrupt, 0, - dev->board_name, dev); - if (ret == 0) -diff -purNx .git BPI-Router-Linux-kernel/drivers/comedi/drivers.c BPI-Router-Linux-kernel-6.16.12/drivers/comedi/drivers.c ---- BPI-Router-Linux-kernel/drivers/comedi/drivers.c 2025-10-22 13:53:23.175329316 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/comedi/drivers.c 2025-10-22 13:53:56.423169585 -0400 -@@ -158,7 +158,7 @@ static void comedi_device_detach_cleanup - int i; - struct comedi_subdevice *s; - -- lockdep_assert_held(&dev->attach_lock); -+ lockdep_assert_held_write(&dev->attach_lock); - lockdep_assert_held(&dev->mutex); - if (dev->subdevices) { - for (i = 0; i < dev->n_subdevices; i++) { -@@ -196,16 +196,23 @@ static void comedi_device_detach_cleanup - comedi_clear_hw_dev(dev); - } - --void comedi_device_detach(struct comedi_device *dev) -+void comedi_device_detach_locked(struct comedi_device *dev) - { -+ lockdep_assert_held_write(&dev->attach_lock); - lockdep_assert_held(&dev->mutex); - comedi_device_cancel_all(dev); -- down_write(&dev->attach_lock); - dev->attached = false; - dev->detach_count++; - if (dev->driver) - dev->driver->detach(dev); - comedi_device_detach_cleanup(dev); -+} -+ -+void comedi_device_detach(struct comedi_device *dev) -+{ -+ lockdep_assert_held(&dev->mutex); -+ down_write(&dev->attach_lock); -+ comedi_device_detach_locked(dev); - up_write(&dev->attach_lock); - } - -@@ -339,10 +346,10 @@ int comedi_dio_insn_config(struct comedi - unsigned int *data, - unsigned int mask) - { -- unsigned int chan_mask = 1 << CR_CHAN(insn->chanspec); -+ unsigned int chan = CR_CHAN(insn->chanspec); - -- if (!mask) -- mask = chan_mask; -+ if (!mask && chan < 32) -+ mask = 1U << chan; - - switch (data[0]) { - case INSN_CONFIG_DIO_INPUT: -@@ -382,7 +389,7 @@ EXPORT_SYMBOL_GPL(comedi_dio_insn_config - unsigned int comedi_dio_update_state(struct comedi_subdevice *s, - unsigned int *data) - { -- unsigned int chanmask = (s->n_chan < 32) ? ((1 << s->n_chan) - 1) -+ unsigned int chanmask = (s->n_chan < 32) ? ((1U << s->n_chan) - 1) - : 0xffffffff; - unsigned int mask = data[0] & chanmask; - unsigned int bits = data[1]; -@@ -613,6 +620,7 @@ static int insn_rw_emulate_bits(struct c - unsigned int chan = CR_CHAN(insn->chanspec); - unsigned int base_chan = (chan < 32) ? 0 : chan; - unsigned int _data[2]; -+ unsigned int i; - int ret; - - memset(_data, 0, sizeof(_data)); -@@ -625,18 +633,21 @@ static int insn_rw_emulate_bits(struct c - if (insn->insn == INSN_WRITE) { - if (!(s->subdev_flags & SDF_WRITABLE)) - return -EINVAL; -- _data[0] = 1 << (chan - base_chan); /* mask */ -- _data[1] = data[0] ? (1 << (chan - base_chan)) : 0; /* bits */ -+ _data[0] = 1U << (chan - base_chan); /* mask */ - } -+ for (i = 0; i < insn->n; i++) { -+ if (insn->insn == INSN_WRITE) -+ _data[1] = data[i] ? _data[0] : 0; /* bits */ - -- ret = s->insn_bits(dev, s, &_insn, _data); -- if (ret < 0) -- return ret; -+ ret = s->insn_bits(dev, s, &_insn, _data); -+ if (ret < 0) -+ return ret; - -- if (insn->insn == INSN_READ) -- data[0] = (_data[1] >> (chan - base_chan)) & 1; -+ if (insn->insn == INSN_READ) -+ data[i] = (_data[1] >> (chan - base_chan)) & 1; -+ } - -- return 1; -+ return insn->n; - } - - static int __comedi_device_postconfig_async(struct comedi_device *dev, -@@ -709,7 +720,7 @@ static int __comedi_device_postconfig(st - - if (s->type == COMEDI_SUBD_DO) { - if (s->n_chan < 32) -- s->io_bits = (1 << s->n_chan) - 1; -+ s->io_bits = (1U << s->n_chan) - 1; - else - s->io_bits = 0xffffffff; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/cpufreq/amd-pstate.c BPI-Router-Linux-kernel-6.16.12/drivers/cpufreq/amd-pstate.c ---- BPI-Router-Linux-kernel/drivers/cpufreq/amd-pstate.c 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/cpufreq/amd-pstate.c 2025-10-22 13:53:56.423169585 -0400 -@@ -1547,13 +1547,15 @@ static void amd_pstate_epp_cpu_exit(stru - pr_debug("CPU %d exiting\n", policy->cpu); - } - --static int amd_pstate_epp_update_limit(struct cpufreq_policy *policy) -+static int amd_pstate_epp_update_limit(struct cpufreq_policy *policy, bool policy_change) - { - struct amd_cpudata *cpudata = policy->driver_data; - union perf_cached perf; - u8 epp; - -- if (policy->min != cpudata->min_limit_freq || policy->max != cpudata->max_limit_freq) -+ if (policy_change || -+ policy->min != cpudata->min_limit_freq || -+ policy->max != cpudata->max_limit_freq) - amd_pstate_update_min_max_limit(policy); - - if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) -@@ -1577,7 +1579,7 @@ static int amd_pstate_epp_set_policy(str - - cpudata->policy = policy->policy; - -- ret = amd_pstate_epp_update_limit(policy); -+ ret = amd_pstate_epp_update_limit(policy, true); - if (ret) - return ret; - -@@ -1619,13 +1621,14 @@ static int amd_pstate_suspend(struct cpu - * min_perf value across kexec reboots. If this CPU is just resumed back without kexec, - * the limits, epp and desired perf will get reset to the cached values in cpudata struct - */ -- ret = amd_pstate_update_perf(policy, perf.bios_min_perf, 0U, 0U, 0U, false); -+ ret = amd_pstate_update_perf(policy, perf.bios_min_perf, -+ FIELD_GET(AMD_CPPC_DES_PERF_MASK, cpudata->cppc_req_cached), -+ FIELD_GET(AMD_CPPC_MAX_PERF_MASK, cpudata->cppc_req_cached), -+ FIELD_GET(AMD_CPPC_EPP_PERF_MASK, cpudata->cppc_req_cached), -+ false); - if (ret) - return ret; - -- /* invalidate to ensure it's rewritten during resume */ -- cpudata->cppc_req_cached = 0; -- - /* set this flag to avoid setting core offline*/ - cpudata->suspended = true; - -@@ -1651,7 +1654,7 @@ static int amd_pstate_epp_resume(struct - int ret; - - /* enable amd pstate from suspend state*/ -- ret = amd_pstate_epp_update_limit(policy); -+ ret = amd_pstate_epp_update_limit(policy, false); - if (ret) - return ret; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/cpufreq/armada-8k-cpufreq.c BPI-Router-Linux-kernel-6.16.12/drivers/cpufreq/armada-8k-cpufreq.c ---- BPI-Router-Linux-kernel/drivers/cpufreq/armada-8k-cpufreq.c 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/cpufreq/armada-8k-cpufreq.c 2025-10-22 13:53:56.423169585 -0400 -@@ -103,7 +103,7 @@ static void armada_8k_cpufreq_free_table - { - int opps_index, nb_cpus = num_possible_cpus(); - -- for (opps_index = 0 ; opps_index <= nb_cpus; opps_index++) { -+ for (opps_index = 0 ; opps_index < nb_cpus; opps_index++) { - int i; - - /* If cpu_dev is NULL then we reached the end of the array */ -@@ -132,7 +132,7 @@ static int __init armada_8k_cpufreq_init - int ret = 0, opps_index = 0, cpu, nb_cpus; - struct freq_table *freq_tables; - struct device_node *node; -- static struct cpumask cpus; -+ static struct cpumask cpus, shared_cpus; - - node = of_find_matching_node_and_match(NULL, armada_8k_cpufreq_of_match, - NULL); -@@ -154,7 +154,6 @@ static int __init armada_8k_cpufreq_init - * divisions of it). - */ - for_each_cpu(cpu, &cpus) { -- struct cpumask shared_cpus; - struct device *cpu_dev; - struct clk *clk; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/cpufreq/cppc_cpufreq.c BPI-Router-Linux-kernel-6.16.12/drivers/cpufreq/cppc_cpufreq.c ---- BPI-Router-Linux-kernel/drivers/cpufreq/cppc_cpufreq.c 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/cpufreq/cppc_cpufreq.c 2025-10-22 13:53:56.423169585 -0400 -@@ -925,7 +925,7 @@ static struct freq_attr *cppc_cpufreq_at - }; - - static struct cpufreq_driver cppc_cpufreq_driver = { -- .flags = CPUFREQ_CONST_LOOPS, -+ .flags = CPUFREQ_CONST_LOOPS | CPUFREQ_NEED_UPDATE_LIMITS, - .verify = cppc_verify_policy, - .target = cppc_cpufreq_set_target, - .get = cppc_cpufreq_get_rate, -diff -purNx .git BPI-Router-Linux-kernel/drivers/cpufreq/cpufreq.c BPI-Router-Linux-kernel-6.16.12/drivers/cpufreq/cpufreq.c ---- BPI-Router-Linux-kernel/drivers/cpufreq/cpufreq.c 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/cpufreq/cpufreq.c 2025-10-22 13:53:56.423169585 -0400 -@@ -1284,6 +1284,8 @@ static struct cpufreq_policy *cpufreq_po - goto err_free_real_cpus; - } - -+ init_rwsem(&policy->rwsem); -+ - freq_constraints_init(&policy->constraints); - - policy->nb_min.notifier_call = cpufreq_notifier_min; -@@ -1306,7 +1308,6 @@ static struct cpufreq_policy *cpufreq_po - } - - INIT_LIST_HEAD(&policy->policy_list); -- init_rwsem(&policy->rwsem); - spin_lock_init(&policy->transition_lock); - init_waitqueue_head(&policy->transition_wait); - INIT_WORK(&policy->update, handle_update); -@@ -2715,10 +2716,12 @@ static int cpufreq_set_policy(struct cpu - pr_debug("starting governor %s failed\n", policy->governor->name); - if (old_gov) { - policy->governor = old_gov; -- if (cpufreq_init_governor(policy)) -+ if (cpufreq_init_governor(policy)) { - policy->governor = NULL; -- else -- cpufreq_start_governor(policy); -+ } else if (cpufreq_start_governor(policy)) { -+ cpufreq_exit_governor(policy); -+ policy->governor = NULL; -+ } - } - - return ret; -@@ -2944,15 +2947,6 @@ int cpufreq_register_driver(struct cpufr - cpufreq_driver = driver_data; - write_unlock_irqrestore(&cpufreq_driver_lock, flags); - -- /* -- * Mark support for the scheduler's frequency invariance engine for -- * drivers that implement target(), target_index() or fast_switch(). -- */ -- if (!cpufreq_driver->setpolicy) { -- static_branch_enable_cpuslocked(&cpufreq_freq_invariance); -- pr_debug("supports frequency invariance"); -- } -- - if (driver_data->setpolicy) - driver_data->flags |= CPUFREQ_CONST_LOOPS; - -@@ -2962,6 +2956,15 @@ int cpufreq_register_driver(struct cpufr - goto err_null_driver; - } - -+ /* -+ * Mark support for the scheduler's frequency invariance engine for -+ * drivers that implement target(), target_index() or fast_switch(). -+ */ -+ if (!cpufreq_driver->setpolicy) { -+ static_branch_enable_cpuslocked(&cpufreq_freq_invariance); -+ pr_debug("cpufreq: supports frequency invariance\n"); -+ } -+ - ret = subsys_interface_register(&cpufreq_interface); - if (ret) - goto err_boost_unreg; -@@ -2989,6 +2992,8 @@ int cpufreq_register_driver(struct cpufr - err_if_unreg: - subsys_interface_unregister(&cpufreq_interface); - err_boost_unreg: -+ if (!cpufreq_driver->setpolicy) -+ static_branch_disable_cpuslocked(&cpufreq_freq_invariance); - remove_boost_sysfs_file(); - err_null_driver: - write_lock_irqsave(&cpufreq_driver_lock, flags); -diff -purNx .git BPI-Router-Linux-kernel/drivers/cpufreq/intel_pstate.c BPI-Router-Linux-kernel-6.16.12/drivers/cpufreq/intel_pstate.c ---- BPI-Router-Linux-kernel/drivers/cpufreq/intel_pstate.c 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/cpufreq/intel_pstate.c 2025-10-22 13:53:56.423169585 -0400 -@@ -1034,8 +1034,8 @@ static bool hybrid_register_perf_domain( - if (!cpu_dev) - return false; - -- if (em_dev_register_perf_domain(cpu_dev, HYBRID_EM_STATE_COUNT, &cb, -- cpumask_of(cpu), false)) -+ if (em_dev_register_pd_no_update(cpu_dev, HYBRID_EM_STATE_COUNT, &cb, -+ cpumask_of(cpu), false)) - return false; - - cpudata->pd_registered = true; -@@ -2775,6 +2775,8 @@ static const struct x86_cpu_id intel_pst - X86_MATCH(INTEL_TIGERLAKE, core_funcs), - X86_MATCH(INTEL_SAPPHIRERAPIDS_X, core_funcs), - X86_MATCH(INTEL_EMERALDRAPIDS_X, core_funcs), -+ X86_MATCH(INTEL_GRANITERAPIDS_D, core_funcs), -+ X86_MATCH(INTEL_GRANITERAPIDS_X, core_funcs), - {} - }; - MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids); -@@ -3249,8 +3251,8 @@ static int intel_cpufreq_update_pstate(s - int max_pstate = policy->strict_target ? - target_pstate : cpu->max_perf_ratio; - -- intel_cpufreq_hwp_update(cpu, target_pstate, max_pstate, 0, -- fast_switch); -+ intel_cpufreq_hwp_update(cpu, target_pstate, max_pstate, -+ target_pstate, fast_switch); - } else if (target_pstate != old_pstate) { - intel_cpufreq_perf_ctl_update(cpu, target_pstate, fast_switch); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/cpufreq/Makefile BPI-Router-Linux-kernel-6.16.12/drivers/cpufreq/Makefile ---- BPI-Router-Linux-kernel/drivers/cpufreq/Makefile 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/cpufreq/Makefile 2025-10-22 13:53:56.423169585 -0400 -@@ -21,6 +21,7 @@ obj-$(CONFIG_CPUFREQ_VIRT) += virtual-c - - # Traces - CFLAGS_amd-pstate-trace.o := -I$(src) -+CFLAGS_powernv-cpufreq.o := -I$(src) - amd_pstate-y := amd-pstate.o amd-pstate-trace.o - - ################################################################################## -diff -purNx .git BPI-Router-Linux-kernel/drivers/cpufreq/powernv-cpufreq.c BPI-Router-Linux-kernel-6.16.12/drivers/cpufreq/powernv-cpufreq.c ---- BPI-Router-Linux-kernel/drivers/cpufreq/powernv-cpufreq.c 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/cpufreq/powernv-cpufreq.c 2025-10-22 13:53:56.427169565 -0400 -@@ -21,7 +21,6 @@ - #include - #include - #include --#include - - #include - #include -@@ -30,6 +29,9 @@ - #include - #include - -+#define CREATE_TRACE_POINTS -+#include "powernv-trace.h" -+ - #define POWERNV_MAX_PSTATES_ORDER 8 - #define POWERNV_MAX_PSTATES (1UL << (POWERNV_MAX_PSTATES_ORDER)) - #define PMSR_PSAFE_ENABLE (1UL << 30) -diff -purNx .git BPI-Router-Linux-kernel/drivers/cpufreq/powernv-trace.h BPI-Router-Linux-kernel-6.16.12/drivers/cpufreq/powernv-trace.h ---- BPI-Router-Linux-kernel/drivers/cpufreq/powernv-trace.h 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/cpufreq/powernv-trace.h 2025-10-22 13:53:56.427169565 -0400 -@@ -0,0 +1,44 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+ -+#if !defined(_POWERNV_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) -+#define _POWERNV_TRACE_H -+ -+#include -+#include -+#include -+ -+#undef TRACE_SYSTEM -+#define TRACE_SYSTEM power -+ -+TRACE_EVENT(powernv_throttle, -+ -+ TP_PROTO(int chip_id, const char *reason, int pmax), -+ -+ TP_ARGS(chip_id, reason, pmax), -+ -+ TP_STRUCT__entry( -+ __field(int, chip_id) -+ __string(reason, reason) -+ __field(int, pmax) -+ ), -+ -+ TP_fast_assign( -+ __entry->chip_id = chip_id; -+ __assign_str(reason); -+ __entry->pmax = pmax; -+ ), -+ -+ TP_printk("Chip %d Pmax %d %s", __entry->chip_id, -+ __entry->pmax, __get_str(reason)) -+); -+ -+#endif /* _POWERNV_TRACE_H */ -+ -+/* This part must be outside protection */ -+#undef TRACE_INCLUDE_PATH -+#define TRACE_INCLUDE_PATH . -+ -+#undef TRACE_INCLUDE_FILE -+#define TRACE_INCLUDE_FILE powernv-trace -+ -+#include -diff -purNx .git BPI-Router-Linux-kernel/drivers/cpufreq/rcpufreq_dt.rs BPI-Router-Linux-kernel-6.16.12/drivers/cpufreq/rcpufreq_dt.rs ---- BPI-Router-Linux-kernel/drivers/cpufreq/rcpufreq_dt.rs 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/cpufreq/rcpufreq_dt.rs 2025-10-22 13:53:56.427169565 -0400 -@@ -26,9 +26,9 @@ fn find_supply_name_exact(dev: &Device, - } - - /// Finds supply name for the CPU from DT. --fn find_supply_names(dev: &Device, cpu: u32) -> Option> { -+fn find_supply_names(dev: &Device, cpu: cpu::CpuId) -> Option> { - // Try "cpu0" for older DTs, fallback to "cpu". -- let name = (cpu == 0) -+ let name = (cpu.as_u32() == 0) - .then(|| find_supply_name_exact(dev, "cpu0")) - .flatten() - .or_else(|| find_supply_name_exact(dev, "cpu"))?; -diff -purNx .git BPI-Router-Linux-kernel/drivers/cpuidle/cpuidle-psci.c BPI-Router-Linux-kernel-6.16.12/drivers/cpuidle/cpuidle-psci.c ---- BPI-Router-Linux-kernel/drivers/cpuidle/cpuidle-psci.c 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/cpuidle/cpuidle-psci.c 2025-10-22 13:53:56.427169565 -0400 -@@ -45,7 +45,6 @@ struct psci_cpuidle_domain_state { - static DEFINE_PER_CPU_READ_MOSTLY(struct psci_cpuidle_data, psci_cpuidle_data); - static DEFINE_PER_CPU(struct psci_cpuidle_domain_state, psci_domain_state); - static bool psci_cpuidle_use_syscore; --static bool psci_cpuidle_use_cpuhp; - - void psci_set_domain_state(struct generic_pm_domain *pd, unsigned int state_idx, - u32 state) -@@ -124,8 +123,12 @@ static int psci_idle_cpuhp_up(unsigned i - { - struct device *pd_dev = __this_cpu_read(psci_cpuidle_data.dev); - -- if (pd_dev) -- pm_runtime_get_sync(pd_dev); -+ if (pd_dev) { -+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) -+ pm_runtime_get_sync(pd_dev); -+ else -+ dev_pm_genpd_resume(pd_dev); -+ } - - return 0; - } -@@ -135,7 +138,11 @@ static int psci_idle_cpuhp_down(unsigned - struct device *pd_dev = __this_cpu_read(psci_cpuidle_data.dev); - - if (pd_dev) { -- pm_runtime_put_sync(pd_dev); -+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) -+ pm_runtime_put_sync(pd_dev); -+ else -+ dev_pm_genpd_suspend(pd_dev); -+ - /* Clear domain state to start fresh at next online. */ - psci_clear_domain_state(); - } -@@ -196,9 +203,6 @@ static void psci_idle_init_cpuhp(void) - { - int err; - -- if (!psci_cpuidle_use_cpuhp) -- return; -- - err = cpuhp_setup_state_nocalls(CPUHP_AP_CPU_PM_STARTING, - "cpuidle/psci:online", - psci_idle_cpuhp_up, -@@ -259,10 +263,8 @@ static int psci_dt_cpu_init_topology(str - * s2ram and s2idle. - */ - drv->states[state_count - 1].enter_s2idle = psci_enter_s2idle_domain_idle_state; -- if (!IS_ENABLED(CONFIG_PREEMPT_RT)) { -+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) - drv->states[state_count - 1].enter = psci_enter_domain_idle_state; -- psci_cpuidle_use_cpuhp = true; -- } - - return 0; - } -@@ -339,7 +341,6 @@ static void psci_cpu_deinit_idle(int cpu - - dt_idle_detach_cpu(data->dev); - psci_cpuidle_use_syscore = false; -- psci_cpuidle_use_cpuhp = false; - } - - static int psci_idle_init_cpu(struct device *dev, int cpu) -diff -purNx .git BPI-Router-Linux-kernel/drivers/cpuidle/governors/menu.c BPI-Router-Linux-kernel-6.16.12/drivers/cpuidle/governors/menu.c ---- BPI-Router-Linux-kernel/drivers/cpuidle/governors/menu.c 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/cpuidle/governors/menu.c 2025-10-22 13:53:56.427169565 -0400 -@@ -97,6 +97,14 @@ static inline int which_bucket(u64 durat - - static DEFINE_PER_CPU(struct menu_device, menu_devices); - -+static void menu_update_intervals(struct menu_device *data, unsigned int interval_us) -+{ -+ /* Update the repeating-pattern data. */ -+ data->intervals[data->interval_ptr++] = interval_us; -+ if (data->interval_ptr >= INTERVALS) -+ data->interval_ptr = 0; -+} -+ - static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev); - - /* -@@ -222,6 +230,14 @@ static int menu_select(struct cpuidle_dr - if (data->needs_update) { - menu_update(drv, dev); - data->needs_update = 0; -+ } else if (!dev->last_residency_ns) { -+ /* -+ * This happens when the driver rejects the previously selected -+ * idle state and returns an error, so update the recent -+ * intervals table to prevent invalid information from being -+ * used going forward. -+ */ -+ menu_update_intervals(data, UINT_MAX); - } - - /* Find the shortest expected idle interval. */ -@@ -271,20 +287,15 @@ static int menu_select(struct cpuidle_dr - return 0; - } - -- if (tick_nohz_tick_stopped()) { -- /* -- * If the tick is already stopped, the cost of possible short -- * idle duration misprediction is much higher, because the CPU -- * may be stuck in a shallow idle state for a long time as a -- * result of it. In that case say we might mispredict and use -- * the known time till the closest timer event for the idle -- * state selection. -- */ -- if (predicted_ns < TICK_NSEC) -- predicted_ns = data->next_timer_ns; -- } else if (latency_req > predicted_ns) { -- latency_req = predicted_ns; -- } -+ /* -+ * If the tick is already stopped, the cost of possible short idle -+ * duration misprediction is much higher, because the CPU may be stuck -+ * in a shallow idle state for a long time as a result of it. In that -+ * case, say we might mispredict and use the known time till the closest -+ * timer event for the idle state selection. -+ */ -+ if (tick_nohz_tick_stopped() && predicted_ns < TICK_NSEC) -+ predicted_ns = data->next_timer_ns; - - /* - * Find the idle state with the lowest power while satisfying -@@ -300,13 +311,15 @@ static int menu_select(struct cpuidle_dr - if (idx == -1) - idx = i; /* first enabled state */ - -+ if (s->exit_latency_ns > latency_req) -+ break; -+ - if (s->target_residency_ns > predicted_ns) { - /* - * Use a physical idle state, not busy polling, unless - * a timer is going to trigger soon enough. - */ - if ((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) && -- s->exit_latency_ns <= latency_req && - s->target_residency_ns <= data->next_timer_ns) { - predicted_ns = s->target_residency_ns; - idx = i; -@@ -338,8 +351,6 @@ static int menu_select(struct cpuidle_dr - - return idx; - } -- if (s->exit_latency_ns > latency_req) -- break; - - idx = i; - } -@@ -482,10 +493,7 @@ static void menu_update(struct cpuidle_d - - data->correction_factor[data->bucket] = new_factor; - -- /* update the repeating-pattern data */ -- data->intervals[data->interval_ptr++] = ktime_to_us(measured_ns); -- if (data->interval_ptr >= INTERVALS) -- data->interval_ptr = 0; -+ menu_update_intervals(data, ktime_to_us(measured_ns)); - } - - /** -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c ---- BPI-Router-Linux-kernel/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c 2025-10-22 13:53:56.427169565 -0400 -@@ -278,8 +278,8 @@ static int sun8i_ce_cipher_prepare(struc - } - - chan->timeout = areq->cryptlen; -- rctx->nr_sgs = nr_sgs; -- rctx->nr_sgd = nr_sgd; -+ rctx->nr_sgs = ns; -+ rctx->nr_sgd = nd; - return 0; - - theend_sgs: -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/caam/ctrl.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/caam/ctrl.c ---- BPI-Router-Linux-kernel/drivers/crypto/caam/ctrl.c 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/caam/ctrl.c 2025-10-22 13:53:56.427169565 -0400 -@@ -573,7 +573,7 @@ static const struct soc_device_attribute - { .soc_id = "i.MX7*", .data = &caam_imx7_data }, - { .soc_id = "i.MX8M*", .data = &caam_imx7_data }, - { .soc_id = "i.MX8ULP", .data = &caam_imx8ulp_data }, -- { .soc_id = "i.MX8QM", .data = &caam_imx8ulp_data }, -+ { .soc_id = "i.MX8Q*", .data = &caam_imx8ulp_data }, - { .soc_id = "VF*", .data = &caam_vf610_data }, - { .family = "Freescale i.MX" }, - { /* sentinel */ } -@@ -831,7 +831,7 @@ static int caam_ctrl_suspend(struct devi - { - const struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev); - -- if (ctrlpriv->caam_off_during_pm && !ctrlpriv->optee_en) -+ if (ctrlpriv->caam_off_during_pm && !ctrlpriv->no_page0) - caam_state_save(dev); - - return 0; -@@ -842,7 +842,7 @@ static int caam_ctrl_resume(struct devic - struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev); - int ret = 0; - -- if (ctrlpriv->caam_off_during_pm && !ctrlpriv->optee_en) { -+ if (ctrlpriv->caam_off_during_pm && !ctrlpriv->no_page0) { - caam_state_restore(dev); - - /* HW and rng will be reset so deinstantiation can be removed */ -@@ -908,6 +908,7 @@ static int caam_probe(struct platform_de - - imx_soc_data = imx_soc_match->data; - reg_access = reg_access && imx_soc_data->page0_access; -+ ctrlpriv->no_page0 = !reg_access; - /* - * CAAM clocks cannot be controlled from kernel. - */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/caam/intern.h BPI-Router-Linux-kernel-6.16.12/drivers/crypto/caam/intern.h ---- BPI-Router-Linux-kernel/drivers/crypto/caam/intern.h 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/caam/intern.h 2025-10-22 13:53:56.427169565 -0400 -@@ -115,6 +115,7 @@ struct caam_drv_private { - u8 blob_present; /* Nonzero if BLOB support present in device */ - u8 mc_en; /* Nonzero if MC f/w is active */ - u8 optee_en; /* Nonzero if OP-TEE f/w is active */ -+ u8 no_page0; /* Nonzero if register page 0 is not controlled by Linux */ - bool pr_support; /* RNG prediction resistance available */ - int secvio_irq; /* Security violation interrupt number */ - int virt_en; /* Virtualization enabled in CAAM */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/ccp/ccp-debugfs.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/ccp/ccp-debugfs.c ---- BPI-Router-Linux-kernel/drivers/crypto/ccp/ccp-debugfs.c 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/ccp/ccp-debugfs.c 2025-10-22 13:53:56.427169565 -0400 -@@ -319,5 +319,8 @@ void ccp5_debugfs_setup(struct ccp_devic - - void ccp5_debugfs_destroy(void) - { -+ mutex_lock(&ccp_debugfs_lock); - debugfs_remove_recursive(ccp_debugfs_dir); -+ ccp_debugfs_dir = NULL; -+ mutex_unlock(&ccp_debugfs_lock); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/ccp/sev-dev.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/ccp/sev-dev.c ---- BPI-Router-Linux-kernel/drivers/crypto/ccp/sev-dev.c 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/ccp/sev-dev.c 2025-10-22 13:53:56.427169565 -0400 -@@ -434,7 +434,7 @@ cleanup: - return rc; - } - --static struct page *__snp_alloc_firmware_pages(gfp_t gfp_mask, int order) -+static struct page *__snp_alloc_firmware_pages(gfp_t gfp_mask, int order, bool locked) - { - unsigned long npages = 1ul << order, paddr; - struct sev_device *sev; -@@ -453,7 +453,7 @@ static struct page *__snp_alloc_firmware - return page; - - paddr = __pa((unsigned long)page_address(page)); -- if (rmp_mark_pages_firmware(paddr, npages, false)) -+ if (rmp_mark_pages_firmware(paddr, npages, locked)) - return NULL; - - return page; -@@ -463,7 +463,7 @@ void *snp_alloc_firmware_page(gfp_t gfp_ - { - struct page *page; - -- page = __snp_alloc_firmware_pages(gfp_mask, 0); -+ page = __snp_alloc_firmware_pages(gfp_mask, 0, false); - - return page ? page_address(page) : NULL; - } -@@ -498,7 +498,7 @@ static void *sev_fw_alloc(unsigned long - { - struct page *page; - -- page = __snp_alloc_firmware_pages(GFP_KERNEL, get_order(len)); -+ page = __snp_alloc_firmware_pages(GFP_KERNEL, get_order(len), true); - if (!page) - return NULL; - -@@ -1276,9 +1276,11 @@ static int __sev_platform_init_handle_in - - static int __sev_platform_init_locked(int *error) - { -- int rc, psp_ret = SEV_RET_NO_FW_CALL; -+ int rc, psp_ret, dfflush_error; - struct sev_device *sev; - -+ psp_ret = dfflush_error = SEV_RET_NO_FW_CALL; -+ - if (!psp_master || !psp_master->sev_data) - return -ENODEV; - -@@ -1320,10 +1322,10 @@ static int __sev_platform_init_locked(in - - /* Prepare for first SEV guest launch after INIT */ - wbinvd_on_all_cpus(); -- rc = __sev_do_cmd_locked(SEV_CMD_DF_FLUSH, NULL, error); -+ rc = __sev_do_cmd_locked(SEV_CMD_DF_FLUSH, NULL, &dfflush_error); - if (rc) { - dev_err(sev->dev, "SEV: DF_FLUSH failed %#x, rc %d\n", -- *error, rc); -+ dfflush_error, rc); - return rc; - } - -@@ -1785,8 +1787,14 @@ static int __sev_snp_shutdown_locked(int - sev->snp_initialized = false; - dev_dbg(sev->dev, "SEV-SNP firmware shutdown\n"); - -- atomic_notifier_chain_unregister(&panic_notifier_list, -- &snp_panic_notifier); -+ /* -+ * __sev_snp_shutdown_locked() deadlocks when it tries to unregister -+ * itself during panic as the panic notifier is called with RCU read -+ * lock held and notifier unregistration does RCU synchronization. -+ */ -+ if (!panic) -+ atomic_notifier_chain_unregister(&panic_notifier_list, -+ &snp_panic_notifier); - - /* Reset TMR size back to default */ - sev_es_tmr_size = SEV_TMR_SIZE; -@@ -2422,7 +2430,7 @@ static void __sev_firmware_shutdown(stru - { - int error; - -- __sev_platform_shutdown_locked(NULL); -+ __sev_platform_shutdown_locked(&error); - - if (sev_es_tmr) { - /* -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/ccp/sp-pci.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/ccp/sp-pci.c ---- BPI-Router-Linux-kernel/drivers/crypto/ccp/sp-pci.c 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/ccp/sp-pci.c 2025-10-22 13:53:56.427169565 -0400 -@@ -453,6 +453,7 @@ static const struct psp_vdata pspv6 = { - .cmdresp_reg = 0x10944, /* C2PMSG_17 */ - .cmdbuff_addr_lo_reg = 0x10948, /* C2PMSG_18 */ - .cmdbuff_addr_hi_reg = 0x1094c, /* C2PMSG_19 */ -+ .bootloader_info_reg = 0x109ec, /* C2PMSG_59 */ - .feature_reg = 0x109fc, /* C2PMSG_63 */ - .inten_reg = 0x10510, /* P2CMSG_INTEN */ - .intsts_reg = 0x10514, /* P2CMSG_INTSTS */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/chelsio/chcr_algo.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/chelsio/chcr_algo.c ---- BPI-Router-Linux-kernel/drivers/crypto/chelsio/chcr_algo.c 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/chelsio/chcr_algo.c 2025-10-22 13:53:56.427169565 -0400 -@@ -314,30 +314,30 @@ static int chcr_compute_partial_hash(str - if (digest_size == SHA1_DIGEST_SIZE) { - error = crypto_shash_init(desc) ?: - crypto_shash_update(desc, iopad, SHA1_BLOCK_SIZE) ?: -- crypto_shash_export(desc, (void *)&sha1_st); -+ crypto_shash_export_core(desc, &sha1_st); - memcpy(result_hash, sha1_st.state, SHA1_DIGEST_SIZE); - } else if (digest_size == SHA224_DIGEST_SIZE) { - error = crypto_shash_init(desc) ?: - crypto_shash_update(desc, iopad, SHA256_BLOCK_SIZE) ?: -- crypto_shash_export(desc, (void *)&sha256_st); -+ crypto_shash_export_core(desc, &sha256_st); - memcpy(result_hash, sha256_st.state, SHA256_DIGEST_SIZE); - - } else if (digest_size == SHA256_DIGEST_SIZE) { - error = crypto_shash_init(desc) ?: - crypto_shash_update(desc, iopad, SHA256_BLOCK_SIZE) ?: -- crypto_shash_export(desc, (void *)&sha256_st); -+ crypto_shash_export_core(desc, &sha256_st); - memcpy(result_hash, sha256_st.state, SHA256_DIGEST_SIZE); - - } else if (digest_size == SHA384_DIGEST_SIZE) { - error = crypto_shash_init(desc) ?: - crypto_shash_update(desc, iopad, SHA512_BLOCK_SIZE) ?: -- crypto_shash_export(desc, (void *)&sha512_st); -+ crypto_shash_export_core(desc, &sha512_st); - memcpy(result_hash, sha512_st.state, SHA512_DIGEST_SIZE); - - } else if (digest_size == SHA512_DIGEST_SIZE) { - error = crypto_shash_init(desc) ?: - crypto_shash_update(desc, iopad, SHA512_BLOCK_SIZE) ?: -- crypto_shash_export(desc, (void *)&sha512_st); -+ crypto_shash_export_core(desc, &sha512_st); - memcpy(result_hash, sha512_st.state, SHA512_DIGEST_SIZE); - } else { - error = -EINVAL; -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/hisilicon/hpre/hpre_crypto.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/hisilicon/hpre/hpre_crypto.c ---- BPI-Router-Linux-kernel/drivers/crypto/hisilicon/hpre/hpre_crypto.c 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/hisilicon/hpre/hpre_crypto.c 2025-10-22 13:53:56.427169565 -0400 -@@ -1491,11 +1491,13 @@ static void hpre_ecdh_cb(struct hpre_ctx - if (overtime_thrhld && hpre_is_bd_timeout(req, overtime_thrhld)) - atomic64_inc(&dfx[HPRE_OVER_THRHLD_CNT].value); - -+ /* Do unmap before data processing */ -+ hpre_ecdh_hw_data_clr_all(ctx, req, areq->dst, areq->src); -+ - p = sg_virt(areq->dst); - memmove(p, p + ctx->key_sz - curve_sz, curve_sz); - memmove(p + curve_sz, p + areq->dst_len - curve_sz, curve_sz); - -- hpre_ecdh_hw_data_clr_all(ctx, req, areq->dst, areq->src); - kpp_request_complete(areq, ret); - - atomic64_inc(&dfx[HPRE_RECV_CNT].value); -@@ -1808,9 +1810,11 @@ static void hpre_curve25519_cb(struct hp - if (overtime_thrhld && hpre_is_bd_timeout(req, overtime_thrhld)) - atomic64_inc(&dfx[HPRE_OVER_THRHLD_CNT].value); - -+ /* Do unmap before data processing */ -+ hpre_curve25519_hw_data_clr_all(ctx, req, areq->dst, areq->src); -+ - hpre_key_to_big_end(sg_virt(areq->dst), CURVE25519_KEY_SIZE); - -- hpre_curve25519_hw_data_clr_all(ctx, req, areq->dst, areq->src); - kpp_request_complete(areq, ret); - - atomic64_inc(&dfx[HPRE_RECV_CNT].value); -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/img-hash.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/img-hash.c ---- BPI-Router-Linux-kernel/drivers/crypto/img-hash.c 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/img-hash.c 2025-10-22 13:53:56.427169565 -0400 -@@ -436,7 +436,7 @@ static int img_hash_write_via_dma_stop(s - struct img_hash_request_ctx *ctx = ahash_request_ctx(hdev->req); - - if (ctx->flags & DRIVER_FLAGS_SG) -- dma_unmap_sg(hdev->dev, ctx->sg, ctx->dma_ct, DMA_TO_DEVICE); -+ dma_unmap_sg(hdev->dev, ctx->sg, 1, DMA_TO_DEVICE); - - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/inside-secure/safexcel_hash.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/inside-secure/safexcel_hash.c ---- BPI-Router-Linux-kernel/drivers/crypto/inside-secure/safexcel_hash.c 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/inside-secure/safexcel_hash.c 2025-10-22 13:53:56.427169565 -0400 -@@ -249,7 +249,9 @@ static int safexcel_handle_req_result(st - safexcel_complete(priv, ring); - - if (sreq->nents) { -- dma_unmap_sg(priv->dev, areq->src, sreq->nents, DMA_TO_DEVICE); -+ dma_unmap_sg(priv->dev, areq->src, -+ sg_nents_for_len(areq->src, areq->nbytes), -+ DMA_TO_DEVICE); - sreq->nents = 0; - } - -@@ -497,7 +499,9 @@ unmap_result: - DMA_FROM_DEVICE); - unmap_sg: - if (req->nents) { -- dma_unmap_sg(priv->dev, areq->src, req->nents, DMA_TO_DEVICE); -+ dma_unmap_sg(priv->dev, areq->src, -+ sg_nents_for_len(areq->src, areq->nbytes), -+ DMA_TO_DEVICE); - req->nents = 0; - } - cdesc_rollback: -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c ---- BPI-Router-Linux-kernel/drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c 2025-10-22 13:53:56.427169565 -0400 -@@ -68,6 +68,7 @@ struct ocs_hcu_ctx { - * @sg_data_total: Total data in the SG list at any time. - * @sg_data_offset: Offset into the data of the current individual SG node. - * @sg_dma_nents: Number of sg entries mapped in dma_list. -+ * @nents: Number of entries in the scatterlist. - */ - struct ocs_hcu_rctx { - struct ocs_hcu_dev *hcu_dev; -@@ -91,6 +92,7 @@ struct ocs_hcu_rctx { - unsigned int sg_data_total; - unsigned int sg_data_offset; - unsigned int sg_dma_nents; -+ unsigned int nents; - }; - - /** -@@ -199,7 +201,7 @@ static void kmb_ocs_hcu_dma_cleanup(stru - - /* Unmap req->src (if mapped). */ - if (rctx->sg_dma_nents) { -- dma_unmap_sg(dev, req->src, rctx->sg_dma_nents, DMA_TO_DEVICE); -+ dma_unmap_sg(dev, req->src, rctx->nents, DMA_TO_DEVICE); - rctx->sg_dma_nents = 0; - } - -@@ -260,6 +262,10 @@ static int kmb_ocs_dma_prepare(struct ah - rc = -ENOMEM; - goto cleanup; - } -+ -+ /* Save the value of nents to pass to dma_unmap_sg. */ -+ rctx->nents = nents; -+ - /* - * The value returned by dma_map_sg() can be < nents; so update - * nents accordingly. -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c ---- BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c 2025-10-22 13:53:56.427169565 -0400 -@@ -191,7 +191,6 @@ static u32 get_accel_cap(struct adf_acce - ICP_ACCEL_CAPABILITIES_SM4 | - ICP_ACCEL_CAPABILITIES_AES_V2 | - ICP_ACCEL_CAPABILITIES_ZUC | -- ICP_ACCEL_CAPABILITIES_ZUC_256 | - ICP_ACCEL_CAPABILITIES_WIRELESS_CRYPTO_EXT | - ICP_ACCEL_CAPABILITIES_EXT_ALGCHAIN; - -@@ -223,17 +222,11 @@ static u32 get_accel_cap(struct adf_acce - - if (fusectl1 & ICP_ACCEL_GEN4_MASK_WCP_WAT_SLICE) { - capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_ZUC; -- capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_ZUC_256; - capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_WIRELESS_CRYPTO_EXT; - } - -- if (fusectl1 & ICP_ACCEL_GEN4_MASK_EIA3_SLICE) { -+ if (fusectl1 & ICP_ACCEL_GEN4_MASK_EIA3_SLICE) - capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_ZUC; -- capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_ZUC_256; -- } -- -- if (fusectl1 & ICP_ACCEL_GEN4_MASK_ZUC_256_SLICE) -- capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_ZUC_256; - - capabilities_asym = ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC | - ICP_ACCEL_CAPABILITIES_SM2 | -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.c ---- BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.c 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.c 2025-10-22 13:53:56.427169565 -0400 -@@ -520,8 +520,8 @@ static void set_vc_csr_for_bank(void __i - * driver must program the ringmodectl CSRs. - */ - value = ADF_CSR_RD(csr, ADF_GEN6_CSR_RINGMODECTL(bank_number)); -- value |= FIELD_PREP(ADF_GEN6_RINGMODECTL_TC_MASK, ADF_GEN6_RINGMODECTL_TC_DEFAULT); -- value |= FIELD_PREP(ADF_GEN6_RINGMODECTL_TC_EN_MASK, ADF_GEN6_RINGMODECTL_TC_EN_OP1); -+ FIELD_MODIFY(ADF_GEN6_RINGMODECTL_TC_MASK, &value, ADF_GEN6_RINGMODECTL_TC_DEFAULT); -+ FIELD_MODIFY(ADF_GEN6_RINGMODECTL_TC_EN_MASK, &value, ADF_GEN6_RINGMODECTL_TC_EN_OP1); - ADF_CSR_WR(csr, ADF_GEN6_CSR_RINGMODECTL(bank_number), value); - } - -@@ -537,7 +537,7 @@ static int set_vc_config(struct adf_acce - * Read PVC0CTL then write the masked values. - */ - pci_read_config_dword(pdev, ADF_GEN6_PVC0CTL_OFFSET, &value); -- value |= FIELD_PREP(ADF_GEN6_PVC0CTL_TCVCMAP_MASK, ADF_GEN6_PVC0CTL_TCVCMAP_DEFAULT); -+ FIELD_MODIFY(ADF_GEN6_PVC0CTL_TCVCMAP_MASK, &value, ADF_GEN6_PVC0CTL_TCVCMAP_DEFAULT); - err = pci_write_config_dword(pdev, ADF_GEN6_PVC0CTL_OFFSET, value); - if (err) { - dev_err(&GET_DEV(accel_dev), "pci write to PVC0CTL failed\n"); -@@ -546,8 +546,8 @@ static int set_vc_config(struct adf_acce - - /* Read PVC1CTL then write masked values */ - pci_read_config_dword(pdev, ADF_GEN6_PVC1CTL_OFFSET, &value); -- value |= FIELD_PREP(ADF_GEN6_PVC1CTL_TCVCMAP_MASK, ADF_GEN6_PVC1CTL_TCVCMAP_DEFAULT); -- value |= FIELD_PREP(ADF_GEN6_PVC1CTL_VCEN_MASK, ADF_GEN6_PVC1CTL_VCEN_ON); -+ FIELD_MODIFY(ADF_GEN6_PVC1CTL_TCVCMAP_MASK, &value, ADF_GEN6_PVC1CTL_TCVCMAP_DEFAULT); -+ FIELD_MODIFY(ADF_GEN6_PVC1CTL_VCEN_MASK, &value, ADF_GEN6_PVC1CTL_VCEN_ON); - err = pci_write_config_dword(pdev, ADF_GEN6_PVC1CTL_OFFSET, value); - if (err) - dev_err(&GET_DEV(accel_dev), "pci write to PVC1CTL failed\n"); -@@ -627,7 +627,15 @@ static u32 get_accel_cap(struct adf_acce - capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_CIPHER; - } - -- capabilities_asym = 0; -+ capabilities_asym = ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC | -+ ICP_ACCEL_CAPABILITIES_SM2 | -+ ICP_ACCEL_CAPABILITIES_ECEDMONT; -+ -+ if (fusectl1 & ICP_ACCEL_GEN6_MASK_PKE_SLICE) { -+ capabilities_asym &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC; -+ capabilities_asym &= ~ICP_ACCEL_CAPABILITIES_SM2; -+ capabilities_asym &= ~ICP_ACCEL_CAPABILITIES_ECEDMONT; -+ } - - capabilities_dc = ICP_ACCEL_CAPABILITIES_COMPRESSION | - ICP_ACCEL_CAPABILITIES_LZ4_COMPRESSION | -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.h BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.h ---- BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.h 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_6xxx/adf_6xxx_hw_data.h 2025-10-22 13:53:56.427169565 -0400 -@@ -99,7 +99,7 @@ - #define ADF_GEN6_PVC0CTL_OFFSET 0x204 - #define ADF_GEN6_PVC0CTL_TCVCMAP_OFFSET 1 - #define ADF_GEN6_PVC0CTL_TCVCMAP_MASK GENMASK(7, 1) --#define ADF_GEN6_PVC0CTL_TCVCMAP_DEFAULT 0x7F -+#define ADF_GEN6_PVC0CTL_TCVCMAP_DEFAULT 0x3F - - /* VC1 Resource Control Register */ - #define ADF_GEN6_PVC1CTL_OFFSET 0x210 -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_common/adf_common_drv.h BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_common/adf_common_drv.h ---- BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_common/adf_common_drv.h 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_common/adf_common_drv.h 2025-10-22 13:53:56.427169565 -0400 -@@ -189,6 +189,7 @@ void adf_exit_misc_wq(void); - bool adf_misc_wq_queue_work(struct work_struct *work); - bool adf_misc_wq_queue_delayed_work(struct delayed_work *work, - unsigned long delay); -+void adf_misc_wq_flush(void); - #if defined(CONFIG_PCI_IOV) - int adf_sriov_configure(struct pci_dev *pdev, int numvfs); - void adf_disable_sriov(struct adf_accel_dev *accel_dev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.c ---- BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.c 2025-10-22 13:53:23.179329297 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.c 2025-10-22 13:53:56.427169565 -0400 -@@ -581,6 +581,28 @@ static int bank_state_restore(struct adf - ops->write_csr_int_srcsel_w_val(base, bank, state->iaintflagsrcsel0); - ops->write_csr_exp_int_en(base, bank, state->ringexpintenable); - ops->write_csr_int_col_ctl(base, bank, state->iaintcolctl); -+ -+ /* -+ * Verify whether any exceptions were raised during the bank save process. -+ * If exceptions occurred, the status and exception registers cannot -+ * be directly restored. Consequently, further restoration is not -+ * feasible, and the current state of the ring should be maintained. -+ */ -+ val = state->ringexpstat; -+ if (val) { -+ pr_info("QAT: Bank %u state not fully restored due to exception in saved state (%#x)\n", -+ bank, val); -+ return 0; -+ } -+ -+ /* Ensure that the restoration process completed without exceptions */ -+ tmp_val = ops->read_csr_exp_stat(base, bank); -+ if (tmp_val) { -+ pr_err("QAT: Bank %u restored with exception: %#x\n", -+ bank, tmp_val); -+ return -EFAULT; -+ } -+ - ops->write_csr_ring_srv_arb_en(base, bank, state->ringsrvarben); - - /* Check that all ring statuses match the saved state. */ -@@ -614,13 +636,6 @@ static int bank_state_restore(struct adf - if (ret) - return ret; - -- tmp_val = ops->read_csr_exp_stat(base, bank); -- val = state->ringexpstat; -- if (tmp_val && !val) { -- pr_err("QAT: Bank was restored with exception: 0x%x\n", val); -- return -EINVAL; -- } -- - return 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_common/adf_init.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_common/adf_init.c ---- BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_common/adf_init.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_common/adf_init.c 2025-10-22 13:53:56.427169565 -0400 -@@ -404,6 +404,7 @@ static void adf_dev_shutdown(struct adf_ - hw_data->exit_admin_comms(accel_dev); - - adf_cleanup_etr_data(accel_dev); -+ adf_misc_wq_flush(); - adf_dev_restore(accel_dev); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_common/adf_isr.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_common/adf_isr.c ---- BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_common/adf_isr.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_common/adf_isr.c 2025-10-22 13:53:56.427169565 -0400 -@@ -407,3 +407,8 @@ bool adf_misc_wq_queue_delayed_work(stru - { - return queue_delayed_work(adf_misc_wq, work, delay); - } -+ -+void adf_misc_wq_flush(void) -+{ -+ flush_workqueue(adf_misc_wq); -+} -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_common/adf_sriov.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_common/adf_sriov.c ---- BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_common/adf_sriov.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_common/adf_sriov.c 2025-10-22 13:53:56.427169565 -0400 -@@ -155,7 +155,6 @@ static int adf_do_enable_sriov(struct ad - if (!device_iommu_mapped(&GET_DEV(accel_dev))) { - dev_warn(&GET_DEV(accel_dev), - "IOMMU should be enabled for SR-IOV to work correctly\n"); -- return -EINVAL; - } - - if (adf_dev_started(accel_dev)) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_common/adf_transport_debug.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_common/adf_transport_debug.c ---- BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_common/adf_transport_debug.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_common/adf_transport_debug.c 2025-10-22 13:53:56.427169565 -0400 -@@ -31,8 +31,10 @@ static void *adf_ring_next(struct seq_fi - struct adf_etr_ring_data *ring = sfile->private; - - if (*pos >= (ADF_SIZE_TO_RING_SIZE_IN_BYTES(ring->ring_size) / -- ADF_MSG_SIZE_TO_BYTES(ring->msg_size))) -+ ADF_MSG_SIZE_TO_BYTES(ring->msg_size))) { -+ (*pos)++; - return NULL; -+ } - - return ring->base_addr + - (ADF_MSG_SIZE_TO_BYTES(ring->msg_size) * (*pos)++); -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_common/qat_algs.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_common/qat_algs.c ---- BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_common/qat_algs.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_common/qat_algs.c 2025-10-22 13:53:56.427169565 -0400 -@@ -5,11 +5,11 @@ - #include - #include - #include -+#include - #include - #include - #include - #include --#include - #include - #include - #include -@@ -154,19 +154,19 @@ static int qat_alg_do_precomputes(struct - - switch (ctx->qat_hash_alg) { - case ICP_QAT_HW_AUTH_ALGO_SHA1: -- if (crypto_shash_export(shash, &ctx->sha1)) -+ if (crypto_shash_export_core(shash, &ctx->sha1)) - return -EFAULT; - for (i = 0; i < digest_size >> 2; i++, hash_state_out++) - *hash_state_out = cpu_to_be32(ctx->sha1.state[i]); - break; - case ICP_QAT_HW_AUTH_ALGO_SHA256: -- if (crypto_shash_export(shash, &ctx->sha256)) -+ if (crypto_shash_export_core(shash, &ctx->sha256)) - return -EFAULT; - for (i = 0; i < digest_size >> 2; i++, hash_state_out++) - *hash_state_out = cpu_to_be32(ctx->sha256.state[i]); - break; - case ICP_QAT_HW_AUTH_ALGO_SHA512: -- if (crypto_shash_export(shash, &ctx->sha512)) -+ if (crypto_shash_export_core(shash, &ctx->sha512)) - return -EFAULT; - for (i = 0; i < digest_size >> 3; i++, hash512_state_out++) - *hash512_state_out = cpu_to_be64(ctx->sha512.state[i]); -@@ -190,19 +190,19 @@ static int qat_alg_do_precomputes(struct - - switch (ctx->qat_hash_alg) { - case ICP_QAT_HW_AUTH_ALGO_SHA1: -- if (crypto_shash_export(shash, &ctx->sha1)) -+ if (crypto_shash_export_core(shash, &ctx->sha1)) - return -EFAULT; - for (i = 0; i < digest_size >> 2; i++, hash_state_out++) - *hash_state_out = cpu_to_be32(ctx->sha1.state[i]); - break; - case ICP_QAT_HW_AUTH_ALGO_SHA256: -- if (crypto_shash_export(shash, &ctx->sha256)) -+ if (crypto_shash_export_core(shash, &ctx->sha256)) - return -EFAULT; - for (i = 0; i < digest_size >> 2; i++, hash_state_out++) - *hash_state_out = cpu_to_be32(ctx->sha256.state[i]); - break; - case ICP_QAT_HW_AUTH_ALGO_SHA512: -- if (crypto_shash_export(shash, &ctx->sha512)) -+ if (crypto_shash_export_core(shash, &ctx->sha512)) - return -EFAULT; - for (i = 0; i < digest_size >> 3; i++, hash512_state_out++) - *hash512_state_out = cpu_to_be64(ctx->sha512.state[i]); -@@ -1277,7 +1277,7 @@ static struct aead_alg qat_aeads[] = { { - .base = { - .cra_name = "authenc(hmac(sha1),cbc(aes))", - .cra_driver_name = "qat_aes_cbc_hmac_sha1", -- .cra_priority = 4001, -+ .cra_priority = 100, - .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct qat_alg_aead_ctx), -@@ -1294,7 +1294,7 @@ static struct aead_alg qat_aeads[] = { { - .base = { - .cra_name = "authenc(hmac(sha256),cbc(aes))", - .cra_driver_name = "qat_aes_cbc_hmac_sha256", -- .cra_priority = 4001, -+ .cra_priority = 100, - .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct qat_alg_aead_ctx), -@@ -1311,7 +1311,7 @@ static struct aead_alg qat_aeads[] = { { - .base = { - .cra_name = "authenc(hmac(sha512),cbc(aes))", - .cra_driver_name = "qat_aes_cbc_hmac_sha512", -- .cra_priority = 4001, -+ .cra_priority = 100, - .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct qat_alg_aead_ctx), -@@ -1329,7 +1329,7 @@ static struct aead_alg qat_aeads[] = { { - static struct skcipher_alg qat_skciphers[] = { { - .base.cra_name = "cbc(aes)", - .base.cra_driver_name = "qat_aes_cbc", -- .base.cra_priority = 4001, -+ .base.cra_priority = 100, - .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY, - .base.cra_blocksize = AES_BLOCK_SIZE, - .base.cra_ctxsize = sizeof(struct qat_alg_skcipher_ctx), -@@ -1347,7 +1347,7 @@ static struct skcipher_alg qat_skciphers - }, { - .base.cra_name = "ctr(aes)", - .base.cra_driver_name = "qat_aes_ctr", -- .base.cra_priority = 4001, -+ .base.cra_priority = 100, - .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY, - .base.cra_blocksize = 1, - .base.cra_ctxsize = sizeof(struct qat_alg_skcipher_ctx), -@@ -1365,7 +1365,7 @@ static struct skcipher_alg qat_skciphers - }, { - .base.cra_name = "xts(aes)", - .base.cra_driver_name = "qat_aes_xts", -- .base.cra_priority = 4001, -+ .base.cra_priority = 100, - .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK | - CRYPTO_ALG_ALLOCATES_MEMORY, - .base.cra_blocksize = AES_BLOCK_SIZE, -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_common/qat_bl.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_common/qat_bl.c ---- BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_common/qat_bl.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_common/qat_bl.c 2025-10-22 13:53:56.427169565 -0400 -@@ -38,7 +38,7 @@ void qat_bl_free_bufl(struct adf_accel_d - for (i = 0; i < blout->num_mapped_bufs; i++) { - dma_unmap_single(dev, blout->buffers[i].addr, - blout->buffers[i].len, -- DMA_FROM_DEVICE); -+ DMA_BIDIRECTIONAL); - } - dma_unmap_single(dev, blpout, sz_out, DMA_TO_DEVICE); - -@@ -162,7 +162,7 @@ static int __qat_bl_sgl_to_bufl(struct a - } - buffers[y].addr = dma_map_single(dev, sg_virt(sg) + left, - sg->length - left, -- DMA_FROM_DEVICE); -+ DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(dev, buffers[y].addr))) - goto err_out; - buffers[y].len = sg->length; -@@ -204,7 +204,7 @@ err_out: - if (!dma_mapping_error(dev, buflout->buffers[i].addr)) - dma_unmap_single(dev, buflout->buffers[i].addr, - buflout->buffers[i].len, -- DMA_FROM_DEVICE); -+ DMA_BIDIRECTIONAL); - } - - if (!buf->sgl_dst_valid) -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_common/qat_compression.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_common/qat_compression.c ---- BPI-Router-Linux-kernel/drivers/crypto/intel/qat/qat_common/qat_compression.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/intel/qat/qat_common/qat_compression.c 2025-10-22 13:53:56.427169565 -0400 -@@ -196,7 +196,7 @@ static int qat_compression_alloc_dc_data - struct adf_dc_data *dc_data = NULL; - u8 *obuff = NULL; - -- dc_data = devm_kzalloc(dev, sizeof(*dc_data), GFP_KERNEL); -+ dc_data = kzalloc_node(sizeof(*dc_data), GFP_KERNEL, dev_to_node(dev)); - if (!dc_data) - goto err; - -@@ -204,7 +204,7 @@ static int qat_compression_alloc_dc_data - if (!obuff) - goto err; - -- obuff_p = dma_map_single(dev, obuff, ovf_buff_sz, DMA_FROM_DEVICE); -+ obuff_p = dma_map_single(dev, obuff, ovf_buff_sz, DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(dev, obuff_p))) - goto err; - -@@ -232,9 +232,9 @@ static void qat_free_dc_data(struct adf_ - return; - - dma_unmap_single(dev, dc_data->ovf_buff_p, dc_data->ovf_buff_sz, -- DMA_FROM_DEVICE); -+ DMA_BIDIRECTIONAL); - kfree_sensitive(dc_data->ovf_buff); -- devm_kfree(dev, dc_data); -+ kfree(dc_data); - accel_dev->dc_data = NULL; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/marvell/cesa/cipher.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/marvell/cesa/cipher.c ---- BPI-Router-Linux-kernel/drivers/crypto/marvell/cesa/cipher.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/marvell/cesa/cipher.c 2025-10-22 13:53:56.427169565 -0400 -@@ -75,9 +75,12 @@ mv_cesa_skcipher_dma_cleanup(struct skci - static inline void mv_cesa_skcipher_cleanup(struct skcipher_request *req) - { - struct mv_cesa_skcipher_req *creq = skcipher_request_ctx(req); -+ struct mv_cesa_engine *engine = creq->base.engine; - - if (mv_cesa_req_get_type(&creq->base) == CESA_DMA_REQ) - mv_cesa_skcipher_dma_cleanup(req); -+ -+ atomic_sub(req->cryptlen, &engine->load); - } - - static void mv_cesa_skcipher_std_step(struct skcipher_request *req) -@@ -212,7 +215,6 @@ mv_cesa_skcipher_complete(struct crypto_ - struct mv_cesa_engine *engine = creq->base.engine; - unsigned int ivsize; - -- atomic_sub(skreq->cryptlen, &engine->load); - ivsize = crypto_skcipher_ivsize(crypto_skcipher_reqtfm(skreq)); - - if (mv_cesa_req_get_type(&creq->base) == CESA_DMA_REQ) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/marvell/cesa/hash.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/marvell/cesa/hash.c ---- BPI-Router-Linux-kernel/drivers/crypto/marvell/cesa/hash.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/marvell/cesa/hash.c 2025-10-22 13:53:56.427169565 -0400 -@@ -110,9 +110,12 @@ static inline void mv_cesa_ahash_dma_cle - static inline void mv_cesa_ahash_cleanup(struct ahash_request *req) - { - struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); -+ struct mv_cesa_engine *engine = creq->base.engine; - - if (mv_cesa_req_get_type(&creq->base) == CESA_DMA_REQ) - mv_cesa_ahash_dma_cleanup(req); -+ -+ atomic_sub(req->nbytes, &engine->load); - } - - static void mv_cesa_ahash_last_cleanup(struct ahash_request *req) -@@ -395,8 +398,6 @@ static void mv_cesa_ahash_complete(struc - } - } - } -- -- atomic_sub(ahashreq->nbytes, &engine->load); - } - - static void mv_cesa_ahash_prepare(struct crypto_async_request *req, -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/marvell/octeontx2/otx2_cpt_common.h BPI-Router-Linux-kernel-6.16.12/drivers/crypto/marvell/octeontx2/otx2_cpt_common.h ---- BPI-Router-Linux-kernel/drivers/crypto/marvell/octeontx2/otx2_cpt_common.h 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/marvell/octeontx2/otx2_cpt_common.h 2025-10-22 13:53:56.427169565 -0400 -@@ -18,9 +18,8 @@ - #define OTX2_CPT_MAX_VFS_NUM 128 - #define OTX2_CPT_RVU_FUNC_ADDR_S(blk, slot, offs) \ - (((blk) << 20) | ((slot) << 12) | (offs)) --#define OTX2_CPT_RVU_PFFUNC(pf, func) \ -- ((((pf) & RVU_PFVF_PF_MASK) << RVU_PFVF_PF_SHIFT) | \ -- (((func) & RVU_PFVF_FUNC_MASK) << RVU_PFVF_FUNC_SHIFT)) -+ -+#define OTX2_CPT_RVU_PFFUNC(pdev, pf, func) rvu_make_pcifunc(pdev, pf, func) - - #define OTX2_CPT_INVALID_CRYPTO_ENG_GRP 0xFF - #define OTX2_CPT_NAME_LENGTH 64 -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c ---- BPI-Router-Linux-kernel/drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/marvell/octeontx2/otx2_cptpf_mbox.c 2025-10-22 13:53:56.427169565 -0400 -@@ -142,7 +142,7 @@ static int send_inline_ipsec_inbound_msg - memset(req, 0, sizeof(*req)); - req->hdr.id = MBOX_MSG_CPT_INLINE_IPSEC_CFG; - req->hdr.sig = OTX2_MBOX_REQ_SIG; -- req->hdr.pcifunc = OTX2_CPT_RVU_PFFUNC(cptpf->pf_id, 0); -+ req->hdr.pcifunc = OTX2_CPT_RVU_PFFUNC(cptpf->pdev, cptpf->pf_id, 0); - req->dir = CPT_INLINE_INBOUND; - req->slot = slot; - req->sso_pf_func_ovrd = cptpf->sso_pf_func_ovrd; -@@ -184,7 +184,8 @@ static int rx_inline_ipsec_lf_cfg(struct - nix_req->gen_cfg.opcode = cpt_inline_rx_opcode(pdev); - nix_req->gen_cfg.param1 = req->param1; - nix_req->gen_cfg.param2 = req->param2; -- nix_req->inst_qsel.cpt_pf_func = OTX2_CPT_RVU_PFFUNC(cptpf->pf_id, 0); -+ nix_req->inst_qsel.cpt_pf_func = -+ OTX2_CPT_RVU_PFFUNC(cptpf->pdev, cptpf->pf_id, 0); - nix_req->inst_qsel.cpt_slot = 0; - ret = otx2_cpt_send_mbox_msg(&cptpf->afpf_mbox, pdev); - if (ret) -@@ -392,9 +393,8 @@ void otx2_cptpf_vfpf_mbox_handler(struct - msg = (struct mbox_msghdr *)(mdev->mbase + offset); - - /* Set which VF sent this message based on mbox IRQ */ -- msg->pcifunc = ((u16)cptpf->pf_id << RVU_PFVF_PF_SHIFT) | -- ((vf->vf_id + 1) & RVU_PFVF_FUNC_MASK); -- -+ msg->pcifunc = rvu_make_pcifunc(cptpf->pdev, cptpf->pf_id, -+ (vf->vf_id + 1)); - err = cptpf_handle_vf_req(cptpf, vf, msg, - msg->next_msgoff - offset); - /* -@@ -469,8 +469,7 @@ static void process_afpf_mbox_msg(struct - - switch (msg->id) { - case MBOX_MSG_READY: -- cptpf->pf_id = (msg->pcifunc >> RVU_PFVF_PF_SHIFT) & -- RVU_PFVF_PF_MASK; -+ cptpf->pf_id = rvu_get_pf(cptpf->pdev, msg->pcifunc); - break; - case MBOX_MSG_MSIX_OFFSET: - rsp_msix = (struct msix_offset_rsp *) msg; -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c ---- BPI-Router-Linux-kernel/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/marvell/octeontx2/otx2_cptpf_ucode.c 2025-10-22 13:53:56.427169565 -0400 -@@ -176,7 +176,9 @@ static int cptx_set_ucode_base(struct ot - /* Set PF number for microcode fetches */ - ret = otx2_cpt_write_af_reg(&cptpf->afpf_mbox, cptpf->pdev, - CPT_AF_PF_FUNC, -- cptpf->pf_id << RVU_PFVF_PF_SHIFT, blkaddr); -+ rvu_make_pcifunc(cptpf->pdev, -+ cptpf->pf_id, 0), -+ blkaddr); - if (ret) - return ret; - -@@ -1491,11 +1493,13 @@ int otx2_cpt_discover_eng_capabilities(s - union otx2_cpt_opcode opcode; - union otx2_cpt_res_s *result; - union otx2_cpt_inst_s inst; -+ dma_addr_t result_baddr; - dma_addr_t rptr_baddr; - struct pci_dev *pdev; -- u32 len, compl_rlen; -+ int timeout = 10000; -+ void *base, *rptr; - int ret, etype; -- void *rptr; -+ u32 len; - - /* - * We don't get capabilities if it was already done -@@ -1518,22 +1522,28 @@ int otx2_cpt_discover_eng_capabilities(s - if (ret) - goto delete_grps; - -- compl_rlen = ALIGN(sizeof(union otx2_cpt_res_s), OTX2_CPT_DMA_MINALIGN); -- len = compl_rlen + LOADFVC_RLEN; -+ /* Allocate extra memory for "rptr" and "result" pointer alignment */ -+ len = LOADFVC_RLEN + ARCH_DMA_MINALIGN + -+ sizeof(union otx2_cpt_res_s) + OTX2_CPT_RES_ADDR_ALIGN; - -- result = kzalloc(len, GFP_KERNEL); -- if (!result) { -+ base = kzalloc(len, GFP_KERNEL); -+ if (!base) { - ret = -ENOMEM; - goto lf_cleanup; - } -- rptr_baddr = dma_map_single(&pdev->dev, (void *)result, len, -- DMA_BIDIRECTIONAL); -+ -+ rptr = PTR_ALIGN(base, ARCH_DMA_MINALIGN); -+ rptr_baddr = dma_map_single(&pdev->dev, rptr, len, DMA_BIDIRECTIONAL); - if (dma_mapping_error(&pdev->dev, rptr_baddr)) { - dev_err(&pdev->dev, "DMA mapping failed\n"); - ret = -EFAULT; -- goto free_result; -+ goto free_rptr; - } -- rptr = (u8 *)result + compl_rlen; -+ -+ result = (union otx2_cpt_res_s *)PTR_ALIGN(rptr + LOADFVC_RLEN, -+ OTX2_CPT_RES_ADDR_ALIGN); -+ result_baddr = ALIGN(rptr_baddr + LOADFVC_RLEN, -+ OTX2_CPT_RES_ADDR_ALIGN); - - /* Fill in the command */ - opcode.s.major = LOADFVC_MAJOR_OP; -@@ -1545,27 +1555,38 @@ int otx2_cpt_discover_eng_capabilities(s - /* 64-bit swap for microcode data reads, not needed for addresses */ - cpu_to_be64s(&iq_cmd.cmd.u); - iq_cmd.dptr = 0; -- iq_cmd.rptr = rptr_baddr + compl_rlen; -+ iq_cmd.rptr = rptr_baddr; - iq_cmd.cptr.u = 0; - - for (etype = 1; etype < OTX2_CPT_MAX_ENG_TYPES; etype++) { - result->s.compcode = OTX2_CPT_COMPLETION_CODE_INIT; - iq_cmd.cptr.s.grp = otx2_cpt_get_eng_grp(&cptpf->eng_grps, - etype); -- otx2_cpt_fill_inst(&inst, &iq_cmd, rptr_baddr); -+ otx2_cpt_fill_inst(&inst, &iq_cmd, result_baddr); - lfs->ops->send_cmd(&inst, 1, &cptpf->lfs.lf[0]); -+ timeout = 10000; - - while (lfs->ops->cpt_get_compcode(result) == -- OTX2_CPT_COMPLETION_CODE_INIT) -+ OTX2_CPT_COMPLETION_CODE_INIT) { - cpu_relax(); -+ udelay(1); -+ timeout--; -+ if (!timeout) { -+ ret = -ENODEV; -+ cptpf->is_eng_caps_discovered = false; -+ dev_warn(&pdev->dev, "Timeout on CPT load_fvc completion poll\n"); -+ goto error_no_response; -+ } -+ } - - cptpf->eng_caps[etype].u = be64_to_cpup(rptr); - } -- dma_unmap_single(&pdev->dev, rptr_baddr, len, DMA_BIDIRECTIONAL); - cptpf->is_eng_caps_discovered = true; - --free_result: -- kfree(result); -+error_no_response: -+ dma_unmap_single(&pdev->dev, rptr_baddr, len, DMA_BIDIRECTIONAL); -+free_rptr: -+ kfree(base); - lf_cleanup: - otx2_cptlf_shutdown(lfs); - delete_grps: -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/marvell/octeontx2/otx2_cpt_reqmgr.h BPI-Router-Linux-kernel-6.16.12/drivers/crypto/marvell/octeontx2/otx2_cpt_reqmgr.h ---- BPI-Router-Linux-kernel/drivers/crypto/marvell/octeontx2/otx2_cpt_reqmgr.h 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/marvell/octeontx2/otx2_cpt_reqmgr.h 2025-10-22 13:53:56.427169565 -0400 -@@ -34,6 +34,9 @@ - #define SG_COMP_2 2 - #define SG_COMP_1 1 - -+#define OTX2_CPT_DPTR_RPTR_ALIGN 8 -+#define OTX2_CPT_RES_ADDR_ALIGN 32 -+ - union otx2_cpt_opcode { - u16 flags; - struct { -@@ -347,22 +350,48 @@ static inline struct otx2_cpt_inst_info - cn10k_sgv2_info_create(struct pci_dev *pdev, struct otx2_cpt_req_info *req, - gfp_t gfp) - { -- u32 dlen = 0, g_len, sg_len, info_len; -- int align = OTX2_CPT_DMA_MINALIGN; -+ u32 dlen = 0, g_len, s_len, sg_len, info_len; - struct otx2_cpt_inst_info *info; -- u16 g_sz_bytes, s_sz_bytes; - u32 total_mem_len; - int i; - -- g_sz_bytes = ((req->in_cnt + 2) / 3) * -- sizeof(struct cn10kb_cpt_sglist_component); -- s_sz_bytes = ((req->out_cnt + 2) / 3) * -- sizeof(struct cn10kb_cpt_sglist_component); -- -- g_len = ALIGN(g_sz_bytes, align); -- sg_len = ALIGN(g_len + s_sz_bytes, align); -- info_len = ALIGN(sizeof(*info), align); -- total_mem_len = sg_len + info_len + sizeof(union otx2_cpt_res_s); -+ /* Allocate memory to meet below alignment requirement: -+ * ------------------------------------ -+ * | struct otx2_cpt_inst_info | -+ * | (No alignment required) | -+ * | --------------------------------| -+ * | | padding for ARCH_DMA_MINALIGN | -+ * | | alignment | -+ * |------------------------------------| -+ * | SG List Gather/Input memory | -+ * | Length = multiple of 32Bytes | -+ * | Alignment = 8Byte | -+ * |---------------------------------- | -+ * | SG List Scatter/Output memory | -+ * | Length = multiple of 32Bytes | -+ * | Alignment = 8Byte | -+ * | -------------------------------| -+ * | | padding for 32B alignment | -+ * |------------------------------------| -+ * | Result response memory | -+ * | Alignment = 32Byte | -+ * ------------------------------------ -+ */ -+ -+ info_len = sizeof(*info); -+ -+ g_len = ((req->in_cnt + 2) / 3) * -+ sizeof(struct cn10kb_cpt_sglist_component); -+ s_len = ((req->out_cnt + 2) / 3) * -+ sizeof(struct cn10kb_cpt_sglist_component); -+ sg_len = g_len + s_len; -+ -+ /* Allocate extra memory for SG and response address alignment */ -+ total_mem_len = ALIGN(info_len, OTX2_CPT_DPTR_RPTR_ALIGN); -+ total_mem_len += (ARCH_DMA_MINALIGN - 1) & -+ ~(OTX2_CPT_DPTR_RPTR_ALIGN - 1); -+ total_mem_len += ALIGN(sg_len, OTX2_CPT_RES_ADDR_ALIGN); -+ total_mem_len += sizeof(union otx2_cpt_res_s); - - info = kzalloc(total_mem_len, gfp); - if (unlikely(!info)) -@@ -372,7 +401,8 @@ cn10k_sgv2_info_create(struct pci_dev *p - dlen += req->in[i].size; - - info->dlen = dlen; -- info->in_buffer = (u8 *)info + info_len; -+ info->in_buffer = PTR_ALIGN((u8 *)info + info_len, ARCH_DMA_MINALIGN); -+ info->out_buffer = info->in_buffer + g_len; - info->gthr_sz = req->in_cnt; - info->sctr_sz = req->out_cnt; - -@@ -384,7 +414,7 @@ cn10k_sgv2_info_create(struct pci_dev *p - } - - if (sgv2io_components_setup(pdev, req->out, req->out_cnt, -- &info->in_buffer[g_len])) { -+ info->out_buffer)) { - dev_err(&pdev->dev, "Failed to setup scatter list\n"); - goto destroy_info; - } -@@ -401,8 +431,10 @@ cn10k_sgv2_info_create(struct pci_dev *p - * Get buffer for union otx2_cpt_res_s response - * structure and its physical address - */ -- info->completion_addr = info->in_buffer + sg_len; -- info->comp_baddr = info->dptr_baddr + sg_len; -+ info->completion_addr = PTR_ALIGN((info->in_buffer + sg_len), -+ OTX2_CPT_RES_ADDR_ALIGN); -+ info->comp_baddr = ALIGN((info->dptr_baddr + sg_len), -+ OTX2_CPT_RES_ADDR_ALIGN); - - return info; - -@@ -417,10 +449,9 @@ static inline struct otx2_cpt_inst_info - otx2_sg_info_create(struct pci_dev *pdev, struct otx2_cpt_req_info *req, - gfp_t gfp) - { -- int align = OTX2_CPT_DMA_MINALIGN; - struct otx2_cpt_inst_info *info; -- u32 dlen, align_dlen, info_len; -- u16 g_sz_bytes, s_sz_bytes; -+ u32 dlen, info_len; -+ u16 g_len, s_len; - u32 total_mem_len; - - if (unlikely(req->in_cnt > OTX2_CPT_MAX_SG_IN_CNT || -@@ -429,22 +460,54 @@ otx2_sg_info_create(struct pci_dev *pdev - return NULL; - } - -- g_sz_bytes = ((req->in_cnt + 3) / 4) * -- sizeof(struct otx2_cpt_sglist_component); -- s_sz_bytes = ((req->out_cnt + 3) / 4) * -- sizeof(struct otx2_cpt_sglist_component); -- -- dlen = g_sz_bytes + s_sz_bytes + SG_LIST_HDR_SIZE; -- align_dlen = ALIGN(dlen, align); -- info_len = ALIGN(sizeof(*info), align); -- total_mem_len = align_dlen + info_len + sizeof(union otx2_cpt_res_s); -+ /* Allocate memory to meet below alignment requirement: -+ * ------------------------------------ -+ * | struct otx2_cpt_inst_info | -+ * | (No alignment required) | -+ * | --------------------------------| -+ * | | padding for ARCH_DMA_MINALIGN | -+ * | | alignment | -+ * |------------------------------------| -+ * | SG List Header of 8 Byte | -+ * |------------------------------------| -+ * | SG List Gather/Input memory | -+ * | Length = multiple of 32Bytes | -+ * | Alignment = 8Byte | -+ * |---------------------------------- | -+ * | SG List Scatter/Output memory | -+ * | Length = multiple of 32Bytes | -+ * | Alignment = 8Byte | -+ * | -------------------------------| -+ * | | padding for 32B alignment | -+ * |------------------------------------| -+ * | Result response memory | -+ * | Alignment = 32Byte | -+ * ------------------------------------ -+ */ -+ -+ info_len = sizeof(*info); -+ -+ g_len = ((req->in_cnt + 3) / 4) * -+ sizeof(struct otx2_cpt_sglist_component); -+ s_len = ((req->out_cnt + 3) / 4) * -+ sizeof(struct otx2_cpt_sglist_component); -+ -+ dlen = g_len + s_len + SG_LIST_HDR_SIZE; -+ -+ /* Allocate extra memory for SG and response address alignment */ -+ total_mem_len = ALIGN(info_len, OTX2_CPT_DPTR_RPTR_ALIGN); -+ total_mem_len += (ARCH_DMA_MINALIGN - 1) & -+ ~(OTX2_CPT_DPTR_RPTR_ALIGN - 1); -+ total_mem_len += ALIGN(dlen, OTX2_CPT_RES_ADDR_ALIGN); -+ total_mem_len += sizeof(union otx2_cpt_res_s); - - info = kzalloc(total_mem_len, gfp); - if (unlikely(!info)) - return NULL; - - info->dlen = dlen; -- info->in_buffer = (u8 *)info + info_len; -+ info->in_buffer = PTR_ALIGN((u8 *)info + info_len, ARCH_DMA_MINALIGN); -+ info->out_buffer = info->in_buffer + SG_LIST_HDR_SIZE + g_len; - - ((u16 *)info->in_buffer)[0] = req->out_cnt; - ((u16 *)info->in_buffer)[1] = req->in_cnt; -@@ -460,7 +523,7 @@ otx2_sg_info_create(struct pci_dev *pdev - } - - if (setup_sgio_components(pdev, req->out, req->out_cnt, -- &info->in_buffer[8 + g_sz_bytes])) { -+ info->out_buffer)) { - dev_err(&pdev->dev, "Failed to setup scatter list\n"); - goto destroy_info; - } -@@ -476,8 +539,10 @@ otx2_sg_info_create(struct pci_dev *pdev - * Get buffer for union otx2_cpt_res_s response - * structure and its physical address - */ -- info->completion_addr = info->in_buffer + align_dlen; -- info->comp_baddr = info->dptr_baddr + align_dlen; -+ info->completion_addr = PTR_ALIGN((info->in_buffer + dlen), -+ OTX2_CPT_RES_ADDR_ALIGN); -+ info->comp_baddr = ALIGN((info->dptr_baddr + dlen), -+ OTX2_CPT_RES_ADDR_ALIGN); - - return info; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/crypto/marvell/octeontx2/otx2_cptvf_mbox.c BPI-Router-Linux-kernel-6.16.12/drivers/crypto/marvell/octeontx2/otx2_cptvf_mbox.c ---- BPI-Router-Linux-kernel/drivers/crypto/marvell/octeontx2/otx2_cptvf_mbox.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/crypto/marvell/octeontx2/otx2_cptvf_mbox.c 2025-10-22 13:53:56.427169565 -0400 -@@ -189,7 +189,7 @@ int otx2_cptvf_send_eng_grp_num_msg(stru - } - req->hdr.id = MBOX_MSG_GET_ENG_GRP_NUM; - req->hdr.sig = OTX2_MBOX_REQ_SIG; -- req->hdr.pcifunc = OTX2_CPT_RVU_PFFUNC(cptvf->vf_id, 0); -+ req->hdr.pcifunc = OTX2_CPT_RVU_PFFUNC(cptvf->pdev, cptvf->vf_id, 0); - req->eng_type = eng_type; - - return otx2_cpt_send_mbox_msg(mbox, pdev); -@@ -210,7 +210,7 @@ int otx2_cptvf_send_kvf_limits_msg(struc - } - req->id = MBOX_MSG_GET_KVF_LIMITS; - req->sig = OTX2_MBOX_REQ_SIG; -- req->pcifunc = OTX2_CPT_RVU_PFFUNC(cptvf->vf_id, 0); -+ req->pcifunc = OTX2_CPT_RVU_PFFUNC(cptvf->pdev, cptvf->vf_id, 0); - - return otx2_cpt_send_mbox_msg(mbox, pdev); - } -@@ -230,7 +230,7 @@ int otx2_cptvf_send_caps_msg(struct otx2 - } - req->id = MBOX_MSG_GET_CAPS; - req->sig = OTX2_MBOX_REQ_SIG; -- req->pcifunc = OTX2_CPT_RVU_PFFUNC(cptvf->vf_id, 0); -+ req->pcifunc = OTX2_CPT_RVU_PFFUNC(cptvf->pdev, cptvf->vf_id, 0); - - return otx2_cpt_send_mbox_msg(mbox, pdev); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/cxl/core/core.h BPI-Router-Linux-kernel-6.16.12/drivers/cxl/core/core.h ---- BPI-Router-Linux-kernel/drivers/cxl/core/core.h 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/cxl/core/core.h 2025-10-22 13:53:56.427169565 -0400 -@@ -80,6 +80,7 @@ int cxl_dpa_alloc(struct cxl_endpoint_de - int cxl_dpa_free(struct cxl_endpoint_decoder *cxled); - resource_size_t cxl_dpa_size(struct cxl_endpoint_decoder *cxled); - resource_size_t cxl_dpa_resource_start(struct cxl_endpoint_decoder *cxled); -+bool cxl_resource_contains_addr(const struct resource *res, const resource_size_t addr); - - enum cxl_rcrb { - CXL_RCRB_DOWNSTREAM, -diff -purNx .git BPI-Router-Linux-kernel/drivers/cxl/core/edac.c BPI-Router-Linux-kernel-6.16.12/drivers/cxl/core/edac.c ---- BPI-Router-Linux-kernel/drivers/cxl/core/edac.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/cxl/core/edac.c 2025-10-22 13:53:56.427169565 -0400 -@@ -103,10 +103,10 @@ static int cxl_scrub_get_attrbs(struct c - u8 *cap, u16 *cycle, u8 *flags, u8 *min_cycle) - { - struct cxl_mailbox *cxl_mbox; -- u8 min_scrub_cycle = U8_MAX; - struct cxl_region_params *p; - struct cxl_memdev *cxlmd; - struct cxl_region *cxlr; -+ u8 min_scrub_cycle = 0; - int i, ret; - - if (!cxl_ps_ctx->cxlr) { -@@ -133,8 +133,12 @@ static int cxl_scrub_get_attrbs(struct c - if (ret) - return ret; - -+ /* -+ * The min_scrub_cycle of a region is the max of minimum scrub -+ * cycles supported by memdevs that back the region. -+ */ - if (min_cycle) -- min_scrub_cycle = min(*min_cycle, min_scrub_cycle); -+ min_scrub_cycle = max(*min_cycle, min_scrub_cycle); - } - - if (min_cycle) -@@ -1099,8 +1103,10 @@ int cxl_store_rec_gen_media(struct cxl_m - old_rec = xa_store(&array_rec->rec_gen_media, - le64_to_cpu(rec->media_hdr.phys_addr), rec, - GFP_KERNEL); -- if (xa_is_err(old_rec)) -+ if (xa_is_err(old_rec)) { -+ kfree(rec); - return xa_err(old_rec); -+ } - - kfree(old_rec); - -@@ -1127,8 +1133,10 @@ int cxl_store_rec_dram(struct cxl_memdev - old_rec = xa_store(&array_rec->rec_dram, - le64_to_cpu(rec->media_hdr.phys_addr), rec, - GFP_KERNEL); -- if (xa_is_err(old_rec)) -+ if (xa_is_err(old_rec)) { -+ kfree(rec); - return xa_err(old_rec); -+ } - - kfree(old_rec); - -@@ -1315,7 +1323,7 @@ cxl_mem_get_rec_dram(struct cxl_memdev * - attrbs.bank = ctx->bank; - break; - case EDAC_REPAIR_RANK_SPARING: -- attrbs.repair_type = CXL_BANK_SPARING; -+ attrbs.repair_type = CXL_RANK_SPARING; - break; - default: - return NULL; -@@ -1915,8 +1923,11 @@ static int cxl_ppr_set_nibble_mask(struc - static int cxl_do_ppr(struct device *dev, void *drv_data, u32 val) - { - struct cxl_ppr_context *cxl_ppr_ctx = drv_data; -+ struct cxl_memdev *cxlmd = cxl_ppr_ctx->cxlmd; -+ struct cxl_dev_state *cxlds = cxlmd->cxlds; - -- if (!cxl_ppr_ctx->dpa || val != EDAC_DO_MEM_REPAIR) -+ if (val != EDAC_DO_MEM_REPAIR || -+ !cxl_resource_contains_addr(&cxlds->dpa_res, cxl_ppr_ctx->dpa)) - return -EINVAL; - - return cxl_mem_perform_ppr(cxl_ppr_ctx); -diff -purNx .git BPI-Router-Linux-kernel/drivers/cxl/core/features.c BPI-Router-Linux-kernel-6.16.12/drivers/cxl/core/features.c ---- BPI-Router-Linux-kernel/drivers/cxl/core/features.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/cxl/core/features.c 2025-10-22 13:53:56.427169565 -0400 -@@ -544,7 +544,7 @@ static bool cxlctl_validate_set_features - u32 flags; - - if (rpc_in->op_size < sizeof(uuid_t)) -- return ERR_PTR(-EINVAL); -+ return false; - - feat = cxl_feature_info(cxlfs, &rpc_in->set_feat_in.uuid); - if (IS_ERR(feat)) -diff -purNx .git BPI-Router-Linux-kernel/drivers/cxl/core/hdm.c BPI-Router-Linux-kernel-6.16.12/drivers/cxl/core/hdm.c ---- BPI-Router-Linux-kernel/drivers/cxl/core/hdm.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/cxl/core/hdm.c 2025-10-22 13:53:56.427169565 -0400 -@@ -547,6 +547,13 @@ resource_size_t cxl_dpa_resource_start(s - return base; - } - -+bool cxl_resource_contains_addr(const struct resource *res, const resource_size_t addr) -+{ -+ struct resource _addr = DEFINE_RES_MEM(addr, 1); -+ -+ return resource_contains(res, &_addr); -+} -+ - int cxl_dpa_free(struct cxl_endpoint_decoder *cxled) - { - struct cxl_port *port = cxled_to_port(cxled); -diff -purNx .git BPI-Router-Linux-kernel/drivers/cxl/core/ras.c BPI-Router-Linux-kernel-6.16.12/drivers/cxl/core/ras.c ---- BPI-Router-Linux-kernel/drivers/cxl/core/ras.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/cxl/core/ras.c 2025-10-22 13:53:56.427169565 -0400 -@@ -31,40 +31,38 @@ static void cxl_cper_trace_uncorr_port_p - ras_cap.header_log); - } - --static void cxl_cper_trace_corr_prot_err(struct pci_dev *pdev, -- struct cxl_ras_capability_regs ras_cap) -+static void cxl_cper_trace_corr_prot_err(struct cxl_memdev *cxlmd, -+ struct cxl_ras_capability_regs ras_cap) - { - u32 status = ras_cap.cor_status & ~ras_cap.cor_mask; -- struct cxl_dev_state *cxlds; - -- cxlds = pci_get_drvdata(pdev); -- if (!cxlds) -- return; -- -- trace_cxl_aer_correctable_error(cxlds->cxlmd, status); -+ trace_cxl_aer_correctable_error(cxlmd, status); - } - --static void cxl_cper_trace_uncorr_prot_err(struct pci_dev *pdev, -- struct cxl_ras_capability_regs ras_cap) -+static void -+cxl_cper_trace_uncorr_prot_err(struct cxl_memdev *cxlmd, -+ struct cxl_ras_capability_regs ras_cap) - { - u32 status = ras_cap.uncor_status & ~ras_cap.uncor_mask; -- struct cxl_dev_state *cxlds; - u32 fe; - -- cxlds = pci_get_drvdata(pdev); -- if (!cxlds) -- return; -- - if (hweight32(status) > 1) - fe = BIT(FIELD_GET(CXL_RAS_CAP_CONTROL_FE_MASK, - ras_cap.cap_control)); - else - fe = status; - -- trace_cxl_aer_uncorrectable_error(cxlds->cxlmd, status, fe, -+ trace_cxl_aer_uncorrectable_error(cxlmd, status, fe, - ras_cap.header_log); - } - -+static int match_memdev_by_parent(struct device *dev, const void *uport) -+{ -+ if (is_cxl_memdev(dev) && dev->parent == uport) -+ return 1; -+ return 0; -+} -+ - static void cxl_cper_handle_prot_err(struct cxl_cper_prot_err_work_data *data) - { - unsigned int devfn = PCI_DEVFN(data->prot_err.agent_addr.device, -@@ -73,13 +71,12 @@ static void cxl_cper_handle_prot_err(str - pci_get_domain_bus_and_slot(data->prot_err.agent_addr.segment, - data->prot_err.agent_addr.bus, - devfn); -+ struct cxl_memdev *cxlmd; - int port_type; - - if (!pdev) - return; - -- guard(device)(&pdev->dev); -- - port_type = pci_pcie_type(pdev); - if (port_type == PCI_EXP_TYPE_ROOT_PORT || - port_type == PCI_EXP_TYPE_DOWNSTREAM || -@@ -92,10 +89,20 @@ static void cxl_cper_handle_prot_err(str - return; - } - -+ guard(device)(&pdev->dev); -+ if (!pdev->dev.driver) -+ return; -+ -+ struct device *mem_dev __free(put_device) = bus_find_device( -+ &cxl_bus_type, NULL, pdev, match_memdev_by_parent); -+ if (!mem_dev) -+ return; -+ -+ cxlmd = to_cxl_memdev(mem_dev); - if (data->severity == AER_CORRECTABLE) -- cxl_cper_trace_corr_prot_err(pdev, data->ras_cap); -+ cxl_cper_trace_corr_prot_err(cxlmd, data->ras_cap); - else -- cxl_cper_trace_uncorr_prot_err(pdev, data->ras_cap); -+ cxl_cper_trace_uncorr_prot_err(cxlmd, data->ras_cap); - } - - static void cxl_cper_prot_err_work_fn(struct work_struct *work) -diff -purNx .git BPI-Router-Linux-kernel/drivers/devfreq/devfreq.c BPI-Router-Linux-kernel-6.16.12/drivers/devfreq/devfreq.c ---- BPI-Router-Linux-kernel/drivers/devfreq/devfreq.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/devfreq/devfreq.c 2025-10-22 13:53:56.427169565 -0400 -@@ -1382,15 +1382,11 @@ int devfreq_remove_governor(struct devfr - int ret; - struct device *dev = devfreq->dev.parent; - -+ if (!devfreq->governor) -+ continue; -+ - if (!strncmp(devfreq->governor->name, governor->name, - DEVFREQ_NAME_LEN)) { -- /* we should have a devfreq governor! */ -- if (!devfreq->governor) { -- dev_warn(dev, "%s: Governor %s NOT present\n", -- __func__, governor->name); -- continue; -- /* Fall through */ -- } - ret = devfreq->governor->event_handler(devfreq, - DEVFREQ_GOV_STOP, NULL); - if (ret) { -@@ -1743,7 +1739,7 @@ static ssize_t trans_stat_show(struct de - for (i = 0; i < max_state; i++) { - if (len >= PAGE_SIZE - 1) - break; -- if (df->freq_table[2] == df->previous_freq) -+ if (df->freq_table[i] == df->previous_freq) - len += sysfs_emit_at(buf, len, "*"); - else - len += sysfs_emit_at(buf, len, " "); -diff -purNx .git BPI-Router-Linux-kernel/drivers/devfreq/governor_userspace.c BPI-Router-Linux-kernel-6.16.12/drivers/devfreq/governor_userspace.c ---- BPI-Router-Linux-kernel/drivers/devfreq/governor_userspace.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/devfreq/governor_userspace.c 2025-10-22 13:53:56.427169565 -0400 -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -39,10 +40,13 @@ static ssize_t set_freq_store(struct dev - unsigned long wanted; - int err = 0; - -+ err = kstrtoul(buf, 0, &wanted); -+ if (err) -+ return err; -+ - mutex_lock(&devfreq->lock); - data = devfreq->governor_data; - -- sscanf(buf, "%lu", &wanted); - data->user_frequency = wanted; - data->valid = true; - err = update_devfreq(devfreq); -diff -purNx .git BPI-Router-Linux-kernel/drivers/dma/dw/rzn1-dmamux.c BPI-Router-Linux-kernel-6.16.12/drivers/dma/dw/rzn1-dmamux.c ---- BPI-Router-Linux-kernel/drivers/dma/dw/rzn1-dmamux.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/dma/dw/rzn1-dmamux.c 2025-10-22 13:53:56.431169546 -0400 -@@ -48,12 +48,16 @@ static void *rzn1_dmamux_route_allocate( - u32 mask; - int ret; - -- if (dma_spec->args_count != RNZ1_DMAMUX_NCELLS) -- return ERR_PTR(-EINVAL); -+ if (dma_spec->args_count != RNZ1_DMAMUX_NCELLS) { -+ ret = -EINVAL; -+ goto put_device; -+ } - - map = kzalloc(sizeof(*map), GFP_KERNEL); -- if (!map) -- return ERR_PTR(-ENOMEM); -+ if (!map) { -+ ret = -ENOMEM; -+ goto put_device; -+ } - - chan = dma_spec->args[0]; - map->req_idx = dma_spec->args[4]; -@@ -94,12 +98,15 @@ static void *rzn1_dmamux_route_allocate( - if (ret) - goto clear_bitmap; - -+ put_device(&pdev->dev); - return map; - - clear_bitmap: - clear_bit(map->req_idx, dmamux->used_chans); - free_map: - kfree(map); -+put_device: -+ put_device(&pdev->dev); - - return ERR_PTR(ret); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/dma/dw-edma/dw-edma-pcie.c BPI-Router-Linux-kernel-6.16.12/drivers/dma/dw-edma/dw-edma-pcie.c ---- BPI-Router-Linux-kernel/drivers/dma/dw-edma/dw-edma-pcie.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/dma/dw-edma/dw-edma-pcie.c 2025-10-22 13:53:56.431169546 -0400 -@@ -161,12 +161,16 @@ static int dw_edma_pcie_probe(struct pci - const struct pci_device_id *pid) - { - struct dw_edma_pcie_data *pdata = (void *)pid->driver_data; -- struct dw_edma_pcie_data vsec_data; -+ struct dw_edma_pcie_data *vsec_data __free(kfree) = NULL; - struct device *dev = &pdev->dev; - struct dw_edma_chip *chip; - int err, nr_irqs; - int i, mask; - -+ vsec_data = kmalloc(sizeof(*vsec_data), GFP_KERNEL); -+ if (!vsec_data) -+ return -ENOMEM; -+ - /* Enable PCI device */ - err = pcim_enable_device(pdev); - if (err) { -@@ -174,23 +178,23 @@ static int dw_edma_pcie_probe(struct pci - return err; - } - -- memcpy(&vsec_data, pdata, sizeof(struct dw_edma_pcie_data)); -+ memcpy(vsec_data, pdata, sizeof(struct dw_edma_pcie_data)); - - /* - * Tries to find if exists a PCIe Vendor-Specific Extended Capability - * for the DMA, if one exists, then reconfigures it. - */ -- dw_edma_pcie_get_vsec_dma_data(pdev, &vsec_data); -+ dw_edma_pcie_get_vsec_dma_data(pdev, vsec_data); - - /* Mapping PCI BAR regions */ -- mask = BIT(vsec_data.rg.bar); -- for (i = 0; i < vsec_data.wr_ch_cnt; i++) { -- mask |= BIT(vsec_data.ll_wr[i].bar); -- mask |= BIT(vsec_data.dt_wr[i].bar); -- } -- for (i = 0; i < vsec_data.rd_ch_cnt; i++) { -- mask |= BIT(vsec_data.ll_rd[i].bar); -- mask |= BIT(vsec_data.dt_rd[i].bar); -+ mask = BIT(vsec_data->rg.bar); -+ for (i = 0; i < vsec_data->wr_ch_cnt; i++) { -+ mask |= BIT(vsec_data->ll_wr[i].bar); -+ mask |= BIT(vsec_data->dt_wr[i].bar); -+ } -+ for (i = 0; i < vsec_data->rd_ch_cnt; i++) { -+ mask |= BIT(vsec_data->ll_rd[i].bar); -+ mask |= BIT(vsec_data->dt_rd[i].bar); - } - err = pcim_iomap_regions(pdev, mask, pci_name(pdev)); - if (err) { -@@ -213,7 +217,7 @@ static int dw_edma_pcie_probe(struct pci - return -ENOMEM; - - /* IRQs allocation */ -- nr_irqs = pci_alloc_irq_vectors(pdev, 1, vsec_data.irqs, -+ nr_irqs = pci_alloc_irq_vectors(pdev, 1, vsec_data->irqs, - PCI_IRQ_MSI | PCI_IRQ_MSIX); - if (nr_irqs < 1) { - pci_err(pdev, "fail to alloc IRQ vector (number of IRQs=%u)\n", -@@ -224,22 +228,22 @@ static int dw_edma_pcie_probe(struct pci - /* Data structure initialization */ - chip->dev = dev; - -- chip->mf = vsec_data.mf; -+ chip->mf = vsec_data->mf; - chip->nr_irqs = nr_irqs; - chip->ops = &dw_edma_pcie_plat_ops; - -- chip->ll_wr_cnt = vsec_data.wr_ch_cnt; -- chip->ll_rd_cnt = vsec_data.rd_ch_cnt; -+ chip->ll_wr_cnt = vsec_data->wr_ch_cnt; -+ chip->ll_rd_cnt = vsec_data->rd_ch_cnt; - -- chip->reg_base = pcim_iomap_table(pdev)[vsec_data.rg.bar]; -+ chip->reg_base = pcim_iomap_table(pdev)[vsec_data->rg.bar]; - if (!chip->reg_base) - return -ENOMEM; - - for (i = 0; i < chip->ll_wr_cnt; i++) { - struct dw_edma_region *ll_region = &chip->ll_region_wr[i]; - struct dw_edma_region *dt_region = &chip->dt_region_wr[i]; -- struct dw_edma_block *ll_block = &vsec_data.ll_wr[i]; -- struct dw_edma_block *dt_block = &vsec_data.dt_wr[i]; -+ struct dw_edma_block *ll_block = &vsec_data->ll_wr[i]; -+ struct dw_edma_block *dt_block = &vsec_data->dt_wr[i]; - - ll_region->vaddr.io = pcim_iomap_table(pdev)[ll_block->bar]; - if (!ll_region->vaddr.io) -@@ -263,8 +267,8 @@ static int dw_edma_pcie_probe(struct pci - for (i = 0; i < chip->ll_rd_cnt; i++) { - struct dw_edma_region *ll_region = &chip->ll_region_rd[i]; - struct dw_edma_region *dt_region = &chip->dt_region_rd[i]; -- struct dw_edma_block *ll_block = &vsec_data.ll_rd[i]; -- struct dw_edma_block *dt_block = &vsec_data.dt_rd[i]; -+ struct dw_edma_block *ll_block = &vsec_data->ll_rd[i]; -+ struct dw_edma_block *dt_block = &vsec_data->dt_rd[i]; - - ll_region->vaddr.io = pcim_iomap_table(pdev)[ll_block->bar]; - if (!ll_region->vaddr.io) -@@ -298,31 +302,31 @@ static int dw_edma_pcie_probe(struct pci - pci_dbg(pdev, "Version:\tUnknown (0x%x)\n", chip->mf); - - pci_dbg(pdev, "Registers:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p)\n", -- vsec_data.rg.bar, vsec_data.rg.off, vsec_data.rg.sz, -+ vsec_data->rg.bar, vsec_data->rg.off, vsec_data->rg.sz, - chip->reg_base); - - - for (i = 0; i < chip->ll_wr_cnt; i++) { - pci_dbg(pdev, "L. List:\tWRITE CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n", -- i, vsec_data.ll_wr[i].bar, -- vsec_data.ll_wr[i].off, chip->ll_region_wr[i].sz, -+ i, vsec_data->ll_wr[i].bar, -+ vsec_data->ll_wr[i].off, chip->ll_region_wr[i].sz, - chip->ll_region_wr[i].vaddr.io, &chip->ll_region_wr[i].paddr); - - pci_dbg(pdev, "Data:\tWRITE CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n", -- i, vsec_data.dt_wr[i].bar, -- vsec_data.dt_wr[i].off, chip->dt_region_wr[i].sz, -+ i, vsec_data->dt_wr[i].bar, -+ vsec_data->dt_wr[i].off, chip->dt_region_wr[i].sz, - chip->dt_region_wr[i].vaddr.io, &chip->dt_region_wr[i].paddr); - } - - for (i = 0; i < chip->ll_rd_cnt; i++) { - pci_dbg(pdev, "L. List:\tREAD CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n", -- i, vsec_data.ll_rd[i].bar, -- vsec_data.ll_rd[i].off, chip->ll_region_rd[i].sz, -+ i, vsec_data->ll_rd[i].bar, -+ vsec_data->ll_rd[i].off, chip->ll_region_rd[i].sz, - chip->ll_region_rd[i].vaddr.io, &chip->ll_region_rd[i].paddr); - - pci_dbg(pdev, "Data:\tREAD CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n", -- i, vsec_data.dt_rd[i].bar, -- vsec_data.dt_rd[i].off, chip->dt_region_rd[i].sz, -+ i, vsec_data->dt_rd[i].bar, -+ vsec_data->dt_rd[i].off, chip->dt_region_rd[i].sz, - chip->dt_region_rd[i].vaddr.io, &chip->dt_region_rd[i].paddr); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/dma/idxd/init.c BPI-Router-Linux-kernel-6.16.12/drivers/dma/idxd/init.c ---- BPI-Router-Linux-kernel/drivers/dma/idxd/init.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/dma/idxd/init.c 2025-10-22 13:53:56.431169546 -0400 -@@ -189,27 +189,30 @@ static int idxd_setup_wqs(struct idxd_de - idxd->wq_enable_map = bitmap_zalloc_node(idxd->max_wqs, GFP_KERNEL, dev_to_node(dev)); - if (!idxd->wq_enable_map) { - rc = -ENOMEM; -- goto err_bitmap; -+ goto err_free_wqs; - } - - for (i = 0; i < idxd->max_wqs; i++) { - wq = kzalloc_node(sizeof(*wq), GFP_KERNEL, dev_to_node(dev)); - if (!wq) { - rc = -ENOMEM; -- goto err; -+ goto err_unwind; - } - - idxd_dev_set_type(&wq->idxd_dev, IDXD_DEV_WQ); - conf_dev = wq_confdev(wq); - wq->id = i; - wq->idxd = idxd; -- device_initialize(wq_confdev(wq)); -+ device_initialize(conf_dev); - conf_dev->parent = idxd_confdev(idxd); - conf_dev->bus = &dsa_bus_type; - conf_dev->type = &idxd_wq_device_type; - rc = dev_set_name(conf_dev, "wq%d.%d", idxd->id, wq->id); -- if (rc < 0) -- goto err; -+ if (rc < 0) { -+ put_device(conf_dev); -+ kfree(wq); -+ goto err_unwind; -+ } - - mutex_init(&wq->wq_lock); - init_waitqueue_head(&wq->err_queue); -@@ -220,15 +223,20 @@ static int idxd_setup_wqs(struct idxd_de - wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES; - wq->wqcfg = kzalloc_node(idxd->wqcfg_size, GFP_KERNEL, dev_to_node(dev)); - if (!wq->wqcfg) { -+ put_device(conf_dev); -+ kfree(wq); - rc = -ENOMEM; -- goto err; -+ goto err_unwind; - } - - if (idxd->hw.wq_cap.op_config) { - wq->opcap_bmap = bitmap_zalloc(IDXD_MAX_OPCAP_BITS, GFP_KERNEL); - if (!wq->opcap_bmap) { -+ kfree(wq->wqcfg); -+ put_device(conf_dev); -+ kfree(wq); - rc = -ENOMEM; -- goto err_opcap_bmap; -+ goto err_unwind; - } - bitmap_copy(wq->opcap_bmap, idxd->opcap_bmap, IDXD_MAX_OPCAP_BITS); - } -@@ -239,13 +247,7 @@ static int idxd_setup_wqs(struct idxd_de - - return 0; - --err_opcap_bmap: -- kfree(wq->wqcfg); -- --err: -- put_device(conf_dev); -- kfree(wq); -- -+err_unwind: - while (--i >= 0) { - wq = idxd->wqs[i]; - if (idxd->hw.wq_cap.op_config) -@@ -254,11 +256,10 @@ err: - conf_dev = wq_confdev(wq); - put_device(conf_dev); - kfree(wq); -- - } - bitmap_free(idxd->wq_enable_map); - --err_bitmap: -+err_free_wqs: - kfree(idxd->wqs); - - return rc; -@@ -1292,10 +1293,12 @@ static void idxd_remove(struct pci_dev * - device_unregister(idxd_confdev(idxd)); - idxd_shutdown(pdev); - idxd_device_remove_debugfs(idxd); -- idxd_cleanup(idxd); -+ perfmon_pmu_remove(idxd); -+ idxd_cleanup_interrupts(idxd); -+ if (device_pasid_enabled(idxd)) -+ idxd_disable_system_pasid(idxd); - pci_iounmap(pdev, idxd->reg_base); - put_device(idxd_confdev(idxd)); -- idxd_free(idxd); - pci_disable_device(pdev); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/dma/mediatek/mtk-cqdma.c BPI-Router-Linux-kernel-6.16.12/drivers/dma/mediatek/mtk-cqdma.c ---- BPI-Router-Linux-kernel/drivers/dma/mediatek/mtk-cqdma.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/dma/mediatek/mtk-cqdma.c 2025-10-22 13:53:56.431169546 -0400 -@@ -449,9 +449,9 @@ static enum dma_status mtk_cqdma_tx_stat - return ret; - - spin_lock_irqsave(&cvc->pc->lock, flags); -- spin_lock_irqsave(&cvc->vc.lock, flags); -+ spin_lock(&cvc->vc.lock); - vd = mtk_cqdma_find_active_desc(c, cookie); -- spin_unlock_irqrestore(&cvc->vc.lock, flags); -+ spin_unlock(&cvc->vc.lock); - spin_unlock_irqrestore(&cvc->pc->lock, flags); - - if (vd) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/dma/mmp_tdma.c BPI-Router-Linux-kernel-6.16.12/drivers/dma/mmp_tdma.c ---- BPI-Router-Linux-kernel/drivers/dma/mmp_tdma.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/dma/mmp_tdma.c 2025-10-22 13:53:56.431169546 -0400 -@@ -641,7 +641,7 @@ static int mmp_tdma_probe(struct platfor - int chan_num = TDMA_CHANNEL_NUM; - struct gen_pool *pool = NULL; - -- type = (enum mmp_tdma_type)device_get_match_data(&pdev->dev); -+ type = (kernel_ulong_t)device_get_match_data(&pdev->dev); - - /* always have couple channels */ - tdev = devm_kzalloc(&pdev->dev, sizeof(*tdev), GFP_KERNEL); -diff -purNx .git BPI-Router-Linux-kernel/drivers/dma/mv_xor.c BPI-Router-Linux-kernel-6.16.12/drivers/dma/mv_xor.c ---- BPI-Router-Linux-kernel/drivers/dma/mv_xor.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/dma/mv_xor.c 2025-10-22 13:53:56.431169546 -0400 -@@ -1061,8 +1061,16 @@ mv_xor_channel_add(struct mv_xor_device - */ - mv_chan->dummy_src_addr = dma_map_single(dma_dev->dev, - mv_chan->dummy_src, MV_XOR_MIN_BYTE_COUNT, DMA_FROM_DEVICE); -+ if (dma_mapping_error(dma_dev->dev, mv_chan->dummy_src_addr)) -+ return ERR_PTR(-ENOMEM); -+ - mv_chan->dummy_dst_addr = dma_map_single(dma_dev->dev, - mv_chan->dummy_dst, MV_XOR_MIN_BYTE_COUNT, DMA_TO_DEVICE); -+ if (dma_mapping_error(dma_dev->dev, mv_chan->dummy_dst_addr)) { -+ ret = -ENOMEM; -+ goto err_unmap_src; -+ } -+ - - /* allocate coherent memory for hardware descriptors - * note: writecombine gives slightly better performance, but -@@ -1071,8 +1079,10 @@ mv_xor_channel_add(struct mv_xor_device - mv_chan->dma_desc_pool_virt = - dma_alloc_wc(&pdev->dev, MV_XOR_POOL_SIZE, &mv_chan->dma_desc_pool, - GFP_KERNEL); -- if (!mv_chan->dma_desc_pool_virt) -- return ERR_PTR(-ENOMEM); -+ if (!mv_chan->dma_desc_pool_virt) { -+ ret = -ENOMEM; -+ goto err_unmap_dst; -+ } - - /* discover transaction capabilities from the platform data */ - dma_dev->cap_mask = cap_mask; -@@ -1155,6 +1165,13 @@ err_free_irq: - err_free_dma: - dma_free_coherent(&pdev->dev, MV_XOR_POOL_SIZE, - mv_chan->dma_desc_pool_virt, mv_chan->dma_desc_pool); -+err_unmap_dst: -+ dma_unmap_single(dma_dev->dev, mv_chan->dummy_dst_addr, -+ MV_XOR_MIN_BYTE_COUNT, DMA_TO_DEVICE); -+err_unmap_src: -+ dma_unmap_single(dma_dev->dev, mv_chan->dummy_src_addr, -+ MV_XOR_MIN_BYTE_COUNT, DMA_FROM_DEVICE); -+ - return ERR_PTR(ret); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/dma/nbpfaxi.c BPI-Router-Linux-kernel-6.16.12/drivers/dma/nbpfaxi.c ---- BPI-Router-Linux-kernel/drivers/dma/nbpfaxi.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/dma/nbpfaxi.c 2025-10-22 13:53:56.431169546 -0400 -@@ -711,6 +711,9 @@ static int nbpf_desc_page_alloc(struct n - list_add_tail(&ldesc->node, &lhead); - ldesc->hwdesc_dma_addr = dma_map_single(dchan->device->dev, - hwdesc, sizeof(*hwdesc), DMA_TO_DEVICE); -+ if (dma_mapping_error(dchan->device->dev, -+ ldesc->hwdesc_dma_addr)) -+ goto unmap_error; - - dev_dbg(dev, "%s(): mapped 0x%p to %pad\n", __func__, - hwdesc, &ldesc->hwdesc_dma_addr); -@@ -737,6 +740,16 @@ static int nbpf_desc_page_alloc(struct n - spin_unlock_irq(&chan->lock); - - return ARRAY_SIZE(dpage->desc); -+ -+unmap_error: -+ while (i--) { -+ ldesc--; hwdesc--; -+ -+ dma_unmap_single(dchan->device->dev, ldesc->hwdesc_dma_addr, -+ sizeof(hwdesc), DMA_TO_DEVICE); -+ } -+ -+ return -ENOMEM; - } - - static void nbpf_desc_put(struct nbpf_desc *desc) -@@ -1351,7 +1364,7 @@ static int nbpf_probe(struct platform_de - if (irqs == 1) { - eirq = irqbuf[0]; - -- for (i = 0; i <= num_channels; i++) -+ for (i = 0; i < num_channels; i++) - nbpf->chan[i].irq = irqbuf[0]; - } else { - eirq = platform_get_irq_byname(pdev, "error"); -@@ -1361,16 +1374,15 @@ static int nbpf_probe(struct platform_de - if (irqs == num_channels + 1) { - struct nbpf_channel *chan; - -- for (i = 0, chan = nbpf->chan; i <= num_channels; -+ for (i = 0, chan = nbpf->chan; i < num_channels; - i++, chan++) { - /* Skip the error IRQ */ - if (irqbuf[i] == eirq) - i++; -+ if (i >= ARRAY_SIZE(irqbuf)) -+ return -EINVAL; - chan->irq = irqbuf[i]; - } -- -- if (chan != nbpf->chan + num_channels) -- return -EINVAL; - } else { - /* 2 IRQs and more than one channel */ - if (irqbuf[0] == eirq) -@@ -1378,7 +1390,7 @@ static int nbpf_probe(struct platform_de - else - irq = irqbuf[0]; - -- for (i = 0; i <= num_channels; i++) -+ for (i = 0; i < num_channels; i++) - nbpf->chan[i].irq = irq; - } - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/dma/qcom/bam_dma.c BPI-Router-Linux-kernel-6.16.12/drivers/dma/qcom/bam_dma.c ---- BPI-Router-Linux-kernel/drivers/dma/qcom/bam_dma.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/dma/qcom/bam_dma.c 2025-10-22 13:53:56.431169546 -0400 -@@ -1283,13 +1283,17 @@ static int bam_dma_probe(struct platform - if (!bdev->bamclk) { - ret = of_property_read_u32(pdev->dev.of_node, "num-channels", - &bdev->num_channels); -- if (ret) -+ if (ret) { - dev_err(bdev->dev, "num-channels unspecified in dt\n"); -+ return ret; -+ } - - ret = of_property_read_u32(pdev->dev.of_node, "qcom,num-ees", - &bdev->num_ees); -- if (ret) -+ if (ret) { - dev_err(bdev->dev, "num-ees unspecified in dt\n"); -+ return ret; -+ } - } - - ret = clk_prepare_enable(bdev->bamclk); -diff -purNx .git BPI-Router-Linux-kernel/drivers/dma/stm32/stm32-dma.c BPI-Router-Linux-kernel-6.16.12/drivers/dma/stm32/stm32-dma.c ---- BPI-Router-Linux-kernel/drivers/dma/stm32/stm32-dma.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/dma/stm32/stm32-dma.c 2025-10-22 13:53:56.431169546 -0400 -@@ -744,7 +744,7 @@ static void stm32_dma_handle_chan_done(s - /* cyclic while CIRC/DBM disable => post resume reconfiguration needed */ - if (!(scr & (STM32_DMA_SCR_CIRC | STM32_DMA_SCR_DBM))) - stm32_dma_post_resume_reconfigure(chan); -- else if (scr & STM32_DMA_SCR_DBM) -+ else if (scr & STM32_DMA_SCR_DBM && chan->desc->num_sgs > 2) - stm32_dma_configure_next_sg(chan); - } else { - chan->busy = false; -diff -purNx .git BPI-Router-Linux-kernel/drivers/dma/ti/edma.c BPI-Router-Linux-kernel-6.16.12/drivers/dma/ti/edma.c ---- BPI-Router-Linux-kernel/drivers/dma/ti/edma.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/dma/ti/edma.c 2025-10-22 13:53:56.431169546 -0400 -@@ -2064,8 +2064,8 @@ static int edma_setup_from_hw(struct dev - * priority. So Q0 is the highest priority queue and the last queue has - * the lowest priority. - */ -- queue_priority_map = devm_kcalloc(dev, ecc->num_tc + 1, sizeof(s8), -- GFP_KERNEL); -+ queue_priority_map = devm_kcalloc(dev, ecc->num_tc + 1, -+ sizeof(*queue_priority_map), GFP_KERNEL); - if (!queue_priority_map) - return -ENOMEM; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/dma-buf/dma-buf.c BPI-Router-Linux-kernel-6.16.12/drivers/dma-buf/dma-buf.c ---- BPI-Router-Linux-kernel/drivers/dma-buf/dma-buf.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/dma-buf/dma-buf.c 2025-10-22 13:53:56.431169546 -0400 -@@ -1118,7 +1118,7 @@ struct sg_table *dma_buf_map_attachment( - * Catch exporters making buffers inaccessible even when - * attachments preventing that exist. - */ -- WARN_ON_ONCE(ret == EBUSY); -+ WARN_ON_ONCE(ret == -EBUSY); - if (ret) - return ERR_PTR(ret); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/dma-buf/dma-resv.c BPI-Router-Linux-kernel-6.16.12/drivers/dma-buf/dma-resv.c ---- BPI-Router-Linux-kernel/drivers/dma-buf/dma-resv.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/dma-buf/dma-resv.c 2025-10-22 13:53:56.431169546 -0400 -@@ -685,11 +685,13 @@ long dma_resv_wait_timeout(struct dma_re - dma_resv_iter_begin(&cursor, obj, usage); - dma_resv_for_each_fence_unlocked(&cursor, fence) { - -- ret = dma_fence_wait_timeout(fence, intr, ret); -- if (ret <= 0) { -- dma_resv_iter_end(&cursor); -- return ret; -- } -+ ret = dma_fence_wait_timeout(fence, intr, timeout); -+ if (ret <= 0) -+ break; -+ -+ /* Even for zero timeout the return value is 1 */ -+ if (timeout) -+ timeout = ret; - } - dma_resv_iter_end(&cursor); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/dma-buf/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/dma-buf/Kconfig ---- BPI-Router-Linux-kernel/drivers/dma-buf/Kconfig 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/dma-buf/Kconfig 2025-10-22 13:53:56.427169565 -0400 -@@ -36,7 +36,6 @@ config UDMABUF - depends on DMA_SHARED_BUFFER - depends on MEMFD_CREATE || COMPILE_TEST - depends on MMU -- select VMAP_PFN - help - A driver to let userspace turn memfd regions into dma-bufs. - Qemu can use this to create host dmabufs for guest framebuffers. -diff -purNx .git BPI-Router-Linux-kernel/drivers/dma-buf/udmabuf.c BPI-Router-Linux-kernel-6.16.12/drivers/dma-buf/udmabuf.c ---- BPI-Router-Linux-kernel/drivers/dma-buf/udmabuf.c 2025-10-22 13:53:23.183329279 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/dma-buf/udmabuf.c 2025-10-22 13:53:56.431169546 -0400 -@@ -109,29 +109,22 @@ static int mmap_udmabuf(struct dma_buf * - static int vmap_udmabuf(struct dma_buf *buf, struct iosys_map *map) - { - struct udmabuf *ubuf = buf->priv; -- unsigned long *pfns; -+ struct page **pages; - void *vaddr; - pgoff_t pg; - - dma_resv_assert_held(buf->resv); - -- /** -- * HVO may free tail pages, so just use pfn to map each folio -- * into vmalloc area. -- */ -- pfns = kvmalloc_array(ubuf->pagecount, sizeof(*pfns), GFP_KERNEL); -- if (!pfns) -+ pages = kvmalloc_array(ubuf->pagecount, sizeof(*pages), GFP_KERNEL); -+ if (!pages) - return -ENOMEM; - -- for (pg = 0; pg < ubuf->pagecount; pg++) { -- unsigned long pfn = folio_pfn(ubuf->folios[pg]); -+ for (pg = 0; pg < ubuf->pagecount; pg++) -+ pages[pg] = folio_page(ubuf->folios[pg], -+ ubuf->offsets[pg] >> PAGE_SHIFT); - -- pfn += ubuf->offsets[pg] >> PAGE_SHIFT; -- pfns[pg] = pfn; -- } -- -- vaddr = vmap_pfn(pfns, ubuf->pagecount, PAGE_KERNEL); -- kvfree(pfns); -+ vaddr = vm_map_ram(pages, ubuf->pagecount, -1); -+ kvfree(pages); - if (!vaddr) - return -EINVAL; - -@@ -264,8 +257,7 @@ static int begin_cpu_udmabuf(struct dma_ - ubuf->sg = NULL; - } - } else { -- dma_sync_sg_for_cpu(dev, ubuf->sg->sgl, ubuf->sg->nents, -- direction); -+ dma_sync_sgtable_for_cpu(dev, ubuf->sg, direction); - } - - return ret; -@@ -280,7 +272,7 @@ static int end_cpu_udmabuf(struct dma_bu - if (!ubuf->sg) - return -EINVAL; - -- dma_sync_sg_for_device(dev, ubuf->sg->sgl, ubuf->sg->nents, direction); -+ dma_sync_sgtable_for_device(dev, ubuf->sg, direction); - return 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/dpll/dpll_netlink.c BPI-Router-Linux-kernel-6.16.12/drivers/dpll/dpll_netlink.c ---- BPI-Router-Linux-kernel/drivers/dpll/dpll_netlink.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/dpll/dpll_netlink.c 2025-10-22 13:53:56.431169546 -0400 -@@ -173,8 +173,8 @@ static int - dpll_msg_add_clock_quality_level(struct sk_buff *msg, struct dpll_device *dpll, - struct netlink_ext_ack *extack) - { -+ DECLARE_BITMAP(qls, DPLL_CLOCK_QUALITY_LEVEL_MAX + 1) = { 0 }; - const struct dpll_device_ops *ops = dpll_device_ops(dpll); -- DECLARE_BITMAP(qls, DPLL_CLOCK_QUALITY_LEVEL_MAX) = { 0 }; - enum dpll_clock_quality_level ql; - int ret; - -@@ -183,7 +183,7 @@ dpll_msg_add_clock_quality_level(struct - ret = ops->clock_quality_level_get(dpll, dpll_priv(dpll), qls, extack); - if (ret) - return ret; -- for_each_set_bit(ql, qls, DPLL_CLOCK_QUALITY_LEVEL_MAX) -+ for_each_set_bit(ql, qls, DPLL_CLOCK_QUALITY_LEVEL_MAX + 1) - if (nla_put_u32(msg, DPLL_A_CLOCK_QUALITY_LEVEL, ql)) - return -EMSGSIZE; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/edac/altera_edac.c BPI-Router-Linux-kernel-6.16.12/drivers/edac/altera_edac.c ---- BPI-Router-Linux-kernel/drivers/edac/altera_edac.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/edac/altera_edac.c 2025-10-22 13:53:56.431169546 -0400 -@@ -128,7 +128,6 @@ static ssize_t altr_sdr_mc_err_inject_wr - - ptemp = dma_alloc_coherent(mci->pdev, 16, &dma_handle, GFP_KERNEL); - if (!ptemp) { -- dma_free_coherent(mci->pdev, 16, ptemp, dma_handle); - edac_printk(KERN_ERR, EDAC_MC, - "Inject: Buffer Allocation error\n"); - return -ENOMEM; -diff -purNx .git BPI-Router-Linux-kernel/drivers/edac/amd64_edac.c BPI-Router-Linux-kernel-6.16.12/drivers/edac/amd64_edac.c ---- BPI-Router-Linux-kernel/drivers/edac/amd64_edac.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/edac/amd64_edac.c 2025-10-22 13:53:56.431169546 -0400 -@@ -1209,7 +1209,9 @@ static int umc_get_cs_mode(int dimm, u8 - if (csrow_enabled(2 * dimm + 1, ctrl, pvt)) - cs_mode |= CS_ODD_PRIMARY; - -- /* Asymmetric dual-rank DIMM support. */ -+ if (csrow_sec_enabled(2 * dimm, ctrl, pvt)) -+ cs_mode |= CS_EVEN_SECONDARY; -+ - if (csrow_sec_enabled(2 * dimm + 1, ctrl, pvt)) - cs_mode |= CS_ODD_SECONDARY; - -@@ -1230,12 +1232,13 @@ static int umc_get_cs_mode(int dimm, u8 - return cs_mode; - } - --static int __addr_mask_to_cs_size(u32 addr_mask_orig, unsigned int cs_mode, -- int csrow_nr, int dimm) -+static int calculate_cs_size(u32 mask, unsigned int cs_mode) - { -- u32 msb, weight, num_zero_bits; -- u32 addr_mask_deinterleaved; -- int size = 0; -+ int msb, weight, num_zero_bits; -+ u32 deinterleaved_mask; -+ -+ if (!mask) -+ return 0; - - /* - * The number of zero bits in the mask is equal to the number of bits -@@ -1248,19 +1251,30 @@ static int __addr_mask_to_cs_size(u32 ad - * without swapping with the most significant bit. This can be handled - * by keeping the MSB where it is and ignoring the single zero bit. - */ -- msb = fls(addr_mask_orig) - 1; -- weight = hweight_long(addr_mask_orig); -+ msb = fls(mask) - 1; -+ weight = hweight_long(mask); - num_zero_bits = msb - weight - !!(cs_mode & CS_3R_INTERLEAVE); - - /* Take the number of zero bits off from the top of the mask. */ -- addr_mask_deinterleaved = GENMASK_ULL(msb - num_zero_bits, 1); -+ deinterleaved_mask = GENMASK(msb - num_zero_bits, 1); -+ edac_dbg(1, " Deinterleaved AddrMask: 0x%x\n", deinterleaved_mask); -+ -+ return (deinterleaved_mask >> 2) + 1; -+} -+ -+static int __addr_mask_to_cs_size(u32 addr_mask, u32 addr_mask_sec, -+ unsigned int cs_mode, int csrow_nr, int dimm) -+{ -+ int size; - - edac_dbg(1, "CS%d DIMM%d AddrMasks:\n", csrow_nr, dimm); -- edac_dbg(1, " Original AddrMask: 0x%x\n", addr_mask_orig); -- edac_dbg(1, " Deinterleaved AddrMask: 0x%x\n", addr_mask_deinterleaved); -+ edac_dbg(1, " Primary AddrMask: 0x%x\n", addr_mask); - - /* Register [31:1] = Address [39:9]. Size is in kBs here. */ -- size = (addr_mask_deinterleaved >> 2) + 1; -+ size = calculate_cs_size(addr_mask, cs_mode); -+ -+ edac_dbg(1, " Secondary AddrMask: 0x%x\n", addr_mask_sec); -+ size += calculate_cs_size(addr_mask_sec, cs_mode); - - /* Return size in MBs. */ - return size >> 10; -@@ -1269,8 +1283,8 @@ static int __addr_mask_to_cs_size(u32 ad - static int umc_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc, - unsigned int cs_mode, int csrow_nr) - { -+ u32 addr_mask = 0, addr_mask_sec = 0; - int cs_mask_nr = csrow_nr; -- u32 addr_mask_orig; - int dimm, size = 0; - - /* No Chip Selects are enabled. */ -@@ -1308,13 +1322,13 @@ static int umc_addr_mask_to_cs_size(stru - if (!pvt->flags.zn_regs_v2) - cs_mask_nr >>= 1; - -- /* Asymmetric dual-rank DIMM support. */ -- if ((csrow_nr & 1) && (cs_mode & CS_ODD_SECONDARY)) -- addr_mask_orig = pvt->csels[umc].csmasks_sec[cs_mask_nr]; -- else -- addr_mask_orig = pvt->csels[umc].csmasks[cs_mask_nr]; -+ if (cs_mode & (CS_EVEN_PRIMARY | CS_ODD_PRIMARY)) -+ addr_mask = pvt->csels[umc].csmasks[cs_mask_nr]; -+ -+ if (cs_mode & (CS_EVEN_SECONDARY | CS_ODD_SECONDARY)) -+ addr_mask_sec = pvt->csels[umc].csmasks_sec[cs_mask_nr]; - -- return __addr_mask_to_cs_size(addr_mask_orig, cs_mode, csrow_nr, dimm); -+ return __addr_mask_to_cs_size(addr_mask, addr_mask_sec, cs_mode, csrow_nr, dimm); - } - - static void umc_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl) -@@ -3512,9 +3526,10 @@ static void gpu_get_err_info(struct mce - static int gpu_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc, - unsigned int cs_mode, int csrow_nr) - { -- u32 addr_mask_orig = pvt->csels[umc].csmasks[csrow_nr]; -+ u32 addr_mask = pvt->csels[umc].csmasks[csrow_nr]; -+ u32 addr_mask_sec = pvt->csels[umc].csmasks_sec[csrow_nr]; - -- return __addr_mask_to_cs_size(addr_mask_orig, cs_mode, csrow_nr, csrow_nr >> 1); -+ return __addr_mask_to_cs_size(addr_mask, addr_mask_sec, cs_mode, csrow_nr, csrow_nr >> 1); - } - - static void gpu_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl) -@@ -3879,6 +3894,7 @@ static int per_family_init(struct amd64_ - break; - case 0x70 ... 0x7f: - pvt->ctl_name = "F19h_M70h"; -+ pvt->max_mcs = 4; - pvt->flags.zn_regs_v2 = 1; - break; - case 0x90 ... 0x9f: -diff -purNx .git BPI-Router-Linux-kernel/drivers/edac/ecs.c BPI-Router-Linux-kernel-6.16.12/drivers/edac/ecs.c ---- BPI-Router-Linux-kernel/drivers/edac/ecs.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/edac/ecs.c 2025-10-22 13:53:56.431169546 -0400 -@@ -170,8 +170,10 @@ static int ecs_create_desc(struct device - fru_ctx->dev_attr[ECS_RESET] = EDAC_ECS_ATTR_WO(reset, fru); - fru_ctx->dev_attr[ECS_THRESHOLD] = EDAC_ECS_ATTR_RW(threshold, fru); - -- for (i = 0; i < ECS_MAX_ATTRS; i++) -+ for (i = 0; i < ECS_MAX_ATTRS; i++) { -+ sysfs_attr_init(&fru_ctx->dev_attr[i].dev_attr.attr); - fru_ctx->ecs_attrs[i] = &fru_ctx->dev_attr[i].dev_attr.attr; -+ } - - sprintf(fru_ctx->name, "%s%d", EDAC_ECS_FRU_NAME, fru); - group->name = fru_ctx->name; -diff -purNx .git BPI-Router-Linux-kernel/drivers/edac/ie31200_edac.c BPI-Router-Linux-kernel-6.16.12/drivers/edac/ie31200_edac.c ---- BPI-Router-Linux-kernel/drivers/edac/ie31200_edac.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/edac/ie31200_edac.c 2025-10-22 13:53:56.431169546 -0400 -@@ -91,6 +91,8 @@ - #define PCI_DEVICE_ID_INTEL_IE31200_RPL_S_2 0x4640 - #define PCI_DEVICE_ID_INTEL_IE31200_RPL_S_3 0x4630 - #define PCI_DEVICE_ID_INTEL_IE31200_RPL_S_4 0xa700 -+#define PCI_DEVICE_ID_INTEL_IE31200_RPL_S_5 0xa740 -+#define PCI_DEVICE_ID_INTEL_IE31200_RPL_S_6 0xa704 - - /* Alder Lake-S */ - #define PCI_DEVICE_ID_INTEL_IE31200_ADL_S_1 0x4660 -@@ -740,6 +742,8 @@ static const struct pci_device_id ie3120 - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IE31200_RPL_S_2), (kernel_ulong_t)&rpl_s_cfg}, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IE31200_RPL_S_3), (kernel_ulong_t)&rpl_s_cfg}, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IE31200_RPL_S_4), (kernel_ulong_t)&rpl_s_cfg}, -+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IE31200_RPL_S_5), (kernel_ulong_t)&rpl_s_cfg}, -+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IE31200_RPL_S_6), (kernel_ulong_t)&rpl_s_cfg}, - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IE31200_ADL_S_1), (kernel_ulong_t)&rpl_s_cfg}, - { 0, } /* 0 terminated list. */ - }; -diff -purNx .git BPI-Router-Linux-kernel/drivers/edac/igen6_edac.c BPI-Router-Linux-kernel-6.16.12/drivers/edac/igen6_edac.c ---- BPI-Router-Linux-kernel/drivers/edac/igen6_edac.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/edac/igen6_edac.c 2025-10-22 13:53:56.431169546 -0400 -@@ -125,7 +125,7 @@ - #define MEM_SLICE_HASH_MASK(v) (GET_BITFIELD(v, 6, 19) << 6) - #define MEM_SLICE_HASH_LSB_MASK_BIT(v) GET_BITFIELD(v, 24, 26) - --static const struct res_config { -+static struct res_config { - bool machine_check; - /* The number of present memory controllers. */ - int num_imc; -@@ -479,7 +479,7 @@ static u64 rpl_p_err_addr(u64 ecclog) - return ECC_ERROR_LOG_ADDR45(ecclog); - } - --static const struct res_config ehl_cfg = { -+static struct res_config ehl_cfg = { - .num_imc = 1, - .imc_base = 0x5000, - .ibecc_base = 0xdc00, -@@ -489,7 +489,7 @@ static const struct res_config ehl_cfg = - .err_addr_to_imc_addr = ehl_err_addr_to_imc_addr, - }; - --static const struct res_config icl_cfg = { -+static struct res_config icl_cfg = { - .num_imc = 1, - .imc_base = 0x5000, - .ibecc_base = 0xd800, -@@ -499,7 +499,7 @@ static const struct res_config icl_cfg = - .err_addr_to_imc_addr = ehl_err_addr_to_imc_addr, - }; - --static const struct res_config tgl_cfg = { -+static struct res_config tgl_cfg = { - .machine_check = true, - .num_imc = 2, - .imc_base = 0x5000, -@@ -513,7 +513,7 @@ static const struct res_config tgl_cfg = - .err_addr_to_imc_addr = tgl_err_addr_to_imc_addr, - }; - --static const struct res_config adl_cfg = { -+static struct res_config adl_cfg = { - .machine_check = true, - .num_imc = 2, - .imc_base = 0xd800, -@@ -524,7 +524,7 @@ static const struct res_config adl_cfg = - .err_addr_to_imc_addr = adl_err_addr_to_imc_addr, - }; - --static const struct res_config adl_n_cfg = { -+static struct res_config adl_n_cfg = { - .machine_check = true, - .num_imc = 1, - .imc_base = 0xd800, -@@ -535,7 +535,7 @@ static const struct res_config adl_n_cfg - .err_addr_to_imc_addr = adl_err_addr_to_imc_addr, - }; - --static const struct res_config rpl_p_cfg = { -+static struct res_config rpl_p_cfg = { - .machine_check = true, - .num_imc = 2, - .imc_base = 0xd800, -@@ -547,7 +547,7 @@ static const struct res_config rpl_p_cfg - .err_addr_to_imc_addr = adl_err_addr_to_imc_addr, - }; - --static const struct res_config mtl_ps_cfg = { -+static struct res_config mtl_ps_cfg = { - .machine_check = true, - .num_imc = 2, - .imc_base = 0xd800, -@@ -558,7 +558,7 @@ static const struct res_config mtl_ps_cf - .err_addr_to_imc_addr = adl_err_addr_to_imc_addr, - }; - --static const struct res_config mtl_p_cfg = { -+static struct res_config mtl_p_cfg = { - .machine_check = true, - .num_imc = 2, - .imc_base = 0xd800, -@@ -569,7 +569,7 @@ static const struct res_config mtl_p_cfg - .err_addr_to_imc_addr = adl_err_addr_to_imc_addr, - }; - --static const struct pci_device_id igen6_pci_tbl[] = { -+static struct pci_device_id igen6_pci_tbl[] = { - { PCI_VDEVICE(INTEL, DID_EHL_SKU5), (kernel_ulong_t)&ehl_cfg }, - { PCI_VDEVICE(INTEL, DID_EHL_SKU6), (kernel_ulong_t)&ehl_cfg }, - { PCI_VDEVICE(INTEL, DID_EHL_SKU7), (kernel_ulong_t)&ehl_cfg }, -@@ -1350,9 +1350,11 @@ static int igen6_register_mcis(struct pc - return -ENODEV; - } - -- if (lmc < res_cfg->num_imc) -+ if (lmc < res_cfg->num_imc) { - igen6_printk(KERN_WARNING, "Expected %d mcs, but only %d detected.", - res_cfg->num_imc, lmc); -+ res_cfg->num_imc = lmc; -+ } - - return 0; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/edac/mem_repair.c BPI-Router-Linux-kernel-6.16.12/drivers/edac/mem_repair.c ---- BPI-Router-Linux-kernel/drivers/edac/mem_repair.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/edac/mem_repair.c 2025-10-22 13:53:56.431169546 -0400 -@@ -333,6 +333,7 @@ static int mem_repair_create_desc(struct - for (i = 0; i < MR_MAX_ATTRS; i++) { - memcpy(&ctx->mem_repair_dev_attr[i], - &dev_attr[i], sizeof(dev_attr[i])); -+ sysfs_attr_init(&ctx->mem_repair_dev_attr[i].dev_attr.attr); - ctx->mem_repair_attrs[i] = - &ctx->mem_repair_dev_attr[i].dev_attr.attr; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/edac/scrub.c BPI-Router-Linux-kernel-6.16.12/drivers/edac/scrub.c ---- BPI-Router-Linux-kernel/drivers/edac/scrub.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/edac/scrub.c 2025-10-22 13:53:56.431169546 -0400 -@@ -176,6 +176,7 @@ static int scrub_create_desc(struct devi - group = &scrub_ctx->group; - for (i = 0; i < SCRUB_MAX_ATTRS; i++) { - memcpy(&scrub_ctx->scrub_dev_attr[i], &dev_attr[i], sizeof(dev_attr[i])); -+ sysfs_attr_init(&scrub_ctx->scrub_dev_attr[i].dev_attr.attr); - scrub_ctx->scrub_attrs[i] = &scrub_ctx->scrub_dev_attr[i].dev_attr.attr; - } - sprintf(scrub_ctx->name, "%s%d", "scrub", instance); -diff -purNx .git BPI-Router-Linux-kernel/drivers/edac/synopsys_edac.c BPI-Router-Linux-kernel-6.16.12/drivers/edac/synopsys_edac.c ---- BPI-Router-Linux-kernel/drivers/edac/synopsys_edac.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/edac/synopsys_edac.c 2025-10-22 13:53:56.431169546 -0400 -@@ -332,20 +332,26 @@ struct synps_edac_priv { - #endif - }; - -+enum synps_platform_type { -+ ZYNQ, -+ ZYNQMP, -+ SYNPS, -+}; -+ - /** - * struct synps_platform_data - synps platform data structure. -+ * @platform: Identifies the target hardware platform - * @get_error_info: Get EDAC error info. - * @get_mtype: Get mtype. - * @get_dtype: Get dtype. -- * @get_ecc_state: Get ECC state. - * @get_mem_info: Get EDAC memory info - * @quirks: To differentiate IPs. - */ - struct synps_platform_data { -+ enum synps_platform_type platform; - int (*get_error_info)(struct synps_edac_priv *priv); - enum mem_type (*get_mtype)(const void __iomem *base); - enum dev_type (*get_dtype)(const void __iomem *base); -- bool (*get_ecc_state)(void __iomem *base); - #ifdef CONFIG_EDAC_DEBUG - u64 (*get_mem_info)(struct synps_edac_priv *priv); - #endif -@@ -720,51 +726,38 @@ static enum dev_type zynqmp_get_dtype(co - return dt; - } - --/** -- * zynq_get_ecc_state - Return the controller ECC enable/disable status. -- * @base: DDR memory controller base address. -- * -- * Get the ECC enable/disable status of the controller. -- * -- * Return: true if enabled, otherwise false. -- */ --static bool zynq_get_ecc_state(void __iomem *base) --{ -- enum dev_type dt; -- u32 ecctype; -- -- dt = zynq_get_dtype(base); -- if (dt == DEV_UNKNOWN) -- return false; -- -- ecctype = readl(base + SCRUB_OFST) & SCRUB_MODE_MASK; -- if ((ecctype == SCRUB_MODE_SECDED) && (dt == DEV_X2)) -- return true; -- -- return false; --} -- --/** -- * zynqmp_get_ecc_state - Return the controller ECC enable/disable status. -- * @base: DDR memory controller base address. -- * -- * Get the ECC enable/disable status for the controller. -- * -- * Return: a ECC status boolean i.e true/false - enabled/disabled. -- */ --static bool zynqmp_get_ecc_state(void __iomem *base) -+static bool get_ecc_state(struct synps_edac_priv *priv) - { -+ u32 ecctype, clearval; - enum dev_type dt; -- u32 ecctype; - -- dt = zynqmp_get_dtype(base); -- if (dt == DEV_UNKNOWN) -- return false; -- -- ecctype = readl(base + ECC_CFG0_OFST) & SCRUB_MODE_MASK; -- if ((ecctype == SCRUB_MODE_SECDED) && -- ((dt == DEV_X2) || (dt == DEV_X4) || (dt == DEV_X8))) -- return true; -+ if (priv->p_data->platform == ZYNQ) { -+ dt = zynq_get_dtype(priv->baseaddr); -+ if (dt == DEV_UNKNOWN) -+ return false; -+ -+ ecctype = readl(priv->baseaddr + SCRUB_OFST) & SCRUB_MODE_MASK; -+ if (ecctype == SCRUB_MODE_SECDED && dt == DEV_X2) { -+ clearval = ECC_CTRL_CLR_CE_ERR | ECC_CTRL_CLR_UE_ERR; -+ writel(clearval, priv->baseaddr + ECC_CTRL_OFST); -+ writel(0x0, priv->baseaddr + ECC_CTRL_OFST); -+ return true; -+ } -+ } else { -+ dt = zynqmp_get_dtype(priv->baseaddr); -+ if (dt == DEV_UNKNOWN) -+ return false; -+ -+ ecctype = readl(priv->baseaddr + ECC_CFG0_OFST) & SCRUB_MODE_MASK; -+ if (ecctype == SCRUB_MODE_SECDED && -+ (dt == DEV_X2 || dt == DEV_X4 || dt == DEV_X8)) { -+ clearval = readl(priv->baseaddr + ECC_CLR_OFST) | -+ ECC_CTRL_CLR_CE_ERR | ECC_CTRL_CLR_CE_ERRCNT | -+ ECC_CTRL_CLR_UE_ERR | ECC_CTRL_CLR_UE_ERRCNT; -+ writel(clearval, priv->baseaddr + ECC_CLR_OFST); -+ return true; -+ } -+ } - - return false; - } -@@ -934,18 +927,18 @@ static int setup_irq(struct mem_ctl_info - } - - static const struct synps_platform_data zynq_edac_def = { -+ .platform = ZYNQ, - .get_error_info = zynq_get_error_info, - .get_mtype = zynq_get_mtype, - .get_dtype = zynq_get_dtype, -- .get_ecc_state = zynq_get_ecc_state, - .quirks = 0, - }; - - static const struct synps_platform_data zynqmp_edac_def = { -+ .platform = ZYNQMP, - .get_error_info = zynqmp_get_error_info, - .get_mtype = zynqmp_get_mtype, - .get_dtype = zynqmp_get_dtype, -- .get_ecc_state = zynqmp_get_ecc_state, - #ifdef CONFIG_EDAC_DEBUG - .get_mem_info = zynqmp_get_mem_info, - #endif -@@ -957,10 +950,10 @@ static const struct synps_platform_data - }; - - static const struct synps_platform_data synopsys_edac_def = { -+ .platform = SYNPS, - .get_error_info = zynqmp_get_error_info, - .get_mtype = zynqmp_get_mtype, - .get_dtype = zynqmp_get_dtype, -- .get_ecc_state = zynqmp_get_ecc_state, - .quirks = (DDR_ECC_INTR_SUPPORT | DDR_ECC_INTR_SELF_CLEAR - #ifdef CONFIG_EDAC_DEBUG - | DDR_ECC_DATA_POISON_SUPPORT -@@ -1390,10 +1383,6 @@ static int mc_probe(struct platform_devi - if (!p_data) - return -ENODEV; - -- if (!p_data->get_ecc_state(baseaddr)) { -- edac_printk(KERN_INFO, EDAC_MC, "ECC not enabled\n"); -- return -ENXIO; -- } - - layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; - layers[0].size = SYNPS_EDAC_NR_CSROWS; -@@ -1413,6 +1402,12 @@ static int mc_probe(struct platform_devi - priv = mci->pvt_info; - priv->baseaddr = baseaddr; - priv->p_data = p_data; -+ if (!get_ecc_state(priv)) { -+ edac_printk(KERN_INFO, EDAC_MC, "ECC not enabled\n"); -+ rc = -ENODEV; -+ goto free_edac_mc; -+ } -+ - spin_lock_init(&priv->reglock); - - mc_init(mci, pdev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/firewire/core-cdev.c BPI-Router-Linux-kernel-6.16.12/drivers/firewire/core-cdev.c ---- BPI-Router-Linux-kernel/drivers/firewire/core-cdev.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/firewire/core-cdev.c 2025-10-22 13:53:56.431169546 -0400 -@@ -41,7 +41,7 @@ - /* - * ABI version history is documented in linux/firewire-cdev.h. - */ --#define FW_CDEV_KERNEL_VERSION 5 -+#define FW_CDEV_KERNEL_VERSION 6 - #define FW_CDEV_VERSION_EVENT_REQUEST2 4 - #define FW_CDEV_VERSION_ALLOCATE_REGION_END 4 - #define FW_CDEV_VERSION_AUTO_FLUSH_ISO_OVERFLOW 5 -diff -purNx .git BPI-Router-Linux-kernel/drivers/firmware/arm_ffa/driver.c BPI-Router-Linux-kernel-6.16.12/drivers/firmware/arm_ffa/driver.c ---- BPI-Router-Linux-kernel/drivers/firmware/arm_ffa/driver.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/firmware/arm_ffa/driver.c 2025-10-22 13:53:56.431169546 -0400 -@@ -110,7 +110,7 @@ struct ffa_drv_info { - struct work_struct sched_recv_irq_work; - struct xarray partition_info; - DECLARE_HASHTABLE(notifier_hash, ilog2(FFA_MAX_NOTIFICATIONS)); -- struct mutex notify_lock; /* lock to protect notifier hashtable */ -+ rwlock_t notify_lock; /* lock to protect notifier hashtable */ - }; - - static struct ffa_drv_info *drv_info; -@@ -1250,13 +1250,12 @@ notifier_hnode_get_by_type(u16 notify_id - return NULL; - } - --static int --update_notifier_cb(struct ffa_device *dev, int notify_id, void *cb, -- void *cb_data, bool is_registration, bool is_framework) -+static int update_notifier_cb(struct ffa_device *dev, int notify_id, -+ struct notifier_cb_info *cb, bool is_framework) - { - struct notifier_cb_info *cb_info = NULL; - enum notify_type type = ffa_notify_type_get(dev->vm_id); -- bool cb_found; -+ bool cb_found, is_registration = !!cb; - - if (is_framework) - cb_info = notifier_hnode_get_by_vmid_uuid(notify_id, dev->vm_id, -@@ -1270,20 +1269,10 @@ update_notifier_cb(struct ffa_device *de - return -EINVAL; - - if (is_registration) { -- cb_info = kzalloc(sizeof(*cb_info), GFP_KERNEL); -- if (!cb_info) -- return -ENOMEM; -- -- cb_info->dev = dev; -- cb_info->cb_data = cb_data; -- if (is_framework) -- cb_info->fwk_cb = cb; -- else -- cb_info->cb = cb; -- -- hash_add(drv_info->notifier_hash, &cb_info->hnode, notify_id); -+ hash_add(drv_info->notifier_hash, &cb->hnode, notify_id); - } else { - hash_del(&cb_info->hnode); -+ kfree(cb_info); - } - - return 0; -@@ -1300,20 +1289,19 @@ static int __ffa_notify_relinquish(struc - if (notify_id >= FFA_MAX_NOTIFICATIONS) - return -EINVAL; - -- mutex_lock(&drv_info->notify_lock); -+ write_lock(&drv_info->notify_lock); - -- rc = update_notifier_cb(dev, notify_id, NULL, NULL, false, -- is_framework); -+ rc = update_notifier_cb(dev, notify_id, NULL, is_framework); - if (rc) { - pr_err("Could not unregister notification callback\n"); -- mutex_unlock(&drv_info->notify_lock); -+ write_unlock(&drv_info->notify_lock); - return rc; - } - - if (!is_framework) - rc = ffa_notification_unbind(dev->vm_id, BIT(notify_id)); - -- mutex_unlock(&drv_info->notify_lock); -+ write_unlock(&drv_info->notify_lock); - - return rc; - } -@@ -1334,6 +1322,7 @@ static int __ffa_notify_request(struct f - { - int rc; - u32 flags = 0; -+ struct notifier_cb_info *cb_info = NULL; - - if (ffa_notifications_disabled()) - return -EOPNOTSUPP; -@@ -1341,28 +1330,40 @@ static int __ffa_notify_request(struct f - if (notify_id >= FFA_MAX_NOTIFICATIONS) - return -EINVAL; - -- mutex_lock(&drv_info->notify_lock); -+ cb_info = kzalloc(sizeof(*cb_info), GFP_KERNEL); -+ if (!cb_info) -+ return -ENOMEM; -+ -+ cb_info->dev = dev; -+ cb_info->cb_data = cb_data; -+ if (is_framework) -+ cb_info->fwk_cb = cb; -+ else -+ cb_info->cb = cb; -+ -+ write_lock(&drv_info->notify_lock); - - if (!is_framework) { - if (is_per_vcpu) - flags = PER_VCPU_NOTIFICATION_FLAG; - - rc = ffa_notification_bind(dev->vm_id, BIT(notify_id), flags); -- if (rc) { -- mutex_unlock(&drv_info->notify_lock); -- return rc; -- } -+ if (rc) -+ goto out_unlock_free; - } - -- rc = update_notifier_cb(dev, notify_id, cb, cb_data, true, -- is_framework); -+ rc = update_notifier_cb(dev, notify_id, cb_info, is_framework); - if (rc) { - pr_err("Failed to register callback for %d - %d\n", - notify_id, rc); - if (!is_framework) - ffa_notification_unbind(dev->vm_id, BIT(notify_id)); - } -- mutex_unlock(&drv_info->notify_lock); -+ -+out_unlock_free: -+ write_unlock(&drv_info->notify_lock); -+ if (rc) -+ kfree(cb_info); - - return rc; - } -@@ -1406,9 +1407,9 @@ static void handle_notif_callbacks(u64 b - if (!(bitmap & 1)) - continue; - -- mutex_lock(&drv_info->notify_lock); -+ read_lock(&drv_info->notify_lock); - cb_info = notifier_hnode_get_by_type(notify_id, type); -- mutex_unlock(&drv_info->notify_lock); -+ read_unlock(&drv_info->notify_lock); - - if (cb_info && cb_info->cb) - cb_info->cb(notify_id, cb_info->cb_data); -@@ -1446,9 +1447,9 @@ static void handle_fwk_notif_callbacks(u - - ffa_rx_release(); - -- mutex_lock(&drv_info->notify_lock); -+ read_lock(&drv_info->notify_lock); - cb_info = notifier_hnode_get_by_vmid_uuid(notify_id, target, &uuid); -- mutex_unlock(&drv_info->notify_lock); -+ read_unlock(&drv_info->notify_lock); - - if (cb_info && cb_info->fwk_cb) - cb_info->fwk_cb(notify_id, cb_info->cb_data, buf); -@@ -1973,7 +1974,7 @@ static void ffa_notifications_setup(void - goto cleanup; - - hash_init(drv_info->notifier_hash); -- mutex_init(&drv_info->notify_lock); -+ rwlock_init(&drv_info->notify_lock); - - drv_info->notif_enabled = true; - return; -@@ -2058,7 +2059,7 @@ free_drv_info: - kfree(drv_info); - return ret; - } --module_init(ffa_init); -+rootfs_initcall(ffa_init); - - static void __exit ffa_exit(void) - { -diff -purNx .git BPI-Router-Linux-kernel/drivers/firmware/arm_scmi/perf.c BPI-Router-Linux-kernel-6.16.12/drivers/firmware/arm_scmi/perf.c ---- BPI-Router-Linux-kernel/drivers/firmware/arm_scmi/perf.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/firmware/arm_scmi/perf.c 2025-10-22 13:53:56.431169546 -0400 -@@ -892,7 +892,7 @@ static int scmi_dvfs_device_opps_add(con - freq = dom->opp[idx].indicative_freq * dom->mult_factor; - - /* All OPPs above the sustained frequency are treated as turbo */ -- data.turbo = freq > dom->sustained_freq_khz * 1000; -+ data.turbo = freq > dom->sustained_freq_khz * 1000UL; - - data.level = dom->opp[idx].perf; - data.freq = freq; -diff -purNx .git BPI-Router-Linux-kernel/drivers/firmware/arm_scmi/scmi_power_control.c BPI-Router-Linux-kernel-6.16.12/drivers/firmware/arm_scmi/scmi_power_control.c ---- BPI-Router-Linux-kernel/drivers/firmware/arm_scmi/scmi_power_control.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/firmware/arm_scmi/scmi_power_control.c 2025-10-22 13:53:56.431169546 -0400 -@@ -46,6 +46,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -324,12 +325,7 @@ static int scmi_userspace_notifier(struc - - static void scmi_suspend_work_func(struct work_struct *work) - { -- struct scmi_syspower_conf *sc = -- container_of(work, struct scmi_syspower_conf, suspend_work); -- - pm_suspend(PM_SUSPEND_MEM); -- -- sc->state = SCMI_SYSPOWER_IDLE; - } - - static int scmi_syspower_probe(struct scmi_device *sdev) -@@ -354,6 +350,7 @@ static int scmi_syspower_probe(struct sc - sc->required_transition = SCMI_SYSTEM_MAX; - sc->userspace_nb.notifier_call = &scmi_userspace_notifier; - sc->dev = &sdev->dev; -+ dev_set_drvdata(&sdev->dev, sc); - - INIT_WORK(&sc->suspend_work, scmi_suspend_work_func); - -@@ -363,6 +360,18 @@ static int scmi_syspower_probe(struct sc - NULL, &sc->userspace_nb); - } - -+static int scmi_system_power_resume(struct device *dev) -+{ -+ struct scmi_syspower_conf *sc = dev_get_drvdata(dev); -+ -+ sc->state = SCMI_SYSPOWER_IDLE; -+ return 0; -+} -+ -+static const struct dev_pm_ops scmi_system_power_pmops = { -+ SYSTEM_SLEEP_PM_OPS(NULL, scmi_system_power_resume) -+}; -+ - static const struct scmi_device_id scmi_id_table[] = { - { SCMI_PROTOCOL_SYSTEM, "syspower" }, - { }, -@@ -370,6 +379,9 @@ static const struct scmi_device_id scmi_ - MODULE_DEVICE_TABLE(scmi, scmi_id_table); - - static struct scmi_driver scmi_system_power_driver = { -+ .driver = { -+ .pm = pm_sleep_ptr(&scmi_system_power_pmops), -+ }, - .name = "scmi-system-power", - .probe = scmi_syspower_probe, - .id_table = scmi_id_table, -diff -purNx .git BPI-Router-Linux-kernel/drivers/firmware/efi/libstub/Makefile.zboot BPI-Router-Linux-kernel-6.16.12/drivers/firmware/efi/libstub/Makefile.zboot ---- BPI-Router-Linux-kernel/drivers/firmware/efi/libstub/Makefile.zboot 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/firmware/efi/libstub/Makefile.zboot 2025-10-22 13:53:56.431169546 -0400 -@@ -36,7 +36,7 @@ aflags-zboot-header-$(EFI_ZBOOT_FORWARD_ - -DPE_DLL_CHAR_EX=IMAGE_DLLCHARACTERISTICS_EX_FORWARD_CFI_COMPAT - - AFLAGS_zboot-header.o += -DMACHINE_TYPE=IMAGE_FILE_MACHINE_$(EFI_ZBOOT_MACH_TYPE) \ -- -DZBOOT_EFI_PATH="\"$(realpath $(obj)/vmlinuz.efi.elf)\"" \ -+ -DZBOOT_EFI_PATH="\"$(abspath $(obj)/vmlinuz.efi.elf)\"" \ - -DZBOOT_SIZE_LEN=$(zboot-size-len-y) \ - -DCOMP_TYPE="\"$(comp-type-y)\"" \ - $(aflags-zboot-header-y) -diff -purNx .git BPI-Router-Linux-kernel/drivers/firmware/efi/libstub/zboot.lds BPI-Router-Linux-kernel-6.16.12/drivers/firmware/efi/libstub/zboot.lds ---- BPI-Router-Linux-kernel/drivers/firmware/efi/libstub/zboot.lds 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/firmware/efi/libstub/zboot.lds 2025-10-22 13:53:56.431169546 -0400 -@@ -29,14 +29,12 @@ SECTIONS - . = _etext; - } - --#ifdef CONFIG_EFI_SBAT - .sbat : ALIGN(4096) { - _sbat = .; - *(.sbat) - _esbat = ALIGN(4096); - . = _esbat; - } --#endif - - .data : ALIGN(4096) { - _data = .; -@@ -60,6 +58,6 @@ SECTIONS - PROVIDE(__efistub__gzdata_size = - ABSOLUTE(__efistub__gzdata_end - __efistub__gzdata_start)); - --PROVIDE(__data_rawsize = ABSOLUTE(_edata - _etext)); --PROVIDE(__data_size = ABSOLUTE(_end - _etext)); -+PROVIDE(__data_rawsize = ABSOLUTE(_edata - _data)); -+PROVIDE(__data_size = ABSOLUTE(_end - _data)); - PROVIDE(__sbat_size = ABSOLUTE(_esbat - _sbat)); -diff -purNx .git BPI-Router-Linux-kernel/drivers/firmware/efi/stmm/tee_stmm_efi.c BPI-Router-Linux-kernel-6.16.12/drivers/firmware/efi/stmm/tee_stmm_efi.c ---- BPI-Router-Linux-kernel/drivers/firmware/efi/stmm/tee_stmm_efi.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/firmware/efi/stmm/tee_stmm_efi.c 2025-10-22 13:53:56.431169546 -0400 -@@ -143,6 +143,10 @@ static efi_status_t mm_communicate(u8 *c - return var_hdr->ret_status; - } - -+#define COMM_BUF_SIZE(__payload_size) (MM_COMMUNICATE_HEADER_SIZE + \ -+ MM_VARIABLE_COMMUNICATE_SIZE + \ -+ (__payload_size)) -+ - /** - * setup_mm_hdr() - Allocate a buffer for StandAloneMM and initialize the - * header data. -@@ -173,9 +177,8 @@ static void *setup_mm_hdr(u8 **dptr, siz - return NULL; - } - -- comm_buf = kzalloc(MM_COMMUNICATE_HEADER_SIZE + -- MM_VARIABLE_COMMUNICATE_SIZE + payload_size, -- GFP_KERNEL); -+ comm_buf = alloc_pages_exact(COMM_BUF_SIZE(payload_size), -+ GFP_KERNEL | __GFP_ZERO); - if (!comm_buf) { - *ret = EFI_OUT_OF_RESOURCES; - return NULL; -@@ -239,7 +242,7 @@ static efi_status_t get_max_payload(size - */ - *size -= 2; - out: -- kfree(comm_buf); -+ free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size)); - return ret; - } - -@@ -282,7 +285,7 @@ static efi_status_t get_property_int(u16 - memcpy(var_property, &smm_property->property, sizeof(*var_property)); - - out: -- kfree(comm_buf); -+ free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size)); - return ret; - } - -@@ -347,7 +350,7 @@ static efi_status_t tee_get_variable(u16 - memcpy(data, (u8 *)var_acc->name + var_acc->name_size, - var_acc->data_size); - out: -- kfree(comm_buf); -+ free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size)); - return ret; - } - -@@ -404,7 +407,7 @@ static efi_status_t tee_get_next_variabl - memcpy(name, var_getnext->name, var_getnext->name_size); - - out: -- kfree(comm_buf); -+ free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size)); - return ret; - } - -@@ -467,7 +470,7 @@ static efi_status_t tee_set_variable(efi - ret = mm_communicate(comm_buf, payload_size); - dev_dbg(pvt_data.dev, "Set Variable %s %d %lx\n", __FILE__, __LINE__, ret); - out: -- kfree(comm_buf); -+ free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size)); - return ret; - } - -@@ -507,7 +510,7 @@ static efi_status_t tee_query_variable_i - *max_variable_size = mm_query_info->max_variable_size; - - out: -- kfree(comm_buf); -+ free_pages_exact(comm_buf, COMM_BUF_SIZE(payload_size)); - return ret; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/firmware/qcom/qcom_scm.c BPI-Router-Linux-kernel-6.16.12/drivers/firmware/qcom/qcom_scm.c ---- BPI-Router-Linux-kernel/drivers/firmware/qcom/qcom_scm.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/firmware/qcom/qcom_scm.c 2025-10-22 13:53:56.431169546 -0400 -@@ -1603,7 +1603,13 @@ bool qcom_scm_lmh_dcvsh_available(void) - } - EXPORT_SYMBOL_GPL(qcom_scm_lmh_dcvsh_available); - --int qcom_scm_shm_bridge_enable(void) -+/* -+ * This is only supposed to be called once by the TZMem module. It takes the -+ * SCM struct device as argument and uses it to pass the call as at the time -+ * the SHM Bridge is enabled, the SCM is not yet fully set up and doesn't -+ * accept global user calls. Don't try to use the __scm pointer here. -+ */ -+int qcom_scm_shm_bridge_enable(struct device *scm_dev) - { - int ret; - -@@ -1615,11 +1621,11 @@ int qcom_scm_shm_bridge_enable(void) - - struct qcom_scm_res res; - -- if (!__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_MP, -+ if (!__qcom_scm_is_call_available(scm_dev, QCOM_SCM_SVC_MP, - QCOM_SCM_MP_SHM_BRIDGE_ENABLE)) - return -EOPNOTSUPP; - -- ret = qcom_scm_call(__scm->dev, &desc, &res); -+ ret = qcom_scm_call(scm_dev, &desc, &res); - - if (ret) - return ret; -@@ -1631,7 +1637,7 @@ int qcom_scm_shm_bridge_enable(void) - } - EXPORT_SYMBOL_GPL(qcom_scm_shm_bridge_enable); - --int qcom_scm_shm_bridge_create(struct device *dev, u64 pfn_and_ns_perm_flags, -+int qcom_scm_shm_bridge_create(u64 pfn_and_ns_perm_flags, - u64 ipfn_and_s_perm_flags, u64 size_and_flags, - u64 ns_vmids, u64 *handle) - { -@@ -1659,7 +1665,7 @@ int qcom_scm_shm_bridge_create(struct de - } - EXPORT_SYMBOL_GPL(qcom_scm_shm_bridge_create); - --int qcom_scm_shm_bridge_delete(struct device *dev, u64 handle) -+int qcom_scm_shm_bridge_delete(u64 handle) - { - struct qcom_scm_desc desc = { - .svc = QCOM_SCM_SVC_MP, -@@ -2250,24 +2256,47 @@ static int qcom_scm_probe(struct platfor - if (ret) - return ret; - -- /* Paired with smp_load_acquire() in qcom_scm_is_available(). */ -- smp_store_release(&__scm, scm); -+ ret = of_reserved_mem_device_init(scm->dev); -+ if (ret && ret != -ENODEV) -+ return dev_err_probe(scm->dev, ret, -+ "Failed to setup the reserved memory region for TZ mem\n"); -+ -+ ret = qcom_tzmem_enable(scm->dev); -+ if (ret) -+ return dev_err_probe(scm->dev, ret, -+ "Failed to enable the TrustZone memory allocator\n"); -+ -+ memset(&pool_config, 0, sizeof(pool_config)); -+ pool_config.initial_size = 0; -+ pool_config.policy = QCOM_TZMEM_POLICY_ON_DEMAND; -+ pool_config.max_size = SZ_256K; -+ -+ scm->mempool = devm_qcom_tzmem_pool_new(scm->dev, &pool_config); -+ if (IS_ERR(scm->mempool)) -+ return dev_err_probe(scm->dev, PTR_ERR(scm->mempool), -+ "Failed to create the SCM memory pool\n"); - - irq = platform_get_irq_optional(pdev, 0); - if (irq < 0) { -- if (irq != -ENXIO) { -- ret = irq; -- goto err; -- } -+ if (irq != -ENXIO) -+ return irq; - } else { -- ret = devm_request_threaded_irq(__scm->dev, irq, NULL, qcom_scm_irq_handler, -- IRQF_ONESHOT, "qcom-scm", __scm); -- if (ret < 0) { -- dev_err_probe(scm->dev, ret, "Failed to request qcom-scm irq\n"); -- goto err; -- } -+ ret = devm_request_threaded_irq(scm->dev, irq, NULL, qcom_scm_irq_handler, -+ IRQF_ONESHOT, "qcom-scm", scm); -+ if (ret < 0) -+ return dev_err_probe(scm->dev, ret, -+ "Failed to request qcom-scm irq\n"); - } - -+ /* -+ * Paired with smp_load_acquire() in qcom_scm_is_available(). -+ * -+ * This marks the SCM API as ready to accept user calls and can only -+ * be called after the TrustZone memory pool is initialized and the -+ * waitqueue interrupt requested. -+ */ -+ smp_store_release(&__scm, scm); -+ - __get_convention(); - - /* -@@ -2283,32 +2312,6 @@ static int qcom_scm_probe(struct platfor - if (of_property_read_bool(pdev->dev.of_node, "qcom,sdi-enabled") || !download_mode) - qcom_scm_disable_sdi(); - -- ret = of_reserved_mem_device_init(__scm->dev); -- if (ret && ret != -ENODEV) { -- dev_err_probe(__scm->dev, ret, -- "Failed to setup the reserved memory region for TZ mem\n"); -- goto err; -- } -- -- ret = qcom_tzmem_enable(__scm->dev); -- if (ret) { -- dev_err_probe(__scm->dev, ret, -- "Failed to enable the TrustZone memory allocator\n"); -- goto err; -- } -- -- memset(&pool_config, 0, sizeof(pool_config)); -- pool_config.initial_size = 0; -- pool_config.policy = QCOM_TZMEM_POLICY_ON_DEMAND; -- pool_config.max_size = SZ_256K; -- -- __scm->mempool = devm_qcom_tzmem_pool_new(__scm->dev, &pool_config); -- if (IS_ERR(__scm->mempool)) { -- ret = dev_err_probe(__scm->dev, PTR_ERR(__scm->mempool), -- "Failed to create the SCM memory pool\n"); -- goto err; -- } -- - /* - * Initialize the QSEECOM interface. - * -@@ -2323,12 +2326,6 @@ static int qcom_scm_probe(struct platfor - WARN(ret < 0, "failed to initialize qseecom: %d\n", ret); - - return 0; -- --err: -- /* Paired with smp_load_acquire() in qcom_scm_is_available(). */ -- smp_store_release(&__scm, NULL); -- -- return ret; - } - - static void qcom_scm_shutdown(struct platform_device *pdev) -diff -purNx .git BPI-Router-Linux-kernel/drivers/firmware/qcom/qcom_scm.h BPI-Router-Linux-kernel-6.16.12/drivers/firmware/qcom/qcom_scm.h ---- BPI-Router-Linux-kernel/drivers/firmware/qcom/qcom_scm.h 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/firmware/qcom/qcom_scm.h 2025-10-22 13:53:56.431169546 -0400 -@@ -83,6 +83,7 @@ int scm_legacy_call(struct device *dev, - struct qcom_scm_res *res); - - struct qcom_tzmem_pool *qcom_scm_get_tzmem_pool(void); -+int qcom_scm_shm_bridge_enable(struct device *scm_dev); - - #define QCOM_SCM_SVC_BOOT 0x01 - #define QCOM_SCM_BOOT_SET_ADDR 0x01 -diff -purNx .git BPI-Router-Linux-kernel/drivers/firmware/qcom/qcom_tzmem.c BPI-Router-Linux-kernel-6.16.12/drivers/firmware/qcom/qcom_tzmem.c ---- BPI-Router-Linux-kernel/drivers/firmware/qcom/qcom_tzmem.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/firmware/qcom/qcom_tzmem.c 2025-10-22 13:53:56.431169546 -0400 -@@ -20,6 +20,7 @@ - #include - #include - -+#include "qcom_scm.h" - #include "qcom_tzmem.h" - - struct qcom_tzmem_area { -@@ -94,7 +95,7 @@ static int qcom_tzmem_init(void) - goto notsupp; - } - -- ret = qcom_scm_shm_bridge_enable(); -+ ret = qcom_scm_shm_bridge_enable(qcom_tzmem_dev); - if (ret == -EOPNOTSUPP) - goto notsupp; - -@@ -124,9 +125,9 @@ static int qcom_tzmem_init_area(struct q - if (!handle) - return -ENOMEM; - -- ret = qcom_scm_shm_bridge_create(qcom_tzmem_dev, pfn_and_ns_perm, -- ipfn_and_s_perm, size_and_flags, -- QCOM_SCM_VMID_HLOS, handle); -+ ret = qcom_scm_shm_bridge_create(pfn_and_ns_perm, ipfn_and_s_perm, -+ size_and_flags, QCOM_SCM_VMID_HLOS, -+ handle); - if (ret) - return ret; - -@@ -142,7 +143,7 @@ static void qcom_tzmem_cleanup_area(stru - if (!qcom_tzmem_using_shm_bridge) - return; - -- qcom_scm_shm_bridge_delete(qcom_tzmem_dev, *handle); -+ qcom_scm_shm_bridge_delete(*handle); - kfree(handle); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/firmware/samsung/exynos-acpm.c BPI-Router-Linux-kernel-6.16.12/drivers/firmware/samsung/exynos-acpm.c ---- BPI-Router-Linux-kernel/drivers/firmware/samsung/exynos-acpm.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/firmware/samsung/exynos-acpm.c 2025-10-22 13:53:56.431169546 -0400 -@@ -430,6 +430,9 @@ int acpm_do_xfer(const struct acpm_handl - return -EOPNOTSUPP; - } - -+ msg.chan_id = xfer->acpm_chan_id; -+ msg.chan_type = EXYNOS_MBOX_CHAN_TYPE_DOORBELL; -+ - scoped_guard(mutex, &achan->tx_lock) { - tx_front = readl(achan->tx.front); - idx = (tx_front + 1) % achan->qlen; -@@ -446,25 +449,15 @@ int acpm_do_xfer(const struct acpm_handl - - /* Advance TX front. */ - writel(idx, achan->tx.front); -- } - -- msg.chan_id = xfer->acpm_chan_id; -- msg.chan_type = EXYNOS_MBOX_CHAN_TYPE_DOORBELL; -- ret = mbox_send_message(achan->chan, (void *)&msg); -- if (ret < 0) -- return ret; -- -- ret = acpm_wait_for_message_response(achan, xfer); -- -- /* -- * NOTE: we might prefer not to need the mailbox ticker to manage the -- * transfer queueing since the protocol layer queues things by itself. -- * Unfortunately, we have to kick the mailbox framework after we have -- * received our message. -- */ -- mbox_client_txdone(achan->chan, ret); -+ ret = mbox_send_message(achan->chan, (void *)&msg); -+ if (ret < 0) -+ return ret; -+ -+ mbox_client_txdone(achan->chan, 0); -+ } - -- return ret; -+ return acpm_wait_for_message_response(achan, xfer); - } - - /** -diff -purNx .git BPI-Router-Linux-kernel/drivers/firmware/tegra/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/firmware/tegra/Kconfig ---- BPI-Router-Linux-kernel/drivers/firmware/tegra/Kconfig 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/firmware/tegra/Kconfig 2025-10-22 13:53:56.431169546 -0400 -@@ -2,7 +2,7 @@ - menu "Tegra firmware driver" - - config TEGRA_IVC -- bool "Tegra IVC protocol" -+ bool "Tegra IVC protocol" if COMPILE_TEST - depends on ARCH_TEGRA - help - IVC (Inter-VM Communication) protocol is part of the IPC -@@ -13,8 +13,9 @@ config TEGRA_IVC - - config TEGRA_BPMP - bool "Tegra BPMP driver" -- depends on ARCH_TEGRA && TEGRA_HSP_MBOX && TEGRA_IVC -+ depends on ARCH_TEGRA && TEGRA_HSP_MBOX - depends on !CPU_BIG_ENDIAN -+ select TEGRA_IVC - help - BPMP (Boot and Power Management Processor) is designed to off-loading - the PM functions which include clock/DVFS/thermal/power from the CPU. -diff -purNx .git BPI-Router-Linux-kernel/drivers/fpga/zynq-fpga.c BPI-Router-Linux-kernel-6.16.12/drivers/fpga/zynq-fpga.c ---- BPI-Router-Linux-kernel/drivers/fpga/zynq-fpga.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/fpga/zynq-fpga.c 2025-10-22 13:53:56.431169546 -0400 -@@ -405,12 +405,12 @@ static int zynq_fpga_ops_write(struct fp - } - } - -- priv->dma_nelms = -- dma_map_sg(mgr->dev.parent, sgt->sgl, sgt->nents, DMA_TO_DEVICE); -- if (priv->dma_nelms == 0) { -+ err = dma_map_sgtable(mgr->dev.parent, sgt, DMA_TO_DEVICE, 0); -+ if (err) { - dev_err(&mgr->dev, "Unable to DMA map (TO_DEVICE)\n"); -- return -ENOMEM; -+ return err; - } -+ priv->dma_nelms = sgt->nents; - - /* enable clock */ - err = clk_enable(priv->clk); -@@ -478,7 +478,7 @@ out_clk: - clk_disable(priv->clk); - - out_free: -- dma_unmap_sg(mgr->dev.parent, sgt->sgl, sgt->nents, DMA_TO_DEVICE); -+ dma_unmap_sgtable(mgr->dev.parent, sgt, DMA_TO_DEVICE, 0); - return err; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpio/gpiolib-acpi-core.c BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpiolib-acpi-core.c ---- BPI-Router-Linux-kernel/drivers/gpio/gpiolib-acpi-core.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpiolib-acpi-core.c 2025-10-22 13:53:56.435169527 -0400 -@@ -942,7 +942,7 @@ struct gpio_desc *acpi_find_gpio(struct - { - struct acpi_device *adev = to_acpi_device_node(fwnode); - bool can_fallback = acpi_can_fallback_to_crs(adev, con_id); -- struct acpi_gpio_info info; -+ struct acpi_gpio_info info = {}; - struct gpio_desc *desc; - - desc = __acpi_find_gpio(fwnode, con_id, idx, can_fallback, &info); -@@ -992,7 +992,7 @@ int acpi_dev_gpio_irq_wake_get_by(struct - int ret; - - for (i = 0, idx = 0; idx <= index; i++) { -- struct acpi_gpio_info info; -+ struct acpi_gpio_info info = {}; - struct gpio_desc *desc; - - /* Ignore -EPROBE_DEFER, it only matters if idx matches */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpio/gpiolib-acpi-quirks.c BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpiolib-acpi-quirks.c ---- BPI-Router-Linux-kernel/drivers/gpio/gpiolib-acpi-quirks.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpiolib-acpi-quirks.c 2025-10-22 13:53:56.435169527 -0400 -@@ -319,6 +319,18 @@ static const struct dmi_system_id gpioli - }, - { - /* -+ * Same as G1619-04. New model. -+ */ -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "GPD"), -+ DMI_MATCH(DMI_PRODUCT_NAME, "G1619-05"), -+ }, -+ .driver_data = &(struct acpi_gpiolib_dmi_quirk) { -+ .ignore_wake = "PNP0C50:00@8", -+ }, -+ }, -+ { -+ /* - * Spurious wakeups from GPIO 11 - * Found in BIOS 1.04 - * https://gitlab.freedesktop.org/drm/amd/-/issues/3954 -@@ -331,6 +343,33 @@ static const struct dmi_system_id gpioli - .ignore_interrupt = "AMDI0030:00@11", - }, - }, -+ { -+ /* -+ * Wakeup only works when keyboard backlight is turned off -+ * https://gitlab.freedesktop.org/drm/amd/-/issues/4169 -+ */ -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"), -+ DMI_MATCH(DMI_PRODUCT_FAMILY, "Acer Nitro V 15"), -+ }, -+ .driver_data = &(struct acpi_gpiolib_dmi_quirk) { -+ .ignore_interrupt = "AMDI0030:00@8", -+ }, -+ }, -+ { -+ /* -+ * Spurious wakeups from TP_ATTN# pin -+ * Found in BIOS 5.35 -+ * https://gitlab.freedesktop.org/drm/amd/-/issues/4482 -+ */ -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), -+ DMI_MATCH(DMI_PRODUCT_FAMILY, "ProArt PX13"), -+ }, -+ .driver_data = &(struct acpi_gpiolib_dmi_quirk) { -+ .ignore_wake = "ASCP1A00:00@8", -+ }, -+ }, - {} /* Terminating entry */ - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpio/gpiolib.c BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpiolib.c ---- BPI-Router-Linux-kernel/drivers/gpio/gpiolib.c 2025-10-22 13:53:23.191329240 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpiolib.c 2025-10-22 13:53:56.435169527 -0400 -@@ -3297,14 +3297,15 @@ static int gpiod_get_raw_value_commit(co - static int gpio_chip_get_multiple(struct gpio_chip *gc, - unsigned long *mask, unsigned long *bits) - { -- int ret; -- - lockdep_assert_held(&gc->gpiodev->srcu); - - if (gc->get_multiple) { -+ int ret; -+ - ret = gc->get_multiple(gc, mask, bits); - if (ret > 0) - return -EBADE; -+ return ret; - } - - if (gc->get) { -@@ -4604,6 +4605,23 @@ static struct gpio_desc *gpiod_find_by_f - return desc; - } - -+static struct gpio_desc *gpiod_fwnode_lookup(struct fwnode_handle *fwnode, -+ struct device *consumer, -+ const char *con_id, -+ unsigned int idx, -+ enum gpiod_flags *flags, -+ unsigned long *lookupflags) -+{ -+ struct gpio_desc *desc; -+ -+ desc = gpiod_find_by_fwnode(fwnode, consumer, con_id, idx, flags, lookupflags); -+ if (gpiod_not_found(desc) && !IS_ERR_OR_NULL(fwnode)) -+ desc = gpiod_find_by_fwnode(fwnode->secondary, consumer, con_id, -+ idx, flags, lookupflags); -+ -+ return desc; -+} -+ - struct gpio_desc *gpiod_find_and_request(struct device *consumer, - struct fwnode_handle *fwnode, - const char *con_id, -@@ -4622,8 +4640,8 @@ struct gpio_desc *gpiod_find_and_request - int ret = 0; - - scoped_guard(srcu, &gpio_devices_srcu) { -- desc = gpiod_find_by_fwnode(fwnode, consumer, con_id, idx, -- &flags, &lookupflags); -+ desc = gpiod_fwnode_lookup(fwnode, consumer, con_id, idx, -+ &flags, &lookupflags); - if (gpiod_not_found(desc) && platform_lookup_allowed) { - /* - * Either we are not using DT or ACPI, or their lookup -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpio/gpiolib-devres.c BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpiolib-devres.c ---- BPI-Router-Linux-kernel/drivers/gpio/gpiolib-devres.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpiolib-devres.c 2025-10-22 13:53:56.435169527 -0400 -@@ -319,7 +319,7 @@ EXPORT_SYMBOL_GPL(devm_gpiod_unhinge); - */ - void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs) - { -- devm_remove_action(dev, devm_gpiod_release_array, descs); -+ devm_release_action(dev, devm_gpiod_release_array, descs); - } - EXPORT_SYMBOL_GPL(devm_gpiod_put_array); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpio/gpiolib-of.c BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpiolib-of.c ---- BPI-Router-Linux-kernel/drivers/gpio/gpiolib-of.c 2025-10-22 13:53:23.191329240 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpiolib-of.c 2025-10-22 13:53:56.435169527 -0400 -@@ -708,7 +708,7 @@ struct gpio_desc *of_find_gpio(struct de - unsigned int idx, unsigned long *flags) - { - char propname[32]; /* 32 is max size of property name */ -- enum of_gpio_flags of_flags; -+ enum of_gpio_flags of_flags = 0; - const of_find_gpio_quirk *q; - struct gpio_desc *desc; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpio/gpio-loongson-64bit.c BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpio-loongson-64bit.c ---- BPI-Router-Linux-kernel/drivers/gpio/gpio-loongson-64bit.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpio-loongson-64bit.c 2025-10-22 13:53:56.431169546 -0400 -@@ -222,6 +222,7 @@ static const struct loongson_gpio_chip_d - .conf_offset = 0x0, - .in_offset = 0xc, - .out_offset = 0x8, -+ .inten_offset = 0x14, - }; - - static const struct loongson_gpio_chip_data loongson_gpio_ls2k2000_data1 = { -@@ -230,6 +231,7 @@ static const struct loongson_gpio_chip_d - .conf_offset = 0x0, - .in_offset = 0x20, - .out_offset = 0x10, -+ .inten_offset = 0x30, - }; - - static const struct loongson_gpio_chip_data loongson_gpio_ls2k2000_data2 = { -@@ -246,6 +248,7 @@ static const struct loongson_gpio_chip_d - .conf_offset = 0x0, - .in_offset = 0xc, - .out_offset = 0x8, -+ .inten_offset = 0x14, - }; - - static const struct loongson_gpio_chip_data loongson_gpio_ls7a_data = { -@@ -254,6 +257,7 @@ static const struct loongson_gpio_chip_d - .conf_offset = 0x800, - .in_offset = 0xa00, - .out_offset = 0x900, -+ .inten_offset = 0xb00, - }; - - /* LS7A2000 chipset GPIO */ -@@ -263,12 +267,13 @@ static const struct loongson_gpio_chip_d - .conf_offset = 0x800, - .in_offset = 0xa00, - .out_offset = 0x900, -+ .inten_offset = 0xb00, - }; - - /* LS7A2000 ACPI GPIO */ - static const struct loongson_gpio_chip_data loongson_gpio_ls7a2000_data1 = { - .label = "ls7a2000_gpio", -- .mode = BYTE_CTRL_MODE, -+ .mode = BIT_CTRL_MODE, - .conf_offset = 0x4, - .in_offset = 0x8, - .out_offset = 0x0, -@@ -281,6 +286,7 @@ static const struct loongson_gpio_chip_d - .conf_offset = 0x0, - .in_offset = 0xc, - .out_offset = 0x8, -+ .inten_offset = 0x14, - }; - - static const struct of_device_id loongson_gpio_of_match[] = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpio/gpio-mlxbf2.c BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpio-mlxbf2.c ---- BPI-Router-Linux-kernel/drivers/gpio/gpio-mlxbf2.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpio-mlxbf2.c 2025-10-22 13:53:56.431169546 -0400 -@@ -397,7 +397,7 @@ mlxbf2_gpio_probe(struct platform_device - gc->ngpio = npins; - gc->owner = THIS_MODULE; - -- irq = platform_get_irq(pdev, 0); -+ irq = platform_get_irq_optional(pdev, 0); - if (irq >= 0) { - girq = &gs->gc.irq; - gpio_irq_chip_set_chip(girq, &mlxbf2_gpio_irq_chip); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpio/gpio-mlxbf3.c BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpio-mlxbf3.c ---- BPI-Router-Linux-kernel/drivers/gpio/gpio-mlxbf3.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpio-mlxbf3.c 2025-10-22 13:53:56.431169546 -0400 -@@ -227,7 +227,7 @@ static int mlxbf3_gpio_probe(struct plat - gc->owner = THIS_MODULE; - gc->add_pin_ranges = mlxbf3_gpio_add_pin_ranges; - -- irq = platform_get_irq(pdev, 0); -+ irq = platform_get_irq_optional(pdev, 0); - if (irq >= 0) { - girq = &gs->gc.irq; - gpio_irq_chip_set_chip(girq, &gpio_mlxbf3_irqchip); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpio/gpio-pca953x.c BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpio-pca953x.c ---- BPI-Router-Linux-kernel/drivers/gpio/gpio-pca953x.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpio-pca953x.c 2025-10-22 13:53:56.435169527 -0400 -@@ -974,7 +974,7 @@ static int pca953x_irq_setup(struct pca9 - IRQF_ONESHOT | IRQF_SHARED, dev_name(dev), - chip); - if (ret) -- return dev_err_probe(dev, client->irq, "failed to request irq\n"); -+ return dev_err_probe(dev, ret, "failed to request irq\n"); - - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpio/gpio-pxa.c BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpio-pxa.c ---- BPI-Router-Linux-kernel/drivers/gpio/gpio-pxa.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpio-pxa.c 2025-10-22 13:53:56.435169527 -0400 -@@ -497,8 +497,6 @@ static void pxa_mask_muxed_gpio(struct i - gfer = readl_relaxed(base + GFER_OFFSET) & ~GPIO_bit(gpio); - writel_relaxed(grer, base + GRER_OFFSET); - writel_relaxed(gfer, base + GFER_OFFSET); -- -- gpiochip_disable_irq(&pchip->chip, gpio); - } - - static int pxa_gpio_set_wake(struct irq_data *d, unsigned int on) -@@ -518,21 +516,17 @@ static void pxa_unmask_muxed_gpio(struct - unsigned int gpio = irqd_to_hwirq(d); - struct pxa_gpio_bank *c = gpio_to_pxabank(&pchip->chip, gpio); - -- gpiochip_enable_irq(&pchip->chip, gpio); -- - c->irq_mask |= GPIO_bit(gpio); - update_edge_detect(c); - } - --static const struct irq_chip pxa_muxed_gpio_chip = { -+static struct irq_chip pxa_muxed_gpio_chip = { - .name = "GPIO", - .irq_ack = pxa_ack_muxed_gpio, - .irq_mask = pxa_mask_muxed_gpio, - .irq_unmask = pxa_unmask_muxed_gpio, - .irq_set_type = pxa_gpio_irq_type, - .irq_set_wake = pxa_gpio_set_wake, -- .flags = IRQCHIP_IMMUTABLE, -- GPIOCHIP_IRQ_RESOURCE_HELPERS, - }; - - static int pxa_gpio_nums(struct platform_device *pdev) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpio/gpio-regmap.c BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpio-regmap.c ---- BPI-Router-Linux-kernel/drivers/gpio/gpio-regmap.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpio-regmap.c 2025-10-22 13:53:56.435169527 -0400 -@@ -274,7 +274,7 @@ struct gpio_regmap *gpio_regmap_register - if (!chip->ngpio) { - ret = gpiochip_get_ngpios(chip, chip->parent); - if (ret) -- return ERR_PTR(ret); -+ goto err_free_gpio; - } - - /* if not set, assume there is only one register */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpio/gpio-spacemit-k1.c BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpio-spacemit-k1.c ---- BPI-Router-Linux-kernel/drivers/gpio/gpio-spacemit-k1.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpio-spacemit-k1.c 2025-10-22 13:53:56.435169527 -0400 -@@ -278,6 +278,7 @@ static const struct of_device_id spacemi - { .compatible = "spacemit,k1-gpio" }, - { /* sentinel */ } - }; -+MODULE_DEVICE_TABLE(of, spacemit_gpio_dt_ids); - - static struct platform_driver spacemit_gpio_driver = { - .probe = spacemit_gpio_probe, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpio/gpio-tps65912.c BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpio-tps65912.c ---- BPI-Router-Linux-kernel/drivers/gpio/gpio-tps65912.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpio-tps65912.c 2025-10-22 13:53:56.435169527 -0400 -@@ -49,10 +49,13 @@ static int tps65912_gpio_direction_outpu - unsigned offset, int value) - { - struct tps65912_gpio *gpio = gpiochip_get_data(gc); -+ int ret; - - /* Set the initial value */ -- regmap_update_bits(gpio->tps->regmap, TPS65912_GPIO1 + offset, -- GPIO_SET_MASK, value ? GPIO_SET_MASK : 0); -+ ret = regmap_update_bits(gpio->tps->regmap, TPS65912_GPIO1 + offset, -+ GPIO_SET_MASK, value ? GPIO_SET_MASK : 0); -+ if (ret) -+ return ret; - - return regmap_update_bits(gpio->tps->regmap, TPS65912_GPIO1 + offset, - GPIO_CFG_MASK, GPIO_CFG_MASK); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpio/gpio-virtio.c BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpio-virtio.c ---- BPI-Router-Linux-kernel/drivers/gpio/gpio-virtio.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpio-virtio.c 2025-10-22 13:53:56.435169527 -0400 -@@ -526,7 +526,6 @@ static const char **virtio_gpio_get_name - - static int virtio_gpio_probe(struct virtio_device *vdev) - { -- struct virtio_gpio_config config; - struct device *dev = &vdev->dev; - struct virtio_gpio *vgpio; - struct irq_chip *gpio_irq_chip; -@@ -539,9 +538,11 @@ static int virtio_gpio_probe(struct virt - return -ENOMEM; - - /* Read configuration */ -- virtio_cread_bytes(vdev, 0, &config, sizeof(config)); -- gpio_names_size = le32_to_cpu(config.gpio_names_size); -- ngpio = le16_to_cpu(config.ngpio); -+ gpio_names_size = -+ virtio_cread32(vdev, offsetof(struct virtio_gpio_config, -+ gpio_names_size)); -+ ngpio = virtio_cread16(vdev, offsetof(struct virtio_gpio_config, -+ ngpio)); - if (!ngpio) { - dev_err(dev, "Number of GPIOs can't be zero\n"); - return -EINVAL; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpio/gpio-wcd934x.c BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpio-wcd934x.c ---- BPI-Router-Linux-kernel/drivers/gpio/gpio-wcd934x.c 2025-10-22 13:53:23.187329259 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpio/gpio-wcd934x.c 2025-10-22 13:53:56.435169527 -0400 -@@ -46,9 +46,12 @@ static int wcd_gpio_direction_output(str - int val) - { - struct wcd_gpio_data *data = gpiochip_get_data(chip); -+ int ret; - -- regmap_update_bits(data->map, WCD_REG_DIR_CTL_OFFSET, -- WCD_PIN_MASK(pin), WCD_PIN_MASK(pin)); -+ ret = regmap_update_bits(data->map, WCD_REG_DIR_CTL_OFFSET, -+ WCD_PIN_MASK(pin), WCD_PIN_MASK(pin)); -+ if (ret) -+ return ret; - - return regmap_update_bits(data->map, WCD_REG_VAL_CTL_OFFSET, - WCD_PIN_MASK(pin), -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/aldebaran.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/aldebaran.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/aldebaran.c 2025-10-22 13:53:23.191329240 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/aldebaran.c 2025-10-22 13:53:56.435169527 -0400 -@@ -71,18 +71,29 @@ aldebaran_get_reset_handler(struct amdgp - return NULL; - } - -+static inline uint32_t aldebaran_get_ip_block_mask(struct amdgpu_device *adev) -+{ -+ uint32_t ip_block_mask = BIT(AMD_IP_BLOCK_TYPE_GFX) | -+ BIT(AMD_IP_BLOCK_TYPE_SDMA); -+ -+ if (adev->aid_mask) -+ ip_block_mask |= BIT(AMD_IP_BLOCK_TYPE_IH); -+ -+ return ip_block_mask; -+} -+ - static int aldebaran_mode2_suspend_ip(struct amdgpu_device *adev) - { -+ uint32_t ip_block_mask = aldebaran_get_ip_block_mask(adev); -+ uint32_t ip_block; - int r, i; - - amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE); - amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE); - - for (i = adev->num_ip_blocks - 1; i >= 0; i--) { -- if (!(adev->ip_blocks[i].version->type == -- AMD_IP_BLOCK_TYPE_GFX || -- adev->ip_blocks[i].version->type == -- AMD_IP_BLOCK_TYPE_SDMA)) -+ ip_block = BIT(adev->ip_blocks[i].version->type); -+ if (!(ip_block_mask & ip_block)) - continue; - - r = amdgpu_ip_block_suspend(&adev->ip_blocks[i]); -@@ -200,8 +211,10 @@ aldebaran_mode2_perform_reset(struct amd - static int aldebaran_mode2_restore_ip(struct amdgpu_device *adev) - { - struct amdgpu_firmware_info *ucode_list[AMDGPU_UCODE_ID_MAXIMUM]; -+ uint32_t ip_block_mask = aldebaran_get_ip_block_mask(adev); - struct amdgpu_firmware_info *ucode; - struct amdgpu_ip_block *cmn_block; -+ struct amdgpu_ip_block *ih_block; - int ucode_count = 0; - int i, r; - -@@ -243,6 +256,18 @@ static int aldebaran_mode2_restore_ip(st - if (r) - return r; - -+ if (ip_block_mask & BIT(AMD_IP_BLOCK_TYPE_IH)) { -+ ih_block = amdgpu_device_ip_get_ip_block(adev, -+ AMD_IP_BLOCK_TYPE_IH); -+ if (unlikely(!ih_block)) { -+ dev_err(adev->dev, "Failed to get IH handle\n"); -+ return -EINVAL; -+ } -+ r = amdgpu_ip_block_resume(ih_block); -+ if (r) -+ return r; -+ } -+ - /* Reinit GFXHUB */ - adev->gfxhub.funcs->init(adev); - r = adev->gfxhub.funcs->gart_enable(adev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c 2025-10-22 13:53:23.191329240 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c 2025-10-22 13:53:56.435169527 -0400 -@@ -320,7 +320,7 @@ static void set_barrier_auto_waitcnt(str - if (!down_read_trylock(&adev->reset_domain->sem)) - return; - -- amdgpu_amdkfd_suspend(adev, false); -+ amdgpu_amdkfd_suspend(adev, true); - - if (suspend_resume_compute_scheduler(adev, true)) - goto out; -@@ -333,7 +333,7 @@ static void set_barrier_auto_waitcnt(str - out: - suspend_resume_compute_scheduler(adev, false); - -- amdgpu_amdkfd_resume(adev, false); -+ amdgpu_amdkfd_resume(adev, true); - - up_read(&adev->reset_domain->sem); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c 2025-10-22 13:53:23.191329240 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c 2025-10-22 13:53:56.435169527 -0400 -@@ -248,18 +248,42 @@ void amdgpu_amdkfd_interrupt(struct amdg - kgd2kfd_interrupt(adev->kfd.dev, ih_ring_entry); - } - --void amdgpu_amdkfd_suspend(struct amdgpu_device *adev, bool run_pm) -+void amdgpu_amdkfd_suspend(struct amdgpu_device *adev, bool suspend_proc) -+{ -+ if (adev->kfd.dev) { -+ if (adev->in_s0ix) -+ kgd2kfd_stop_sched_all_nodes(adev->kfd.dev); -+ else -+ kgd2kfd_suspend(adev->kfd.dev, suspend_proc); -+ } -+} -+ -+int amdgpu_amdkfd_resume(struct amdgpu_device *adev, bool resume_proc) -+{ -+ int r = 0; -+ -+ if (adev->kfd.dev) { -+ if (adev->in_s0ix) -+ r = kgd2kfd_start_sched_all_nodes(adev->kfd.dev); -+ else -+ r = kgd2kfd_resume(adev->kfd.dev, resume_proc); -+ } -+ -+ return r; -+} -+ -+void amdgpu_amdkfd_suspend_process(struct amdgpu_device *adev) - { - if (adev->kfd.dev) -- kgd2kfd_suspend(adev->kfd.dev, run_pm); -+ kgd2kfd_suspend_process(adev->kfd.dev); - } - --int amdgpu_amdkfd_resume(struct amdgpu_device *adev, bool run_pm) -+int amdgpu_amdkfd_resume_process(struct amdgpu_device *adev) - { - int r = 0; - - if (adev->kfd.dev) -- r = kgd2kfd_resume(adev->kfd.dev, run_pm); -+ r = kgd2kfd_resume_process(adev->kfd.dev); - - return r; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c 2025-10-22 13:53:23.191329240 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c 2025-10-22 13:53:56.435169527 -0400 -@@ -561,6 +561,13 @@ static uint32_t read_vmid_from_vmfault_r - return REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS, VMID); - } - -+static uint32_t kgd_hqd_sdma_get_doorbell(struct amdgpu_device *adev, -+ int engine, int queue) -+ -+{ -+ return 0; -+} -+ - const struct kfd2kgd_calls gfx_v7_kfd2kgd = { - .program_sh_mem_settings = kgd_program_sh_mem_settings, - .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping, -@@ -578,4 +585,5 @@ const struct kfd2kgd_calls gfx_v7_kfd2kg - .set_scratch_backing_va = set_scratch_backing_va, - .set_vm_context_page_table_base = set_vm_context_page_table_base, - .read_vmid_from_vmfault_reg = read_vmid_from_vmfault_reg, -+ .hqd_sdma_get_doorbell = kgd_hqd_sdma_get_doorbell, - }; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c 2025-10-22 13:53:23.191329240 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c 2025-10-22 13:53:56.435169527 -0400 -@@ -582,6 +582,13 @@ static void set_vm_context_page_table_ba - lower_32_bits(page_table_base)); - } - -+static uint32_t kgd_hqd_sdma_get_doorbell(struct amdgpu_device *adev, -+ int engine, int queue) -+ -+{ -+ return 0; -+} -+ - const struct kfd2kgd_calls gfx_v8_kfd2kgd = { - .program_sh_mem_settings = kgd_program_sh_mem_settings, - .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping, -@@ -599,4 +606,5 @@ const struct kfd2kgd_calls gfx_v8_kfd2kg - get_atc_vmid_pasid_mapping_info, - .set_scratch_backing_va = set_scratch_backing_va, - .set_vm_context_page_table_base = set_vm_context_page_table_base, -+ .hqd_sdma_get_doorbell = kgd_hqd_sdma_get_doorbell, - }; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c 2025-10-22 13:53:23.191329240 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c 2025-10-22 13:53:56.435169527 -0400 -@@ -213,19 +213,35 @@ int amdgpu_amdkfd_reserve_mem_limit(stru - spin_lock(&kfd_mem_limit.mem_limit_lock); - - if (kfd_mem_limit.system_mem_used + system_mem_needed > -- kfd_mem_limit.max_system_mem_limit) -+ kfd_mem_limit.max_system_mem_limit) { - pr_debug("Set no_system_mem_limit=1 if using shared memory\n"); -+ if (!no_system_mem_limit) { -+ ret = -ENOMEM; -+ goto release; -+ } -+ } - -- if ((kfd_mem_limit.system_mem_used + system_mem_needed > -- kfd_mem_limit.max_system_mem_limit && !no_system_mem_limit) || -- (kfd_mem_limit.ttm_mem_used + ttm_mem_needed > -- kfd_mem_limit.max_ttm_mem_limit) || -- (adev && xcp_id >= 0 && adev->kfd.vram_used[xcp_id] + vram_needed > -- vram_size - reserved_for_pt - reserved_for_ras - atomic64_read(&adev->vram_pin_size))) { -+ if (kfd_mem_limit.ttm_mem_used + ttm_mem_needed > -+ kfd_mem_limit.max_ttm_mem_limit) { - ret = -ENOMEM; - goto release; - } - -+ /*if is_app_apu is false and apu_prefer_gtt is true, it is an APU with -+ * carve out < gtt. In that case, VRAM allocation will go to gtt domain, skip -+ * VRAM check since ttm_mem_limit check already cover this allocation -+ */ -+ -+ if (adev && xcp_id >= 0 && (!adev->apu_prefer_gtt || adev->gmc.is_app_apu)) { -+ uint64_t vram_available = -+ vram_size - reserved_for_pt - reserved_for_ras - -+ atomic64_read(&adev->vram_pin_size); -+ if (adev->kfd.vram_used[xcp_id] + vram_needed > vram_available) { -+ ret = -ENOMEM; -+ goto release; -+ } -+ } -+ - /* Update memory accounting by decreasing available system - * memory, TTM memory and GPU memory as computed above - */ -@@ -1626,11 +1642,15 @@ size_t amdgpu_amdkfd_get_available_memor - uint64_t vram_available, system_mem_available, ttm_mem_available; - - spin_lock(&kfd_mem_limit.mem_limit_lock); -- vram_available = KFD_XCP_MEMORY_SIZE(adev, xcp_id) -- - adev->kfd.vram_used_aligned[xcp_id] -- - atomic64_read(&adev->vram_pin_size) -- - reserved_for_pt -- - reserved_for_ras; -+ if (adev->apu_prefer_gtt && !adev->gmc.is_app_apu) -+ vram_available = KFD_XCP_MEMORY_SIZE(adev, xcp_id) -+ - adev->kfd.vram_used_aligned[xcp_id]; -+ else -+ vram_available = KFD_XCP_MEMORY_SIZE(adev, xcp_id) -+ - adev->kfd.vram_used_aligned[xcp_id] -+ - atomic64_read(&adev->vram_pin_size) -+ - reserved_for_pt -+ - reserved_for_ras; - - if (adev->apu_prefer_gtt) { - system_mem_available = no_system_mem_limit ? -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h 2025-10-22 13:53:23.191329240 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h 2025-10-22 13:53:56.435169527 -0400 -@@ -154,8 +154,10 @@ struct amdkfd_process_info { - int amdgpu_amdkfd_init(void); - void amdgpu_amdkfd_fini(void); - --void amdgpu_amdkfd_suspend(struct amdgpu_device *adev, bool run_pm); --int amdgpu_amdkfd_resume(struct amdgpu_device *adev, bool run_pm); -+void amdgpu_amdkfd_suspend(struct amdgpu_device *adev, bool suspend_proc); -+int amdgpu_amdkfd_resume(struct amdgpu_device *adev, bool resume_proc); -+void amdgpu_amdkfd_suspend_process(struct amdgpu_device *adev); -+int amdgpu_amdkfd_resume_process(struct amdgpu_device *adev); - void amdgpu_amdkfd_interrupt(struct amdgpu_device *adev, - const void *ih_ring_entry); - void amdgpu_amdkfd_device_probe(struct amdgpu_device *adev); -@@ -411,8 +413,10 @@ struct kfd_dev *kgd2kfd_probe(struct amd - bool kgd2kfd_device_init(struct kfd_dev *kfd, - const struct kgd2kfd_shared_resources *gpu_resources); - void kgd2kfd_device_exit(struct kfd_dev *kfd); --void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm); --int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm); -+void kgd2kfd_suspend(struct kfd_dev *kfd, bool suspend_proc); -+int kgd2kfd_resume(struct kfd_dev *kfd, bool resume_proc); -+void kgd2kfd_suspend_process(struct kfd_dev *kfd); -+int kgd2kfd_resume_process(struct kfd_dev *kfd); - int kgd2kfd_pre_reset(struct kfd_dev *kfd, - struct amdgpu_reset_context *reset_context); - int kgd2kfd_post_reset(struct kfd_dev *kfd); -@@ -422,7 +426,9 @@ void kgd2kfd_smi_event_throttle(struct k - int kgd2kfd_check_and_lock_kfd(void); - void kgd2kfd_unlock_kfd(void); - int kgd2kfd_start_sched(struct kfd_dev *kfd, uint32_t node_id); -+int kgd2kfd_start_sched_all_nodes(struct kfd_dev *kfd); - int kgd2kfd_stop_sched(struct kfd_dev *kfd, uint32_t node_id); -+int kgd2kfd_stop_sched_all_nodes(struct kfd_dev *kfd); - bool kgd2kfd_compute_active(struct kfd_dev *kfd, uint32_t node_id); - bool kgd2kfd_vmfault_fast_path(struct amdgpu_device *adev, struct amdgpu_iv_entry *entry, - bool retry_fault); -@@ -454,11 +460,20 @@ static inline void kgd2kfd_device_exit(s - { - } - --static inline void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm) -+static inline void kgd2kfd_suspend(struct kfd_dev *kfd, bool suspend_proc) - { - } - --static inline int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm) -+static inline int kgd2kfd_resume(struct kfd_dev *kfd, bool resume_proc) -+{ -+ return 0; -+} -+ -+static inline void kgd2kfd_suspend_process(struct kfd_dev *kfd) -+{ -+} -+ -+static inline int kgd2kfd_resume_process(struct kfd_dev *kfd) - { - return 0; - } -@@ -503,10 +518,20 @@ static inline int kgd2kfd_start_sched(st - return 0; - } - -+static inline int kgd2kfd_start_sched_all_nodes(struct kfd_dev *kfd) -+{ -+ return 0; -+} -+ - static inline int kgd2kfd_stop_sched(struct kfd_dev *kfd, uint32_t node_id) - { - return 0; - } -+ -+static inline int kgd2kfd_stop_sched_all_nodes(struct kfd_dev *kfd) -+{ -+ return 0; -+} - - static inline bool kgd2kfd_compute_active(struct kfd_dev *kfd, uint32_t node_id) - { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c 2025-10-22 13:53:23.191329240 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_cper.c 2025-10-22 13:53:56.435169527 -0400 -@@ -212,7 +212,7 @@ int amdgpu_cper_entry_fill_bad_page_thre - NONSTD_SEC_OFFSET(hdr->sec_cnt, idx)); - - amdgpu_cper_entry_fill_section_desc(adev, section_desc, true, false, -- CPER_SEV_NUM, RUNTIME, NONSTD_SEC_LEN, -+ CPER_SEV_FATAL, RUNTIME, NONSTD_SEC_LEN, - NONSTD_SEC_OFFSET(hdr->sec_cnt, idx)); - - section->hdr.valid_bits.err_info_cnt = 1; -@@ -326,7 +326,9 @@ int amdgpu_cper_generate_bp_threshold_re - return -ENOMEM; - } - -- amdgpu_cper_entry_fill_hdr(adev, bp_threshold, AMDGPU_CPER_TYPE_BP_THRESHOLD, CPER_SEV_NUM); -+ amdgpu_cper_entry_fill_hdr(adev, bp_threshold, -+ AMDGPU_CPER_TYPE_BP_THRESHOLD, -+ CPER_SEV_FATAL); - ret = amdgpu_cper_entry_fill_bad_page_threshold_section(adev, bp_threshold, 0); - if (ret) - return ret; -@@ -457,7 +459,7 @@ calc: - - void amdgpu_cper_ring_write(struct amdgpu_ring *ring, void *src, int count) - { -- u64 pos, wptr_old, rptr = *ring->rptr_cpu_addr & ring->ptr_mask; -+ u64 pos, wptr_old, rptr; - int rec_cnt_dw = count >> 2; - u32 chunk, ent_sz; - u8 *s = (u8 *)src; -@@ -470,9 +472,11 @@ void amdgpu_cper_ring_write(struct amdgp - return; - } - -+ mutex_lock(&ring->adev->cper.ring_lock); -+ - wptr_old = ring->wptr; -+ rptr = *ring->rptr_cpu_addr & ring->ptr_mask; - -- mutex_lock(&ring->adev->cper.ring_lock); - while (count) { - ent_sz = amdgpu_cper_ring_get_ent_sz(ring, ring->wptr); - chunk = umin(ent_sz, count); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c 2025-10-22 13:53:23.191329240 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c 2025-10-22 13:53:56.435169527 -0400 -@@ -1138,6 +1138,9 @@ static int amdgpu_cs_vm_handling(struct - } - } - -+ if (!amdgpu_vm_ready(vm)) -+ return -EINVAL; -+ - r = amdgpu_vm_clear_freed(adev, vm, NULL); - if (r) - return r; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c 2025-10-22 13:53:23.191329240 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c 2025-10-22 13:53:56.435169527 -0400 -@@ -944,6 +944,7 @@ static void amdgpu_ctx_mgr_entity_fini(s - drm_sched_entity_fini(entity); - } - } -+ kref_put(&ctx->refcount, amdgpu_ctx_fini); - } - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c 2025-10-22 13:53:23.191329240 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c 2025-10-22 13:53:56.435169527 -0400 -@@ -1902,7 +1902,7 @@ no_preempt: - continue; - } - job = to_amdgpu_job(s_job); -- if (preempted && (&job->hw_fence) == fence) -+ if (preempted && (&job->hw_fence.base) == fence) - /* mark the job as preempted */ - job->preemption_status |= AMDGPU_IB_PREEMPTED; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 2025-10-22 13:53:23.191329240 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c 2025-10-22 13:53:56.435169527 -0400 -@@ -2561,9 +2561,6 @@ static int amdgpu_device_parse_gpu_info_ - - adev->firmware.gpu_info_fw = NULL; - -- if (adev->mman.discovery_bin) -- return 0; -- - switch (adev->asic_type) { - default: - return 0; -@@ -2585,6 +2582,8 @@ static int amdgpu_device_parse_gpu_info_ - chip_name = "arcturus"; - break; - case CHIP_NAVI12: -+ if (adev->mman.discovery_bin) -+ return 0; - chip_name = "navi12"; - break; - } -@@ -3235,6 +3234,7 @@ static bool amdgpu_device_check_vram_los - * always assumed to be lost. - */ - switch (amdgpu_asic_reset_method(adev)) { -+ case AMD_RESET_METHOD_LEGACY: - case AMD_RESET_METHOD_LINK: - case AMD_RESET_METHOD_BACO: - case AMD_RESET_METHOD_MODE1: -@@ -3518,7 +3518,7 @@ static int amdgpu_device_ip_fini_early(s - amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE); - amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE); - -- amdgpu_amdkfd_suspend(adev, false); -+ amdgpu_amdkfd_suspend(adev, true); - amdgpu_userq_suspend(adev); - - /* Workaround for ASICs need to disable SMC first */ -@@ -5055,6 +5055,8 @@ int amdgpu_device_suspend(struct drm_dev - adev->in_suspend = true; - - if (amdgpu_sriov_vf(adev)) { -+ if (!adev->in_runpm) -+ amdgpu_amdkfd_suspend_process(adev); - amdgpu_virt_fini_data_exchange(adev); - r = amdgpu_virt_request_full_gpu(adev, false); - if (r) -@@ -5073,10 +5075,8 @@ int amdgpu_device_suspend(struct drm_dev - - amdgpu_device_ip_suspend_phase1(adev); - -- if (!adev->in_s0ix) { -- amdgpu_amdkfd_suspend(adev, adev->in_runpm); -- amdgpu_userq_suspend(adev); -- } -+ amdgpu_amdkfd_suspend(adev, !amdgpu_sriov_vf(adev) && !adev->in_runpm); -+ amdgpu_userq_suspend(adev); - - r = amdgpu_device_evict_resources(adev); - if (r) -@@ -5139,15 +5139,13 @@ int amdgpu_device_resume(struct drm_devi - goto exit; - } - -- if (!adev->in_s0ix) { -- r = amdgpu_amdkfd_resume(adev, adev->in_runpm); -- if (r) -- goto exit; -+ r = amdgpu_amdkfd_resume(adev, !amdgpu_sriov_vf(adev) && !adev->in_runpm); -+ if (r) -+ goto exit; - -- r = amdgpu_userq_resume(adev); -- if (r) -- goto exit; -- } -+ r = amdgpu_userq_resume(adev); -+ if (r) -+ goto exit; - - r = amdgpu_device_ip_late_init(adev); - if (r) -@@ -5159,6 +5157,9 @@ exit: - if (amdgpu_sriov_vf(adev)) { - amdgpu_virt_init_data_exchange(adev); - amdgpu_virt_release_full_gpu(adev, true); -+ -+ if (!r && !adev->in_runpm) -+ r = amdgpu_amdkfd_resume_process(adev); - } - - if (r) -@@ -5193,6 +5194,8 @@ exit: - dev->dev->power.disable_depth--; - #endif - } -+ -+ amdgpu_vram_mgr_clear_reset_blocks(adev); - adev->in_suspend = false; - - if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DEV_D0)) -@@ -6019,16 +6022,12 @@ static int amdgpu_device_health_check(st - return ret; - } - --static int amdgpu_device_halt_activities(struct amdgpu_device *adev, -- struct amdgpu_job *job, -- struct amdgpu_reset_context *reset_context, -- struct list_head *device_list, -- struct amdgpu_hive_info *hive, -- bool need_emergency_restart) -+static int amdgpu_device_recovery_prepare(struct amdgpu_device *adev, -+ struct list_head *device_list, -+ struct amdgpu_hive_info *hive) - { -- struct list_head *device_list_handle = NULL; - struct amdgpu_device *tmp_adev = NULL; -- int i, r = 0; -+ int r; - - /* - * Build list of devices to reset. -@@ -6045,26 +6044,54 @@ static int amdgpu_device_halt_activities - } - if (!list_is_first(&adev->reset_list, device_list)) - list_rotate_to_front(&adev->reset_list, device_list); -- device_list_handle = device_list; - } else { - list_add_tail(&adev->reset_list, device_list); -- device_list_handle = device_list; - } - - if (!amdgpu_sriov_vf(adev) && (!adev->pcie_reset_ctx.occurs_dpc)) { -- r = amdgpu_device_health_check(device_list_handle); -+ r = amdgpu_device_health_check(device_list); - if (r) - return r; - } - -- /* We need to lock reset domain only once both for XGMI and single device */ -- tmp_adev = list_first_entry(device_list_handle, struct amdgpu_device, -- reset_list); -+ return 0; -+} -+ -+static void amdgpu_device_recovery_get_reset_lock(struct amdgpu_device *adev, -+ struct list_head *device_list) -+{ -+ struct amdgpu_device *tmp_adev = NULL; -+ -+ if (list_empty(device_list)) -+ return; -+ tmp_adev = -+ list_first_entry(device_list, struct amdgpu_device, reset_list); - amdgpu_device_lock_reset_domain(tmp_adev->reset_domain); -+} - -- /* block all schedulers and reset given job's ring */ -- list_for_each_entry(tmp_adev, device_list_handle, reset_list) { -+static void amdgpu_device_recovery_put_reset_lock(struct amdgpu_device *adev, -+ struct list_head *device_list) -+{ -+ struct amdgpu_device *tmp_adev = NULL; - -+ if (list_empty(device_list)) -+ return; -+ tmp_adev = -+ list_first_entry(device_list, struct amdgpu_device, reset_list); -+ amdgpu_device_unlock_reset_domain(tmp_adev->reset_domain); -+} -+ -+static int amdgpu_device_halt_activities( -+ struct amdgpu_device *adev, struct amdgpu_job *job, -+ struct amdgpu_reset_context *reset_context, -+ struct list_head *device_list, struct amdgpu_hive_info *hive, -+ bool need_emergency_restart) -+{ -+ struct amdgpu_device *tmp_adev = NULL; -+ int i, r = 0; -+ -+ /* block all schedulers and reset given job's ring */ -+ list_for_each_entry(tmp_adev, device_list, reset_list) { - amdgpu_device_set_mp1_state(tmp_adev); - - /* -@@ -6252,11 +6279,6 @@ static void amdgpu_device_gpu_resume(str - amdgpu_ras_set_error_query_ready(tmp_adev, true); - - } -- -- tmp_adev = list_first_entry(device_list, struct amdgpu_device, -- reset_list); -- amdgpu_device_unlock_reset_domain(tmp_adev->reset_domain); -- - } - - -@@ -6324,10 +6346,16 @@ int amdgpu_device_gpu_recover(struct amd - reset_context->hive = hive; - INIT_LIST_HEAD(&device_list); - -+ if (amdgpu_device_recovery_prepare(adev, &device_list, hive)) -+ goto end_reset; -+ -+ /* We need to lock reset domain only once both for XGMI and single device */ -+ amdgpu_device_recovery_get_reset_lock(adev, &device_list); -+ - r = amdgpu_device_halt_activities(adev, job, reset_context, &device_list, - hive, need_emergency_restart); - if (r) -- goto end_reset; -+ goto reset_unlock; - - if (need_emergency_restart) - goto skip_sched_resume; -@@ -6337,7 +6365,7 @@ int amdgpu_device_gpu_recover(struct amd - * - * job->base holds a reference to parent fence - */ -- if (job && dma_fence_is_signaled(&job->hw_fence)) { -+ if (job && dma_fence_is_signaled(&job->hw_fence.base)) { - job_signaled = true; - dev_info(adev->dev, "Guilty job already signaled, skipping HW reset"); - goto skip_hw_reset; -@@ -6345,13 +6373,15 @@ int amdgpu_device_gpu_recover(struct amd - - r = amdgpu_device_asic_reset(adev, &device_list, reset_context); - if (r) -- goto end_reset; -+ goto reset_unlock; - skip_hw_reset: - r = amdgpu_device_sched_resume(&device_list, reset_context, job_signaled); - if (r) -- goto end_reset; -+ goto reset_unlock; - skip_sched_resume: - amdgpu_device_gpu_resume(adev, &device_list, need_emergency_restart); -+reset_unlock: -+ amdgpu_device_recovery_put_reset_lock(adev, &device_list); - end_reset: - if (hive) { - mutex_unlock(&hive->hive_lock); -@@ -6763,6 +6793,8 @@ pci_ers_result_t amdgpu_pci_error_detect - memset(&reset_context, 0, sizeof(reset_context)); - INIT_LIST_HEAD(&device_list); - -+ amdgpu_device_recovery_prepare(adev, &device_list, hive); -+ amdgpu_device_recovery_get_reset_lock(adev, &device_list); - r = amdgpu_device_halt_activities(adev, NULL, &reset_context, &device_list, - hive, false); - if (hive) { -@@ -6880,8 +6912,8 @@ out: - if (hive) { - list_for_each_entry(tmp_adev, &device_list, reset_list) - amdgpu_device_unset_mp1_state(tmp_adev); -- amdgpu_device_unlock_reset_domain(adev->reset_domain); - } -+ amdgpu_device_recovery_put_reset_lock(adev, &device_list); - } - - if (hive) { -@@ -6927,6 +6959,7 @@ void amdgpu_pci_resume(struct pci_dev *p - - amdgpu_device_sched_resume(&device_list, NULL, NULL); - amdgpu_device_gpu_resume(adev, &device_list, false); -+ amdgpu_device_recovery_put_reset_lock(adev, &device_list); - adev->pcie_reset_ctx.occurs_dpc = false; - - if (hive) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c 2025-10-22 13:53:23.191329240 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c 2025-10-22 13:53:56.435169527 -0400 -@@ -276,7 +276,7 @@ static int amdgpu_discovery_read_binary_ - u32 msg; - - if (!amdgpu_sriov_vf(adev)) { -- /* It can take up to a second for IFWI init to complete on some dGPUs, -+ /* It can take up to two second for IFWI init to complete on some dGPUs, - * but generally it should be in the 60-100ms range. Normally this starts - * as soon as the device gets power so by the time the OS loads this has long - * completed. However, when a card is hotplugged via e.g., USB4, we need to -@@ -284,7 +284,7 @@ static int amdgpu_discovery_read_binary_ - * continue. - */ - -- for (i = 0; i < 1000; i++) { -+ for (i = 0; i < 2000; i++) { - msg = RREG32(mmMP0_SMN_C2PMSG_33); - if (msg & 0x80000000) - break; -@@ -321,10 +321,12 @@ static int amdgpu_discovery_read_binary_ - const struct firmware *fw; - int r; - -- r = request_firmware(&fw, fw_name, adev->dev); -+ r = firmware_request_nowarn(&fw, fw_name, adev->dev); - if (r) { -- dev_err(adev->dev, "can't load firmware \"%s\"\n", -- fw_name); -+ if (amdgpu_discovery == 2) -+ dev_err(adev->dev, "can't load firmware \"%s\"\n", fw_name); -+ else -+ drm_info(&adev->ddev, "Optional firmware \"%s\" was not found\n", fw_name); - return r; - } - -@@ -459,16 +461,12 @@ static int amdgpu_discovery_init(struct - /* Read from file if it is the preferred option */ - fw_name = amdgpu_discovery_get_fw_name(adev); - if (fw_name != NULL) { -- dev_info(adev->dev, "use ip discovery information from file"); -+ drm_dbg(&adev->ddev, "use ip discovery information from file"); - r = amdgpu_discovery_read_binary_from_file(adev, adev->mman.discovery_bin, fw_name); -- -- if (r) { -- dev_err(adev->dev, "failed to read ip discovery binary from file\n"); -- r = -EINVAL; -+ if (r) - goto out; -- } -- - } else { -+ drm_dbg(&adev->ddev, "use ip discovery information from memory"); - r = amdgpu_discovery_read_binary_from_mem( - adev, adev->mman.discovery_bin); - if (r) -@@ -1338,10 +1336,8 @@ static int amdgpu_discovery_reg_base_ini - int r; - - r = amdgpu_discovery_init(adev); -- if (r) { -- DRM_ERROR("amdgpu_discovery_init failed\n"); -+ if (r) - return r; -- } - - wafl_ver = 0; - adev->gfx.xcc_mask = 0; -@@ -2559,38 +2555,11 @@ int amdgpu_discovery_set_ip_blocks(struc - - switch (adev->asic_type) { - case CHIP_VEGA10: -- case CHIP_VEGA12: -- case CHIP_RAVEN: -- case CHIP_VEGA20: -- case CHIP_ARCTURUS: -- case CHIP_ALDEBARAN: -- /* this is not fatal. We have a fallback below -- * if the new firmwares are not present. some of -- * this will be overridden below to keep things -- * consistent with the current behavior. -+ /* This is not fatal. We only need the discovery -+ * binary for sysfs. We don't need it for a -+ * functional system. - */ -- r = amdgpu_discovery_reg_base_init(adev); -- if (!r) { -- amdgpu_discovery_harvest_ip(adev); -- amdgpu_discovery_get_gfx_info(adev); -- amdgpu_discovery_get_mall_info(adev); -- amdgpu_discovery_get_vcn_info(adev); -- } -- break; -- default: -- r = amdgpu_discovery_reg_base_init(adev); -- if (r) -- return -EINVAL; -- -- amdgpu_discovery_harvest_ip(adev); -- amdgpu_discovery_get_gfx_info(adev); -- amdgpu_discovery_get_mall_info(adev); -- amdgpu_discovery_get_vcn_info(adev); -- break; -- } -- -- switch (adev->asic_type) { -- case CHIP_VEGA10: -+ amdgpu_discovery_init(adev); - vega10_reg_base_init(adev); - adev->sdma.num_instances = 2; - adev->gmc.num_umc = 4; -@@ -2613,6 +2582,11 @@ int amdgpu_discovery_set_ip_blocks(struc - adev->ip_versions[DCI_HWIP][0] = IP_VERSION(12, 0, 0); - break; - case CHIP_VEGA12: -+ /* This is not fatal. We only need the discovery -+ * binary for sysfs. We don't need it for a -+ * functional system. -+ */ -+ amdgpu_discovery_init(adev); - vega10_reg_base_init(adev); - adev->sdma.num_instances = 2; - adev->gmc.num_umc = 4; -@@ -2635,6 +2609,11 @@ int amdgpu_discovery_set_ip_blocks(struc - adev->ip_versions[DCI_HWIP][0] = IP_VERSION(12, 0, 1); - break; - case CHIP_RAVEN: -+ /* This is not fatal. We only need the discovery -+ * binary for sysfs. We don't need it for a -+ * functional system. -+ */ -+ amdgpu_discovery_init(adev); - vega10_reg_base_init(adev); - adev->sdma.num_instances = 1; - adev->vcn.num_vcn_inst = 1; -@@ -2676,6 +2655,11 @@ int amdgpu_discovery_set_ip_blocks(struc - } - break; - case CHIP_VEGA20: -+ /* This is not fatal. We only need the discovery -+ * binary for sysfs. We don't need it for a -+ * functional system. -+ */ -+ amdgpu_discovery_init(adev); - vega20_reg_base_init(adev); - adev->sdma.num_instances = 2; - adev->gmc.num_umc = 8; -@@ -2699,6 +2683,11 @@ int amdgpu_discovery_set_ip_blocks(struc - adev->ip_versions[DCI_HWIP][0] = IP_VERSION(12, 1, 0); - break; - case CHIP_ARCTURUS: -+ /* This is not fatal. We only need the discovery -+ * binary for sysfs. We don't need it for a -+ * functional system. -+ */ -+ amdgpu_discovery_init(adev); - arct_reg_base_init(adev); - adev->sdma.num_instances = 8; - adev->vcn.num_vcn_inst = 2; -@@ -2727,6 +2716,11 @@ int amdgpu_discovery_set_ip_blocks(struc - adev->ip_versions[UVD_HWIP][1] = IP_VERSION(2, 5, 0); - break; - case CHIP_ALDEBARAN: -+ /* This is not fatal. We only need the discovery -+ * binary for sysfs. We don't need it for a -+ * functional system. -+ */ -+ amdgpu_discovery_init(adev); - aldebaran_reg_base_init(adev); - adev->sdma.num_instances = 5; - adev->vcn.num_vcn_inst = 2; -@@ -2753,6 +2747,16 @@ int amdgpu_discovery_set_ip_blocks(struc - adev->ip_versions[XGMI_HWIP][0] = IP_VERSION(6, 1, 0); - break; - default: -+ r = amdgpu_discovery_reg_base_init(adev); -+ if (r) { -+ drm_err(&adev->ddev, "discovery failed: %d\n", r); -+ return r; -+ } -+ -+ amdgpu_discovery_harvest_ip(adev); -+ amdgpu_discovery_get_gfx_info(adev); -+ amdgpu_discovery_get_mall_info(adev); -+ amdgpu_discovery_get_vcn_info(adev); - break; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c 2025-10-22 13:53:23.191329240 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c 2025-10-22 13:53:56.435169527 -0400 -@@ -41,22 +41,6 @@ - #include "amdgpu_trace.h" - #include "amdgpu_reset.h" - --/* -- * Fences mark an event in the GPUs pipeline and are used -- * for GPU/CPU synchronization. When the fence is written, -- * it is expected that all buffers associated with that fence -- * are no longer in use by the associated ring on the GPU and -- * that the relevant GPU caches have been flushed. -- */ -- --struct amdgpu_fence { -- struct dma_fence base; -- -- /* RB, DMA, etc. */ -- struct amdgpu_ring *ring; -- ktime_t start_timestamp; --}; -- - static struct kmem_cache *amdgpu_fence_slab; - - int amdgpu_fence_slab_init(void) -@@ -151,12 +135,12 @@ int amdgpu_fence_emit(struct amdgpu_ring - am_fence = kmem_cache_alloc(amdgpu_fence_slab, GFP_ATOMIC); - if (am_fence == NULL) - return -ENOMEM; -- fence = &am_fence->base; -- am_fence->ring = ring; - } else { - /* take use of job-embedded fence */ -- fence = &job->hw_fence; -+ am_fence = &job->hw_fence; - } -+ fence = &am_fence->base; -+ am_fence->ring = ring; - - seq = ++ring->fence_drv.sync_seq; - if (job && job->job_run_counter) { -@@ -718,7 +702,7 @@ void amdgpu_fence_driver_clear_job_fence - * it right here or we won't be able to track them in fence_drv - * and they will remain unsignaled during sa_bo free. - */ -- job = container_of(old, struct amdgpu_job, hw_fence); -+ job = container_of(old, struct amdgpu_job, hw_fence.base); - if (!job->base.s_fence && !dma_fence_is_signaled(old)) - dma_fence_signal(old); - RCU_INIT_POINTER(*ptr, NULL); -@@ -780,7 +764,7 @@ static const char *amdgpu_fence_get_time - - static const char *amdgpu_job_fence_get_timeline_name(struct dma_fence *f) - { -- struct amdgpu_job *job = container_of(f, struct amdgpu_job, hw_fence); -+ struct amdgpu_job *job = container_of(f, struct amdgpu_job, hw_fence.base); - - return (const char *)to_amdgpu_ring(job->base.sched)->name; - } -@@ -810,7 +794,7 @@ static bool amdgpu_fence_enable_signalin - */ - static bool amdgpu_job_fence_enable_signaling(struct dma_fence *f) - { -- struct amdgpu_job *job = container_of(f, struct amdgpu_job, hw_fence); -+ struct amdgpu_job *job = container_of(f, struct amdgpu_job, hw_fence.base); - - if (!timer_pending(&to_amdgpu_ring(job->base.sched)->fence_drv.fallback_timer)) - amdgpu_fence_schedule_fallback(to_amdgpu_ring(job->base.sched)); -@@ -845,7 +829,7 @@ static void amdgpu_job_fence_free(struct - struct dma_fence *f = container_of(rcu, struct dma_fence, rcu); - - /* free job if fence has a parent job */ -- kfree(container_of(f, struct amdgpu_job, hw_fence)); -+ kfree(container_of(f, struct amdgpu_job, hw_fence.base)); - } - - /** -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu.h 2025-10-22 13:53:23.191329240 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu.h 2025-10-22 13:53:56.435169527 -0400 -@@ -886,6 +886,7 @@ struct amdgpu_mqd_prop { - uint64_t csa_addr; - uint64_t fence_address; - bool tmz_queue; -+ bool kernel_queue; - }; - - struct amdgpu_mqd { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c 2025-10-22 13:53:23.195329221 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c 2025-10-22 13:53:56.435169527 -0400 -@@ -91,8 +91,8 @@ static enum drm_gpu_sched_stat amdgpu_jo - struct amdgpu_job *job = to_amdgpu_job(s_job); - struct amdgpu_task_info *ti; - struct amdgpu_device *adev = ring->adev; -- int idx; -- int r; -+ bool set_error = false; -+ int idx, r; - - if (!drm_dev_enter(adev_to_drm(adev), &idx)) { - dev_info(adev->dev, "%s - device unplugged skipping recovery on scheduler:%s", -@@ -136,10 +136,12 @@ static enum drm_gpu_sched_stat amdgpu_jo - } else if (amdgpu_gpu_recovery && ring->funcs->reset) { - bool is_guilty; - -- dev_err(adev->dev, "Starting %s ring reset\n", s_job->sched->name); -- /* stop the scheduler, but don't mess with the -- * bad job yet because if ring reset fails -- * we'll fall back to full GPU reset. -+ dev_err(adev->dev, "Starting %s ring reset\n", -+ s_job->sched->name); -+ -+ /* -+ * Stop the scheduler to prevent anybody else from touching the -+ * ring buffer. - */ - drm_sched_wqueue_stop(&ring->sched); - -@@ -152,26 +154,27 @@ static enum drm_gpu_sched_stat amdgpu_jo - else - is_guilty = true; - -- if (is_guilty) -+ if (is_guilty) { - dma_fence_set_error(&s_job->s_fence->finished, -ETIME); -+ set_error = true; -+ } - - r = amdgpu_ring_reset(ring, job->vmid); - if (!r) { -- if (amdgpu_ring_sched_ready(ring)) -- drm_sched_stop(&ring->sched, s_job); -- if (is_guilty) { -+ if (is_guilty) - atomic_inc(&ring->adev->gpu_reset_counter); -- amdgpu_fence_driver_force_completion(ring); -- } -- if (amdgpu_ring_sched_ready(ring)) -- drm_sched_start(&ring->sched, 0); -- dev_err(adev->dev, "Ring %s reset succeeded\n", ring->sched.name); -- drm_dev_wedged_event(adev_to_drm(adev), DRM_WEDGE_RECOVERY_NONE); -+ drm_sched_wqueue_start(&ring->sched); -+ dev_err(adev->dev, "Ring %s reset succeeded\n", -+ ring->sched.name); -+ drm_dev_wedged_event(adev_to_drm(adev), -+ DRM_WEDGE_RECOVERY_NONE); - goto exit; - } -- dev_err(adev->dev, "Ring %s reset failure\n", ring->sched.name); -+ dev_err(adev->dev, "Ring %s reset failed\n", ring->sched.name); - } -- dma_fence_set_error(&s_job->s_fence->finished, -ETIME); -+ -+ if (!set_error) -+ dma_fence_set_error(&s_job->s_fence->finished, -ETIME); - - if (amdgpu_device_should_recover_gpu(ring->adev)) { - struct amdgpu_reset_context reset_context; -@@ -272,8 +275,8 @@ void amdgpu_job_free_resources(struct am - /* Check if any fences where initialized */ - if (job->base.s_fence && job->base.s_fence->finished.ops) - f = &job->base.s_fence->finished; -- else if (job->hw_fence.ops) -- f = &job->hw_fence; -+ else if (job->hw_fence.base.ops) -+ f = &job->hw_fence.base; - else - f = NULL; - -@@ -290,10 +293,10 @@ static void amdgpu_job_free_cb(struct dr - amdgpu_sync_free(&job->explicit_sync); - - /* only put the hw fence if has embedded fence */ -- if (!job->hw_fence.ops) -+ if (!job->hw_fence.base.ops) - kfree(job); - else -- dma_fence_put(&job->hw_fence); -+ dma_fence_put(&job->hw_fence.base); - } - - void amdgpu_job_set_gang_leader(struct amdgpu_job *job, -@@ -322,10 +325,10 @@ void amdgpu_job_free(struct amdgpu_job * - if (job->gang_submit != &job->base.s_fence->scheduled) - dma_fence_put(job->gang_submit); - -- if (!job->hw_fence.ops) -+ if (!job->hw_fence.base.ops) - kfree(job); - else -- dma_fence_put(&job->hw_fence); -+ dma_fence_put(&job->hw_fence.base); - } - - struct dma_fence *amdgpu_job_submit(struct amdgpu_job *job) -@@ -384,13 +387,6 @@ amdgpu_job_prepare_job(struct drm_sched_ - dev_err(ring->adev->dev, "Error getting VM ID (%d)\n", r); - goto error; - } -- /* -- * The VM structure might be released after the VMID is -- * assigned, we had multiple problems with people trying to use -- * the VM pointer so better set it to NULL. -- */ -- if (!fence) -- job->vm = NULL; - return fence; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_job.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_job.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_job.h 2025-10-22 13:53:23.195329221 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_job.h 2025-10-22 13:53:56.435169527 -0400 -@@ -48,7 +48,7 @@ struct amdgpu_job { - struct drm_sched_job base; - struct amdgpu_vm *vm; - struct amdgpu_sync explicit_sync; -- struct dma_fence hw_fence; -+ struct amdgpu_fence hw_fence; - struct dma_fence *gang_submit; - uint32_t preamble_status; - uint32_t preemption_status; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c 2025-10-22 13:53:23.195329221 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c 2025-10-22 13:53:56.439169508 -0400 -@@ -447,7 +447,7 @@ static int psp_sw_init(struct amdgpu_ip_ - psp->cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); - if (!psp->cmd) { - dev_err(adev->dev, "Failed to allocate memory to command buffer!\n"); -- ret = -ENOMEM; -+ return -ENOMEM; - } - - adev->psp.xgmi_context.supports_extended_data = -@@ -3522,8 +3522,12 @@ int psp_init_sos_microcode(struct psp_co - uint8_t *ucode_array_start_addr; - int err = 0; - -- err = amdgpu_ucode_request(adev, &adev->psp.sos_fw, AMDGPU_UCODE_REQUIRED, -- "amdgpu/%s_sos.bin", chip_name); -+ if (amdgpu_is_kicker_fw(adev)) -+ err = amdgpu_ucode_request(adev, &adev->psp.sos_fw, AMDGPU_UCODE_REQUIRED, -+ "amdgpu/%s_sos_kicker.bin", chip_name); -+ else -+ err = amdgpu_ucode_request(adev, &adev->psp.sos_fw, AMDGPU_UCODE_REQUIRED, -+ "amdgpu/%s_sos.bin", chip_name); - if (err) - goto out; - -@@ -3799,8 +3803,12 @@ int psp_init_ta_microcode(struct psp_con - struct amdgpu_device *adev = psp->adev; - int err; - -- err = amdgpu_ucode_request(adev, &adev->psp.ta_fw, AMDGPU_UCODE_REQUIRED, -- "amdgpu/%s_ta.bin", chip_name); -+ if (amdgpu_is_kicker_fw(adev)) -+ err = amdgpu_ucode_request(adev, &adev->psp.ta_fw, AMDGPU_UCODE_REQUIRED, -+ "amdgpu/%s_ta_kicker.bin", chip_name); -+ else -+ err = amdgpu_ucode_request(adev, &adev->psp.ta_fw, AMDGPU_UCODE_REQUIRED, -+ "amdgpu/%s_ta.bin", chip_name); - if (err) - return err; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c 2025-10-22 13:53:23.195329221 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c 2025-10-22 13:53:56.439169508 -0400 -@@ -476,6 +476,8 @@ int amdgpu_ras_eeprom_reset_table(struct - - control->ras_num_recs = 0; - control->ras_num_bad_pages = 0; -+ control->ras_num_mca_recs = 0; -+ control->ras_num_pa_recs = 0; - control->ras_fri = 0; - - amdgpu_dpm_send_hbm_bad_pages_num(adev, control->ras_num_bad_pages); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c 2025-10-22 13:53:23.195329221 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c 2025-10-22 13:53:56.439169508 -0400 -@@ -389,8 +389,6 @@ void amdgpu_ring_fini(struct amdgpu_ring - dma_fence_put(ring->vmid_wait); - ring->vmid_wait = NULL; - ring->me = 0; -- -- ring->adev->rings[ring->idx] = NULL; - } - - /** -@@ -427,6 +425,7 @@ bool amdgpu_ring_soft_recovery(struct am - { - unsigned long flags; - ktime_t deadline; -+ bool ret; - - if (unlikely(ring->adev->debug_disable_soft_recovery)) - return false; -@@ -441,12 +440,16 @@ bool amdgpu_ring_soft_recovery(struct am - dma_fence_set_error(fence, -ENODATA); - spin_unlock_irqrestore(fence->lock, flags); - -- atomic_inc(&ring->adev->gpu_reset_counter); - while (!dma_fence_is_signaled(fence) && - ktime_to_ns(ktime_sub(deadline, ktime_get())) > 0) - ring->funcs->soft_recovery(ring, vmid); - -- return dma_fence_is_signaled(fence); -+ ret = dma_fence_is_signaled(fence); -+ /* increment the counter only if soft reset worked */ -+ if (ret) -+ atomic_inc(&ring->adev->gpu_reset_counter); -+ -+ return ret; - } - - /* -@@ -682,6 +685,7 @@ static void amdgpu_ring_to_mqd_prop(stru - prop->eop_gpu_addr = ring->eop_gpu_addr; - prop->use_doorbell = ring->use_doorbell; - prop->doorbell_index = ring->doorbell_index; -+ prop->kernel_queue = true; - - /* map_queues packet doesn't need activate the queue, - * so only kiq need set this field. -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h 2025-10-22 13:53:23.195329221 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h 2025-10-22 13:53:56.439169508 -0400 -@@ -127,6 +127,22 @@ struct amdgpu_fence_driver { - struct dma_fence **fences; - }; - -+/* -+ * Fences mark an event in the GPUs pipeline and are used -+ * for GPU/CPU synchronization. When the fence is written, -+ * it is expected that all buffers associated with that fence -+ * are no longer in use by the associated ring on the GPU and -+ * that the relevant GPU caches have been flushed. -+ */ -+ -+struct amdgpu_fence { -+ struct dma_fence base; -+ -+ /* RB, DMA, etc. */ -+ struct amdgpu_ring *ring; -+ ktime_t start_timestamp; -+}; -+ - extern const struct drm_sched_backend_ops amdgpu_sched_ops; - - void amdgpu_fence_driver_clear_job_fences(struct amdgpu_ring *ring); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c 2025-10-22 13:53:23.195329221 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c 2025-10-22 13:53:56.439169508 -0400 -@@ -540,8 +540,10 @@ static int amdgpu_sdma_soft_reset(struct - case IP_VERSION(4, 4, 2): - case IP_VERSION(4, 4, 4): - case IP_VERSION(4, 4, 5): -- /* For SDMA 4.x, use the existing DPM interface for backward compatibility */ -- r = amdgpu_dpm_reset_sdma(adev, 1 << instance_id); -+ /* For SDMA 4.x, use the existing DPM interface for backward compatibility, -+ * we need to convert the logical instance ID to physical instance ID before reset. -+ */ -+ r = amdgpu_dpm_reset_sdma(adev, 1 << GET_INST(SDMA0, instance_id)); - break; - case IP_VERSION(5, 0, 0): - case IP_VERSION(5, 0, 1): -@@ -568,7 +570,7 @@ static int amdgpu_sdma_soft_reset(struct - /** - * amdgpu_sdma_reset_engine - Reset a specific SDMA engine - * @adev: Pointer to the AMDGPU device -- * @instance_id: ID of the SDMA engine instance to reset -+ * @instance_id: Logical ID of the SDMA engine instance to reset - * - * Returns: 0 on success, or a negative error code on failure. - */ -@@ -595,18 +597,24 @@ int amdgpu_sdma_reset_engine(struct amdg - page_sched_stopped = true; - } - -- if (sdma_instance->funcs->stop_kernel_queue) -+ if (sdma_instance->funcs->stop_kernel_queue) { - sdma_instance->funcs->stop_kernel_queue(gfx_ring); -+ if (adev->sdma.has_page_queue) -+ sdma_instance->funcs->stop_kernel_queue(page_ring); -+ } - - /* Perform the SDMA reset for the specified instance */ - ret = amdgpu_sdma_soft_reset(adev, instance_id); - if (ret) { -- dev_err(adev->dev, "Failed to reset SDMA instance %u\n", instance_id); -+ dev_err(adev->dev, "Failed to reset SDMA logical instance %u\n", instance_id); - goto exit; - } - -- if (sdma_instance->funcs->start_kernel_queue) -+ if (sdma_instance->funcs->start_kernel_queue) { - sdma_instance->funcs->start_kernel_queue(gfx_ring); -+ if (adev->sdma.has_page_queue) -+ sdma_instance->funcs->start_kernel_queue(page_ring); -+ } - - exit: - /* Restart the scheduler's work queue for the GFX and page rings -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h 2025-10-22 13:53:23.195329221 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h 2025-10-22 13:53:56.439169508 -0400 -@@ -154,6 +154,7 @@ int amdgpu_vram_mgr_reserve_range(struct - uint64_t start, uint64_t size); - int amdgpu_vram_mgr_query_page_status(struct amdgpu_vram_mgr *mgr, - uint64_t start); -+void amdgpu_vram_mgr_clear_reset_blocks(struct amdgpu_device *adev); - - bool amdgpu_res_cpu_visible(struct amdgpu_device *adev, - struct ttm_resource *res); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c 2025-10-22 13:53:23.195329221 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c 2025-10-22 13:53:56.439169508 -0400 -@@ -30,6 +30,11 @@ - - #define AMDGPU_UCODE_NAME_MAX (128) - -+static const struct kicker_device kicker_device_list[] = { -+ {0x744B, 0x00}, -+ {0x7551, 0xC8} -+}; -+ - static void amdgpu_ucode_print_common_hdr(const struct common_firmware_header *hdr) - { - DRM_DEBUG("size_bytes: %u\n", le32_to_cpu(hdr->size_bytes)); -@@ -1387,6 +1392,19 @@ static const char *amdgpu_ucode_legacy_n - return NULL; - } - -+bool amdgpu_is_kicker_fw(struct amdgpu_device *adev) -+{ -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(kicker_device_list); i++) { -+ if (adev->pdev->device == kicker_device_list[i].device && -+ adev->pdev->revision == kicker_device_list[i].revision) -+ return true; -+ } -+ -+ return false; -+} -+ - void amdgpu_ucode_ip_version_decode(struct amdgpu_device *adev, int block_type, char *ucode_prefix, int len) - { - int maj, min, rev; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h 2025-10-22 13:53:23.195329221 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h 2025-10-22 13:53:56.439169508 -0400 -@@ -605,6 +605,11 @@ struct amdgpu_firmware { - uint32_t pldm_version; - }; - -+struct kicker_device{ -+ unsigned short device; -+ u8 revision; -+}; -+ - void amdgpu_ucode_print_mc_hdr(const struct common_firmware_header *hdr); - void amdgpu_ucode_print_smc_hdr(const struct common_firmware_header *hdr); - void amdgpu_ucode_print_imu_hdr(const struct common_firmware_header *hdr); -@@ -632,5 +637,6 @@ amdgpu_ucode_get_load_type(struct amdgpu - const char *amdgpu_ucode_name(enum AMDGPU_UCODE_ID ucode_id); - - void amdgpu_ucode_ip_version_decode(struct amdgpu_device *adev, int block_type, char *ucode_prefix, int len); -+bool amdgpu_is_kicker_fw(struct amdgpu_device *adev); - - #endif -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c 2025-10-22 13:53:23.195329221 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c 2025-10-22 13:53:56.439169508 -0400 -@@ -426,6 +426,7 @@ amdgpu_userq_create(struct drm_file *fil - if (index == (uint64_t)-EINVAL) { - drm_file_err(uq_mgr->file, "Failed to get doorbell for queue\n"); - kfree(queue); -+ r = -EINVAL; - goto unlock; - } - -@@ -664,7 +665,7 @@ static void amdgpu_userq_restore_worker( - struct amdgpu_fpriv *fpriv = uq_mgr_to_fpriv(uq_mgr); - int ret; - -- flush_work(&fpriv->evf_mgr.suspend_work.work); -+ flush_delayed_work(&fpriv->evf_mgr.suspend_work); - - mutex_lock(&uq_mgr->userq_mutex); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 2025-10-22 13:53:23.195329221 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 2025-10-22 13:53:56.439169508 -0400 -@@ -654,11 +654,10 @@ int amdgpu_vm_validate(struct amdgpu_dev - * Check if all VM PDs/PTs are ready for updates - * - * Returns: -- * True if VM is not evicting. -+ * True if VM is not evicting and all VM entities are not stopped - */ - bool amdgpu_vm_ready(struct amdgpu_vm *vm) - { -- bool empty; - bool ret; - - amdgpu_vm_eviction_lock(vm); -@@ -666,10 +665,18 @@ bool amdgpu_vm_ready(struct amdgpu_vm *v - amdgpu_vm_eviction_unlock(vm); - - spin_lock(&vm->status_lock); -- empty = list_empty(&vm->evicted); -+ ret &= list_empty(&vm->evicted); - spin_unlock(&vm->status_lock); - -- return ret && empty; -+ spin_lock(&vm->immediate.lock); -+ ret &= !vm->immediate.stopped; -+ spin_unlock(&vm->immediate.lock); -+ -+ spin_lock(&vm->delayed.lock); -+ ret &= !vm->delayed.stopped; -+ spin_unlock(&vm->delayed.lock); -+ -+ return ret; - } - - /** -@@ -2409,13 +2416,11 @@ void amdgpu_vm_adjust_size(struct amdgpu - */ - long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout) - { -- timeout = dma_resv_wait_timeout(vm->root.bo->tbo.base.resv, -- DMA_RESV_USAGE_BOOKKEEP, -- true, timeout); -+ timeout = drm_sched_entity_flush(&vm->immediate, timeout); - if (timeout <= 0) - return timeout; - -- return dma_fence_wait_timeout(vm->last_unlocked, true, timeout); -+ return drm_sched_entity_flush(&vm->delayed, timeout); - } - - static void amdgpu_vm_destroy_task_info(struct kref *kref) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c 2025-10-22 13:53:23.195329221 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c 2025-10-22 13:53:56.439169508 -0400 -@@ -648,9 +648,8 @@ static void amdgpu_vram_mgr_del(struct t - list_for_each_entry(block, &vres->blocks, link) - vis_usage += amdgpu_vram_mgr_vis_size(adev, block); - -- amdgpu_vram_mgr_do_reserve(man); -- - drm_buddy_free_list(mm, &vres->blocks, vres->flags); -+ amdgpu_vram_mgr_do_reserve(man); - mutex_unlock(&mgr->lock); - - atomic64_sub(vis_usage, &mgr->vis_usage); -@@ -783,6 +782,23 @@ uint64_t amdgpu_vram_mgr_vis_usage(struc - } - - /** -+ * amdgpu_vram_mgr_clear_reset_blocks - reset clear blocks -+ * -+ * @adev: amdgpu device pointer -+ * -+ * Reset the cleared drm buddy blocks. -+ */ -+void amdgpu_vram_mgr_clear_reset_blocks(struct amdgpu_device *adev) -+{ -+ struct amdgpu_vram_mgr *mgr = &adev->mman.vram_mgr; -+ struct drm_buddy *mm = &mgr->mm; -+ -+ mutex_lock(&mgr->lock); -+ drm_buddy_reset_clear(mm, false); -+ mutex_unlock(&mgr->lock); -+} -+ -+/** - * amdgpu_vram_mgr_intersects - test each drm buddy block for intersection - * - * @man: TTM memory type manager -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c 2025-10-22 13:53:23.195329221 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c 2025-10-22 13:53:56.439169508 -0400 -@@ -453,6 +453,7 @@ static int __aqua_vanjaram_get_px_mode_i - uint16_t *nps_modes) - { - struct amdgpu_device *adev = xcp_mgr->adev; -+ uint32_t gc_ver = amdgpu_ip_version(adev, GC_HWIP, 0); - - if (!num_xcp || !nps_modes || !(xcp_mgr->supp_xcp_modes & BIT(px_mode))) - return -EINVAL; -@@ -476,12 +477,14 @@ static int __aqua_vanjaram_get_px_mode_i - *num_xcp = 4; - *nps_modes = BIT(AMDGPU_NPS1_PARTITION_MODE) | - BIT(AMDGPU_NPS4_PARTITION_MODE); -+ if (gc_ver == IP_VERSION(9, 5, 0)) -+ *nps_modes |= BIT(AMDGPU_NPS2_PARTITION_MODE); - break; - case AMDGPU_CPX_PARTITION_MODE: - *num_xcp = NUM_XCC(adev->gfx.xcc_mask); - *nps_modes = BIT(AMDGPU_NPS1_PARTITION_MODE) | - BIT(AMDGPU_NPS4_PARTITION_MODE); -- if (amdgpu_sriov_vf(adev)) -+ if (gc_ver == IP_VERSION(9, 5, 0)) - *nps_modes |= BIT(AMDGPU_NPS2_PARTITION_MODE); - break; - default: -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c 2025-10-22 13:53:23.195329221 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c 2025-10-22 13:53:56.439169508 -0400 -@@ -1462,17 +1462,12 @@ static int dce_v10_0_audio_init(struct a - - static void dce_v10_0_audio_fini(struct amdgpu_device *adev) - { -- int i; -- - if (!amdgpu_audio) - return; - - if (!adev->mode_info.audio.enabled) - return; - -- for (i = 0; i < adev->mode_info.audio.num_pins; i++) -- dce_v10_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false); -- - adev->mode_info.audio.enabled = false; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c 2025-10-22 13:53:23.195329221 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c 2025-10-22 13:53:56.439169508 -0400 -@@ -1511,17 +1511,12 @@ static int dce_v11_0_audio_init(struct a - - static void dce_v11_0_audio_fini(struct amdgpu_device *adev) - { -- int i; -- - if (!amdgpu_audio) - return; - - if (!adev->mode_info.audio.enabled) - return; - -- for (i = 0; i < adev->mode_info.audio.num_pins; i++) -- dce_v11_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false); -- - adev->mode_info.audio.enabled = false; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c 2025-10-22 13:53:23.195329221 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c 2025-10-22 13:53:56.439169508 -0400 -@@ -1451,17 +1451,12 @@ static int dce_v6_0_audio_init(struct am - - static void dce_v6_0_audio_fini(struct amdgpu_device *adev) - { -- int i; -- - if (!amdgpu_audio) - return; - - if (!adev->mode_info.audio.enabled) - return; - -- for (i = 0; i < adev->mode_info.audio.num_pins; i++) -- dce_v6_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false); -- - adev->mode_info.audio.enabled = false; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c 2025-10-22 13:53:23.199329201 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c 2025-10-22 13:53:56.439169508 -0400 -@@ -1443,17 +1443,12 @@ static int dce_v8_0_audio_init(struct am - - static void dce_v8_0_audio_fini(struct amdgpu_device *adev) - { -- int i; -- - if (!amdgpu_audio) - return; - - if (!adev->mode_info.audio.enabled) - return; - -- for (i = 0; i < adev->mode_info.audio.num_pins; i++) -- dce_v8_0_audio_enable(adev, &adev->mode_info.audio.pin[i], false); -- - adev->mode_info.audio.enabled = false; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c 2025-10-22 13:53:23.199329201 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c 2025-10-22 13:53:56.439169508 -0400 -@@ -9540,7 +9540,7 @@ static int gfx_v10_0_reset_kgq(struct am - - spin_lock_irqsave(&kiq->ring_lock, flags); - -- if (amdgpu_ring_alloc(kiq_ring, 5 + 7 + 7 + kiq->pmf->map_queues_size)) { -+ if (amdgpu_ring_alloc(kiq_ring, 5 + 7 + 7)) { - spin_unlock_irqrestore(&kiq->ring_lock, flags); - return -ENOMEM; - } -@@ -9560,12 +9560,9 @@ static int gfx_v10_0_reset_kgq(struct am - 0, 1, 0x20); - gfx_v10_0_ring_emit_reg_wait(kiq_ring, - SOC15_REG_OFFSET(GC, 0, mmCP_VMID_RESET), 0, 0xffffffff); -- kiq->pmf->kiq_map_queues(kiq_ring, ring); - amdgpu_ring_commit(kiq_ring); -- -- spin_unlock_irqrestore(&kiq->ring_lock, flags); -- - r = amdgpu_ring_test_ring(kiq_ring); -+ spin_unlock_irqrestore(&kiq->ring_lock, flags); - if (r) - return r; - -@@ -9575,7 +9572,24 @@ static int gfx_v10_0_reset_kgq(struct am - return r; - } - -- return amdgpu_ring_test_ring(ring); -+ spin_lock_irqsave(&kiq->ring_lock, flags); -+ -+ if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->map_queues_size)) { -+ spin_unlock_irqrestore(&kiq->ring_lock, flags); -+ return -ENOMEM; -+ } -+ kiq->pmf->kiq_map_queues(kiq_ring, ring); -+ amdgpu_ring_commit(kiq_ring); -+ r = amdgpu_ring_test_ring(kiq_ring); -+ spin_unlock_irqrestore(&kiq->ring_lock, flags); -+ if (r) -+ return r; -+ -+ r = amdgpu_ring_test_ring(ring); -+ if (r) -+ return r; -+ amdgpu_fence_driver_force_completion(ring); -+ return 0; - } - - static int gfx_v10_0_reset_kcq(struct amdgpu_ring *ring, -@@ -9603,9 +9617,8 @@ static int gfx_v10_0_reset_kcq(struct am - kiq->pmf->kiq_unmap_queues(kiq_ring, ring, RESET_QUEUES, - 0, 0); - amdgpu_ring_commit(kiq_ring); -- spin_unlock_irqrestore(&kiq->ring_lock, flags); -- - r = amdgpu_ring_test_ring(kiq_ring); -+ spin_unlock_irqrestore(&kiq->ring_lock, flags); - if (r) - return r; - -@@ -9641,13 +9654,16 @@ static int gfx_v10_0_reset_kcq(struct am - } - kiq->pmf->kiq_map_queues(kiq_ring, ring); - amdgpu_ring_commit(kiq_ring); -- spin_unlock_irqrestore(&kiq->ring_lock, flags); -- - r = amdgpu_ring_test_ring(kiq_ring); -+ spin_unlock_irqrestore(&kiq->ring_lock, flags); - if (r) - return r; - -- return amdgpu_ring_test_ring(ring); -+ r = amdgpu_ring_test_ring(ring); -+ if (r) -+ return r; -+ amdgpu_fence_driver_force_completion(ring); -+ return 0; - } - - static void gfx_v10_ip_print(struct amdgpu_ip_block *ip_block, struct drm_printer *p) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c 2025-10-22 13:53:23.199329201 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c 2025-10-22 13:53:56.443169488 -0400 -@@ -85,6 +85,7 @@ MODULE_FIRMWARE("amdgpu/gc_11_0_0_pfp.bi - MODULE_FIRMWARE("amdgpu/gc_11_0_0_me.bin"); - MODULE_FIRMWARE("amdgpu/gc_11_0_0_mec.bin"); - MODULE_FIRMWARE("amdgpu/gc_11_0_0_rlc.bin"); -+MODULE_FIRMWARE("amdgpu/gc_11_0_0_rlc_kicker.bin"); - MODULE_FIRMWARE("amdgpu/gc_11_0_0_rlc_1.bin"); - MODULE_FIRMWARE("amdgpu/gc_11_0_0_toc.bin"); - MODULE_FIRMWARE("amdgpu/gc_11_0_1_pfp.bin"); -@@ -759,6 +760,10 @@ static int gfx_v11_0_init_microcode(stru - err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, - AMDGPU_UCODE_REQUIRED, - "amdgpu/gc_11_0_0_rlc_1.bin"); -+ else if (amdgpu_is_kicker_fw(adev)) -+ err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, -+ AMDGPU_UCODE_REQUIRED, -+ "amdgpu/%s_rlc_kicker.bin", ucode_prefix); - else - err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, - AMDGPU_UCODE_REQUIRED, -@@ -1607,9 +1612,9 @@ static int gfx_v11_0_sw_init(struct amdg - case IP_VERSION(11, 0, 2): - case IP_VERSION(11, 0, 3): - if (!adev->gfx.disable_uq && -- adev->gfx.me_fw_version >= 2390 && -- adev->gfx.pfp_fw_version >= 2530 && -- adev->gfx.mec_fw_version >= 2600 && -+ adev->gfx.me_fw_version >= 2420 && -+ adev->gfx.pfp_fw_version >= 2580 && -+ adev->gfx.mec_fw_version >= 2650 && - adev->mes.fw_version[0] >= 120) { - adev->userq_funcs[AMDGPU_HW_IP_GFX] = &userq_mes_funcs; - adev->userq_funcs[AMDGPU_HW_IP_COMPUTE] = &userq_mes_funcs; -@@ -1649,6 +1654,21 @@ static int gfx_v11_0_sw_init(struct amdg - } - } - break; -+ case IP_VERSION(11, 0, 1): -+ case IP_VERSION(11, 0, 4): -+ adev->gfx.cleaner_shader_ptr = gfx_11_0_3_cleaner_shader_hex; -+ adev->gfx.cleaner_shader_size = sizeof(gfx_11_0_3_cleaner_shader_hex); -+ if (adev->gfx.pfp_fw_version >= 102 && -+ adev->gfx.mec_fw_version >= 66 && -+ adev->mes.fw_version[0] >= 128) { -+ adev->gfx.enable_cleaner_shader = true; -+ r = amdgpu_gfx_cleaner_shader_sw_init(adev, adev->gfx.cleaner_shader_size); -+ if (r) { -+ adev->gfx.enable_cleaner_shader = false; -+ dev_err(adev->dev, "Failed to initialize cleaner shader\n"); -+ } -+ } -+ break; - case IP_VERSION(11, 5, 0): - case IP_VERSION(11, 5, 1): - adev->gfx.cleaner_shader_ptr = gfx_11_0_3_cleaner_shader_hex; -@@ -4119,6 +4139,8 @@ static int gfx_v11_0_gfx_mqd_init(struct - #endif - if (prop->tmz_queue) - tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, TMZ_MATCH, 1); -+ if (!prop->kernel_queue) -+ tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, RB_NON_PRIV, 1); - mqd->cp_gfx_hqd_cntl = tmp; - - /* set up cp_doorbell_control */ -@@ -4271,8 +4293,10 @@ static int gfx_v11_0_compute_mqd_init(st - tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 1); - tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, TUNNEL_DISPATCH, - prop->allow_tunneling); -- tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1); -- tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, KMD_QUEUE, 1); -+ if (prop->kernel_queue) { -+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1); -+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, KMD_QUEUE, 1); -+ } - if (prop->tmz_queue) - tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, TMZ, 1); - mqd->cp_hqd_pq_control = tmp; -@@ -6835,7 +6859,11 @@ static int gfx_v11_0_reset_kgq(struct am - return r; - } - -- return amdgpu_ring_test_ring(ring); -+ r = amdgpu_ring_test_ring(ring); -+ if (r) -+ return r; -+ amdgpu_fence_driver_force_completion(ring); -+ return 0; - } - - static int gfx_v11_0_reset_compute_pipe(struct amdgpu_ring *ring) -@@ -6995,7 +7023,11 @@ static int gfx_v11_0_reset_kcq(struct am - return r; - } - -- return amdgpu_ring_test_ring(ring); -+ r = amdgpu_ring_test_ring(ring); -+ if (r) -+ return r; -+ amdgpu_fence_driver_force_completion(ring); -+ return 0; - } - - static void gfx_v11_ip_print(struct amdgpu_ip_block *ip_block, struct drm_printer *p) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c 2025-10-22 13:53:23.199329201 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c 2025-10-22 13:53:56.443169488 -0400 -@@ -79,6 +79,7 @@ MODULE_FIRMWARE("amdgpu/gc_12_0_1_pfp.bi - MODULE_FIRMWARE("amdgpu/gc_12_0_1_me.bin"); - MODULE_FIRMWARE("amdgpu/gc_12_0_1_mec.bin"); - MODULE_FIRMWARE("amdgpu/gc_12_0_1_rlc.bin"); -+MODULE_FIRMWARE("amdgpu/gc_12_0_1_rlc_kicker.bin"); - MODULE_FIRMWARE("amdgpu/gc_12_0_1_toc.bin"); - - static const struct amdgpu_hwip_reg_entry gc_reg_list_12_0[] = { -@@ -586,7 +587,7 @@ out: - - static int gfx_v12_0_init_microcode(struct amdgpu_device *adev) - { -- char ucode_prefix[15]; -+ char ucode_prefix[30]; - int err; - const struct rlc_firmware_header_v2_0 *rlc_hdr; - uint16_t version_major; -@@ -613,9 +614,14 @@ static int gfx_v12_0_init_microcode(stru - amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_RS64_ME_P0_STACK); - - if (!amdgpu_sriov_vf(adev)) { -- err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, -- AMDGPU_UCODE_REQUIRED, -- "amdgpu/%s_rlc.bin", ucode_prefix); -+ if (amdgpu_is_kicker_fw(adev)) -+ err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, -+ AMDGPU_UCODE_REQUIRED, -+ "amdgpu/%s_rlc_kicker.bin", ucode_prefix); -+ else -+ err = amdgpu_ucode_request(adev, &adev->gfx.rlc_fw, -+ AMDGPU_UCODE_REQUIRED, -+ "amdgpu/%s_rlc.bin", ucode_prefix); - if (err) - goto out; - rlc_hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data; -@@ -3016,6 +3022,8 @@ static int gfx_v12_0_gfx_mqd_init(struct - #endif - if (prop->tmz_queue) - tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, TMZ_MATCH, 1); -+ if (!prop->kernel_queue) -+ tmp = REG_SET_FIELD(tmp, CP_GFX_HQD_CNTL, RB_NON_PRIV, 1); - mqd->cp_gfx_hqd_cntl = tmp; - - /* set up cp_doorbell_control */ -@@ -3165,8 +3173,10 @@ static int gfx_v12_0_compute_mqd_init(st - (order_base_2(AMDGPU_GPU_PAGE_SIZE / 4) - 1)); - tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, UNORD_DISPATCH, 1); - tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, TUNNEL_DISPATCH, 0); -- tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1); -- tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, KMD_QUEUE, 1); -+ if (prop->kernel_queue) { -+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1); -+ tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, KMD_QUEUE, 1); -+ } - if (prop->tmz_queue) - tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, TMZ, 1); - mqd->cp_hqd_pq_control = tmp; -@@ -5335,7 +5345,11 @@ static int gfx_v12_0_reset_kgq(struct am - return r; - } - -- return amdgpu_ring_test_ring(ring); -+ r = amdgpu_ring_test_ring(ring); -+ if (r) -+ return r; -+ amdgpu_fence_driver_force_completion(ring); -+ return 0; - } - - static int gfx_v12_0_reset_compute_pipe(struct amdgpu_ring *ring) -@@ -5448,7 +5462,11 @@ static int gfx_v12_0_reset_kcq(struct am - return r; - } - -- return amdgpu_ring_test_ring(ring); -+ r = amdgpu_ring_test_ring(ring); -+ if (r) -+ return r; -+ amdgpu_fence_driver_force_completion(ring); -+ return 0; - } - - static void gfx_v12_0_ring_begin_use(struct amdgpu_ring *ring) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c 2025-10-22 13:53:23.199329201 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c 2025-10-22 13:53:56.443169488 -0400 -@@ -4640,6 +4640,7 @@ static int gfx_v8_0_kcq_init_queue(struc - memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct vi_mqd_allocation)); - /* reset ring buffer */ - ring->wptr = 0; -+ atomic64_set((atomic64_t *)ring->wptr_cpu_addr, 0); - amdgpu_ring_clear_ring(ring); - } - return 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c 2025-10-22 13:53:23.199329201 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c 2025-10-22 13:53:56.443169488 -0400 -@@ -2235,6 +2235,25 @@ static int gfx_v9_0_sw_init(struct amdgp - } - - switch (amdgpu_ip_version(adev, GC_HWIP, 0)) { -+ case IP_VERSION(9, 0, 1): -+ case IP_VERSION(9, 2, 1): -+ case IP_VERSION(9, 4, 0): -+ case IP_VERSION(9, 2, 2): -+ case IP_VERSION(9, 1, 0): -+ case IP_VERSION(9, 3, 0): -+ adev->gfx.cleaner_shader_ptr = gfx_9_4_2_cleaner_shader_hex; -+ adev->gfx.cleaner_shader_size = sizeof(gfx_9_4_2_cleaner_shader_hex); -+ if (adev->gfx.me_fw_version >= 167 && -+ adev->gfx.pfp_fw_version >= 196 && -+ adev->gfx.mec_fw_version >= 474) { -+ adev->gfx.enable_cleaner_shader = true; -+ r = amdgpu_gfx_cleaner_shader_sw_init(adev, adev->gfx.cleaner_shader_size); -+ if (r) { -+ adev->gfx.enable_cleaner_shader = false; -+ dev_err(adev->dev, "Failed to initialize cleaner shader\n"); -+ } -+ } -+ break; - case IP_VERSION(9, 4, 2): - adev->gfx.cleaner_shader_ptr = gfx_9_4_2_cleaner_shader_hex; - adev->gfx.cleaner_shader_size = sizeof(gfx_9_4_2_cleaner_shader_hex); -@@ -7261,13 +7280,18 @@ static int gfx_v9_0_reset_kcq(struct amd - } - kiq->pmf->kiq_map_queues(kiq_ring, ring); - amdgpu_ring_commit(kiq_ring); -- spin_unlock_irqrestore(&kiq->ring_lock, flags); - r = amdgpu_ring_test_ring(kiq_ring); -+ spin_unlock_irqrestore(&kiq->ring_lock, flags); - if (r) { - DRM_ERROR("fail to remap queue\n"); - return r; - } -- return amdgpu_ring_test_ring(ring); -+ -+ r = amdgpu_ring_test_ring(ring); -+ if (r) -+ return r; -+ amdgpu_fence_driver_force_completion(ring); -+ return 0; - } - - static void gfx_v9_ip_print(struct amdgpu_ip_block *ip_block, struct drm_printer *p) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c 2025-10-22 13:53:56.443169488 -0400 -@@ -3612,14 +3612,18 @@ pipe_reset: - } - kiq->pmf->kiq_map_queues(kiq_ring, ring); - amdgpu_ring_commit(kiq_ring); -- spin_unlock_irqrestore(&kiq->ring_lock, flags); -- - r = amdgpu_ring_test_ring(kiq_ring); -+ spin_unlock_irqrestore(&kiq->ring_lock, flags); - if (r) { - dev_err(adev->dev, "fail to remap queue\n"); - return r; - } -- return amdgpu_ring_test_ring(ring); -+ -+ r = amdgpu_ring_test_ring(ring); -+ if (r) -+ return r; -+ amdgpu_fence_driver_force_completion(ring); -+ return 0; - } - - enum amdgpu_gfx_cp_ras_mem_id { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/imu_v11_0.c 2025-10-22 13:53:56.443169488 -0400 -@@ -32,6 +32,7 @@ - #include "gc/gc_11_0_0_sh_mask.h" - - MODULE_FIRMWARE("amdgpu/gc_11_0_0_imu.bin"); -+MODULE_FIRMWARE("amdgpu/gc_11_0_0_imu_kicker.bin"); - MODULE_FIRMWARE("amdgpu/gc_11_0_1_imu.bin"); - MODULE_FIRMWARE("amdgpu/gc_11_0_2_imu.bin"); - MODULE_FIRMWARE("amdgpu/gc_11_0_3_imu.bin"); -@@ -51,8 +52,12 @@ static int imu_v11_0_init_microcode(stru - DRM_DEBUG("\n"); - - amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix)); -- err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, AMDGPU_UCODE_REQUIRED, -- "amdgpu/%s_imu.bin", ucode_prefix); -+ if (amdgpu_is_kicker_fw(adev)) -+ err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, AMDGPU_UCODE_REQUIRED, -+ "amdgpu/%s_imu_kicker.bin", ucode_prefix); -+ else -+ err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, AMDGPU_UCODE_REQUIRED, -+ "amdgpu/%s_imu.bin", ucode_prefix); - if (err) - goto out; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/imu_v12_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/imu_v12_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/imu_v12_0.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/imu_v12_0.c 2025-10-22 13:53:56.443169488 -0400 -@@ -34,12 +34,13 @@ - - MODULE_FIRMWARE("amdgpu/gc_12_0_0_imu.bin"); - MODULE_FIRMWARE("amdgpu/gc_12_0_1_imu.bin"); -+MODULE_FIRMWARE("amdgpu/gc_12_0_1_imu_kicker.bin"); - - #define TRANSFER_RAM_MASK 0x001c0000 - - static int imu_v12_0_init_microcode(struct amdgpu_device *adev) - { -- char ucode_prefix[15]; -+ char ucode_prefix[30]; - int err; - const struct imu_firmware_header_v1_0 *imu_hdr; - struct amdgpu_firmware_info *info = NULL; -@@ -47,8 +48,12 @@ static int imu_v12_0_init_microcode(stru - DRM_DEBUG("\n"); - - amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix)); -- err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, AMDGPU_UCODE_REQUIRED, -- "amdgpu/%s_imu.bin", ucode_prefix); -+ if (amdgpu_is_kicker_fw(adev)) -+ err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, AMDGPU_UCODE_REQUIRED, -+ "amdgpu/%s_imu_kicker.bin", ucode_prefix); -+ else -+ err = amdgpu_ucode_request(adev, &adev->gfx.imu_fw, AMDGPU_UCODE_REQUIRED, -+ "amdgpu/%s_imu.bin", ucode_prefix); - if (err) - goto out; - -@@ -362,7 +367,7 @@ static void program_imu_rlc_ram(struct a - static void imu_v12_0_program_rlc_ram(struct amdgpu_device *adev) - { - u32 reg_data, size = 0; -- const u32 *data; -+ const u32 *data = NULL; - int r = -EINVAL; - - WREG32_SOC15(GC, 0, regGFX_IMU_RLC_RAM_INDEX, 0x2); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/isp_v4_1_1.c 2025-10-22 13:53:56.443169488 -0400 -@@ -29,6 +29,8 @@ - #include "amdgpu.h" - #include "isp_v4_1_1.h" - -+MODULE_FIRMWARE("amdgpu/isp_4_1_1.bin"); -+ - static const unsigned int isp_4_1_1_int_srcid[MAX_ISP411_INT_SRC] = { - ISP_4_1__SRCID__ISP_RINGBUFFER_WPT9, - ISP_4_1__SRCID__ISP_RINGBUFFER_WPT10, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c 2025-10-22 13:53:56.443169488 -0400 -@@ -766,9 +766,15 @@ static int jpeg_v2_0_process_interrupt(s - - static int jpeg_v2_0_ring_reset(struct amdgpu_ring *ring, unsigned int vmid) - { -+ int r; -+ - jpeg_v2_0_stop(ring->adev); - jpeg_v2_0_start(ring->adev); -- return amdgpu_ring_test_helper(ring); -+ r = amdgpu_ring_test_helper(ring); -+ if (r) -+ return r; -+ amdgpu_fence_driver_force_completion(ring); -+ return 0; - } - - static const struct amd_ip_funcs jpeg_v2_0_ip_funcs = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c 2025-10-22 13:53:56.443169488 -0400 -@@ -645,9 +645,15 @@ static int jpeg_v2_5_process_interrupt(s - - static int jpeg_v2_5_ring_reset(struct amdgpu_ring *ring, unsigned int vmid) - { -+ int r; -+ - jpeg_v2_5_stop_inst(ring->adev, ring->me); - jpeg_v2_5_start_inst(ring->adev, ring->me); -- return amdgpu_ring_test_helper(ring); -+ r = amdgpu_ring_test_helper(ring); -+ if (r) -+ return r; -+ amdgpu_fence_driver_force_completion(ring); -+ return 0; - } - - static const struct amd_ip_funcs jpeg_v2_5_ip_funcs = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c 2025-10-22 13:53:56.443169488 -0400 -@@ -557,9 +557,15 @@ static int jpeg_v3_0_process_interrupt(s - - static int jpeg_v3_0_ring_reset(struct amdgpu_ring *ring, unsigned int vmid) - { -+ int r; -+ - jpeg_v3_0_stop(ring->adev); - jpeg_v3_0_start(ring->adev); -- return amdgpu_ring_test_helper(ring); -+ r = amdgpu_ring_test_helper(ring); -+ if (r) -+ return r; -+ amdgpu_fence_driver_force_completion(ring); -+ return 0; - } - - static const struct amd_ip_funcs jpeg_v3_0_ip_funcs = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c 2025-10-22 13:53:56.443169488 -0400 -@@ -1145,12 +1145,18 @@ static void jpeg_v4_0_3_core_stall_reset - - static int jpeg_v4_0_3_ring_reset(struct amdgpu_ring *ring, unsigned int vmid) - { -+ int r; -+ - if (amdgpu_sriov_vf(ring->adev)) - return -EOPNOTSUPP; - - jpeg_v4_0_3_core_stall_reset(ring); - jpeg_v4_0_3_start_jrbc(ring); -- return amdgpu_ring_test_helper(ring); -+ r = amdgpu_ring_test_helper(ring); -+ if (r) -+ return r; -+ amdgpu_fence_driver_force_completion(ring); -+ return 0; - } - - static const struct amd_ip_funcs jpeg_v4_0_3_ip_funcs = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c 2025-10-22 13:53:56.443169488 -0400 -@@ -722,12 +722,18 @@ static int jpeg_v4_0_process_interrupt(s - - static int jpeg_v4_0_ring_reset(struct amdgpu_ring *ring, unsigned int vmid) - { -+ int r; -+ - if (amdgpu_sriov_vf(ring->adev)) - return -EINVAL; - - jpeg_v4_0_stop(ring->adev); - jpeg_v4_0_start(ring->adev); -- return amdgpu_ring_test_helper(ring); -+ r = amdgpu_ring_test_helper(ring); -+ if (r) -+ return r; -+ amdgpu_fence_driver_force_completion(ring); -+ return 0; - } - - static const struct amd_ip_funcs jpeg_v4_0_ip_funcs = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c 2025-10-22 13:53:56.443169488 -0400 -@@ -836,12 +836,18 @@ static void jpeg_v5_0_1_core_stall_reset - - static int jpeg_v5_0_1_ring_reset(struct amdgpu_ring *ring, unsigned int vmid) - { -+ int r; -+ - if (amdgpu_sriov_vf(ring->adev)) - return -EOPNOTSUPP; - - jpeg_v5_0_1_core_stall_reset(ring); - jpeg_v5_0_1_init_jrbc(ring); -- return amdgpu_ring_test_helper(ring); -+ r = amdgpu_ring_test_helper(ring); -+ if (r) -+ return r; -+ amdgpu_fence_driver_force_completion(ring); -+ return 0; - } - - static const struct amd_ip_funcs jpeg_v5_0_1_ip_funcs = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c 2025-10-22 13:53:56.443169488 -0400 -@@ -641,8 +641,9 @@ static int mes_v11_0_misc_op(struct amdg - break; - case MES_MISC_OP_CHANGE_CONFIG: - if ((mes->adev->mes.sched_version & AMDGPU_MES_VERSION_MASK) < 0x63) { -- dev_err(mes->adev->dev, "MES FW version must be larger than 0x63 to support limit single process feature.\n"); -- return -EINVAL; -+ dev_warn_once(mes->adev->dev, -+ "MES FW version must be larger than 0x63 to support limit single process feature.\n"); -+ return 0; - } - misc_pkt.opcode = MESAPI_MISC__CHANGE_CONFIG; - misc_pkt.change_config.opcode = -@@ -710,6 +711,12 @@ static int mes_v11_0_set_hw_resources(st - mes_set_hw_res_pkt.enable_reg_active_poll = 1; - mes_set_hw_res_pkt.enable_level_process_quantum_check = 1; - mes_set_hw_res_pkt.oversubscription_timer = 50; -+ if ((mes->adev->mes.sched_version & AMDGPU_MES_VERSION_MASK) >= 0x7f) -+ mes_set_hw_res_pkt.enable_lr_compute_wa = 1; -+ else -+ dev_info_once(mes->adev->dev, -+ "MES FW version must be >= 0x7f to enable LR compute workaround.\n"); -+ - if (amdgpu_mes_log_enable) { - mes_set_hw_res_pkt.enable_mes_event_int_logging = 1; - mes_set_hw_res_pkt.event_intr_history_gpu_mc_ptr = -@@ -1630,10 +1637,12 @@ static int mes_v11_0_hw_init(struct amdg - if (r) - goto failure; - -- r = mes_v11_0_set_hw_resources_1(&adev->mes); -- if (r) { -- DRM_ERROR("failed mes_v11_0_set_hw_resources_1, r=%d\n", r); -- goto failure; -+ if ((adev->mes.sched_version & AMDGPU_MES_VERSION_MASK) >= 0x50) { -+ r = mes_v11_0_set_hw_resources_1(&adev->mes); -+ if (r) { -+ DRM_ERROR("failed mes_v11_0_set_hw_resources_1, r=%d\n", r); -+ goto failure; -+ } - } - - r = mes_v11_0_query_sched_status(&adev->mes); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/mes_v12_0.c 2025-10-22 13:53:56.443169488 -0400 -@@ -738,6 +738,11 @@ static int mes_v12_0_set_hw_resources(st - mes_set_hw_res_pkt.use_different_vmid_compute = 1; - mes_set_hw_res_pkt.enable_reg_active_poll = 1; - mes_set_hw_res_pkt.enable_level_process_quantum_check = 1; -+ if ((mes->adev->mes.sched_version & AMDGPU_MES_VERSION_MASK) >= 0x82) -+ mes_set_hw_res_pkt.enable_lr_compute_wa = 1; -+ else -+ dev_info_once(adev->dev, -+ "MES FW version must be >= 0x82 to enable LR compute workaround.\n"); - - /* - * Keep oversubscribe timer for sdma . When we have unmapped doorbell -@@ -1742,7 +1747,8 @@ static int mes_v12_0_hw_init(struct amdg - if (r) - goto failure; - -- mes_v12_0_set_hw_resources_1(&adev->mes, AMDGPU_MES_SCHED_PIPE); -+ if ((adev->mes.sched_version & AMDGPU_MES_VERSION_MASK) >= 0x4b) -+ mes_v12_0_set_hw_resources_1(&adev->mes, AMDGPU_MES_SCHED_PIPE); - - mes_v12_0_init_aggregated_doorbell(&adev->mes); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c 2025-10-22 13:53:56.443169488 -0400 -@@ -36,40 +36,47 @@ - - static const char *mmhub_client_ids_v3_0_1[][2] = { - [0][0] = "VMC", -+ [1][0] = "ISPXT", -+ [2][0] = "ISPIXT", - [4][0] = "DCEDMC", - [5][0] = "DCEVGA", - [6][0] = "MP0", - [7][0] = "MP1", -- [8][0] = "MPIO", -- [16][0] = "HDP", -- [17][0] = "LSDMA", -- [18][0] = "JPEG", -- [19][0] = "VCNU0", -- [21][0] = "VSCH", -- [22][0] = "VCNU1", -- [23][0] = "VCN1", -- [32+20][0] = "VCN0", -- [2][1] = "DBGUNBIO", -+ [8][0] = "MPM", -+ [12][0] = "ISPTNR", -+ [14][0] = "ISPCRD0", -+ [15][0] = "ISPCRD1", -+ [16][0] = "ISPCRD2", -+ [22][0] = "HDP", -+ [23][0] = "LSDMA", -+ [24][0] = "JPEG", -+ [27][0] = "VSCH", -+ [28][0] = "VCNU", -+ [29][0] = "VCN", -+ [1][1] = "ISPXT", -+ [2][1] = "ISPIXT", - [3][1] = "DCEDWB", - [4][1] = "DCEDMC", - [5][1] = "DCEVGA", - [6][1] = "MP0", - [7][1] = "MP1", -- [8][1] = "MPIO", -- [10][1] = "DBGU0", -- [11][1] = "DBGU1", -- [12][1] = "DBGU2", -- [13][1] = "DBGU3", -- [14][1] = "XDP", -- [15][1] = "OSSSYS", -- [16][1] = "HDP", -- [17][1] = "LSDMA", -- [18][1] = "JPEG", -- [19][1] = "VCNU0", -- [20][1] = "VCN0", -- [21][1] = "VSCH", -- [22][1] = "VCNU1", -- [23][1] = "VCN1", -+ [8][1] = "MPM", -+ [10][1] = "ISPMWR0", -+ [11][1] = "ISPMWR1", -+ [12][1] = "ISPTNR", -+ [13][1] = "ISPSWR", -+ [14][1] = "ISPCWR0", -+ [15][1] = "ISPCWR1", -+ [16][1] = "ISPCWR2", -+ [17][1] = "ISPCWR3", -+ [18][1] = "XDP", -+ [21][1] = "OSSSYS", -+ [22][1] = "HDP", -+ [23][1] = "LSDMA", -+ [24][1] = "JPEG", -+ [27][1] = "VSCH", -+ [28][1] = "VCNU", -+ [29][1] = "VCN", - }; - - static uint32_t mmhub_v3_0_1_get_invalidate_req(unsigned int vmid, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c 2025-10-22 13:53:56.443169488 -0400 -@@ -40,30 +40,129 @@ - - static const char *mmhub_client_ids_v3_3[][2] = { - [0][0] = "VMC", -+ [1][0] = "ISPXT", -+ [2][0] = "ISPIXT", - [4][0] = "DCEDMC", - [6][0] = "MP0", - [7][0] = "MP1", - [8][0] = "MPM", -+ [9][0] = "ISPPDPRD", -+ [10][0] = "ISPCSTATRD", -+ [11][0] = "ISPBYRPRD", -+ [12][0] = "ISPRGBPRD", -+ [13][0] = "ISPMCFPRD", -+ [14][0] = "ISPMCFPRD1", -+ [15][0] = "ISPYUVPRD", -+ [16][0] = "ISPMCSCRD", -+ [17][0] = "ISPGDCRD", -+ [18][0] = "ISPLMERD", -+ [22][0] = "ISPXT1", -+ [23][0] = "ISPIXT1", - [24][0] = "HDP", - [25][0] = "LSDMA", - [26][0] = "JPEG", - [27][0] = "VPE", -+ [28][0] = "VSCH", - [29][0] = "VCNU", - [30][0] = "VCN", -+ [1][1] = "ISPXT", -+ [2][1] = "ISPIXT", - [3][1] = "DCEDWB", - [4][1] = "DCEDMC", -+ [5][1] = "ISPCSISWR", - [6][1] = "MP0", - [7][1] = "MP1", - [8][1] = "MPM", -+ [9][1] = "ISPPDPWR", -+ [10][1] = "ISPCSTATWR", -+ [11][1] = "ISPBYRPWR", -+ [12][1] = "ISPRGBPWR", -+ [13][1] = "ISPMCFPWR", -+ [14][1] = "ISPMWR0", -+ [15][1] = "ISPYUVPWR", -+ [16][1] = "ISPMCSCWR", -+ [17][1] = "ISPGDCWR", -+ [18][1] = "ISPLMEWR", -+ [20][1] = "ISPMWR2", - [21][1] = "OSSSYS", -+ [22][1] = "ISPXT1", -+ [23][1] = "ISPIXT1", - [24][1] = "HDP", - [25][1] = "LSDMA", - [26][1] = "JPEG", - [27][1] = "VPE", -+ [28][1] = "VSCH", - [29][1] = "VCNU", - [30][1] = "VCN", - }; - -+static const char *mmhub_client_ids_v3_3_1[][2] = { -+ [0][0] = "VMC", -+ [4][0] = "DCEDMC", -+ [6][0] = "MP0", -+ [7][0] = "MP1", -+ [8][0] = "MPM", -+ [24][0] = "HDP", -+ [25][0] = "LSDMA", -+ [26][0] = "JPEG0", -+ [27][0] = "VPE0", -+ [28][0] = "VSCH", -+ [29][0] = "VCNU0", -+ [30][0] = "VCN0", -+ [32+1][0] = "ISPXT", -+ [32+2][0] = "ISPIXT", -+ [32+9][0] = "ISPPDPRD", -+ [32+10][0] = "ISPCSTATRD", -+ [32+11][0] = "ISPBYRPRD", -+ [32+12][0] = "ISPRGBPRD", -+ [32+13][0] = "ISPMCFPRD", -+ [32+14][0] = "ISPMCFPRD1", -+ [32+15][0] = "ISPYUVPRD", -+ [32+16][0] = "ISPMCSCRD", -+ [32+17][0] = "ISPGDCRD", -+ [32+18][0] = "ISPLMERD", -+ [32+22][0] = "ISPXT1", -+ [32+23][0] = "ISPIXT1", -+ [32+26][0] = "JPEG1", -+ [32+27][0] = "VPE1", -+ [32+29][0] = "VCNU1", -+ [32+30][0] = "VCN1", -+ [3][1] = "DCEDWB", -+ [4][1] = "DCEDMC", -+ [6][1] = "MP0", -+ [7][1] = "MP1", -+ [8][1] = "MPM", -+ [21][1] = "OSSSYS", -+ [24][1] = "HDP", -+ [25][1] = "LSDMA", -+ [26][1] = "JPEG0", -+ [27][1] = "VPE0", -+ [28][1] = "VSCH", -+ [29][1] = "VCNU0", -+ [30][1] = "VCN0", -+ [32+1][1] = "ISPXT", -+ [32+2][1] = "ISPIXT", -+ [32+5][1] = "ISPCSISWR", -+ [32+9][1] = "ISPPDPWR", -+ [32+10][1] = "ISPCSTATWR", -+ [32+11][1] = "ISPBYRPWR", -+ [32+12][1] = "ISPRGBPWR", -+ [32+13][1] = "ISPMCFPWR", -+ [32+14][1] = "ISPMWR0", -+ [32+15][1] = "ISPYUVPWR", -+ [32+16][1] = "ISPMCSCWR", -+ [32+17][1] = "ISPGDCWR", -+ [32+18][1] = "ISPLMEWR", -+ [32+19][1] = "ISPMWR1", -+ [32+20][1] = "ISPMWR2", -+ [32+22][1] = "ISPXT1", -+ [32+23][1] = "ISPIXT1", -+ [32+26][1] = "JPEG1", -+ [32+27][1] = "VPE1", -+ [32+29][1] = "VCNU1", -+ [32+30][1] = "VCN1", -+}; -+ - static uint32_t mmhub_v3_3_get_invalidate_req(unsigned int vmid, - uint32_t flush_type) - { -@@ -102,12 +201,16 @@ mmhub_v3_3_print_l2_protection_fault_sta - - switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) { - case IP_VERSION(3, 3, 0): -- case IP_VERSION(3, 3, 1): - case IP_VERSION(3, 3, 2): - mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_v3_3) ? - mmhub_client_ids_v3_3[cid][rw] : - cid == 0x140 ? "UMSCH" : NULL; - break; -+ case IP_VERSION(3, 3, 1): -+ mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_v3_3_1) ? -+ mmhub_client_ids_v3_3_1[cid][rw] : -+ cid == 0x140 ? "UMSCH" : NULL; -+ break; - default: - mmhub_cid = NULL; - break; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c 2025-10-22 13:53:56.443169488 -0400 -@@ -37,39 +37,31 @@ - static const char *mmhub_client_ids_v4_1_0[][2] = { - [0][0] = "VMC", - [4][0] = "DCEDMC", -- [5][0] = "DCEVGA", - [6][0] = "MP0", - [7][0] = "MP1", - [8][0] = "MPIO", -- [16][0] = "HDP", -- [17][0] = "LSDMA", -- [18][0] = "JPEG", -- [19][0] = "VCNU0", -- [21][0] = "VSCH", -- [22][0] = "VCNU1", -- [23][0] = "VCN1", -- [32+20][0] = "VCN0", -- [2][1] = "DBGUNBIO", -+ [16][0] = "LSDMA", -+ [17][0] = "JPEG", -+ [19][0] = "VCNU", -+ [22][0] = "VSCH", -+ [23][0] = "HDP", -+ [32+23][0] = "VCNRD", - [3][1] = "DCEDWB", - [4][1] = "DCEDMC", -- [5][1] = "DCEVGA", - [6][1] = "MP0", - [7][1] = "MP1", - [8][1] = "MPIO", - [10][1] = "DBGU0", - [11][1] = "DBGU1", -- [12][1] = "DBGU2", -- [13][1] = "DBGU3", -+ [12][1] = "DBGUNBIO", - [14][1] = "XDP", - [15][1] = "OSSSYS", -- [16][1] = "HDP", -- [17][1] = "LSDMA", -- [18][1] = "JPEG", -- [19][1] = "VCNU0", -- [20][1] = "VCN0", -- [21][1] = "VSCH", -- [22][1] = "VCNU1", -- [23][1] = "VCN1", -+ [16][1] = "LSDMA", -+ [17][1] = "JPEG", -+ [18][1] = "VCNWR", -+ [19][1] = "VCNU", -+ [22][1] = "VSCH", -+ [23][1] = "HDP", - }; - - static uint32_t mmhub_v4_1_0_get_invalidate_req(unsigned int vmid, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c 2025-10-22 13:53:56.443169488 -0400 -@@ -31,9 +31,6 @@ - - #define NPS_MODE_MASK 0x000000FFL - --/* Core 0 Port 0 counter */ --#define smnPCIEP_NAK_COUNTER 0x1A340218 -- - static void nbio_v7_9_remap_hdp_registers(struct amdgpu_device *adev) - { - WREG32_SOC15(NBIO, 0, regBIF_BX0_REMAP_HDP_MEM_FLUSH_CNTL, -@@ -467,22 +464,6 @@ static void nbio_v7_9_init_registers(str - } - } - --static u64 nbio_v7_9_get_pcie_replay_count(struct amdgpu_device *adev) --{ -- u32 val, nak_r, nak_g; -- -- if (adev->flags & AMD_IS_APU) -- return 0; -- -- /* Get the number of NAKs received and generated */ -- val = RREG32_PCIE(smnPCIEP_NAK_COUNTER); -- nak_r = val & 0xFFFF; -- nak_g = val >> 16; -- -- /* Add the total number of NAKs, i.e the number of replays */ -- return (nak_r + nak_g); --} -- - #define MMIO_REG_HOLE_OFFSET 0x1A000 - - static void nbio_v7_9_set_reg_remap(struct amdgpu_device *adev) -@@ -524,7 +505,6 @@ const struct amdgpu_nbio_funcs nbio_v7_9 - .get_memory_partition_mode = nbio_v7_9_get_memory_partition_mode, - .is_nps_switch_requested = nbio_v7_9_is_nps_switch_requested, - .init_registers = nbio_v7_9_init_registers, -- .get_pcie_replay_count = nbio_v7_9_get_pcie_replay_count, - .set_reg_remap = nbio_v7_9_set_reg_remap, - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c 2025-10-22 13:53:56.443169488 -0400 -@@ -42,7 +42,9 @@ MODULE_FIRMWARE("amdgpu/psp_13_0_5_ta.bi - MODULE_FIRMWARE("amdgpu/psp_13_0_8_toc.bin"); - MODULE_FIRMWARE("amdgpu/psp_13_0_8_ta.bin"); - MODULE_FIRMWARE("amdgpu/psp_13_0_0_sos.bin"); -+MODULE_FIRMWARE("amdgpu/psp_13_0_0_sos_kicker.bin"); - MODULE_FIRMWARE("amdgpu/psp_13_0_0_ta.bin"); -+MODULE_FIRMWARE("amdgpu/psp_13_0_0_ta_kicker.bin"); - MODULE_FIRMWARE("amdgpu/psp_13_0_7_sos.bin"); - MODULE_FIRMWARE("amdgpu/psp_13_0_7_ta.bin"); - MODULE_FIRMWARE("amdgpu/psp_13_0_10_sos.bin"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c 2025-10-22 13:53:56.443169488 -0400 -@@ -34,7 +34,9 @@ - MODULE_FIRMWARE("amdgpu/psp_14_0_2_sos.bin"); - MODULE_FIRMWARE("amdgpu/psp_14_0_2_ta.bin"); - MODULE_FIRMWARE("amdgpu/psp_14_0_3_sos.bin"); -+MODULE_FIRMWARE("amdgpu/psp_14_0_3_sos_kicker.bin"); - MODULE_FIRMWARE("amdgpu/psp_14_0_3_ta.bin"); -+MODULE_FIRMWARE("amdgpu/psp_14_0_3_ta_kicker.bin"); - MODULE_FIRMWARE("amdgpu/psp_14_0_5_toc.bin"); - MODULE_FIRMWARE("amdgpu/psp_14_0_5_ta.bin"); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c 2025-10-22 13:53:56.447169469 -0400 -@@ -45,6 +45,7 @@ - #include "amdgpu_ras.h" - - MODULE_FIRMWARE("amdgpu/sdma_4_4_2.bin"); -+MODULE_FIRMWARE("amdgpu/sdma_4_4_4.bin"); - MODULE_FIRMWARE("amdgpu/sdma_4_4_5.bin"); - - static const struct amdgpu_hwip_reg_entry sdma_reg_list_4_4_2[] = { -@@ -490,7 +491,7 @@ static void sdma_v4_4_2_inst_gfx_stop(st - { - struct amdgpu_ring *sdma[AMDGPU_MAX_SDMA_INSTANCES]; - u32 doorbell_offset, doorbell; -- u32 rb_cntl, ib_cntl; -+ u32 rb_cntl, ib_cntl, sdma_cntl; - int i; - - for_each_inst(i, inst_mask) { -@@ -502,6 +503,9 @@ static void sdma_v4_4_2_inst_gfx_stop(st - ib_cntl = RREG32_SDMA(i, regSDMA_GFX_IB_CNTL); - ib_cntl = REG_SET_FIELD(ib_cntl, SDMA_GFX_IB_CNTL, IB_ENABLE, 0); - WREG32_SDMA(i, regSDMA_GFX_IB_CNTL, ib_cntl); -+ sdma_cntl = RREG32_SDMA(i, regSDMA_CNTL); -+ sdma_cntl = REG_SET_FIELD(sdma_cntl, SDMA_CNTL, UTC_L1_ENABLE, 0); -+ WREG32_SDMA(i, regSDMA_CNTL, sdma_cntl); - - if (sdma[i]->use_doorbell) { - doorbell = RREG32_SDMA(i, regSDMA_GFX_DOORBELL); -@@ -995,6 +999,7 @@ static int sdma_v4_4_2_inst_start(struct - /* set utc l1 enable flag always to 1 */ - temp = RREG32_SDMA(i, regSDMA_CNTL); - temp = REG_SET_FIELD(temp, SDMA_CNTL, UTC_L1_ENABLE, 1); -+ WREG32_SDMA(i, regSDMA_CNTL, temp); - - if (amdgpu_ip_version(adev, SDMA0_HWIP, 0) < IP_VERSION(4, 4, 5)) { - /* enable context empty interrupt during initialization */ -@@ -1669,24 +1674,30 @@ static bool sdma_v4_4_2_page_ring_is_gui - - static int sdma_v4_4_2_reset_queue(struct amdgpu_ring *ring, unsigned int vmid) - { -+ bool is_guilty = ring->funcs->is_guilty(ring); - struct amdgpu_device *adev = ring->adev; -- u32 id = GET_INST(SDMA0, ring->me); -+ u32 id = ring->me; - int r; - - if (!(adev->sdma.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE)) - return -EOPNOTSUPP; - -- amdgpu_amdkfd_suspend(adev, false); -+ amdgpu_amdkfd_suspend(adev, true); - r = amdgpu_sdma_reset_engine(adev, id); -- amdgpu_amdkfd_resume(adev, false); -+ amdgpu_amdkfd_resume(adev, true); -+ if (r) -+ return r; - -- return r; -+ if (is_guilty) -+ amdgpu_fence_driver_force_completion(ring); -+ -+ return 0; - } - - static int sdma_v4_4_2_stop_queue(struct amdgpu_ring *ring) - { - struct amdgpu_device *adev = ring->adev; -- u32 instance_id = GET_INST(SDMA0, ring->me); -+ u32 instance_id = ring->me; - u32 inst_mask; - uint64_t rptr; - -@@ -1724,8 +1735,8 @@ static int sdma_v4_4_2_stop_queue(struct - static int sdma_v4_4_2_restore_queue(struct amdgpu_ring *ring) - { - struct amdgpu_device *adev = ring->adev; -- u32 inst_mask; -- int i; -+ u32 inst_mask, tmp_mask; -+ int i, r; - - inst_mask = 1 << ring->me; - udelay(50); -@@ -1742,7 +1753,24 @@ static int sdma_v4_4_2_restore_queue(str - return -ETIMEDOUT; - } - -- return sdma_v4_4_2_inst_start(adev, inst_mask, true); -+ r = sdma_v4_4_2_inst_start(adev, inst_mask, true); -+ if (r) -+ return r; -+ -+ tmp_mask = inst_mask; -+ for_each_inst(i, tmp_mask) { -+ ring = &adev->sdma.instance[i].ring; -+ -+ amdgpu_fence_driver_force_completion(ring); -+ -+ if (adev->sdma.has_page_queue) { -+ struct amdgpu_ring *page = &adev->sdma.instance[i].page; -+ -+ amdgpu_fence_driver_force_completion(page); -+ } -+ } -+ -+ return r; - } - - static int sdma_v4_4_2_set_trap_irq_state(struct amdgpu_device *adev, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c 2025-10-22 13:53:56.447169469 -0400 -@@ -1399,6 +1399,7 @@ static int sdma_v5_0_sw_init(struct amdg - return r; - - for (i = 0; i < adev->sdma.num_instances; i++) { -+ mutex_init(&adev->sdma.instance[i].engine_reset_mutex); - adev->sdma.instance[i].funcs = &sdma_v5_0_sdma_funcs; - ring = &adev->sdma.instance[i].ring; - ring->ring_obj = NULL; -@@ -1542,8 +1543,13 @@ static int sdma_v5_0_reset_queue(struct - { - struct amdgpu_device *adev = ring->adev; - u32 inst_id = ring->me; -+ int r; -+ -+ amdgpu_amdkfd_suspend(adev, true); -+ r = amdgpu_sdma_reset_engine(adev, inst_id); -+ amdgpu_amdkfd_resume(adev, true); - -- return amdgpu_sdma_reset_engine(adev, inst_id); -+ return r; - } - - static int sdma_v5_0_stop_queue(struct amdgpu_ring *ring) -@@ -1610,7 +1616,10 @@ static int sdma_v5_0_restore_queue(struc - - r = sdma_v5_0_gfx_resume_instance(adev, inst_id, true); - amdgpu_gfx_rlc_exit_safe_mode(adev, 0); -- return r; -+ if (r) -+ return r; -+ amdgpu_fence_driver_force_completion(ring); -+ return 0; - } - - static int sdma_v5_0_ring_preempt_ib(struct amdgpu_ring *ring) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c 2025-10-22 13:53:56.447169469 -0400 -@@ -1318,6 +1318,7 @@ static int sdma_v5_2_sw_init(struct amdg - } - - for (i = 0; i < adev->sdma.num_instances; i++) { -+ mutex_init(&adev->sdma.instance[i].engine_reset_mutex); - adev->sdma.instance[i].funcs = &sdma_v5_2_sdma_funcs; - ring = &adev->sdma.instance[i].ring; - ring->ring_obj = NULL; -@@ -1455,8 +1456,13 @@ static int sdma_v5_2_reset_queue(struct - { - struct amdgpu_device *adev = ring->adev; - u32 inst_id = ring->me; -+ int r; -+ -+ amdgpu_amdkfd_suspend(adev, true); -+ r = amdgpu_sdma_reset_engine(adev, inst_id); -+ amdgpu_amdkfd_resume(adev, true); - -- return amdgpu_sdma_reset_engine(adev, inst_id); -+ return r; - } - - static int sdma_v5_2_stop_queue(struct amdgpu_ring *ring) -@@ -1526,7 +1532,10 @@ static int sdma_v5_2_restore_queue(struc - r = sdma_v5_2_gfx_resume_instance(adev, inst_id, true); - - amdgpu_gfx_rlc_exit_safe_mode(adev, 0); -- return r; -+ if (r) -+ return r; -+ amdgpu_fence_driver_force_completion(ring); -+ return 0; - } - - static int sdma_v5_2_ring_preempt_ib(struct amdgpu_ring *ring) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c 2025-10-22 13:53:56.447169469 -0400 -@@ -1374,9 +1374,22 @@ static int sdma_v6_0_sw_init(struct amdg - else - DRM_ERROR("Failed to allocated memory for SDMA IP Dump\n"); - -- /* add firmware version checks here */ -- if (0 && !adev->sdma.disable_uq) -- adev->userq_funcs[AMDGPU_HW_IP_DMA] = &userq_mes_funcs; -+ switch (amdgpu_ip_version(adev, SDMA0_HWIP, 0)) { -+ case IP_VERSION(6, 0, 0): -+ if ((adev->sdma.instance[0].fw_version >= 27) && !adev->sdma.disable_uq) -+ adev->userq_funcs[AMDGPU_HW_IP_DMA] = &userq_mes_funcs; -+ break; -+ case IP_VERSION(6, 0, 2): -+ if ((adev->sdma.instance[0].fw_version >= 23) && !adev->sdma.disable_uq) -+ adev->userq_funcs[AMDGPU_HW_IP_DMA] = &userq_mes_funcs; -+ break; -+ case IP_VERSION(6, 0, 3): -+ if ((adev->sdma.instance[0].fw_version >= 27) && !adev->sdma.disable_uq) -+ adev->userq_funcs[AMDGPU_HW_IP_DMA] = &userq_mes_funcs; -+ break; -+ default: -+ break; -+ } - - r = amdgpu_sdma_sysfs_reset_mask_init(adev); - if (r) -@@ -1559,7 +1572,11 @@ static int sdma_v6_0_reset_queue(struct - if (r) - return r; - -- return sdma_v6_0_gfx_resume_instance(adev, i, true); -+ r = sdma_v6_0_gfx_resume_instance(adev, i, true); -+ if (r) -+ return r; -+ amdgpu_fence_driver_force_completion(ring); -+ return 0; - } - - static int sdma_v6_0_set_trap_irq_state(struct amdgpu_device *adev, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c 2025-10-22 13:53:56.447169469 -0400 -@@ -824,7 +824,11 @@ static int sdma_v7_0_reset_queue(struct - if (r) - return r; - -- return sdma_v7_0_gfx_resume_instance(adev, i, true); -+ r = sdma_v7_0_gfx_resume_instance(adev, i, true); -+ if (r) -+ return r; -+ amdgpu_fence_driver_force_completion(ring); -+ return 0; - } - - /** -@@ -1349,9 +1353,15 @@ static int sdma_v7_0_sw_init(struct amdg - else - DRM_ERROR("Failed to allocated memory for SDMA IP Dump\n"); - -- /* add firmware version checks here */ -- if (0 && !adev->sdma.disable_uq) -- adev->userq_funcs[AMDGPU_HW_IP_DMA] = &userq_mes_funcs; -+ switch (amdgpu_ip_version(adev, SDMA0_HWIP, 0)) { -+ case IP_VERSION(7, 0, 0): -+ case IP_VERSION(7, 0, 1): -+ if ((adev->sdma.instance[0].fw_version >= 7836028) && !adev->sdma.disable_uq) -+ adev->userq_funcs[AMDGPU_HW_IP_DMA] = &userq_mes_funcs; -+ break; -+ default: -+ break; -+ } - - return r; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/soc15.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/soc15.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/soc15.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/soc15.c 2025-10-22 13:53:56.447169469 -0400 -@@ -1218,6 +1218,8 @@ static int soc15_common_early_init(struc - AMD_PG_SUPPORT_JPEG; - /*TODO: need a new external_rev_id for GC 9.4.4? */ - adev->external_rev_id = adev->rev_id + 0x46; -+ if (amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 5, 0)) -+ adev->external_rev_id = adev->rev_id + 0x50; - break; - default: - /* FIXME: not supported yet */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c 2025-10-22 13:53:56.447169469 -0400 -@@ -1875,15 +1875,19 @@ static int vcn_v3_0_limit_sched(struct a - struct amdgpu_job *job) - { - struct drm_gpu_scheduler **scheds; -- -- /* The create msg must be in the first IB submitted */ -- if (atomic_read(&job->base.entity->fence_seq)) -- return -EINVAL; -+ struct dma_fence *fence; - - /* if VCN0 is harvested, we can't support AV1 */ - if (p->adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) - return -EINVAL; - -+ /* wait for all jobs to finish before switching to instance 0 */ -+ fence = amdgpu_ctx_get_fence(p->ctx, job->base.entity, ~0ull); -+ if (fence) { -+ dma_fence_wait(fence, false); -+ dma_fence_put(fence); -+ } -+ - scheds = p->adev->gpu_sched[AMDGPU_HW_IP_VCN_DEC] - [AMDGPU_RING_PRIO_DEFAULT].sched; - drm_sched_entity_modify_sched(job->base.entity, scheds, 1); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c 2025-10-22 13:53:56.447169469 -0400 -@@ -1621,8 +1621,10 @@ static int vcn_v4_0_3_ring_reset(struct - vcn_v4_0_3_hw_init_inst(vinst); - vcn_v4_0_3_start_dpg_mode(vinst, adev->vcn.inst[ring->me].indirect_sram); - r = amdgpu_ring_test_helper(ring); -- -- return r; -+ if (r) -+ return r; -+ amdgpu_fence_driver_force_completion(ring); -+ return 0; - } - - static const struct amdgpu_ring_funcs vcn_v4_0_3_unified_ring_vm_funcs = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c 2025-10-22 13:53:56.447169469 -0400 -@@ -1469,6 +1469,7 @@ static int vcn_v4_0_5_ring_reset(struct - { - struct amdgpu_device *adev = ring->adev; - struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me]; -+ int r; - - if (!(adev->vcn.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE)) - return -EOPNOTSUPP; -@@ -1476,7 +1477,11 @@ static int vcn_v4_0_5_ring_reset(struct - vcn_v4_0_5_stop(vinst); - vcn_v4_0_5_start(vinst); - -- return amdgpu_ring_test_helper(ring); -+ r = amdgpu_ring_test_helper(ring); -+ if (r) -+ return r; -+ amdgpu_fence_driver_force_completion(ring); -+ return 0; - } - - static struct amdgpu_ring_funcs vcn_v4_0_5_unified_ring_vm_funcs = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c 2025-10-22 13:53:56.447169469 -0400 -@@ -1807,15 +1807,19 @@ static int vcn_v4_0_limit_sched(struct a - struct amdgpu_job *job) - { - struct drm_gpu_scheduler **scheds; -- -- /* The create msg must be in the first IB submitted */ -- if (atomic_read(&job->base.entity->fence_seq)) -- return -EINVAL; -+ struct dma_fence *fence; - - /* if VCN0 is harvested, we can't support AV1 */ - if (p->adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) - return -EINVAL; - -+ /* wait for all jobs to finish before switching to instance 0 */ -+ fence = amdgpu_ctx_get_fence(p->ctx, job->base.entity, ~0ull); -+ if (fence) { -+ dma_fence_wait(fence, false); -+ dma_fence_put(fence); -+ } -+ - scheds = p->adev->gpu_sched[AMDGPU_HW_IP_VCN_ENC] - [AMDGPU_RING_PRIO_0].sched; - drm_sched_entity_modify_sched(job->base.entity, scheds, 1); -@@ -1906,22 +1910,16 @@ out: - - #define RADEON_VCN_ENGINE_TYPE_ENCODE (0x00000002) - #define RADEON_VCN_ENGINE_TYPE_DECODE (0x00000003) -- - #define RADEON_VCN_ENGINE_INFO (0x30000001) --#define RADEON_VCN_ENGINE_INFO_MAX_OFFSET 16 -- - #define RENCODE_ENCODE_STANDARD_AV1 2 - #define RENCODE_IB_PARAM_SESSION_INIT 0x00000003 --#define RENCODE_IB_PARAM_SESSION_INIT_MAX_OFFSET 64 - --/* return the offset in ib if id is found, -1 otherwise -- * to speed up the searching we only search upto max_offset -- */ --static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int max_offset) -+/* return the offset in ib if id is found, -1 otherwise */ -+static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int start) - { - int i; - -- for (i = 0; i < ib->length_dw && i < max_offset && ib->ptr[i] >= 8; i += ib->ptr[i]/4) { -+ for (i = start; i < ib->length_dw && ib->ptr[i] >= 8; i += ib->ptr[i] / 4) { - if (ib->ptr[i + 1] == id) - return i; - } -@@ -1936,33 +1934,29 @@ static int vcn_v4_0_ring_patch_cs_in_pla - struct amdgpu_vcn_decode_buffer *decode_buffer; - uint64_t addr; - uint32_t val; -- int idx; -+ int idx = 0, sidx; - - /* The first instance can decode anything */ - if (!ring->me) - return 0; - -- /* RADEON_VCN_ENGINE_INFO is at the top of ib block */ -- idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, -- RADEON_VCN_ENGINE_INFO_MAX_OFFSET); -- if (idx < 0) /* engine info is missing */ -- return 0; -- -- val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */ -- if (val == RADEON_VCN_ENGINE_TYPE_DECODE) { -- decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6]; -- -- if (!(decode_buffer->valid_buf_flag & 0x1)) -- return 0; -- -- addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 | -- decode_buffer->msg_buffer_address_lo; -- return vcn_v4_0_dec_msg(p, job, addr); -- } else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) { -- idx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, -- RENCODE_IB_PARAM_SESSION_INIT_MAX_OFFSET); -- if (idx >= 0 && ib->ptr[idx + 2] == RENCODE_ENCODE_STANDARD_AV1) -- return vcn_v4_0_limit_sched(p, job); -+ while ((idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, idx)) >= 0) { -+ val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */ -+ if (val == RADEON_VCN_ENGINE_TYPE_DECODE) { -+ decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6]; -+ -+ if (!(decode_buffer->valid_buf_flag & 0x1)) -+ return 0; -+ -+ addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 | -+ decode_buffer->msg_buffer_address_lo; -+ return vcn_v4_0_dec_msg(p, job, addr); -+ } else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) { -+ sidx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, idx); -+ if (sidx >= 0 && ib->ptr[sidx + 2] == RENCODE_ENCODE_STANDARD_AV1) -+ return vcn_v4_0_limit_sched(p, job); -+ } -+ idx += ib->ptr[idx] / 4; - } - return 0; - } -@@ -1971,6 +1965,7 @@ static int vcn_v4_0_ring_reset(struct am - { - struct amdgpu_device *adev = ring->adev; - struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me]; -+ int r; - - if (!(adev->vcn.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE)) - return -EOPNOTSUPP; -@@ -1978,7 +1973,11 @@ static int vcn_v4_0_ring_reset(struct am - vcn_v4_0_stop(vinst); - vcn_v4_0_start(vinst); - -- return amdgpu_ring_test_helper(ring); -+ r = amdgpu_ring_test_helper(ring); -+ if (r) -+ return r; -+ amdgpu_fence_driver_force_completion(ring); -+ return 0; - } - - static struct amdgpu_ring_funcs vcn_v4_0_unified_ring_vm_funcs = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c 2025-10-22 13:53:23.203329182 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c 2025-10-22 13:53:56.447169469 -0400 -@@ -1196,6 +1196,7 @@ static int vcn_v5_0_0_ring_reset(struct - { - struct amdgpu_device *adev = ring->adev; - struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me]; -+ int r; - - if (!(adev->vcn.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE)) - return -EOPNOTSUPP; -@@ -1203,7 +1204,11 @@ static int vcn_v5_0_0_ring_reset(struct - vcn_v5_0_0_stop(vinst); - vcn_v5_0_0_start(vinst); - -- return amdgpu_ring_test_helper(ring); -+ r = amdgpu_ring_test_helper(ring); -+ if (r) -+ return r; -+ amdgpu_fence_driver_force_completion(ring); -+ return 0; - } - - static const struct amdgpu_ring_funcs vcn_v5_0_0_unified_ring_vm_funcs = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c 2025-10-22 13:53:23.207329164 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c 2025-10-22 13:53:56.447169469 -0400 -@@ -669,6 +669,9 @@ static int vcn_v5_0_1_start_dpg_mode(str - if (indirect) - amdgpu_vcn_psp_update_sram(adev, inst_idx, AMDGPU_UCODE_ID_VCN0_RAM); - -+ /* resetting ring, fw should not check RB ring */ -+ fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET; -+ - /* Pause dpg */ - vcn_v5_0_1_pause_dpg_mode(vinst, &state); - -@@ -681,7 +684,7 @@ static int vcn_v5_0_1_start_dpg_mode(str - tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE); - tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK); - WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp); -- fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET; -+ - WREG32_SOC15(VCN, vcn_inst, regUVD_RB_RPTR, 0); - WREG32_SOC15(VCN, vcn_inst, regUVD_RB_WPTR, 0); - -@@ -692,6 +695,7 @@ static int vcn_v5_0_1_start_dpg_mode(str - tmp = RREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE); - tmp |= VCN_RB_ENABLE__RB1_EN_MASK; - WREG32_SOC15(VCN, vcn_inst, regVCN_RB_ENABLE, tmp); -+ /* resetting done, fw can check RB ring */ - fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF); - - WREG32_SOC15(VCN, vcn_inst, regVCN_RB1_DB_CTRL, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdkfd/kfd_device.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdkfd/kfd_device.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdkfd/kfd_device.c 2025-10-22 13:53:23.207329164 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdkfd/kfd_device.c 2025-10-22 13:53:56.447169469 -0400 -@@ -971,7 +971,7 @@ int kgd2kfd_pre_reset(struct kfd_dev *kf - kfd_smi_event_update_gpu_reset(node, false, reset_context); - } - -- kgd2kfd_suspend(kfd, false); -+ kgd2kfd_suspend(kfd, true); - - for (i = 0; i < kfd->num_nodes; i++) - kfd_signal_reset_event(kfd->nodes[i]); -@@ -1019,7 +1019,7 @@ bool kfd_is_locked(void) - return (kfd_locked > 0); - } - --void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm) -+void kgd2kfd_suspend(struct kfd_dev *kfd, bool suspend_proc) - { - struct kfd_node *node; - int i; -@@ -1027,14 +1027,8 @@ void kgd2kfd_suspend(struct kfd_dev *kfd - if (!kfd->init_complete) - return; - -- /* for runtime suspend, skip locking kfd */ -- if (!run_pm) { -- mutex_lock(&kfd_processes_mutex); -- /* For first KFD device suspend all the KFD processes */ -- if (++kfd_locked == 1) -- kfd_suspend_all_processes(); -- mutex_unlock(&kfd_processes_mutex); -- } -+ if (suspend_proc) -+ kgd2kfd_suspend_process(kfd); - - for (i = 0; i < kfd->num_nodes; i++) { - node = kfd->nodes[i]; -@@ -1042,7 +1036,7 @@ void kgd2kfd_suspend(struct kfd_dev *kfd - } - } - --int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm) -+int kgd2kfd_resume(struct kfd_dev *kfd, bool resume_proc) - { - int ret, i; - -@@ -1055,14 +1049,36 @@ int kgd2kfd_resume(struct kfd_dev *kfd, - return ret; - } - -- /* for runtime resume, skip unlocking kfd */ -- if (!run_pm) { -- mutex_lock(&kfd_processes_mutex); -- if (--kfd_locked == 0) -- ret = kfd_resume_all_processes(); -- WARN_ONCE(kfd_locked < 0, "KFD suspend / resume ref. error"); -- mutex_unlock(&kfd_processes_mutex); -- } -+ if (resume_proc) -+ ret = kgd2kfd_resume_process(kfd); -+ -+ return ret; -+} -+ -+void kgd2kfd_suspend_process(struct kfd_dev *kfd) -+{ -+ if (!kfd->init_complete) -+ return; -+ -+ mutex_lock(&kfd_processes_mutex); -+ /* For first KFD device suspend all the KFD processes */ -+ if (++kfd_locked == 1) -+ kfd_suspend_all_processes(); -+ mutex_unlock(&kfd_processes_mutex); -+} -+ -+int kgd2kfd_resume_process(struct kfd_dev *kfd) -+{ -+ int ret = 0; -+ -+ if (!kfd->init_complete) -+ return 0; -+ -+ mutex_lock(&kfd_processes_mutex); -+ if (--kfd_locked == 0) -+ ret = kfd_resume_all_processes(); -+ WARN_ONCE(kfd_locked < 0, "KFD suspend / resume ref. error"); -+ mutex_unlock(&kfd_processes_mutex); - - return ret; - } -@@ -1485,6 +1501,25 @@ int kgd2kfd_start_sched(struct kfd_dev * - return ret; - } - -+int kgd2kfd_start_sched_all_nodes(struct kfd_dev *kfd) -+{ -+ struct kfd_node *node; -+ int i, r; -+ -+ if (!kfd->init_complete) -+ return 0; -+ -+ for (i = 0; i < kfd->num_nodes; i++) { -+ node = kfd->nodes[i]; -+ r = node->dqm->ops.unhalt(node->dqm); -+ if (r) { -+ dev_err(kfd_device, "Error in starting scheduler\n"); -+ return r; -+ } -+ } -+ return 0; -+} -+ - int kgd2kfd_stop_sched(struct kfd_dev *kfd, uint32_t node_id) - { - struct kfd_node *node; -@@ -1502,6 +1537,23 @@ int kgd2kfd_stop_sched(struct kfd_dev *k - return node->dqm->ops.halt(node->dqm); - } - -+int kgd2kfd_stop_sched_all_nodes(struct kfd_dev *kfd) -+{ -+ struct kfd_node *node; -+ int i, r; -+ -+ if (!kfd->init_complete) -+ return 0; -+ -+ for (i = 0; i < kfd->num_nodes; i++) { -+ node = kfd->nodes[i]; -+ r = node->dqm->ops.halt(node->dqm); -+ if (r) -+ return r; -+ } -+ return 0; -+} -+ - bool kgd2kfd_compute_active(struct kfd_dev *kfd, uint32_t node_id) - { - struct kfd_node *node; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c 2025-10-22 13:53:23.207329164 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c 2025-10-22 13:53:56.447169469 -0400 -@@ -2716,7 +2716,7 @@ static void get_queue_checkpoint_info(st - - dqm_lock(dqm); - mqd_mgr = dqm->mqd_mgrs[mqd_type]; -- *mqd_size = mqd_mgr->mqd_size; -+ *mqd_size = mqd_mgr->mqd_size * NUM_XCC(mqd_mgr->dev->xcc_mask); - *ctl_stack_size = 0; - - if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE && mqd_mgr->get_checkpoint_info) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdkfd/kfd_module.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdkfd/kfd_module.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdkfd/kfd_module.c 2025-10-22 13:53:23.207329164 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdkfd/kfd_module.c 2025-10-22 13:53:56.447169469 -0400 -@@ -78,8 +78,8 @@ err_ioctl: - static void kfd_exit(void) - { - kfd_cleanup_processes(); -- kfd_debugfs_fini(); - kfd_process_destroy_wq(); -+ kfd_debugfs_fini(); - kfd_procfs_shutdown(); - kfd_topology_shutdown(); - kfd_chardev_exit(); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c 2025-10-22 13:53:23.207329164 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c 2025-10-22 13:53:56.447169469 -0400 -@@ -373,7 +373,7 @@ static void get_checkpoint_info(struct m - { - struct v9_mqd *m = get_mqd(mqd); - -- *ctl_stack_size = m->cp_hqd_cntl_stack_size; -+ *ctl_stack_size = m->cp_hqd_cntl_stack_size * NUM_XCC(mm->dev->xcc_mask); - } - - static void checkpoint_mqd(struct mqd_manager *mm, void *mqd, void *mqd_dst, void *ctl_stack_dst) -@@ -388,6 +388,24 @@ static void checkpoint_mqd(struct mqd_ma - memcpy(ctl_stack_dst, ctl_stack, m->cp_hqd_cntl_stack_size); - } - -+static void checkpoint_mqd_v9_4_3(struct mqd_manager *mm, -+ void *mqd, -+ void *mqd_dst, -+ void *ctl_stack_dst) -+{ -+ struct v9_mqd *m; -+ int xcc; -+ uint64_t size = get_mqd(mqd)->cp_mqd_stride_size; -+ -+ for (xcc = 0; xcc < NUM_XCC(mm->dev->xcc_mask); xcc++) { -+ m = get_mqd(mqd + size * xcc); -+ -+ checkpoint_mqd(mm, m, -+ (uint8_t *)mqd_dst + sizeof(*m) * xcc, -+ (uint8_t *)ctl_stack_dst + m->cp_hqd_cntl_stack_size * xcc); -+ } -+} -+ - static void restore_mqd(struct mqd_manager *mm, void **mqd, - struct kfd_mem_obj *mqd_mem_obj, uint64_t *gart_addr, - struct queue_properties *qp, -@@ -764,13 +782,35 @@ static void restore_mqd_v9_4_3(struct mq - const void *mqd_src, - const void *ctl_stack_src, u32 ctl_stack_size) - { -- restore_mqd(mm, mqd, mqd_mem_obj, gart_addr, qp, mqd_src, ctl_stack_src, ctl_stack_size); -- if (amdgpu_sriov_multi_vf_mode(mm->dev->adev)) { -- struct v9_mqd *m; -+ struct kfd_mem_obj xcc_mqd_mem_obj; -+ u32 mqd_ctl_stack_size; -+ struct v9_mqd *m; -+ u32 num_xcc; -+ int xcc; - -- m = (struct v9_mqd *) mqd_mem_obj->cpu_ptr; -- m->cp_hqd_pq_doorbell_control |= 1 << -- CP_HQD_PQ_DOORBELL_CONTROL__DOORBELL_MODE__SHIFT; -+ uint64_t offset = mm->mqd_stride(mm, qp); -+ -+ mm->dev->dqm->current_logical_xcc_start++; -+ -+ num_xcc = NUM_XCC(mm->dev->xcc_mask); -+ mqd_ctl_stack_size = ctl_stack_size / num_xcc; -+ -+ memset(&xcc_mqd_mem_obj, 0x0, sizeof(struct kfd_mem_obj)); -+ -+ /* Set the MQD pointer and gart address to XCC0 MQD */ -+ *mqd = mqd_mem_obj->cpu_ptr; -+ if (gart_addr) -+ *gart_addr = mqd_mem_obj->gpu_addr; -+ -+ for (xcc = 0; xcc < num_xcc; xcc++) { -+ get_xcc_mqd(mqd_mem_obj, &xcc_mqd_mem_obj, offset * xcc); -+ restore_mqd(mm, (void **)&m, -+ &xcc_mqd_mem_obj, -+ NULL, -+ qp, -+ (uint8_t *)mqd_src + xcc * sizeof(*m), -+ (uint8_t *)ctl_stack_src + xcc * mqd_ctl_stack_size, -+ mqd_ctl_stack_size); - } - } - static int destroy_mqd_v9_4_3(struct mqd_manager *mm, void *mqd, -@@ -906,7 +946,6 @@ struct mqd_manager *mqd_manager_init_v9( - mqd->free_mqd = kfd_free_mqd_cp; - mqd->is_occupied = kfd_is_occupied_cp; - mqd->get_checkpoint_info = get_checkpoint_info; -- mqd->checkpoint_mqd = checkpoint_mqd; - mqd->mqd_size = sizeof(struct v9_mqd); - mqd->mqd_stride = mqd_stride_v9; - #if defined(CONFIG_DEBUG_FS) -@@ -918,16 +957,18 @@ struct mqd_manager *mqd_manager_init_v9( - mqd->init_mqd = init_mqd_v9_4_3; - mqd->load_mqd = load_mqd_v9_4_3; - mqd->update_mqd = update_mqd_v9_4_3; -- mqd->restore_mqd = restore_mqd_v9_4_3; - mqd->destroy_mqd = destroy_mqd_v9_4_3; - mqd->get_wave_state = get_wave_state_v9_4_3; -+ mqd->checkpoint_mqd = checkpoint_mqd_v9_4_3; -+ mqd->restore_mqd = restore_mqd_v9_4_3; - } else { - mqd->init_mqd = init_mqd; - mqd->load_mqd = load_mqd; - mqd->update_mqd = update_mqd; -- mqd->restore_mqd = restore_mqd; - mqd->destroy_mqd = kfd_destroy_mqd_cp; - mqd->get_wave_state = get_wave_state; -+ mqd->checkpoint_mqd = checkpoint_mqd; -+ mqd->restore_mqd = restore_mqd; - } - break; - case KFD_MQD_TYPE_HIQ: -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c 2025-10-22 13:53:23.207329164 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c 2025-10-22 13:53:56.447169469 -0400 -@@ -240,7 +240,7 @@ static int pm_map_queues_v9(struct packe - - packet->bitfields2.engine_sel = - engine_sel__mes_map_queues__compute_vi; -- packet->bitfields2.gws_control_queue = q->gws ? 1 : 0; -+ packet->bitfields2.gws_control_queue = q->properties.is_gws ? 1 : 0; - packet->bitfields2.extended_engine_sel = - extended_engine_sel__mes_map_queues__legacy_engine_sel; - packet->bitfields2.queue_type = -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c 2025-10-22 13:53:23.207329164 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c 2025-10-22 13:53:56.447169469 -0400 -@@ -914,7 +914,10 @@ static int criu_checkpoint_queues_device - - q_data = (struct kfd_criu_queue_priv_data *)q_private_data; - -- /* data stored in this order: priv_data, mqd, ctl_stack */ -+ /* -+ * data stored in this order: -+ * priv_data, mqd[xcc0], mqd[xcc1],..., ctl_stack[xcc0], ctl_stack[xcc1]... -+ */ - q_data->mqd_size = mqd_size; - q_data->ctl_stack_size = ctl_stack_size; - -@@ -963,7 +966,7 @@ int kfd_criu_checkpoint_queues(struct kf - } - - static void set_queue_properties_from_criu(struct queue_properties *qp, -- struct kfd_criu_queue_priv_data *q_data) -+ struct kfd_criu_queue_priv_data *q_data, uint32_t num_xcc) - { - qp->is_interop = false; - qp->queue_percent = q_data->q_percent; -@@ -976,7 +979,11 @@ static void set_queue_properties_from_cr - qp->eop_ring_buffer_size = q_data->eop_ring_buffer_size; - qp->ctx_save_restore_area_address = q_data->ctx_save_restore_area_address; - qp->ctx_save_restore_area_size = q_data->ctx_save_restore_area_size; -- qp->ctl_stack_size = q_data->ctl_stack_size; -+ if (q_data->type == KFD_QUEUE_TYPE_COMPUTE) -+ qp->ctl_stack_size = q_data->ctl_stack_size / num_xcc; -+ else -+ qp->ctl_stack_size = q_data->ctl_stack_size; -+ - qp->type = q_data->type; - qp->format = q_data->format; - } -@@ -1036,12 +1043,15 @@ int kfd_criu_restore_queue(struct kfd_pr - goto exit; - } - -- /* data stored in this order: mqd, ctl_stack */ -+ /* -+ * data stored in this order: -+ * mqd[xcc0], mqd[xcc1],..., ctl_stack[xcc0], ctl_stack[xcc1]... -+ */ - mqd = q_extra_data; - ctl_stack = mqd + q_data->mqd_size; - - memset(&qp, 0, sizeof(qp)); -- set_queue_properties_from_criu(&qp, q_data); -+ set_queue_properties_from_criu(&qp, q_data, NUM_XCC(pdd->dev->adev->gfx.xcc_mask)); - - print_queue_properties(&qp); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdkfd/kfd_svm.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdkfd/kfd_svm.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 2025-10-22 13:53:23.207329164 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdkfd/kfd_svm.c 2025-10-22 13:53:56.447169469 -0400 -@@ -1171,13 +1171,12 @@ svm_range_split_head(struct svm_range *p - } - - static void --svm_range_add_child(struct svm_range *prange, struct mm_struct *mm, -- struct svm_range *pchild, enum svm_work_list_ops op) -+svm_range_add_child(struct svm_range *prange, struct svm_range *pchild, enum svm_work_list_ops op) - { - pr_debug("add child 0x%p [0x%lx 0x%lx] to prange 0x%p child list %d\n", - pchild, pchild->start, pchild->last, prange, op); - -- pchild->work_item.mm = mm; -+ pchild->work_item.mm = NULL; - pchild->work_item.op = op; - list_add_tail(&pchild->child_list, &prange->child_list); - } -@@ -1278,7 +1277,7 @@ svm_range_get_pte_flags(struct kfd_node - mapping_flags |= ext_coherent ? AMDGPU_VM_MTYPE_UC : AMDGPU_VM_MTYPE_NC; - /* system memory accessed by the dGPU */ - } else { -- if (gc_ip_version < IP_VERSION(9, 5, 0)) -+ if (gc_ip_version < IP_VERSION(9, 5, 0) || ext_coherent) - mapping_flags |= AMDGPU_VM_MTYPE_UC; - else - mapping_flags |= AMDGPU_VM_MTYPE_NC; -@@ -2394,15 +2393,17 @@ svm_range_add_list_work(struct svm_range - prange->work_item.op != SVM_OP_UNMAP_RANGE) - prange->work_item.op = op; - } else { -- prange->work_item.op = op; -- -- /* Pairs with mmput in deferred_list_work */ -- mmget(mm); -- prange->work_item.mm = mm; -- list_add_tail(&prange->deferred_list, -- &prange->svms->deferred_range_list); -- pr_debug("add prange 0x%p [0x%lx 0x%lx] to work list op %d\n", -- prange, prange->start, prange->last, op); -+ /* Pairs with mmput in deferred_list_work. -+ * If process is exiting and mm is gone, don't update mmu notifier. -+ */ -+ if (mmget_not_zero(mm)) { -+ prange->work_item.mm = mm; -+ prange->work_item.op = op; -+ list_add_tail(&prange->deferred_list, -+ &prange->svms->deferred_range_list); -+ pr_debug("add prange 0x%p [0x%lx 0x%lx] to work list op %d\n", -+ prange, prange->start, prange->last, op); -+ } - } - spin_unlock(&svms->deferred_list_lock); - } -@@ -2416,8 +2417,7 @@ void schedule_deferred_list_work(struct - } - - static void --svm_range_unmap_split(struct mm_struct *mm, struct svm_range *parent, -- struct svm_range *prange, unsigned long start, -+svm_range_unmap_split(struct svm_range *parent, struct svm_range *prange, unsigned long start, - unsigned long last) - { - struct svm_range *head; -@@ -2438,12 +2438,12 @@ svm_range_unmap_split(struct mm_struct * - svm_range_split(tail, last + 1, tail->last, &head); - - if (head != prange && tail != prange) { -- svm_range_add_child(parent, mm, head, SVM_OP_UNMAP_RANGE); -- svm_range_add_child(parent, mm, tail, SVM_OP_ADD_RANGE); -+ svm_range_add_child(parent, head, SVM_OP_UNMAP_RANGE); -+ svm_range_add_child(parent, tail, SVM_OP_ADD_RANGE); - } else if (tail != prange) { -- svm_range_add_child(parent, mm, tail, SVM_OP_UNMAP_RANGE); -+ svm_range_add_child(parent, tail, SVM_OP_UNMAP_RANGE); - } else if (head != prange) { -- svm_range_add_child(parent, mm, head, SVM_OP_UNMAP_RANGE); -+ svm_range_add_child(parent, head, SVM_OP_UNMAP_RANGE); - } else if (parent != prange) { - prange->work_item.op = SVM_OP_UNMAP_RANGE; - } -@@ -2520,14 +2520,14 @@ svm_range_unmap_from_cpu(struct mm_struc - l = min(last, pchild->last); - if (l >= s) - svm_range_unmap_from_gpus(pchild, s, l, trigger); -- svm_range_unmap_split(mm, prange, pchild, start, last); -+ svm_range_unmap_split(prange, pchild, start, last); - mutex_unlock(&pchild->lock); - } - s = max(start, prange->start); - l = min(last, prange->last); - if (l >= s) - svm_range_unmap_from_gpus(prange, s, l, trigger); -- svm_range_unmap_split(mm, prange, prange, start, last); -+ svm_range_unmap_split(prange, prange, start, last); - - if (unmap_parent) - svm_range_add_list_work(svms, prange, mm, SVM_OP_UNMAP_RANGE); -@@ -2570,8 +2570,6 @@ svm_range_cpu_invalidate_pagetables(stru - - if (range->event == MMU_NOTIFY_RELEASE) - return true; -- if (!mmget_not_zero(mni->mm)) -- return true; - - start = mni->interval_tree.start; - last = mni->interval_tree.last; -@@ -2598,7 +2596,6 @@ svm_range_cpu_invalidate_pagetables(stru - } - - svm_range_unlock(prange); -- mmput(mni->mm); - - return true; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdkfd/kfd_topology.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdkfd/kfd_topology.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/amdkfd/kfd_topology.c 2025-10-22 13:53:23.207329164 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/amdkfd/kfd_topology.c 2025-10-22 13:53:56.447169469 -0400 -@@ -510,6 +510,10 @@ static ssize_t node_show(struct kobject - dev->node_props.capability |= - HSA_CAP_AQL_QUEUE_DOUBLE_MAP; - -+ if (KFD_GC_VERSION(dev->gpu) < IP_VERSION(10, 0, 0) && -+ (dev->gpu->adev->sdma.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE)) -+ dev->node_props.capability2 |= HSA_CAP2_PER_SDMA_QUEUE_RESET_SUPPORTED; -+ - sysfs_show_32bit_prop(buffer, offs, "max_engine_clk_fcompute", - dev->node_props.max_engine_clk_fcompute); - -@@ -1583,7 +1587,8 @@ static int kfd_dev_create_p2p_links(void - break; - if (!dev->gpu || !dev->gpu->adev || - (dev->gpu->kfd->hive_id && -- dev->gpu->kfd->hive_id == new_dev->gpu->kfd->hive_id)) -+ dev->gpu->kfd->hive_id == new_dev->gpu->kfd->hive_id && -+ amdgpu_xgmi_get_is_sharing_enabled(dev->gpu->adev, new_dev->gpu->adev))) - goto next; - - /* check if node(s) is/are peer accessible in one direction or bi-direction */ -@@ -2008,8 +2013,6 @@ static void kfd_topology_set_capabilitie - if (!amdgpu_sriov_vf(dev->gpu->adev)) - dev->node_props.capability |= HSA_CAP_PER_QUEUE_RESET_SUPPORTED; - -- if (dev->gpu->adev->sdma.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE) -- dev->node_props.capability2 |= HSA_CAP2_PER_SDMA_QUEUE_RESET_SUPPORTED; - } else { - dev->node_props.debug_prop |= HSA_DBG_WATCH_ADDR_MASK_LO_BIT_GFX10 | - HSA_DBG_WATCH_ADDR_MASK_HI_BIT; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 2025-10-22 13:53:23.207329164 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 2025-10-22 13:53:56.451169450 -0400 -@@ -2035,6 +2035,8 @@ static int amdgpu_dm_init(struct amdgpu_ - - dc_hardware_init(adev->dm.dc); - -+ adev->dm.restore_backlight = true; -+ - adev->dm.hpd_rx_offload_wq = hpd_rx_irq_create_workqueue(adev); - if (!adev->dm.hpd_rx_offload_wq) { - drm_err(adev_to_drm(adev), "amdgpu: failed to create hpd rx offload workqueue.\n"); -@@ -2910,6 +2912,17 @@ static int dm_oem_i2c_hw_init(struct amd - return 0; - } - -+static void dm_oem_i2c_hw_fini(struct amdgpu_device *adev) -+{ -+ struct amdgpu_display_manager *dm = &adev->dm; -+ -+ if (dm->oem_i2c) { -+ i2c_del_adapter(&dm->oem_i2c->base); -+ kfree(dm->oem_i2c); -+ dm->oem_i2c = NULL; -+ } -+} -+ - /** - * dm_hw_init() - Initialize DC device - * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. -@@ -2960,7 +2973,7 @@ static int dm_hw_fini(struct amdgpu_ip_b - { - struct amdgpu_device *adev = ip_block->adev; - -- kfree(adev->dm.oem_i2c); -+ dm_oem_i2c_hw_fini(adev); - - amdgpu_dm_hpd_fini(adev); - -@@ -3060,19 +3073,68 @@ static void hpd_rx_irq_work_suspend(stru - } - } - --static int dm_prepare_suspend(struct amdgpu_ip_block *ip_block) -+static int dm_cache_state(struct amdgpu_device *adev) - { -- struct amdgpu_device *adev = ip_block->adev; -- -- if (amdgpu_in_reset(adev)) -- return 0; -+ int r; - -- WARN_ON(adev->dm.cached_state); - adev->dm.cached_state = drm_atomic_helper_suspend(adev_to_drm(adev)); -- if (IS_ERR(adev->dm.cached_state)) -- return PTR_ERR(adev->dm.cached_state); -+ if (IS_ERR(adev->dm.cached_state)) { -+ r = PTR_ERR(adev->dm.cached_state); -+ adev->dm.cached_state = NULL; -+ } - -- return 0; -+ return adev->dm.cached_state ? 0 : r; -+} -+ -+static void dm_destroy_cached_state(struct amdgpu_device *adev) -+{ -+ struct amdgpu_display_manager *dm = &adev->dm; -+ struct drm_device *ddev = adev_to_drm(adev); -+ struct dm_plane_state *dm_new_plane_state; -+ struct drm_plane_state *new_plane_state; -+ struct dm_crtc_state *dm_new_crtc_state; -+ struct drm_crtc_state *new_crtc_state; -+ struct drm_plane *plane; -+ struct drm_crtc *crtc; -+ int i; -+ -+ if (!dm->cached_state) -+ return; -+ -+ /* Force mode set in atomic commit */ -+ for_each_new_crtc_in_state(dm->cached_state, crtc, new_crtc_state, i) { -+ new_crtc_state->active_changed = true; -+ dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); -+ reset_freesync_config_for_crtc(dm_new_crtc_state); -+ } -+ -+ /* -+ * atomic_check is expected to create the dc states. We need to release -+ * them here, since they were duplicated as part of the suspend -+ * procedure. -+ */ -+ for_each_new_crtc_in_state(dm->cached_state, crtc, new_crtc_state, i) { -+ dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); -+ if (dm_new_crtc_state->stream) { -+ WARN_ON(kref_read(&dm_new_crtc_state->stream->refcount) > 1); -+ dc_stream_release(dm_new_crtc_state->stream); -+ dm_new_crtc_state->stream = NULL; -+ } -+ dm_new_crtc_state->base.color_mgmt_changed = true; -+ } -+ -+ for_each_new_plane_in_state(dm->cached_state, plane, new_plane_state, i) { -+ dm_new_plane_state = to_dm_plane_state(new_plane_state); -+ if (dm_new_plane_state->dc_state) { -+ WARN_ON(kref_read(&dm_new_plane_state->dc_state->refcount) > 1); -+ dc_plane_state_release(dm_new_plane_state->dc_state); -+ dm_new_plane_state->dc_state = NULL; -+ } -+ } -+ -+ drm_atomic_helper_resume(ddev, dm->cached_state); -+ -+ dm->cached_state = NULL; - } - - static int dm_suspend(struct amdgpu_ip_block *ip_block) -@@ -3106,9 +3168,10 @@ static int dm_suspend(struct amdgpu_ip_b - } - - if (!adev->dm.cached_state) { -- adev->dm.cached_state = drm_atomic_helper_suspend(adev_to_drm(adev)); -- if (IS_ERR(adev->dm.cached_state)) -- return PTR_ERR(adev->dm.cached_state); -+ int r = dm_cache_state(adev); -+ -+ if (r) -+ return r; - } - - s3_handle_hdmi_cec(adev_to_drm(adev), true); -@@ -3295,12 +3358,6 @@ static int dm_resume(struct amdgpu_ip_bl - struct amdgpu_dm_connector *aconnector; - struct drm_connector *connector; - struct drm_connector_list_iter iter; -- struct drm_crtc *crtc; -- struct drm_crtc_state *new_crtc_state; -- struct dm_crtc_state *dm_new_crtc_state; -- struct drm_plane *plane; -- struct drm_plane_state *new_plane_state; -- struct dm_plane_state *dm_new_plane_state; - struct dm_atomic_state *dm_state = to_dm_atomic_state(dm->atomic_obj.state); - enum dc_connection_type new_connection_type = dc_connection_none; - struct dc_state *dc_state; -@@ -3332,13 +3389,16 @@ static int dm_resume(struct amdgpu_ip_bl - link_enc_cfg_copy(adev->dm.dc->current_state, dc_state); - - r = dm_dmub_hw_init(adev); -- if (r) -+ if (r) { - drm_err(adev_to_drm(adev), "DMUB interface failed to initialize: status=%d\n", r); -+ return r; -+ } - - dc_dmub_srv_set_power_state(dm->dc->ctx->dmub_srv, DC_ACPI_CM_POWER_STATE_D0); - dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D0); - - dc_resume(dm->dc); -+ adev->dm.restore_backlight = true; - - amdgpu_dm_irq_resume_early(adev); - -@@ -3457,40 +3517,7 @@ static int dm_resume(struct amdgpu_ip_bl - } - drm_connector_list_iter_end(&iter); - -- /* Force mode set in atomic commit */ -- for_each_new_crtc_in_state(dm->cached_state, crtc, new_crtc_state, i) { -- new_crtc_state->active_changed = true; -- dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); -- reset_freesync_config_for_crtc(dm_new_crtc_state); -- } -- -- /* -- * atomic_check is expected to create the dc states. We need to release -- * them here, since they were duplicated as part of the suspend -- * procedure. -- */ -- for_each_new_crtc_in_state(dm->cached_state, crtc, new_crtc_state, i) { -- dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); -- if (dm_new_crtc_state->stream) { -- WARN_ON(kref_read(&dm_new_crtc_state->stream->refcount) > 1); -- dc_stream_release(dm_new_crtc_state->stream); -- dm_new_crtc_state->stream = NULL; -- } -- dm_new_crtc_state->base.color_mgmt_changed = true; -- } -- -- for_each_new_plane_in_state(dm->cached_state, plane, new_plane_state, i) { -- dm_new_plane_state = to_dm_plane_state(new_plane_state); -- if (dm_new_plane_state->dc_state) { -- WARN_ON(kref_read(&dm_new_plane_state->dc_state->refcount) > 1); -- dc_plane_state_release(dm_new_plane_state->dc_state); -- dm_new_plane_state->dc_state = NULL; -- } -- } -- -- drm_atomic_helper_resume(ddev, dm->cached_state); -- -- dm->cached_state = NULL; -+ dm_destroy_cached_state(adev); - - /* Do mst topology probing after resuming cached state*/ - drm_connector_list_iter_begin(ddev, &iter); -@@ -3536,7 +3563,6 @@ static const struct amd_ip_funcs amdgpu_ - .early_fini = amdgpu_dm_early_fini, - .hw_init = dm_hw_init, - .hw_fini = dm_hw_fini, -- .prepare_suspend = dm_prepare_suspend, - .suspend = dm_suspend, - .resume = dm_resume, - .is_idle = dm_is_idle, -@@ -3610,13 +3636,15 @@ static void update_connector_ext_caps(st - - luminance_range = &conn_base->display_info.luminance_range; - -- if (luminance_range->max_luminance) { -- caps->aux_min_input_signal = luminance_range->min_luminance; -+ if (luminance_range->max_luminance) - caps->aux_max_input_signal = luminance_range->max_luminance; -- } else { -- caps->aux_min_input_signal = 0; -+ else - caps->aux_max_input_signal = 512; -- } -+ -+ if (luminance_range->min_luminance) -+ caps->aux_min_input_signal = luminance_range->min_luminance; -+ else -+ caps->aux_min_input_signal = 1; - - min_input_signal_override = drm_get_panel_min_brightness_quirk(aconnector->drm_edid); - if (min_input_signal_override >= 0) -@@ -4718,9 +4746,23 @@ static int get_brightness_range(const st - return 1; - } - -+/* Rescale from [min..max] to [0..AMDGPU_MAX_BL_LEVEL] */ -+static inline u32 scale_input_to_fw(int min, int max, u64 input) -+{ -+ return DIV_ROUND_CLOSEST_ULL(input * AMDGPU_MAX_BL_LEVEL, max - min); -+} -+ -+/* Rescale from [0..AMDGPU_MAX_BL_LEVEL] to [min..max] */ -+static inline u32 scale_fw_to_input(int min, int max, u64 input) -+{ -+ return min + DIV_ROUND_CLOSEST_ULL(input * (max - min), AMDGPU_MAX_BL_LEVEL); -+} -+ - static void convert_custom_brightness(const struct amdgpu_dm_backlight_caps *caps, -- uint32_t *brightness) -+ unsigned int min, unsigned int max, -+ uint32_t *user_brightness) - { -+ u32 brightness = scale_input_to_fw(min, max, *user_brightness); - u8 prev_signal = 0, prev_lum = 0; - int i = 0; - -@@ -4731,7 +4773,7 @@ static void convert_custom_brightness(co - return; - - /* choose start to run less interpolation steps */ -- if (caps->luminance_data[caps->data_points/2].input_signal > *brightness) -+ if (caps->luminance_data[caps->data_points/2].input_signal > brightness) - i = caps->data_points/2; - do { - u8 signal = caps->luminance_data[i].input_signal; -@@ -4742,17 +4784,18 @@ static void convert_custom_brightness(co - * brightness < signal: interpolate between previous and current luminance numerator - * brightness > signal: find next data point - */ -- if (*brightness > signal) { -+ if (brightness > signal) { - prev_signal = signal; - prev_lum = lum; - i++; - continue; - } -- if (*brightness < signal) -+ if (brightness < signal) - lum = prev_lum + DIV_ROUND_CLOSEST((lum - prev_lum) * -- (*brightness - prev_signal), -+ (brightness - prev_signal), - signal - prev_signal); -- *brightness = DIV_ROUND_CLOSEST(lum * *brightness, 101); -+ *user_brightness = scale_fw_to_input(min, max, -+ DIV_ROUND_CLOSEST(lum * brightness, 101)); - return; - } while (i < caps->data_points); - } -@@ -4765,11 +4808,10 @@ static u32 convert_brightness_from_user( - if (!get_brightness_range(caps, &min, &max)) - return brightness; - -- convert_custom_brightness(caps, &brightness); -+ convert_custom_brightness(caps, min, max, &brightness); - -- // Rescale 0..255 to min..max -- return min + DIV_ROUND_CLOSEST((max - min) * brightness, -- AMDGPU_MAX_BL_LEVEL); -+ // Rescale 0..max to min..max -+ return min + DIV_ROUND_CLOSEST_ULL((u64)(max - min) * brightness, max); - } - - static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *caps, -@@ -4782,8 +4824,8 @@ static u32 convert_brightness_to_user(co - - if (brightness < min) - return 0; -- // Rescale min..max to 0..255 -- return DIV_ROUND_CLOSEST(AMDGPU_MAX_BL_LEVEL * (brightness - min), -+ // Rescale min..max to 0..max -+ return DIV_ROUND_CLOSEST_ULL((u64)max * (brightness - min), - max - min); - } - -@@ -4908,7 +4950,7 @@ amdgpu_dm_register_backlight_device(stru - struct drm_device *drm = aconnector->base.dev; - struct amdgpu_display_manager *dm = &drm_to_adev(drm)->dm; - struct backlight_properties props = { 0 }; -- struct amdgpu_dm_backlight_caps caps = { 0 }; -+ struct amdgpu_dm_backlight_caps *caps; - char bl_name[16]; - int min, max; - -@@ -4922,22 +4964,21 @@ amdgpu_dm_register_backlight_device(stru - return; - } - -- amdgpu_acpi_get_backlight_caps(&caps); -- if (caps.caps_valid && get_brightness_range(&caps, &min, &max)) { -+ caps = &dm->backlight_caps[aconnector->bl_idx]; -+ if (get_brightness_range(caps, &min, &max)) { - if (power_supply_is_system_supplied() > 0) -- props.brightness = (max - min) * DIV_ROUND_CLOSEST(caps.ac_level, 100); -+ props.brightness = DIV_ROUND_CLOSEST((max - min) * caps->ac_level, 100); - else -- props.brightness = (max - min) * DIV_ROUND_CLOSEST(caps.dc_level, 100); -+ props.brightness = DIV_ROUND_CLOSEST((max - min) * caps->dc_level, 100); - /* min is zero, so max needs to be adjusted */ - props.max_brightness = max - min; - drm_dbg(drm, "Backlight caps: min: %d, max: %d, ac %d, dc %d\n", min, max, -- caps.ac_level, caps.dc_level); -+ caps->ac_level, caps->dc_level); - } else -- props.brightness = AMDGPU_MAX_BL_LEVEL; -+ props.brightness = props.max_brightness = MAX_BACKLIGHT_LEVEL; - -- if (caps.data_points && !(amdgpu_dc_debug_mask & DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE)) -+ if (caps->data_points && !(amdgpu_dc_debug_mask & DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE)) - drm_info(drm, "Using custom brightness curve\n"); -- props.max_brightness = AMDGPU_MAX_BL_LEVEL; - props.type = BACKLIGHT_RAW; - - snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d", -@@ -5353,7 +5394,8 @@ fail: - - static void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm) - { -- drm_atomic_private_obj_fini(&dm->atomic_obj); -+ if (dm->atomic_obj.state) -+ drm_atomic_private_obj_fini(&dm->atomic_obj); - } - - /****************************************************************************** -@@ -7732,6 +7774,9 @@ amdgpu_dm_connector_atomic_check(struct - struct amdgpu_dm_connector *aconn = to_amdgpu_dm_connector(conn); - int ret; - -+ if (WARN_ON(unlikely(!old_con_state || !new_con_state))) -+ return -EINVAL; -+ - trace_amdgpu_dm_connector_atomic_check(new_con_state); - - if (conn->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { -@@ -8647,7 +8692,16 @@ static int amdgpu_dm_encoder_init(struct - static void manage_dm_interrupts(struct amdgpu_device *adev, - struct amdgpu_crtc *acrtc, - struct dm_crtc_state *acrtc_state) --{ -+{ /* -+ * We cannot be sure that the frontend index maps to the same -+ * backend index - some even map to more than one. -+ * So we have to go through the CRTC to find the right IRQ. -+ */ -+ int irq_type = amdgpu_display_crtc_idx_to_irq_type( -+ adev, -+ acrtc->crtc_id); -+ struct drm_device *dev = adev_to_drm(adev); -+ - struct drm_vblank_crtc_config config = {0}; - struct dc_crtc_timing *timing; - int offdelay; -@@ -8700,7 +8754,35 @@ static void manage_dm_interrupts(struct - - drm_crtc_vblank_on_config(&acrtc->base, - &config); -+ /* Allow RX6xxx, RX7700, RX7800 GPUs to call amdgpu_irq_get.*/ -+ switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) { -+ case IP_VERSION(3, 0, 0): -+ case IP_VERSION(3, 0, 2): -+ case IP_VERSION(3, 0, 3): -+ case IP_VERSION(3, 2, 0): -+ if (amdgpu_irq_get(adev, &adev->pageflip_irq, irq_type)) -+ drm_err(dev, "DM_IRQ: Cannot get pageflip irq!\n"); -+#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) -+ if (amdgpu_irq_get(adev, &adev->vline0_irq, irq_type)) -+ drm_err(dev, "DM_IRQ: Cannot get vline0 irq!\n"); -+#endif -+ } -+ - } else { -+ /* Allow RX6xxx, RX7700, RX7800 GPUs to call amdgpu_irq_put.*/ -+ switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) { -+ case IP_VERSION(3, 0, 0): -+ case IP_VERSION(3, 0, 2): -+ case IP_VERSION(3, 0, 3): -+ case IP_VERSION(3, 2, 0): -+#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY) -+ if (amdgpu_irq_put(adev, &adev->vline0_irq, irq_type)) -+ drm_err(dev, "DM_IRQ: Cannot put vline0 irq!\n"); -+#endif -+ if (amdgpu_irq_put(adev, &adev->pageflip_irq, irq_type)) -+ drm_err(dev, "DM_IRQ: Cannot put pageflip irq!\n"); -+ } -+ - drm_crtc_vblank_off(&acrtc->base); - } - } -@@ -9722,7 +9804,6 @@ static void amdgpu_dm_commit_streams(str - bool mode_set_reset_required = false; - u32 i; - struct dc_commit_streams_params params = {dc_state->streams, dc_state->stream_count}; -- bool set_backlight_level = false; - - /* Disable writeback */ - for_each_old_connector_in_state(state, connector, old_con_state, i) { -@@ -9842,7 +9923,6 @@ static void amdgpu_dm_commit_streams(str - acrtc->hw_mode = new_crtc_state->mode; - crtc->hwmode = new_crtc_state->mode; - mode_set_reset_required = true; -- set_backlight_level = true; - } else if (modereset_required(new_crtc_state)) { - drm_dbg_atomic(dev, - "Atomic commit: RESET. crtc id %d:[%p]\n", -@@ -9899,13 +9979,16 @@ static void amdgpu_dm_commit_streams(str - * to fix a flicker issue. - * It will cause the dm->actual_brightness is not the current panel brightness - * level. (the dm->brightness is the correct panel level) -- * So we set the backlight level with dm->brightness value after set mode -+ * So we set the backlight level with dm->brightness value after initial -+ * set mode. Use restore_backlight flag to avoid setting backlight level -+ * for every subsequent mode set. - */ -- if (set_backlight_level) { -+ if (dm->restore_backlight) { - for (i = 0; i < dm->num_of_edps; i++) { - if (dm->backlight_dev[i]) - amdgpu_dm_backlight_set_level(dm, i, dm->brightness[i]); - } -+ dm->restore_backlight = false; - } - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c 2025-10-22 13:53:23.207329164 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c 2025-10-22 13:53:56.451169450 -0400 -@@ -299,6 +299,25 @@ static inline int amdgpu_dm_crtc_set_vbl - irq_type = amdgpu_display_crtc_idx_to_irq_type(adev, acrtc->crtc_id); - - if (enable) { -+ struct dc *dc = adev->dm.dc; -+ struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc); -+ struct psr_settings *psr = &acrtc_state->stream->link->psr_settings; -+ struct replay_settings *pr = &acrtc_state->stream->link->replay_settings; -+ bool sr_supported = (psr->psr_version != DC_PSR_VERSION_UNSUPPORTED) || -+ pr->config.replay_supported; -+ -+ /* -+ * IPS & self-refresh feature can cause vblank counter resets between -+ * vblank disable and enable. -+ * It may cause system stuck due to waiting for the vblank counter. -+ * Call this function to estimate missed vblanks by using timestamps and -+ * update the vblank counter in DRM. -+ */ -+ if (dc->caps.ips_support && -+ dc->config.disable_ips != DMUB_IPS_DISABLE_ALL && -+ sr_supported && vblank->config.disable_immediate) -+ drm_crtc_vblank_restore(crtc); -+ - /* vblank irq on -> Only need vupdate irq in vrr mode */ - if (amdgpu_dm_crtc_vrr_active(acrtc_state)) - rc = amdgpu_dm_crtc_set_vupdate_irq(crtc, true); -@@ -661,6 +680,15 @@ static int amdgpu_dm_crtc_helper_atomic_ - return -EINVAL; - } - -+ if (!state->legacy_cursor_update && amdgpu_dm_crtc_vrr_active(dm_crtc_state)) { -+ struct drm_plane_state *primary_state; -+ -+ /* Pull in primary plane for correct VRR handling */ -+ primary_state = drm_atomic_get_plane_state(state, crtc->primary); -+ if (IS_ERR(primary_state)) -+ return PTR_ERR(primary_state); -+ } -+ - /* In some use cases, like reset, no stream is attached */ - if (!dm_crtc_state->stream) - return 0; -@@ -728,7 +756,16 @@ int amdgpu_dm_crtc_init(struct amdgpu_di - * support programmable degamma anywhere. - */ - is_dcn = dm->adev->dm.dc->caps.color.dpp.dcn_arch; -- drm_crtc_enable_color_mgmt(&acrtc->base, is_dcn ? MAX_COLOR_LUT_ENTRIES : 0, -+ /* Dont't enable DRM CRTC degamma property for DCN401 since the -+ * pre-blending degamma LUT doesn't apply to cursor, and therefore -+ * can't work similar to a post-blending degamma LUT as in other hw -+ * versions. -+ * TODO: revisit it once KMS plane color API is merged. -+ */ -+ drm_crtc_enable_color_mgmt(&acrtc->base, -+ (is_dcn && -+ dm->adev->dm.dc->ctx->dce_version != DCN_VERSION_4_01) ? -+ MAX_COLOR_LUT_ENTRIES : 0, - true, MAX_COLOR_LUT_ENTRIES); - - drm_mode_crtc_set_gamma_size(&acrtc->base, MAX_COLOR_LEGACY_LUT_ENTRIES); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c 2025-10-22 13:53:23.207329164 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c 2025-10-22 13:53:56.451169450 -0400 -@@ -3988,7 +3988,7 @@ static int capabilities_show(struct seq_ - - struct hubbub *hubbub = dc->res_pool->hubbub; - -- if (hubbub->funcs->get_mall_en) -+ if (hubbub && hubbub->funcs->get_mall_en) - hubbub->funcs->get_mall_en(hubbub, &mall_in_use); - - if (dc->cap_funcs.get_subvp_en) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h 2025-10-22 13:53:23.207329164 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h 2025-10-22 13:53:56.451169450 -0400 -@@ -611,6 +611,13 @@ struct amdgpu_display_manager { - u32 actual_brightness[AMDGPU_DM_MAX_NUM_EDP]; - - /** -+ * @restore_backlight: -+ * -+ * Flag to indicate whether to restore backlight after modeset. -+ */ -+ bool restore_backlight; -+ -+ /** - * @aux_hpd_discon_quirk: - * - * quirk for hpd discon while aux is on-going. -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 2025-10-22 13:53:23.207329164 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c 2025-10-22 13:53:56.451169450 -0400 -@@ -1029,6 +1029,10 @@ enum dc_edid_status dm_helpers_read_loca - return EDID_NO_RESPONSE; - - edid = drm_edid_raw(drm_edid); // FIXME: Get rid of drm_edid_raw() -+ if (!edid || -+ edid->extensions >= sizeof(sink->dc_edid.raw_edid) / EDID_LENGTH) -+ return EDID_BAD_INPUT; -+ - sink->dc_edid.length = EDID_LENGTH * (edid->extensions + 1); - memmove(sink->dc_edid.raw_edid, (uint8_t *)edid, sink->dc_edid.length); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c 2025-10-22 13:53:23.207329164 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c 2025-10-22 13:53:56.451169450 -0400 -@@ -809,6 +809,7 @@ void amdgpu_dm_initialize_dp_connector(s - drm_dp_aux_init(&aconnector->dm_dp_aux.aux); - drm_dp_cec_register_connector(&aconnector->dm_dp_aux.aux, - &aconnector->base); -+ drm_dp_dpcd_set_probe(&aconnector->dm_dp_aux.aux, false); - - if (aconnector->base.connector_type == DRM_MODE_CONNECTOR_eDP) - return; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c 2025-10-22 13:53:23.207329164 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c 2025-10-22 13:53:56.451169450 -0400 -@@ -119,8 +119,10 @@ bool amdgpu_dm_link_setup_psr(struct dc_ - psr_config.allow_multi_disp_optimizations = - (amdgpu_dc_feature_mask & DC_PSR_ALLOW_MULTI_DISP_OPT); - -- if (!psr_su_set_dsc_slice_height(dc, link, stream, &psr_config)) -- return false; -+ if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) { -+ if (!psr_su_set_dsc_slice_height(dc, link, stream, &psr_config)) -+ return false; -+ } - - ret = dc_link_setup_psr(link, stream, &psr_config, &psr_context); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c 2025-10-22 13:53:23.207329164 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c 2025-10-22 13:53:56.451169450 -0400 -@@ -174,11 +174,8 @@ static struct graphics_object_id bios_pa - return object_id; - } - -- if (tbl->ucNumberOfObjects <= i) { -- dm_error("Can't find connector id %d in connector table of size %d.\n", -- i, tbl->ucNumberOfObjects); -+ if (tbl->ucNumberOfObjects <= i) - return object_id; -- } - - id = le16_to_cpu(tbl->asObjects[i].usObjectID); - object_id = object_id_from_bios_object_id(id); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/bios/command_table.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/bios/command_table.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/bios/command_table.c 2025-10-22 13:53:23.207329164 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/bios/command_table.c 2025-10-22 13:53:56.451169450 -0400 -@@ -993,7 +993,7 @@ static enum bp_result set_pixel_clock_v3 - allocation.sPCLKInput.usFbDiv = - cpu_to_le16((uint16_t)bp_params->feedback_divider); - allocation.sPCLKInput.ucFracFbDiv = -- (uint8_t)bp_params->fractional_feedback_divider; -+ (uint8_t)(bp_params->fractional_feedback_divider / 100000); - allocation.sPCLKInput.ucPostDiv = - (uint8_t)bp_params->pixel_clock_post_divider; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c 2025-10-22 13:53:23.207329164 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c 2025-10-22 13:53:56.451169450 -0400 -@@ -158,7 +158,6 @@ struct clk_mgr *dc_clk_mgr_create(struct - return NULL; - } - dce60_clk_mgr_construct(ctx, clk_mgr); -- dce_clk_mgr_construct(ctx, clk_mgr); - return &clk_mgr->base; - } - #endif -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c 2025-10-22 13:53:23.207329164 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c 2025-10-22 13:53:56.451169450 -0400 -@@ -72,9 +72,9 @@ static const struct state_dependent_cloc - /* ClocksStateLow */ - { .display_clk_khz = 352000, .pixel_clk_khz = 330000}, - /* ClocksStateNominal */ --{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 }, -+{ .display_clk_khz = 625000, .pixel_clk_khz = 400000 }, - /* ClocksStatePerformance */ --{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 } }; -+{ .display_clk_khz = 625000, .pixel_clk_khz = 400000 } }; - - int dentist_get_divider_from_did(int did) - { -@@ -245,6 +245,11 @@ int dce_set_clock( - pxl_clk_params.target_pixel_clock_100hz = requested_clk_khz * 10; - pxl_clk_params.pll_id = CLOCK_SOURCE_ID_DFS; - -+ /* DCE 6.0, DCE 6.4: engine clock is the same as PLL0 */ -+ if (clk_mgr_base->ctx->dce_version == DCE_VERSION_6_0 || -+ clk_mgr_base->ctx->dce_version == DCE_VERSION_6_4) -+ pxl_clk_params.pll_id = CLOCK_SOURCE_ID_PLL0; -+ - if (clk_mgr_dce->dfs_bypass_active) - pxl_clk_params.flags.SET_DISPCLK_DFS_BYPASS = true; - -@@ -386,8 +391,6 @@ static void dce_pplib_apply_display_requ - { - struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; - -- pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context); -- - dce110_fill_display_configs(context, pp_display_cfg); - - if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0) -@@ -400,11 +403,9 @@ static void dce_update_clocks(struct clk - { - struct clk_mgr_internal *clk_mgr_dce = TO_CLK_MGR_INTERNAL(clk_mgr_base); - struct dm_pp_power_level_change_request level_change_req; -- int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz; -- -- /*TODO: W/A for dal3 linux, investigate why this works */ -- if (!clk_mgr_dce->dfs_bypass_active) -- patched_disp_clk = patched_disp_clk * 115 / 100; -+ const int max_disp_clk = -+ clk_mgr_dce->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz; -+ int patched_disp_clk = MIN(max_disp_clk, context->bw_ctx.bw.dce.dispclk_khz); - - level_change_req.power_level = dce_get_required_clocks_state(clk_mgr_base, context); - /* get max clock state from PPLIB */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c 2025-10-22 13:53:23.211329144 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c 2025-10-22 13:53:56.451169450 -0400 -@@ -120,9 +120,15 @@ void dce110_fill_display_configs( - const struct dc_state *context, - struct dm_pp_display_configuration *pp_display_cfg) - { -+ struct dc *dc = context->clk_mgr->ctx->dc; - int j; - int num_cfgs = 0; - -+ pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context); -+ pp_display_cfg->disp_clk_khz = dc->clk_mgr->clks.dispclk_khz; -+ pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; -+ pp_display_cfg->crtc_index = dc->res_pool->res_cap->num_timing_generator; -+ - for (j = 0; j < context->stream_count; j++) { - int k; - -@@ -164,6 +170,23 @@ void dce110_fill_display_configs( - cfg->v_refresh /= stream->timing.h_total; - cfg->v_refresh = (cfg->v_refresh + stream->timing.v_total / 2) - / stream->timing.v_total; -+ -+ /* Find first CRTC index and calculate its line time. -+ * This is necessary for DPM on SI GPUs. -+ */ -+ if (cfg->pipe_idx < pp_display_cfg->crtc_index) { -+ const struct dc_crtc_timing *timing = -+ &context->streams[0]->timing; -+ -+ pp_display_cfg->crtc_index = cfg->pipe_idx; -+ pp_display_cfg->line_time_in_us = -+ timing->h_total * 10000 / timing->pix_clk_100hz; -+ } -+ } -+ -+ if (!num_cfgs) { -+ pp_display_cfg->crtc_index = 0; -+ pp_display_cfg->line_time_in_us = 0; - } - - pp_display_cfg->display_count = num_cfgs; -@@ -223,25 +246,8 @@ void dce11_pplib_apply_display_requireme - pp_display_cfg->min_engine_clock_deep_sleep_khz - = context->bw_ctx.bw.dce.sclk_deep_sleep_khz; - -- pp_display_cfg->avail_mclk_switch_time_us = -- dce110_get_min_vblank_time_us(context); -- /* TODO: dce11.2*/ -- pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0; -- -- pp_display_cfg->disp_clk_khz = dc->clk_mgr->clks.dispclk_khz; -- - dce110_fill_display_configs(context, pp_display_cfg); - -- /* TODO: is this still applicable?*/ -- if (pp_display_cfg->display_count == 1) { -- const struct dc_crtc_timing *timing = -- &context->streams[0]->timing; -- -- pp_display_cfg->crtc_index = -- pp_display_cfg->disp_configs[0].pipe_idx; -- pp_display_cfg->line_time_in_us = timing->h_total * 10000 / timing->pix_clk_100hz; -- } -- - if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0) - dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c 2025-10-22 13:53:23.211329144 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c 2025-10-22 13:53:56.451169450 -0400 -@@ -83,22 +83,13 @@ static const struct state_dependent_cloc - static int dce60_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base) - { - struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); -- int dprefclk_wdivider; -- int dp_ref_clk_khz; -- int target_div; -- -- /* DCE6 has no DPREFCLK_CNTL to read DP Reference Clock source */ -- -- /* Read the mmDENTIST_DISPCLK_CNTL to get the currently -- * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ -- REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, &dprefclk_wdivider); -- -- /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ -- target_div = dentist_get_divider_from_did(dprefclk_wdivider); -- -- /* Calculate the current DFS clock, in kHz.*/ -- dp_ref_clk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR -- * clk_mgr->base.dentist_vco_freq_khz) / target_div; -+ struct dc_context *ctx = clk_mgr_base->ctx; -+ int dp_ref_clk_khz = 0; -+ -+ if (ASIC_REV_IS_TAHITI_P(ctx->asic_id.hw_internal_rev)) -+ dp_ref_clk_khz = ctx->dc_bios->fw_info.default_display_engine_pll_frequency; -+ else -+ dp_ref_clk_khz = clk_mgr_base->clks.dispclk_khz; - - return dce_adjust_dp_ref_freq_for_ss(clk_mgr, dp_ref_clk_khz); - } -@@ -109,8 +100,6 @@ static void dce60_pplib_apply_display_re - { - struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; - -- pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context); -- - dce110_fill_display_configs(context, pp_display_cfg); - - if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0) -@@ -123,11 +112,9 @@ static void dce60_update_clocks(struct c - { - struct clk_mgr_internal *clk_mgr_dce = TO_CLK_MGR_INTERNAL(clk_mgr_base); - struct dm_pp_power_level_change_request level_change_req; -- int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz; -- -- /*TODO: W/A for dal3 linux, investigate why this works */ -- if (!clk_mgr_dce->dfs_bypass_active) -- patched_disp_clk = patched_disp_clk * 115 / 100; -+ const int max_disp_clk = -+ clk_mgr_dce->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz; -+ int patched_disp_clk = MIN(max_disp_clk, context->bw_ctx.bw.dce.dispclk_khz); - - level_change_req.power_level = dce_get_required_clocks_state(clk_mgr_base, context); - /* get max clock state from PPLIB */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c 2025-10-22 13:53:23.211329144 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c 2025-10-22 13:53:56.451169450 -0400 -@@ -1565,7 +1565,7 @@ struct clk_mgr_internal *dcn401_clk_mgr_ - clk_mgr->base.bw_params = kzalloc(sizeof(*clk_mgr->base.bw_params), GFP_KERNEL); - if (!clk_mgr->base.bw_params) { - BREAK_TO_DEBUGGER(); -- kfree(clk_mgr); -+ kfree(clk_mgr401); - return NULL; - } - -@@ -1576,6 +1576,7 @@ struct clk_mgr_internal *dcn401_clk_mgr_ - if (!clk_mgr->wm_range_table) { - BREAK_TO_DEBUGGER(); - kfree(clk_mgr->base.bw_params); -+ kfree(clk_mgr401); - return NULL; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/core/dc.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/core/dc.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/core/dc.c 2025-10-22 13:53:23.211329144 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/core/dc.c 2025-10-22 13:53:56.451169450 -0400 -@@ -217,11 +217,24 @@ static bool create_links( - connectors_num, - num_virtual_links); - -- // condition loop on link_count to allow skipping invalid indices -+ /* When getting the number of connectors, the VBIOS reports the number of valid indices, -+ * but it doesn't say which indices are valid, and not every index has an actual connector. -+ * So, if we don't find a connector on an index, that is not an error. -+ * -+ * - There is no guarantee that the first N indices will be valid -+ * - VBIOS may report a higher amount of valid indices than there are actual connectors -+ * - Some VBIOS have valid configurations for more connectors than there actually are -+ * on the card. This may be because the manufacturer used the same VBIOS for different -+ * variants of the same card. -+ */ - for (i = 0; dc->link_count < connectors_num && i < MAX_LINKS; i++) { -+ struct graphics_object_id connector_id = bios->funcs->get_connector_id(bios, i); - struct link_init_data link_init_params = {0}; - struct dc_link *link; - -+ if (connector_id.id == CONNECTOR_ID_UNKNOWN) -+ continue; -+ - DC_LOG_DC("BIOS object table - printing link object info for connector number: %d, link_index: %d", i, dc->link_count); - - link_init_params.ctx = dc->ctx; -@@ -241,6 +254,7 @@ static bool create_links( - DC_LOG_DC("BIOS object table - end"); - - /* Create a link for each usb4 dpia port */ -+ dc->lowest_dpia_link_index = MAX_LINKS; - for (i = 0; i < dc->res_pool->usb4_dpia_count; i++) { - struct link_init_data link_init_params = {0}; - struct dc_link *link; -@@ -253,6 +267,9 @@ static bool create_links( - - link = dc->link_srv->create_link(&link_init_params); - if (link) { -+ if (dc->lowest_dpia_link_index > dc->link_count) -+ dc->lowest_dpia_link_index = dc->link_count; -+ - dc->links[dc->link_count] = link; - link->dc = dc; - ++dc->link_count; -@@ -934,17 +951,18 @@ static void dc_destruct(struct dc *dc) - if (dc->link_srv) - link_destroy_link_service(&dc->link_srv); - -- if (dc->ctx->gpio_service) -- dal_gpio_service_destroy(&dc->ctx->gpio_service); -- -- if (dc->ctx->created_bios) -- dal_bios_parser_destroy(&dc->ctx->dc_bios); -- -- kfree(dc->ctx->logger); -- dc_perf_trace_destroy(&dc->ctx->perf_trace); -+ if (dc->ctx) { -+ if (dc->ctx->gpio_service) -+ dal_gpio_service_destroy(&dc->ctx->gpio_service); -+ -+ if (dc->ctx->created_bios) -+ dal_bios_parser_destroy(&dc->ctx->dc_bios); -+ kfree(dc->ctx->logger); -+ dc_perf_trace_destroy(&dc->ctx->perf_trace); - -- kfree(dc->ctx); -- dc->ctx = NULL; -+ kfree(dc->ctx); -+ dc->ctx = NULL; -+ } - - kfree(dc->bw_vbios); - dc->bw_vbios = NULL; -@@ -5435,8 +5453,8 @@ bool dc_update_planes_and_stream(struct - else - ret = update_planes_and_stream_v2(dc, srf_updates, - surface_count, stream, stream_update); -- -- if (ret) -+ if (ret && (dc->ctx->dce_version >= DCN_VERSION_3_2 || -+ dc->ctx->dce_version == DCN_VERSION_3_01)) - clear_update_flags(srf_updates, surface_count, stream); - - return ret; -@@ -5467,7 +5485,7 @@ void dc_commit_updates_for_stream(struct - ret = update_planes_and_stream_v1(dc, srf_updates, surface_count, stream, - stream_update, state); - -- if (ret) -+ if (ret && dc->ctx->dce_version >= DCN_VERSION_3_2) - clear_update_flags(srf_updates, surface_count, stream); - } - -@@ -6376,6 +6394,37 @@ unsigned int dc_get_det_buffer_size_from - else - return 0; - } -+/** -+ *********************************************************************************************** -+ * dc_get_host_router_index: Get index of host router from a dpia link -+ * -+ * This function return a host router index of the target link. If the target link is dpia link. -+ * -+ * @param [in] link: target link -+ * @param [out] host_router_index: host router index of the target link -+ * -+ * @return: true if the host router index is found and valid. -+ * -+ *********************************************************************************************** -+ */ -+bool dc_get_host_router_index(const struct dc_link *link, unsigned int *host_router_index) -+{ -+ struct dc *dc; -+ -+ if (!link || !host_router_index || link->ep_type != DISPLAY_ENDPOINT_USB4_DPIA) -+ return false; -+ -+ dc = link->ctx->dc; -+ -+ if (link->link_index < dc->lowest_dpia_link_index) -+ return false; -+ -+ *host_router_index = (link->link_index - dc->lowest_dpia_link_index) / dc->caps.num_of_dpias_per_host_router; -+ if (*host_router_index < dc->caps.num_of_host_routers) -+ return true; -+ else -+ return false; -+} - - bool dc_is_cursor_limit_pending(struct dc *dc) - { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c 2025-10-22 13:53:23.211329144 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c 2025-10-22 13:53:56.451169450 -0400 -@@ -133,30 +133,34 @@ enum dsc_clk_source { - }; - - --static void dccg35_set_dsc_clk_rcg(struct dccg *dccg, int inst, bool enable) -+static void dccg35_set_dsc_clk_rcg(struct dccg *dccg, int inst, bool allow_rcg) - { - struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); - -- if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc && enable) -+ if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc && allow_rcg) - return; - - switch (inst) { - case 0: -- REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK0_ROOT_GATE_DISABLE, enable ? 0 : 1); -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK0_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1); - break; - case 1: -- REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK1_ROOT_GATE_DISABLE, enable ? 0 : 1); -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK1_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1); - break; - case 2: -- REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK2_ROOT_GATE_DISABLE, enable ? 0 : 1); -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK2_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1); - break; - case 3: -- REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK3_ROOT_GATE_DISABLE, enable ? 0 : 1); -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK3_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1); - break; - default: - BREAK_TO_DEBUGGER(); - return; - } -+ -+ /* Wait for clock to ramp */ -+ if (!allow_rcg) -+ udelay(10); - } - - static void dccg35_set_symclk32_se_rcg( -@@ -385,35 +389,34 @@ static void dccg35_set_dtbclk_p_rcg(stru - } - } - --static void dccg35_set_dppclk_rcg(struct dccg *dccg, -- int inst, bool enable) -+static void dccg35_set_dppclk_rcg(struct dccg *dccg, int inst, bool allow_rcg) - { -- - struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); - -- -- if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dpp && enable) -+ if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dpp && allow_rcg) - return; - - switch (inst) { - case 0: -- REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK0_ROOT_GATE_DISABLE, enable ? 0 : 1); -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK0_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1); - break; - case 1: -- REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK1_ROOT_GATE_DISABLE, enable ? 0 : 1); -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK1_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1); - break; - case 2: -- REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK2_ROOT_GATE_DISABLE, enable ? 0 : 1); -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK2_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1); - break; - case 3: -- REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK3_ROOT_GATE_DISABLE, enable ? 0 : 1); -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK3_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1); - break; - default: - BREAK_TO_DEBUGGER(); - break; - } -- //DC_LOG_DEBUG("%s: inst(%d) DPPCLK rcg_disable: %d\n", __func__, inst, enable ? 0 : 1); - -+ /* Wait for clock to ramp */ -+ if (!allow_rcg) -+ udelay(10); - } - - static void dccg35_set_dpstreamclk_rcg( -@@ -1177,32 +1180,34 @@ static void dccg35_update_dpp_dto(struct - } - - static void dccg35_set_dppclk_root_clock_gating(struct dccg *dccg, -- uint32_t dpp_inst, uint32_t enable) -+ uint32_t dpp_inst, uint32_t disallow_rcg) - { - struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); - -- if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dpp) -+ if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dpp && !disallow_rcg) - return; - - - switch (dpp_inst) { - case 0: -- REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK0_ROOT_GATE_DISABLE, enable); -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK0_ROOT_GATE_DISABLE, disallow_rcg); - break; - case 1: -- REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK1_ROOT_GATE_DISABLE, enable); -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK1_ROOT_GATE_DISABLE, disallow_rcg); - break; - case 2: -- REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK2_ROOT_GATE_DISABLE, enable); -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK2_ROOT_GATE_DISABLE, disallow_rcg); - break; - case 3: -- REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK3_ROOT_GATE_DISABLE, enable); -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK3_ROOT_GATE_DISABLE, disallow_rcg); - break; - default: - break; - } -- //DC_LOG_DEBUG("%s: dpp_inst(%d) rcg: %d\n", __func__, dpp_inst, enable); - -+ /* Wait for clock to ramp */ -+ if (disallow_rcg) -+ udelay(10); - } - - static void dccg35_get_pixel_rate_div( -@@ -1782,8 +1787,7 @@ static void dccg35_enable_dscclk(struct - //Disable DTO - switch (inst) { - case 0: -- if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc) -- REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK0_ROOT_GATE_DISABLE, 1); -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK0_ROOT_GATE_DISABLE, 1); - - REG_UPDATE_2(DSCCLK0_DTO_PARAM, - DSCCLK0_DTO_PHASE, 0, -@@ -1791,8 +1795,7 @@ static void dccg35_enable_dscclk(struct - REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK0_EN, 1); - break; - case 1: -- if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc) -- REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK1_ROOT_GATE_DISABLE, 1); -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK1_ROOT_GATE_DISABLE, 1); - - REG_UPDATE_2(DSCCLK1_DTO_PARAM, - DSCCLK1_DTO_PHASE, 0, -@@ -1800,8 +1803,7 @@ static void dccg35_enable_dscclk(struct - REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK1_EN, 1); - break; - case 2: -- if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc) -- REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK2_ROOT_GATE_DISABLE, 1); -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK2_ROOT_GATE_DISABLE, 1); - - REG_UPDATE_2(DSCCLK2_DTO_PARAM, - DSCCLK2_DTO_PHASE, 0, -@@ -1809,8 +1811,7 @@ static void dccg35_enable_dscclk(struct - REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK2_EN, 1); - break; - case 3: -- if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc) -- REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK3_ROOT_GATE_DISABLE, 1); -+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK3_ROOT_GATE_DISABLE, 1); - - REG_UPDATE_2(DSCCLK3_DTO_PARAM, - DSCCLK3_DTO_PHASE, 0, -@@ -1821,6 +1822,9 @@ static void dccg35_enable_dscclk(struct - BREAK_TO_DEBUGGER(); - return; - } -+ -+ /* Wait for clock to ramp */ -+ udelay(10); - } - - static void dccg35_disable_dscclk(struct dccg *dccg, -@@ -1864,6 +1868,9 @@ static void dccg35_disable_dscclk(struct - default: - return; - } -+ -+ /* Wait for clock ramp */ -+ udelay(10); - } - - static void dccg35_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst) -@@ -2349,10 +2356,7 @@ static void dccg35_disable_symclk_se_cb( - - void dccg35_root_gate_disable_control(struct dccg *dccg, uint32_t pipe_idx, uint32_t disable_clock_gating) - { -- -- if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpp) { -- dccg35_set_dppclk_root_clock_gating(dccg, pipe_idx, disable_clock_gating); -- } -+ dccg35_set_dppclk_root_clock_gating(dccg, pipe_idx, disable_clock_gating); - } - - static const struct dccg_funcs dccg35_funcs_new = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/dc_dp_types.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/dc_dp_types.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/dc_dp_types.h 2025-10-22 13:53:23.211329144 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/dc_dp_types.h 2025-10-22 13:53:56.451169450 -0400 -@@ -1172,8 +1172,8 @@ struct dc_lttpr_caps { - union dp_128b_132b_supported_lttpr_link_rates supported_128b_132b_rates; - union dp_alpm_lttpr_cap alpm; - uint8_t aux_rd_interval[MAX_REPEATER_CNT - 1]; -- uint8_t lttpr_ieee_oui[3]; -- uint8_t lttpr_device_id[6]; -+ uint8_t lttpr_ieee_oui[3]; // Always read from closest LTTPR to host -+ uint8_t lttpr_device_id[6]; // Always read from closest LTTPR to host - }; - - struct dc_dongle_dfp_cap_ext { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c 2025-10-22 13:53:23.211329144 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c 2025-10-22 13:53:56.451169450 -0400 -@@ -896,13 +896,13 @@ void dce110_link_encoder_construct( - enc110->base.id, &bp_cap_info); - - /* Override features with DCE-specific values */ -- if (BP_RESULT_OK == result) { -+ if (result == BP_RESULT_OK) { - enc110->base.features.flags.bits.IS_HBR2_CAPABLE = - bp_cap_info.DP_HBR2_EN; - enc110->base.features.flags.bits.IS_HBR3_CAPABLE = - bp_cap_info.DP_HBR3_EN; - enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; -- } else { -+ } else if (result != BP_RESULT_NORECORD) { - DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", - __func__, - result); -@@ -1798,13 +1798,13 @@ void dce60_link_encoder_construct( - enc110->base.id, &bp_cap_info); - - /* Override features with DCE-specific values */ -- if (BP_RESULT_OK == result) { -+ if (result == BP_RESULT_OK) { - enc110->base.features.flags.bits.IS_HBR2_CAPABLE = - bp_cap_info.DP_HBR2_EN; - enc110->base.features.flags.bits.IS_HBR3_CAPABLE = - bp_cap_info.DP_HBR3_EN; - enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; -- } else { -+ } else if (result != BP_RESULT_NORECORD) { - DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n", - __func__, - result); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/dc.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/dc.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/dc.h 2025-10-22 13:53:23.211329144 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/dc.h 2025-10-22 13:53:56.451169450 -0400 -@@ -66,7 +66,8 @@ struct dmub_notification; - #define MAX_STREAMS 6 - #define MIN_VIEWPORT_SIZE 12 - #define MAX_NUM_EDP 2 --#define MAX_HOST_ROUTERS_NUM 2 -+#define MAX_HOST_ROUTERS_NUM 3 -+#define MAX_DPIA_PER_HOST_ROUTER 2 - - /* Display Core Interfaces */ - struct dc_versions { -@@ -305,6 +306,8 @@ struct dc_caps { - /* Conservative limit for DCC cases which require ODM4:1 to support*/ - uint32_t dcc_plane_width_limit; - struct dc_scl_caps scl_caps; -+ uint8_t num_of_host_routers; -+ uint8_t num_of_dpias_per_host_router; - }; - - struct dc_bug_wa { -@@ -1092,6 +1095,7 @@ struct dc_debug_options { - bool enable_hblank_borrow; - bool force_subvp_df_throttle; - uint32_t acpi_transition_bitmasks[MAX_PIPES]; -+ bool enable_pg_cntl_debug_logs; - }; - - -@@ -1288,7 +1292,6 @@ union surface_update_flags { - uint32_t in_transfer_func_change:1; - uint32_t input_csc_change:1; - uint32_t coeff_reduction_change:1; -- uint32_t output_tf_change:1; - uint32_t pixel_format_change:1; - uint32_t plane_size_change:1; - uint32_t gamut_remap_change:1; -@@ -1603,6 +1606,7 @@ struct dc { - - uint8_t link_count; - struct dc_link *links[MAX_LINKS]; -+ uint8_t lowest_dpia_link_index; - struct link_service *link_srv; - - struct dc_state *current_state; -@@ -2595,6 +2599,8 @@ struct dc_power_profile dc_get_power_pro - - unsigned int dc_get_det_buffer_size_from_state(const struct dc_state *context); - -+bool dc_get_host_router_index(const struct dc_link *link, unsigned int *host_router_index); -+ - /* DSC Interfaces */ - #include "dc_dsc.h" - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/dc_hw_types.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/dc_hw_types.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/dc_hw_types.h 2025-10-22 13:53:23.211329144 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/dc_hw_types.h 2025-10-22 13:53:56.451169450 -0400 -@@ -974,6 +974,7 @@ struct dc_crtc_timing { - uint32_t pix_clk_100hz; - - uint32_t min_refresh_in_uhz; -+ uint32_t max_refresh_in_uhz; - - uint32_t vic; - uint32_t hdmi_vic; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c 2025-10-22 13:53:23.211329144 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c 2025-10-22 13:53:56.451169450 -0400 -@@ -788,6 +788,7 @@ static void populate_dml21_plane_config_ - plane->pixel_format = dml2_420_10; - break; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: -+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: - case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: - plane->pixel_format = dml2_444_64; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c 2025-10-22 13:53:23.211329144 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c 2025-10-22 13:53:56.455169431 -0400 -@@ -4685,7 +4685,10 @@ static void calculate_tdlut_setting( - //the tdlut is fetched during the 2 row times of prefetch. - if (p->setup_for_tdlut) { - *p->tdlut_groups_per_2row_ub = (unsigned int)math_ceil2((double) *p->tdlut_bytes_per_frame / *p->tdlut_bytes_per_group, 1); -- *p->tdlut_opt_time = (*p->tdlut_bytes_per_frame - p->cursor_buffer_size * 1024) / tdlut_drain_rate; -+ if (*p->tdlut_bytes_per_frame > p->cursor_buffer_size * 1024) -+ *p->tdlut_opt_time = (*p->tdlut_bytes_per_frame - p->cursor_buffer_size * 1024) / tdlut_drain_rate; -+ else -+ *p->tdlut_opt_time = 0; - *p->tdlut_drain_time = p->cursor_buffer_size * 1024 / tdlut_drain_rate; - *p->tdlut_bytes_to_deliver = (unsigned int) (p->cursor_buffer_size * 1024.0); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c 2025-10-22 13:53:23.211329144 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c 2025-10-22 13:53:56.455169431 -0400 -@@ -953,6 +953,7 @@ static void populate_dml_surface_cfg_fro - out->SourcePixelFormat[location] = dml_420_10; - break; - case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: -+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: - case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: - case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: - out->SourcePixelFormat[location] = dml_444_64; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c 2025-10-22 13:53:23.211329144 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c 2025-10-22 13:53:56.455169431 -0400 -@@ -520,6 +520,15 @@ void dpp1_dppclk_control( - REG_UPDATE(DPP_CONTROL, DPP_CLOCK_ENABLE, 0); - } - -+void dpp_force_disable_cursor(struct dpp *dpp_base) -+{ -+ struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); -+ -+ /* Force disable cursor */ -+ REG_UPDATE(CURSOR0_CONTROL, CUR0_ENABLE, 0); -+ dpp_base->pos.cur0_ctl.bits.cur0_enable = 0; -+} -+ - static const struct dpp_funcs dcn10_dpp_funcs = { - .dpp_read_state = dpp_read_state, - .dpp_reset = dpp_reset, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.h 2025-10-22 13:53:23.211329144 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.h 2025-10-22 13:53:56.455169431 -0400 -@@ -1525,4 +1525,6 @@ void dpp1_construct(struct dcn10_dpp *dp - - void dpp1_cm_get_gamut_remap(struct dpp *dpp_base, - struct dpp_grph_csc_adjustment *adjust); -+void dpp_force_disable_cursor(struct dpp *dpp_base); -+ - #endif -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c 2025-10-22 13:53:23.211329144 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c 2025-10-22 13:53:56.455169431 -0400 -@@ -1494,6 +1494,7 @@ static struct dpp_funcs dcn30_dpp_funcs - .dpp_dppclk_control = dpp1_dppclk_control, - .dpp_set_hdr_multiplier = dpp3_set_hdr_multiplier, - .dpp_get_gamut_remap = dpp3_cm_get_gamut_remap, -+ .dpp_force_disable_cursor = dpp_force_disable_cursor, - }; - - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c 2025-10-22 13:53:56.455169431 -0400 -@@ -1225,7 +1225,7 @@ void dce110_blank_stream(struct pipe_ctx - return; - - if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) { -- if (!link->skip_implict_edp_power_control) -+ if (!link->skip_implict_edp_power_control && hws) - hws->funcs.edp_backlight_control(link, false); - link->dc->hwss.set_abm_immediate_disable(pipe_ctx); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c 2025-10-22 13:53:56.455169431 -0400 -@@ -283,14 +283,13 @@ void dcn20_setup_gsl_group_as_lock( - } - - /* at this point we want to program whether it's to enable or disable */ -- if (pipe_ctx->stream_res.tg->funcs->set_gsl != NULL && -- pipe_ctx->stream_res.tg->funcs->set_gsl_source_select != NULL) { -+ if (pipe_ctx->stream_res.tg->funcs->set_gsl != NULL) { - pipe_ctx->stream_res.tg->funcs->set_gsl( - pipe_ctx->stream_res.tg, - &gsl); -- -- pipe_ctx->stream_res.tg->funcs->set_gsl_source_select( -- pipe_ctx->stream_res.tg, group_idx, enable ? 4 : 0); -+ if (pipe_ctx->stream_res.tg->funcs->set_gsl_source_select != NULL) -+ pipe_ctx->stream_res.tg->funcs->set_gsl_source_select( -+ pipe_ctx->stream_res.tg, group_idx, enable ? 4 : 0); - } else - BREAK_TO_DEBUGGER(); - } -@@ -956,7 +955,7 @@ enum dc_status dcn20_enable_stream_timin - return DC_ERROR_UNEXPECTED; - } - -- hws->funcs.wait_for_blank_complete(pipe_ctx->stream_res.opp); -+ udelay(stream->timing.v_total * (stream->timing.h_total * 10000u / stream->timing.pix_clk_100hz)); - - params.vertical_total_min = stream->adjust.v_total_min; - params.vertical_total_max = stream->adjust.v_total_max; -@@ -1991,10 +1990,8 @@ static void dcn20_program_pipe( - * updating on slave planes - */ - if (pipe_ctx->update_flags.bits.enable || -- pipe_ctx->update_flags.bits.plane_changed || -- pipe_ctx->stream->update_flags.bits.out_tf || -- (pipe_ctx->plane_state && -- pipe_ctx->plane_state->update_flags.bits.output_tf_change)) -+ pipe_ctx->update_flags.bits.plane_changed || -+ pipe_ctx->stream->update_flags.bits.out_tf) - hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream); - - /* If the pipe has been enabled or has a different opp, we -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c 2025-10-22 13:53:56.455169431 -0400 -@@ -528,3 +528,75 @@ void dcn314_disable_link_output(struct d - - apply_symclk_on_tx_off_wa(link); - } -+ -+/** -+ * dcn314_dpp_pg_control - DPP power gate control. -+ * -+ * @hws: dce_hwseq reference. -+ * @dpp_inst: DPP instance reference. -+ * @power_on: true if we want to enable power gate, false otherwise. -+ * -+ * Enable or disable power gate in the specific DPP instance. -+ * If power gating is disabled, will force disable cursor in the DPP instance. -+ */ -+void dcn314_dpp_pg_control( -+ struct dce_hwseq *hws, -+ unsigned int dpp_inst, -+ bool power_on) -+{ -+ uint32_t power_gate = power_on ? 0 : 1; -+ uint32_t pwr_status = power_on ? 0 : 2; -+ -+ -+ if (hws->ctx->dc->debug.disable_dpp_power_gate) { -+ /* Workaround for DCN314 with disabled power gating */ -+ if (!power_on) { -+ -+ /* Force disable cursor if power gating is disabled */ -+ struct dpp *dpp = hws->ctx->dc->res_pool->dpps[dpp_inst]; -+ if (dpp && dpp->funcs->dpp_force_disable_cursor) -+ dpp->funcs->dpp_force_disable_cursor(dpp); -+ } -+ return; -+ } -+ if (REG(DOMAIN1_PG_CONFIG) == 0) -+ return; -+ -+ switch (dpp_inst) { -+ case 0: /* DPP0 */ -+ REG_UPDATE(DOMAIN1_PG_CONFIG, -+ DOMAIN1_POWER_GATE, power_gate); -+ -+ REG_WAIT(DOMAIN1_PG_STATUS, -+ DOMAIN1_PGFSM_PWR_STATUS, pwr_status, -+ 1, 1000); -+ break; -+ case 1: /* DPP1 */ -+ REG_UPDATE(DOMAIN3_PG_CONFIG, -+ DOMAIN3_POWER_GATE, power_gate); -+ -+ REG_WAIT(DOMAIN3_PG_STATUS, -+ DOMAIN3_PGFSM_PWR_STATUS, pwr_status, -+ 1, 1000); -+ break; -+ case 2: /* DPP2 */ -+ REG_UPDATE(DOMAIN5_PG_CONFIG, -+ DOMAIN5_POWER_GATE, power_gate); -+ -+ REG_WAIT(DOMAIN5_PG_STATUS, -+ DOMAIN5_PGFSM_PWR_STATUS, pwr_status, -+ 1, 1000); -+ break; -+ case 3: /* DPP3 */ -+ REG_UPDATE(DOMAIN7_PG_CONFIG, -+ DOMAIN7_POWER_GATE, power_gate); -+ -+ REG_WAIT(DOMAIN7_PG_STATUS, -+ DOMAIN7_PGFSM_PWR_STATUS, pwr_status, -+ 1, 1000); -+ break; -+ default: -+ BREAK_TO_DEBUGGER(); -+ break; -+ } -+} -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.h 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.h 2025-10-22 13:53:56.455169431 -0400 -@@ -47,4 +47,6 @@ void dcn314_dpp_root_clock_control(struc - - void dcn314_disable_link_output(struct dc_link *link, const struct link_resource *link_res, enum signal_type signal); - -+void dcn314_dpp_pg_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on); -+ - #endif /* __DC_HWSS_DCN314_H__ */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_init.c 2025-10-22 13:53:56.455169431 -0400 -@@ -141,6 +141,7 @@ static const struct hwseq_private_funcs - .enable_power_gating_plane = dcn314_enable_power_gating_plane, - .dpp_root_clock_control = dcn314_dpp_root_clock_control, - .hubp_pg_control = dcn31_hubp_pg_control, -+ .dpp_pg_control = dcn314_dpp_pg_control, - .program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree, - .update_odm = dcn314_update_odm, - .dsc_pg_control = dcn314_dsc_pg_control, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c 2025-10-22 13:53:56.455169431 -0400 -@@ -113,6 +113,14 @@ static void enable_memory_low_power(stru - } - #endif - -+static void print_pg_status(struct dc *dc, const char *debug_func, const char *debug_log) -+{ -+ if (dc->debug.enable_pg_cntl_debug_logs && dc->res_pool->pg_cntl) { -+ if (dc->res_pool->pg_cntl->funcs->print_pg_status) -+ dc->res_pool->pg_cntl->funcs->print_pg_status(dc->res_pool->pg_cntl, debug_func, debug_log); -+ } -+} -+ - void dcn35_set_dmu_fgcg(struct dce_hwseq *hws, bool enable) - { - REG_UPDATE_3(DMU_CLK_CNTL, -@@ -137,6 +145,8 @@ void dcn35_init_hw(struct dc *dc) - uint32_t user_level = MAX_BACKLIGHT_LEVEL; - int i; - -+ print_pg_status(dc, __func__, ": start"); -+ - if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) - dc->clk_mgr->funcs->init_clocks(dc->clk_mgr); - -@@ -200,10 +210,7 @@ void dcn35_init_hw(struct dc *dc) - - /* we want to turn off all dp displays before doing detection */ - dc->link_srv->blank_all_dp_displays(dc); --/* -- if (hws->funcs.enable_power_gating_plane) -- hws->funcs.enable_power_gating_plane(dc->hwseq, true); --*/ -+ - if (res_pool->hubbub && res_pool->hubbub->funcs->dchubbub_init) - res_pool->hubbub->funcs->dchubbub_init(dc->res_pool->hubbub); - /* If taking control over from VBIOS, we may want to optimize our first -@@ -236,6 +243,8 @@ void dcn35_init_hw(struct dc *dc) - } - - hws->funcs.init_pipes(dc, dc->current_state); -+ print_pg_status(dc, __func__, ": after init_pipes"); -+ - if (dc->res_pool->hubbub->funcs->allow_self_refresh_control && - !dc->res_pool->hubbub->ctx->dc->debug.disable_stutter) - dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, -@@ -312,6 +321,7 @@ void dcn35_init_hw(struct dc *dc) - if (dc->res_pool->pg_cntl->funcs->init_pg_status) - dc->res_pool->pg_cntl->funcs->init_pg_status(dc->res_pool->pg_cntl); - } -+ print_pg_status(dc, __func__, ": after init_pg_status"); - } - - static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) -@@ -500,97 +510,6 @@ void dcn35_physymclk_root_clock_control( - } - } - --void dcn35_dsc_pg_control( -- struct dce_hwseq *hws, -- unsigned int dsc_inst, -- bool power_on) --{ -- uint32_t power_gate = power_on ? 0 : 1; -- uint32_t pwr_status = power_on ? 0 : 2; -- uint32_t org_ip_request_cntl = 0; -- -- if (hws->ctx->dc->debug.disable_dsc_power_gate) -- return; -- if (hws->ctx->dc->debug.ignore_pg) -- return; -- REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl); -- if (org_ip_request_cntl == 0) -- REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); -- -- switch (dsc_inst) { -- case 0: /* DSC0 */ -- REG_UPDATE(DOMAIN16_PG_CONFIG, -- DOMAIN_POWER_GATE, power_gate); -- -- REG_WAIT(DOMAIN16_PG_STATUS, -- DOMAIN_PGFSM_PWR_STATUS, pwr_status, -- 1, 1000); -- break; -- case 1: /* DSC1 */ -- REG_UPDATE(DOMAIN17_PG_CONFIG, -- DOMAIN_POWER_GATE, power_gate); -- -- REG_WAIT(DOMAIN17_PG_STATUS, -- DOMAIN_PGFSM_PWR_STATUS, pwr_status, -- 1, 1000); -- break; -- case 2: /* DSC2 */ -- REG_UPDATE(DOMAIN18_PG_CONFIG, -- DOMAIN_POWER_GATE, power_gate); -- -- REG_WAIT(DOMAIN18_PG_STATUS, -- DOMAIN_PGFSM_PWR_STATUS, pwr_status, -- 1, 1000); -- break; -- case 3: /* DSC3 */ -- REG_UPDATE(DOMAIN19_PG_CONFIG, -- DOMAIN_POWER_GATE, power_gate); -- -- REG_WAIT(DOMAIN19_PG_STATUS, -- DOMAIN_PGFSM_PWR_STATUS, pwr_status, -- 1, 1000); -- break; -- default: -- BREAK_TO_DEBUGGER(); -- break; -- } -- -- if (org_ip_request_cntl == 0) -- REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); --} -- --void dcn35_enable_power_gating_plane(struct dce_hwseq *hws, bool enable) --{ -- bool force_on = true; /* disable power gating */ -- uint32_t org_ip_request_cntl = 0; -- -- if (hws->ctx->dc->debug.disable_hubp_power_gate) -- return; -- if (hws->ctx->dc->debug.ignore_pg) -- return; -- REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl); -- if (org_ip_request_cntl == 0) -- REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); -- /* DCHUBP0/1/2/3/4/5 */ -- REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); -- REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); -- /* DPP0/1/2/3/4/5 */ -- REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); -- REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); -- -- force_on = true; /* disable power gating */ -- if (enable && !hws->ctx->dc->debug.disable_dsc_power_gate) -- force_on = false; -- -- /* DCS0/1/2/3/4 */ -- REG_UPDATE(DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); -- REG_UPDATE(DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); -- REG_UPDATE(DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); -- REG_UPDATE(DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); -- -- --} -- - /* In headless boot cases, DIG may be turned - * on which causes HW/SW discrepancies. - * To avoid this, power down hardware on boot -@@ -1047,6 +966,15 @@ void dcn35_calc_blocks_to_gate(struct dc - if (dc->caps.sequential_ono) { - update_state->pg_pipe_res_update[PG_HUBP][pipe_ctx->stream_res.dsc->inst] = false; - update_state->pg_pipe_res_update[PG_DPP][pipe_ctx->stream_res.dsc->inst] = false; -+ -+ /* All HUBP/DPP instances must be powered if the DSC inst != HUBP inst */ -+ if (!pipe_ctx->top_pipe && pipe_ctx->plane_res.hubp && -+ pipe_ctx->plane_res.hubp->inst != pipe_ctx->stream_res.dsc->inst) { -+ for (j = 0; j < dc->res_pool->pipe_count; ++j) { -+ update_state->pg_pipe_res_update[PG_HUBP][j] = false; -+ update_state->pg_pipe_res_update[PG_DPP][j] = false; -+ } -+ } - } - } - -@@ -1193,6 +1121,25 @@ void dcn35_calc_blocks_to_ungate(struct - update_state->pg_pipe_res_update[PG_HDMISTREAM][0] = true; - - if (dc->caps.sequential_ono) { -+ for (i = 0; i < dc->res_pool->pipe_count; i++) { -+ struct pipe_ctx *new_pipe = &context->res_ctx.pipe_ctx[i]; -+ -+ if (new_pipe->stream_res.dsc && !new_pipe->top_pipe && -+ update_state->pg_pipe_res_update[PG_DSC][new_pipe->stream_res.dsc->inst]) { -+ update_state->pg_pipe_res_update[PG_HUBP][new_pipe->stream_res.dsc->inst] = true; -+ update_state->pg_pipe_res_update[PG_DPP][new_pipe->stream_res.dsc->inst] = true; -+ -+ /* All HUBP/DPP instances must be powered if the DSC inst != HUBP inst */ -+ if (new_pipe->plane_res.hubp && -+ new_pipe->plane_res.hubp->inst != new_pipe->stream_res.dsc->inst) { -+ for (j = 0; j < dc->res_pool->pipe_count; ++j) { -+ update_state->pg_pipe_res_update[PG_HUBP][j] = true; -+ update_state->pg_pipe_res_update[PG_DPP][j] = true; -+ } -+ } -+ } -+ } -+ - for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { - if (update_state->pg_pipe_res_update[PG_HUBP][i] && - update_state->pg_pipe_res_update[PG_DPP][i]) { -@@ -1425,6 +1372,8 @@ void dcn35_prepare_bandwidth( - } - - dcn20_prepare_bandwidth(dc, context); -+ -+ print_pg_status(dc, __func__, ": after rcg and power up"); - } - - void dcn35_optimize_bandwidth( -@@ -1433,6 +1382,8 @@ void dcn35_optimize_bandwidth( - { - struct pg_block_update pg_update_state; - -+ print_pg_status(dc, __func__, ": before rcg and power up"); -+ - dcn20_optimize_bandwidth(dc, context); - - if (dc->hwss.calc_blocks_to_gate) { -@@ -1444,6 +1395,8 @@ void dcn35_optimize_bandwidth( - if (dc->hwss.root_clock_control) - dc->hwss.root_clock_control(dc, &pg_update_state, false); - } -+ -+ print_pg_status(dc, __func__, ": after rcg and power up"); - } - - void dcn35_set_drr(struct pipe_ctx **pipe_ctx, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c 2025-10-22 13:53:56.455169431 -0400 -@@ -115,7 +115,6 @@ static const struct hw_sequencer_funcs d - .exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state, - .update_visual_confirm_color = dcn10_update_visual_confirm_color, - .apply_idle_power_optimizations = dcn35_apply_idle_power_optimizations, -- .update_dsc_pg = dcn32_update_dsc_pg, - .calc_blocks_to_gate = dcn35_calc_blocks_to_gate, - .calc_blocks_to_ungate = dcn35_calc_blocks_to_ungate, - .hw_block_power_up = dcn35_hw_block_power_up, -@@ -150,7 +149,6 @@ static const struct hwseq_private_funcs - .plane_atomic_disable = dcn35_plane_atomic_disable, - //.plane_atomic_disable = dcn20_plane_atomic_disable,/*todo*/ - //.hubp_pg_control = dcn35_hubp_pg_control, -- .enable_power_gating_plane = dcn35_enable_power_gating_plane, - .dpp_root_clock_control = dcn35_dpp_root_clock_control, - .dpstream_root_clock_control = dcn35_dpstream_root_clock_control, - .physymclk_root_clock_control = dcn35_physymclk_root_clock_control, -@@ -165,7 +163,6 @@ static const struct hwseq_private_funcs - .calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values, - .resync_fifo_dccg_dio = dcn314_resync_fifo_dccg_dio, - .is_dp_dig_pixel_rate_div_policy = dcn35_is_dp_dig_pixel_rate_div_policy, -- .dsc_pg_control = dcn35_dsc_pg_control, - .dsc_pg_status = dcn32_dsc_pg_status, - .enable_plane = dcn35_enable_plane, - .wait_for_pipe_update_if_needed = dcn10_wait_for_pipe_update_if_needed, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c 2025-10-22 13:53:56.455169431 -0400 -@@ -114,7 +114,6 @@ static const struct hw_sequencer_funcs d - .exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state, - .update_visual_confirm_color = dcn10_update_visual_confirm_color, - .apply_idle_power_optimizations = dcn35_apply_idle_power_optimizations, -- .update_dsc_pg = dcn32_update_dsc_pg, - .calc_blocks_to_gate = dcn351_calc_blocks_to_gate, - .calc_blocks_to_ungate = dcn351_calc_blocks_to_ungate, - .hw_block_power_up = dcn351_hw_block_power_up, -@@ -145,7 +144,6 @@ static const struct hwseq_private_funcs - .plane_atomic_disable = dcn35_plane_atomic_disable, - //.plane_atomic_disable = dcn20_plane_atomic_disable,/*todo*/ - //.hubp_pg_control = dcn35_hubp_pg_control, -- .enable_power_gating_plane = dcn35_enable_power_gating_plane, - .dpp_root_clock_control = dcn35_dpp_root_clock_control, - .dpstream_root_clock_control = dcn35_dpstream_root_clock_control, - .physymclk_root_clock_control = dcn35_physymclk_root_clock_control, -@@ -159,7 +157,6 @@ static const struct hwseq_private_funcs - .setup_hpo_hw_control = dcn35_setup_hpo_hw_control, - .calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values, - .is_dp_dig_pixel_rate_div_policy = dcn35_is_dp_dig_pixel_rate_div_policy, -- .dsc_pg_control = dcn35_dsc_pg_control, - .dsc_pg_status = dcn32_dsc_pg_status, - .enable_plane = dcn35_enable_plane, - .wait_for_pipe_update_if_needed = dcn10_wait_for_pipe_update_if_needed, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c 2025-10-22 13:53:56.455169431 -0400 -@@ -2289,10 +2289,8 @@ void dcn401_program_pipe( - * updating on slave planes - */ - if (pipe_ctx->update_flags.bits.enable || -- pipe_ctx->update_flags.bits.plane_changed || -- pipe_ctx->stream->update_flags.bits.out_tf || -- (pipe_ctx->plane_state && -- pipe_ctx->plane_state->update_flags.bits.output_tf_change)) -+ pipe_ctx->update_flags.bits.plane_changed || -+ pipe_ctx->stream->update_flags.bits.out_tf) - hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream); - - /* If the pipe has been enabled or has a different opp, we -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h 2025-10-22 13:53:56.455169431 -0400 -@@ -349,6 +349,9 @@ struct dpp_funcs { - struct dpp *dpp_base, - enum dc_color_space color_space, - struct dc_csc_transform cursor_csc_color_matrix); -+ -+ void (*dpp_force_disable_cursor)(struct dpp *dpp_base); -+ - }; - - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/inc/hw/pg_cntl.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/inc/hw/pg_cntl.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/inc/hw/pg_cntl.h 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/inc/hw/pg_cntl.h 2025-10-22 13:53:56.455169431 -0400 -@@ -47,6 +47,7 @@ struct pg_cntl_funcs { - void (*optc_pg_control)(struct pg_cntl *pg_cntl, unsigned int optc_inst, bool power_on); - void (*dwb_pg_control)(struct pg_cntl *pg_cntl, bool power_on); - void (*init_pg_status)(struct pg_cntl *pg_cntl); -+ void (*print_pg_status)(struct pg_cntl *pg_cntl, const char *debug_func, const char *debug_log); - }; - - #endif //__DC_PG_CNTL_H__ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/link/link_dpms.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/link/link_dpms.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/link/link_dpms.c 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/link/link_dpms.c 2025-10-22 13:53:56.455169431 -0400 -@@ -140,7 +140,8 @@ void link_blank_dp_stream(struct dc_link - } - } - -- if ((!link->wa_flags.dp_keep_receiver_powered) || hw_init) -+ if (((!link->wa_flags.dp_keep_receiver_powered) || hw_init) && -+ (link->type != dc_connection_none)) - dpcd_write_rx_power_ctrl(link, false); - } - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c 2025-10-22 13:53:56.455169431 -0400 -@@ -385,9 +385,15 @@ bool dp_is_128b_132b_signal(struct pipe_ - bool dp_is_lttpr_present(struct dc_link *link) - { - /* Some sink devices report invalid LTTPR revision, so don't validate against that cap */ -- return (dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) != 0 && -+ uint32_t lttpr_count = dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt); -+ bool is_lttpr_present = (lttpr_count > 0 && - link->dpcd_caps.lttpr_caps.max_lane_count > 0 && - link->dpcd_caps.lttpr_caps.max_lane_count <= 4); -+ -+ if (lttpr_count > 0 && !is_lttpr_present) -+ DC_LOG_ERROR("LTTPR count is nonzero but invalid lane count reported. Assuming no LTTPR present.\n"); -+ -+ return is_lttpr_present; - } - - /* in DP compliance test, DPR-120 may have -@@ -1551,6 +1557,8 @@ enum dc_status dp_retrieve_lttpr_cap(str - uint8_t lttpr_dpcd_data[10] = {0}; - enum dc_status status; - bool is_lttpr_present; -+ uint32_t lttpr_count; -+ uint32_t closest_lttpr_offset; - - /* Logic to determine LTTPR support*/ - bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware; -@@ -1602,20 +1610,22 @@ enum dc_status dp_retrieve_lttpr_cap(str - lttpr_dpcd_data[DP_LTTPR_ALPM_CAPABILITIES - - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; - -+ lttpr_count = dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt); -+ - /* If this chip cap is set, at least one retimer must exist in the chain - * Override count to 1 if we receive a known bad count (0 or an invalid value) */ - if (((link->chip_caps & AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK) == AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && -- (dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == 0)) { -+ lttpr_count == 0) { - /* If you see this message consistently, either the host platform has FIXED_VS flag - * incorrectly configured or the sink device is returning an invalid count. - */ - DC_LOG_ERROR("lttpr_caps phy_repeater_cnt is 0x%x, forcing it to 0x80.", - link->dpcd_caps.lttpr_caps.phy_repeater_cnt); - link->dpcd_caps.lttpr_caps.phy_repeater_cnt = 0x80; -+ lttpr_count = 1; - DC_LOG_DC("lttpr_caps forced phy_repeater_cnt = %d\n", link->dpcd_caps.lttpr_caps.phy_repeater_cnt); - } - -- /* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */ - is_lttpr_present = dp_is_lttpr_present(link); - - DC_LOG_DC("is_lttpr_present = %d\n", is_lttpr_present); -@@ -1623,11 +1633,25 @@ enum dc_status dp_retrieve_lttpr_cap(str - if (is_lttpr_present) { - CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: "); - -- core_link_read_dpcd(link, DP_LTTPR_IEEE_OUI, link->dpcd_caps.lttpr_caps.lttpr_ieee_oui, sizeof(link->dpcd_caps.lttpr_caps.lttpr_ieee_oui)); -- CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_ieee_oui, sizeof(link->dpcd_caps.lttpr_caps.lttpr_ieee_oui), "LTTPR IEEE OUI: "); -+ // Identify closest LTTPR to determine if workarounds required for known embedded LTTPR -+ closest_lttpr_offset = dp_get_closest_lttpr_offset(lttpr_count); - -- core_link_read_dpcd(link, DP_LTTPR_DEVICE_ID, link->dpcd_caps.lttpr_caps.lttpr_device_id, sizeof(link->dpcd_caps.lttpr_caps.lttpr_device_id)); -- CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_device_id, sizeof(link->dpcd_caps.lttpr_caps.lttpr_device_id), "LTTPR Device ID: "); -+ core_link_read_dpcd(link, (DP_LTTPR_IEEE_OUI + closest_lttpr_offset), -+ link->dpcd_caps.lttpr_caps.lttpr_ieee_oui, sizeof(link->dpcd_caps.lttpr_caps.lttpr_ieee_oui)); -+ core_link_read_dpcd(link, (DP_LTTPR_DEVICE_ID + closest_lttpr_offset), -+ link->dpcd_caps.lttpr_caps.lttpr_device_id, sizeof(link->dpcd_caps.lttpr_caps.lttpr_device_id)); -+ -+ if (lttpr_count > 1) { -+ CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_ieee_oui, sizeof(link->dpcd_caps.lttpr_caps.lttpr_ieee_oui), -+ "Closest LTTPR To Host's IEEE OUI: "); -+ CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_device_id, sizeof(link->dpcd_caps.lttpr_caps.lttpr_device_id), -+ "Closest LTTPR To Host's LTTPR Device ID: "); -+ } else { -+ CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_ieee_oui, sizeof(link->dpcd_caps.lttpr_caps.lttpr_ieee_oui), -+ "LTTPR IEEE OUI: "); -+ CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_device_id, sizeof(link->dpcd_caps.lttpr_caps.lttpr_device_id), -+ "LTTPR Device ID: "); -+ } - } - - return status; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c 2025-10-22 13:53:56.455169431 -0400 -@@ -561,7 +561,7 @@ void mpc401_get_gamut_remap(struct mpc * - struct mpc_grph_gamut_adjustment *adjust) - { - uint16_t arr_reg_val[12] = {0}; -- uint32_t mode_select; -+ uint32_t mode_select = MPCC_GAMUT_REMAP_MODE_SELECT_0; - - read_gamut_remap(mpc, mpcc_id, arr_reg_val, adjust->mpcc_gamut_remap_block_id, &mode_select); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/pg/dcn35/dcn35_pg_cntl.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/pg/dcn35/dcn35_pg_cntl.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/pg/dcn35/dcn35_pg_cntl.c 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/pg/dcn35/dcn35_pg_cntl.c 2025-10-22 13:53:56.455169431 -0400 -@@ -79,16 +79,12 @@ void pg_cntl35_dsc_pg_control(struct pg_ - uint32_t power_gate = power_on ? 0 : 1; - uint32_t pwr_status = power_on ? 0 : 2; - uint32_t org_ip_request_cntl = 0; -- bool block_enabled; -- -- /*need to enable dscclk regardless DSC_PG*/ -- if (pg_cntl->ctx->dc->res_pool->dccg->funcs->enable_dsc && power_on) -- pg_cntl->ctx->dc->res_pool->dccg->funcs->enable_dsc( -- pg_cntl->ctx->dc->res_pool->dccg, dsc_inst); -+ bool block_enabled = false; -+ bool skip_pg = pg_cntl->ctx->dc->debug.ignore_pg || -+ pg_cntl->ctx->dc->debug.disable_dsc_power_gate || -+ pg_cntl->ctx->dc->idle_optimizations_allowed; - -- if (pg_cntl->ctx->dc->debug.ignore_pg || -- pg_cntl->ctx->dc->debug.disable_dsc_power_gate || -- pg_cntl->ctx->dc->idle_optimizations_allowed) -+ if (skip_pg && !power_on) - return; - - block_enabled = pg_cntl35_dsc_pg_status(pg_cntl, dsc_inst); -@@ -111,7 +107,7 @@ void pg_cntl35_dsc_pg_control(struct pg_ - - REG_WAIT(DOMAIN16_PG_STATUS, - DOMAIN_PGFSM_PWR_STATUS, pwr_status, -- 1, 1000); -+ 1, 10000); - break; - case 1: /* DSC1 */ - REG_UPDATE(DOMAIN17_PG_CONFIG, -@@ -119,7 +115,7 @@ void pg_cntl35_dsc_pg_control(struct pg_ - - REG_WAIT(DOMAIN17_PG_STATUS, - DOMAIN_PGFSM_PWR_STATUS, pwr_status, -- 1, 1000); -+ 1, 10000); - break; - case 2: /* DSC2 */ - REG_UPDATE(DOMAIN18_PG_CONFIG, -@@ -127,7 +123,7 @@ void pg_cntl35_dsc_pg_control(struct pg_ - - REG_WAIT(DOMAIN18_PG_STATUS, - DOMAIN_PGFSM_PWR_STATUS, pwr_status, -- 1, 1000); -+ 1, 10000); - break; - case 3: /* DSC3 */ - REG_UPDATE(DOMAIN19_PG_CONFIG, -@@ -135,7 +131,7 @@ void pg_cntl35_dsc_pg_control(struct pg_ - - REG_WAIT(DOMAIN19_PG_STATUS, - DOMAIN_PGFSM_PWR_STATUS, pwr_status, -- 1, 1000); -+ 1, 10000); - break; - default: - BREAK_TO_DEBUGGER(); -@@ -144,12 +140,6 @@ void pg_cntl35_dsc_pg_control(struct pg_ - - if (dsc_inst < MAX_PIPES) - pg_cntl->pg_pipe_res_enable[PG_DSC][dsc_inst] = power_on; -- -- if (pg_cntl->ctx->dc->res_pool->dccg->funcs->disable_dsc && !power_on) { -- /*this is to disable dscclk*/ -- pg_cntl->ctx->dc->res_pool->dccg->funcs->disable_dsc( -- pg_cntl->ctx->dc->res_pool->dccg, dsc_inst); -- } - } - - static bool pg_cntl35_hubp_dpp_pg_status(struct pg_cntl *pg_cntl, unsigned int hubp_dpp_inst) -@@ -189,11 +179,12 @@ void pg_cntl35_hubp_dpp_pg_control(struc - uint32_t pwr_status = power_on ? 0 : 2; - uint32_t org_ip_request_cntl; - bool block_enabled; -+ bool skip_pg = pg_cntl->ctx->dc->debug.ignore_pg || -+ pg_cntl->ctx->dc->debug.disable_hubp_power_gate || -+ pg_cntl->ctx->dc->debug.disable_dpp_power_gate || -+ pg_cntl->ctx->dc->idle_optimizations_allowed; - -- if (pg_cntl->ctx->dc->debug.ignore_pg || -- pg_cntl->ctx->dc->debug.disable_hubp_power_gate || -- pg_cntl->ctx->dc->debug.disable_dpp_power_gate || -- pg_cntl->ctx->dc->idle_optimizations_allowed) -+ if (skip_pg && !power_on) - return; - - block_enabled = pg_cntl35_hubp_dpp_pg_status(pg_cntl, hubp_dpp_inst); -@@ -213,22 +204,22 @@ void pg_cntl35_hubp_dpp_pg_control(struc - case 0: - /* DPP0 & HUBP0 */ - REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, power_gate); -- REG_WAIT(DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000); -+ REG_WAIT(DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 10000); - break; - case 1: - /* DPP1 & HUBP1 */ - REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, power_gate); -- REG_WAIT(DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000); -+ REG_WAIT(DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 10000); - break; - case 2: - /* DPP2 & HUBP2 */ - REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, power_gate); -- REG_WAIT(DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000); -+ REG_WAIT(DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 10000); - break; - case 3: - /* DPP3 & HUBP3 */ - REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, power_gate); -- REG_WAIT(DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000); -+ REG_WAIT(DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 10000); - break; - default: - BREAK_TO_DEBUGGER(); -@@ -501,6 +492,36 @@ void pg_cntl35_init_pg_status(struct pg_ - pg_cntl->pg_res_enable[PG_DWB] = block_enabled; - } - -+static void pg_cntl35_print_pg_status(struct pg_cntl *pg_cntl, const char *debug_func, const char *debug_log) -+{ -+ int i = 0; -+ bool block_enabled = false; -+ -+ DC_LOG_DEBUG("%s: %s", debug_func, debug_log); -+ -+ DC_LOG_DEBUG("PG_CNTL status:\n"); -+ -+ block_enabled = pg_cntl35_io_clk_status(pg_cntl); -+ DC_LOG_DEBUG("ONO0=%d (DCCG, DIO, DCIO)\n", block_enabled ? 1 : 0); -+ -+ block_enabled = pg_cntl35_mem_status(pg_cntl); -+ DC_LOG_DEBUG("ONO1=%d (DCHUBBUB, DCHVM, DCHUBBUBMEM)\n", block_enabled ? 1 : 0); -+ -+ block_enabled = pg_cntl35_plane_otg_status(pg_cntl); -+ DC_LOG_DEBUG("ONO2=%d (MPC, OPP, OPTC, DWB)\n", block_enabled ? 1 : 0); -+ -+ block_enabled = pg_cntl35_hpo_pg_status(pg_cntl); -+ DC_LOG_DEBUG("ONO3=%d (HPO)\n", block_enabled ? 1 : 0); -+ -+ for (i = 0; i < pg_cntl->ctx->dc->res_pool->pipe_count; i++) { -+ block_enabled = pg_cntl35_hubp_dpp_pg_status(pg_cntl, i); -+ DC_LOG_DEBUG("ONO%d=%d (DCHUBP%d, DPP%d)\n", 4 + i * 2, block_enabled ? 1 : 0, i, i); -+ -+ block_enabled = pg_cntl35_dsc_pg_status(pg_cntl, i); -+ DC_LOG_DEBUG("ONO%d=%d (DSC%d)\n", 5 + i * 2, block_enabled ? 1 : 0, i); -+ } -+} -+ - static const struct pg_cntl_funcs pg_cntl35_funcs = { - .init_pg_status = pg_cntl35_init_pg_status, - .dsc_pg_control = pg_cntl35_dsc_pg_control, -@@ -511,7 +532,8 @@ static const struct pg_cntl_funcs pg_cnt - .mpcc_pg_control = pg_cntl35_mpcc_pg_control, - .opp_pg_control = pg_cntl35_opp_pg_control, - .optc_pg_control = pg_cntl35_optc_pg_control, -- .dwb_pg_control = pg_cntl35_dwb_pg_control -+ .dwb_pg_control = pg_cntl35_dwb_pg_control, -+ .print_pg_status = pg_cntl35_print_pg_status - }; - - struct pg_cntl *pg_cntl35_create( -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c 2025-10-22 13:53:56.455169431 -0400 -@@ -373,7 +373,7 @@ static const struct resource_caps res_ca - .num_timing_generator = 6, - .num_audio = 6, - .num_stream_encoder = 6, -- .num_pll = 2, -+ .num_pll = 3, - .num_ddc = 6, - }; - -@@ -389,7 +389,7 @@ static const struct resource_caps res_ca - .num_timing_generator = 2, - .num_audio = 2, - .num_stream_encoder = 2, -- .num_pll = 2, -+ .num_pll = 3, - .num_ddc = 2, - }; - -@@ -973,21 +973,24 @@ static bool dce60_construct( - - if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) { - pool->base.dp_clock_source = -- dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); -+ dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); - -+ /* DCE 6.0 and 6.4: PLL0 can only be used with DP. Don't initialize it here. */ - pool->base.clock_sources[0] = -- dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], false); -+ dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); - pool->base.clock_sources[1] = -- dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); -+ dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); - pool->base.clk_src_count = 2; - - } else { - pool->base.dp_clock_source = -- dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true); -+ dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true); - - pool->base.clock_sources[0] = -- dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); -- pool->base.clk_src_count = 1; -+ dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); -+ pool->base.clock_sources[1] = -+ dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); -+ pool->base.clk_src_count = 2; - } - - if (pool->base.dp_clock_source == NULL) { -@@ -1365,21 +1368,24 @@ static bool dce64_construct( - - if (bp->fw_info_valid && bp->fw_info.external_clock_source_frequency_for_dp != 0) { - pool->base.dp_clock_source = -- dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); -+ dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_EXTERNAL, NULL, true); - -+ /* DCE 6.0 and 6.4: PLL0 can only be used with DP. Don't initialize it here. */ - pool->base.clock_sources[0] = -- dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], false); -+ dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); - pool->base.clock_sources[1] = -- dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false); -+ dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); - pool->base.clk_src_count = 2; - - } else { - pool->base.dp_clock_source = -- dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[0], true); -+ dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL0, &clk_src_regs[0], true); - - pool->base.clock_sources[0] = -- dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[1], false); -- pool->base.clk_src_count = 1; -+ dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL1, &clk_src_regs[1], false); -+ pool->base.clock_sources[1] = -+ dce60_clock_source_create(ctx, bp, CLOCK_SOURCE_ID_PLL2, &clk_src_regs[2], false); -+ pool->base.clk_src_count = 2; - } - - if (pool->base.dp_clock_source == NULL) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c 2025-10-22 13:53:56.459169411 -0400 -@@ -1954,6 +1954,9 @@ static bool dcn31_resource_construct( - dc->caps.color.mpc.ogam_rom_caps.hlg = 0; - dc->caps.color.mpc.ocsc = 1; - -+ dc->caps.num_of_host_routers = 2; -+ dc->caps.num_of_dpias_per_host_router = 2; -+ - /* Use pipe context based otg sync logic */ - dc->config.use_pipe_ctx_sync_logic = true; - dc->config.disable_hbr_audio_dp2 = true; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c 2025-10-22 13:53:56.459169411 -0400 -@@ -926,6 +926,7 @@ static const struct dc_debug_options deb - .seamless_boot_odm_combine = true, - .enable_legacy_fast_update = true, - .using_dml2 = false, -+ .disable_dsc_power_gate = true, - }; - - static const struct dc_panel_config panel_config_defaults = { -@@ -1885,6 +1886,9 @@ static bool dcn314_resource_construct( - - dc->caps.max_disp_clock_khz_at_vmin = 650000; - -+ dc->caps.num_of_host_routers = 2; -+ dc->caps.num_of_dpias_per_host_router = 2; -+ - /* Use pipe context based otg sync logic */ - dc->config.use_pipe_ctx_sync_logic = true; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c 2025-10-22 13:53:56.459169411 -0400 -@@ -1894,6 +1894,9 @@ static bool dcn35_resource_construct( - dc->caps.color.mpc.ogam_rom_caps.hlg = 0; - dc->caps.color.mpc.ocsc = 1; - -+ dc->caps.num_of_host_routers = 2; -+ dc->caps.num_of_dpias_per_host_router = 2; -+ - /* max_disp_clock_khz_at_vmin is slightly lower than the STA value in order - * to provide some margin. - * It's expected for furture ASIC to have equal or higher value, in order to -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c 2025-10-22 13:53:56.459169411 -0400 -@@ -1866,6 +1866,9 @@ static bool dcn351_resource_construct( - dc->caps.color.mpc.ogam_rom_caps.hlg = 0; - dc->caps.color.mpc.ocsc = 1; - -+ dc->caps.num_of_host_routers = 2; -+ dc->caps.num_of_dpias_per_host_router = 2; -+ - /* max_disp_clock_khz_at_vmin is slightly lower than the STA value in order - * to provide some margin. - * It's expected for furture ASIC to have equal or higher value, in order to -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c 2025-10-22 13:53:56.459169411 -0400 -@@ -1867,6 +1867,9 @@ static bool dcn36_resource_construct( - dc->caps.color.mpc.ogam_rom_caps.hlg = 0; - dc->caps.color.mpc.ocsc = 1; - -+ dc->caps.num_of_host_routers = 2; -+ dc->caps.num_of_dpias_per_host_router = 2; -+ - /* max_disp_clock_khz_at_vmin is slightly lower than the STA value in order - * to provide some margin. - * It's expected for furture ASIC to have equal or higher value, in order to -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c 2025-10-22 13:53:56.459169411 -0400 -@@ -92,19 +92,15 @@ void dmub_dcn35_reset(struct dmub_srv *d - uint32_t in_reset, is_enabled, scratch, i, pwait_mode; - - REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset); -+ REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_enabled); - -- if (in_reset == 0) { -+ if (in_reset == 0 && is_enabled != 0) { - cmd.bits.status = 1; - cmd.bits.command_code = DMUB_GPINT__STOP_FW; - cmd.bits.param = 0; - - dmub->hw_funcs.set_gpint(dmub, cmd); - -- /** -- * Timeout covers both the ACK and the wait -- * for remaining work to finish. -- */ -- - for (i = 0; i < timeout; ++i) { - if (dmub->hw_funcs.is_gpint_acked(dmub, cmd)) - break; -@@ -130,11 +126,9 @@ void dmub_dcn35_reset(struct dmub_srv *d - /* Force reset in case we timed out, DMCUB is likely hung. */ - } - -- REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_enabled); -- - if (is_enabled) { - REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1); -- REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); -+ udelay(1); - REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0); - } - -@@ -160,11 +154,7 @@ void dmub_dcn35_reset_release(struct dmu - LONO_SOCCLK_GATE_DISABLE, 1, - LONO_DMCUBCLK_GATE_DISABLE, 1); - -- REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1); -- udelay(1); - REG_UPDATE_2(DMCUB_CNTL, DMCUB_ENABLE, 1, DMCUB_TRACEPORT_EN, 1); -- REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1); -- udelay(1); - REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 0); - REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 0); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/modules/freesync/freesync.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/modules/freesync/freesync.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/modules/freesync/freesync.c 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/modules/freesync/freesync.c 2025-10-22 13:53:56.459169411 -0400 -@@ -155,6 +155,14 @@ unsigned int mod_freesync_calc_v_total_f - v_total = div64_u64(div64_u64(((unsigned long long)( - frame_duration_in_ns) * (stream->timing.pix_clk_100hz / 10)), - stream->timing.h_total), 1000000); -+ } else if (refresh_in_uhz >= stream->timing.max_refresh_in_uhz) { -+ /* When the target refresh rate is the maximum panel refresh rate -+ * round up the vtotal value to prevent off-by-one error causing -+ * v_total_min to be below the panel's lower bound -+ */ -+ v_total = div64_u64(div64_u64(((unsigned long long)( -+ frame_duration_in_ns) * (stream->timing.pix_clk_100hz / 10)), -+ stream->timing.h_total) + (1000000 - 1), 1000000); - } else { - v_total = div64_u64(div64_u64(((unsigned long long)( - frame_duration_in_ns) * (stream->timing.pix_clk_100hz / 10)), -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c 2025-10-22 13:53:56.459169411 -0400 -@@ -260,6 +260,9 @@ enum mod_hdcp_status mod_hdcp_hdcp1_crea - return MOD_HDCP_STATUS_FAILURE; - } - -+ if (!display) -+ return MOD_HDCP_STATUS_DISPLAY_NOT_FOUND; -+ - hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf; - - mutex_lock(&psp->hdcp_context.mutex); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/include/mes_v11_api_def.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/include/mes_v11_api_def.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/include/mes_v11_api_def.h 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/include/mes_v11_api_def.h 2025-10-22 13:53:56.459169411 -0400 -@@ -238,7 +238,8 @@ union MESAPI_SET_HW_RESOURCES { - uint32_t enable_mes_sch_stb_log : 1; - uint32_t limit_single_process : 1; - uint32_t is_strix_tmz_wa_enabled :1; -- uint32_t reserved : 13; -+ uint32_t enable_lr_compute_wa : 1; -+ uint32_t reserved : 12; - }; - uint32_t uint32_t_all; - }; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/include/mes_v12_api_def.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/include/mes_v12_api_def.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/include/mes_v12_api_def.h 2025-10-22 13:53:23.215329125 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/include/mes_v12_api_def.h 2025-10-22 13:53:56.459169411 -0400 -@@ -286,7 +286,8 @@ union MESAPI_SET_HW_RESOURCES { - uint32_t limit_single_process : 1; - uint32_t unmapped_doorbell_handling: 2; - uint32_t enable_mes_fence_int: 1; -- uint32_t reserved : 10; -+ uint32_t enable_lr_compute_wa : 1; -+ uint32_t reserved : 9; - }; - uint32_t uint32_all; - }; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/pm/amdgpu_pm.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/pm/amdgpu_pm.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/pm/amdgpu_pm.c 2025-10-22 13:53:23.219329106 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/pm/amdgpu_pm.c 2025-10-22 13:53:56.459169411 -0400 -@@ -1398,6 +1398,8 @@ static ssize_t amdgpu_set_pp_power_profi - if (ret) - return -EINVAL; - parameter_size++; -+ if (!tmp_str) -+ break; - while (isspace(*tmp_str)) - tmp_str++; - } -@@ -3456,14 +3458,16 @@ static umode_t hwmon_attributes_visible( - effective_mode &= ~S_IWUSR; - - /* not implemented yet for APUs other than GC 10.3.1 (vangogh) and 9.4.3 */ -- if (((adev->family == AMDGPU_FAMILY_SI) || -- ((adev->flags & AMD_IS_APU) && (gc_ver != IP_VERSION(10, 3, 1)) && -- (gc_ver != IP_VERSION(9, 4, 3) && gc_ver != IP_VERSION(9, 4, 4)))) && -- (attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr || -- attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr || -- attr == &sensor_dev_attr_power1_cap.dev_attr.attr || -- attr == &sensor_dev_attr_power1_cap_default.dev_attr.attr)) -- return 0; -+ if (attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr || -+ attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr || -+ attr == &sensor_dev_attr_power1_cap.dev_attr.attr || -+ attr == &sensor_dev_attr_power1_cap_default.dev_attr.attr) { -+ if (adev->family == AMDGPU_FAMILY_SI || -+ ((adev->flags & AMD_IS_APU) && gc_ver != IP_VERSION(10, 3, 1) && -+ (gc_ver != IP_VERSION(9, 4, 3) && gc_ver != IP_VERSION(9, 4, 4))) || -+ (amdgpu_sriov_vf(adev) && gc_ver == IP_VERSION(11, 0, 3))) -+ return 0; -+ } - - /* not implemented yet for APUs having < GC 9.3.0 (Renoir) */ - if (((adev->family == AMDGPU_FAMILY_SI) || -@@ -3645,6 +3649,9 @@ static int parse_input_od_command_lines( - return -EINVAL; - parameter_size++; - -+ if (!tmp_str) -+ break; -+ - while (isspace(*tmp_str)) - tmp_str++; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c 2025-10-22 13:53:23.219329106 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c 2025-10-22 13:53:56.459169411 -0400 -@@ -149,7 +149,7 @@ int phm_wait_on_indirect_register(struct - } - - cgs_write_register(hwmgr->device, indirect_port, index); -- return phm_wait_on_register(hwmgr, indirect_port + 1, mask, value); -+ return phm_wait_on_register(hwmgr, indirect_port + 1, value, mask); - } - - int phm_wait_for_register_unequal(struct pp_hwmgr *hwmgr, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c 2025-10-22 13:53:23.219329106 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c 2025-10-22 13:53:56.459169411 -0400 -@@ -76,6 +76,9 @@ static void smu_power_profile_mode_get(s - enum PP_SMC_POWER_PROFILE profile_mode); - static void smu_power_profile_mode_put(struct smu_context *smu, - enum PP_SMC_POWER_PROFILE profile_mode); -+static int smu_od_edit_dpm_table(void *handle, -+ enum PP_OD_DPM_TABLE_COMMAND type, -+ long *input, uint32_t size); - - static int smu_sys_get_pp_feature_mask(void *handle, - char *buf) -@@ -2144,6 +2147,7 @@ static int smu_resume(struct amdgpu_ip_b - int ret; - struct amdgpu_device *adev = ip_block->adev; - struct smu_context *smu = adev->powerplay.pp_handle; -+ struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); - - if (amdgpu_sriov_multi_vf_mode(adev)) - return 0; -@@ -2175,6 +2179,18 @@ static int smu_resume(struct amdgpu_ip_b - - adev->pm.dpm_enabled = true; - -+ if (smu->current_power_limit) { -+ ret = smu_set_power_limit(smu, smu->current_power_limit); -+ if (ret && ret != -EOPNOTSUPP) -+ return ret; -+ } -+ -+ if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL && smu->od_enabled) { -+ ret = smu_od_edit_dpm_table(smu, PP_OD_COMMIT_DPM_TABLE, NULL, 0); -+ if (ret) -+ return ret; -+ } -+ - dev_info(adev->dev, "SMU is resumed successfully!\n"); - - return 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c 2025-10-22 13:53:23.219329106 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c 2025-10-22 13:53:56.459169411 -0400 -@@ -666,7 +666,6 @@ static int vangogh_print_clk_levels(stru - { - DpmClocks_t *clk_table = smu->smu_table.clocks_table; - SmuMetrics_t metrics; -- struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); - int i, idx, size = 0, ret = 0; - uint32_t cur_value = 0, value = 0, count = 0; - bool cur_value_match_level = false; -@@ -682,31 +681,25 @@ static int vangogh_print_clk_levels(stru - - switch (clk_type) { - case SMU_OD_SCLK: -- if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { -- size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK"); -- size += sysfs_emit_at(buf, size, "0: %10uMhz\n", -- (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq); -- size += sysfs_emit_at(buf, size, "1: %10uMhz\n", -- (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq); -- } -+ size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK"); -+ size += sysfs_emit_at(buf, size, "0: %10uMhz\n", -+ (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq); -+ size += sysfs_emit_at(buf, size, "1: %10uMhz\n", -+ (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq); - break; - case SMU_OD_CCLK: -- if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { -- size += sysfs_emit_at(buf, size, "CCLK_RANGE in Core%d:\n", smu->cpu_core_id_select); -- size += sysfs_emit_at(buf, size, "0: %10uMhz\n", -- (smu->cpu_actual_soft_min_freq > 0) ? smu->cpu_actual_soft_min_freq : smu->cpu_default_soft_min_freq); -- size += sysfs_emit_at(buf, size, "1: %10uMhz\n", -- (smu->cpu_actual_soft_max_freq > 0) ? smu->cpu_actual_soft_max_freq : smu->cpu_default_soft_max_freq); -- } -+ size += sysfs_emit_at(buf, size, "CCLK_RANGE in Core%d:\n", smu->cpu_core_id_select); -+ size += sysfs_emit_at(buf, size, "0: %10uMhz\n", -+ (smu->cpu_actual_soft_min_freq > 0) ? smu->cpu_actual_soft_min_freq : smu->cpu_default_soft_min_freq); -+ size += sysfs_emit_at(buf, size, "1: %10uMhz\n", -+ (smu->cpu_actual_soft_max_freq > 0) ? smu->cpu_actual_soft_max_freq : smu->cpu_default_soft_max_freq); - break; - case SMU_OD_RANGE: -- if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { -- size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); -- size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", -- smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq); -- size += sysfs_emit_at(buf, size, "CCLK: %7uMhz %10uMhz\n", -- smu->cpu_default_soft_min_freq, smu->cpu_default_soft_max_freq); -- } -+ size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); -+ size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", -+ smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq); -+ size += sysfs_emit_at(buf, size, "CCLK: %7uMhz %10uMhz\n", -+ smu->cpu_default_soft_min_freq, smu->cpu_default_soft_max_freq); - break; - case SMU_SOCCLK: - /* the level 3 ~ 6 of socclk use the same frequency for vangogh */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c 2025-10-22 13:53:23.219329106 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c 2025-10-22 13:53:56.459169411 -0400 -@@ -58,6 +58,7 @@ - - MODULE_FIRMWARE("amdgpu/aldebaran_smc.bin"); - MODULE_FIRMWARE("amdgpu/smu_13_0_0.bin"); -+MODULE_FIRMWARE("amdgpu/smu_13_0_0_kicker.bin"); - MODULE_FIRMWARE("amdgpu/smu_13_0_7.bin"); - MODULE_FIRMWARE("amdgpu/smu_13_0_10.bin"); - -@@ -92,7 +93,7 @@ const int pmfw_decoded_link_width[7] = { - int smu_v13_0_init_microcode(struct smu_context *smu) - { - struct amdgpu_device *adev = smu->adev; -- char ucode_prefix[15]; -+ char ucode_prefix[30]; - int err = 0; - const struct smc_firmware_header_v1_0 *hdr; - const struct common_firmware_header *header; -@@ -103,8 +104,13 @@ int smu_v13_0_init_microcode(struct smu_ - return 0; - - amdgpu_ucode_ip_version_decode(adev, MP1_HWIP, ucode_prefix, sizeof(ucode_prefix)); -- err = amdgpu_ucode_request(adev, &adev->pm.fw, AMDGPU_UCODE_REQUIRED, -- "amdgpu/%s.bin", ucode_prefix); -+ -+ if (amdgpu_is_kicker_fw(adev)) -+ err = amdgpu_ucode_request(adev, &adev->pm.fw, AMDGPU_UCODE_REQUIRED, -+ "amdgpu/%s_kicker.bin", ucode_prefix); -+ else -+ err = amdgpu_ucode_request(adev, &adev->pm.fw, AMDGPU_UCODE_REQUIRED, -+ "amdgpu/%s.bin", ucode_prefix); - if (err) - goto out; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c 2025-10-22 13:53:23.219329106 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c 2025-10-22 13:53:56.459169411 -0400 -@@ -1689,9 +1689,11 @@ static int smu_v14_0_2_get_power_limit(s - uint32_t *min_power_limit) - { - struct smu_table_context *table_context = &smu->smu_table; -+ struct smu_14_0_2_powerplay_table *powerplay_table = -+ table_context->power_play_table; - PPTable_t *pptable = table_context->driver_pptable; - CustomSkuTable_t *skutable = &pptable->CustomSkuTable; -- uint32_t power_limit; -+ uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0; - uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC]; - - if (smu_v14_0_get_current_power_limit(smu, &power_limit)) -@@ -1704,11 +1706,29 @@ static int smu_v14_0_2_get_power_limit(s - if (default_power_limit) - *default_power_limit = power_limit; - -- if (max_power_limit) -- *max_power_limit = msg_limit; -+ if (powerplay_table) { -+ if (smu->od_enabled && -+ smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) { -+ od_percent_upper = pptable->SkuTable.OverDriveLimitsBasicMax.Ppt; -+ od_percent_lower = pptable->SkuTable.OverDriveLimitsBasicMin.Ppt; -+ } else if (smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) { -+ od_percent_upper = 0; -+ od_percent_lower = pptable->SkuTable.OverDriveLimitsBasicMin.Ppt; -+ } -+ } - -- if (min_power_limit) -- *min_power_limit = 0; -+ dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n", -+ od_percent_upper, od_percent_lower, power_limit); -+ -+ if (max_power_limit) { -+ *max_power_limit = msg_limit * (100 + od_percent_upper); -+ *max_power_limit /= 100; -+ } -+ -+ if (min_power_limit) { -+ *min_power_limit = power_limit * (100 + od_percent_lower); -+ *min_power_limit /= 100; -+ } - - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c 2025-10-22 13:53:23.219329106 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c 2025-10-22 13:53:56.459169411 -0400 -@@ -62,13 +62,14 @@ const int decoded_link_width[8] = {0, 1, - - MODULE_FIRMWARE("amdgpu/smu_14_0_2.bin"); - MODULE_FIRMWARE("amdgpu/smu_14_0_3.bin"); -+MODULE_FIRMWARE("amdgpu/smu_14_0_3_kicker.bin"); - - #define ENABLE_IMU_ARG_GFXOFF_ENABLE 1 - - int smu_v14_0_init_microcode(struct smu_context *smu) - { - struct amdgpu_device *adev = smu->adev; -- char ucode_prefix[15]; -+ char ucode_prefix[30]; - int err = 0; - const struct smc_firmware_header_v1_0 *hdr; - const struct common_firmware_header *header; -@@ -79,8 +80,12 @@ int smu_v14_0_init_microcode(struct smu_ - return 0; - - amdgpu_ucode_ip_version_decode(adev, MP1_HWIP, ucode_prefix, sizeof(ucode_prefix)); -- err = amdgpu_ucode_request(adev, &adev->pm.fw, AMDGPU_UCODE_REQUIRED, -- "amdgpu/%s.bin", ucode_prefix); -+ if (amdgpu_is_kicker_fw(adev)) -+ err = amdgpu_ucode_request(adev, &adev->pm.fw, AMDGPU_UCODE_REQUIRED, -+ "amdgpu/%s_kicker.bin", ucode_prefix); -+ else -+ err = amdgpu_ucode_request(adev, &adev->pm.fw, AMDGPU_UCODE_REQUIRED, -+ "amdgpu/%s.bin", ucode_prefix); - if (err) - goto out; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h 2025-10-22 13:53:23.219329106 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h 2025-10-22 13:53:56.459169411 -0400 -@@ -40,28 +40,29 @@ - #define SMU_IH_INTERRUPT_CONTEXT_ID_FAN_ABNORMAL 0x8 - #define SMU_IH_INTERRUPT_CONTEXT_ID_FAN_RECOVERY 0x9 - --#define smu_cmn_init_soft_gpu_metrics(ptr, frev, crev) \ -- do { \ -- typecheck(struct gpu_metrics_v##frev##_##crev, \ -- typeof(*(ptr))); \ -- struct metrics_table_header *header = \ -- (struct metrics_table_header *)(ptr); \ -- memset(header, 0xFF, sizeof(*(ptr))); \ -- header->format_revision = frev; \ -- header->content_revision = crev; \ -- header->structure_size = sizeof(*(ptr)); \ -+#define smu_cmn_init_soft_gpu_metrics(ptr, frev, crev) \ -+ do { \ -+ typecheck(struct gpu_metrics_v##frev##_##crev *, (ptr)); \ -+ struct gpu_metrics_v##frev##_##crev *tmp = (ptr); \ -+ struct metrics_table_header *header = \ -+ (struct metrics_table_header *)tmp; \ -+ memset(header, 0xFF, sizeof(*tmp)); \ -+ header->format_revision = frev; \ -+ header->content_revision = crev; \ -+ header->structure_size = sizeof(*tmp); \ - } while (0) - --#define smu_cmn_init_partition_metrics(ptr, frev, crev) \ -- do { \ -- typecheck(struct amdgpu_partition_metrics_v##frev##_##crev, \ -- typeof(*(ptr))); \ -- struct metrics_table_header *header = \ -- (struct metrics_table_header *)(ptr); \ -- memset(header, 0xFF, sizeof(*(ptr))); \ -- header->format_revision = frev; \ -- header->content_revision = crev; \ -- header->structure_size = sizeof(*(ptr)); \ -+#define smu_cmn_init_partition_metrics(ptr, fr, cr) \ -+ do { \ -+ typecheck(struct amdgpu_partition_metrics_v##fr##_##cr *, \ -+ (ptr)); \ -+ struct amdgpu_partition_metrics_v##fr##_##cr *tmp = (ptr); \ -+ struct metrics_table_header *header = \ -+ (struct metrics_table_header *)tmp; \ -+ memset(header, 0xFF, sizeof(*tmp)); \ -+ header->format_revision = fr; \ -+ header->content_revision = cr; \ -+ header->structure_size = sizeof(*tmp); \ - } while (0) - - extern const int link_speed[]; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/arm/malidp_planes.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/arm/malidp_planes.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/arm/malidp_planes.c 2025-10-22 13:53:23.219329106 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/arm/malidp_planes.c 2025-10-22 13:53:56.459169411 -0400 -@@ -159,7 +159,7 @@ bool malidp_format_mod_supported(struct - } - - if (!fourcc_mod_is_vendor(modifier, ARM)) { -- DRM_ERROR("Unknown modifier (not Arm)\n"); -+ DRM_DEBUG_KMS("Unknown modifier (not Arm)\n"); - return false; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/ast/ast_dp.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/ast/ast_dp.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/ast/ast_dp.c 2025-10-22 13:53:23.219329106 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/ast/ast_dp.c 2025-10-22 13:53:56.459169411 -0400 -@@ -134,7 +134,7 @@ static int ast_astdp_read_edid_block(voi - * 3. The Delays are often longer a lot when system resume from S3/S4. - */ - if (j) -- mdelay(j + 1); -+ msleep(j + 1); - - /* Wait for EDID offset to show up in mirror register */ - vgacrd7 = ast_get_index_reg(ast, AST_IO_VGACRI, 0xd7); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/ast/ast_mode.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/ast/ast_mode.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/ast/ast_mode.c 2025-10-22 13:53:23.219329106 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/ast/ast_mode.c 2025-10-22 13:53:56.459169411 -0400 -@@ -29,7 +29,6 @@ - */ - - #include --#include - #include - - #include -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/bridge/analogix/anx7625.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/bridge/analogix/anx7625.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/bridge/analogix/anx7625.c 2025-10-22 13:53:23.219329106 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/bridge/analogix/anx7625.c 2025-10-22 13:53:56.459169411 -0400 -@@ -2678,7 +2678,7 @@ static int anx7625_i2c_probe(struct i2c_ - ret = devm_request_threaded_irq(dev, platform->pdata.intp_irq, - NULL, anx7625_intr_hpd_isr, - IRQF_TRIGGER_FALLING | -- IRQF_ONESHOT, -+ IRQF_ONESHOT | IRQF_NO_AUTOEN, - "anx7625-intp", platform); - if (ret) { - DRM_DEV_ERROR(dev, "fail to request irq\n"); -@@ -2747,8 +2747,10 @@ static int anx7625_i2c_probe(struct i2c_ - } - - /* Add work function */ -- if (platform->pdata.intp_irq) -+ if (platform->pdata.intp_irq) { -+ enable_irq(platform->pdata.intp_irq); - queue_work(platform->workqueue, &platform->work); -+ } - - if (platform->pdata.audio_en) - anx7625_register_audio(dev, platform); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/bridge/aux-hpd-bridge.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/bridge/aux-hpd-bridge.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/bridge/aux-hpd-bridge.c 2025-10-22 13:53:23.219329106 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/bridge/aux-hpd-bridge.c 2025-10-22 13:53:56.459169411 -0400 -@@ -64,10 +64,11 @@ struct auxiliary_device *devm_drm_dp_hpd - adev->id = ret; - adev->name = "dp_hpd_bridge"; - adev->dev.parent = parent; -- adev->dev.of_node = of_node_get(parent->of_node); - adev->dev.release = drm_aux_hpd_bridge_release; - adev->dev.platform_data = of_node_get(np); - -+ device_set_of_node_from_dev(&adev->dev, parent); -+ - ret = auxiliary_device_init(adev); - if (ret) { - of_node_put(adev->dev.platform_data); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c 2025-10-22 13:53:23.219329106 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c 2025-10-22 13:53:56.459169411 -0400 -@@ -1984,8 +1984,10 @@ static void cdns_mhdp_atomic_enable(stru - mhdp_state = to_cdns_mhdp_bridge_state(new_state); - - mhdp_state->current_mode = drm_mode_duplicate(bridge->dev, mode); -- if (!mhdp_state->current_mode) -- return; -+ if (!mhdp_state->current_mode) { -+ ret = -EINVAL; -+ goto out; -+ } - - drm_mode_set_name(mhdp_state->current_mode); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/bridge/panel.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/bridge/panel.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/bridge/panel.c 2025-10-22 13:53:23.219329106 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/bridge/panel.c 2025-10-22 13:53:56.459169411 -0400 -@@ -299,6 +299,7 @@ struct drm_bridge *drm_panel_bridge_add_ - panel_bridge->bridge.of_node = panel->dev->of_node; - panel_bridge->bridge.ops = DRM_BRIDGE_OP_MODES; - panel_bridge->bridge.type = connector_type; -+ panel_bridge->bridge.pre_enable_prev_first = panel->prepare_prev_first; - - drm_bridge_add(&panel_bridge->bridge); - -@@ -413,8 +414,6 @@ struct drm_bridge *devm_drm_panel_bridge - return bridge; - } - -- bridge->pre_enable_prev_first = panel->prepare_prev_first; -- - *ptr = bridge; - devres_add(dev, ptr); - -@@ -456,8 +455,6 @@ struct drm_bridge *drmm_panel_bridge_add - if (ret) - return ERR_PTR(ret); - -- bridge->pre_enable_prev_first = panel->prepare_prev_first; -- - return bridge; - } - EXPORT_SYMBOL(drmm_panel_bridge_add); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/bridge/samsung-dsim.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/bridge/samsung-dsim.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/bridge/samsung-dsim.c 2025-10-22 13:53:23.219329106 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/bridge/samsung-dsim.c 2025-10-22 13:53:56.459169411 -0400 -@@ -1095,7 +1095,7 @@ static void samsung_dsim_send_to_fifo(st - bool first = !xfer->tx_done; - u32 reg; - -- dev_dbg(dev, "< xfer %pK: tx len %u, done %u, rx len %u, done %u\n", -+ dev_dbg(dev, "< xfer %p: tx len %u, done %u, rx len %u, done %u\n", - xfer, length, xfer->tx_done, xfer->rx_len, xfer->rx_done); - - if (length > DSI_TX_FIFO_SIZE) -@@ -1293,7 +1293,7 @@ static bool samsung_dsim_transfer_finish - spin_unlock_irqrestore(&dsi->transfer_lock, flags); - - dev_dbg(dsi->dev, -- "> xfer %pK, tx_len %zu, tx_done %u, rx_len %u, rx_done %u\n", -+ "> xfer %p, tx_len %zu, tx_done %u, rx_len %u, rx_done %u\n", - xfer, xfer->packet.payload_length, xfer->tx_done, xfer->rx_len, - xfer->rx_done); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/bridge/ti-sn65dsi86.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/bridge/ti-sn65dsi86.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/bridge/ti-sn65dsi86.c 2025-10-22 13:53:23.219329106 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/bridge/ti-sn65dsi86.c 2025-10-22 13:53:56.459169411 -0400 -@@ -348,12 +348,18 @@ static void ti_sn65dsi86_enable_comms(st - * 200 ms. We'll assume that the panel driver will have the hardcoded - * delay in its prepare and always disable HPD. - * -- * If HPD somehow makes sense on some future panel we'll have to -- * change this to be conditional on someone specifying that HPD should -- * be used. -+ * For DisplayPort bridge type, we need HPD. So we use the bridge type -+ * to conditionally disable HPD. -+ * NOTE: The bridge type is set in ti_sn_bridge_probe() but enable_comms() -+ * can be called before. So for DisplayPort, HPD will be enabled once -+ * bridge type is set. We are using bridge type instead of "no-hpd" -+ * property because it is not used properly in devicetree description -+ * and hence is unreliable. - */ -- regmap_update_bits(pdata->regmap, SN_HPD_DISABLE_REG, HPD_DISABLE, -- HPD_DISABLE); -+ -+ if (pdata->bridge.type != DRM_MODE_CONNECTOR_DisplayPort) -+ regmap_update_bits(pdata->regmap, SN_HPD_DISABLE_REG, HPD_DISABLE, -+ HPD_DISABLE); - - pdata->comms_enabled = true; - -@@ -387,6 +393,17 @@ static int __maybe_unused ti_sn65dsi86_r - gpiod_set_value_cansleep(pdata->enable_gpio, 1); - - /* -+ * After EN is deasserted and an external clock is detected, the bridge -+ * will sample GPIO3:1 to determine its frequency. The driver will -+ * overwrite this setting in ti_sn_bridge_set_refclk_freq(). But this is -+ * racy. Thus we have to wait a couple of us. According to the datasheet -+ * the GPIO lines has to be stable at least 5 us (td5) but it seems that -+ * is not enough and the refclk frequency value is still lost or -+ * overwritten by the bridge itself. Waiting for 20us seems to work. -+ */ -+ usleep_range(20, 30); -+ -+ /* - * If we have a reference clock we can enable communication w/ the - * panel (including the aux channel) w/out any need for an input clock - * so we can do it in resume which lets us read the EDID before -@@ -1195,9 +1212,14 @@ static enum drm_connector_status ti_sn_b - struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); - int val = 0; - -- pm_runtime_get_sync(pdata->dev); -+ /* -+ * Runtime reference is grabbed in ti_sn_bridge_hpd_enable() -+ * as the chip won't report HPD just after being powered on. -+ * HPD_DEBOUNCED_STATE reflects correct state only after the -+ * debounce time (~100-400 ms). -+ */ -+ - regmap_read(pdata->regmap, SN_HPD_DISABLE_REG, &val); -- pm_runtime_put_autosuspend(pdata->dev); - - return val & HPD_DEBOUNCED_STATE ? connector_status_connected - : connector_status_disconnected; -@@ -1220,6 +1242,26 @@ static void ti_sn65dsi86_debugfs_init(st - debugfs_create_file("status", 0600, debugfs, pdata, &status_fops); - } - -+static void ti_sn_bridge_hpd_enable(struct drm_bridge *bridge) -+{ -+ struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); -+ -+ /* -+ * Device needs to be powered on before reading the HPD state -+ * for reliable hpd detection in ti_sn_bridge_detect() due to -+ * the high debounce time. -+ */ -+ -+ pm_runtime_get_sync(pdata->dev); -+} -+ -+static void ti_sn_bridge_hpd_disable(struct drm_bridge *bridge) -+{ -+ struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge); -+ -+ pm_runtime_put_autosuspend(pdata->dev); -+} -+ - static const struct drm_bridge_funcs ti_sn_bridge_funcs = { - .attach = ti_sn_bridge_attach, - .detach = ti_sn_bridge_detach, -@@ -1234,6 +1276,8 @@ static const struct drm_bridge_funcs ti_ - .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, - .debugfs_init = ti_sn65dsi86_debugfs_init, -+ .hpd_enable = ti_sn_bridge_hpd_enable, -+ .hpd_disable = ti_sn_bridge_hpd_disable, - }; - - static void ti_sn_bridge_parse_lanes(struct ti_sn65dsi86 *pdata, -@@ -1321,8 +1365,26 @@ static int ti_sn_bridge_probe(struct aux - pdata->bridge.type = pdata->next_bridge->type == DRM_MODE_CONNECTOR_DisplayPort - ? DRM_MODE_CONNECTOR_DisplayPort : DRM_MODE_CONNECTOR_eDP; - -- if (pdata->bridge.type == DRM_MODE_CONNECTOR_DisplayPort) -- pdata->bridge.ops = DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_DETECT; -+ if (pdata->bridge.type == DRM_MODE_CONNECTOR_DisplayPort) { -+ pdata->bridge.ops = DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_DETECT | -+ DRM_BRIDGE_OP_HPD; -+ /* -+ * If comms were already enabled they would have been enabled -+ * with the wrong value of HPD_DISABLE. Update it now. Comms -+ * could be enabled if anyone is holding a pm_runtime reference -+ * (like if a GPIO is in use). Note that in most cases nobody -+ * is doing AUX channel xfers before the bridge is added so -+ * HPD doesn't _really_ matter then. The only exception is in -+ * the eDP case where the panel wants to read the EDID before -+ * the bridge is added. We always consistently have HPD disabled -+ * for eDP. -+ */ -+ mutex_lock(&pdata->comms_mutex); -+ if (pdata->comms_enabled) -+ regmap_update_bits(pdata->regmap, SN_HPD_DISABLE_REG, -+ HPD_DISABLE, 0); -+ mutex_unlock(&pdata->comms_mutex); -+ } - - drm_bridge_add(&pdata->bridge); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/clients/drm_client_setup.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/clients/drm_client_setup.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/clients/drm_client_setup.c 2025-10-22 13:53:23.219329106 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/clients/drm_client_setup.c 2025-10-22 13:53:56.459169411 -0400 -@@ -2,6 +2,7 @@ - - #include - #include -+#include - #include - #include - -@@ -31,6 +32,10 @@ MODULE_PARM_DESC(active, - */ - void drm_client_setup(struct drm_device *dev, const struct drm_format_info *format) - { -+ if (!drm_core_check_feature(dev, DRIVER_MODESET)) { -+ drm_dbg(dev, "driver does not support mode-setting, skipping DRM clients\n"); -+ return; -+ } - - #ifdef CONFIG_DRM_FBDEV_EMULATION - if (!strcmp(drm_client_default, "fbdev")) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/display/drm_bridge_connector.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/display/drm_bridge_connector.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/display/drm_bridge_connector.c 2025-10-22 13:53:23.219329106 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/display/drm_bridge_connector.c 2025-10-22 13:53:56.463169392 -0400 -@@ -708,11 +708,14 @@ struct drm_connector *drm_bridge_connect - if (bridge_connector->bridge_hdmi_audio || - bridge_connector->bridge_dp_audio) { - struct device *dev; -+ struct drm_bridge *bridge; - - if (bridge_connector->bridge_hdmi_audio) -- dev = bridge_connector->bridge_hdmi_audio->hdmi_audio_dev; -+ bridge = bridge_connector->bridge_hdmi_audio; - else -- dev = bridge_connector->bridge_dp_audio->hdmi_audio_dev; -+ bridge = bridge_connector->bridge_dp_audio; -+ -+ dev = bridge->hdmi_audio_dev; - - ret = drm_connector_hdmi_audio_init(connector, dev, - &drm_bridge_connector_hdmi_audio_funcs, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/display/drm_dp_helper.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/display/drm_dp_helper.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/display/drm_dp_helper.c 2025-10-22 13:53:23.219329106 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/display/drm_dp_helper.c 2025-10-22 13:53:56.463169392 -0400 -@@ -692,6 +692,34 @@ void drm_dp_dpcd_set_powered(struct drm_ - EXPORT_SYMBOL(drm_dp_dpcd_set_powered); - - /** -+ * drm_dp_dpcd_set_probe() - Set whether a probing before DPCD access is done -+ * @aux: DisplayPort AUX channel -+ * @enable: Enable the probing if required -+ */ -+void drm_dp_dpcd_set_probe(struct drm_dp_aux *aux, bool enable) -+{ -+ WRITE_ONCE(aux->dpcd_probe_disabled, !enable); -+} -+EXPORT_SYMBOL(drm_dp_dpcd_set_probe); -+ -+static bool dpcd_access_needs_probe(struct drm_dp_aux *aux) -+{ -+ /* -+ * HP ZR24w corrupts the first DPCD access after entering power save -+ * mode. Eg. on a read, the entire buffer will be filled with the same -+ * byte. Do a throw away read to avoid corrupting anything we care -+ * about. Afterwards things will work correctly until the monitor -+ * gets woken up and subsequently re-enters power save mode. -+ * -+ * The user pressing any button on the monitor is enough to wake it -+ * up, so there is no particularly good place to do the workaround. -+ * We just have to do it before any DPCD access and hope that the -+ * monitor doesn't power down exactly after the throw away read. -+ */ -+ return !aux->is_remote && !READ_ONCE(aux->dpcd_probe_disabled); -+} -+ -+/** - * drm_dp_dpcd_read() - read a series of bytes from the DPCD - * @aux: DisplayPort AUX channel (SST or MST) - * @offset: address of the (first) register to read -@@ -712,20 +740,8 @@ ssize_t drm_dp_dpcd_read(struct drm_dp_a - { - int ret; - -- /* -- * HP ZR24w corrupts the first DPCD access after entering power save -- * mode. Eg. on a read, the entire buffer will be filled with the same -- * byte. Do a throw away read to avoid corrupting anything we care -- * about. Afterwards things will work correctly until the monitor -- * gets woken up and subsequently re-enters power save mode. -- * -- * The user pressing any button on the monitor is enough to wake it -- * up, so there is no particularly good place to do the workaround. -- * We just have to do it before any DPCD access and hope that the -- * monitor doesn't power down exactly after the throw away read. -- */ -- if (!aux->is_remote) { -- ret = drm_dp_dpcd_probe(aux, DP_DPCD_REV); -+ if (dpcd_access_needs_probe(aux)) { -+ ret = drm_dp_dpcd_probe(aux, DP_TRAINING_PATTERN_SET); - if (ret < 0) - return ret; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/display/drm_hdmi_state_helper.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/display/drm_hdmi_state_helper.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/display/drm_hdmi_state_helper.c 2025-10-22 13:53:23.219329106 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/display/drm_hdmi_state_helper.c 2025-10-22 13:53:56.463169392 -0400 -@@ -798,12 +798,12 @@ int drm_atomic_helper_connector_hdmi_che - if (!new_conn_state->crtc || !new_conn_state->best_encoder) - return 0; - -- new_conn_state->hdmi.is_limited_range = hdmi_is_limited_range(connector, new_conn_state); -- - ret = hdmi_compute_config(connector, new_conn_state, mode); - if (ret) - return ret; - -+ new_conn_state->hdmi.is_limited_range = hdmi_is_limited_range(connector, new_conn_state); -+ - ret = hdmi_generate_infoframes(connector, new_conn_state); - if (ret) - return ret; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/drm_buddy.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_buddy.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/drm_buddy.c 2025-10-22 13:53:23.219329106 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_buddy.c 2025-10-22 13:53:56.463169392 -0400 -@@ -405,6 +405,49 @@ drm_get_buddy(struct drm_buddy_block *bl - EXPORT_SYMBOL(drm_get_buddy); - - /** -+ * drm_buddy_reset_clear - reset blocks clear state -+ * -+ * @mm: DRM buddy manager -+ * @is_clear: blocks clear state -+ * -+ * Reset the clear state based on @is_clear value for each block -+ * in the freelist. -+ */ -+void drm_buddy_reset_clear(struct drm_buddy *mm, bool is_clear) -+{ -+ u64 root_size, size, start; -+ unsigned int order; -+ int i; -+ -+ size = mm->size; -+ for (i = 0; i < mm->n_roots; ++i) { -+ order = ilog2(size) - ilog2(mm->chunk_size); -+ start = drm_buddy_block_offset(mm->roots[i]); -+ __force_merge(mm, start, start + size, order); -+ -+ root_size = mm->chunk_size << order; -+ size -= root_size; -+ } -+ -+ for (i = 0; i <= mm->max_order; ++i) { -+ struct drm_buddy_block *block; -+ -+ list_for_each_entry_reverse(block, &mm->free_list[i], link) { -+ if (is_clear != drm_buddy_block_is_clear(block)) { -+ if (is_clear) { -+ mark_cleared(block); -+ mm->clear_avail += drm_buddy_block_size(mm, block); -+ } else { -+ clear_reset(block); -+ mm->clear_avail -= drm_buddy_block_size(mm, block); -+ } -+ } -+ } -+ } -+} -+EXPORT_SYMBOL(drm_buddy_reset_clear); -+ -+/** - * drm_buddy_free_block - free a block - * - * @mm: DRM buddy manager -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/drm_edid.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_edid.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/drm_edid.c 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_edid.c 2025-10-22 13:53:56.463169392 -0400 -@@ -66,34 +66,36 @@ static int oui(u8 first, u8 second, u8 t - * on as many displays as possible). - */ - --/* First detailed mode wrong, use largest 60Hz mode */ --#define EDID_QUIRK_PREFER_LARGE_60 (1 << 0) --/* Reported 135MHz pixel clock is too high, needs adjustment */ --#define EDID_QUIRK_135_CLOCK_TOO_HIGH (1 << 1) --/* Prefer the largest mode at 75 Hz */ --#define EDID_QUIRK_PREFER_LARGE_75 (1 << 2) --/* Detail timing is in cm not mm */ --#define EDID_QUIRK_DETAILED_IN_CM (1 << 3) --/* Detailed timing descriptors have bogus size values, so just take the -- * maximum size and use that. -- */ --#define EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE (1 << 4) --/* use +hsync +vsync for detailed mode */ --#define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) --/* Force reduced-blanking timings for detailed modes */ --#define EDID_QUIRK_FORCE_REDUCED_BLANKING (1 << 7) --/* Force 8bpc */ --#define EDID_QUIRK_FORCE_8BPC (1 << 8) --/* Force 12bpc */ --#define EDID_QUIRK_FORCE_12BPC (1 << 9) --/* Force 6bpc */ --#define EDID_QUIRK_FORCE_6BPC (1 << 10) --/* Force 10bpc */ --#define EDID_QUIRK_FORCE_10BPC (1 << 11) --/* Non desktop display (i.e. HMD) */ --#define EDID_QUIRK_NON_DESKTOP (1 << 12) --/* Cap the DSC target bitrate to 15bpp */ --#define EDID_QUIRK_CAP_DSC_15BPP (1 << 13) -+enum drm_edid_internal_quirk { -+ /* First detailed mode wrong, use largest 60Hz mode */ -+ EDID_QUIRK_PREFER_LARGE_60 = DRM_EDID_QUIRK_NUM, -+ /* Reported 135MHz pixel clock is too high, needs adjustment */ -+ EDID_QUIRK_135_CLOCK_TOO_HIGH, -+ /* Prefer the largest mode at 75 Hz */ -+ EDID_QUIRK_PREFER_LARGE_75, -+ /* Detail timing is in cm not mm */ -+ EDID_QUIRK_DETAILED_IN_CM, -+ /* Detailed timing descriptors have bogus size values, so just take the -+ * maximum size and use that. -+ */ -+ EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE, -+ /* use +hsync +vsync for detailed mode */ -+ EDID_QUIRK_DETAILED_SYNC_PP, -+ /* Force reduced-blanking timings for detailed modes */ -+ EDID_QUIRK_FORCE_REDUCED_BLANKING, -+ /* Force 8bpc */ -+ EDID_QUIRK_FORCE_8BPC, -+ /* Force 12bpc */ -+ EDID_QUIRK_FORCE_12BPC, -+ /* Force 6bpc */ -+ EDID_QUIRK_FORCE_6BPC, -+ /* Force 10bpc */ -+ EDID_QUIRK_FORCE_10BPC, -+ /* Non desktop display (i.e. HMD) */ -+ EDID_QUIRK_NON_DESKTOP, -+ /* Cap the DSC target bitrate to 15bpp */ -+ EDID_QUIRK_CAP_DSC_15BPP, -+}; - - #define MICROSOFT_IEEE_OUI 0xca125c - -@@ -128,124 +130,132 @@ static const struct edid_quirk { - u32 quirks; - } edid_quirk_list[] = { - /* Acer AL1706 */ -- EDID_QUIRK('A', 'C', 'R', 44358, EDID_QUIRK_PREFER_LARGE_60), -+ EDID_QUIRK('A', 'C', 'R', 44358, BIT(EDID_QUIRK_PREFER_LARGE_60)), - /* Acer F51 */ -- EDID_QUIRK('A', 'P', 'I', 0x7602, EDID_QUIRK_PREFER_LARGE_60), -+ EDID_QUIRK('A', 'P', 'I', 0x7602, BIT(EDID_QUIRK_PREFER_LARGE_60)), - - /* AEO model 0 reports 8 bpc, but is a 6 bpc panel */ -- EDID_QUIRK('A', 'E', 'O', 0, EDID_QUIRK_FORCE_6BPC), -+ EDID_QUIRK('A', 'E', 'O', 0, BIT(EDID_QUIRK_FORCE_6BPC)), - - /* BenQ GW2765 */ -- EDID_QUIRK('B', 'N', 'Q', 0x78d6, EDID_QUIRK_FORCE_8BPC), -+ EDID_QUIRK('B', 'N', 'Q', 0x78d6, BIT(EDID_QUIRK_FORCE_8BPC)), - - /* BOE model on HP Pavilion 15-n233sl reports 8 bpc, but is a 6 bpc panel */ -- EDID_QUIRK('B', 'O', 'E', 0x78b, EDID_QUIRK_FORCE_6BPC), -+ EDID_QUIRK('B', 'O', 'E', 0x78b, BIT(EDID_QUIRK_FORCE_6BPC)), - - /* CPT panel of Asus UX303LA reports 8 bpc, but is a 6 bpc panel */ -- EDID_QUIRK('C', 'P', 'T', 0x17df, EDID_QUIRK_FORCE_6BPC), -+ EDID_QUIRK('C', 'P', 'T', 0x17df, BIT(EDID_QUIRK_FORCE_6BPC)), - - /* SDC panel of Lenovo B50-80 reports 8 bpc, but is a 6 bpc panel */ -- EDID_QUIRK('S', 'D', 'C', 0x3652, EDID_QUIRK_FORCE_6BPC), -+ EDID_QUIRK('S', 'D', 'C', 0x3652, BIT(EDID_QUIRK_FORCE_6BPC)), - - /* BOE model 0x0771 reports 8 bpc, but is a 6 bpc panel */ -- EDID_QUIRK('B', 'O', 'E', 0x0771, EDID_QUIRK_FORCE_6BPC), -+ EDID_QUIRK('B', 'O', 'E', 0x0771, BIT(EDID_QUIRK_FORCE_6BPC)), - - /* Belinea 10 15 55 */ -- EDID_QUIRK('M', 'A', 'X', 1516, EDID_QUIRK_PREFER_LARGE_60), -- EDID_QUIRK('M', 'A', 'X', 0x77e, EDID_QUIRK_PREFER_LARGE_60), -+ EDID_QUIRK('M', 'A', 'X', 1516, BIT(EDID_QUIRK_PREFER_LARGE_60)), -+ EDID_QUIRK('M', 'A', 'X', 0x77e, BIT(EDID_QUIRK_PREFER_LARGE_60)), - - /* Envision Peripherals, Inc. EN-7100e */ -- EDID_QUIRK('E', 'P', 'I', 59264, EDID_QUIRK_135_CLOCK_TOO_HIGH), -+ EDID_QUIRK('E', 'P', 'I', 59264, BIT(EDID_QUIRK_135_CLOCK_TOO_HIGH)), - /* Envision EN2028 */ -- EDID_QUIRK('E', 'P', 'I', 8232, EDID_QUIRK_PREFER_LARGE_60), -+ EDID_QUIRK('E', 'P', 'I', 8232, BIT(EDID_QUIRK_PREFER_LARGE_60)), - - /* Funai Electronics PM36B */ -- EDID_QUIRK('F', 'C', 'M', 13600, EDID_QUIRK_PREFER_LARGE_75 | -- EDID_QUIRK_DETAILED_IN_CM), -+ EDID_QUIRK('F', 'C', 'M', 13600, BIT(EDID_QUIRK_PREFER_LARGE_75) | -+ BIT(EDID_QUIRK_DETAILED_IN_CM)), - - /* LG 27GP950 */ -- EDID_QUIRK('G', 'S', 'M', 0x5bbf, EDID_QUIRK_CAP_DSC_15BPP), -+ EDID_QUIRK('G', 'S', 'M', 0x5bbf, BIT(EDID_QUIRK_CAP_DSC_15BPP)), - - /* LG 27GN950 */ -- EDID_QUIRK('G', 'S', 'M', 0x5b9a, EDID_QUIRK_CAP_DSC_15BPP), -+ EDID_QUIRK('G', 'S', 'M', 0x5b9a, BIT(EDID_QUIRK_CAP_DSC_15BPP)), - - /* LGD panel of HP zBook 17 G2, eDP 10 bpc, but reports unknown bpc */ -- EDID_QUIRK('L', 'G', 'D', 764, EDID_QUIRK_FORCE_10BPC), -+ EDID_QUIRK('L', 'G', 'D', 764, BIT(EDID_QUIRK_FORCE_10BPC)), - - /* LG Philips LCD LP154W01-A5 */ -- EDID_QUIRK('L', 'P', 'L', 0, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE), -- EDID_QUIRK('L', 'P', 'L', 0x2a00, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE), -+ EDID_QUIRK('L', 'P', 'L', 0, BIT(EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE)), -+ EDID_QUIRK('L', 'P', 'L', 0x2a00, BIT(EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE)), - - /* Samsung SyncMaster 205BW. Note: irony */ -- EDID_QUIRK('S', 'A', 'M', 541, EDID_QUIRK_DETAILED_SYNC_PP), -+ EDID_QUIRK('S', 'A', 'M', 541, BIT(EDID_QUIRK_DETAILED_SYNC_PP)), - /* Samsung SyncMaster 22[5-6]BW */ -- EDID_QUIRK('S', 'A', 'M', 596, EDID_QUIRK_PREFER_LARGE_60), -- EDID_QUIRK('S', 'A', 'M', 638, EDID_QUIRK_PREFER_LARGE_60), -+ EDID_QUIRK('S', 'A', 'M', 596, BIT(EDID_QUIRK_PREFER_LARGE_60)), -+ EDID_QUIRK('S', 'A', 'M', 638, BIT(EDID_QUIRK_PREFER_LARGE_60)), - - /* Sony PVM-2541A does up to 12 bpc, but only reports max 8 bpc */ -- EDID_QUIRK('S', 'N', 'Y', 0x2541, EDID_QUIRK_FORCE_12BPC), -+ EDID_QUIRK('S', 'N', 'Y', 0x2541, BIT(EDID_QUIRK_FORCE_12BPC)), - - /* ViewSonic VA2026w */ -- EDID_QUIRK('V', 'S', 'C', 5020, EDID_QUIRK_FORCE_REDUCED_BLANKING), -+ EDID_QUIRK('V', 'S', 'C', 5020, BIT(EDID_QUIRK_FORCE_REDUCED_BLANKING)), - - /* Medion MD 30217 PG */ -- EDID_QUIRK('M', 'E', 'D', 0x7b8, EDID_QUIRK_PREFER_LARGE_75), -+ EDID_QUIRK('M', 'E', 'D', 0x7b8, BIT(EDID_QUIRK_PREFER_LARGE_75)), - - /* Lenovo G50 */ -- EDID_QUIRK('S', 'D', 'C', 18514, EDID_QUIRK_FORCE_6BPC), -+ EDID_QUIRK('S', 'D', 'C', 18514, BIT(EDID_QUIRK_FORCE_6BPC)), - - /* Panel in Samsung NP700G7A-S01PL notebook reports 6bpc */ -- EDID_QUIRK('S', 'E', 'C', 0xd033, EDID_QUIRK_FORCE_8BPC), -+ EDID_QUIRK('S', 'E', 'C', 0xd033, BIT(EDID_QUIRK_FORCE_8BPC)), - - /* Rotel RSX-1058 forwards sink's EDID but only does HDMI 1.1*/ -- EDID_QUIRK('E', 'T', 'R', 13896, EDID_QUIRK_FORCE_8BPC), -+ EDID_QUIRK('E', 'T', 'R', 13896, BIT(EDID_QUIRK_FORCE_8BPC)), - - /* Valve Index Headset */ -- EDID_QUIRK('V', 'L', 'V', 0x91a8, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('V', 'L', 'V', 0x91b0, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('V', 'L', 'V', 0x91b1, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('V', 'L', 'V', 0x91b2, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('V', 'L', 'V', 0x91b3, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('V', 'L', 'V', 0x91b4, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('V', 'L', 'V', 0x91b5, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('V', 'L', 'V', 0x91b6, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('V', 'L', 'V', 0x91b7, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('V', 'L', 'V', 0x91b8, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('V', 'L', 'V', 0x91b9, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('V', 'L', 'V', 0x91ba, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('V', 'L', 'V', 0x91bb, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('V', 'L', 'V', 0x91bc, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('V', 'L', 'V', 0x91bd, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('V', 'L', 'V', 0x91be, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('V', 'L', 'V', 0x91bf, EDID_QUIRK_NON_DESKTOP), -+ EDID_QUIRK('V', 'L', 'V', 0x91a8, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('V', 'L', 'V', 0x91b0, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('V', 'L', 'V', 0x91b1, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('V', 'L', 'V', 0x91b2, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('V', 'L', 'V', 0x91b3, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('V', 'L', 'V', 0x91b4, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('V', 'L', 'V', 0x91b5, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('V', 'L', 'V', 0x91b6, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('V', 'L', 'V', 0x91b7, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('V', 'L', 'V', 0x91b8, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('V', 'L', 'V', 0x91b9, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('V', 'L', 'V', 0x91ba, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('V', 'L', 'V', 0x91bb, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('V', 'L', 'V', 0x91bc, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('V', 'L', 'V', 0x91bd, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('V', 'L', 'V', 0x91be, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('V', 'L', 'V', 0x91bf, BIT(EDID_QUIRK_NON_DESKTOP)), - - /* HTC Vive and Vive Pro VR Headsets */ -- EDID_QUIRK('H', 'V', 'R', 0xaa01, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('H', 'V', 'R', 0xaa02, EDID_QUIRK_NON_DESKTOP), -+ EDID_QUIRK('H', 'V', 'R', 0xaa01, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('H', 'V', 'R', 0xaa02, BIT(EDID_QUIRK_NON_DESKTOP)), - - /* Oculus Rift DK1, DK2, CV1 and Rift S VR Headsets */ -- EDID_QUIRK('O', 'V', 'R', 0x0001, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('O', 'V', 'R', 0x0003, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('O', 'V', 'R', 0x0004, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('O', 'V', 'R', 0x0012, EDID_QUIRK_NON_DESKTOP), -+ EDID_QUIRK('O', 'V', 'R', 0x0001, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('O', 'V', 'R', 0x0003, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('O', 'V', 'R', 0x0004, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('O', 'V', 'R', 0x0012, BIT(EDID_QUIRK_NON_DESKTOP)), - - /* Windows Mixed Reality Headsets */ -- EDID_QUIRK('A', 'C', 'R', 0x7fce, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('L', 'E', 'N', 0x0408, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('F', 'U', 'J', 0x1970, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('D', 'E', 'L', 0x7fce, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('S', 'E', 'C', 0x144a, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('A', 'U', 'S', 0xc102, EDID_QUIRK_NON_DESKTOP), -+ EDID_QUIRK('A', 'C', 'R', 0x7fce, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('L', 'E', 'N', 0x0408, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('F', 'U', 'J', 0x1970, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('D', 'E', 'L', 0x7fce, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('S', 'E', 'C', 0x144a, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('A', 'U', 'S', 0xc102, BIT(EDID_QUIRK_NON_DESKTOP)), - - /* Sony PlayStation VR Headset */ -- EDID_QUIRK('S', 'N', 'Y', 0x0704, EDID_QUIRK_NON_DESKTOP), -+ EDID_QUIRK('S', 'N', 'Y', 0x0704, BIT(EDID_QUIRK_NON_DESKTOP)), - - /* Sensics VR Headsets */ -- EDID_QUIRK('S', 'E', 'N', 0x1019, EDID_QUIRK_NON_DESKTOP), -+ EDID_QUIRK('S', 'E', 'N', 0x1019, BIT(EDID_QUIRK_NON_DESKTOP)), - - /* OSVR HDK and HDK2 VR Headsets */ -- EDID_QUIRK('S', 'V', 'R', 0x1019, EDID_QUIRK_NON_DESKTOP), -- EDID_QUIRK('A', 'U', 'O', 0x1111, EDID_QUIRK_NON_DESKTOP), -+ EDID_QUIRK('S', 'V', 'R', 0x1019, BIT(EDID_QUIRK_NON_DESKTOP)), -+ EDID_QUIRK('A', 'U', 'O', 0x1111, BIT(EDID_QUIRK_NON_DESKTOP)), -+ -+ /* -+ * @drm_edid_internal_quirk entries end here, following with the -+ * @drm_edid_quirk entries. -+ */ -+ -+ /* HP ZR24w DP AUX DPCD access requires probing to prevent corruption. */ -+ EDID_QUIRK('H', 'W', 'P', 0x2869, BIT(DRM_EDID_QUIRK_DP_DPCD_PROBE)), - }; - - /* -@@ -2951,6 +2961,18 @@ static u32 edid_get_quirks(const struct - return 0; - } - -+static bool drm_edid_has_internal_quirk(struct drm_connector *connector, -+ enum drm_edid_internal_quirk quirk) -+{ -+ return connector->display_info.quirks & BIT(quirk); -+} -+ -+bool drm_edid_has_quirk(struct drm_connector *connector, enum drm_edid_quirk quirk) -+{ -+ return connector->display_info.quirks & BIT(quirk); -+} -+EXPORT_SYMBOL(drm_edid_has_quirk); -+ - #define MODE_SIZE(m) ((m)->hdisplay * (m)->vdisplay) - #define MODE_REFRESH_DIFF(c,t) (abs((c) - (t))) - -@@ -2960,7 +2982,6 @@ static u32 edid_get_quirks(const struct - */ - static void edid_fixup_preferred(struct drm_connector *connector) - { -- const struct drm_display_info *info = &connector->display_info; - struct drm_display_mode *t, *cur_mode, *preferred_mode; - int target_refresh = 0; - int cur_vrefresh, preferred_vrefresh; -@@ -2968,9 +2989,9 @@ static void edid_fixup_preferred(struct - if (list_empty(&connector->probed_modes)) - return; - -- if (info->quirks & EDID_QUIRK_PREFER_LARGE_60) -+ if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_PREFER_LARGE_60)) - target_refresh = 60; -- if (info->quirks & EDID_QUIRK_PREFER_LARGE_75) -+ if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_PREFER_LARGE_75)) - target_refresh = 75; - - preferred_mode = list_first_entry(&connector->probed_modes, -@@ -3474,7 +3495,6 @@ static struct drm_display_mode *drm_mode - const struct drm_edid *drm_edid, - const struct detailed_timing *timing) - { -- const struct drm_display_info *info = &connector->display_info; - struct drm_device *dev = connector->dev; - struct drm_display_mode *mode; - const struct detailed_pixel_timing *pt = &timing->data.pixel_data; -@@ -3508,7 +3528,7 @@ static struct drm_display_mode *drm_mode - return NULL; - } - -- if (info->quirks & EDID_QUIRK_FORCE_REDUCED_BLANKING) { -+ if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_FORCE_REDUCED_BLANKING)) { - mode = drm_cvt_mode(dev, hactive, vactive, 60, true, false, false); - if (!mode) - return NULL; -@@ -3520,7 +3540,7 @@ static struct drm_display_mode *drm_mode - if (!mode) - return NULL; - -- if (info->quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH) -+ if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_135_CLOCK_TOO_HIGH)) - mode->clock = 1088 * 10; - else - mode->clock = le16_to_cpu(timing->pixel_clock) * 10; -@@ -3551,7 +3571,7 @@ static struct drm_display_mode *drm_mode - - drm_mode_do_interlace_quirk(mode, pt); - -- if (info->quirks & EDID_QUIRK_DETAILED_SYNC_PP) { -+ if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_DETAILED_SYNC_PP)) { - mode->flags |= DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC; - } else { - mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ? -@@ -3564,12 +3584,12 @@ set_size: - mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4; - mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf) << 8; - -- if (info->quirks & EDID_QUIRK_DETAILED_IN_CM) { -+ if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_DETAILED_IN_CM)) { - mode->width_mm *= 10; - mode->height_mm *= 10; - } - -- if (info->quirks & EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE) { -+ if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE)) { - mode->width_mm = drm_edid->edid->width_cm * 10; - mode->height_mm = drm_edid->edid->height_cm * 10; - } -@@ -6734,26 +6754,26 @@ static void update_display_info(struct d - drm_update_mso(connector, drm_edid); - - out: -- if (info->quirks & EDID_QUIRK_NON_DESKTOP) { -+ if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_NON_DESKTOP)) { - drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] Non-desktop display%s\n", - connector->base.id, connector->name, - info->non_desktop ? " (redundant quirk)" : ""); - info->non_desktop = true; - } - -- if (info->quirks & EDID_QUIRK_CAP_DSC_15BPP) -+ if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_CAP_DSC_15BPP)) - info->max_dsc_bpp = 15; - -- if (info->quirks & EDID_QUIRK_FORCE_6BPC) -+ if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_FORCE_6BPC)) - info->bpc = 6; - -- if (info->quirks & EDID_QUIRK_FORCE_8BPC) -+ if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_FORCE_8BPC)) - info->bpc = 8; - -- if (info->quirks & EDID_QUIRK_FORCE_10BPC) -+ if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_FORCE_10BPC)) - info->bpc = 10; - -- if (info->quirks & EDID_QUIRK_FORCE_12BPC) -+ if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_FORCE_12BPC)) - info->bpc = 12; - - /* Depends on info->cea_rev set by drm_parse_cea_ext() above */ -@@ -6918,7 +6938,6 @@ static int add_displayid_detailed_modes( - static int _drm_edid_connector_add_modes(struct drm_connector *connector, - const struct drm_edid *drm_edid) - { -- const struct drm_display_info *info = &connector->display_info; - int num_modes = 0; - - if (!drm_edid) -@@ -6948,7 +6967,8 @@ static int _drm_edid_connector_add_modes - if (drm_edid->edid->features & DRM_EDID_FEATURE_CONTINUOUS_FREQ) - num_modes += add_inferred_modes(connector, drm_edid); - -- if (info->quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) -+ if (drm_edid_has_internal_quirk(connector, EDID_QUIRK_PREFER_LARGE_60) || -+ drm_edid_has_internal_quirk(connector, EDID_QUIRK_PREFER_LARGE_75)) - edid_fixup_preferred(connector); - - return num_modes; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/drm_format_helper.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_format_helper.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/drm_format_helper.c 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_format_helper.c 2025-10-22 13:53:56.463169392 -0400 -@@ -857,11 +857,33 @@ static void drm_fb_xrgb8888_to_abgr8888_ - drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_abgr8888); - } - --static void drm_fb_xrgb8888_to_abgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, -- const struct iosys_map *src, -- const struct drm_framebuffer *fb, -- const struct drm_rect *clip, -- struct drm_format_conv_state *state) -+/** -+ * drm_fb_xrgb8888_to_abgr8888 - Convert XRGB8888 to ABGR8888 clip buffer -+ * @dst: Array of ABGR8888 destination buffers -+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines -+ * within @dst; can be NULL if scanlines are stored next to each other. -+ * @src: Array of XRGB8888 source buffer -+ * @fb: DRM framebuffer -+ * @clip: Clip rectangle area to copy -+ * @state: Transform and conversion state -+ * -+ * This function copies parts of a framebuffer to display memory and converts the -+ * color format during the process. The parameters @dst, @dst_pitch and @src refer -+ * to arrays. Each array must have at least as many entries as there are planes in -+ * @fb's format. Each entry stores the value for the format's respective color plane -+ * at the same index. -+ * -+ * This function does not apply clipping on @dst (i.e. the destination is at the -+ * top-left corner). -+ * -+ * Drivers can use this function for ABGR8888 devices that don't support XRGB8888 -+ * natively. It sets an opaque alpha channel as part of the conversion. -+ */ -+void drm_fb_xrgb8888_to_abgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, -+ const struct iosys_map *src, -+ const struct drm_framebuffer *fb, -+ const struct drm_rect *clip, -+ struct drm_format_conv_state *state) - { - static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { - 4, -@@ -870,17 +892,40 @@ static void drm_fb_xrgb8888_to_abgr8888( - drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, - drm_fb_xrgb8888_to_abgr8888_line); - } -+EXPORT_SYMBOL(drm_fb_xrgb8888_to_abgr8888); - - static void drm_fb_xrgb8888_to_xbgr8888_line(void *dbuf, const void *sbuf, unsigned int pixels) - { - drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_xbgr8888); - } - --static void drm_fb_xrgb8888_to_xbgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, -- const struct iosys_map *src, -- const struct drm_framebuffer *fb, -- const struct drm_rect *clip, -- struct drm_format_conv_state *state) -+/** -+ * drm_fb_xrgb8888_to_xbgr8888 - Convert XRGB8888 to XBGR8888 clip buffer -+ * @dst: Array of XBGR8888 destination buffers -+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines -+ * within @dst; can be NULL if scanlines are stored next to each other. -+ * @src: Array of XRGB8888 source buffer -+ * @fb: DRM framebuffer -+ * @clip: Clip rectangle area to copy -+ * @state: Transform and conversion state -+ * -+ * This function copies parts of a framebuffer to display memory and converts the -+ * color format during the process. The parameters @dst, @dst_pitch and @src refer -+ * to arrays. Each array must have at least as many entries as there are planes in -+ * @fb's format. Each entry stores the value for the format's respective color plane -+ * at the same index. -+ * -+ * This function does not apply clipping on @dst (i.e. the destination is at the -+ * top-left corner). -+ * -+ * Drivers can use this function for XBGR8888 devices that don't support XRGB8888 -+ * natively. -+ */ -+void drm_fb_xrgb8888_to_xbgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, -+ const struct iosys_map *src, -+ const struct drm_framebuffer *fb, -+ const struct drm_rect *clip, -+ struct drm_format_conv_state *state) - { - static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { - 4, -@@ -889,6 +934,49 @@ static void drm_fb_xrgb8888_to_xbgr8888( - drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, - drm_fb_xrgb8888_to_xbgr8888_line); - } -+EXPORT_SYMBOL(drm_fb_xrgb8888_to_xbgr8888); -+ -+static void drm_fb_xrgb8888_to_bgrx8888_line(void *dbuf, const void *sbuf, unsigned int pixels) -+{ -+ drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_bgrx8888); -+} -+ -+/** -+ * drm_fb_xrgb8888_to_bgrx8888 - Convert XRGB8888 to BGRX8888 clip buffer -+ * @dst: Array of BGRX8888 destination buffers -+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines -+ * within @dst; can be NULL if scanlines are stored next to each other. -+ * @src: Array of XRGB8888 source buffer -+ * @fb: DRM framebuffer -+ * @clip: Clip rectangle area to copy -+ * @state: Transform and conversion state -+ * -+ * This function copies parts of a framebuffer to display memory and converts the -+ * color format during the process. The parameters @dst, @dst_pitch and @src refer -+ * to arrays. Each array must have at least as many entries as there are planes in -+ * @fb's format. Each entry stores the value for the format's respective color plane -+ * at the same index. -+ * -+ * This function does not apply clipping on @dst (i.e. the destination is at the -+ * top-left corner). -+ * -+ * Drivers can use this function for BGRX8888 devices that don't support XRGB8888 -+ * natively. -+ */ -+void drm_fb_xrgb8888_to_bgrx8888(struct iosys_map *dst, const unsigned int *dst_pitch, -+ const struct iosys_map *src, -+ const struct drm_framebuffer *fb, -+ const struct drm_rect *clip, -+ struct drm_format_conv_state *state) -+{ -+ static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { -+ 4, -+ }; -+ -+ drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, -+ drm_fb_xrgb8888_to_bgrx8888_line); -+} -+EXPORT_SYMBOL(drm_fb_xrgb8888_to_bgrx8888); - - static void drm_fb_xrgb8888_to_xrgb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels) - { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/drm_format_internal.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_format_internal.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/drm_format_internal.h 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_format_internal.h 2025-10-22 13:53:56.463169392 -0400 -@@ -111,6 +111,14 @@ static inline u32 drm_pixel_xrgb8888_to_ - ((pix & 0x000000ff) << 16); - } - -+static inline u32 drm_pixel_xrgb8888_to_bgrx8888(u32 pix) -+{ -+ return ((pix & 0xff000000) >> 24) | /* also copy filler bits */ -+ ((pix & 0x00ff0000) >> 8) | -+ ((pix & 0x0000ff00) << 8) | -+ ((pix & 0x000000ff) << 24); -+} -+ - static inline u32 drm_pixel_xrgb8888_to_abgr8888(u32 pix) - { - return GENMASK(31, 24) | /* fill alpha bits */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/drm_framebuffer.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_framebuffer.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/drm_framebuffer.c 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_framebuffer.c 2025-10-22 13:53:56.463169392 -0400 -@@ -862,11 +862,23 @@ EXPORT_SYMBOL_FOR_TESTS_ONLY(drm_framebu - int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb, - const struct drm_framebuffer_funcs *funcs) - { -+ unsigned int i; - int ret; -+ bool exists; - - if (WARN_ON_ONCE(fb->dev != dev || !fb->format)) - return -EINVAL; - -+ for (i = 0; i < fb->format->num_planes; i++) { -+ if (drm_WARN_ON_ONCE(dev, fb->internal_flags & DRM_FRAMEBUFFER_HAS_HANDLE_REF(i))) -+ fb->internal_flags &= ~DRM_FRAMEBUFFER_HAS_HANDLE_REF(i); -+ if (fb->obj[i]) { -+ exists = drm_gem_object_handle_get_if_exists_unlocked(fb->obj[i]); -+ if (exists) -+ fb->internal_flags |= DRM_FRAMEBUFFER_HAS_HANDLE_REF(i); -+ } -+ } -+ - INIT_LIST_HEAD(&fb->filp_head); - - fb->funcs = funcs; -@@ -875,7 +887,7 @@ int drm_framebuffer_init(struct drm_devi - ret = __drm_mode_object_add(dev, &fb->base, DRM_MODE_OBJECT_FB, - false, drm_framebuffer_free); - if (ret) -- goto out; -+ goto err; - - mutex_lock(&dev->mode_config.fb_lock); - dev->mode_config.num_fb++; -@@ -883,7 +895,16 @@ int drm_framebuffer_init(struct drm_devi - mutex_unlock(&dev->mode_config.fb_lock); - - drm_mode_object_register(dev, &fb->base); --out: -+ -+ return 0; -+ -+err: -+ for (i = 0; i < fb->format->num_planes; i++) { -+ if (fb->internal_flags & DRM_FRAMEBUFFER_HAS_HANDLE_REF(i)) { -+ drm_gem_object_handle_put_unlocked(fb->obj[i]); -+ fb->internal_flags &= ~DRM_FRAMEBUFFER_HAS_HANDLE_REF(i); -+ } -+ } - return ret; - } - EXPORT_SYMBOL(drm_framebuffer_init); -@@ -960,6 +981,12 @@ EXPORT_SYMBOL(drm_framebuffer_unregister - void drm_framebuffer_cleanup(struct drm_framebuffer *fb) - { - struct drm_device *dev = fb->dev; -+ unsigned int i; -+ -+ for (i = 0; i < fb->format->num_planes; i++) { -+ if (fb->internal_flags & DRM_FRAMEBUFFER_HAS_HANDLE_REF(i)) -+ drm_gem_object_handle_put_unlocked(fb->obj[i]); -+ } - - mutex_lock(&dev->mode_config.fb_lock); - list_del(&fb->head); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/drm_gem.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_gem.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/drm_gem.c 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_gem.c 2025-10-22 13:53:56.463169392 -0400 -@@ -212,6 +212,46 @@ void drm_gem_private_object_fini(struct - } - EXPORT_SYMBOL(drm_gem_private_object_fini); - -+static void drm_gem_object_handle_get(struct drm_gem_object *obj) -+{ -+ struct drm_device *dev = obj->dev; -+ -+ drm_WARN_ON(dev, !mutex_is_locked(&dev->object_name_lock)); -+ -+ if (obj->handle_count++ == 0) -+ drm_gem_object_get(obj); -+} -+ -+/** -+ * drm_gem_object_handle_get_if_exists_unlocked - acquire reference on user-space handle, if any -+ * @obj: GEM object -+ * -+ * Acquires a reference on the GEM buffer object's handle. Required to keep -+ * the GEM object alive. Call drm_gem_object_handle_put_if_exists_unlocked() -+ * to release the reference. Does nothing if the buffer object has no handle. -+ * -+ * Returns: -+ * True if a handle exists, or false otherwise -+ */ -+bool drm_gem_object_handle_get_if_exists_unlocked(struct drm_gem_object *obj) -+{ -+ struct drm_device *dev = obj->dev; -+ -+ guard(mutex)(&dev->object_name_lock); -+ -+ /* -+ * First ref taken during GEM object creation, if any. Some -+ * drivers set up internal framebuffers with GEM objects that -+ * do not have a GEM handle. Hence, this counter can be zero. -+ */ -+ if (!obj->handle_count) -+ return false; -+ -+ drm_gem_object_handle_get(obj); -+ -+ return true; -+} -+ - /** - * drm_gem_object_handle_free - release resources bound to userspace handles - * @obj: GEM object to clean up. -@@ -242,20 +282,26 @@ static void drm_gem_object_exported_dma_ - } - } - --static void --drm_gem_object_handle_put_unlocked(struct drm_gem_object *obj) -+/** -+ * drm_gem_object_handle_put_unlocked - releases reference on user-space handle -+ * @obj: GEM object -+ * -+ * Releases a reference on the GEM buffer object's handle. Possibly releases -+ * the GEM buffer object and associated dma-buf objects. -+ */ -+void drm_gem_object_handle_put_unlocked(struct drm_gem_object *obj) - { - struct drm_device *dev = obj->dev; - bool final = false; - -- if (WARN_ON(READ_ONCE(obj->handle_count) == 0)) -+ if (drm_WARN_ON(dev, READ_ONCE(obj->handle_count) == 0)) - return; - - /* -- * Must bump handle count first as this may be the last -- * ref, in which case the object would disappear before we -- * checked for a name -- */ -+ * Must bump handle count first as this may be the last -+ * ref, in which case the object would disappear before -+ * we checked for a name. -+ */ - - mutex_lock(&dev->object_name_lock); - if (--obj->handle_count == 0) { -@@ -279,6 +325,9 @@ drm_gem_object_release_handle(int id, vo - struct drm_file *file_priv = data; - struct drm_gem_object *obj = ptr; - -+ if (drm_WARN_ON(obj->dev, !data)) -+ return 0; -+ - if (obj->funcs->close) - obj->funcs->close(obj, file_priv); - -@@ -389,8 +438,8 @@ drm_gem_handle_create_tail(struct drm_fi - int ret; - - WARN_ON(!mutex_is_locked(&dev->object_name_lock)); -- if (obj->handle_count++ == 0) -- drm_gem_object_get(obj); -+ -+ drm_gem_object_handle_get(obj); - - /* - * Get the user-visible handle using idr. Preload and perform -@@ -399,7 +448,7 @@ drm_gem_handle_create_tail(struct drm_fi - idr_preload(GFP_KERNEL); - spin_lock(&file_priv->table_lock); - -- ret = idr_alloc(&file_priv->object_idr, obj, 1, 0, GFP_NOWAIT); -+ ret = idr_alloc(&file_priv->object_idr, NULL, 1, 0, GFP_NOWAIT); - - spin_unlock(&file_priv->table_lock); - idr_preload_end(); -@@ -420,6 +469,11 @@ drm_gem_handle_create_tail(struct drm_fi - goto err_revoke; - } - -+ /* mirrors drm_gem_handle_delete to avoid races */ -+ spin_lock(&file_priv->table_lock); -+ obj = idr_replace(&file_priv->object_idr, obj, handle); -+ WARN_ON(obj != NULL); -+ spin_unlock(&file_priv->table_lock); - *handlep = handle; - return 0; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/drm_gem_dma_helper.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_gem_dma_helper.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/drm_gem_dma_helper.c 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_gem_dma_helper.c 2025-10-22 13:53:56.463169392 -0400 -@@ -230,7 +230,7 @@ void drm_gem_dma_free(struct drm_gem_dma - - if (drm_gem_is_imported(gem_obj)) { - if (dma_obj->vaddr) -- dma_buf_vunmap_unlocked(gem_obj->dma_buf, &map); -+ dma_buf_vunmap_unlocked(gem_obj->import_attach->dmabuf, &map); - drm_prime_gem_destroy(gem_obj, dma_obj->sgt); - } else if (dma_obj->vaddr) { - if (dma_obj->map_noncoherent) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/drm_gem_framebuffer_helper.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_gem_framebuffer_helper.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/drm_gem_framebuffer_helper.c 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_gem_framebuffer_helper.c 2025-10-22 13:53:56.463169392 -0400 -@@ -419,6 +419,7 @@ EXPORT_SYMBOL(drm_gem_fb_vunmap); - static void __drm_gem_fb_end_cpu_access(struct drm_framebuffer *fb, enum dma_data_direction dir, - unsigned int num_planes) - { -+ struct dma_buf_attachment *import_attach; - struct drm_gem_object *obj; - int ret; - -@@ -427,9 +428,10 @@ static void __drm_gem_fb_end_cpu_access( - obj = drm_gem_fb_get_obj(fb, num_planes); - if (!obj) - continue; -+ import_attach = obj->import_attach; - if (!drm_gem_is_imported(obj)) - continue; -- ret = dma_buf_end_cpu_access(obj->dma_buf, dir); -+ ret = dma_buf_end_cpu_access(import_attach->dmabuf, dir); - if (ret) - drm_err(fb->dev, "dma_buf_end_cpu_access(%u, %d) failed: %d\n", - ret, num_planes, dir); -@@ -452,6 +454,7 @@ static void __drm_gem_fb_end_cpu_access( - */ - int drm_gem_fb_begin_cpu_access(struct drm_framebuffer *fb, enum dma_data_direction dir) - { -+ struct dma_buf_attachment *import_attach; - struct drm_gem_object *obj; - unsigned int i; - int ret; -@@ -462,9 +465,10 @@ int drm_gem_fb_begin_cpu_access(struct d - ret = -EINVAL; - goto err___drm_gem_fb_end_cpu_access; - } -+ import_attach = obj->import_attach; - if (!drm_gem_is_imported(obj)) - continue; -- ret = dma_buf_begin_cpu_access(obj->dma_buf, dir); -+ ret = dma_buf_begin_cpu_access(import_attach->dmabuf, dir); - if (ret) - goto err___drm_gem_fb_end_cpu_access; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/drm_gem_shmem_helper.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_gem_shmem_helper.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/drm_gem_shmem_helper.c 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_gem_shmem_helper.c 2025-10-22 13:53:56.463169392 -0400 -@@ -349,7 +349,7 @@ int drm_gem_shmem_vmap_locked(struct drm - int ret = 0; - - if (drm_gem_is_imported(obj)) { -- ret = dma_buf_vmap(obj->dma_buf, map); -+ ret = dma_buf_vmap(obj->import_attach->dmabuf, map); - } else { - pgprot_t prot = PAGE_KERNEL; - -@@ -409,7 +409,7 @@ void drm_gem_shmem_vunmap_locked(struct - struct drm_gem_object *obj = &shmem->base; - - if (drm_gem_is_imported(obj)) { -- dma_buf_vunmap(obj->dma_buf, map); -+ dma_buf_vunmap(obj->import_attach->dmabuf, map); - } else { - dma_resv_assert_held(shmem->base.resv); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/drm_internal.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_internal.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/drm_internal.h 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_internal.h 2025-10-22 13:53:56.463169392 -0400 -@@ -161,6 +161,8 @@ void drm_sysfs_lease_event(struct drm_de - - /* drm_gem.c */ - int drm_gem_init(struct drm_device *dev); -+bool drm_gem_object_handle_get_if_exists_unlocked(struct drm_gem_object *obj); -+void drm_gem_object_handle_put_unlocked(struct drm_gem_object *obj); - int drm_gem_handle_create_tail(struct drm_file *file_priv, - struct drm_gem_object *obj, - u32 *handlep); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/drm_mipi_dsi.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_mipi_dsi.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/drm_mipi_dsi.c 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_mipi_dsi.c 2025-10-22 13:53:56.463169392 -0400 -@@ -91,12 +91,13 @@ static const struct dev_pm_ops mipi_dsi_ - .restore = pm_generic_restore, - }; - --static const struct bus_type mipi_dsi_bus_type = { -+const struct bus_type mipi_dsi_bus_type = { - .name = "mipi-dsi", - .match = mipi_dsi_device_match, - .uevent = mipi_dsi_uevent, - .pm = &mipi_dsi_device_pm_ops, - }; -+EXPORT_SYMBOL_GPL(mipi_dsi_bus_type); - - /** - * of_find_mipi_dsi_device_by_node() - find the MIPI DSI device matching a -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/drm_panic_qr.rs BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_panic_qr.rs ---- BPI-Router-Linux-kernel/drivers/gpu/drm/drm_panic_qr.rs 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_panic_qr.rs 2025-10-22 13:53:56.463169392 -0400 -@@ -27,7 +27,7 @@ - //! * - //! * - --use kernel::{prelude::*, str::CStr}; -+use kernel::prelude::*; - - #[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)] - struct Version(usize); -@@ -381,6 +381,26 @@ struct DecFifo { - len: usize, - } - -+// On arm32 architecture, dividing an `u64` by a constant will generate a call -+// to `__aeabi_uldivmod` which is not present in the kernel. -+// So use the multiply by inverse method for this architecture. -+fn div10(val: u64) -> u64 { -+ if cfg!(target_arch = "arm") { -+ let val_h = val >> 32; -+ let val_l = val & 0xFFFFFFFF; -+ let b_h: u64 = 0x66666666; -+ let b_l: u64 = 0x66666667; -+ -+ let tmp1 = val_h * b_l + ((val_l * b_l) >> 32); -+ let tmp2 = val_l * b_h + (tmp1 & 0xffffffff); -+ let tmp3 = val_h * b_h + (tmp1 >> 32) + (tmp2 >> 32); -+ -+ tmp3 >> 2 -+ } else { -+ val / 10 -+ } -+} -+ - impl DecFifo { - fn push(&mut self, data: u64, len: usize) { - let mut chunk = data; -@@ -389,7 +409,7 @@ impl DecFifo { - } - for i in 0..len { - self.decimals[i] = (chunk % 10) as u8; -- chunk /= 10; -+ chunk = div10(chunk); - } - self.len += len; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/drm_prime.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_prime.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/drm_prime.c 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_prime.c 2025-10-22 13:53:56.463169392 -0400 -@@ -453,7 +453,13 @@ struct dma_buf *drm_gem_prime_handle_to_ - } - - mutex_lock(&dev->object_name_lock); -- /* re-export the original imported/exported object */ -+ /* re-export the original imported object */ -+ if (obj->import_attach) { -+ dmabuf = obj->import_attach->dmabuf; -+ get_dma_buf(dmabuf); -+ goto out_have_obj; -+ } -+ - if (obj->dma_buf) { - get_dma_buf(obj->dma_buf); - dmabuf = obj->dma_buf; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/drm_writeback.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_writeback.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/drm_writeback.c 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/drm_writeback.c 2025-10-22 13:53:56.463169392 -0400 -@@ -343,17 +343,18 @@ EXPORT_SYMBOL(drm_writeback_connector_in - /** - * drm_writeback_connector_cleanup - Cleanup the writeback connector - * @dev: DRM device -- * @wb_connector: Pointer to the writeback connector to clean up -+ * @data: Pointer to the writeback connector to clean up - * - * This will decrement the reference counter of blobs and destroy properties. It - * will also clean the remaining jobs in this writeback connector. Caution: This helper will not - * clean up the attached encoder and the drm_connector. - */ - static void drm_writeback_connector_cleanup(struct drm_device *dev, -- struct drm_writeback_connector *wb_connector) -+ void *data) - { - unsigned long flags; - struct drm_writeback_job *pos, *n; -+ struct drm_writeback_connector *wb_connector = data; - - delete_writeback_properties(dev); - drm_property_blob_put(wb_connector->pixel_formats_blob_ptr); -@@ -405,7 +406,7 @@ int drmm_writeback_connector_init(struct - if (ret) - return ret; - -- ret = drmm_add_action_or_reset(dev, (void *)drm_writeback_connector_cleanup, -+ ret = drmm_add_action_or_reset(dev, drm_writeback_connector_cleanup, - wb_connector); - if (ret) - return ret; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c 2025-10-22 13:53:56.463169392 -0400 -@@ -65,7 +65,7 @@ static void etnaviv_gem_prime_release(st - struct iosys_map map = IOSYS_MAP_INIT_VADDR(etnaviv_obj->vaddr); - - if (etnaviv_obj->vaddr) -- dma_buf_vunmap_unlocked(etnaviv_obj->base.dma_buf, &map); -+ dma_buf_vunmap_unlocked(etnaviv_obj->base.import_attach->dmabuf, &map); - - /* Don't drop the pages for imported dmabuf, as they are not - * ours, just free the array we allocated: -@@ -82,7 +82,7 @@ static void *etnaviv_gem_prime_vmap_impl - - lockdep_assert_held(&etnaviv_obj->lock); - -- ret = dma_buf_vmap(etnaviv_obj->base.dma_buf, &map); -+ ret = dma_buf_vmap(etnaviv_obj->base.import_attach->dmabuf, &map); - if (ret) - return NULL; - return map.vaddr; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/etnaviv/etnaviv_sched.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/etnaviv/etnaviv_sched.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/etnaviv/etnaviv_sched.c 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/etnaviv/etnaviv_sched.c 2025-10-22 13:53:56.463169392 -0400 -@@ -35,6 +35,7 @@ static enum drm_gpu_sched_stat etnaviv_s - *sched_job) - { - struct etnaviv_gem_submit *submit = to_etnaviv_submit(sched_job); -+ struct drm_gpu_scheduler *sched = sched_job->sched; - struct etnaviv_gpu *gpu = submit->gpu; - u32 dma_addr, primid = 0; - int change; -@@ -89,7 +90,9 @@ static enum drm_gpu_sched_stat etnaviv_s - return DRM_GPU_SCHED_STAT_NOMINAL; - - out_no_timeout: -- list_add(&sched_job->list, &sched_job->sched->pending_list); -+ spin_lock(&sched->job_list_lock); -+ list_add(&sched_job->list, &sched->pending_list); -+ spin_unlock(&sched->job_list_lock); - return DRM_GPU_SCHED_STAT_NOMINAL; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/exynos/exynos7_drm_decon.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/exynos/exynos7_drm_decon.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/exynos/exynos7_drm_decon.c 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/exynos/exynos7_drm_decon.c 2025-10-22 13:53:56.463169392 -0400 -@@ -636,6 +636,10 @@ static irqreturn_t decon_irq_handler(int - if (!ctx->drm_dev) - goto out; - -+ /* check if crtc and vblank have been initialized properly */ -+ if (!drm_dev_has_vblank(ctx->drm_dev)) -+ goto out; -+ - if (!ctx->i80_if) { - drm_crtc_handle_vblank(&ctx->crtc->base); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/exynos/exynos_drm_fimd.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/exynos/exynos_drm_fimd.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/exynos/exynos_drm_fimd.c 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/exynos/exynos_drm_fimd.c 2025-10-22 13:53:56.463169392 -0400 -@@ -187,6 +187,7 @@ struct fimd_context { - u32 i80ifcon; - bool i80_if; - bool suspended; -+ bool dp_clk_enabled; - wait_queue_head_t wait_vsync_queue; - atomic_t wait_vsync_event; - atomic_t win_updated; -@@ -1047,7 +1048,18 @@ static void fimd_dp_clock_enable(struct - struct fimd_context *ctx = container_of(clk, struct fimd_context, - dp_clk); - u32 val = enable ? DP_MIE_CLK_DP_ENABLE : DP_MIE_CLK_DISABLE; -+ -+ if (enable == ctx->dp_clk_enabled) -+ return; -+ -+ if (enable) -+ pm_runtime_resume_and_get(ctx->dev); -+ -+ ctx->dp_clk_enabled = enable; - writel(val, ctx->regs + DP_MIE_CLKCON); -+ -+ if (!enable) -+ pm_runtime_put(ctx->dev); - } - - static const struct exynos_drm_crtc_ops fimd_crtc_ops = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/exynos/exynos_drm_gem.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/exynos/exynos_drm_gem.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/exynos/exynos_drm_gem.c 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/exynos/exynos_drm_gem.c 2025-10-22 13:53:56.463169392 -0400 -@@ -174,7 +174,7 @@ static struct exynos_drm_gem *exynos_drm - return ERR_PTR(ret); - } - -- DRM_DEV_DEBUG_KMS(dev->dev, "created file object = %pK\n", obj->filp); -+ DRM_DEV_DEBUG_KMS(dev->dev, "created file object = %p\n", obj->filp); - - return exynos_gem; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/exynos/exynos_drm_ipp.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/exynos/exynos_drm_ipp.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/exynos/exynos_drm_ipp.c 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/exynos/exynos_drm_ipp.c 2025-10-22 13:53:56.463169392 -0400 -@@ -271,7 +271,7 @@ static inline struct exynos_drm_ipp_task - task->src.rect.h = task->dst.rect.h = UINT_MAX; - task->transform.rotation = DRM_MODE_ROTATE_0; - -- DRM_DEV_DEBUG_DRIVER(task->dev, "Allocated task %pK\n", task); -+ DRM_DEV_DEBUG_DRIVER(task->dev, "Allocated task %p\n", task); - - return task; - } -@@ -339,7 +339,7 @@ static int exynos_drm_ipp_task_set(struc - } - - DRM_DEV_DEBUG_DRIVER(task->dev, -- "Got task %pK configuration from userspace\n", -+ "Got task %p configuration from userspace\n", - task); - return 0; - } -@@ -394,7 +394,7 @@ static void exynos_drm_ipp_task_release_ - static void exynos_drm_ipp_task_free(struct exynos_drm_ipp *ipp, - struct exynos_drm_ipp_task *task) - { -- DRM_DEV_DEBUG_DRIVER(task->dev, "Freeing task %pK\n", task); -+ DRM_DEV_DEBUG_DRIVER(task->dev, "Freeing task %p\n", task); - - exynos_drm_ipp_task_release_buf(&task->src); - exynos_drm_ipp_task_release_buf(&task->dst); -@@ -559,7 +559,7 @@ static int exynos_drm_ipp_check_format(s - DRM_EXYNOS_IPP_FORMAT_DESTINATION); - if (!fmt) { - DRM_DEV_DEBUG_DRIVER(task->dev, -- "Task %pK: %s format not supported\n", -+ "Task %p: %s format not supported\n", - task, buf == src ? "src" : "dst"); - return -EINVAL; - } -@@ -609,7 +609,7 @@ static int exynos_drm_ipp_task_check(str - bool rotate = (rotation != DRM_MODE_ROTATE_0); - bool scale = false; - -- DRM_DEV_DEBUG_DRIVER(task->dev, "Checking task %pK\n", task); -+ DRM_DEV_DEBUG_DRIVER(task->dev, "Checking task %p\n", task); - - if (src->rect.w == UINT_MAX) - src->rect.w = src->buf.width; -@@ -625,7 +625,7 @@ static int exynos_drm_ipp_task_check(str - dst->rect.x + dst->rect.w > (dst->buf.width) || - dst->rect.y + dst->rect.h > (dst->buf.height)) { - DRM_DEV_DEBUG_DRIVER(task->dev, -- "Task %pK: defined area is outside provided buffers\n", -+ "Task %p: defined area is outside provided buffers\n", - task); - return -EINVAL; - } -@@ -642,7 +642,7 @@ static int exynos_drm_ipp_task_check(str - (!(ipp->capabilities & DRM_EXYNOS_IPP_CAP_SCALE) && scale) || - (!(ipp->capabilities & DRM_EXYNOS_IPP_CAP_CONVERT) && - src->buf.fourcc != dst->buf.fourcc)) { -- DRM_DEV_DEBUG_DRIVER(task->dev, "Task %pK: hw capabilities exceeded\n", -+ DRM_DEV_DEBUG_DRIVER(task->dev, "Task %p: hw capabilities exceeded\n", - task); - return -EINVAL; - } -@@ -655,7 +655,7 @@ static int exynos_drm_ipp_task_check(str - if (ret) - return ret; - -- DRM_DEV_DEBUG_DRIVER(ipp->dev, "Task %pK: all checks done.\n", -+ DRM_DEV_DEBUG_DRIVER(ipp->dev, "Task %p: all checks done.\n", - task); - - return ret; -@@ -667,25 +667,25 @@ static int exynos_drm_ipp_task_setup_buf - struct exynos_drm_ipp_buffer *src = &task->src, *dst = &task->dst; - int ret = 0; - -- DRM_DEV_DEBUG_DRIVER(task->dev, "Setting buffer for task %pK\n", -+ DRM_DEV_DEBUG_DRIVER(task->dev, "Setting buffer for task %p\n", - task); - - ret = exynos_drm_ipp_task_setup_buffer(src, filp); - if (ret) { - DRM_DEV_DEBUG_DRIVER(task->dev, -- "Task %pK: src buffer setup failed\n", -+ "Task %p: src buffer setup failed\n", - task); - return ret; - } - ret = exynos_drm_ipp_task_setup_buffer(dst, filp); - if (ret) { - DRM_DEV_DEBUG_DRIVER(task->dev, -- "Task %pK: dst buffer setup failed\n", -+ "Task %p: dst buffer setup failed\n", - task); - return ret; - } - -- DRM_DEV_DEBUG_DRIVER(task->dev, "Task %pK: buffers prepared.\n", -+ DRM_DEV_DEBUG_DRIVER(task->dev, "Task %p: buffers prepared.\n", - task); - - return ret; -@@ -764,7 +764,7 @@ void exynos_drm_ipp_task_done(struct exy - struct exynos_drm_ipp *ipp = task->ipp; - unsigned long flags; - -- DRM_DEV_DEBUG_DRIVER(task->dev, "ipp: %d, task %pK done: %d\n", -+ DRM_DEV_DEBUG_DRIVER(task->dev, "ipp: %d, task %p done: %d\n", - ipp->id, task, ret); - - spin_lock_irqsave(&ipp->lock, flags); -@@ -807,7 +807,7 @@ static void exynos_drm_ipp_next_task(str - spin_unlock_irqrestore(&ipp->lock, flags); - - DRM_DEV_DEBUG_DRIVER(ipp->dev, -- "ipp: %d, selected task %pK to run\n", ipp->id, -+ "ipp: %d, selected task %p to run\n", ipp->id, - task); - - ret = ipp->funcs->commit(ipp, task); -@@ -917,14 +917,14 @@ int exynos_drm_ipp_commit_ioctl(struct d - */ - if (arg->flags & DRM_EXYNOS_IPP_FLAG_NONBLOCK) { - DRM_DEV_DEBUG_DRIVER(ipp->dev, -- "ipp: %d, nonblocking processing task %pK\n", -+ "ipp: %d, nonblocking processing task %p\n", - ipp->id, task); - - task->flags |= DRM_EXYNOS_IPP_TASK_ASYNC; - exynos_drm_ipp_schedule_task(task->ipp, task); - ret = 0; - } else { -- DRM_DEV_DEBUG_DRIVER(ipp->dev, "ipp: %d, processing task %pK\n", -+ DRM_DEV_DEBUG_DRIVER(ipp->dev, "ipp: %d, processing task %p\n", - ipp->id, task); - exynos_drm_ipp_schedule_task(ipp, task); - ret = wait_event_interruptible(ipp->done_wq, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/gma500/oaktrail_hdmi.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/gma500/oaktrail_hdmi.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/gma500/oaktrail_hdmi.c 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/gma500/oaktrail_hdmi.c 2025-10-22 13:53:56.463169392 -0400 -@@ -726,8 +726,8 @@ void oaktrail_hdmi_teardown(struct drm_d - - if (hdmi_dev) { - pdev = hdmi_dev->dev; -- pci_set_drvdata(pdev, NULL); - oaktrail_hdmi_i2c_exit(pdev); -+ pci_set_drvdata(pdev, NULL); - iounmap(hdmi_dev->regs); - kfree(hdmi_dev); - pci_dev_put(pdev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c 2025-10-22 13:53:56.463169392 -0400 -@@ -325,6 +325,17 @@ static int hibmc_dp_link_downgrade_train - return hibmc_dp_link_reduce_rate(dp); - } - -+static void hibmc_dp_update_caps(struct hibmc_dp_dev *dp) -+{ -+ dp->link.cap.link_rate = dp->dpcd[DP_MAX_LINK_RATE]; -+ if (dp->link.cap.link_rate > DP_LINK_BW_8_1 || !dp->link.cap.link_rate) -+ dp->link.cap.link_rate = DP_LINK_BW_8_1; -+ -+ dp->link.cap.lanes = dp->dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK; -+ if (dp->link.cap.lanes > HIBMC_DP_LANE_NUM_MAX) -+ dp->link.cap.lanes = HIBMC_DP_LANE_NUM_MAX; -+} -+ - int hibmc_dp_link_training(struct hibmc_dp_dev *dp) - { - struct hibmc_dp_link *link = &dp->link; -@@ -334,8 +345,7 @@ int hibmc_dp_link_training(struct hibmc_ - if (ret) - drm_err(dp->dev, "dp aux read dpcd failed, ret: %d\n", ret); - -- dp->link.cap.link_rate = dp->dpcd[DP_MAX_LINK_RATE]; -- dp->link.cap.lanes = 0x2; -+ hibmc_dp_update_caps(dp); - - ret = hibmc_dp_get_serdes_rate_cfg(dp); - if (ret < 0) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c 2025-10-22 13:53:56.463169392 -0400 -@@ -32,7 +32,7 @@ - - DEFINE_DRM_GEM_FOPS(hibmc_fops); - --static const char *g_irqs_names_map[HIBMC_MAX_VECTORS] = { "vblank", "hpd" }; -+static const char *g_irqs_names_map[HIBMC_MAX_VECTORS] = { "hibmc-vblank", "hibmc-hpd" }; - - static irqreturn_t hibmc_interrupt(int irq, void *arg) - { -@@ -115,6 +115,8 @@ static const struct drm_mode_config_func - static int hibmc_kms_init(struct hibmc_drm_private *priv) - { - struct drm_device *dev = &priv->dev; -+ struct drm_encoder *encoder; -+ u32 clone_mask = 0; - int ret; - - ret = drmm_mode_config_init(dev); -@@ -154,6 +156,12 @@ static int hibmc_kms_init(struct hibmc_d - return ret; - } - -+ drm_for_each_encoder(encoder, dev) -+ clone_mask |= drm_encoder_mask(encoder); -+ -+ drm_for_each_encoder(encoder, dev) -+ encoder->possible_clones = clone_mask; -+ - return 0; - } - -@@ -277,7 +285,6 @@ static void hibmc_unload(struct drm_devi - static int hibmc_msi_init(struct drm_device *dev) - { - struct pci_dev *pdev = to_pci_dev(dev->dev); -- char name[32] = {0}; - int valid_irq_num; - int irq; - int ret; -@@ -292,9 +299,6 @@ static int hibmc_msi_init(struct drm_dev - valid_irq_num = ret; - - for (int i = 0; i < valid_irq_num; i++) { -- snprintf(name, ARRAY_SIZE(name) - 1, "%s-%s-%s", -- dev->driver->name, pci_name(pdev), g_irqs_names_map[i]); -- - irq = pci_irq_vector(pdev, i); - - if (i) -@@ -302,10 +306,10 @@ static int hibmc_msi_init(struct drm_dev - ret = devm_request_threaded_irq(&pdev->dev, irq, - hibmc_dp_interrupt, - hibmc_dp_hpd_isr, -- IRQF_SHARED, name, dev); -+ IRQF_SHARED, g_irqs_names_map[i], dev); - else - ret = devm_request_irq(&pdev->dev, irq, hibmc_interrupt, -- IRQF_SHARED, name, dev); -+ IRQF_SHARED, g_irqs_names_map[i], dev); - if (ret) { - drm_err(dev, "install irq failed: %d\n", ret); - return ret; -@@ -323,13 +327,13 @@ static int hibmc_load(struct drm_device - - ret = hibmc_hw_init(priv); - if (ret) -- goto err; -+ return ret; - - ret = drmm_vram_helper_init(dev, pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); - if (ret) { - drm_err(dev, "Error initializing VRAM MM; %d\n", ret); -- goto err; -+ return ret; - } - - ret = hibmc_kms_init(priv); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h 2025-10-22 13:53:56.463169392 -0400 -@@ -69,6 +69,7 @@ int hibmc_de_init(struct hibmc_drm_priva - int hibmc_vdac_init(struct hibmc_drm_private *priv); - - int hibmc_ddc_create(struct drm_device *drm_dev, struct hibmc_vdac *connector); -+void hibmc_ddc_del(struct hibmc_vdac *vdac); - - int hibmc_dp_init(struct hibmc_drm_private *priv); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c 2025-10-22 13:53:56.463169392 -0400 -@@ -95,3 +95,8 @@ int hibmc_ddc_create(struct drm_device * - - return i2c_bit_add_bus(&vdac->adapter); - } -+ -+void hibmc_ddc_del(struct hibmc_vdac *vdac) -+{ -+ i2c_del_adapter(&vdac->adapter); -+} -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c 2025-10-22 13:53:56.463169392 -0400 -@@ -53,7 +53,7 @@ static void hibmc_connector_destroy(stru - { - struct hibmc_vdac *vdac = to_hibmc_vdac(connector); - -- i2c_del_adapter(&vdac->adapter); -+ hibmc_ddc_del(vdac); - drm_connector_cleanup(connector); - } - -@@ -110,7 +110,7 @@ int hibmc_vdac_init(struct hibmc_drm_pri - ret = drmm_encoder_init(dev, encoder, NULL, DRM_MODE_ENCODER_DAC, NULL); - if (ret) { - drm_err(dev, "failed to init encoder: %d\n", ret); -- return ret; -+ goto err; - } - - drm_encoder_helper_add(encoder, &hibmc_encoder_helper_funcs); -@@ -121,7 +121,7 @@ int hibmc_vdac_init(struct hibmc_drm_pri - &vdac->adapter); - if (ret) { - drm_err(dev, "failed to init connector: %d\n", ret); -- return ret; -+ goto err; - } - - drm_connector_helper_add(connector, &hibmc_connector_helper_funcs); -@@ -131,4 +131,9 @@ int hibmc_vdac_init(struct hibmc_drm_pri - connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; - - return 0; -+ -+err: -+ hibmc_ddc_del(vdac); -+ -+ return ret; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/i915/display/intel_bios.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/display/intel_bios.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/i915/display/intel_bios.c 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/display/intel_bios.c 2025-10-22 13:53:56.463169392 -0400 -@@ -1938,7 +1938,7 @@ static int get_init_otp_deassert_fragmen - int index, len; - - if (drm_WARN_ON(display->drm, -- !data || panel->vbt.dsi.seq_version != 1)) -+ !data || panel->vbt.dsi.seq_version >= 3)) - return 0; - - /* index = 1 to skip sequence byte */ -@@ -1961,7 +1961,7 @@ static int get_init_otp_deassert_fragmen - } - - /* -- * Some v1 VBT MIPI sequences do the deassert in the init OTP sequence. -+ * Some v1/v2 VBT MIPI sequences do the deassert in the init OTP sequence. - * The deassert must be done before calling intel_dsi_device_ready, so for - * these devices we split the init OTP sequence into a deassert sequence and - * the actual init OTP part. -@@ -1972,9 +1972,9 @@ static void vlv_fixup_mipi_sequences(str - u8 *init_otp; - int len; - -- /* Limit this to v1 vid-mode sequences */ -+ /* Limit this to v1/v2 vid-mode sequences */ - if (panel->vbt.dsi.config->is_cmd_mode || -- panel->vbt.dsi.seq_version != 1) -+ panel->vbt.dsi.seq_version >= 3) - return; - - /* Only do this if there are otp and assert seqs and no deassert seq */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/i915/display/intel_ddi.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/display/intel_ddi.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/i915/display/intel_ddi.c 2025-10-22 13:53:23.223329087 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/display/intel_ddi.c 2025-10-22 13:53:56.467169373 -0400 -@@ -593,8 +593,9 @@ intel_ddi_transcoder_func_reg_val_get(st - enum transcoder master; - - master = crtc_state->mst_master_transcoder; -- drm_WARN_ON(display->drm, -- master == INVALID_TRANSCODER); -+ if (drm_WARN_ON(display->drm, -+ master == INVALID_TRANSCODER)) -+ master = TRANSCODER_A; - temp |= TRANS_DDI_MST_TRANSPORT_SELECT(master); - } - } else { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/i915/display/intel_display.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/display/intel_display.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/i915/display/intel_display.c 2025-10-22 13:53:23.227329067 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/display/intel_display.c 2025-10-22 13:53:56.467169373 -0400 -@@ -7061,7 +7061,8 @@ static void intel_atomic_commit_fence_wa - struct drm_i915_private *i915 = to_i915(intel_state->base.dev); - struct drm_plane *plane; - struct drm_plane_state *new_plane_state; -- int ret, i; -+ long ret; -+ int i; - - for_each_new_plane_in_state(&intel_state->base, plane, new_plane_state, i) { - if (new_plane_state->fence) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/i915/display/intel_display_irq.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/display/intel_display_irq.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/i915/display/intel_display_irq.c 2025-10-22 13:53:23.227329067 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/display/intel_display_irq.c 2025-10-22 13:53:56.467169373 -0400 -@@ -1492,10 +1492,14 @@ u32 gen11_gu_misc_irq_ack(struct intel_d - if (!(master_ctl & GEN11_GU_MISC_IRQ)) - return 0; - -+ intel_display_rpm_assert_block(display); -+ - iir = intel_de_read(display, GEN11_GU_MISC_IIR); - if (likely(iir)) - intel_de_write(display, GEN11_GU_MISC_IIR, iir); - -+ intel_display_rpm_assert_unblock(display); -+ - return iir; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/i915/display/intel_display_power.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/display/intel_display_power.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/i915/display/intel_display_power.c 2025-10-22 13:53:23.227329067 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/display/intel_display_power.c 2025-10-22 13:53:56.467169373 -0400 -@@ -1169,7 +1169,7 @@ static void icl_mbus_init(struct intel_d - if (DISPLAY_VER(display) == 12) - abox_regs |= BIT(0); - -- for_each_set_bit(i, &abox_regs, sizeof(abox_regs)) -+ for_each_set_bit(i, &abox_regs, BITS_PER_TYPE(abox_regs)) - intel_de_rmw(display, MBUS_ABOX_CTL(i), mask, val); - } - -@@ -1630,11 +1630,11 @@ static void tgl_bw_buddy_init(struct int - if (table[config].page_mask == 0) { - drm_dbg_kms(display->drm, - "Unknown memory configuration; disabling address buddy logic.\n"); -- for_each_set_bit(i, &abox_mask, sizeof(abox_mask)) -+ for_each_set_bit(i, &abox_mask, BITS_PER_TYPE(abox_mask)) - intel_de_write(display, BW_BUDDY_CTL(i), - BW_BUDDY_DISABLE); - } else { -- for_each_set_bit(i, &abox_mask, sizeof(abox_mask)) { -+ for_each_set_bit(i, &abox_mask, BITS_PER_TYPE(abox_mask)) { - intel_de_write(display, BW_BUDDY_PAGE_MASK(i), - table[config].page_mask); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/i915/display/intel_dp.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/display/intel_dp.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/i915/display/intel_dp.c 2025-10-22 13:53:23.227329067 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/display/intel_dp.c 2025-10-22 13:53:56.467169373 -0400 -@@ -1604,6 +1604,12 @@ int intel_dp_rate_select(struct intel_dp - void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock, - u8 *link_bw, u8 *rate_select) - { -+ struct intel_display *display = to_intel_display(intel_dp); -+ -+ /* FIXME g4x can't generate an exact 2.7GHz with the 96MHz non-SSC refclk */ -+ if (display->platform.g4x && port_clock == 268800) -+ port_clock = 270000; -+ - /* eDP 1.4 rate select method. */ - if (intel_dp->use_rate_select) { - *link_bw = 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/i915/display/intel_fbc.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/display/intel_fbc.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/i915/display/intel_fbc.c 2025-10-22 13:53:23.227329067 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/display/intel_fbc.c 2025-10-22 13:53:56.467169373 -0400 -@@ -550,10 +550,6 @@ static void ilk_fbc_deactivate(struct in - if (dpfc_ctl & DPFC_CTL_EN) { - dpfc_ctl &= ~DPFC_CTL_EN; - intel_de_write(display, ILK_DPFC_CONTROL(fbc->id), dpfc_ctl); -- -- /* wa_18038517565 Enable DPFC clock gating after FBC disable */ -- if (display->platform.dg2 || DISPLAY_VER(display) >= 14) -- fbc_compressor_clkgate_disable_wa(fbc, false); - } - } - -@@ -1708,6 +1704,10 @@ static void __intel_fbc_disable(struct i - - __intel_fbc_cleanup_cfb(fbc); - -+ /* wa_18038517565 Enable DPFC clock gating after FBC disable */ -+ if (display->platform.dg2 || DISPLAY_VER(display) >= 14) -+ fbc_compressor_clkgate_disable_wa(fbc, false); -+ - fbc->state.plane = NULL; - fbc->flip_pending = false; - fbc->busy_bits = 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/i915/display/intel_psr.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/display/intel_psr.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/i915/display/intel_psr.c 2025-10-22 13:53:23.227329067 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/display/intel_psr.c 2025-10-22 13:53:56.467169373 -0400 -@@ -3250,7 +3250,9 @@ static void intel_psr_configure_full_fra - - static void _psr_invalidate_handle(struct intel_dp *intel_dp) - { -- if (intel_dp->psr.psr2_sel_fetch_enabled) { -+ struct intel_display *display = to_intel_display(intel_dp); -+ -+ if (DISPLAY_VER(display) < 20 && intel_dp->psr.psr2_sel_fetch_enabled) { - if (!intel_dp->psr.psr2_sel_fetch_cff_enabled) { - intel_dp->psr.psr2_sel_fetch_cff_enabled = true; - intel_psr_configure_full_frame_update(intel_dp); -@@ -3338,7 +3340,7 @@ static void _psr_flush_handle(struct int - struct intel_display *display = to_intel_display(intel_dp); - struct drm_i915_private *dev_priv = to_i915(display->drm); - -- if (intel_dp->psr.psr2_sel_fetch_enabled) { -+ if (DISPLAY_VER(display) < 20 && intel_dp->psr.psr2_sel_fetch_enabled) { - if (intel_dp->psr.psr2_sel_fetch_cff_enabled) { - /* can we turn CFF off? */ - if (intel_dp->psr.busy_frontbuffer_bits == 0) -@@ -3355,11 +3357,13 @@ static void _psr_flush_handle(struct int - * existing SU configuration - */ - intel_psr_configure_full_frame_update(intel_dp); -- } - -- intel_psr_force_update(intel_dp); -+ intel_psr_force_update(intel_dp); -+ } else { -+ intel_psr_exit(intel_dp); -+ } - -- if (!intel_dp->psr.psr2_sel_fetch_enabled && !intel_dp->psr.active && -+ if ((!intel_dp->psr.psr2_sel_fetch_enabled || DISPLAY_VER(display) >= 20) && - !intel_dp->psr.busy_frontbuffer_bits) - queue_work(dev_priv->unordered_wq, &intel_dp->psr.work); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c 2025-10-22 13:53:23.227329067 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c 2025-10-22 13:53:56.467169373 -0400 -@@ -103,8 +103,8 @@ static void get_ana_cp_int_prop(u64 vco_ - DIV_ROUND_DOWN_ULL(curve_1_interpolated, CURVE0_MULTIPLIER))); - - ana_cp_int_temp = -- DIV_ROUND_CLOSEST_ULL(DIV_ROUND_DOWN_ULL(adjusted_vco_clk1, curve_2_scaled1), -- CURVE2_MULTIPLIER); -+ DIV64_U64_ROUND_CLOSEST(DIV_ROUND_DOWN_ULL(adjusted_vco_clk1, curve_2_scaled1), -+ CURVE2_MULTIPLIER); - - *ana_cp_int = max(1, min(ana_cp_int_temp, 127)); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/i915/display/intel_tc.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/display/intel_tc.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/i915/display/intel_tc.c 2025-10-22 13:53:23.227329067 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/display/intel_tc.c 2025-10-22 13:53:56.467169373 -0400 -@@ -22,6 +22,7 @@ - #include "intel_modeset_lock.h" - #include "intel_tc.h" - -+#define DP_PIN_ASSIGNMENT_NONE 0x0 - #define DP_PIN_ASSIGNMENT_C 0x3 - #define DP_PIN_ASSIGNMENT_D 0x4 - #define DP_PIN_ASSIGNMENT_E 0x5 -@@ -65,6 +66,7 @@ struct intel_tc_port { - enum tc_port_mode init_mode; - enum phy_fia phy_fia; - u8 phy_fia_idx; -+ u8 max_lane_count; - }; - - static enum intel_display_power_domain -@@ -306,6 +308,8 @@ static int lnl_tc_port_get_max_lane_coun - REG_FIELD_GET(TCSS_DDI_STATUS_PIN_ASSIGNMENT_MASK, val); - - switch (pin_assignment) { -+ case DP_PIN_ASSIGNMENT_NONE: -+ return 0; - default: - MISSING_CASE(pin_assignment); - fallthrough; -@@ -364,12 +368,12 @@ static int intel_tc_port_get_max_lane_co - } - } - --int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port) -+static int get_max_lane_count(struct intel_tc_port *tc) - { -- struct intel_display *display = to_intel_display(dig_port); -- struct intel_tc_port *tc = to_tc_port(dig_port); -+ struct intel_display *display = to_intel_display(tc->dig_port); -+ struct intel_digital_port *dig_port = tc->dig_port; - -- if (!intel_encoder_is_tc(&dig_port->base) || tc->mode != TC_PORT_DP_ALT) -+ if (tc->mode != TC_PORT_DP_ALT) - return 4; - - assert_tc_cold_blocked(tc); -@@ -383,6 +387,25 @@ int intel_tc_port_max_lane_count(struct - return intel_tc_port_get_max_lane_count(dig_port); - } - -+static void read_pin_configuration(struct intel_tc_port *tc) -+{ -+ tc->max_lane_count = get_max_lane_count(tc); -+} -+ -+int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port) -+{ -+ struct intel_display *display = to_intel_display(dig_port); -+ struct intel_tc_port *tc = to_tc_port(dig_port); -+ -+ if (!intel_encoder_is_tc(&dig_port->base)) -+ return 4; -+ -+ if (DISPLAY_VER(display) < 20) -+ return get_max_lane_count(tc); -+ -+ return tc->max_lane_count; -+} -+ - void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port, - int required_lanes) - { -@@ -595,9 +618,12 @@ static void icl_tc_phy_get_hw_state(stru - tc_cold_wref = __tc_cold_block(tc, &domain); - - tc->mode = tc_phy_get_current_mode(tc); -- if (tc->mode != TC_PORT_DISCONNECTED) -+ if (tc->mode != TC_PORT_DISCONNECTED) { - tc->lock_wakeref = tc_cold_block(tc); - -+ read_pin_configuration(tc); -+ } -+ - __tc_cold_unblock(tc, domain, tc_cold_wref); - } - -@@ -655,8 +681,11 @@ static bool icl_tc_phy_connect(struct in - - tc->lock_wakeref = tc_cold_block(tc); - -- if (tc->mode == TC_PORT_TBT_ALT) -+ if (tc->mode == TC_PORT_TBT_ALT) { -+ read_pin_configuration(tc); -+ - return true; -+ } - - if ((!tc_phy_is_ready(tc) || - !icl_tc_phy_take_ownership(tc, true)) && -@@ -667,6 +696,7 @@ static bool icl_tc_phy_connect(struct in - goto out_unblock_tc_cold; - } - -+ read_pin_configuration(tc); - - if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes)) - goto out_release_phy; -@@ -857,9 +887,12 @@ static void adlp_tc_phy_get_hw_state(str - port_wakeref = intel_display_power_get(display, port_power_domain); - - tc->mode = tc_phy_get_current_mode(tc); -- if (tc->mode != TC_PORT_DISCONNECTED) -+ if (tc->mode != TC_PORT_DISCONNECTED) { - tc->lock_wakeref = tc_cold_block(tc); - -+ read_pin_configuration(tc); -+ } -+ - intel_display_power_put(display, port_power_domain, port_wakeref); - } - -@@ -872,6 +905,9 @@ static bool adlp_tc_phy_connect(struct i - - if (tc->mode == TC_PORT_TBT_ALT) { - tc->lock_wakeref = tc_cold_block(tc); -+ -+ read_pin_configuration(tc); -+ - return true; - } - -@@ -893,6 +929,8 @@ static bool adlp_tc_phy_connect(struct i - - tc->lock_wakeref = tc_cold_block(tc); - -+ read_pin_configuration(tc); -+ - if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes)) - goto out_unblock_tc_cold; - -@@ -1123,9 +1161,18 @@ static void xelpdp_tc_phy_get_hw_state(s - tc_cold_wref = __tc_cold_block(tc, &domain); - - tc->mode = tc_phy_get_current_mode(tc); -- if (tc->mode != TC_PORT_DISCONNECTED) -+ if (tc->mode != TC_PORT_DISCONNECTED) { - tc->lock_wakeref = tc_cold_block(tc); - -+ read_pin_configuration(tc); -+ /* -+ * Set a valid lane count value for a DP-alt sink which got -+ * disconnected. The driver can only disable the output on this PHY. -+ */ -+ if (tc->max_lane_count == 0) -+ tc->max_lane_count = 4; -+ } -+ - drm_WARN_ON(display->drm, - (tc->mode == TC_PORT_DP_ALT || tc->mode == TC_PORT_LEGACY) && - !xelpdp_tc_phy_tcss_power_is_enabled(tc)); -@@ -1137,14 +1184,19 @@ static bool xelpdp_tc_phy_connect(struct - { - tc->lock_wakeref = tc_cold_block(tc); - -- if (tc->mode == TC_PORT_TBT_ALT) -+ if (tc->mode == TC_PORT_TBT_ALT) { -+ read_pin_configuration(tc); -+ - return true; -+ } - - if (!xelpdp_tc_phy_enable_tcss_power(tc, true)) - goto out_unblock_tccold; - - xelpdp_tc_phy_take_ownership(tc, true); - -+ read_pin_configuration(tc); -+ - if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes)) - goto out_release_phy; - -@@ -1225,14 +1277,19 @@ static void tc_phy_get_hw_state(struct i - tc->phy_ops->get_hw_state(tc); - } - --static bool tc_phy_is_ready_and_owned(struct intel_tc_port *tc, -- bool phy_is_ready, bool phy_is_owned) -+/* Is the PHY owned by display i.e. is it in legacy or DP-alt mode? */ -+static bool tc_phy_owned_by_display(struct intel_tc_port *tc, -+ bool phy_is_ready, bool phy_is_owned) - { - struct intel_display *display = to_intel_display(tc->dig_port); - -- drm_WARN_ON(display->drm, phy_is_owned && !phy_is_ready); -+ if (DISPLAY_VER(display) < 20) { -+ drm_WARN_ON(display->drm, phy_is_owned && !phy_is_ready); - -- return phy_is_ready && phy_is_owned; -+ return phy_is_ready && phy_is_owned; -+ } else { -+ return phy_is_owned; -+ } - } - - static bool tc_phy_is_connected(struct intel_tc_port *tc, -@@ -1243,7 +1300,7 @@ static bool tc_phy_is_connected(struct i - bool phy_is_owned = tc_phy_is_owned(tc); - bool is_connected; - -- if (tc_phy_is_ready_and_owned(tc, phy_is_ready, phy_is_owned)) -+ if (tc_phy_owned_by_display(tc, phy_is_ready, phy_is_owned)) - is_connected = port_pll_type == ICL_PORT_DPLL_MG_PHY; - else - is_connected = port_pll_type == ICL_PORT_DPLL_DEFAULT; -@@ -1351,7 +1408,7 @@ tc_phy_get_current_mode(struct intel_tc_ - phy_is_ready = tc_phy_is_ready(tc); - phy_is_owned = tc_phy_is_owned(tc); - -- if (!tc_phy_is_ready_and_owned(tc, phy_is_ready, phy_is_owned)) { -+ if (!tc_phy_owned_by_display(tc, phy_is_ready, phy_is_owned)) { - mode = get_tc_mode_in_phy_not_owned_state(tc, live_mode); - } else { - drm_WARN_ON(display->drm, live_mode == TC_PORT_TBT_ALT); -@@ -1440,11 +1497,11 @@ static void intel_tc_port_reset_mode(str - intel_display_power_flush_work(display); - if (!intel_tc_cold_requires_aux_pw(dig_port)) { - enum intel_display_power_domain aux_domain; -- bool aux_powered; - - aux_domain = intel_aux_power_domain(dig_port); -- aux_powered = intel_display_power_is_enabled(display, aux_domain); -- drm_WARN_ON(display->drm, aux_powered); -+ if (intel_display_power_is_enabled(display, aux_domain)) -+ drm_dbg_kms(display->drm, "Port %s: AUX unexpectedly powered\n", -+ tc->port_name); - } - - tc_phy_disconnect(tc); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/i915/display/vlv_dsi.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/display/vlv_dsi.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/i915/display/vlv_dsi.c 2025-10-22 13:53:23.227329067 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/display/vlv_dsi.c 2025-10-22 13:53:56.467169373 -0400 -@@ -1056,7 +1056,7 @@ static void bxt_dsi_get_pipe_config(stru - BXT_MIPI_TRANS_VACTIVE(port)); - adjusted_mode->crtc_vtotal = - intel_de_read(display, -- BXT_MIPI_TRANS_VTOTAL(port)); -+ BXT_MIPI_TRANS_VTOTAL(port)) + 1; - - hactive = adjusted_mode->crtc_hdisplay; - hfp = intel_de_read(display, MIPI_HFP_COUNT(display, port)); -@@ -1260,7 +1260,7 @@ static void set_dsi_timings(struct intel - intel_de_write(display, BXT_MIPI_TRANS_VACTIVE(port), - adjusted_mode->crtc_vdisplay); - intel_de_write(display, BXT_MIPI_TRANS_VTOTAL(port), -- adjusted_mode->crtc_vtotal); -+ adjusted_mode->crtc_vtotal - 1); - } - - intel_de_write(display, MIPI_HACTIVE_AREA_COUNT(display, port), -@@ -1589,8 +1589,8 @@ static void vlv_dsi_add_properties(struc - - static void vlv_dphy_param_init(struct intel_dsi *intel_dsi) - { -+ struct intel_display *display = to_intel_display(&intel_dsi->base); - struct intel_connector *connector = intel_dsi->attached_connector; -- struct intel_display *display = to_intel_display(connector); - struct mipi_config *mipi_config = connector->panel.vbt.dsi.config; - u32 tlpx_ns, extra_byte_count, tlpx_ui; - u32 ui_num, ui_den; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/i915/gt/intel_gsc.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/gt/intel_gsc.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/i915/gt/intel_gsc.c 2025-10-22 13:53:23.227329067 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/gt/intel_gsc.c 2025-10-22 13:53:56.467169373 -0400 -@@ -284,7 +284,7 @@ static void gsc_irq_handler(struct intel - if (gt->gsc.intf[intf_id].irq < 0) - return; - -- ret = generic_handle_irq(gt->gsc.intf[intf_id].irq); -+ ret = generic_handle_irq_safe(gt->gsc.intf[intf_id].irq); - if (ret) - gt_err_ratelimited(gt, "error handling GSC irq: %d\n", ret); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/i915/gt/intel_ring_submission.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/gt/intel_ring_submission.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/i915/gt/intel_ring_submission.c 2025-10-22 13:53:23.227329067 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/gt/intel_ring_submission.c 2025-10-22 13:53:56.467169373 -0400 -@@ -610,7 +610,6 @@ static int ring_context_alloc(struct int - /* One ringbuffer to rule them all */ - GEM_BUG_ON(!engine->legacy.ring); - ce->ring = engine->legacy.ring; -- ce->timeline = intel_timeline_get(engine->legacy.timeline); - - GEM_BUG_ON(ce->state); - if (engine->context_size) { -@@ -623,6 +622,8 @@ static int ring_context_alloc(struct int - ce->state = vma; - } - -+ ce->timeline = intel_timeline_get(engine->legacy.timeline); -+ - return 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/i915/gt/intel_workarounds.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/gt/intel_workarounds.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/i915/gt/intel_workarounds.c 2025-10-22 13:53:23.227329067 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/gt/intel_workarounds.c 2025-10-22 13:53:56.467169373 -0400 -@@ -634,6 +634,8 @@ static void cfl_ctx_workarounds_init(str - static void icl_ctx_workarounds_init(struct intel_engine_cs *engine, - struct i915_wa_list *wal) - { -+ struct drm_i915_private *i915 = engine->i915; -+ - /* Wa_1406697149 (WaDisableBankHangMode:icl) */ - wa_write(wal, GEN8_L3CNTLREG, GEN8_ERRDETBCTRL); - -@@ -669,6 +671,15 @@ static void icl_ctx_workarounds_init(str - - /* Wa_1406306137:icl,ehl */ - wa_mcr_masked_en(wal, GEN9_ROW_CHICKEN4, GEN11_DIS_PICK_2ND_EU); -+ -+ if (IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) { -+ /* -+ * Disable Repacking for Compression (masked R/W access) -+ * before rendering compressed surfaces for display. -+ */ -+ wa_masked_en(wal, CACHE_MODE_0_GEN7, -+ DISABLE_REPACKING_FOR_COMPRESSION); -+ } - } - - /* -@@ -2306,15 +2317,6 @@ rcs_engine_wa_init(struct intel_engine_c - GEN8_RC_SEMA_IDLE_MSG_DISABLE); - } - -- if (IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) { -- /* -- * "Disable Repacking for Compression (masked R/W access) -- * before rendering compressed surfaces for display." -- */ -- wa_masked_en(wal, CACHE_MODE_0_GEN7, -- DISABLE_REPACKING_FOR_COMPRESSION); -- } -- - if (GRAPHICS_VER(i915) == 11) { - /* This is not an Wa. Enable for better image quality */ - wa_masked_en(wal, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/i915/i915_pmu.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/i915_pmu.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/i915/i915_pmu.c 2025-10-22 13:53:23.227329067 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/i915_pmu.c 2025-10-22 13:53:56.471169353 -0400 -@@ -108,11 +108,11 @@ static unsigned int config_bit(const u64 - return other_bit(config); - } - --static u32 config_mask(const u64 config) -+static __always_inline u32 config_mask(const u64 config) - { - unsigned int bit = config_bit(config); - -- if (__builtin_constant_p(config)) -+ if (__builtin_constant_p(bit)) - BUILD_BUG_ON(bit > - BITS_PER_TYPE(typeof_member(struct i915_pmu, - enable)) - 1); -@@ -121,7 +121,7 @@ static u32 config_mask(const u64 config) - BITS_PER_TYPE(typeof_member(struct i915_pmu, - enable)) - 1); - -- return BIT(config_bit(config)); -+ return BIT(bit); - } - - static bool is_engine_event(struct perf_event *event) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/i915/selftests/i915_request.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/selftests/i915_request.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/i915/selftests/i915_request.c 2025-10-22 13:53:23.227329067 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/selftests/i915_request.c 2025-10-22 13:53:56.471169353 -0400 -@@ -73,8 +73,8 @@ static int igt_add_request(void *arg) - /* Basic preliminary test to create a request and let it loose! */ - - request = mock_request(rcs0(i915)->kernel_context, HZ / 10); -- if (!request) -- return -ENOMEM; -+ if (IS_ERR(request)) -+ return PTR_ERR(request); - - i915_request_add(request); - -@@ -91,8 +91,8 @@ static int igt_wait_request(void *arg) - /* Submit a request, then wait upon it */ - - request = mock_request(rcs0(i915)->kernel_context, T); -- if (!request) -- return -ENOMEM; -+ if (IS_ERR(request)) -+ return PTR_ERR(request); - - i915_request_get(request); - -@@ -160,8 +160,8 @@ static int igt_fence_wait(void *arg) - /* Submit a request, treat it as a fence and wait upon it */ - - request = mock_request(rcs0(i915)->kernel_context, T); -- if (!request) -- return -ENOMEM; -+ if (IS_ERR(request)) -+ return PTR_ERR(request); - - if (dma_fence_wait_timeout(&request->fence, false, T) != -ETIME) { - pr_err("fence wait success before submit (expected timeout)!\n"); -@@ -219,8 +219,8 @@ static int igt_request_rewind(void *arg) - GEM_BUG_ON(IS_ERR(ce)); - request = mock_request(ce, 2 * HZ); - intel_context_put(ce); -- if (!request) { -- err = -ENOMEM; -+ if (IS_ERR(request)) { -+ err = PTR_ERR(request); - goto err_context_0; - } - -@@ -237,8 +237,8 @@ static int igt_request_rewind(void *arg) - GEM_BUG_ON(IS_ERR(ce)); - vip = mock_request(ce, 0); - intel_context_put(ce); -- if (!vip) { -- err = -ENOMEM; -+ if (IS_ERR(vip)) { -+ err = PTR_ERR(vip); - goto err_context_1; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/i915/selftests/mock_request.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/selftests/mock_request.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/i915/selftests/mock_request.c 2025-10-22 13:53:23.227329067 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/i915/selftests/mock_request.c 2025-10-22 13:53:56.471169353 -0400 -@@ -35,7 +35,7 @@ mock_request(struct intel_context *ce, u - /* NB the i915->requests slab cache is enlarged to fit mock_request */ - request = intel_context_create_request(ce); - if (IS_ERR(request)) -- return NULL; -+ return request; - - request->mock.delay = delay; - return request; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/imagination/pvr_power.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/imagination/pvr_power.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/imagination/pvr_power.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/imagination/pvr_power.c 2025-10-22 13:53:56.471169353 -0400 -@@ -340,6 +340,63 @@ pvr_power_device_idle(struct device *dev - return pvr_power_is_idle(pvr_dev) ? 0 : -EBUSY; - } - -+static int -+pvr_power_clear_error(struct pvr_device *pvr_dev) -+{ -+ struct device *dev = from_pvr_device(pvr_dev)->dev; -+ int err; -+ -+ /* Ensure the device state is known and nothing is happening past this point */ -+ pm_runtime_disable(dev); -+ -+ /* Attempt to clear the runtime PM error by setting the current state again */ -+ if (pm_runtime_status_suspended(dev)) -+ err = pm_runtime_set_suspended(dev); -+ else -+ err = pm_runtime_set_active(dev); -+ -+ if (err) { -+ drm_err(from_pvr_device(pvr_dev), -+ "%s: Failed to clear runtime PM error (new error %d)\n", -+ __func__, err); -+ } -+ -+ pm_runtime_enable(dev); -+ -+ return err; -+} -+ -+/** -+ * pvr_power_get_clear() - Acquire a power reference, correcting any errors -+ * @pvr_dev: Device pointer -+ * -+ * Attempt to acquire a power reference on the device. If the runtime PM -+ * is in error state, attempt to clear the error and retry. -+ * -+ * Returns: -+ * * 0 on success, or -+ * * Any error code returned by pvr_power_get() or the runtime PM API. -+ */ -+static int -+pvr_power_get_clear(struct pvr_device *pvr_dev) -+{ -+ int err; -+ -+ err = pvr_power_get(pvr_dev); -+ if (err == 0) -+ return err; -+ -+ drm_warn(from_pvr_device(pvr_dev), -+ "%s: pvr_power_get returned error %d, attempting recovery\n", -+ __func__, err); -+ -+ err = pvr_power_clear_error(pvr_dev); -+ if (err) -+ return err; -+ -+ return pvr_power_get(pvr_dev); -+} -+ - /** - * pvr_power_reset() - Reset the GPU - * @pvr_dev: Device pointer -@@ -364,7 +421,7 @@ pvr_power_reset(struct pvr_device *pvr_d - * Take a power reference during the reset. This should prevent any interference with the - * power state during reset. - */ -- WARN_ON(pvr_power_get(pvr_dev)); -+ WARN_ON(pvr_power_get_clear(pvr_dev)); - - down_write(&pvr_dev->reset_sem); - -@@ -386,13 +443,13 @@ pvr_power_reset(struct pvr_device *pvr_d - if (!err) { - if (hard_reset) { - pvr_dev->fw_dev.booted = false; -- WARN_ON(pm_runtime_force_suspend(from_pvr_device(pvr_dev)->dev)); -+ WARN_ON(pvr_power_device_suspend(from_pvr_device(pvr_dev)->dev)); - - err = pvr_fw_hard_reset(pvr_dev); - if (err) - goto err_device_lost; - -- err = pm_runtime_force_resume(from_pvr_device(pvr_dev)->dev); -+ err = pvr_power_device_resume(from_pvr_device(pvr_dev)->dev); - pvr_dev->fw_dev.booted = true; - if (err) - goto err_device_lost; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/mediatek/mtk_crtc.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mediatek/mtk_crtc.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/mediatek/mtk_crtc.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mediatek/mtk_crtc.c 2025-10-22 13:53:56.471169353 -0400 -@@ -719,6 +719,39 @@ int mtk_crtc_plane_check(struct drm_crtc - return 0; - } - -+void mtk_crtc_plane_disable(struct drm_crtc *crtc, struct drm_plane *plane) -+{ -+#if IS_REACHABLE(CONFIG_MTK_CMDQ) -+ struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc); -+ struct mtk_plane_state *plane_state = to_mtk_plane_state(plane->state); -+ int i; -+ -+ /* no need to wait for disabling the plane by CPU */ -+ if (!mtk_crtc->cmdq_client.chan) -+ return; -+ -+ if (!mtk_crtc->enabled) -+ return; -+ -+ /* set pending plane state to disabled */ -+ for (i = 0; i < mtk_crtc->layer_nr; i++) { -+ struct drm_plane *mtk_plane = &mtk_crtc->planes[i]; -+ struct mtk_plane_state *mtk_plane_state = to_mtk_plane_state(mtk_plane->state); -+ -+ if (mtk_plane->index == plane->index) { -+ memcpy(mtk_plane_state, plane_state, sizeof(*plane_state)); -+ break; -+ } -+ } -+ mtk_crtc_update_config(mtk_crtc, false); -+ -+ /* wait for planes to be disabled by CMDQ */ -+ wait_event_timeout(mtk_crtc->cb_blocking_queue, -+ mtk_crtc->cmdq_vblank_cnt == 0, -+ msecs_to_jiffies(500)); -+#endif -+} -+ - void mtk_crtc_async_update(struct drm_crtc *crtc, struct drm_plane *plane, - struct drm_atomic_state *state) - { -@@ -930,7 +963,8 @@ static int mtk_crtc_init_comp_planes(str - mtk_ddp_comp_supported_rotations(comp), - mtk_ddp_comp_get_blend_modes(comp), - mtk_ddp_comp_get_formats(comp), -- mtk_ddp_comp_get_num_formats(comp), i); -+ mtk_ddp_comp_get_num_formats(comp), -+ mtk_ddp_comp_is_afbc_supported(comp), i); - if (ret) - return ret; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/mediatek/mtk_crtc.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mediatek/mtk_crtc.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/mediatek/mtk_crtc.h 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mediatek/mtk_crtc.h 2025-10-22 13:53:56.471169353 -0400 -@@ -21,6 +21,7 @@ int mtk_crtc_create(struct drm_device *d - unsigned int num_conn_routes); - int mtk_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane, - struct mtk_plane_state *state); -+void mtk_crtc_plane_disable(struct drm_crtc *crtc, struct drm_plane *plane); - void mtk_crtc_async_update(struct drm_crtc *crtc, struct drm_plane *plane, - struct drm_atomic_state *plane_state); - struct device *mtk_crtc_dma_dev_get(struct drm_crtc *crtc); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/mediatek/mtk_ddp_comp.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mediatek/mtk_ddp_comp.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/mediatek/mtk_ddp_comp.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mediatek/mtk_ddp_comp.c 2025-10-22 13:53:56.471169353 -0400 -@@ -366,6 +366,7 @@ static const struct mtk_ddp_comp_funcs d - .get_blend_modes = mtk_ovl_get_blend_modes, - .get_formats = mtk_ovl_get_formats, - .get_num_formats = mtk_ovl_get_num_formats, -+ .is_afbc_supported = mtk_ovl_is_afbc_supported, - }; - - static const struct mtk_ddp_comp_funcs ddp_postmask = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/mediatek/mtk_ddp_comp.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mediatek/mtk_ddp_comp.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/mediatek/mtk_ddp_comp.h 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mediatek/mtk_ddp_comp.h 2025-10-22 13:53:56.471169353 -0400 -@@ -83,6 +83,7 @@ struct mtk_ddp_comp_funcs { - u32 (*get_blend_modes)(struct device *dev); - const u32 *(*get_formats)(struct device *dev); - size_t (*get_num_formats)(struct device *dev); -+ bool (*is_afbc_supported)(struct device *dev); - void (*connect)(struct device *dev, struct device *mmsys_dev, unsigned int next); - void (*disconnect)(struct device *dev, struct device *mmsys_dev, unsigned int next); - void (*add)(struct device *dev, struct mtk_mutex *mutex); -@@ -294,6 +295,14 @@ size_t mtk_ddp_comp_get_num_formats(stru - return 0; - } - -+static inline bool mtk_ddp_comp_is_afbc_supported(struct mtk_ddp_comp *comp) -+{ -+ if (comp->funcs && comp->funcs->is_afbc_supported) -+ return comp->funcs->is_afbc_supported(comp->dev); -+ -+ return false; -+} -+ - static inline bool mtk_ddp_comp_add(struct mtk_ddp_comp *comp, struct mtk_mutex *mutex) - { - if (comp->funcs && comp->funcs->add) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/mediatek/mtk_disp_drv.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mediatek/mtk_disp_drv.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/mediatek/mtk_disp_drv.h 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mediatek/mtk_disp_drv.h 2025-10-22 13:53:56.471169353 -0400 -@@ -106,6 +106,7 @@ void mtk_ovl_disable_vblank(struct devic - u32 mtk_ovl_get_blend_modes(struct device *dev); - const u32 *mtk_ovl_get_formats(struct device *dev); - size_t mtk_ovl_get_num_formats(struct device *dev); -+bool mtk_ovl_is_afbc_supported(struct device *dev); - - void mtk_ovl_adaptor_add_comp(struct device *dev, struct mtk_mutex *mutex); - void mtk_ovl_adaptor_remove_comp(struct device *dev, struct mtk_mutex *mutex); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/mediatek/mtk_disp_ovl.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mediatek/mtk_disp_ovl.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/mediatek/mtk_disp_ovl.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mediatek/mtk_disp_ovl.c 2025-10-22 13:53:56.471169353 -0400 -@@ -236,6 +236,13 @@ size_t mtk_ovl_get_num_formats(struct de - return ovl->data->num_formats; - } - -+bool mtk_ovl_is_afbc_supported(struct device *dev) -+{ -+ struct mtk_disp_ovl *ovl = dev_get_drvdata(dev); -+ -+ return ovl->data->supports_afbc; -+} -+ - int mtk_ovl_clk_enable(struct device *dev) - { - struct mtk_disp_ovl *ovl = dev_get_drvdata(dev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/mediatek/mtk_dpi.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mediatek/mtk_dpi.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/mediatek/mtk_dpi.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mediatek/mtk_dpi.c 2025-10-22 13:53:56.471169353 -0400 -@@ -1095,7 +1095,6 @@ static const u32 mt8183_output_fmts[] = - }; - - static const u32 mt8195_dpi_output_fmts[] = { -- MEDIA_BUS_FMT_BGR888_1X24, - MEDIA_BUS_FMT_RGB888_1X24, - MEDIA_BUS_FMT_RGB888_2X12_LE, - MEDIA_BUS_FMT_RGB888_2X12_BE, -@@ -1103,18 +1102,19 @@ static const u32 mt8195_dpi_output_fmts[ - MEDIA_BUS_FMT_YUYV8_1X16, - MEDIA_BUS_FMT_YUYV10_1X20, - MEDIA_BUS_FMT_YUYV12_1X24, -+ MEDIA_BUS_FMT_BGR888_1X24, - MEDIA_BUS_FMT_YUV8_1X24, - MEDIA_BUS_FMT_YUV10_1X30, - }; - - static const u32 mt8195_dp_intf_output_fmts[] = { -- MEDIA_BUS_FMT_BGR888_1X24, - MEDIA_BUS_FMT_RGB888_1X24, - MEDIA_BUS_FMT_RGB888_2X12_LE, - MEDIA_BUS_FMT_RGB888_2X12_BE, - MEDIA_BUS_FMT_RGB101010_1X30, - MEDIA_BUS_FMT_YUYV8_1X16, - MEDIA_BUS_FMT_YUYV10_1X20, -+ MEDIA_BUS_FMT_BGR888_1X24, - MEDIA_BUS_FMT_YUV8_1X24, - MEDIA_BUS_FMT_YUV10_1X30, - }; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/mediatek/mtk_drm_drv.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mediatek/mtk_drm_drv.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/mediatek/mtk_drm_drv.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mediatek/mtk_drm_drv.c 2025-10-22 13:53:56.471169353 -0400 -@@ -396,11 +396,11 @@ static bool mtk_drm_get_all_drm_priv(str - - drm_dev = device_find_child(&pdev->dev, NULL, mtk_drm_match); - if (!drm_dev) -- continue; -+ goto next_put_device_pdev_dev; - - temp_drm_priv = dev_get_drvdata(drm_dev); - if (!temp_drm_priv) -- continue; -+ goto next_put_device_drm_dev; - - if (temp_drm_priv->data->main_len) - all_drm_priv[CRTC_MAIN] = temp_drm_priv; -@@ -412,6 +412,12 @@ static bool mtk_drm_get_all_drm_priv(str - if (temp_drm_priv->mtk_drm_bound) - cnt++; - -+next_put_device_drm_dev: -+ put_device(drm_dev); -+ -+next_put_device_pdev_dev: -+ put_device(&pdev->dev); -+ - if (cnt == MAX_CRTC) { - of_node_put(node); - break; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/mediatek/mtk_hdmi.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mediatek/mtk_hdmi.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/mediatek/mtk_hdmi.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mediatek/mtk_hdmi.c 2025-10-22 13:53:56.471169353 -0400 -@@ -182,8 +182,8 @@ static inline struct mtk_hdmi *hdmi_ctx_ - - static void mtk_hdmi_hw_vid_black(struct mtk_hdmi *hdmi, bool black) - { -- regmap_update_bits(hdmi->regs, VIDEO_SOURCE_SEL, -- VIDEO_CFG_4, black ? GEN_RGB : NORMAL_PATH); -+ regmap_update_bits(hdmi->regs, VIDEO_CFG_4, -+ VIDEO_SOURCE_SEL, black ? GEN_RGB : NORMAL_PATH); - } - - static void mtk_hdmi_hw_make_reg_writable(struct mtk_hdmi *hdmi, bool enable) -@@ -310,8 +310,8 @@ static void mtk_hdmi_hw_send_info_frame( - - static void mtk_hdmi_hw_send_aud_packet(struct mtk_hdmi *hdmi, bool enable) - { -- regmap_update_bits(hdmi->regs, AUDIO_PACKET_OFF, -- GRL_SHIFT_R2, enable ? 0 : AUDIO_PACKET_OFF); -+ regmap_update_bits(hdmi->regs, GRL_SHIFT_R2, -+ AUDIO_PACKET_OFF, enable ? 0 : AUDIO_PACKET_OFF); - } - - static void mtk_hdmi_hw_config_sys(struct mtk_hdmi *hdmi) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/mediatek/mtk_plane.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mediatek/mtk_plane.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/mediatek/mtk_plane.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mediatek/mtk_plane.c 2025-10-22 13:53:56.471169353 -0400 -@@ -285,9 +285,15 @@ static void mtk_plane_atomic_disable(str - struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, - plane); - struct mtk_plane_state *mtk_plane_state = to_mtk_plane_state(new_state); -+ struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, -+ plane); -+ - mtk_plane_state->pending.enable = false; - wmb(); /* Make sure the above parameter is set before update */ - mtk_plane_state->pending.dirty = true; -+ -+ if (old_state && old_state->crtc) -+ mtk_crtc_plane_disable(old_state->crtc, plane); - } - - static void mtk_plane_atomic_update(struct drm_plane *plane, -@@ -321,7 +327,8 @@ static const struct drm_plane_helper_fun - int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane, - unsigned long possible_crtcs, enum drm_plane_type type, - unsigned int supported_rotations, const u32 blend_modes, -- const u32 *formats, size_t num_formats, unsigned int plane_idx) -+ const u32 *formats, size_t num_formats, -+ bool supports_afbc, unsigned int plane_idx) - { - int err; - -@@ -332,7 +339,9 @@ int mtk_plane_init(struct drm_device *de - - err = drm_universal_plane_init(dev, plane, possible_crtcs, - &mtk_plane_funcs, formats, -- num_formats, modifiers, type, NULL); -+ num_formats, -+ supports_afbc ? modifiers : NULL, -+ type, NULL); - if (err) { - DRM_ERROR("failed to initialize plane\n"); - return err; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/mediatek/mtk_plane.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mediatek/mtk_plane.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/mediatek/mtk_plane.h 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mediatek/mtk_plane.h 2025-10-22 13:53:56.471169353 -0400 -@@ -49,5 +49,6 @@ to_mtk_plane_state(struct drm_plane_stat - int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane, - unsigned long possible_crtcs, enum drm_plane_type type, - unsigned int supported_rotations, const u32 blend_modes, -- const u32 *formats, size_t num_formats, unsigned int plane_idx); -+ const u32 *formats, size_t num_formats, -+ bool supports_afbc, unsigned int plane_idx); - #endif -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/meson/meson_encoder_hdmi.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/meson/meson_encoder_hdmi.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/meson/meson_encoder_hdmi.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/meson/meson_encoder_hdmi.c 2025-10-22 13:53:56.471169353 -0400 -@@ -109,7 +109,7 @@ static void meson_encoder_hdmi_set_vclk( - venc_freq /= 2; - - dev_dbg(priv->dev, -- "vclk:%lluHz phy=%lluHz venc=%lluHz hdmi=%lluHz enci=%d\n", -+ "phy:%lluHz vclk=%lluHz venc=%lluHz hdmi=%lluHz enci=%d\n", - phy_freq, vclk_freq, venc_freq, hdmi_freq, - priv->venc.hdmi_use_enci); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/meson/meson_vclk.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/meson/meson_vclk.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/meson/meson_vclk.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/meson/meson_vclk.c 2025-10-22 13:53:56.471169353 -0400 -@@ -110,10 +110,7 @@ - #define HDMI_PLL_LOCK BIT(31) - #define HDMI_PLL_LOCK_G12A (3 << 30) - --#define PIXEL_FREQ_1000_1001(_freq) \ -- DIV_ROUND_CLOSEST_ULL((_freq) * 1000ULL, 1001ULL) --#define PHY_FREQ_1000_1001(_freq) \ -- (PIXEL_FREQ_1000_1001(DIV_ROUND_DOWN_ULL(_freq, 10ULL)) * 10) -+#define FREQ_1000_1001(_freq) DIV_ROUND_CLOSEST_ULL((_freq) * 1000ULL, 1001ULL) - - /* VID PLL Dividers */ - enum { -@@ -772,6 +769,36 @@ static void meson_hdmi_pll_generic_set(s - pll_freq); - } - -+static bool meson_vclk_freqs_are_matching_param(unsigned int idx, -+ unsigned long long phy_freq, -+ unsigned long long vclk_freq) -+{ -+ DRM_DEBUG_DRIVER("i = %d vclk_freq = %lluHz alt = %lluHz\n", -+ idx, params[idx].vclk_freq, -+ FREQ_1000_1001(params[idx].vclk_freq)); -+ DRM_DEBUG_DRIVER("i = %d phy_freq = %lluHz alt = %lluHz\n", -+ idx, params[idx].phy_freq, -+ FREQ_1000_1001(params[idx].phy_freq)); -+ -+ /* Match strict frequency */ -+ if (phy_freq == params[idx].phy_freq && -+ vclk_freq == params[idx].vclk_freq) -+ return true; -+ -+ /* Match 1000/1001 variant: vclk deviation has to be less than 1kHz -+ * (drm EDID is defined in 1kHz steps, so everything smaller must be -+ * rounding error) and the PHY freq deviation has to be less than -+ * 10kHz (as the TMDS clock is 10 times the pixel clock, so anything -+ * smaller must be rounding error as well). -+ */ -+ if (abs(vclk_freq - FREQ_1000_1001(params[idx].vclk_freq)) < 1000 && -+ abs(phy_freq - FREQ_1000_1001(params[idx].phy_freq)) < 10000) -+ return true; -+ -+ /* no match */ -+ return false; -+} -+ - enum drm_mode_status - meson_vclk_vic_supported_freq(struct meson_drm *priv, - unsigned long long phy_freq, -@@ -790,19 +817,7 @@ meson_vclk_vic_supported_freq(struct mes - } - - for (i = 0 ; params[i].pixel_freq ; ++i) { -- DRM_DEBUG_DRIVER("i = %d pixel_freq = %lluHz alt = %lluHz\n", -- i, params[i].pixel_freq, -- PIXEL_FREQ_1000_1001(params[i].pixel_freq)); -- DRM_DEBUG_DRIVER("i = %d phy_freq = %lluHz alt = %lluHz\n", -- i, params[i].phy_freq, -- PHY_FREQ_1000_1001(params[i].phy_freq)); -- /* Match strict frequency */ -- if (phy_freq == params[i].phy_freq && -- vclk_freq == params[i].vclk_freq) -- return MODE_OK; -- /* Match 1000/1001 variant */ -- if (phy_freq == PHY_FREQ_1000_1001(params[i].phy_freq) && -- vclk_freq == PIXEL_FREQ_1000_1001(params[i].vclk_freq)) -+ if (meson_vclk_freqs_are_matching_param(i, phy_freq, vclk_freq)) - return MODE_OK; - } - -@@ -1075,10 +1090,8 @@ void meson_vclk_setup(struct meson_drm * - } - - for (freq = 0 ; params[freq].pixel_freq ; ++freq) { -- if ((phy_freq == params[freq].phy_freq || -- phy_freq == PHY_FREQ_1000_1001(params[freq].phy_freq)) && -- (vclk_freq == params[freq].vclk_freq || -- vclk_freq == PIXEL_FREQ_1000_1001(params[freq].vclk_freq))) { -+ if (meson_vclk_freqs_are_matching_param(freq, phy_freq, -+ vclk_freq)) { - if (vclk_freq != params[freq].vclk_freq) - vic_alternate_clock = true; - else -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/mgag200/mgag200_ddc.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mgag200/mgag200_ddc.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/mgag200/mgag200_ddc.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/mgag200/mgag200_ddc.c 2025-10-22 13:53:56.471169353 -0400 -@@ -26,7 +26,6 @@ - * Authors: Dave Airlie - */ - --#include - #include - #include - #include -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/a2xx_gpummu.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/a2xx_gpummu.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/a2xx_gpummu.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/a2xx_gpummu.c 2025-10-22 13:53:56.471169353 -0400 -@@ -71,10 +71,6 @@ static int a2xx_gpummu_unmap(struct msm_ - return 0; - } - --static void a2xx_gpummu_resume_translation(struct msm_mmu *mmu) --{ --} -- - static void a2xx_gpummu_destroy(struct msm_mmu *mmu) - { - struct a2xx_gpummu *gpummu = to_a2xx_gpummu(mmu); -@@ -90,7 +86,6 @@ static const struct msm_mmu_funcs funcs - .map = a2xx_gpummu_map, - .unmap = a2xx_gpummu_unmap, - .destroy = a2xx_gpummu_destroy, -- .resume_translation = a2xx_gpummu_resume_translation, - }; - - struct msm_mmu *a2xx_gpummu_new(struct device *dev, struct msm_gpu *gpu) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/a5xx_gpu.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/a5xx_gpu.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 2025-10-22 13:53:56.471169353 -0400 -@@ -131,6 +131,8 @@ static void a5xx_submit(struct msm_gpu * - struct msm_ringbuffer *ring = submit->ring; - unsigned int i, ibs = 0; - -+ adreno_check_and_reenable_stall(adreno_gpu); -+ - if (IS_ENABLED(CONFIG_DRM_MSM_GPU_SUDO) && submit->in_rb) { - ring->cur_ctx_seqno = 0; - a5xx_submit_in_rb(gpu, submit); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/a6xx_catalog.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/a6xx_catalog.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/a6xx_catalog.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/a6xx_catalog.c 2025-10-22 13:53:56.471169353 -0400 -@@ -1335,7 +1335,7 @@ static const uint32_t a7xx_pwrup_reglist - REG_A6XX_RB_NC_MODE_CNTL, - REG_A6XX_RB_CMP_DBG_ECO_CNTL, - REG_A7XX_GRAS_NC_MODE_CNTL, -- REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE, -+ REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE_ENABLE, - REG_A6XX_UCHE_GBIF_GX_CONFIG, - REG_A6XX_UCHE_CLIENT_PF, - REG_A6XX_TPL1_DBG_ECO_CNTL1, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/a6xx_gpu.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/a6xx_gpu.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 2025-10-22 13:53:56.471169353 -0400 -@@ -130,6 +130,20 @@ static void a6xx_set_pagetable(struct a6 - OUT_RING(ring, lower_32_bits(rbmemptr(ring, fence))); - OUT_RING(ring, upper_32_bits(rbmemptr(ring, fence))); - OUT_RING(ring, submit->seqno - 1); -+ -+ OUT_PKT7(ring, CP_THREAD_CONTROL, 1); -+ OUT_RING(ring, CP_SET_THREAD_BOTH); -+ -+ /* Reset state used to synchronize BR and BV */ -+ OUT_PKT7(ring, CP_RESET_CONTEXT_STATE, 1); -+ OUT_RING(ring, -+ CP_RESET_CONTEXT_STATE_0_CLEAR_ON_CHIP_TS | -+ CP_RESET_CONTEXT_STATE_0_CLEAR_RESOURCE_TABLE | -+ CP_RESET_CONTEXT_STATE_0_CLEAR_BV_BR_COUNTER | -+ CP_RESET_CONTEXT_STATE_0_RESET_GLOBAL_LOCAL_TS); -+ -+ OUT_PKT7(ring, CP_THREAD_CONTROL, 1); -+ OUT_RING(ring, CP_SET_THREAD_BR); - } - - if (!sysprof) { -@@ -212,6 +226,8 @@ static void a6xx_submit(struct msm_gpu * - struct msm_ringbuffer *ring = submit->ring; - unsigned int i, ibs = 0; - -+ adreno_check_and_reenable_stall(adreno_gpu); -+ - a6xx_set_pagetable(a6xx_gpu, ring, submit); - - get_stats_counter(ring, REG_A6XX_RBBM_PERFCTR_CP(0), -@@ -335,6 +351,8 @@ static void a7xx_submit(struct msm_gpu * - struct msm_ringbuffer *ring = submit->ring; - unsigned int i, ibs = 0; - -+ adreno_check_and_reenable_stall(adreno_gpu); -+ - /* - * Toggle concurrent binning for pagetable switch and set the thread to - * BR since only it can execute the pagetable switch packets. -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/a6xx_gpu.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/a6xx_gpu.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/a6xx_gpu.h 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/a6xx_gpu.h 2025-10-22 13:53:56.471169353 -0400 -@@ -6,6 +6,10 @@ - - - #include "adreno_gpu.h" -+#include "a6xx_enums.xml.h" -+#include "a7xx_enums.xml.h" -+#include "a6xx_perfcntrs.xml.h" -+#include "a7xx_perfcntrs.xml.h" - #include "a6xx.xml.h" - - #include "a6xx_gmu.h" -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c 2025-10-22 13:53:56.471169353 -0400 -@@ -158,7 +158,7 @@ static int a6xx_crashdumper_run(struct m - /* Make sure all pending memory writes are posted */ - wmb(); - -- gpu_write64(gpu, REG_A6XX_CP_CRASH_SCRIPT_BASE, dumper->iova); -+ gpu_write64(gpu, REG_A6XX_CP_CRASH_DUMP_SCRIPT_BASE, dumper->iova); - - gpu_write(gpu, REG_A6XX_CP_CRASH_DUMP_CNTL, 1); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h 2025-10-22 13:53:56.471169353 -0400 -@@ -212,7 +212,7 @@ static const struct a6xx_shader_block { - SHADER(A6XX_SP_LB_5_DATA, 0x200), - SHADER(A6XX_SP_CB_BINDLESS_DATA, 0x800), - SHADER(A6XX_SP_CB_LEGACY_DATA, 0x280), -- SHADER(A6XX_SP_UAV_DATA, 0x80), -+ SHADER(A6XX_SP_GFX_UAV_BASE_DATA, 0x80), - SHADER(A6XX_SP_INST_TAG, 0x80), - SHADER(A6XX_SP_CB_BINDLESS_TAG, 0x80), - SHADER(A6XX_SP_TMO_UMO_TAG, 0x80), -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/a6xx_preempt.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/a6xx_preempt.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/a6xx_preempt.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/a6xx_preempt.c 2025-10-22 13:53:56.471169353 -0400 -@@ -210,7 +210,7 @@ void a6xx_preempt_hw_init(struct msm_gpu - gpu_write64(gpu, REG_A6XX_CP_CONTEXT_SWITCH_SMMU_INFO, 0); - - /* Enable the GMEM save/restore feature for preemption */ -- gpu_write(gpu, REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE, 0x1); -+ gpu_write(gpu, REG_A6XX_RB_CONTEXT_SWITCH_GMEM_SAVE_RESTORE_ENABLE, 0x1); - - /* Reset the preemption state */ - set_preempt_state(a6xx_gpu, PREEMPT_NONE); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/adreno_device.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/adreno_device.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/adreno_device.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/adreno_device.c 2025-10-22 13:53:56.471169353 -0400 -@@ -137,9 +137,8 @@ err_disable_rpm: - return NULL; - } - --static int find_chipid(struct device *dev, uint32_t *chipid) -+static int find_chipid(struct device_node *node, uint32_t *chipid) - { -- struct device_node *node = dev->of_node; - const char *compat; - int ret; - -@@ -173,15 +172,36 @@ static int find_chipid(struct device *de - /* and if that fails, fall back to legacy "qcom,chipid" property: */ - ret = of_property_read_u32(node, "qcom,chipid", chipid); - if (ret) { -- DRM_DEV_ERROR(dev, "could not parse qcom,chipid: %d\n", ret); -+ DRM_ERROR("%pOF: could not parse qcom,chipid: %d\n", -+ node, ret); - return ret; - } - -- dev_warn(dev, "Using legacy qcom,chipid binding!\n"); -+ pr_warn("%pOF: Using legacy qcom,chipid binding!\n", node); - - return 0; - } - -+bool adreno_has_gpu(struct device_node *node) -+{ -+ const struct adreno_info *info; -+ uint32_t chip_id; -+ int ret; -+ -+ ret = find_chipid(node, &chip_id); -+ if (ret) -+ return false; -+ -+ info = adreno_info(chip_id); -+ if (!info) { -+ pr_warn("%pOF: Unknown GPU revision: %"ADRENO_CHIPID_FMT"\n", -+ node, ADRENO_CHIPID_ARGS(chip_id)); -+ return false; -+ } -+ -+ return true; -+} -+ - static int adreno_bind(struct device *dev, struct device *master, void *data) - { - static struct adreno_platform_config config = {}; -@@ -191,19 +211,18 @@ static int adreno_bind(struct device *de - struct msm_gpu *gpu; - int ret; - -- ret = find_chipid(dev, &config.chip_id); -- if (ret) -+ ret = find_chipid(dev->of_node, &config.chip_id); -+ /* We shouldn't have gotten this far if we can't parse the chip_id */ -+ if (WARN_ON(ret)) - return ret; - - dev->platform_data = &config; - priv->gpu_pdev = to_platform_device(dev); - - info = adreno_info(config.chip_id); -- if (!info) { -- dev_warn(drm->dev, "Unknown GPU revision: %"ADRENO_CHIPID_FMT"\n", -- ADRENO_CHIPID_ARGS(config.chip_id)); -+ /* We shouldn't have gotten this far if we don't recognize the GPU: */ -+ if (WARN_ON(!info)) - return -ENXIO; -- } - - config.info = info; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/adreno_gen7_9_0_snapshot.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/adreno_gen7_9_0_snapshot.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/adreno_gen7_9_0_snapshot.h 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/adreno_gen7_9_0_snapshot.h 2025-10-22 13:53:56.471169353 -0400 -@@ -1311,8 +1311,8 @@ static struct a6xx_indexed_registers gen - REG_A7XX_CP_BV_SQE_UCODE_DBG_DATA, 0x08000}, - { "CP_BV_SQE_STAT_ADDR", REG_A7XX_CP_BV_SQE_STAT_ADDR, - REG_A7XX_CP_BV_SQE_STAT_DATA, 0x00040}, -- { "CP_RESOURCE_TBL", REG_A7XX_CP_RESOURCE_TBL_DBG_ADDR, -- REG_A7XX_CP_RESOURCE_TBL_DBG_DATA, 0x04100}, -+ { "CP_RESOURCE_TBL", REG_A7XX_CP_RESOURCE_TABLE_DBG_ADDR, -+ REG_A7XX_CP_RESOURCE_TABLE_DBG_DATA, 0x04100}, - { "CP_LPAC_DRAW_STATE_ADDR", REG_A7XX_CP_LPAC_DRAW_STATE_ADDR, - REG_A7XX_CP_LPAC_DRAW_STATE_DATA, 0x00200}, - { "CP_LPAC_ROQ", REG_A7XX_CP_LPAC_ROQ_DBG_ADDR, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/adreno_gpu.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/adreno_gpu.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/adreno_gpu.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/adreno_gpu.c 2025-10-22 13:53:56.471169353 -0400 -@@ -259,24 +259,54 @@ u64 adreno_private_address_space_size(st - return BIT(ttbr1_cfg->ias) - ADRENO_VM_START; - } - -+void adreno_check_and_reenable_stall(struct adreno_gpu *adreno_gpu) -+{ -+ struct msm_gpu *gpu = &adreno_gpu->base; -+ struct msm_drm_private *priv = gpu->dev->dev_private; -+ unsigned long flags; -+ -+ /* -+ * Wait until the cooldown period has passed and we would actually -+ * collect a crashdump to re-enable stall-on-fault. -+ */ -+ spin_lock_irqsave(&priv->fault_stall_lock, flags); -+ if (!priv->stall_enabled && -+ ktime_after(ktime_get(), priv->stall_reenable_time) && -+ !READ_ONCE(gpu->crashstate)) { -+ priv->stall_enabled = true; -+ -+ gpu->aspace->mmu->funcs->set_stall(gpu->aspace->mmu, true); -+ } -+ spin_unlock_irqrestore(&priv->fault_stall_lock, flags); -+} -+ - #define ARM_SMMU_FSR_TF BIT(1) - #define ARM_SMMU_FSR_PF BIT(3) - #define ARM_SMMU_FSR_EF BIT(4) -+#define ARM_SMMU_FSR_SS BIT(30) - - int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags, - struct adreno_smmu_fault_info *info, const char *block, - u32 scratch[4]) - { -+ struct msm_drm_private *priv = gpu->dev->dev_private; - const char *type = "UNKNOWN"; -- bool do_devcoredump = info && !READ_ONCE(gpu->crashstate); -+ bool do_devcoredump = info && (info->fsr & ARM_SMMU_FSR_SS) && -+ !READ_ONCE(gpu->crashstate); -+ unsigned long irq_flags; - - /* -- * If we aren't going to be resuming later from fault_worker, then do -- * it now. -+ * In case there is a subsequent storm of pagefaults, disable -+ * stall-on-fault for at least half a second. - */ -- if (!do_devcoredump) { -- gpu->aspace->mmu->funcs->resume_translation(gpu->aspace->mmu); -+ spin_lock_irqsave(&priv->fault_stall_lock, irq_flags); -+ if (priv->stall_enabled) { -+ priv->stall_enabled = false; -+ -+ gpu->aspace->mmu->funcs->set_stall(gpu->aspace->mmu, false); - } -+ priv->stall_reenable_time = ktime_add_ms(ktime_get(), 500); -+ spin_unlock_irqrestore(&priv->fault_stall_lock, irq_flags); - - /* - * Print a default message if we couldn't get the data from the -@@ -304,16 +334,18 @@ int adreno_fault_handler(struct msm_gpu - scratch[0], scratch[1], scratch[2], scratch[3]); - - if (do_devcoredump) { -+ struct msm_gpu_fault_info fault_info = {}; -+ - /* Turn off the hangcheck timer to keep it from bothering us */ - timer_delete(&gpu->hangcheck_timer); - -- gpu->fault_info.ttbr0 = info->ttbr0; -- gpu->fault_info.iova = iova; -- gpu->fault_info.flags = flags; -- gpu->fault_info.type = type; -- gpu->fault_info.block = block; -+ fault_info.ttbr0 = info->ttbr0; -+ fault_info.iova = iova; -+ fault_info.flags = flags; -+ fault_info.type = type; -+ fault_info.block = block; - -- kthread_queue_work(gpu->worker, &gpu->fault_work); -+ msm_gpu_fault_crashstate_capture(gpu, &fault_info); - } - - return 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/adreno_gpu.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/adreno_gpu.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/adreno/adreno_gpu.h 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/adreno/adreno_gpu.h 2025-10-22 13:53:56.471169353 -0400 -@@ -636,6 +636,8 @@ int adreno_fault_handler(struct msm_gpu - struct adreno_smmu_fault_info *info, const char *block, - u32 scratch[4]); - -+void adreno_check_and_reenable_stall(struct adreno_gpu *gpu); -+ - int adreno_read_speedbin(struct device *dev, u32 *speedbin); - - /* -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h 2025-10-22 13:53:56.471169353 -0400 -@@ -383,6 +383,7 @@ static const struct dpu_perf_cfg sc8180x - .min_core_ib = 2400000, - .min_llcc_ib = 800000, - .min_dram_ib = 800000, -+ .min_prefill_lines = 24, - .danger_lut_tbl = {0xf, 0xffff, 0x0}, - .safe_lut_tbl = {0xfff0, 0xf000, 0xffff}, - .qos_lut_tbl = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 2025-10-22 13:53:56.471169353 -0400 -@@ -729,6 +729,8 @@ bool dpu_encoder_needs_modeset(struct dr - return false; - - conn_state = drm_atomic_get_new_connector_state(state, connector); -+ if (!conn_state) -+ return false; - - /** - * These checks are duplicated from dpu_encoder_update_topology() since -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 2025-10-22 13:53:56.471169353 -0400 -@@ -94,17 +94,21 @@ static void drm_mode_to_intf_timing_para - timing->vsync_polarity = 0; - } - -- /* for DP/EDP, Shift timings to align it to bottom right */ -- if (phys_enc->hw_intf->cap->type == INTF_DP) { -+ timing->wide_bus_en = dpu_encoder_is_widebus_enabled(phys_enc->parent); -+ timing->compression_en = dpu_encoder_is_dsc_enabled(phys_enc->parent); -+ -+ /* -+ * For DP/EDP, Shift timings to align it to bottom right. -+ * wide_bus_en is set for everything excluding SDM845 & -+ * porch changes cause DisplayPort failure and HDMI tearing. -+ */ -+ if (phys_enc->hw_intf->cap->type == INTF_DP && timing->wide_bus_en) { - timing->h_back_porch += timing->h_front_porch; - timing->h_front_porch = 0; - timing->v_back_porch += timing->v_front_porch; - timing->v_front_porch = 0; - } - -- timing->wide_bus_en = dpu_encoder_is_widebus_enabled(phys_enc->parent); -- timing->compression_en = dpu_encoder_is_dsc_enabled(phys_enc->parent); -- - /* - * for DP, divide the horizonal parameters by 2 when - * widebus is enabled -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 2025-10-22 13:53:56.471169353 -0400 -@@ -1136,7 +1136,7 @@ static int dpu_plane_virtual_atomic_chec - struct drm_plane_state *old_plane_state = - drm_atomic_get_old_plane_state(state, plane); - struct dpu_plane_state *pstate = to_dpu_plane_state(plane_state); -- struct drm_crtc_state *crtc_state; -+ struct drm_crtc_state *crtc_state = NULL; - int ret; - - if (IS_ERR(plane_state)) -@@ -1169,7 +1169,7 @@ static int dpu_plane_virtual_atomic_chec - if (!old_plane_state || !old_plane_state->fb || - old_plane_state->src_w != plane_state->src_w || - old_plane_state->src_h != plane_state->src_h || -- old_plane_state->src_w != plane_state->src_w || -+ old_plane_state->crtc_w != plane_state->crtc_w || - old_plane_state->crtc_h != plane_state->crtc_h || - msm_framebuffer_format(old_plane_state->fb) != - msm_framebuffer_format(plane_state->fb)) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/dp/dp_display.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/dp/dp_display.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/dp/dp_display.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/dp/dp_display.c 2025-10-22 13:53:56.471169353 -0400 -@@ -128,6 +128,11 @@ static const struct msm_dp_desc msm_dp_d - {} - }; - -+static const struct msm_dp_desc msm_dp_desc_sdm845[] = { -+ { .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0 }, -+ {} -+}; -+ - static const struct msm_dp_desc msm_dp_desc_sc7180[] = { - { .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0, .wide_bus_supported = true }, - {} -@@ -180,7 +185,7 @@ static const struct of_device_id msm_dp_ - { .compatible = "qcom,sc8180x-edp", .data = &msm_dp_desc_sc8180x }, - { .compatible = "qcom,sc8280xp-dp", .data = &msm_dp_desc_sc8280xp }, - { .compatible = "qcom,sc8280xp-edp", .data = &msm_dp_desc_sc8280xp }, -- { .compatible = "qcom,sdm845-dp", .data = &msm_dp_desc_sc7180 }, -+ { .compatible = "qcom,sdm845-dp", .data = &msm_dp_desc_sdm845 }, - { .compatible = "qcom,sm8350-dp", .data = &msm_dp_desc_sc7180 }, - { .compatible = "qcom,sm8650-dp", .data = &msm_dp_desc_sm8650 }, - { .compatible = "qcom,x1e80100-dp", .data = &msm_dp_desc_x1e80100 }, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/dsi/phy/dsi_phy_10nm.c 2025-10-22 13:53:56.471169353 -0400 -@@ -704,6 +704,13 @@ static int dsi_pll_10nm_init(struct msm_ - /* TODO: Remove this when we have proper display handover support */ - msm_dsi_phy_pll_save_state(phy); - -+ /* -+ * Store also proper vco_current_rate, because its value will be used in -+ * dsi_10nm_pll_restore_state(). -+ */ -+ if (!dsi_pll_10nm_vco_recalc_rate(&pll_10nm->clk_hw, VCO_REF_CLK_RATE)) -+ pll_10nm->vco_current_rate = pll_10nm->phy->cfg->min_pll_rate; -+ - return 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/Makefile BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/Makefile ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/Makefile 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/Makefile 2025-10-22 13:53:56.471169353 -0400 -@@ -195,6 +195,11 @@ ADRENO_HEADERS = \ - generated/a4xx.xml.h \ - generated/a5xx.xml.h \ - generated/a6xx.xml.h \ -+ generated/a6xx_descriptors.xml.h \ -+ generated/a6xx_enums.xml.h \ -+ generated/a6xx_perfcntrs.xml.h \ -+ generated/a7xx_enums.xml.h \ -+ generated/a7xx_perfcntrs.xml.h \ - generated/a6xx_gmu.xml.h \ - generated/adreno_common.xml.h \ - generated/adreno_pm4.xml.h \ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/msm_debugfs.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/msm_debugfs.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/msm_debugfs.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/msm_debugfs.c 2025-10-22 13:53:56.471169353 -0400 -@@ -208,6 +208,35 @@ DEFINE_DEBUGFS_ATTRIBUTE(shrink_fops, - shrink_get, shrink_set, - "0x%08llx\n"); - -+/* -+ * Return the number of microseconds to wait until stall-on-fault is -+ * re-enabled. If 0 then it is already enabled or will be re-enabled on the -+ * next submit (unless there's a leftover devcoredump). This is useful for -+ * kernel tests that intentionally produce a fault and check the devcoredump to -+ * wait until the cooldown period is over. -+ */ -+ -+static int -+stall_reenable_time_get(void *data, u64 *val) -+{ -+ struct msm_drm_private *priv = data; -+ unsigned long irq_flags; -+ -+ spin_lock_irqsave(&priv->fault_stall_lock, irq_flags); -+ -+ if (priv->stall_enabled) -+ *val = 0; -+ else -+ *val = max(ktime_us_delta(priv->stall_reenable_time, ktime_get()), 0); -+ -+ spin_unlock_irqrestore(&priv->fault_stall_lock, irq_flags); -+ -+ return 0; -+} -+ -+DEFINE_DEBUGFS_ATTRIBUTE(stall_reenable_time_fops, -+ stall_reenable_time_get, NULL, -+ "%lld\n"); - - static int msm_gem_show(struct seq_file *m, void *arg) - { -@@ -319,6 +348,9 @@ static void msm_debugfs_gpu_init(struct - debugfs_create_bool("disable_err_irq", 0600, minor->debugfs_root, - &priv->disable_err_irq); - -+ debugfs_create_file("stall_reenable_time_us", 0400, minor->debugfs_root, -+ priv, &stall_reenable_time_fops); -+ - gpu_devfreq = debugfs_create_dir("devfreq", minor->debugfs_root); - - debugfs_create_bool("idle_clamp",0600, gpu_devfreq, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/msm_drv.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/msm_drv.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/msm_drv.c 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/msm_drv.c 2025-10-22 13:53:56.471169353 -0400 -@@ -245,6 +245,10 @@ static int msm_drm_init(struct device *d - drm_gem_lru_init(&priv->lru.willneed, &priv->lru.lock); - drm_gem_lru_init(&priv->lru.dontneed, &priv->lru.lock); - -+ /* Initialize stall-on-fault */ -+ spin_lock_init(&priv->fault_stall_lock); -+ priv->stall_enabled = true; -+ - /* Teach lockdep about lock ordering wrt. shrinker: */ - fs_reclaim_acquire(GFP_KERNEL); - might_lock(&priv->lru.lock); -@@ -551,6 +555,7 @@ static int msm_ioctl_gem_info_set_metada - u32 metadata_size) - { - struct msm_gem_object *msm_obj = to_msm_bo(obj); -+ void *new_metadata; - void *buf; - int ret; - -@@ -568,8 +573,14 @@ static int msm_ioctl_gem_info_set_metada - if (ret) - goto out; - -- msm_obj->metadata = -+ new_metadata = - krealloc(msm_obj->metadata, metadata_size, GFP_KERNEL); -+ if (!new_metadata) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ -+ msm_obj->metadata = new_metadata; - msm_obj->metadata_size = metadata_size; - memcpy(msm_obj->metadata, buf, metadata_size); - -@@ -926,7 +937,7 @@ static const struct drm_driver msm_drive - * is no external component that we need to add since LVDS is within MDP4 - * itself. - */ --static int add_components_mdp(struct device *master_dev, -+static int add_mdp_components(struct device *master_dev, - struct component_match **matchptr) - { - struct device_node *np = master_dev->of_node; -@@ -1030,7 +1041,7 @@ static int add_gpu_components(struct dev - if (!np) - return 0; - -- if (of_device_is_available(np)) -+ if (of_device_is_available(np) && adreno_has_gpu(np)) - drm_of_component_match_add(dev, matchptr, component_compare_of, np); - - of_node_put(np); -@@ -1071,7 +1082,7 @@ int msm_drv_probe(struct device *master_ - - /* Add mdp components if we have KMS. */ - if (kms_init) { -- ret = add_components_mdp(master_dev, &match); -+ ret = add_mdp_components(master_dev, &match); - if (ret) - return ret; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/msm_drv.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/msm_drv.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/msm_drv.h 2025-10-22 13:53:23.231329048 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/msm_drv.h 2025-10-22 13:53:56.471169353 -0400 -@@ -222,6 +222,29 @@ struct msm_drm_private { - * the sw hangcheck mechanism. - */ - bool disable_err_irq; -+ -+ /** -+ * @fault_stall_lock: -+ * -+ * Serialize changes to stall-on-fault state. -+ */ -+ spinlock_t fault_stall_lock; -+ -+ /** -+ * @fault_stall_reenable_time: -+ * -+ * If stall_enabled is false, when to reenable stall-on-fault. -+ * Protected by @fault_stall_lock. -+ */ -+ ktime_t stall_reenable_time; -+ -+ /** -+ * @stall_enabled: -+ * -+ * Whether stall-on-fault is currently enabled. Protected by -+ * @fault_stall_lock. -+ */ -+ bool stall_enabled; - }; - - const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format, uint64_t modifier); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/msm_gem.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/msm_gem.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/msm_gem.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/msm_gem.c 2025-10-22 13:53:56.471169353 -0400 -@@ -963,7 +963,8 @@ void msm_gem_describe(struct drm_gem_obj - uint64_t off = drm_vma_node_start(&obj->vma_node); - const char *madv; - -- msm_gem_lock(obj); -+ if (!msm_gem_trylock(obj)) -+ return; - - stats->all.count++; - stats->all.size += obj->size; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/msm_gem.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/msm_gem.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/msm_gem.h 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/msm_gem.h 2025-10-22 13:53:56.475169334 -0400 -@@ -188,6 +188,12 @@ msm_gem_lock(struct drm_gem_object *obj) - dma_resv_lock(obj->resv, NULL); - } - -+static inline bool __must_check -+msm_gem_trylock(struct drm_gem_object *obj) -+{ -+ return dma_resv_trylock(obj->resv); -+} -+ - static inline int - msm_gem_lock_interruptible(struct drm_gem_object *obj) - { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/msm_gem_submit.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/msm_gem_submit.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/msm_gem_submit.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/msm_gem_submit.c 2025-10-22 13:53:56.475169334 -0400 -@@ -85,6 +85,15 @@ void __msm_gem_submit_destroy(struct kre - container_of(kref, struct msm_gem_submit, ref); - unsigned i; - -+ /* -+ * In error paths, we could unref the submit without calling -+ * drm_sched_entity_push_job(), so msm_job_free() will never -+ * get called. Since drm_sched_job_cleanup() will NULL out -+ * s_fence, we can use that to detect this case. -+ */ -+ if (submit->base.s_fence) -+ drm_sched_job_cleanup(&submit->base); -+ - if (submit->fence_id) { - spin_lock(&submit->queue->idr_lock); - idr_remove(&submit->queue->fence_idr, submit->fence_id); -@@ -649,6 +658,7 @@ int msm_ioctl_gem_submit(struct drm_devi - struct msm_ringbuffer *ring; - struct msm_submit_post_dep *post_deps = NULL; - struct drm_syncobj **syncobjs_to_reset = NULL; -+ struct sync_file *sync_file = NULL; - int out_fence_fd = -1; - unsigned i; - int ret; -@@ -858,13 +868,9 @@ int msm_ioctl_gem_submit(struct drm_devi - } - - if (ret == 0 && args->flags & MSM_SUBMIT_FENCE_FD_OUT) { -- struct sync_file *sync_file = sync_file_create(submit->user_fence); -- if (!sync_file) { -+ sync_file = sync_file_create(submit->user_fence); -+ if (!sync_file) - ret = -ENOMEM; -- } else { -- fd_install(out_fence_fd, sync_file->file); -- args->fence_fd = out_fence_fd; -- } - } - - if (ret) -@@ -892,8 +898,15 @@ out: - out_unlock: - mutex_unlock(&queue->lock); - out_post_unlock: -- if (ret && (out_fence_fd >= 0)) -- put_unused_fd(out_fence_fd); -+ if (ret) { -+ if (out_fence_fd >= 0) -+ put_unused_fd(out_fence_fd); -+ if (sync_file) -+ fput(sync_file->file); -+ } else if (sync_file) { -+ fd_install(out_fence_fd, sync_file->file); -+ args->fence_fd = out_fence_fd; -+ } - - if (!IS_ERR_OR_NULL(submit)) { - msm_gem_submit_put(submit); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/msm_gpu.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/msm_gpu.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/msm_gpu.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/msm_gpu.c 2025-10-22 13:53:56.475169334 -0400 -@@ -257,7 +257,8 @@ out: - } - - static void msm_gpu_crashstate_capture(struct msm_gpu *gpu, -- struct msm_gem_submit *submit, char *comm, char *cmd) -+ struct msm_gem_submit *submit, struct msm_gpu_fault_info *fault_info, -+ char *comm, char *cmd) - { - struct msm_gpu_state *state; - -@@ -276,7 +277,8 @@ static void msm_gpu_crashstate_capture(s - /* Fill in the additional crash state information */ - state->comm = kstrdup(comm, GFP_KERNEL); - state->cmd = kstrdup(cmd, GFP_KERNEL); -- state->fault_info = gpu->fault_info; -+ if (fault_info) -+ state->fault_info = *fault_info; - - if (submit) { - int i; -@@ -308,7 +310,8 @@ static void msm_gpu_crashstate_capture(s - } - #else - static void msm_gpu_crashstate_capture(struct msm_gpu *gpu, -- struct msm_gem_submit *submit, char *comm, char *cmd) -+ struct msm_gem_submit *submit, struct msm_gpu_fault_info *fault_info, -+ char *comm, char *cmd) - { - } - #endif -@@ -405,7 +408,7 @@ static void recover_worker(struct kthrea - - /* Record the crash state */ - pm_runtime_get_sync(&gpu->pdev->dev); -- msm_gpu_crashstate_capture(gpu, submit, comm, cmd); -+ msm_gpu_crashstate_capture(gpu, submit, NULL, comm, cmd); - - kfree(cmd); - kfree(comm); -@@ -459,9 +462,8 @@ out_unlock: - msm_gpu_retire(gpu); - } - --static void fault_worker(struct kthread_work *work) -+void msm_gpu_fault_crashstate_capture(struct msm_gpu *gpu, struct msm_gpu_fault_info *fault_info) - { -- struct msm_gpu *gpu = container_of(work, struct msm_gpu, fault_work); - struct msm_gem_submit *submit; - struct msm_ringbuffer *cur_ring = gpu->funcs->active_ring(gpu); - char *comm = NULL, *cmd = NULL; -@@ -484,16 +486,13 @@ static void fault_worker(struct kthread_ - - /* Record the crash state */ - pm_runtime_get_sync(&gpu->pdev->dev); -- msm_gpu_crashstate_capture(gpu, submit, comm, cmd); -+ msm_gpu_crashstate_capture(gpu, submit, fault_info, comm, cmd); - pm_runtime_put_sync(&gpu->pdev->dev); - - kfree(cmd); - kfree(comm); - - resume_smmu: -- memset(&gpu->fault_info, 0, sizeof(gpu->fault_info)); -- gpu->aspace->mmu->funcs->resume_translation(gpu->aspace->mmu); -- - mutex_unlock(&gpu->lock); - } - -@@ -882,7 +881,6 @@ int msm_gpu_init(struct drm_device *drm, - init_waitqueue_head(&gpu->retire_event); - kthread_init_work(&gpu->retire_work, retire_worker); - kthread_init_work(&gpu->recover_work, recover_worker); -- kthread_init_work(&gpu->fault_work, fault_worker); - - priv->hangcheck_period = DRM_MSM_HANGCHECK_DEFAULT_PERIOD; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/msm_gpu.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/msm_gpu.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/msm_gpu.h 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/msm_gpu.h 2025-10-22 13:53:56.475169334 -0400 -@@ -253,12 +253,6 @@ struct msm_gpu { - #define DRM_MSM_HANGCHECK_PROGRESS_RETRIES 3 - struct timer_list hangcheck_timer; - -- /* Fault info for most recent iova fault: */ -- struct msm_gpu_fault_info fault_info; -- -- /* work for handling GPU ioval faults: */ -- struct kthread_work fault_work; -- - /* work for handling GPU recovery: */ - struct kthread_work recover_work; - -@@ -668,6 +662,7 @@ msm_gpu_create_private_address_space(str - void msm_gpu_cleanup(struct msm_gpu *gpu); - - struct msm_gpu *adreno_load_gpu(struct drm_device *dev); -+bool adreno_has_gpu(struct device_node *node); - void __init adreno_register(void); - void __exit adreno_unregister(void); - -@@ -705,6 +700,8 @@ static inline void msm_gpu_crashstate_pu - mutex_unlock(&gpu->lock); - } - -+void msm_gpu_fault_crashstate_capture(struct msm_gpu *gpu, struct msm_gpu_fault_info *fault_info); -+ - /* - * Simple macro to semi-cleanly add the MAP_PRIV flag for targets that can - * support expanded privileges -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/msm_iommu.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/msm_iommu.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/msm_iommu.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/msm_iommu.c 2025-10-22 13:53:56.475169334 -0400 -@@ -345,7 +345,6 @@ static int msm_gpu_fault_handler(struct - unsigned long iova, int flags, void *arg) - { - struct msm_iommu *iommu = arg; -- struct msm_mmu *mmu = &iommu->base; - struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(iommu->base.dev); - struct adreno_smmu_fault_info info, *ptr = NULL; - -@@ -359,9 +358,6 @@ static int msm_gpu_fault_handler(struct - - pr_warn_ratelimited("*** fault: iova=%16lx, flags=%d\n", iova, flags); - -- if (mmu->funcs->resume_translation) -- mmu->funcs->resume_translation(mmu); -- - return 0; - } - -@@ -376,12 +372,12 @@ static int msm_disp_fault_handler(struct - return -ENOSYS; - } - --static void msm_iommu_resume_translation(struct msm_mmu *mmu) -+static void msm_iommu_set_stall(struct msm_mmu *mmu, bool enable) - { - struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(mmu->dev); - -- if (adreno_smmu->resume_translation) -- adreno_smmu->resume_translation(adreno_smmu->cookie, true); -+ if (adreno_smmu->set_stall) -+ adreno_smmu->set_stall(adreno_smmu->cookie, enable); - } - - static void msm_iommu_detach(struct msm_mmu *mmu) -@@ -431,7 +427,7 @@ static const struct msm_mmu_funcs funcs - .map = msm_iommu_map, - .unmap = msm_iommu_unmap, - .destroy = msm_iommu_destroy, -- .resume_translation = msm_iommu_resume_translation, -+ .set_stall = msm_iommu_set_stall, - }; - - struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/msm_kms.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/msm_kms.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/msm_kms.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/msm_kms.c 2025-10-22 13:53:56.475169334 -0400 -@@ -258,6 +258,12 @@ int msm_drm_kms_init(struct device *dev, - if (ret) - return ret; - -+ ret = msm_disp_snapshot_init(ddev); -+ if (ret) { -+ DRM_DEV_ERROR(dev, "msm_disp_snapshot_init failed ret = %d\n", ret); -+ return ret; -+ } -+ - ret = priv->kms_init(ddev); - if (ret) { - DRM_DEV_ERROR(dev, "failed to load kms\n"); -@@ -310,10 +316,6 @@ int msm_drm_kms_init(struct device *dev, - goto err_msm_uninit; - } - -- ret = msm_disp_snapshot_init(ddev); -- if (ret) -- DRM_DEV_ERROR(dev, "msm_disp_snapshot_init failed ret = %d\n", ret); -- - drm_mode_config_reset(ddev); - - return 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/msm_mmu.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/msm_mmu.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/msm_mmu.h 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/msm_mmu.h 2025-10-22 13:53:56.475169334 -0400 -@@ -15,7 +15,7 @@ struct msm_mmu_funcs { - size_t len, int prot); - int (*unmap)(struct msm_mmu *mmu, uint64_t iova, size_t len); - void (*destroy)(struct msm_mmu *mmu); -- void (*resume_translation)(struct msm_mmu *mmu); -+ void (*set_stall)(struct msm_mmu *mmu, bool enable); - }; - - enum msm_mmu_type { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/registers/adreno/a6xx_descriptors.xml BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/registers/adreno/a6xx_descriptors.xml ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/registers/adreno/a6xx_descriptors.xml 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/registers/adreno/a6xx_descriptors.xml 2025-10-22 13:53:56.475169334 -0400 -@@ -0,0 +1,198 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+ Texture sampler dwords -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ clamp result to [0, 1] if the format is unorm or -+ [-1, 1] if the format is snorm, *after* -+ filtering. Has no effect for other formats. -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ Texture constant dwords -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ probably for D3D structured UAVs, normally set to 1 -+ -+ -+ -+ -+ -+ Pitch in bytes (so actually stride) -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/registers/adreno/a6xx_enums.xml BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/registers/adreno/a6xx_enums.xml ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/registers/adreno/a6xx_enums.xml 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/registers/adreno/a6xx_enums.xml 2025-10-22 13:53:56.475169334 -0400 -@@ -0,0 +1,383 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ A special buffer type for usage as the source for buffer -+ to image copies with lower alignment requirements than -+ A6XX_TEX_2D, available since A7XX. -+ -+ -+ -+ -+ -+ Allow early z-test and early-lrz (if applicable) -+ -+ Disable early z-test and early-lrz test (if applicable) -+ -+ -+ A special mode that allows early-lrz (if applicable) or early-z -+ tests, but also does late-z tests at which point it writes depth. -+ -+ This mode is used when fragment can be killed (via discard or -+ sample mask) after early-z tests and it writes depth. In such case -+ depth can be written only at late-z stage, but it's ok to use -+ early-z to discard fragments. -+ -+ However this mode is not compatible with: -+ - Lack of D/S attachment -+ - Stencil writes on stencil or depth test failures -+ - Per-sample shading -+ -+ -+ Not a real hw value, used internally by mesa -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/registers/adreno/a6xx_perfcntrs.xml BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/registers/adreno/a6xx_perfcntrs.xml ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/registers/adreno/a6xx_perfcntrs.xml 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/registers/adreno/a6xx_perfcntrs.xml 2025-10-22 13:53:56.475169334 -0400 -@@ -0,0 +1,600 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/registers/adreno/a6xx.xml BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/registers/adreno/a6xx.xml ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/registers/adreno/a6xx.xml 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/registers/adreno/a6xx.xml 2025-10-22 13:53:56.475169334 -0400 -@@ -5,6 +5,11 @@ xsi:schemaLocation="https://gitlab.freed - - - -+ -+ -+ -+ -+ - - - -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- Allow early z-test and early-lrz (if applicable) -- -- Disable early z-test and early-lrz test (if applicable) -- -- -- A special mode that allows early-lrz test but disables -- early-z test. Which might sound a bit funny, since -- lrz-test happens before z-test. But as long as a couple -- conditions are maintained this allows using lrz-test in -- cases where fragment shader has kill/discard: -- -- 1) Disable lrz-write in cases where it is uncertain during -- binning pass that a fragment will pass. Ie. if frag -- shader has-kill, writes-z, or alpha/stencil test is -- enabled. (For correctness, lrz-write must be disabled -- when blend is enabled.) This is analogous to how a -- z-prepass works. -- -- 2) Disable lrz-write and test if a depth-test direction -- reversal is detected. Due to condition (1), the contents -- of the lrz buffer are a conservative estimation of the -- depth buffer during the draw pass. Meaning that geometry -- that we know for certain will not be visible will not pass -- lrz-test. But geometry which may be (or contributes to -- blend) will pass the lrz-test. -- -- This allows us to keep early-lrz-test in cases where the frag -- shader does not write-z (ie. we know the z-value before FS) -- and does not have side-effects (image/ssbo writes, etc), but -- does have kill/discard. Which turns out to be a common -- enough case that it is useful to keep early-lrz test against -- the conservative lrz buffer to discard fragments that we -- know will definitely not be visible. -- -- -- Not a real hw value, used internally by mesa -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - - - -@@ -2371,7 +177,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -2400,22 +206,22 @@ to upconvert to 32b float internally? - --> - - -- -+ - - - -- -- -- -- -- -- -- -- -- -- -- -- -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ - - - number of remaining dwords incl current dword being consumed? -@@ -2451,6 +257,7 @@ to upconvert to 32b float internally? - - - -+ - - - -@@ -2468,8 +275,8 @@ to upconvert to 32b float internally? - - - -- -- -+ -+ - - - -@@ -2619,28 +426,17 @@ to upconvert to 32b float internally? - vertices in, number of primnitives assembled etc. - --> - -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ - - - -@@ -2779,7 +575,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -2840,7 +636,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - Set to true when binning, isn't changed afterwards -@@ -2936,8 +732,8 @@ to upconvert to 32b float internally? - - - -- -- -+ -+ - - - -@@ -2967,14 +763,14 @@ to upconvert to 32b float internally? - - LIMIT is set to PITCH - 64, to make room for a bit of overflow - --> -- -- -- -- -- -- -+ -+ -+ -+ -+ -+ - -- -+ - - Seems to be a bitmap of which tiles mapped to the VSC - pipe contain geometry. -@@ -2985,7 +781,7 @@ to upconvert to 32b float internally? - - - -- -+ - - Has the size of data written to corresponding VSC_PRIM_STRM - buffer. -@@ -2993,10 +789,10 @@ to upconvert to 32b float internally? - - - -- -+ - - Has the size of data written to corresponding VSC pipe, ie. -- same thing that is written out to VSC_DRAW_STRM_SIZE_ADDRESS_LO/HI -+ same thing that is written out to VSC_SIZE_BASE - - - -@@ -3028,17 +824,17 @@ to upconvert to 32b float internally? - - - -- -+ - - - -- -- -- -- -+ -+ -+ -+ - -- -- -+ -+ - - - -@@ -3067,7 +863,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -3075,7 +871,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -3124,7 +920,12 @@ to upconvert to 32b float internally? - - - -- -+ -+ -+ -+ -+ -+ - - - -@@ -3133,13 +934,13 @@ to upconvert to 32b float internally? - - - -- -+ - - - -- -- -- -+ -+ -+ - - - -@@ -3213,13 +1014,13 @@ to upconvert to 32b float internally? - - - -- -+ - -- -+ - - - -- -+ - - - -@@ -3235,22 +1036,22 @@ to upconvert to 32b float internally? - - - -- -+ - - - - -- -+ - - - - -- -+ - - - - -- -+ - - - -@@ -3261,9 +1062,9 @@ to upconvert to 32b float internally? - - - -- -- -- -+ -+ -+ - - - -@@ -3286,13 +1087,36 @@ to upconvert to 32b float internally? - - - -- -- -- -- -- -- -- -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ - - - -@@ -3313,7 +1137,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -3339,14 +1163,13 @@ to upconvert to 32b float internally? - - - -- -+ - - - - -- - -- -+ - - - - - -- -+ - - - -- -+ - - - -@@ -3408,7 +1231,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -3430,7 +1253,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -3447,22 +1270,22 @@ to upconvert to 32b float internally? - - - -- -+ - -- -- -- -- -- -- -+ -+ -+ -+ -+ -+ - - - -- -- -+ -+ - - - -@@ -3481,7 +1304,7 @@ to upconvert to 32b float internally? - --> - - -- -+ - - - -@@ -3490,7 +1313,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -3501,8 +1324,7 @@ to upconvert to 32b float internally? - - - -- -- -+ - - - -@@ -3515,15 +1337,14 @@ to upconvert to 32b float internally? - - - -- -- -+ - - - - - - -- -+ - - - -@@ -3536,16 +1357,16 @@ to upconvert to 32b float internally? - - - -- -- -- -+ -+ -+ - - -- -- -+ -+ - - - -@@ -3555,7 +1376,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -3567,16 +1388,16 @@ to upconvert to 32b float internally? - - - -- -+ - - - - - -- -+ - - -- -+ - - - -@@ -3608,7 +1429,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -3672,18 +1493,18 @@ to upconvert to 32b float internally? - - - -- -- -- -- -- -+ -+ -+ -+ -+ - - - - - - -- -+ - - - -@@ -3726,12 +1547,12 @@ to upconvert to 32b float internally? - - - -- -+ - -- -- -+ -+ - -- -+ - - - - -- -+ - - - -@@ -3791,27 +1612,27 @@ to upconvert to 32b float internally? - - - -- -- -+ -+ - -- -+ - - - -- -- -+ -+ - -- -+ - - - -- -- -+ -+ - - -- -+ - -- -+ - - - -@@ -3820,25 +1641,31 @@ to upconvert to 32b float internally? - - - -- -- -+ -+ - -- -- -- -+ -+ -+ - - - - -- -- -- -- -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ - - -- -- -- -+ -+ - - - -@@ -3853,16 +1680,20 @@ to upconvert to 32b float internally? - - - - - -- -- -- -+ -+ -+ -+ -+ -+ -+ - - - -@@ -3871,7 +1702,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -3895,7 +1726,13 @@ to upconvert to 32b float internally? - - - -- -+ -+ -+ -+ -+ -+ -+ - - - -@@ -3906,7 +1743,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -3915,10 +1752,10 @@ to upconvert to 32b float internally? - - - -- RB_SAMPLE_COUNT_ADDR register is used up to (and including) a730. After that -+ RB_SAMPLE_COUNTER_BASE register is used up to (and including) a730. After that - the address is specified through CP_EVENT_WRITE7::WRITE_SAMPLE_COUNT. - -- -+ - - - -@@ -3932,10 +1769,10 @@ to upconvert to 32b float internally? - - - -- -- -+ -+ - -- -+ - - - -@@ -3954,7 +1791,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -3965,26 +1802,26 @@ to upconvert to 32b float internally? - - - -- -- -- -+ -+ -+ - -- -- -- -+ -+ -+ - -- -- -+ -+ - -- -- -+ -+ - - - -- -- -- -- -+ -+ -+ -+ - - - -@@ -3996,7 +1833,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -4017,10 +1854,21 @@ to upconvert to 32b float internally? - - - -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ - - -- -- -+ -+ -+ - - - -@@ -4046,9 +1894,9 @@ to upconvert to 32b float internally? - - - -- -+ - -- -+ - - - -@@ -4069,38 +1917,38 @@ to upconvert to 32b float internally? - - - -- -- -- -- -- -- -- -+ -+ -+ -+ -+ -+ -+ - -- -+ - - - - - -- -- -- -- -- -- -- -+ -+ -+ -+ -+ -+ -+ - - -- -+ - - - -- -+ - - - -- -+ - - - -@@ -4113,7 +1961,7 @@ to upconvert to 32b float internally? - - - -- -+ - - geometry shader - -@@ -4125,7 +1973,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -4139,10 +1987,10 @@ to upconvert to 32b float internally? - - - -- -- -- -- -+ -+ -+ -+ - - - -@@ -4159,11 +2007,11 @@ to upconvert to 32b float internally? - - - -- -+ - Packed array of a6xx_varying_interp_mode - - -- -+ - Packed array of a6xx_varying_ps_repl_mode - - -@@ -4172,12 +2020,12 @@ to upconvert to 32b float internally? - - - -- -+ - - - - -- -+ - - -@@ -4206,7 +2054,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -4215,7 +2063,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -4225,14 +2073,14 @@ to upconvert to 32b float internally? - - - -- -+ - - - - - - -- -+ - - num of varyings plus four for gl_Position (plus one if gl_PointSize) - plus # of transform-feedback (streamout) varyings if using the -@@ -4249,11 +2097,11 @@ to upconvert to 32b float internally? - - - -- -- -- -+ -+ -+ - -- -+ - - - -@@ -4272,7 +2120,7 @@ to upconvert to 32b float internally? - - - -- -+ - -@@ -4282,19 +2130,19 @@ to upconvert to 32b float internally? - - - -- -+ - - -- -+ - - -- -+ - - -- -+ - - -- -+ - - - -@@ -4311,15 +2159,15 @@ to upconvert to 32b float internally? - - - -- -+ - - -- -+ - - - - -- -+ - - - -@@ -4334,7 +2182,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -4344,15 +2192,15 @@ to upconvert to 32b float internally? - - - -- -+ - - - -- -+ - - - -- -+ - - - -@@ -4367,27 +2215,27 @@ to upconvert to 32b float internally? - - - -- -+ - - -- -+ - - - -- -+ - - - - - -- -- -+ -+ - - - - - -- -+ - - - -@@ -4397,17 +2245,17 @@ to upconvert to 32b float internally? - -- -+ - -- -+ - - - -- -+ - -- -+ - - num of varyings plus four for gl_Position (plus one if gl_PointSize) - plus # of transform-feedback (streamout) varyings if using the -@@ -4417,19 +2265,19 @@ to upconvert to 32b float internally? - - - -- -+ - - - - - -- -- -+ -+ - -- -- -+ -+ - -- -+ - - - -@@ -4438,9 +2286,9 @@ to upconvert to 32b float internally? - - - -- -+ - -- -+ - - - -@@ -4451,31 +2299,31 @@ to upconvert to 32b float internally? - - - -- -- -- -- -- -+ -+ -+ -+ -+ - -- -+ - - Possibly not really "initiating" the draw but the layout is similar - to VGT_DRAW_INITIATOR on older gens - - -- -- -+ -+ - - -- -+ - - - - -- -- -+ -+ - -- -+ - Written by CP_SET_VISIBILITY_OVERRIDE handler - - -@@ -4488,18 +2336,18 @@ to upconvert to 32b float internally? - - - -- -+ - - - -- -+ - - - - - - -- -+ - - - This is the ID of the current patch within the -@@ -4512,32 +2360,32 @@ to upconvert to 32b float internally? - - - -- -+ - - - - - -- -+ - - -- -+ - - - -- -+ - - - - -- -+ - - - -- -- -+ -+ - - - -@@ -4546,14 +2394,14 @@ to upconvert to 32b float internally? - - - -- -+ - - - - -- -+ - -- -+ - - - -@@ -4573,7 +2421,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -4588,7 +2436,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - - - -- -+ - - - -@@ -4630,17 +2478,17 @@ to upconvert to 32b float internally? - --> - - -- -+ - - -- -+ - - - - - - -- -+ - -- -+ - -- -- -+ -+ - - - -@@ -4678,12 +2526,12 @@ to upconvert to 32b float internally? - - -- -+ - - - -@@ -4752,7 +2600,7 @@ to upconvert to 32b float internally? - - - -- -+ - - This seems to be be the equivalent of HWSTACKOFFSET in - a3xx. The ldp/stp offset formula above isn't affected by -@@ -4763,18 +2611,18 @@ to upconvert to 32b float internally? - - - -- -- -+ -+ - -- -+ - -- -+ - -- -- -- -+ -+ -+ - -- -+ - - - -@@ -4782,32 +2630,32 @@ to upconvert to 32b float internally? - Total size of local storage in dwords divided by the wave size. - The maximum value is 64. With the wave size being always 64 for HS, - the maximum size of local storage should be: -- 64 (wavesize) * 64 (SP_HS_WAVE_INPUT_SIZE) * 4 = 16k -+ 64 (wavesize) * 64 (SP_HS_CNTL_1) * 4 = 16k - --> -- -- -+ -+ - - -- -- -+ -+ - -- -+ - -- -+ - -- -- -- -+ -+ -+ - -- -+ - - - -- -+ - - -- -- -+ -+ - - - -@@ -4815,7 +2663,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -4825,22 +2673,22 @@ to upconvert to 32b float internally? - - - -- -- -+ -+ - -- -+ - -- -+ - -- -- -- -+ -+ -+ - -- -+ - - - -- -+ - - Normally the size of the output of the last stage in - dwords. It should be programmed as follows: -@@ -4854,11 +2702,11 @@ to upconvert to 32b float internally? - doesn't matter in practice. - - -- -+ - - -- -- -+ -+ - - - -@@ -4867,7 +2715,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -4877,29 +2725,29 @@ to upconvert to 32b float internally? - - - -- -- -+ -+ - -- -+ - -- -+ - -- -- -- -- -- -- -- -- -- -- -- -- -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ - - - -- -+ - - - -@@ -4909,8 +2757,7 @@ to upconvert to 32b float internally? - fine derivatives and quad subgroup ops. - - -- -- -+ - - - -@@ -4923,12 +2770,12 @@ to upconvert to 32b float internally? - - - -- -- -- -- -- -- -+ -+ -+ -+ -+ -+ - - - -@@ -4948,7 +2795,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -4958,17 +2805,17 @@ to upconvert to 32b float internally? - - - -- -+ - - - - - -- -+ - - - -- -+ - per MRT - - -@@ -4976,7 +2823,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -4985,7 +2832,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -5002,7 +2849,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -5016,7 +2863,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -5028,22 +2875,23 @@ to upconvert to 32b float internally? - - - -- -+ - - - - - -- -+ - -- -+ -+ - - - - - - -- -+ - - - -@@ -5053,8 +2901,15 @@ to upconvert to 32b float internally? - - - -+ -+ -+ -+ -+ -+ -+ - -- -+ - - - If 0 - all 32k of shared storage is enabled, otherwise -@@ -5065,32 +2920,36 @@ to upconvert to 32b float internally? - always return 0) - - -- -- -- -- -- -- -- -+ -+ -+ This defines the split between consts and local -+ memory in the Local Buffer. The programmed value -+ must be at least the actual CONSTLEN. -+ -+ -+ -+ -+ -+ - -- -+ - -- -+ - -- -- -+ -+ - -- -+ - -- -- -+ -+ - - - - - -- -- -+ -+ - - - - - -@@ -5110,18 +2980,16 @@ to upconvert to 32b float internally? - - - -- -- -+ How invocations/fibers within a workgroup are tiled. -+ - - - - -- -- -- -- -+ -+ -+ -+ - - - -@@ -5146,18 +3014,19 @@ to upconvert to 32b float internally? - - - -- -- -+ -+ -+ - - -- -+ - -- -+ - - -- -+ - - Specify for which components the output color should be read - from alias, e.g. for: -@@ -5167,7 +3036,7 @@ to upconvert to 32b float internally? - alias.1.b32.0 r1.x, c4.x - alias.1.b32.0 r0.x, c0.x - -- the SP_PS_ALIASED_COMPONENTS would be 0x00001111 -+ the SP_PS_OUTPUT_CONST_MASK would be 0x00001111 - - - -@@ -5193,7 +3062,7 @@ to upconvert to 32b float internally? - - - -- -+ - -- -- -+ -+ - - - -- -+ - - - -@@ -5248,8 +3117,8 @@ to upconvert to 32b float internally? - - - -- -- -+ -+ - - - -@@ -5257,16 +3126,16 @@ to upconvert to 32b float internally? - - - -- -+ - - - - -- -- -- -+ -+ -+ - -- -+ - -@@ -5281,7 +3150,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -@@ -5301,33 +3170,44 @@ to upconvert to 32b float internally? - "a6xx_sp_ps_tp_cluster" but this actually specifies the border - color base for compute shaders. - --> -- -+ - - - - - - -- -- -- -+ - - - -- -+ - - - - - -- -- -- -- -- -- -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ - -- -+ -+ -+ - - - -@@ -5336,42 +3216,45 @@ to upconvert to 32b float internally? - badly named or the functionality moved in a6xx. But downstream kernel - calls this "a6xx_sp_ps_tp_2d_cluster" - --> -- -- -+ -+ - - - -- -- -+ -+ - - - - -- -- -+ -+ - - - -- -- -- -- -+ -+ -+ -+ - - - -- -- -- -- -- -- -- -+ -+ -+ -+ -+ -+ -+ - -- -- -+ -+ - -- -- -+ -+ - - - -@@ -5383,8 +3266,12 @@ to upconvert to 32b float internally? - - - -- -- -+ -+ -+ -+ -+ -+ - - - -@@ -5422,34 +3309,44 @@ to upconvert to 32b float internally? - - - -- -+ - - - - - -- -- -- -- -+ -+ -+ -+ - -- -- -- -- -+ -+ -+ -+ - -- -- -- -+ -+ - - -- -- -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ - -- -- -+ -+ -+ -+ -+ - -- -+ - - - -@@ -5462,94 +3359,94 @@ to upconvert to 32b float internally? - - - -- -+ - - - - - -- -+ - - - - - - -- -+ - - - - - -- -+ - - - - -- -+ - -- -+ - - - -- -+ - - - - - - -- -- -- -- -- -- -+ -+ -+ -+ -+ -+ - - -- -+ - - - - - - -- -- -- -- -+ -+ -+ -+ - - -- -+ - - - - - - -- -+ - - -- -+ - - -- -+ - - -- -+ - - -- -+ - - -- -+ - - -- -+ - - -@@ -5557,7 +3454,7 @@ to upconvert to 32b float internally? - - - -- -+ - - - -- -- -- -+ -+ -+ - - -- -+ - - - - - - -- -+ - - -- -+ - - -- -+ - - -- -+ - - -- -+ - - -- -+ - - - -- -- -- -+ -+ -+ - - - -@@ -5611,19 +3508,29 @@ to upconvert to 32b float internally? - - - -- -+ - - - - -- -- -- -- -+ -+ When this bit is enabled, the dispatch order interleaves -+ the z coordinate instead of launching all workgroups -+ with z=0, then all with z=1 and so on. -+ -+ -+ -+ When both fields are non-0 then the dispatcher uses -+ these tile sizes to launch workgroups in a tiled manner -+ when the x and y workgroup counts are -+ both more than 1. -+ -+ -+ - - -- -- -+ -+ - - - -@@ -5641,29 +3548,27 @@ to upconvert to 32b float internally? - - - -- -- -+ -+ - -- -- -- -+ - - -- -+ - - - -- -+ - - - -- -+ - - - - - -- -+ - - This register clears pending loads queued up by - CP_LOAD_STATE6. Each bit resets a particular kind(s) of -@@ -5678,8 +3583,8 @@ to upconvert to 32b float internally? - - - -- -- -+ -+ - - - -@@ -5690,20 +3595,20 @@ to upconvert to 32b float internally? - - - -- -+ - - - -- -+ - - - -- -+ - - - - -- -+ - - This register clears pending loads queued up by - CP_LOAD_STATE6. Each bit resets a particular kind(s) of -@@ -5718,18 +3623,18 @@ to upconvert to 32b float internally? - - - -- -- -+ -+ - - - - - - -- -- -+ -+ - -- -+ - - - -@@ -5738,7 +3643,7 @@ to upconvert to 32b float internally? - const pool and 16 in the geometry const pool although - only 8 are actually used (why?) and they are mapped to - c504-c511 in each stage. Both VS and FS shared consts -- are written using ST6_CONSTANTS/SB6_IBO, so that both -+ are written using ST6_CONSTANTS/SB6_UAV, so that both - the geometry and FS shared consts can be written at once - by using CP_LOAD_STATE6 rather than - CP_LOAD_STATE6_FRAG/CP_LOAD_STATE6_GEOM. In addition -@@ -5747,13 +3652,13 @@ to upconvert to 32b float internally? - - There is also a separate shared constant pool for CS, - which is loaded through CP_LOAD_STATE6_FRAG with -- ST6_UBO/ST6_IBO. However the only real difference for CS -+ ST6_UBO/ST6_UAV. However the only real difference for CS - is the dword units. - - - - -- -+ - - - -@@ -5788,10 +3693,10 @@ to upconvert to 32b float internally? - sequence. The sequence used internally for an event looks like: - - write EVENT_CMD pipe register - - write CP_EVENT_START -- - write HLSQ_EVENT_CMD with event or HLSQ_DRAW_CMD -- - write PC_EVENT_CMD with event or PC_DRAW_CMD -- - write HLSQ_EVENT_CMD(CONTEXT_DONE) -- - write PC_EVENT_CMD(CONTEXT_DONE) -+ - write SP_EVENT_INITIATOR with event or SP_DRAW_INITIATOR -+ - write PC_EVENT_INITIATOR with event or PC_DRAW_INITIATOR -+ - write SP_EVENT_INITIATOR(CONTEXT_DONE) -+ - write PC_EVENT_INITIATOR(CONTEXT_DONE) - - write CP_EVENT_END - Writing to CP_EVENT_END seems to actually trigger the context roll - --> -@@ -5809,193 +3714,6 @@ to upconvert to 32b float internally? - - - -- -- -- Texture sampler dwords -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- clamp result to [0, 1] if the format is unorm or -- [-1, 1] if the format is snorm, *after* -- filtering. Has no effect for other formats. -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- Texture constant dwords -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- probably for D3D structured UAVs, normally set to 1 -- -- -- -- -- -- Pitch in bytes (so actually stride) -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - - - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/registers/adreno/a7xx_enums.xml BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/registers/adreno/a7xx_enums.xml ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/registers/adreno/a7xx_enums.xml 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/registers/adreno/a7xx_enums.xml 2025-10-22 13:53:56.475169334 -0400 -@@ -0,0 +1,223 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/registers/adreno/a7xx_perfcntrs.xml BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/registers/adreno/a7xx_perfcntrs.xml ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/registers/adreno/a7xx_perfcntrs.xml 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/registers/adreno/a7xx_perfcntrs.xml 2025-10-22 13:53:56.475169334 -0400 -@@ -0,0 +1,1030 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/registers/adreno/adreno_pm4.xml BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/registers/adreno/adreno_pm4.xml ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/registers/adreno/adreno_pm4.xml 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/registers/adreno/adreno_pm4.xml 2025-10-22 13:53:56.475169334 -0400 -@@ -21,9 +21,9 @@ xsi:schemaLocation="https://gitlab.freed - - - -- -- -- -+ -+ -+ - - - -@@ -31,8 +31,8 @@ xsi:schemaLocation="https://gitlab.freed - - - -- If A6XX_RB_SAMPLE_COUNT_CONTROL.copy is true, writes OQ Z passed -- sample counts to RB_SAMPLE_COUNT_ADDR. This writes to main -+ If A6XX_RB_SAMPLE_COUNTER_CNTL.copy is true, writes OQ Z passed -+ sample counts to RB_SAMPLE_COUNTER_BASE. This writes to main - memory, skipping UCHE. - - -@@ -98,6 +98,13 @@ xsi:schemaLocation="https://gitlab.freed - - - -+ Flip between the primary and secondary LRZ buffers. This is used -+ for concurrent binning, so that BV can write to one buffer while -+ BR reads from the other. -+ -+ -+ -+ - Clears based on GRAS_LRZ_CNTL configuration, could clear - fast-clear buffer or LRZ direction. - LRZ direction is stored at lrz_fc_offset + 0x200, has 1 byte which -@@ -114,6 +121,7 @@ xsi:schemaLocation="https://gitlab.freed - - - -+ - - - -@@ -372,7 +380,7 @@ xsi:schemaLocation="https://gitlab.freed - - - Conditionally load a IB based on a flag, prefetch enabled -- -+ - Conditionally load a IB based on a flag, prefetch disabled - - Load a buffer with pre-fetch enabled -@@ -538,7 +546,7 @@ xsi:schemaLocation="https://gitlab.freed - - - -- -+ - - - -@@ -650,6 +658,11 @@ xsi:schemaLocation="https://gitlab.freed - - Reset various on-chip state used for synchronization - -+ -+ Invalidates the "CCHE" introduced on a740 -+ -+ -+ - - - -@@ -792,14 +805,14 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) - - - -- -- -+ -+ - - - - - -- -+ - - - -@@ -1121,39 +1134,93 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) - - - -+ -+ -+ -+ -+ - - -+ -+ -+ A mask of bins, starting at VSC_N, whose -+ visibility is OR'd together. A value of 0 is -+ interpreted as 1 (i.e. just use VSC_N for -+ visbility) for backwards compatibility. Only -+ exists on a7xx. -+ -+ - - - - -+ -+ -+ If this field is 1, VSC_MASK and VSC_N are -+ ignored and instead a new ordinal immediately -+ after specifies the full 32-bit mask of bins -+ to use. The mask is "absolute" instead of -+ relative to VSC_N. -+ -+ - -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ - - - -@@ -1164,23 +1231,42 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) - stream is recorded. - - -+ - - - - -+ - -- -- -- -- -- -- -- -- -- -- -- -- -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ - - - -@@ -1198,6 +1284,9 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) - - - -+ -+ -+ - - - -@@ -1348,6 +1437,8 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) - - - -+ -+ - - - -@@ -1655,8 +1746,8 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) - - - -- -- -+ -+ - - - -@@ -1670,15 +1761,11 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) - - - -+ - - - -- -- -- -- -- -- -+ - - - -@@ -1773,13 +1860,23 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) - - - Tell CP the current operation mode, indicates save and restore procedure -+ -+ -+ -+ -+ -+ -+ -+ -+ - -- -- -- -- -- -- -+ -+ -+ -+ -+ -+ -+ - - - -@@ -1789,23 +1886,40 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) - --> - - -- -- -- - - -+ -+ -+ -+ -+ -+ -+ -+ -+ - -- -- -+ CP_SET_MARKER is used with these bits to create a -+ critical section around a workaround for ray tracing. -+ The workaround happens after BVH building, and appears -+ to invalidate the RTU's BVH node cache. It makes sure -+ that only one of BR/BV/LPAC is executing the -+ workaround at a time, and no draws using RT on BV/LPAC -+ are executing while the workaround is executed on BR (or -+ vice versa, that no draws on BV/BR using RT are executed -+ while the workaround executes on LPAC), by -+ hooking subsequent CP_EVENT_WRITE/CP_DRAW_*/CP_EXEC_CS. -+ The blob usage is: -+ -+ CP_SET_MARKER(RT_WA_START) -+ ... workaround here ... -+ CP_SET_MARKER(RT_WA_END) -+ ... -+ CP_SET_MARKER(SHADER_USES_RT) -+ CP_DRAW_INDX(...) or CP_EXEC_CS(...) -+ --> -+ -+ -+ - - - -@@ -1832,9 +1946,9 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) - If concurrent binning is disabled then BR also does binning so it will also - write the "real" registers in BR. - --> -- -- -- -+ -+ -+ - - - -@@ -1935,11 +2049,11 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) - a bitmask of which modes pass the test. - --> - -- -+ - - - -- -+ - - - -@@ -2014,10 +2128,10 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) - - - -- Used by the userspace and kernel drivers to set various IB's -- which are executed during context save/restore for handling -- state that isn't restored by the context switch routine itself. -- -+ Used by the userspace and kernel drivers to set various IB's -+ which are executed during context save/restore for handling -+ state that isn't restored by the context switch routine itself. -+ - - - Executed unconditionally when switching back to the context. -@@ -2087,12 +2201,12 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) - - - Tracks GRAS_LRZ_CNTL::GREATER, GRAS_LRZ_CNTL::DIR, and -- GRAS_LRZ_DEPTH_VIEW with previous values, and if one of -+ GRAS_LRZ_VIEW_INFO with previous values, and if one of - the following is true: - - GRAS_LRZ_CNTL::GREATER has changed - - GRAS_LRZ_CNTL::DIR has changed, the old value is not - CUR_DIR_GE, and the new value is not CUR_DIR_DISABLED -- - GRAS_LRZ_DEPTH_VIEW has changed -+ - GRAS_LRZ_VIEW_INFO has changed - then it does a LRZ_FLUSH with GRAS_LRZ_CNTL::ENABLE - forced to 1. - Only exists in a650_sqe.fw. -@@ -2207,7 +2321,7 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) - - - -- Best guess is that it is a faster way to fetch all the VSC_STATE registers -+ Best guess is that it is a faster way to fetch all the VSC_CHANNEL_VISIBILITY registers - and keep them in a local scratch memory instead of fetching every time - when skipping IBs. - -@@ -2255,7 +2369,18 @@ opcode: CP_LOAD_STATE4 (30) (4 dwords) - - - -- -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ - - - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/registers/display/dsi.xml BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/registers/display/dsi.xml ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/registers/display/dsi.xml 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/registers/display/dsi.xml 2025-10-22 13:53:56.475169334 -0400 -@@ -159,28 +159,28 @@ xsi:schemaLocation="https://gitlab.freed - - - -- -- -+ -+ - - -- -- -+ -+ - - -- -- -+ -+ - - -- -- -+ -+ - - -- -- -+ -+ - - -- -- -+ -+ - - - -@@ -209,8 +209,8 @@ xsi:schemaLocation="https://gitlab.freed - - - -- -- -+ -+ - - - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/msm/registers/gen_header.py BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/registers/gen_header.py ---- BPI-Router-Linux-kernel/drivers/gpu/drm/msm/registers/gen_header.py 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/msm/registers/gen_header.py 2025-10-22 13:53:56.475169334 -0400 -@@ -11,6 +11,7 @@ import collections - import argparse - import time - import datetime -+import re - - class Error(Exception): - def __init__(self, message): -@@ -877,13 +878,14 @@ The rules-ng-ng source files this header - """) - maxlen = 0 - for filepath in p.xml_files: -- maxlen = max(maxlen, len(filepath)) -+ new_filepath = re.sub("^.+drivers","drivers",filepath) -+ maxlen = max(maxlen, len(new_filepath)) - for filepath in p.xml_files: -- pad = " " * (maxlen - len(filepath)) -+ pad = " " * (maxlen - len(new_filepath)) - filesize = str(os.path.getsize(filepath)) - filesize = " " * (7 - len(filesize)) + filesize - filetime = time.ctime(os.path.getmtime(filepath)) -- print("- " + filepath + pad + " (" + filesize + " bytes, from " + filetime + ")") -+ print("- " + new_filepath + pad + " (" + filesize + " bytes, from )") - if p.copyright_year: - current_year = str(datetime.date.today().year) - print() -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/dispnv50/wndw.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/dispnv50/wndw.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/dispnv50/wndw.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/dispnv50/wndw.c 2025-10-22 13:53:56.475169334 -0400 -@@ -795,6 +795,10 @@ static bool nv50_plane_format_mod_suppor - struct nouveau_drm *drm = nouveau_drm(plane->dev); - uint8_t i; - -+ /* All chipsets can display all formats in linear layout */ -+ if (modifier == DRM_FORMAT_MOD_LINEAR) -+ return true; -+ - if (drm->client.device.info.chipset < 0xc0) { - const struct drm_format_info *info = drm_format_info(format); - const uint8_t kind = (modifier >> 12) & 0xff; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/gv100_fence.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/gv100_fence.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/gv100_fence.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/gv100_fence.c 2025-10-22 13:53:56.475169334 -0400 -@@ -18,7 +18,7 @@ gv100_fence_emit32(struct nouveau_channe - struct nvif_push *push = &chan->chan.push; - int ret; - -- ret = PUSH_WAIT(push, 8); -+ ret = PUSH_WAIT(push, 13); - if (ret) - return ret; - -@@ -32,6 +32,11 @@ gv100_fence_emit32(struct nouveau_channe - NVDEF(NVC36F, SEM_EXECUTE, PAYLOAD_SIZE, 32BIT) | - NVDEF(NVC36F, SEM_EXECUTE, RELEASE_TIMESTAMP, DIS)); - -+ PUSH_MTHD(push, NVC36F, MEM_OP_A, 0, -+ MEM_OP_B, 0, -+ MEM_OP_C, NVDEF(NVC36F, MEM_OP_C, MEMBAR_TYPE, SYS_MEMBAR), -+ MEM_OP_D, NVDEF(NVC36F, MEM_OP_D, OPERATION, MEMBAR)); -+ - PUSH_MTHD(push, NVC36F, NON_STALL_INTERRUPT, 0); - - PUSH_KICK(push); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/include/nvhw/class/clc36f.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/include/nvhw/class/clc36f.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/include/nvhw/class/clc36f.h 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/include/nvhw/class/clc36f.h 2025-10-22 13:53:56.475169334 -0400 -@@ -7,6 +7,91 @@ - - #define NVC36F_NON_STALL_INTERRUPT (0x00000020) - #define NVC36F_NON_STALL_INTERRUPT_HANDLE 31:0 -+// NOTE - MEM_OP_A and MEM_OP_B have been replaced in gp100 with methods for -+// specifying the page address for a targeted TLB invalidate and the uTLB for -+// a targeted REPLAY_CANCEL for UVM. -+// The previous MEM_OP_A/B functionality is in MEM_OP_C/D, with slightly -+// rearranged fields. -+#define NVC36F_MEM_OP_A (0x00000028) -+#define NVC36F_MEM_OP_A_TLB_INVALIDATE_CANCEL_TARGET_CLIENT_UNIT_ID 5:0 // only relevant for REPLAY_CANCEL_TARGETED -+#define NVC36F_MEM_OP_A_TLB_INVALIDATE_INVALIDATION_SIZE 5:0 // Used to specify size of invalidate, used for invalidates which are not of the REPLAY_CANCEL_TARGETED type -+#define NVC36F_MEM_OP_A_TLB_INVALIDATE_CANCEL_TARGET_GPC_ID 10:6 // only relevant for REPLAY_CANCEL_TARGETED -+#define NVC36F_MEM_OP_A_TLB_INVALIDATE_CANCEL_MMU_ENGINE_ID 6:0 // only relevant for REPLAY_CANCEL_VA_GLOBAL -+#define NVC36F_MEM_OP_A_TLB_INVALIDATE_SYSMEMBAR 11:11 -+#define NVC36F_MEM_OP_A_TLB_INVALIDATE_SYSMEMBAR_EN 0x00000001 -+#define NVC36F_MEM_OP_A_TLB_INVALIDATE_SYSMEMBAR_DIS 0x00000000 -+#define NVC36F_MEM_OP_A_TLB_INVALIDATE_TARGET_ADDR_LO 31:12 -+#define NVC36F_MEM_OP_B (0x0000002c) -+#define NVC36F_MEM_OP_B_TLB_INVALIDATE_TARGET_ADDR_HI 31:0 -+#define NVC36F_MEM_OP_C (0x00000030) -+#define NVC36F_MEM_OP_C_MEMBAR_TYPE 2:0 -+#define NVC36F_MEM_OP_C_MEMBAR_TYPE_SYS_MEMBAR 0x00000000 -+#define NVC36F_MEM_OP_C_MEMBAR_TYPE_MEMBAR 0x00000001 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_PDB 0:0 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_PDB_ONE 0x00000000 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_PDB_ALL 0x00000001 // Probably nonsensical for MMU_TLB_INVALIDATE_TARGETED -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_GPC 1:1 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_GPC_ENABLE 0x00000000 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_GPC_DISABLE 0x00000001 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_REPLAY 4:2 // only relevant if GPC ENABLE -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_REPLAY_NONE 0x00000000 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_REPLAY_START 0x00000001 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_REPLAY_START_ACK_ALL 0x00000002 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_REPLAY_CANCEL_TARGETED 0x00000003 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_REPLAY_CANCEL_GLOBAL 0x00000004 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_REPLAY_CANCEL_VA_GLOBAL 0x00000005 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_ACK_TYPE 6:5 // only relevant if GPC ENABLE -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_ACK_TYPE_NONE 0x00000000 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_ACK_TYPE_GLOBALLY 0x00000001 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_ACK_TYPE_INTRANODE 0x00000002 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_ACCESS_TYPE 9:7 //only relevant for REPLAY_CANCEL_VA_GLOBAL -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_ACCESS_TYPE_VIRT_READ 0 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_ACCESS_TYPE_VIRT_WRITE 1 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_ACCESS_TYPE_VIRT_ATOMIC_STRONG 2 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_ACCESS_TYPE_VIRT_RSVRVD 3 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_ACCESS_TYPE_VIRT_ATOMIC_WEAK 4 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_ACCESS_TYPE_VIRT_ATOMIC_ALL 5 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_ACCESS_TYPE_VIRT_WRITE_AND_ATOMIC 6 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_ACCESS_TYPE_VIRT_ALL 7 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_PAGE_TABLE_LEVEL 9:7 // Invalidate affects this level and all below -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_PAGE_TABLE_LEVEL_ALL 0x00000000 // Invalidate tlb caches at all levels of the page table -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_PAGE_TABLE_LEVEL_PTE_ONLY 0x00000001 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_PAGE_TABLE_LEVEL_UP_TO_PDE0 0x00000002 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_PAGE_TABLE_LEVEL_UP_TO_PDE1 0x00000003 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_PAGE_TABLE_LEVEL_UP_TO_PDE2 0x00000004 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_PAGE_TABLE_LEVEL_UP_TO_PDE3 0x00000005 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_PAGE_TABLE_LEVEL_UP_TO_PDE4 0x00000006 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_PAGE_TABLE_LEVEL_UP_TO_PDE5 0x00000007 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_PDB_APERTURE 11:10 // only relevant if PDB_ONE -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_PDB_APERTURE_VID_MEM 0x00000000 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_PDB_APERTURE_SYS_MEM_COHERENT 0x00000002 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_PDB_APERTURE_SYS_MEM_NONCOHERENT 0x00000003 -+#define NVC36F_MEM_OP_C_TLB_INVALIDATE_PDB_ADDR_LO 31:12 // only relevant if PDB_ONE -+#define NVC36F_MEM_OP_C_ACCESS_COUNTER_CLR_TARGETED_NOTIFY_TAG 19:0 -+// MEM_OP_D MUST be preceded by MEM_OPs A-C. -+#define NVC36F_MEM_OP_D (0x00000034) -+#define NVC36F_MEM_OP_D_TLB_INVALIDATE_PDB_ADDR_HI 26:0 // only relevant if PDB_ONE -+#define NVC36F_MEM_OP_D_OPERATION 31:27 -+#define NVC36F_MEM_OP_D_OPERATION_MEMBAR 0x00000005 -+#define NVC36F_MEM_OP_D_OPERATION_MMU_TLB_INVALIDATE 0x00000009 -+#define NVC36F_MEM_OP_D_OPERATION_MMU_TLB_INVALIDATE_TARGETED 0x0000000a -+#define NVC36F_MEM_OP_D_OPERATION_L2_PEERMEM_INVALIDATE 0x0000000d -+#define NVC36F_MEM_OP_D_OPERATION_L2_SYSMEM_INVALIDATE 0x0000000e -+// CLEAN_LINES is an alias for Tegra/GPU IP usage -+#define NVC36F_MEM_OP_B_OPERATION_L2_INVALIDATE_CLEAN_LINES 0x0000000e -+#define NVC36F_MEM_OP_D_OPERATION_L2_CLEAN_COMPTAGS 0x0000000f -+#define NVC36F_MEM_OP_D_OPERATION_L2_FLUSH_DIRTY 0x00000010 -+#define NVC36F_MEM_OP_D_OPERATION_L2_WAIT_FOR_SYS_PENDING_READS 0x00000015 -+#define NVC36F_MEM_OP_D_OPERATION_ACCESS_COUNTER_CLR 0x00000016 -+#define NVC36F_MEM_OP_D_ACCESS_COUNTER_CLR_TYPE 1:0 -+#define NVC36F_MEM_OP_D_ACCESS_COUNTER_CLR_TYPE_MIMC 0x00000000 -+#define NVC36F_MEM_OP_D_ACCESS_COUNTER_CLR_TYPE_MOMC 0x00000001 -+#define NVC36F_MEM_OP_D_ACCESS_COUNTER_CLR_TYPE_ALL 0x00000002 -+#define NVC36F_MEM_OP_D_ACCESS_COUNTER_CLR_TYPE_TARGETED 0x00000003 -+#define NVC36F_MEM_OP_D_ACCESS_COUNTER_CLR_TARGETED_TYPE 2:2 -+#define NVC36F_MEM_OP_D_ACCESS_COUNTER_CLR_TARGETED_TYPE_MIMC 0x00000000 -+#define NVC36F_MEM_OP_D_ACCESS_COUNTER_CLR_TARGETED_TYPE_MOMC 0x00000001 -+#define NVC36F_MEM_OP_D_ACCESS_COUNTER_CLR_TARGETED_BANK 6:3 - #define NVC36F_SEM_ADDR_LO (0x0000005c) - #define NVC36F_SEM_ADDR_LO_OFFSET 31:2 - #define NVC36F_SEM_ADDR_HI (0x00000060) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nouveau_backlight.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nouveau_backlight.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nouveau_backlight.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nouveau_backlight.c 2025-10-22 13:53:56.475169334 -0400 -@@ -42,7 +42,7 @@ - #include "nouveau_acpi.h" - - static struct ida bl_ida; --#define BL_NAME_SIZE 15 // 12 for name + 2 for digits + 1 for '\0' -+#define BL_NAME_SIZE 24 // 12 for name + 11 for digits + 1 for '\0' - - static bool - nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE], -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nouveau_debugfs.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nouveau_debugfs.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nouveau_debugfs.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nouveau_debugfs.c 2025-10-22 13:53:56.475169334 -0400 -@@ -314,14 +314,10 @@ nouveau_debugfs_fini(struct nouveau_drm - drm->debugfs = NULL; - } - --int -+void - nouveau_module_debugfs_init(void) - { - nouveau_debugfs_root = debugfs_create_dir("nouveau", NULL); -- if (IS_ERR(nouveau_debugfs_root)) -- return PTR_ERR(nouveau_debugfs_root); -- -- return 0; - } - - void -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nouveau_debugfs.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nouveau_debugfs.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nouveau_debugfs.h 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nouveau_debugfs.h 2025-10-22 13:53:56.475169334 -0400 -@@ -24,7 +24,7 @@ extern void nouveau_debugfs_fini(struct - - extern struct dentry *nouveau_debugfs_root; - --int nouveau_module_debugfs_init(void); -+void nouveau_module_debugfs_init(void); - void nouveau_module_debugfs_fini(void); - #else - static inline void -@@ -42,10 +42,9 @@ nouveau_debugfs_fini(struct nouveau_drm - { - } - --static inline int -+static inline void - nouveau_module_debugfs_init(void) - { -- return 0; - } - - static inline void -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nouveau_drm.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nouveau_drm.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nouveau_drm.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nouveau_drm.c 2025-10-22 13:53:56.475169334 -0400 -@@ -1461,9 +1461,7 @@ nouveau_drm_init(void) - if (!nouveau_modeset) - return 0; - -- ret = nouveau_module_debugfs_init(); -- if (ret) -- return ret; -+ nouveau_module_debugfs_init(); - - #ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER - platform_driver_register(&nouveau_platform_driver); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvif/chan.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvif/chan.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvif/chan.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvif/chan.c 2025-10-22 13:53:56.475169334 -0400 -@@ -39,6 +39,9 @@ nvif_chan_gpfifo_post(struct nvif_chan * - const u32 pbptr = (chan->push.cur - map) + chan->func->gpfifo.post_size; - const u32 gpptr = (chan->gpfifo.cur + 1) & chan->gpfifo.max; - -+ if (!chan->func->gpfifo.post) -+ return 0; -+ - return chan->func->gpfifo.post(chan, gpptr, pbptr); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvif/vmm.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvif/vmm.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvif/vmm.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvif/vmm.c 2025-10-22 13:53:56.475169334 -0400 -@@ -219,7 +219,8 @@ nvif_vmm_ctor(struct nvif_mmu *mmu, cons - case RAW: args->type = NVIF_VMM_V0_TYPE_RAW; break; - default: - WARN_ON(1); -- return -EINVAL; -+ ret = -EINVAL; -+ goto done; - } - - memcpy(args->data, argv, argc); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c 2025-10-22 13:53:56.475169334 -0400 -@@ -350,6 +350,8 @@ nvkm_fifo_dtor(struct nvkm_engine *engin - nvkm_chid_unref(&fifo->chid); - - nvkm_event_fini(&fifo->nonstall.event); -+ if (fifo->func->nonstall_dtor) -+ fifo->func->nonstall_dtor(fifo); - mutex_destroy(&fifo->mutex); - - if (fifo->func->dtor) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c 2025-10-22 13:53:56.475169334 -0400 -@@ -517,19 +517,11 @@ ga100_fifo_nonstall_intr(struct nvkm_int - static void - ga100_fifo_nonstall_block(struct nvkm_event *event, int type, int index) - { -- struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), nonstall.event); -- struct nvkm_runl *runl = nvkm_runl_get(fifo, index, 0); -- -- nvkm_inth_block(&runl->nonstall.inth); - } - - static void - ga100_fifo_nonstall_allow(struct nvkm_event *event, int type, int index) - { -- struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), nonstall.event); -- struct nvkm_runl *runl = nvkm_runl_get(fifo, index, 0); -- -- nvkm_inth_allow(&runl->nonstall.inth); - } - - const struct nvkm_event_func -@@ -564,12 +556,26 @@ ga100_fifo_nonstall_ctor(struct nvkm_fif - if (ret) - return ret; - -+ nvkm_inth_allow(&runl->nonstall.inth); -+ - nr = max(nr, runl->id + 1); - } - - return nr; - } - -+void -+ga100_fifo_nonstall_dtor(struct nvkm_fifo *fifo) -+{ -+ struct nvkm_runl *runl; -+ -+ nvkm_runl_foreach(runl, fifo) { -+ if (runl->nonstall.vector < 0) -+ continue; -+ nvkm_inth_block(&runl->nonstall.inth); -+ } -+} -+ - int - ga100_fifo_runl_ctor(struct nvkm_fifo *fifo) - { -@@ -599,6 +605,7 @@ ga100_fifo = { - .runl_ctor = ga100_fifo_runl_ctor, - .mmu_fault = &tu102_fifo_mmu_fault, - .nonstall_ctor = ga100_fifo_nonstall_ctor, -+ .nonstall_dtor = ga100_fifo_nonstall_dtor, - .nonstall = &ga100_fifo_nonstall, - .runl = &ga100_runl, - .runq = &ga100_runq, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c 2025-10-22 13:53:56.475169334 -0400 -@@ -30,6 +30,7 @@ ga102_fifo = { - .runl_ctor = ga100_fifo_runl_ctor, - .mmu_fault = &tu102_fifo_mmu_fault, - .nonstall_ctor = ga100_fifo_nonstall_ctor, -+ .nonstall_dtor = ga100_fifo_nonstall_dtor, - .nonstall = &ga100_fifo_nonstall, - .runl = &ga100_runl, - .runq = &ga100_runq, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h 2025-10-22 13:53:56.475169334 -0400 -@@ -41,6 +41,7 @@ struct nvkm_fifo_func { - void (*start)(struct nvkm_fifo *, unsigned long *); - - int (*nonstall_ctor)(struct nvkm_fifo *); -+ void (*nonstall_dtor)(struct nvkm_fifo *); - const struct nvkm_event_func *nonstall; - - const struct nvkm_runl_func *runl; -@@ -200,6 +201,7 @@ u32 tu102_chan_doorbell_handle(struct nv - - int ga100_fifo_runl_ctor(struct nvkm_fifo *); - int ga100_fifo_nonstall_ctor(struct nvkm_fifo *); -+void ga100_fifo_nonstall_dtor(struct nvkm_fifo *); - extern const struct nvkm_event_func ga100_fifo_nonstall; - extern const struct nvkm_runl_func ga100_runl; - extern const struct nvkm_runq_func ga100_runq; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c 2025-10-22 13:53:56.475169334 -0400 -@@ -103,7 +103,7 @@ gm200_flcn_pio_imem_wr_init(struct nvkm_ - static void - gm200_flcn_pio_imem_wr(struct nvkm_falcon *falcon, u8 port, const u8 *img, int len, u16 tag) - { -- nvkm_falcon_wr32(falcon, 0x188 + (port * 0x10), tag++); -+ nvkm_falcon_wr32(falcon, 0x188 + (port * 0x10), tag); - while (len >= 4) { - nvkm_falcon_wr32(falcon, 0x184 + (port * 0x10), *(u32 *)img); - img += 4; -@@ -249,9 +249,11 @@ int - gm200_flcn_fw_load(struct nvkm_falcon_fw *fw) - { - struct nvkm_falcon *falcon = fw->falcon; -- int target, ret; -+ int ret; - - if (fw->inst) { -+ int target; -+ - nvkm_falcon_mask(falcon, 0x048, 0x00000001, 0x00000001); - - switch (nvkm_memory_target(fw->inst)) { -@@ -285,15 +287,6 @@ gm200_flcn_fw_load(struct nvkm_falcon_fw - } - - if (fw->boot) { -- switch (nvkm_memory_target(&fw->fw.mem.memory)) { -- case NVKM_MEM_TARGET_VRAM: target = 4; break; -- case NVKM_MEM_TARGET_HOST: target = 5; break; -- case NVKM_MEM_TARGET_NCOH: target = 6; break; -- default: -- WARN_ON(1); -- return -EINVAL; -- } -- - ret = nvkm_falcon_pio_wr(falcon, fw->boot, 0, 0, - IMEM, falcon->code.limit - fw->boot_size, fw->boot_size, - fw->boot_addr >> 8, false); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/fwsec.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/fwsec.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/fwsec.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/fwsec.c 2025-10-22 13:53:56.475169334 -0400 -@@ -209,11 +209,12 @@ nvkm_gsp_fwsec_v2(struct nvkm_gsp *gsp, - fw->boot_addr = bld->start_tag << 8; - fw->boot_size = bld->code_size; - fw->boot = kmemdup(bl->data + hdr->data_offset + bld->code_off, fw->boot_size, GFP_KERNEL); -- if (!fw->boot) -- ret = -ENOMEM; - - nvkm_firmware_put(bl); - -+ if (!fw->boot) -+ return -ENOMEM; -+ - /* Patch in interface data. */ - return nvkm_gsp_fwsec_patch(gsp, fw, desc->InterfaceOffset, init_cmd); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fifo.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fifo.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fifo.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fifo.c 2025-10-22 13:53:56.475169334 -0400 -@@ -601,6 +601,7 @@ r535_fifo_new(const struct nvkm_fifo_fun - rm->chan.func = &r535_chan; - rm->nonstall = &ga100_fifo_nonstall; - rm->nonstall_ctor = ga100_fifo_nonstall_ctor; -+ rm->nonstall_dtor = ga100_fifo_nonstall_dtor; - - return nvkm_fifo_new_(rm, device, type, inst, pfifo); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c 2025-10-22 13:53:56.475169334 -0400 -@@ -719,7 +719,6 @@ r535_gsp_acpi_caps(acpi_handle handle, C - union acpi_object argv4 = { - .buffer.type = ACPI_TYPE_BUFFER, - .buffer.length = 4, -- .buffer.pointer = kmalloc(argv4.buffer.length, GFP_KERNEL), - }, *obj; - - caps->status = 0xffff; -@@ -727,17 +726,22 @@ r535_gsp_acpi_caps(acpi_handle handle, C - if (!acpi_check_dsm(handle, &NVOP_DSM_GUID, NVOP_DSM_REV, BIT_ULL(0x1a))) - return; - -+ argv4.buffer.pointer = kmalloc(argv4.buffer.length, GFP_KERNEL); -+ if (!argv4.buffer.pointer) -+ return; -+ - obj = acpi_evaluate_dsm(handle, &NVOP_DSM_GUID, NVOP_DSM_REV, 0x1a, &argv4); - if (!obj) -- return; -+ goto done; - - if (WARN_ON(obj->type != ACPI_TYPE_BUFFER) || - WARN_ON(obj->buffer.length != 4)) -- return; -+ goto done; - - caps->status = 0; - caps->optimusCaps = *(u32 *)obj->buffer.pointer; - -+done: - ACPI_FREE(obj); - - kfree(argv4.buffer.pointer); -@@ -754,24 +758,28 @@ r535_gsp_acpi_jt(acpi_handle handle, JT_ - union acpi_object argv4 = { - .buffer.type = ACPI_TYPE_BUFFER, - .buffer.length = sizeof(caps), -- .buffer.pointer = kmalloc(argv4.buffer.length, GFP_KERNEL), - }, *obj; - - jt->status = 0xffff; - -+ argv4.buffer.pointer = kmalloc(argv4.buffer.length, GFP_KERNEL); -+ if (!argv4.buffer.pointer) -+ return; -+ - obj = acpi_evaluate_dsm(handle, &JT_DSM_GUID, JT_DSM_REV, 0x1, &argv4); - if (!obj) -- return; -+ goto done; - - if (WARN_ON(obj->type != ACPI_TYPE_BUFFER) || - WARN_ON(obj->buffer.length != 4)) -- return; -+ goto done; - - jt->status = 0; - jt->jtCaps = *(u32 *)obj->buffer.pointer; - jt->jtRevId = (jt->jtCaps & 0xfff00000) >> 20; - jt->bSBIOSCaps = 0; - -+done: - ACPI_FREE(obj); - - kfree(argv4.buffer.pointer); -@@ -1744,6 +1752,13 @@ r535_gsp_fini(struct nvkm_gsp *gsp, bool - nvkm_gsp_sg_free(gsp->subdev.device, &gsp->sr.sgt); - return ret; - } -+ -+ /* -+ * TODO: Debug the GSP firmware / RPC handling to find out why -+ * without this Turing (but none of the other architectures) -+ * ends up resetting all channels after resume. -+ */ -+ msleep(50); - } - - ret = r535_gsp_rpc_unloading_guest_driver(gsp, suspend); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c 2025-10-22 13:53:56.475169334 -0400 -@@ -325,7 +325,7 @@ r535_gsp_msgq_recv(struct nvkm_gsp *gsp, - - rpc = r535_gsp_msgq_peek(gsp, sizeof(*rpc), info.retries); - if (IS_ERR_OR_NULL(rpc)) { -- kfree(buf); -+ kvfree(buf); - return rpc; - } - -@@ -334,7 +334,7 @@ r535_gsp_msgq_recv(struct nvkm_gsp *gsp, - - rpc = r535_gsp_msgq_recv_one_elem(gsp, &info); - if (IS_ERR_OR_NULL(rpc)) { -- kfree(buf); -+ kvfree(buf); - return rpc; - } - -@@ -637,12 +637,18 @@ r535_gsp_rpc_push(struct nvkm_gsp *gsp, - if (payload_size > max_payload_size) { - const u32 fn = rpc->function; - u32 remain_payload_size = payload_size; -+ void *next; - -- /* Adjust length, and send initial RPC. */ -- rpc->length = sizeof(*rpc) + max_payload_size; -- msg->checksum = rpc->length; -+ /* Send initial RPC. */ -+ next = r535_gsp_rpc_get(gsp, fn, max_payload_size); -+ if (IS_ERR(next)) { -+ repv = next; -+ goto done; -+ } - -- repv = r535_gsp_rpc_send(gsp, payload, NVKM_GSP_RPC_REPLY_NOWAIT, 0); -+ memcpy(next, payload, max_payload_size); -+ -+ repv = r535_gsp_rpc_send(gsp, next, NVKM_GSP_RPC_REPLY_NOWAIT, 0); - if (IS_ERR(repv)) - goto done; - -@@ -653,7 +659,6 @@ r535_gsp_rpc_push(struct nvkm_gsp *gsp, - while (remain_payload_size) { - u32 size = min(remain_payload_size, - max_payload_size); -- void *next; - - next = r535_gsp_rpc_get(gsp, NV_VGPU_MSG_FUNCTION_CONTINUATION_RECORD, size); - if (IS_ERR(next)) { -@@ -674,6 +679,8 @@ r535_gsp_rpc_push(struct nvkm_gsp *gsp, - /* Wait for reply. */ - repv = r535_gsp_rpc_handle_reply(gsp, fn, policy, payload_size + - sizeof(*rpc)); -+ if (!IS_ERR(repv)) -+ kvfree(msg); - } else { - repv = r535_gsp_rpc_send(gsp, payload, policy, gsp_rpc_len); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/vmm.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/vmm.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/vmm.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/vmm.c 2025-10-22 13:53:56.475169334 -0400 -@@ -121,7 +121,7 @@ r535_mmu_vaspace_new(struct nvkm_vmm *vm - page_shift -= desc->bits; - - ctrl->levels[i].physAddress = pd->pt[0]->addr; -- ctrl->levels[i].size = (1 << desc->bits) * desc->size; -+ ctrl->levels[i].size = BIT_ULL(desc->bits) * desc->size; - ctrl->levels[i].aperture = 1; - ctrl->levels[i].pageShift = page_shift; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/nova/file.rs BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nova/file.rs ---- BPI-Router-Linux-kernel/drivers/gpu/drm/nova/file.rs 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/nova/file.rs 2025-10-22 13:53:56.475169334 -0400 -@@ -39,7 +39,8 @@ impl File { - _ => return Err(EINVAL), - }; - -- getparam.set_value(value); -+ #[allow(clippy::useless_conversion)] -+ getparam.set_value(value.into()); - - Ok(0) - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/panel/panel-raydium-rm67200.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/panel/panel-raydium-rm67200.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/panel/panel-raydium-rm67200.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/panel/panel-raydium-rm67200.c 2025-10-22 13:53:56.475169334 -0400 -@@ -318,6 +318,7 @@ static void w552793baa_setup(struct mipi - static int raydium_rm67200_prepare(struct drm_panel *panel) - { - struct raydium_rm67200 *ctx = to_raydium_rm67200(panel); -+ struct mipi_dsi_multi_context mctx = { .dsi = ctx->dsi }; - int ret; - - ret = regulator_bulk_enable(ctx->num_supplies, ctx->supplies); -@@ -328,6 +329,12 @@ static int raydium_rm67200_prepare(struc - - msleep(60); - -+ ctx->panel_info->panel_setup(&mctx); -+ mipi_dsi_dcs_exit_sleep_mode_multi(&mctx); -+ mipi_dsi_msleep(&mctx, 120); -+ mipi_dsi_dcs_set_display_on_multi(&mctx); -+ mipi_dsi_msleep(&mctx, 30); -+ - return 0; - } - -@@ -343,20 +350,6 @@ static int raydium_rm67200_unprepare(str - return 0; - } - --static int raydium_rm67200_enable(struct drm_panel *panel) --{ -- struct raydium_rm67200 *rm67200 = to_raydium_rm67200(panel); -- struct mipi_dsi_multi_context ctx = { .dsi = rm67200->dsi }; -- -- rm67200->panel_info->panel_setup(&ctx); -- mipi_dsi_dcs_exit_sleep_mode_multi(&ctx); -- mipi_dsi_msleep(&ctx, 120); -- mipi_dsi_dcs_set_display_on_multi(&ctx); -- mipi_dsi_msleep(&ctx, 30); -- -- return ctx.accum_err; --} -- - static int raydium_rm67200_disable(struct drm_panel *panel) - { - struct raydium_rm67200 *rm67200 = to_raydium_rm67200(panel); -@@ -381,7 +374,6 @@ static const struct drm_panel_funcs rayd - .prepare = raydium_rm67200_prepare, - .unprepare = raydium_rm67200_unprepare, - .get_modes = raydium_rm67200_get_modes, -- .enable = raydium_rm67200_enable, - .disable = raydium_rm67200_disable, - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/panel/panel-simple.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/panel/panel-simple.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/panel/panel-simple.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/panel/panel-simple.c 2025-10-22 13:53:56.475169334 -0400 -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -136,6 +137,14 @@ struct panel_desc { - int connector_type; - }; - -+struct panel_desc_dsi { -+ struct panel_desc desc; -+ -+ unsigned long flags; -+ enum mipi_dsi_pixel_format format; -+ unsigned int lanes; -+}; -+ - struct panel_simple { - struct drm_panel base; - -@@ -430,10 +439,7 @@ static const struct drm_panel_funcs pane - .get_timings = panel_simple_get_timings, - }; - --static struct panel_desc panel_dpi; -- --static int panel_dpi_probe(struct device *dev, -- struct panel_simple *panel) -+static struct panel_desc *panel_dpi_probe(struct device *dev) - { - struct display_timing *timing; - const struct device_node *np; -@@ -445,17 +451,17 @@ static int panel_dpi_probe(struct device - np = dev->of_node; - desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL); - if (!desc) -- return -ENOMEM; -+ return ERR_PTR(-ENOMEM); - - timing = devm_kzalloc(dev, sizeof(*timing), GFP_KERNEL); - if (!timing) -- return -ENOMEM; -+ return ERR_PTR(-ENOMEM); - - ret = of_get_display_timing(np, "panel-timing", timing); - if (ret < 0) { - dev_err(dev, "%pOF: no panel-timing node found for \"panel-dpi\" binding\n", - np); -- return ret; -+ return ERR_PTR(ret); - } - - desc->timings = timing; -@@ -473,9 +479,7 @@ static int panel_dpi_probe(struct device - /* We do not know the connector for the DT node, so guess it */ - desc->connector_type = DRM_MODE_CONNECTOR_DPI; - -- panel->desc = desc; -- -- return 0; -+ return desc; - } - - #define PANEL_SIMPLE_BOUNDS_CHECK(to_check, bounds, field) \ -@@ -570,8 +574,44 @@ static int panel_simple_override_nondefa - return 0; - } - --static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) -+static const struct panel_desc *panel_simple_get_desc(struct device *dev) -+{ -+ if (IS_ENABLED(CONFIG_DRM_MIPI_DSI) && -+ dev_is_mipi_dsi(dev)) { -+ const struct panel_desc_dsi *dsi_desc; -+ -+ dsi_desc = of_device_get_match_data(dev); -+ if (!dsi_desc) -+ return ERR_PTR(-ENODEV); -+ -+ return &dsi_desc->desc; -+ } -+ -+ if (dev_is_platform(dev)) { -+ const struct panel_desc *desc; -+ -+ desc = of_device_get_match_data(dev); -+ if (!desc) { -+ /* -+ * panel-dpi probes without a descriptor and -+ * panel_dpi_probe() will initialize one for us -+ * based on the device tree. -+ */ -+ if (of_device_is_compatible(dev->of_node, "panel-dpi")) -+ return panel_dpi_probe(dev); -+ else -+ return ERR_PTR(-ENODEV); -+ } -+ -+ return desc; -+ } -+ -+ return ERR_PTR(-ENODEV); -+} -+ -+static struct panel_simple *panel_simple_probe(struct device *dev) - { -+ const struct panel_desc *desc; - struct panel_simple *panel; - struct display_timing dt; - struct device_node *ddc; -@@ -579,27 +619,31 @@ static int panel_simple_probe(struct dev - u32 bus_flags; - int err; - -+ desc = panel_simple_get_desc(dev); -+ if (IS_ERR(desc)) -+ return ERR_CAST(desc); -+ - panel = devm_drm_panel_alloc(dev, struct panel_simple, base, - &panel_simple_funcs, desc->connector_type); - if (IS_ERR(panel)) -- return PTR_ERR(panel); -+ return ERR_CAST(panel); - - panel->desc = desc; - - panel->supply = devm_regulator_get(dev, "power"); - if (IS_ERR(panel->supply)) -- return PTR_ERR(panel->supply); -+ return ERR_CAST(panel->supply); - - panel->enable_gpio = devm_gpiod_get_optional(dev, "enable", - GPIOD_OUT_LOW); - if (IS_ERR(panel->enable_gpio)) -- return dev_err_probe(dev, PTR_ERR(panel->enable_gpio), -- "failed to request GPIO\n"); -+ return dev_err_cast_probe(dev, panel->enable_gpio, -+ "failed to request GPIO\n"); - - err = of_drm_get_panel_orientation(dev->of_node, &panel->orientation); - if (err) { - dev_err(dev, "%pOF: failed to get orientation %d\n", dev->of_node, err); -- return err; -+ return ERR_PTR(err); - } - - ddc = of_parse_phandle(dev->of_node, "ddc-i2c-bus", 0); -@@ -608,19 +652,12 @@ static int panel_simple_probe(struct dev - of_node_put(ddc); - - if (!panel->ddc) -- return -EPROBE_DEFER; -+ return ERR_PTR(-EPROBE_DEFER); - } - -- if (desc == &panel_dpi) { -- /* Handle the generic panel-dpi binding */ -- err = panel_dpi_probe(dev, panel); -- if (err) -- goto free_ddc; -- desc = panel->desc; -- } else { -- if (!of_get_display_timing(dev->of_node, "panel-timing", &dt)) -- panel_simple_parse_panel_timing_node(dev, panel, &dt); -- } -+ if (!of_device_is_compatible(dev->of_node, "panel-dpi") && -+ !of_get_display_timing(dev->of_node, "panel-timing", &dt)) -+ panel_simple_parse_panel_timing_node(dev, panel, &dt); - - if (desc->connector_type == DRM_MODE_CONNECTOR_LVDS) { - /* Optional data-mapping property for overriding bus format */ -@@ -703,7 +740,7 @@ static int panel_simple_probe(struct dev - - drm_panel_add(&panel->base); - -- return 0; -+ return panel; - - disable_pm_runtime: - pm_runtime_dont_use_autosuspend(dev); -@@ -712,7 +749,7 @@ free_ddc: - if (panel->ddc) - put_device(&panel->ddc->dev); - -- return err; -+ return ERR_PTR(err); - } - - static void panel_simple_shutdown(struct device *dev) -@@ -5367,7 +5404,12 @@ static const struct of_device_id platfor - }, { - /* Must be the last entry */ - .compatible = "panel-dpi", -- .data = &panel_dpi, -+ -+ /* -+ * Explicitly NULL, the panel_desc structure will be -+ * allocated by panel_dpi_probe(). -+ */ -+ .data = NULL, - }, { - /* sentinel */ - } -@@ -5376,13 +5418,13 @@ MODULE_DEVICE_TABLE(of, platform_of_matc - - static int panel_simple_platform_probe(struct platform_device *pdev) - { -- const struct panel_desc *desc; -+ struct panel_simple *panel; - -- desc = of_device_get_match_data(&pdev->dev); -- if (!desc) -- return -ENODEV; -+ panel = panel_simple_probe(&pdev->dev); -+ if (IS_ERR(panel)) -+ return PTR_ERR(panel); - -- return panel_simple_probe(&pdev->dev, desc); -+ return 0; - } - - static void panel_simple_platform_remove(struct platform_device *pdev) -@@ -5412,14 +5454,6 @@ static struct platform_driver panel_simp - .shutdown = panel_simple_platform_shutdown, - }; - --struct panel_desc_dsi { -- struct panel_desc desc; -- -- unsigned long flags; -- enum mipi_dsi_pixel_format format; -- unsigned int lanes; --}; -- - static const struct drm_display_mode auo_b080uan01_mode = { - .clock = 154500, - .hdisplay = 1200, -@@ -5653,16 +5687,14 @@ MODULE_DEVICE_TABLE(of, dsi_of_match); - static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi) - { - const struct panel_desc_dsi *desc; -+ struct panel_simple *panel; - int err; - -- desc = of_device_get_match_data(&dsi->dev); -- if (!desc) -- return -ENODEV; -- -- err = panel_simple_probe(&dsi->dev, &desc->desc); -- if (err < 0) -- return err; -+ panel = panel_simple_probe(&dsi->dev); -+ if (IS_ERR(panel)) -+ return PTR_ERR(panel); - -+ desc = container_of(panel->desc, struct panel_desc_dsi, desc); - dsi->mode_flags = desc->flags; - dsi->format = desc->format; - dsi->lanes = desc->lanes; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/panfrost/panfrost_devfreq.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/panfrost/panfrost_devfreq.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/panfrost/panfrost_devfreq.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/panfrost/panfrost_devfreq.c 2025-10-22 13:53:56.475169334 -0400 -@@ -29,7 +29,7 @@ static void panfrost_devfreq_update_util - static int panfrost_devfreq_target(struct device *dev, unsigned long *freq, - u32 flags) - { -- struct panfrost_device *ptdev = dev_get_drvdata(dev); -+ struct panfrost_device *pfdev = dev_get_drvdata(dev); - struct dev_pm_opp *opp; - int err; - -@@ -40,7 +40,7 @@ static int panfrost_devfreq_target(struc - - err = dev_pm_opp_set_rate(dev, *freq); - if (!err) -- ptdev->pfdevfreq.current_frequency = *freq; -+ pfdev->pfdevfreq.current_frequency = *freq; - - return err; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/panfrost/panfrost_drv.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/panfrost/panfrost_drv.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/panfrost/panfrost_drv.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/panfrost/panfrost_drv.c 2025-10-22 13:53:56.475169334 -0400 -@@ -789,6 +789,8 @@ static const struct panfrost_compatible - .vendor_quirk = panfrost_gpu_amlogic_quirk, - }; - -+static const char * const mediatek_pm_domains[] = { "core0", "core1", "core2", -+ "core3", "core4" }; - /* - * The old data with two power supplies for MT8183 is here only to - * keep retro-compatibility with older devicetrees, as DVFS will -@@ -797,51 +799,53 @@ static const struct panfrost_compatible - * On new devicetrees please use the _b variant with a single and - * coupled regulators instead. - */ --static const char * const mediatek_mt8183_supplies[] = { "mali", "sram", NULL }; --static const char * const mediatek_mt8183_pm_domains[] = { "core0", "core1", "core2" }; -+static const char * const legacy_supplies[] = { "mali", "sram", NULL }; - static const struct panfrost_compatible mediatek_mt8183_data = { -- .num_supplies = ARRAY_SIZE(mediatek_mt8183_supplies) - 1, -- .supply_names = mediatek_mt8183_supplies, -- .num_pm_domains = ARRAY_SIZE(mediatek_mt8183_pm_domains), -- .pm_domain_names = mediatek_mt8183_pm_domains, -+ .num_supplies = ARRAY_SIZE(legacy_supplies) - 1, -+ .supply_names = legacy_supplies, -+ .num_pm_domains = 3, -+ .pm_domain_names = mediatek_pm_domains, - }; - --static const char * const mediatek_mt8183_b_supplies[] = { "mali", NULL }; - static const struct panfrost_compatible mediatek_mt8183_b_data = { -- .num_supplies = ARRAY_SIZE(mediatek_mt8183_b_supplies) - 1, -- .supply_names = mediatek_mt8183_b_supplies, -- .num_pm_domains = ARRAY_SIZE(mediatek_mt8183_pm_domains), -- .pm_domain_names = mediatek_mt8183_pm_domains, -+ .num_supplies = ARRAY_SIZE(default_supplies) - 1, -+ .supply_names = default_supplies, -+ .num_pm_domains = 3, -+ .pm_domain_names = mediatek_pm_domains, - .pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF), - }; - --static const char * const mediatek_mt8186_pm_domains[] = { "core0", "core1" }; - static const struct panfrost_compatible mediatek_mt8186_data = { -- .num_supplies = ARRAY_SIZE(mediatek_mt8183_b_supplies) - 1, -- .supply_names = mediatek_mt8183_b_supplies, -- .num_pm_domains = ARRAY_SIZE(mediatek_mt8186_pm_domains), -- .pm_domain_names = mediatek_mt8186_pm_domains, -+ .num_supplies = ARRAY_SIZE(default_supplies) - 1, -+ .supply_names = default_supplies, -+ .num_pm_domains = 2, -+ .pm_domain_names = mediatek_pm_domains, - .pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF), - }; - --/* MT8188 uses the same power domains and power supplies as MT8183 */ - static const struct panfrost_compatible mediatek_mt8188_data = { -- .num_supplies = ARRAY_SIZE(mediatek_mt8183_b_supplies) - 1, -- .supply_names = mediatek_mt8183_b_supplies, -- .num_pm_domains = ARRAY_SIZE(mediatek_mt8183_pm_domains), -- .pm_domain_names = mediatek_mt8183_pm_domains, -+ .num_supplies = ARRAY_SIZE(default_supplies) - 1, -+ .supply_names = default_supplies, -+ .num_pm_domains = 3, -+ .pm_domain_names = mediatek_pm_domains, - .pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF), - .gpu_quirks = BIT(GPU_QUIRK_FORCE_AARCH64_PGTABLE), - }; - --static const char * const mediatek_mt8192_supplies[] = { "mali", NULL }; --static const char * const mediatek_mt8192_pm_domains[] = { "core0", "core1", "core2", -- "core3", "core4" }; - static const struct panfrost_compatible mediatek_mt8192_data = { -- .num_supplies = ARRAY_SIZE(mediatek_mt8192_supplies) - 1, -- .supply_names = mediatek_mt8192_supplies, -- .num_pm_domains = ARRAY_SIZE(mediatek_mt8192_pm_domains), -- .pm_domain_names = mediatek_mt8192_pm_domains, -+ .num_supplies = ARRAY_SIZE(default_supplies) - 1, -+ .supply_names = default_supplies, -+ .num_pm_domains = 5, -+ .pm_domain_names = mediatek_pm_domains, -+ .pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF), -+ .gpu_quirks = BIT(GPU_QUIRK_FORCE_AARCH64_PGTABLE), -+}; -+ -+static const struct panfrost_compatible mediatek_mt8370_data = { -+ .num_supplies = ARRAY_SIZE(default_supplies) - 1, -+ .supply_names = default_supplies, -+ .num_pm_domains = 2, -+ .pm_domain_names = mediatek_pm_domains, - .pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF), - .gpu_quirks = BIT(GPU_QUIRK_FORCE_AARCH64_PGTABLE), - }; -@@ -868,6 +872,7 @@ static const struct of_device_id dt_matc - { .compatible = "mediatek,mt8186-mali", .data = &mediatek_mt8186_data }, - { .compatible = "mediatek,mt8188-mali", .data = &mediatek_mt8188_data }, - { .compatible = "mediatek,mt8192-mali", .data = &mediatek_mt8192_data }, -+ { .compatible = "mediatek,mt8370-mali", .data = &mediatek_mt8370_data }, - { .compatible = "allwinner,sun50i-h616-mali", .data = &allwinner_h616_data }, - {} - }; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/panfrost/panfrost_job.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/panfrost/panfrost_job.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/panfrost/panfrost_job.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/panfrost/panfrost_job.c 2025-10-22 13:53:56.475169334 -0400 -@@ -841,7 +841,6 @@ int panfrost_job_init(struct panfrost_de - .num_rqs = DRM_SCHED_PRIORITY_COUNT, - .credit_limit = 2, - .timeout = msecs_to_jiffies(JOB_TIMEOUT_MS), -- .timeout_wq = pfdev->reset.wq, - .name = "pan_js", - .dev = pfdev->dev, - }; -@@ -879,6 +878,7 @@ int panfrost_job_init(struct panfrost_de - pfdev->reset.wq = alloc_ordered_workqueue("panfrost-reset", 0); - if (!pfdev->reset.wq) - return -ENOMEM; -+ args.timeout_wq = pfdev->reset.wq; - - for (j = 0; j < NUM_JOB_SLOTS; j++) { - js->queue[j].fence_context = dma_fence_context_alloc(1); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/panthor/panthor_drv.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/panthor/panthor_drv.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/panthor/panthor_drv.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/panthor/panthor_drv.c 2025-10-22 13:53:56.475169334 -0400 -@@ -1093,7 +1093,7 @@ static int panthor_ioctl_group_create(st - struct drm_panthor_queue_create *queue_args; - int ret; - -- if (!args->queues.count) -+ if (!args->queues.count || args->queues.count > MAX_CS_PER_CSG) - return -EINVAL; - - ret = PANTHOR_UOBJ_GET_ARRAY(queue_args, &args->queues); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/panthor/panthor_gem.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/panthor/panthor_gem.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/panthor/panthor_gem.c 2025-10-22 13:53:23.235329030 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/panthor/panthor_gem.c 2025-10-22 13:53:56.475169334 -0400 -@@ -16,10 +16,15 @@ - #include "panthor_mmu.h" - - #ifdef CONFIG_DEBUG_FS --static void panthor_gem_debugfs_bo_add(struct panthor_device *ptdev, -- struct panthor_gem_object *bo) -+static void panthor_gem_debugfs_bo_init(struct panthor_gem_object *bo) - { - INIT_LIST_HEAD(&bo->debugfs.node); -+} -+ -+static void panthor_gem_debugfs_bo_add(struct panthor_gem_object *bo) -+{ -+ struct panthor_device *ptdev = container_of(bo->base.base.dev, -+ struct panthor_device, base); - - bo->debugfs.creator.tgid = current->group_leader->pid; - get_task_comm(bo->debugfs.creator.process_name, current->group_leader); -@@ -44,14 +49,13 @@ static void panthor_gem_debugfs_bo_rm(st - - static void panthor_gem_debugfs_set_usage_flags(struct panthor_gem_object *bo, u32 usage_flags) - { -- bo->debugfs.flags = usage_flags | PANTHOR_DEBUGFS_GEM_USAGE_FLAG_INITIALIZED; -+ bo->debugfs.flags = usage_flags; -+ panthor_gem_debugfs_bo_add(bo); - } - #else --static void panthor_gem_debugfs_bo_add(struct panthor_device *ptdev, -- struct panthor_gem_object *bo) --{} - static void panthor_gem_debugfs_bo_rm(struct panthor_gem_object *bo) {} - static void panthor_gem_debugfs_set_usage_flags(struct panthor_gem_object *bo, u32 usage_flags) {} -+static void panthor_gem_debugfs_bo_init(struct panthor_gem_object *bo) {} - #endif - - static void panthor_gem_free_object(struct drm_gem_object *obj) -@@ -246,7 +250,7 @@ struct drm_gem_object *panthor_gem_creat - drm_gem_gpuva_set_lock(&obj->base.base, &obj->gpuva_list_lock); - mutex_init(&obj->label.lock); - -- panthor_gem_debugfs_bo_add(ptdev, obj); -+ panthor_gem_debugfs_bo_init(obj); - - return &obj->base.base; - } -@@ -285,6 +289,8 @@ panthor_gem_create_with_handle(struct dr - bo->base.base.resv = bo->exclusive_vm_root_gem->resv; - } - -+ panthor_gem_debugfs_set_usage_flags(bo, 0); -+ - /* - * Allocate an id of idr table where the obj is registered - * and handle has the id what user can see. -@@ -296,12 +302,6 @@ panthor_gem_create_with_handle(struct dr - /* drop reference from allocate - handle holds it now. */ - drm_gem_object_put(&shmem->base); - -- /* -- * No explicit flags are needed in the call below, since the -- * function internally sets the INITIALIZED bit for us. -- */ -- panthor_gem_debugfs_set_usage_flags(bo, 0); -- - return ret; - } - -@@ -387,7 +387,7 @@ static void panthor_gem_debugfs_bo_print - unsigned int refcount = kref_read(&bo->base.base.refcount); - char creator_info[32] = {}; - size_t resident_size; -- u32 gem_usage_flags = bo->debugfs.flags & (u32)~PANTHOR_DEBUGFS_GEM_USAGE_FLAG_INITIALIZED; -+ u32 gem_usage_flags = bo->debugfs.flags; - u32 gem_state_flags = 0; - - /* Skip BOs being destroyed. */ -@@ -436,8 +436,7 @@ void panthor_gem_debugfs_print_bos(struc - - scoped_guard(mutex, &ptdev->gems.lock) { - list_for_each_entry(bo, &ptdev->gems.node, debugfs.node) { -- if (bo->debugfs.flags & PANTHOR_DEBUGFS_GEM_USAGE_FLAG_INITIALIZED) -- panthor_gem_debugfs_bo_print(bo, m, &totals); -+ panthor_gem_debugfs_bo_print(bo, m, &totals); - } - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/panthor/panthor_gem.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/panthor/panthor_gem.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/panthor/panthor_gem.h 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/panthor/panthor_gem.h 2025-10-22 13:53:56.475169334 -0400 -@@ -35,9 +35,6 @@ enum panthor_debugfs_gem_usage_flags { - - /** @PANTHOR_DEBUGFS_GEM_USAGE_FLAG_FW_MAPPED: BO is mapped on the FW VM. */ - PANTHOR_DEBUGFS_GEM_USAGE_FLAG_FW_MAPPED = BIT(PANTHOR_DEBUGFS_GEM_USAGE_FW_MAPPED_BIT), -- -- /** @PANTHOR_DEBUGFS_GEM_USAGE_FLAG_INITIALIZED: BO is ready for DebugFS display. */ -- PANTHOR_DEBUGFS_GEM_USAGE_FLAG_INITIALIZED = BIT(31), - }; - - /** -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/panthor/panthor_sched.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/panthor/panthor_sched.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/panthor/panthor_sched.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/panthor/panthor_sched.c 2025-10-22 13:53:56.475169334 -0400 -@@ -886,8 +886,7 @@ static void group_free_queue(struct pant - if (IS_ERR_OR_NULL(queue)) - return; - -- if (queue->entity.fence_context) -- drm_sched_entity_destroy(&queue->entity); -+ drm_sched_entity_destroy(&queue->entity); - - if (queue->scheduler.ops) - drm_sched_fini(&queue->scheduler); -@@ -3558,11 +3557,6 @@ int panthor_group_destroy(struct panthor - if (!group) - return -EINVAL; - -- for (u32 i = 0; i < group->queue_count; i++) { -- if (group->queues[i]) -- drm_sched_entity_destroy(&group->queues[i]->entity); -- } -- - mutex_lock(&sched->reset.lock); - mutex_lock(&sched->lock); - group->destroyed = true; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/radeon/radeon_device.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/radeon/radeon_device.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/radeon/radeon_device.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/radeon/radeon_device.c 2025-10-22 13:53:56.479169315 -0400 -@@ -26,7 +26,6 @@ - * Jerome Glisse - */ - --#include - #include - #include - #include -@@ -1635,11 +1634,9 @@ int radeon_suspend_kms(struct drm_device - pci_set_power_state(pdev, PCI_D3hot); - } - -- if (notify_clients) { -- console_lock(); -- drm_client_dev_suspend(dev, true); -- console_unlock(); -- } -+ if (notify_clients) -+ drm_client_dev_suspend(dev, false); -+ - return 0; - } - -@@ -1661,17 +1658,11 @@ int radeon_resume_kms(struct drm_device - if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) - return 0; - -- if (notify_clients) { -- console_lock(); -- } - if (resume) { - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); -- if (pci_enable_device(pdev)) { -- if (notify_clients) -- console_unlock(); -+ if (pci_enable_device(pdev)) - return -1; -- } - } - /* resume AGP if in use */ - radeon_agp_resume(rdev); -@@ -1747,10 +1738,8 @@ int radeon_resume_kms(struct drm_device - if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) - radeon_pm_compute_clocks(rdev); - -- if (notify_clients) { -- drm_client_dev_resume(dev, true); -- console_unlock(); -- } -+ if (notify_clients) -+ drm_client_dev_resume(dev, false); - - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c 2025-10-22 13:53:56.479169315 -0400 -@@ -585,6 +585,9 @@ rzg2l_mipi_dsi_bridge_mode_valid(struct - if (mode->clock > 148500) - return MODE_CLOCK_HIGH; - -+ if (mode->clock < 5803) -+ return MODE_CLOCK_LOW; -+ - return MODE_OK; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/rockchip/rockchip_drm_fb.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/rockchip/rockchip_drm_fb.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/rockchip/rockchip_drm_fb.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/rockchip/rockchip_drm_fb.c 2025-10-22 13:53:56.479169315 -0400 -@@ -52,16 +52,9 @@ rockchip_fb_create(struct drm_device *de - } - - if (drm_is_afbc(mode_cmd->modifier[0])) { -- int ret, i; -- - ret = drm_gem_fb_afbc_init(dev, mode_cmd, afbc_fb); - if (ret) { -- struct drm_gem_object **obj = afbc_fb->base.obj; -- -- for (i = 0; i < info->num_planes; ++i) -- drm_gem_object_put(obj[i]); -- -- kfree(afbc_fb); -+ drm_framebuffer_put(&afbc_fb->base); - return ERR_PTR(ret); - } - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c 2025-10-22 13:53:56.479169315 -0400 -@@ -146,25 +146,6 @@ static void vop2_unlock(struct vop2 *vop - mutex_unlock(&vop2->vop2_lock); - } - --/* -- * Note: -- * The write mask function is documented but missing on rk3566/8, writes -- * to these bits have no effect. For newer soc(rk3588 and following) the -- * write mask is needed for register writes. -- * -- * GLB_CFG_DONE_EN has no write mask bit. -- * -- */ --static void vop2_cfg_done(struct vop2_video_port *vp) --{ -- struct vop2 *vop2 = vp->vop2; -- u32 val = RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN; -- -- val |= BIT(vp->id) | (BIT(vp->id) << 16); -- -- regmap_set_bits(vop2->map, RK3568_REG_CFG_DONE, val); --} -- - static void vop2_win_disable(struct vop2_win *win) - { - vop2_win_write(win, VOP2_WIN_ENABLE, 0); -@@ -854,6 +835,11 @@ static void vop2_enable(struct vop2 *vop - if (vop2->version == VOP_VERSION_RK3588) - rk3588_vop2_power_domain_enable_all(vop2); - -+ if (vop2->version <= VOP_VERSION_RK3588) { -+ vop2->old_layer_sel = vop2_readl(vop2, RK3568_OVL_LAYER_SEL); -+ vop2->old_port_sel = vop2_readl(vop2, RK3568_OVL_PORT_SEL); -+ } -+ - vop2_writel(vop2, RK3568_REG_CFG_DONE, RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN); - - /* -@@ -2422,6 +2408,10 @@ static int vop2_create_crtcs(struct vop2 - break; - } - } -+ -+ if (!vp->primary_plane) -+ return dev_err_probe(drm->dev, -ENOENT, -+ "no primary plane for vp %d\n", i); - } - - /* Register all unused window as overlay plane */ -@@ -2589,12 +2579,13 @@ static int vop2_win_init(struct vop2 *vo - } - - /* -- * The window registers are only updated when config done is written. -- * Until that they read back the old value. As we read-modify-write -- * these registers mark them as non-volatile. This makes sure we read -- * the new values from the regmap register cache. -+ * The window and video port registers are only updated when config -+ * done is written. Until that they read back the old value. As we -+ * read-modify-write these registers mark them as non-volatile. This -+ * makes sure we read the new values from the regmap register cache. - */ - static const struct regmap_range vop2_nonvolatile_range[] = { -+ regmap_reg_range(RK3568_VP0_CTRL_BASE, RK3588_VP3_CTRL_BASE + 255), - regmap_reg_range(0x1000, 0x23ff), - }; - -@@ -2724,6 +2715,7 @@ static int vop2_bind(struct device *dev, - return dev_err_probe(drm->dev, vop2->irq, "cannot find irq for vop2\n"); - - mutex_init(&vop2->vop2_lock); -+ mutex_init(&vop2->ovl_lock); - - ret = devm_request_irq(dev, vop2->irq, vop2_isr, IRQF_SHARED, dev_name(dev), vop2); - if (ret) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h 2025-10-22 13:53:56.479169315 -0400 -@@ -334,6 +334,19 @@ struct vop2 { - /* optional internal rgb encoder */ - struct rockchip_rgb *rgb; - -+ /* -+ * Used to record layer selection configuration on rk356x/rk3588 -+ * as register RK3568_OVL_LAYER_SEL and RK3568_OVL_PORT_SEL are -+ * shared for all the Video Ports. -+ */ -+ u32 old_layer_sel; -+ u32 old_port_sel; -+ /* -+ * Ensure that the updates to these two registers(RKK3568_OVL_LAYER_SEL/RK3568_OVL_PORT_SEL) -+ * take effect in sequence. -+ */ -+ struct mutex ovl_lock; -+ - /* must be put at the end of the struct */ - struct vop2_win win[]; - }; -@@ -727,6 +740,7 @@ enum dst_factor_mode { - #define RK3588_OVL_PORT_SEL__CLUSTER2 GENMASK(21, 20) - #define RK3568_OVL_PORT_SEL__CLUSTER1 GENMASK(19, 18) - #define RK3568_OVL_PORT_SEL__CLUSTER0 GENMASK(17, 16) -+#define RK3588_OVL_PORT_SET__PORT3_MUX GENMASK(15, 12) - #define RK3568_OVL_PORT_SET__PORT2_MUX GENMASK(11, 8) - #define RK3568_OVL_PORT_SET__PORT1_MUX GENMASK(7, 4) - #define RK3568_OVL_PORT_SET__PORT0_MUX GENMASK(3, 0) -@@ -831,4 +845,23 @@ static inline struct vop2_win *to_vop2_w - return container_of(p, struct vop2_win, base); - } - -+/* -+ * Note: -+ * The write mask function is documented but missing on rk3566/8, writes -+ * to these bits have no effect. For newer soc(rk3588 and following) the -+ * write mask is needed for register writes. -+ * -+ * GLB_CFG_DONE_EN has no write mask bit. -+ * -+ */ -+static inline void vop2_cfg_done(struct vop2_video_port *vp) -+{ -+ struct vop2 *vop2 = vp->vop2; -+ u32 val = RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN; -+ -+ val |= BIT(vp->id) | (BIT(vp->id) << 16); -+ -+ regmap_set_bits(vop2->map, RK3568_REG_CFG_DONE, val); -+} -+ - #endif /* _ROCKCHIP_DRM_VOP2_H */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c 2025-10-22 13:53:56.479169315 -0400 -@@ -2052,12 +2052,55 @@ static void vop2_setup_alpha(struct vop2 - } - } - -+static u32 rk3568_vop2_read_port_mux(struct vop2 *vop2) -+{ -+ return vop2_readl(vop2, RK3568_OVL_PORT_SEL); -+} -+ -+static void rk3568_vop2_wait_for_port_mux_done(struct vop2 *vop2) -+{ -+ u32 port_mux_sel; -+ int ret; -+ -+ /* -+ * Spin until the previous port_mux figuration is done. -+ */ -+ ret = readx_poll_timeout_atomic(rk3568_vop2_read_port_mux, vop2, port_mux_sel, -+ port_mux_sel == vop2->old_port_sel, 0, 50 * 1000); -+ if (ret) -+ DRM_DEV_ERROR(vop2->dev, "wait port_mux done timeout: 0x%x--0x%x\n", -+ port_mux_sel, vop2->old_port_sel); -+} -+ -+static u32 rk3568_vop2_read_layer_cfg(struct vop2 *vop2) -+{ -+ return vop2_readl(vop2, RK3568_OVL_LAYER_SEL); -+} -+ -+static void rk3568_vop2_wait_for_layer_cfg_done(struct vop2 *vop2, u32 cfg) -+{ -+ u32 atv_layer_cfg; -+ int ret; -+ -+ /* -+ * Spin until the previous layer configuration is done. -+ */ -+ ret = readx_poll_timeout_atomic(rk3568_vop2_read_layer_cfg, vop2, atv_layer_cfg, -+ atv_layer_cfg == cfg, 0, 50 * 1000); -+ if (ret) -+ DRM_DEV_ERROR(vop2->dev, "wait layer cfg done timeout: 0x%x--0x%x\n", -+ atv_layer_cfg, cfg); -+} -+ - static void rk3568_vop2_setup_layer_mixer(struct vop2_video_port *vp) - { - struct vop2 *vop2 = vp->vop2; - struct drm_plane *plane; - u32 layer_sel = 0; - u32 port_sel; -+ u32 old_layer_sel = 0; -+ u32 atv_layer_sel = 0; -+ u32 old_port_sel = 0; - u8 layer_id; - u8 old_layer_id; - u8 layer_sel_id; -@@ -2069,19 +2112,18 @@ static void rk3568_vop2_setup_layer_mixe - struct vop2_video_port *vp2 = &vop2->vps[2]; - struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(vp->crtc.state); - -+ mutex_lock(&vop2->ovl_lock); - ovl_ctrl = vop2_readl(vop2, RK3568_OVL_CTRL); - ovl_ctrl &= ~RK3568_OVL_CTRL__LAYERSEL_REGDONE_IMD; - ovl_ctrl &= ~RK3568_OVL_CTRL__LAYERSEL_REGDONE_SEL; -- ovl_ctrl |= FIELD_PREP(RK3568_OVL_CTRL__LAYERSEL_REGDONE_SEL, vp->id); - - if (vcstate->yuv_overlay) - ovl_ctrl |= RK3568_OVL_CTRL__YUV_MODE(vp->id); - else - ovl_ctrl &= ~RK3568_OVL_CTRL__YUV_MODE(vp->id); - -- vop2_writel(vop2, RK3568_OVL_CTRL, ovl_ctrl); -- -- port_sel = vop2_readl(vop2, RK3568_OVL_PORT_SEL); -+ old_port_sel = vop2->old_port_sel; -+ port_sel = old_port_sel; - port_sel &= RK3568_OVL_PORT_SEL__SEL_PORT; - - if (vp0->nlayers) -@@ -2102,7 +2144,13 @@ static void rk3568_vop2_setup_layer_mixe - else - port_sel |= FIELD_PREP(RK3568_OVL_PORT_SET__PORT2_MUX, 8); - -- layer_sel = vop2_readl(vop2, RK3568_OVL_LAYER_SEL); -+ /* Fixed value for rk3588 */ -+ if (vop2->version == VOP_VERSION_RK3588) -+ port_sel |= FIELD_PREP(RK3588_OVL_PORT_SET__PORT3_MUX, 7); -+ -+ atv_layer_sel = vop2_readl(vop2, RK3568_OVL_LAYER_SEL); -+ old_layer_sel = vop2->old_layer_sel; -+ layer_sel = old_layer_sel; - - ofs = 0; - for (i = 0; i < vp->id; i++) -@@ -2186,8 +2234,37 @@ static void rk3568_vop2_setup_layer_mixe - old_win->data->layer_sel_id[vp->id]); - } - -+ vop2->old_layer_sel = layer_sel; -+ vop2->old_port_sel = port_sel; -+ /* -+ * As the RK3568_OVL_LAYER_SEL and RK3568_OVL_PORT_SEL are shared by all Video Ports, -+ * and the configuration take effect by one Video Port's vsync. -+ * When performing layer migration or change the zpos of layers, there are two things -+ * to be observed and followed: -+ * 1. When a layer is migrated from one VP to another, the configuration of the layer -+ * can only take effect after the Port mux configuration is enabled. -+ * -+ * 2. When we change the zpos of layers, we must ensure that the change for the previous -+ * VP takes effect before we proceed to change the next VP. Otherwise, the new -+ * configuration might overwrite the previous one for the previous VP, or it could -+ * lead to the configuration of the previous VP being take effect along with the VSYNC -+ * of the new VP. -+ */ -+ if (layer_sel != old_layer_sel || port_sel != old_port_sel) -+ ovl_ctrl |= FIELD_PREP(RK3568_OVL_CTRL__LAYERSEL_REGDONE_SEL, vp->id); -+ vop2_writel(vop2, RK3568_OVL_CTRL, ovl_ctrl); -+ -+ if (port_sel != old_port_sel) { -+ vop2_writel(vop2, RK3568_OVL_PORT_SEL, port_sel); -+ vop2_cfg_done(vp); -+ rk3568_vop2_wait_for_port_mux_done(vop2); -+ } -+ -+ if (layer_sel != old_layer_sel && atv_layer_sel != old_layer_sel) -+ rk3568_vop2_wait_for_layer_cfg_done(vop2, vop2->old_layer_sel); -+ - vop2_writel(vop2, RK3568_OVL_LAYER_SEL, layer_sel); -- vop2_writel(vop2, RK3568_OVL_PORT_SEL, port_sel); -+ mutex_unlock(&vop2->ovl_lock); - } - - static void rk3568_vop2_setup_dly_for_windows(struct vop2_video_port *vp) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/scheduler/sched_entity.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/scheduler/sched_entity.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/scheduler/sched_entity.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/scheduler/sched_entity.c 2025-10-22 13:53:56.479169315 -0400 -@@ -355,17 +355,6 @@ void drm_sched_entity_destroy(struct drm - } - EXPORT_SYMBOL(drm_sched_entity_destroy); - --/* drm_sched_entity_clear_dep - callback to clear the entities dependency */ --static void drm_sched_entity_clear_dep(struct dma_fence *f, -- struct dma_fence_cb *cb) --{ -- struct drm_sched_entity *entity = -- container_of(cb, struct drm_sched_entity, cb); -- -- entity->dependency = NULL; -- dma_fence_put(f); --} -- - /* - * drm_sched_entity_wakeup - callback to clear the entity's dependency and - * wake up the scheduler -@@ -376,7 +365,8 @@ static void drm_sched_entity_wakeup(stru - struct drm_sched_entity *entity = - container_of(cb, struct drm_sched_entity, cb); - -- drm_sched_entity_clear_dep(f, cb); -+ entity->dependency = NULL; -+ dma_fence_put(f); - drm_sched_wakeup(entity->rq->sched); - } - -@@ -429,13 +419,6 @@ static bool drm_sched_entity_add_depende - fence = dma_fence_get(&s_fence->scheduled); - dma_fence_put(entity->dependency); - entity->dependency = fence; -- if (!dma_fence_add_callback(fence, &entity->cb, -- drm_sched_entity_clear_dep)) -- return true; -- -- /* Ignore it when it is already scheduled */ -- dma_fence_put(fence); -- return false; - } - - if (!dma_fence_add_callback(entity->dependency, &entity->cb, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/scheduler/sched_main.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/scheduler/sched_main.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/scheduler/sched_main.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/scheduler/sched_main.c 2025-10-22 13:53:56.479169315 -0400 -@@ -1348,6 +1348,18 @@ Out_check_own: - } - EXPORT_SYMBOL(drm_sched_init); - -+static void drm_sched_cancel_remaining_jobs(struct drm_gpu_scheduler *sched) -+{ -+ struct drm_sched_job *job, *tmp; -+ -+ /* All other accessors are stopped. No locking necessary. */ -+ list_for_each_entry_safe_reverse(job, tmp, &sched->pending_list, list) { -+ sched->ops->cancel_job(job); -+ list_del(&job->list); -+ sched->ops->free_job(job); -+ } -+} -+ - /** - * drm_sched_fini - Destroy a gpu scheduler - * -@@ -1355,19 +1367,11 @@ EXPORT_SYMBOL(drm_sched_init); - * - * Tears down and cleans up the scheduler. - * -- * This stops submission of new jobs to the hardware through -- * drm_sched_backend_ops.run_job(). Consequently, drm_sched_backend_ops.free_job() -- * will not be called for all jobs still in drm_gpu_scheduler.pending_list. -- * There is no solution for this currently. Thus, it is up to the driver to make -- * sure that: -- * -- * a) drm_sched_fini() is only called after for all submitted jobs -- * drm_sched_backend_ops.free_job() has been called or that -- * b) the jobs for which drm_sched_backend_ops.free_job() has not been called -- * after drm_sched_fini() ran are freed manually. -- * -- * FIXME: Take care of the above problem and prevent this function from leaking -- * the jobs in drm_gpu_scheduler.pending_list under any circumstances. -+ * This stops submission of new jobs to the hardware through &struct -+ * drm_sched_backend_ops.run_job. If &struct drm_sched_backend_ops.cancel_job -+ * is implemented, all jobs will be canceled through it and afterwards cleaned -+ * up through &struct drm_sched_backend_ops.free_job. If cancel_job is not -+ * implemented, memory could leak. - */ - void drm_sched_fini(struct drm_gpu_scheduler *sched) - { -@@ -1397,6 +1401,10 @@ void drm_sched_fini(struct drm_gpu_sched - /* Confirm no work left behind accessing device structures */ - cancel_delayed_work_sync(&sched->work_tdr); - -+ /* Avoid memory leaks if supported by the driver. */ -+ if (sched->ops->cancel_job) -+ drm_sched_cancel_remaining_jobs(sched); -+ - if (sched->own_submit_wq) - destroy_workqueue(sched->submit_wq); - sched->ready = false; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/scheduler/tests/tests_basic.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/scheduler/tests/tests_basic.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/scheduler/tests/tests_basic.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/scheduler/tests/tests_basic.c 2025-10-22 13:53:56.479169315 -0400 -@@ -204,6 +204,47 @@ static struct kunit_suite drm_sched_basi - .test_cases = drm_sched_basic_tests, - }; - -+static void drm_sched_basic_cancel(struct kunit *test) -+{ -+ struct drm_mock_sched_entity *entity; -+ struct drm_mock_scheduler *sched; -+ struct drm_mock_sched_job *job; -+ bool done; -+ -+ /* -+ * Check that drm_sched_fini() uses the cancel_job() callback to cancel -+ * jobs that are still pending. -+ */ -+ -+ sched = drm_mock_sched_new(test, MAX_SCHEDULE_TIMEOUT); -+ entity = drm_mock_sched_entity_new(test, DRM_SCHED_PRIORITY_NORMAL, -+ sched); -+ -+ job = drm_mock_sched_job_new(test, entity); -+ -+ drm_mock_sched_job_submit(job); -+ -+ done = drm_mock_sched_job_wait_scheduled(job, HZ); -+ KUNIT_ASSERT_TRUE(test, done); -+ -+ drm_mock_sched_entity_free(entity); -+ drm_mock_sched_fini(sched); -+ -+ KUNIT_ASSERT_EQ(test, job->hw_fence.error, -ECANCELED); -+} -+ -+static struct kunit_case drm_sched_cancel_tests[] = { -+ KUNIT_CASE(drm_sched_basic_cancel), -+ {} -+}; -+ -+static struct kunit_suite drm_sched_cancel = { -+ .name = "drm_sched_basic_cancel_tests", -+ .init = drm_sched_basic_init, -+ .exit = drm_sched_basic_exit, -+ .test_cases = drm_sched_cancel_tests, -+}; -+ - static void drm_sched_basic_timeout(struct kunit *test) - { - struct drm_mock_scheduler *sched = test->priv; -@@ -471,6 +512,7 @@ static struct kunit_suite drm_sched_cred - - kunit_test_suites(&drm_sched_basic, - &drm_sched_timeout, -+ &drm_sched_cancel, - &drm_sched_priority, - &drm_sched_modify_sched, - &drm_sched_credits); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/sitronix/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/sitronix/Kconfig ---- BPI-Router-Linux-kernel/drivers/gpu/drm/sitronix/Kconfig 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/sitronix/Kconfig 2025-10-22 13:53:56.479169315 -0400 -@@ -5,15 +5,12 @@ config DRM_ST7571_I2C - select DRM_GEM_SHMEM_HELPER - select DRM_KMS_HELPER - select REGMAP_I2C -+ select VIDEOMODE_HELPERS - help - DRM driver for Sitronix ST7571 panels controlled over I2C. - - if M is selected the module will be called st7571-i2c. - --config TINYDRM_ST7586 -- tristate -- default n -- - config DRM_ST7586 - tristate "DRM support for Sitronix ST7586 display panels" - depends on DRM && SPI -@@ -21,17 +18,12 @@ config DRM_ST7586 - select DRM_KMS_HELPER - select DRM_GEM_DMA_HELPER - select DRM_MIPI_DBI -- default TINYDRM_ST7586 - help - DRM driver for the following Sitronix ST7586 panels: - * LEGO MINDSTORMS EV3 - - If M is selected the module will be called st7586. - --config TINYDRM_ST7735R -- tristate -- default n -- - config DRM_ST7735R - tristate "DRM support for Sitronix ST7715R/ST7735R display panels" - depends on DRM && SPI -@@ -40,7 +32,6 @@ config DRM_ST7735R - select DRM_GEM_DMA_HELPER - select DRM_MIPI_DBI - select BACKLIGHT_CLASS_DEVICE -- default TINYDRM_ST7735R - help - DRM driver for Sitronix ST7715R/ST7735R with one of the following - LCDs: -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/solomon/ssd130x.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/solomon/ssd130x.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/solomon/ssd130x.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/solomon/ssd130x.c 2025-10-22 13:53:56.479169315 -0400 -@@ -974,7 +974,7 @@ static void ssd130x_clear_screen(struct - - static void ssd132x_clear_screen(struct ssd130x_device *ssd130x, u8 *data_array) - { -- unsigned int columns = DIV_ROUND_UP(ssd130x->height, SSD132X_SEGMENT_WIDTH); -+ unsigned int columns = DIV_ROUND_UP(ssd130x->width, SSD132X_SEGMENT_WIDTH); - unsigned int height = ssd130x->height; - - memset(data_array, 0, columns * height); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/sysfb/vesadrm.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/sysfb/vesadrm.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/sysfb/vesadrm.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/sysfb/vesadrm.c 2025-10-22 13:53:56.479169315 -0400 -@@ -362,14 +362,19 @@ static struct vesadrm_device *vesadrm_de - - if (!__screen_info_vbe_mode_nonvga(si)) { - vesa->cmap_write = vesadrm_vga_cmap_write; --#if defined(CONFIG_X86_32) - } else { -+#if defined(CONFIG_X86_32) - phys_addr_t pmi_base = __screen_info_vesapm_info_base(si); -- const u16 *pmi_addr = phys_to_virt(pmi_base); - -- vesa->pmi.PrimaryPalette = (u8 *)pmi_addr + pmi_addr[2]; -- vesa->cmap_write = vesadrm_pmi_cmap_write; -+ if (pmi_base) { -+ const u16 *pmi_addr = phys_to_virt(pmi_base); -+ -+ vesa->pmi.PrimaryPalette = (u8 *)pmi_addr + pmi_addr[2]; -+ vesa->cmap_write = vesadrm_pmi_cmap_write; -+ } else - #endif -+ if (format->is_color_indexed) -+ drm_warn(dev, "hardware palette is unchangeable, colors may be incorrect\n"); - } - - #ifdef CONFIG_X86 -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/tegra/nvdec.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/tegra/nvdec.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/tegra/nvdec.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/tegra/nvdec.c 2025-10-22 13:53:56.479169315 -0400 -@@ -261,10 +261,8 @@ static int nvdec_load_falcon_firmware(st - - if (!client->group) { - virt = dma_alloc_coherent(nvdec->dev, size, &iova, GFP_KERNEL); -- -- err = dma_mapping_error(nvdec->dev, iova); -- if (err < 0) -- return err; -+ if (!virt) -+ return -ENOMEM; - } else { - virt = tegra_drm_alloc(tegra, size, &iova); - if (IS_ERR(virt)) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/tests/drm_format_helper_test.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/tests/drm_format_helper_test.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/tests/drm_format_helper_test.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/tests/drm_format_helper_test.c 2025-10-22 13:53:56.479169315 -0400 -@@ -748,14 +748,9 @@ static void drm_test_fb_xrgb8888_to_rgb5 - buf = dst.vaddr; - memset(buf, 0, dst_size); - -- int blit_result = 0; -- -- blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_RGB565, &src, &fb, ¶ms->clip, -- &fmtcnv_state); -- -+ drm_fb_xrgb8888_to_rgb565(&dst, dst_pitch, &src, &fb, ¶ms->clip, -+ &fmtcnv_state, false); - buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); -- -- KUNIT_EXPECT_FALSE(test, blit_result); - KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); - } - -@@ -795,14 +790,8 @@ static void drm_test_fb_xrgb8888_to_xrgb - buf = dst.vaddr; /* restore original value of buf */ - memset(buf, 0, dst_size); - -- int blit_result = 0; -- -- blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_XRGB1555, &src, &fb, ¶ms->clip, -- &fmtcnv_state); -- -+ drm_fb_xrgb8888_to_xrgb1555(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); - buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); -- -- KUNIT_EXPECT_FALSE(test, blit_result); - KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); - } - -@@ -842,14 +831,8 @@ static void drm_test_fb_xrgb8888_to_argb - buf = dst.vaddr; /* restore original value of buf */ - memset(buf, 0, dst_size); - -- int blit_result = 0; -- -- blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_ARGB1555, &src, &fb, ¶ms->clip, -- &fmtcnv_state); -- -+ drm_fb_xrgb8888_to_argb1555(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); - buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); -- -- KUNIT_EXPECT_FALSE(test, blit_result); - KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); - } - -@@ -889,14 +872,8 @@ static void drm_test_fb_xrgb8888_to_rgba - buf = dst.vaddr; /* restore original value of buf */ - memset(buf, 0, dst_size); - -- int blit_result = 0; -- -- blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_RGBA5551, &src, &fb, ¶ms->clip, -- &fmtcnv_state); -- -+ drm_fb_xrgb8888_to_rgba5551(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); - buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); -- -- KUNIT_EXPECT_FALSE(test, blit_result); - KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); - } - -@@ -939,12 +916,7 @@ static void drm_test_fb_xrgb8888_to_rgb8 - buf = dst.vaddr; /* restore original value of buf */ - memset(buf, 0, dst_size); - -- int blit_result = 0; -- -- blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_RGB888, &src, &fb, ¶ms->clip, -- &fmtcnv_state); -- -- KUNIT_EXPECT_FALSE(test, blit_result); -+ drm_fb_xrgb8888_to_rgb888(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); - KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); - } - -@@ -985,12 +957,8 @@ static void drm_test_fb_xrgb8888_to_bgr8 - buf = dst.vaddr; /* restore original value of buf */ - memset(buf, 0, dst_size); - -- int blit_result = 0; -- -- blit_result = drm_fb_blit(&dst, &result->dst_pitch, DRM_FORMAT_BGR888, &src, &fb, ¶ms->clip, -+ drm_fb_xrgb8888_to_bgr888(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip, - &fmtcnv_state); -- -- KUNIT_EXPECT_FALSE(test, blit_result); - KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); - } - -@@ -1030,14 +998,8 @@ static void drm_test_fb_xrgb8888_to_argb - buf = dst.vaddr; /* restore original value of buf */ - memset(buf, 0, dst_size); - -- int blit_result = 0; -- -- blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_ARGB8888, &src, &fb, ¶ms->clip, -- &fmtcnv_state); -- -+ drm_fb_xrgb8888_to_argb8888(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); - buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); -- -- KUNIT_EXPECT_FALSE(test, blit_result); - KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); - } - -@@ -1071,18 +1033,14 @@ static void drm_test_fb_xrgb8888_to_xrgb - NULL : &result->dst_pitch; - - drm_fb_xrgb8888_to_xrgb2101010(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); -- buf = le32buf_to_cpu(test, buf, dst_size / sizeof(u32)); -+ buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); - KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); - - buf = dst.vaddr; /* restore original value of buf */ - memset(buf, 0, dst_size); - -- int blit_result = 0; -- -- blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_XRGB2101010, &src, &fb, -- ¶ms->clip, &fmtcnv_state); -- -- KUNIT_EXPECT_FALSE(test, blit_result); -+ drm_fb_xrgb8888_to_xrgb2101010(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); -+ buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); - KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); - } - -@@ -1122,14 +1080,8 @@ static void drm_test_fb_xrgb8888_to_argb - buf = dst.vaddr; /* restore original value of buf */ - memset(buf, 0, dst_size); - -- int blit_result = 0; -- -- blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_ARGB2101010, &src, &fb, -- ¶ms->clip, &fmtcnv_state); -- -+ drm_fb_xrgb8888_to_argb2101010(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); - buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); -- -- KUNIT_EXPECT_FALSE(test, blit_result); - KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); - } - -@@ -1202,23 +1154,15 @@ static void drm_test_fb_swab(struct kuni - buf = dst.vaddr; /* restore original value of buf */ - memset(buf, 0, dst_size); - -- int blit_result; -- -- blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_XRGB8888 | DRM_FORMAT_BIG_ENDIAN, -- &src, &fb, ¶ms->clip, &fmtcnv_state); -+ drm_fb_swab(&dst, dst_pitch, &src, &fb, ¶ms->clip, false, &fmtcnv_state); - buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); -- -- KUNIT_EXPECT_FALSE(test, blit_result); - KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); - - buf = dst.vaddr; - memset(buf, 0, dst_size); - -- blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_BGRX8888, &src, &fb, ¶ms->clip, -- &fmtcnv_state); -+ drm_fb_xrgb8888_to_bgrx8888(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); - buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); -- -- KUNIT_EXPECT_FALSE(test, blit_result); - KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); - - buf = dst.vaddr; -@@ -1229,11 +1173,8 @@ static void drm_test_fb_swab(struct kuni - mock_format.format |= DRM_FORMAT_BIG_ENDIAN; - fb.format = &mock_format; - -- blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_XRGB8888, &src, &fb, ¶ms->clip, -- &fmtcnv_state); -+ drm_fb_swab(&dst, dst_pitch, &src, &fb, ¶ms->clip, false, &fmtcnv_state); - buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); -- -- KUNIT_EXPECT_FALSE(test, blit_result); - KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); - } - -@@ -1266,14 +1207,8 @@ static void drm_test_fb_xrgb8888_to_abgr - const unsigned int *dst_pitch = (result->dst_pitch == TEST_USE_DEFAULT_PITCH) ? - NULL : &result->dst_pitch; - -- int blit_result = 0; -- -- blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_ABGR8888, &src, &fb, ¶ms->clip, -- &fmtcnv_state); -- -+ drm_fb_xrgb8888_to_abgr8888(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); - buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); -- -- KUNIT_EXPECT_FALSE(test, blit_result); - KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); - } - -@@ -1306,14 +1241,8 @@ static void drm_test_fb_xrgb8888_to_xbgr - const unsigned int *dst_pitch = (result->dst_pitch == TEST_USE_DEFAULT_PITCH) ? - NULL : &result->dst_pitch; - -- int blit_result = 0; -- -- blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_XBGR8888, &src, &fb, ¶ms->clip, -- &fmtcnv_state); -- -+ drm_fb_xrgb8888_to_xbgr8888(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); - buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); -- -- KUNIT_EXPECT_FALSE(test, blit_result); - KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); - } - -@@ -1910,12 +1839,8 @@ static void drm_test_fb_memcpy(struct ku - memset(buf[i], 0, dst_size[i]); - } - -- int blit_result; -- -- blit_result = drm_fb_blit(dst, dst_pitches, params->format, src, &fb, ¶ms->clip, -- &fmtcnv_state); -+ drm_fb_memcpy(dst, dst_pitches, src, &fb, ¶ms->clip); - -- KUNIT_EXPECT_FALSE(test, blit_result); - for (size_t i = 0; i < fb.format->num_planes; i++) { - expected[i] = cpubuf_to_le32(test, params->expected[i], TEST_BUF_SIZE); - KUNIT_EXPECT_MEMEQ_MSG(test, buf[i], expected[i], dst_size[i], -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/ttm/ttm_bo_util.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/ttm/ttm_bo_util.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/ttm/ttm_bo_util.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/ttm/ttm_bo_util.c 2025-10-22 13:53:56.479169315 -0400 -@@ -254,6 +254,13 @@ static int ttm_buffer_object_transfer(st - ret = dma_resv_trylock(&fbo->base.base._resv); - WARN_ON(!ret); - -+ ret = dma_resv_reserve_fences(&fbo->base.base._resv, 1); -+ if (ret) { -+ dma_resv_unlock(&fbo->base.base._resv); -+ kfree(fbo); -+ return ret; -+ } -+ - if (fbo->base.resource) { - ttm_resource_set_bo(fbo->base.resource, &fbo->base); - bo->resource = NULL; -@@ -262,12 +269,6 @@ static int ttm_buffer_object_transfer(st - fbo->base.bulk_move = NULL; - } - -- ret = dma_resv_reserve_fences(&fbo->base.base._resv, 1); -- if (ret) { -- kfree(fbo); -- return ret; -- } -- - ttm_bo_get(bo); - fbo->bo = bo; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/ttm/ttm_pool.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/ttm/ttm_pool.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/ttm/ttm_pool.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/ttm/ttm_pool.c 2025-10-22 13:53:56.479169315 -0400 -@@ -1132,7 +1132,6 @@ void ttm_pool_fini(struct ttm_pool *pool - } - EXPORT_SYMBOL(ttm_pool_fini); - --/* As long as pages are available make sure to release at least one */ - static unsigned long ttm_pool_shrinker_scan(struct shrinker *shrink, - struct shrink_control *sc) - { -@@ -1140,9 +1139,12 @@ static unsigned long ttm_pool_shrinker_s - - do - num_freed += ttm_pool_shrink(); -- while (!num_freed && atomic_long_read(&allocated_pages)); -+ while (num_freed < sc->nr_to_scan && -+ atomic_long_read(&allocated_pages)); - -- return num_freed; -+ sc->nr_scanned = num_freed; -+ -+ return num_freed ?: SHRINK_STOP; - } - - /* Return the number of pages available or SHRINK_EMPTY if we have none */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/ttm/ttm_resource.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/ttm/ttm_resource.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/ttm/ttm_resource.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/ttm/ttm_resource.c 2025-10-22 13:53:56.479169315 -0400 -@@ -557,6 +557,9 @@ int ttm_resource_manager_evict_all(struc - cond_resched(); - } while (!ret); - -+ if (ret && ret != -ENOENT) -+ return ret; -+ - spin_lock(&man->move_lock); - fence = dma_fence_get(man->move); - spin_unlock(&man->move_lock); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/v3d/v3d_drv.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/v3d/v3d_drv.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/v3d/v3d_drv.h 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/v3d/v3d_drv.h 2025-10-22 13:53:56.479169315 -0400 -@@ -101,6 +101,12 @@ enum v3d_gen { - V3D_GEN_71 = 71, - }; - -+enum v3d_irq { -+ V3D_CORE_IRQ, -+ V3D_HUB_IRQ, -+ V3D_MAX_IRQS, -+}; -+ - struct v3d_dev { - struct drm_device drm; - -@@ -112,6 +118,8 @@ struct v3d_dev { - - bool single_irq_line; - -+ int irq[V3D_MAX_IRQS]; -+ - struct v3d_perfmon_info perfmon_info; - - void __iomem *hub_regs; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/v3d/v3d_gem.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/v3d/v3d_gem.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/v3d/v3d_gem.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/v3d/v3d_gem.c 2025-10-22 13:53:56.479169315 -0400 -@@ -134,6 +134,8 @@ v3d_reset(struct v3d_dev *v3d) - if (false) - v3d_idle_axi(v3d, 0); - -+ v3d_irq_disable(v3d); -+ - v3d_idle_gca(v3d); - v3d_reset_sms(v3d); - v3d_reset_v3d(v3d); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/v3d/v3d_irq.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/v3d/v3d_irq.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/v3d/v3d_irq.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/v3d/v3d_irq.c 2025-10-22 13:53:56.479169315 -0400 -@@ -260,7 +260,7 @@ v3d_hub_irq(int irq, void *arg) - int - v3d_irq_init(struct v3d_dev *v3d) - { -- int irq1, ret, core; -+ int irq, ret, core; - - INIT_WORK(&v3d->overflow_mem_work, v3d_overflow_mem_work); - -@@ -271,17 +271,24 @@ v3d_irq_init(struct v3d_dev *v3d) - V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS(v3d->ver)); - V3D_WRITE(V3D_HUB_INT_CLR, V3D_HUB_IRQS(v3d->ver)); - -- irq1 = platform_get_irq_optional(v3d_to_pdev(v3d), 1); -- if (irq1 == -EPROBE_DEFER) -- return irq1; -- if (irq1 > 0) { -- ret = devm_request_irq(v3d->drm.dev, irq1, -+ irq = platform_get_irq_optional(v3d_to_pdev(v3d), 1); -+ if (irq == -EPROBE_DEFER) -+ return irq; -+ if (irq > 0) { -+ v3d->irq[V3D_CORE_IRQ] = irq; -+ -+ ret = devm_request_irq(v3d->drm.dev, v3d->irq[V3D_CORE_IRQ], - v3d_irq, IRQF_SHARED, - "v3d_core0", v3d); - if (ret) - goto fail; -- ret = devm_request_irq(v3d->drm.dev, -- platform_get_irq(v3d_to_pdev(v3d), 0), -+ -+ irq = platform_get_irq(v3d_to_pdev(v3d), 0); -+ if (irq < 0) -+ return irq; -+ v3d->irq[V3D_HUB_IRQ] = irq; -+ -+ ret = devm_request_irq(v3d->drm.dev, v3d->irq[V3D_HUB_IRQ], - v3d_hub_irq, IRQF_SHARED, - "v3d_hub", v3d); - if (ret) -@@ -289,8 +296,12 @@ v3d_irq_init(struct v3d_dev *v3d) - } else { - v3d->single_irq_line = true; - -- ret = devm_request_irq(v3d->drm.dev, -- platform_get_irq(v3d_to_pdev(v3d), 0), -+ irq = platform_get_irq(v3d_to_pdev(v3d), 0); -+ if (irq < 0) -+ return irq; -+ v3d->irq[V3D_CORE_IRQ] = irq; -+ -+ ret = devm_request_irq(v3d->drm.dev, v3d->irq[V3D_CORE_IRQ], - v3d_irq, IRQF_SHARED, - "v3d", v3d); - if (ret) -@@ -331,6 +342,12 @@ v3d_irq_disable(struct v3d_dev *v3d) - V3D_CORE_WRITE(core, V3D_CTL_INT_MSK_SET, ~0); - V3D_WRITE(V3D_HUB_INT_MSK_SET, ~0); - -+ /* Finish any interrupt handler still in flight. */ -+ for (int i = 0; i < V3D_MAX_IRQS; i++) { -+ if (v3d->irq[i]) -+ synchronize_irq(v3d->irq[i]); -+ } -+ - /* Clear any pending interrupts we might have left. */ - for (core = 0; core < v3d->cores; core++) - V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS(v3d->ver)); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/v3d/v3d_sched.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/v3d/v3d_sched.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/v3d/v3d_sched.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/v3d/v3d_sched.c 2025-10-22 13:53:56.479169315 -0400 -@@ -199,7 +199,6 @@ v3d_job_update_stats(struct v3d_job *job - struct v3d_dev *v3d = job->v3d; - struct v3d_file_priv *file = job->file->driver_priv; - struct v3d_stats *global_stats = &v3d->queue[queue].stats; -- struct v3d_stats *local_stats = &file->stats[queue]; - u64 now = local_clock(); - unsigned long flags; - -@@ -209,7 +208,12 @@ v3d_job_update_stats(struct v3d_job *job - else - preempt_disable(); - -- v3d_stats_update(local_stats, now); -+ /* Don't update the local stats if the file context has already closed */ -+ if (file) -+ v3d_stats_update(&file->stats[queue], now); -+ else -+ drm_dbg(&v3d->drm, "The file descriptor was closed before job completion\n"); -+ - v3d_stats_update(global_stats, now); - - if (IS_ENABLED(CONFIG_LOCKDEP)) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/vc4/vc4_hdmi.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/vc4/vc4_hdmi.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/vc4/vc4_hdmi.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/vc4/vc4_hdmi.c 2025-10-22 13:53:56.479169315 -0400 -@@ -560,12 +560,6 @@ static int vc4_hdmi_connector_init(struc - if (ret) - return ret; - -- ret = drm_connector_hdmi_audio_init(connector, dev->dev, -- &vc4_hdmi_audio_funcs, -- 8, false, -1); -- if (ret) -- return ret; -- - drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs); - - /* -@@ -2291,6 +2285,12 @@ static int vc4_hdmi_audio_init(struct vc - return ret; - } - -+ ret = drm_connector_hdmi_audio_init(&vc4_hdmi->connector, dev, -+ &vc4_hdmi_audio_funcs, 8, false, -+ -1); -+ if (ret) -+ return ret; -+ - dai_link->cpus = &vc4_hdmi->audio.cpu; - dai_link->codecs = &vc4_hdmi->audio.codec; - dai_link->platforms = &vc4_hdmi->audio.platform; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/virtio/virtgpu_prime.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/virtio/virtgpu_prime.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/virtio/virtgpu_prime.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/virtio/virtgpu_prime.c 2025-10-22 13:53:56.479169315 -0400 -@@ -204,15 +204,16 @@ static void virtgpu_dma_buf_free_obj(str - { - struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj); - struct virtio_gpu_device *vgdev = obj->dev->dev_private; -+ struct dma_buf_attachment *attach = obj->import_attach; - - if (drm_gem_is_imported(obj)) { -- struct dma_buf *dmabuf = obj->dma_buf; -+ struct dma_buf *dmabuf = attach->dmabuf; - - dma_resv_lock(dmabuf->resv, NULL); - virtgpu_dma_buf_unmap(bo); - dma_resv_unlock(dmabuf->resv); - -- dma_buf_detach(dmabuf, obj->import_attach); -+ dma_buf_detach(dmabuf, attach); - dma_buf_put(dmabuf); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c 2025-10-22 13:53:56.479169315 -0400 -@@ -749,7 +749,7 @@ static int vmw_setup_pci_resources(struc - dev->fifo_mem = devm_memremap(dev->drm.dev, - fifo_start, - fifo_size, -- MEMREMAP_WB); -+ MEMREMAP_WB | MEMREMAP_DEC); - - if (IS_ERR(dev->fifo_mem)) { - drm_err(&dev->drm, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c 2025-10-22 13:53:56.479169315 -0400 -@@ -85,10 +85,10 @@ static int vmw_gem_vmap(struct drm_gem_o - int ret; - - if (drm_gem_is_imported(obj)) { -- ret = dma_buf_vmap(obj->dma_buf, map); -+ ret = dma_buf_vmap(obj->import_attach->dmabuf, map); - if (!ret) { - if (drm_WARN_ON(obj->dev, map->is_iomem)) { -- dma_buf_vunmap(obj->dma_buf, map); -+ dma_buf_vunmap(obj->import_attach->dmabuf, map); - return -EIO; - } - } -@@ -102,7 +102,7 @@ static int vmw_gem_vmap(struct drm_gem_o - static void vmw_gem_vunmap(struct drm_gem_object *obj, struct iosys_map *map) - { - if (drm_gem_is_imported(obj)) -- dma_buf_vunmap(obj->dma_buf, map); -+ dma_buf_vunmap(obj->import_attach->dmabuf, map); - else - drm_gem_ttm_vunmap(obj, map); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c 2025-10-22 13:53:56.479169315 -0400 -@@ -896,7 +896,7 @@ int vmw_compat_shader_add(struct vmw_pri - .busy_domain = VMW_BO_DOMAIN_SYS, - .bo_type = ttm_bo_type_device, - .size = size, -- .pin = true, -+ .pin = false, - .keep_resv = true, - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/display/xe_display.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/display/xe_display.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/display/xe_display.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/display/xe_display.c 2025-10-22 13:53:56.479169315 -0400 -@@ -104,6 +104,8 @@ int xe_display_create(struct xe_device * - spin_lock_init(&xe->display.fb_tracking.lock); - - xe->display.hotplug.dp_wq = alloc_ordered_workqueue("xe-dp", 0); -+ if (!xe->display.hotplug.dp_wq) -+ return -ENOMEM; - - return drmm_add_action_or_reset(&xe->drm, display_destroy, NULL); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/display/xe_dsb_buffer.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/display/xe_dsb_buffer.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/display/xe_dsb_buffer.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/display/xe_dsb_buffer.c 2025-10-22 13:53:56.479169315 -0400 -@@ -17,10 +17,7 @@ u32 intel_dsb_buffer_ggtt_offset(struct - - void intel_dsb_buffer_write(struct intel_dsb_buffer *dsb_buf, u32 idx, u32 val) - { -- struct xe_device *xe = dsb_buf->vma->bo->tile->xe; -- - iosys_map_wr(&dsb_buf->vma->bo->vmap, idx * 4, u32, val); -- xe_device_l2_flush(xe); - } - - u32 intel_dsb_buffer_read(struct intel_dsb_buffer *dsb_buf, u32 idx) -@@ -30,12 +27,9 @@ u32 intel_dsb_buffer_read(struct intel_d - - void intel_dsb_buffer_memset(struct intel_dsb_buffer *dsb_buf, u32 idx, u32 val, size_t size) - { -- struct xe_device *xe = dsb_buf->vma->bo->tile->xe; -- - WARN_ON(idx > (dsb_buf->buf_size - size) / sizeof(*dsb_buf->cmd_buf)); - - iosys_map_memset(&dsb_buf->vma->bo->vmap, idx * 4, val, size); -- xe_device_l2_flush(xe); - } - - bool intel_dsb_buffer_create(struct intel_crtc *crtc, struct intel_dsb_buffer *dsb_buf, size_t size) -@@ -74,9 +68,12 @@ void intel_dsb_buffer_cleanup(struct int - - void intel_dsb_buffer_flush_map(struct intel_dsb_buffer *dsb_buf) - { -+ struct xe_device *xe = dsb_buf->vma->bo->tile->xe; -+ - /* - * The memory barrier here is to ensure coherency of DSB vs MMIO, - * both for weak ordering archs and discrete cards. - */ -- xe_device_wmb(dsb_buf->vma->bo->tile->xe); -+ xe_device_wmb(xe); -+ xe_device_l2_flush(xe); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/display/xe_fb_pin.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/display/xe_fb_pin.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/display/xe_fb_pin.c 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/display/xe_fb_pin.c 2025-10-22 13:53:56.479169315 -0400 -@@ -164,6 +164,9 @@ static int __xe_pin_fb_vma_dpt(const str - - vma->dpt = dpt; - vma->node = dpt->ggtt_node[tile0->id]; -+ -+ /* Ensure DPT writes are flushed */ -+ xe_device_l2_flush(xe); - return 0; - } - -@@ -333,8 +336,6 @@ static struct i915_vma *__xe_pin_fb_vma( - if (ret) - goto err_unpin; - -- /* Ensure DPT writes are flushed */ -- xe_device_l2_flush(xe); - return vma; - - err_unpin: -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/Kconfig ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/Kconfig 2025-10-22 13:53:23.239329010 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/Kconfig 2025-10-22 13:53:56.479169315 -0400 -@@ -1,9 +1,11 @@ - # SPDX-License-Identifier: GPL-2.0-only - config DRM_XE -- tristate "Intel Xe Graphics" -- depends on DRM && PCI && (m || (y && KUNIT=y)) -+ tristate "Intel Xe2 Graphics" -+ depends on DRM && PCI -+ depends on KUNIT || !KUNIT - depends on INTEL_VSEC || !INTEL_VSEC - depends on X86_PLATFORM_DEVICES || !(X86 && ACPI) -+ depends on PAGE_SIZE_4KB || COMPILE_TEST || BROKEN - select INTERVAL_TREE - # we need shmfs for the swappable backing store, and in particular - # the shmem_readpage() which depends upon tmpfs -@@ -46,7 +48,8 @@ config DRM_XE - select AUXILIARY_BUS - select HMM_MIRROR - help -- Experimental driver for Intel Xe series GPUs -+ Driver for Intel Xe2 series GPUs and later. Experimental support -+ for Xe series is also available. - - If "M" is selected, the module will be called xe. - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/regs/xe_mchbar_regs.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/regs/xe_mchbar_regs.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/regs/xe_mchbar_regs.h 2025-10-22 13:53:23.243328991 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/regs/xe_mchbar_regs.h 2025-10-22 13:53:56.483169296 -0400 -@@ -40,6 +40,7 @@ - #define PCU_CR_PACKAGE_RAPL_LIMIT XE_REG(MCHBAR_MIRROR_BASE_SNB + 0x59a0) - #define PWR_LIM_VAL REG_GENMASK(14, 0) - #define PWR_LIM_EN REG_BIT(15) -+#define PWR_LIM REG_GENMASK(15, 0) - #define PWR_LIM_TIME REG_GENMASK(23, 17) - #define PWR_LIM_TIME_X REG_GENMASK(23, 22) - #define PWR_LIM_TIME_Y REG_GENMASK(21, 17) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/tests/xe_bo.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/tests/xe_bo.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/tests/xe_bo.c 2025-10-22 13:53:23.243328991 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/tests/xe_bo.c 2025-10-22 13:53:56.483169296 -0400 -@@ -236,7 +236,7 @@ static int evict_test_run_tile(struct xe - } - - xe_bo_lock(external, false); -- err = xe_bo_pin_external(external); -+ err = xe_bo_pin_external(external, false); - xe_bo_unlock(external); - if (err) { - KUNIT_FAIL(test, "external bo pin err=%pe\n", -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/tests/xe_dma_buf.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/tests/xe_dma_buf.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/tests/xe_dma_buf.c 2025-10-22 13:53:23.243328991 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/tests/xe_dma_buf.c 2025-10-22 13:53:56.483169296 -0400 -@@ -89,15 +89,7 @@ static void check_residency(struct kunit - return; - } - -- /* -- * If on different devices, the exporter is kept in system if -- * possible, saving a migration step as the transfer is just -- * likely as fast from system memory. -- */ -- if (params->mem_mask & XE_BO_FLAG_SYSTEM) -- KUNIT_EXPECT_TRUE(test, xe_bo_is_mem_type(exported, XE_PL_TT)); -- else -- KUNIT_EXPECT_TRUE(test, xe_bo_is_mem_type(exported, mem_type)); -+ KUNIT_EXPECT_TRUE(test, xe_bo_is_mem_type(exported, mem_type)); - - if (params->force_different_devices) - KUNIT_EXPECT_TRUE(test, xe_bo_is_mem_type(imported, XE_PL_TT)); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_bo.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_bo.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_bo.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_bo.c 2025-10-22 13:53:56.483169296 -0400 -@@ -184,6 +184,8 @@ static void try_add_system(struct xe_dev - - bo->placements[*c] = (struct ttm_place) { - .mem_type = XE_PL_TT, -+ .flags = (bo_flags & XE_BO_FLAG_VRAM_MASK) ? -+ TTM_PL_FLAG_FALLBACK : 0, - }; - *c += 1; - } -@@ -796,14 +798,14 @@ static int xe_bo_move(struct ttm_buffer_ - } - - if (ttm_bo->type == ttm_bo_type_sg) { -- ret = xe_bo_move_notify(bo, ctx); -+ if (new_mem->mem_type == XE_PL_SYSTEM) -+ ret = xe_bo_move_notify(bo, ctx); - if (!ret) - ret = xe_bo_move_dmabuf(ttm_bo, new_mem); - return ret; - } - -- tt_has_data = ttm && (ttm_tt_is_populated(ttm) || -- (ttm->page_flags & TTM_TT_FLAG_SWAPPED)); -+ tt_has_data = ttm && (ttm_tt_is_populated(ttm) || ttm_tt_is_swapped(ttm)); - - move_lacks_source = !old_mem || (handle_system_ccs ? (!bo->ccs_cleared) : - (!mem_type_is_vram(old_mem_type) && !tt_has_data)); -@@ -2266,6 +2268,7 @@ uint64_t vram_region_gpu_offset(struct t - /** - * xe_bo_pin_external - pin an external BO - * @bo: buffer object to be pinned -+ * @in_place: Pin in current placement, don't attempt to migrate. - * - * Pin an external (not tied to a VM, can be exported via dma-buf / prime FD) - * BO. Unique call compared to xe_bo_pin as this function has it own set of -@@ -2273,7 +2276,7 @@ uint64_t vram_region_gpu_offset(struct t - * - * Returns 0 for success, negative error code otherwise. - */ --int xe_bo_pin_external(struct xe_bo *bo) -+int xe_bo_pin_external(struct xe_bo *bo, bool in_place) - { - struct xe_device *xe = xe_bo_device(bo); - int err; -@@ -2282,9 +2285,11 @@ int xe_bo_pin_external(struct xe_bo *bo) - xe_assert(xe, xe_bo_is_user(bo)); - - if (!xe_bo_is_pinned(bo)) { -- err = xe_bo_validate(bo, NULL, false); -- if (err) -- return err; -+ if (!in_place) { -+ err = xe_bo_validate(bo, NULL, false); -+ if (err) -+ return err; -+ } - - spin_lock(&xe->pinned.lock); - list_add_tail(&bo->pinned_link, &xe->pinned.late.external); -@@ -2435,9 +2440,11 @@ int xe_bo_validate(struct xe_bo *bo, str - .no_wait_gpu = false, - .gfp_retry_mayfail = true, - }; -- struct pin_cookie cookie; - int ret; - -+ if (xe_bo_is_pinned(bo)) -+ return 0; -+ - if (vm) { - lockdep_assert_held(&vm->lock); - xe_vm_assert_held(vm); -@@ -2446,10 +2453,10 @@ int xe_bo_validate(struct xe_bo *bo, str - ctx.resv = xe_vm_resv(vm); - } - -- cookie = xe_vm_set_validating(vm, allow_res_evict); -+ xe_vm_set_validating(vm, allow_res_evict); - trace_xe_bo_validate(bo); - ret = ttm_bo_validate(&bo->ttm, &bo->placement, &ctx); -- xe_vm_clear_validating(vm, allow_res_evict, cookie); -+ xe_vm_clear_validating(vm, allow_res_evict); - - return ret; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_bo_evict.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_bo_evict.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_bo_evict.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_bo_evict.c 2025-10-22 13:53:56.483169296 -0400 -@@ -158,8 +158,8 @@ int xe_bo_evict_all(struct xe_device *xe - if (ret) - return ret; - -- ret = xe_bo_apply_to_pinned(xe, &xe->pinned.late.kernel_bo_present, -- &xe->pinned.late.evicted, xe_bo_evict_pinned); -+ ret = xe_bo_apply_to_pinned(xe, &xe->pinned.late.external, -+ &xe->pinned.late.external, xe_bo_evict_pinned); - - if (!ret) - ret = xe_bo_apply_to_pinned(xe, &xe->pinned.late.kernel_bo_present, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_bo.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_bo.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_bo.h 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_bo.h 2025-10-22 13:53:56.483169296 -0400 -@@ -201,7 +201,7 @@ static inline void xe_bo_unlock_vm_held( - } - } - --int xe_bo_pin_external(struct xe_bo *bo); -+int xe_bo_pin_external(struct xe_bo *bo, bool in_place); - int xe_bo_pin(struct xe_bo *bo); - void xe_bo_unpin_external(struct xe_bo *bo); - void xe_bo_unpin(struct xe_bo *bo); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_configfs.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_configfs.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_configfs.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_configfs.c 2025-10-22 13:53:56.483169296 -0400 -@@ -133,7 +133,8 @@ static struct config_group *xe_config_ma - - pdev = pci_get_domain_bus_and_slot(domain, bus, PCI_DEVFN(slot, function)); - if (!pdev) -- return ERR_PTR(-EINVAL); -+ return ERR_PTR(-ENODEV); -+ pci_dev_put(pdev); - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) -@@ -243,7 +244,7 @@ int __init xe_configfs_init(void) - return 0; - } - --void __exit xe_configfs_exit(void) -+void xe_configfs_exit(void) - { - configfs_unregister_subsystem(&xe_configfs); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_devcoredump.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_devcoredump.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_devcoredump.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_devcoredump.c 2025-10-22 13:53:56.483169296 -0400 -@@ -171,14 +171,32 @@ static void xe_devcoredump_snapshot_free - - #define XE_DEVCOREDUMP_CHUNK_MAX (SZ_512M + SZ_1G) - -+/** -+ * xe_devcoredump_read() - Read data from the Xe device coredump snapshot -+ * @buffer: Destination buffer to copy the coredump data into -+ * @offset: Offset in the coredump data to start reading from -+ * @count: Number of bytes to read -+ * @data: Pointer to the xe_devcoredump structure -+ * @datalen: Length of the data (unused) -+ * -+ * Reads a chunk of the coredump snapshot data into the provided buffer. -+ * If the devcoredump is smaller than 1.5 GB (XE_DEVCOREDUMP_CHUNK_MAX), -+ * it is read directly from a pre-written buffer. For larger devcoredumps, -+ * the pre-written buffer must be periodically repopulated from the snapshot -+ * state due to kmalloc size limitations. -+ * -+ * Return: Number of bytes copied on success, or a negative error code on failure. -+ */ - static ssize_t xe_devcoredump_read(char *buffer, loff_t offset, - size_t count, void *data, size_t datalen) - { - struct xe_devcoredump *coredump = data; - struct xe_devcoredump_snapshot *ss; -- ssize_t byte_copied; -+ ssize_t byte_copied = 0; - u32 chunk_offset; - ssize_t new_chunk_position; -+ bool pm_needed = false; -+ int ret = 0; - - if (!coredump) - return -ENODEV; -@@ -188,20 +206,19 @@ static ssize_t xe_devcoredump_read(char - /* Ensure delayed work is captured before continuing */ - flush_work(&ss->work); - -- if (ss->read.size > XE_DEVCOREDUMP_CHUNK_MAX) -+ pm_needed = ss->read.size > XE_DEVCOREDUMP_CHUNK_MAX; -+ if (pm_needed) - xe_pm_runtime_get(gt_to_xe(ss->gt)); - - mutex_lock(&coredump->lock); - - if (!ss->read.buffer) { -- mutex_unlock(&coredump->lock); -- return -ENODEV; -+ ret = -ENODEV; -+ goto unlock; - } - -- if (offset >= ss->read.size) { -- mutex_unlock(&coredump->lock); -- return 0; -- } -+ if (offset >= ss->read.size) -+ goto unlock; - - new_chunk_position = div_u64_rem(offset, - XE_DEVCOREDUMP_CHUNK_MAX, -@@ -221,12 +238,13 @@ static ssize_t xe_devcoredump_read(char - ss->read.size - offset; - memcpy(buffer, ss->read.buffer + chunk_offset, byte_copied); - -+unlock: - mutex_unlock(&coredump->lock); - -- if (ss->read.size > XE_DEVCOREDUMP_CHUNK_MAX) -+ if (pm_needed) - xe_pm_runtime_put(gt_to_xe(ss->gt)); - -- return byte_copied; -+ return byte_copied ? byte_copied : ret; - } - - static void xe_devcoredump_free(void *data) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_device.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_device.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_device.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_device.c 2025-10-22 13:53:56.483169296 -0400 -@@ -40,6 +40,7 @@ - #include "xe_gt_printk.h" - #include "xe_gt_sriov_vf.h" - #include "xe_guc.h" -+#include "xe_guc_pc.h" - #include "xe_hw_engine_group.h" - #include "xe_hwmon.h" - #include "xe_irq.h" -@@ -684,6 +685,7 @@ static void sriov_update_device_info(str - /* disable features that are not available/applicable to VFs */ - if (IS_SRIOV_VF(xe)) { - xe->info.probe_display = 0; -+ xe->info.has_heci_cscfi = 0; - xe->info.has_heci_gscfi = 0; - xe->info.skip_guc_pc = 1; - xe->info.skip_pcode = 1; -@@ -986,38 +988,15 @@ void xe_device_wmb(struct xe_device *xe) - xe_mmio_write32(xe_root_tile_mmio(xe), VF_CAP_REG, 0); - } - --/** -- * xe_device_td_flush() - Flush transient L3 cache entries -- * @xe: The device -- * -- * Display engine has direct access to memory and is never coherent with L3/L4 -- * caches (or CPU caches), however KMD is responsible for specifically flushing -- * transient L3 GPU cache entries prior to the flip sequence to ensure scanout -- * can happen from such a surface without seeing corruption. -- * -- * Display surfaces can be tagged as transient by mapping it using one of the -- * various L3:XD PAT index modes on Xe2. -- * -- * Note: On non-discrete xe2 platforms, like LNL, the entire L3 cache is flushed -- * at the end of each submission via PIPE_CONTROL for compute/render, since SA -- * Media is not coherent with L3 and we want to support render-vs-media -- * usescases. For other engines like copy/blt the HW internally forces uncached -- * behaviour, hence why we can skip the TDF on such platforms. -+/* -+ * Issue a TRANSIENT_FLUSH_REQUEST and wait for completion on each gt. - */ --void xe_device_td_flush(struct xe_device *xe) -+static void tdf_request_sync(struct xe_device *xe) - { -- struct xe_gt *gt; - unsigned int fw_ref; -+ struct xe_gt *gt; - u8 id; - -- if (!IS_DGFX(xe) || GRAPHICS_VER(xe) < 20) -- return; -- -- if (XE_WA(xe_root_mmio_gt(xe), 16023588340)) { -- xe_device_l2_flush(xe); -- return; -- } -- - for_each_gt(gt, xe, id) { - if (xe_gt_is_media_type(gt)) - continue; -@@ -1027,6 +1006,7 @@ void xe_device_td_flush(struct xe_device - return; - - xe_mmio_write32(>->mmio, XE2_TDF_CTRL, TRANSIENT_FLUSH_REQUEST); -+ - /* - * FIXME: We can likely do better here with our choice of - * timeout. Currently we just assume the worst case, i.e. 150us, -@@ -1057,15 +1037,52 @@ void xe_device_l2_flush(struct xe_device - return; - - spin_lock(>->global_invl_lock); -- xe_mmio_write32(>->mmio, XE2_GLOBAL_INVAL, 0x1); - -+ xe_mmio_write32(>->mmio, XE2_GLOBAL_INVAL, 0x1); - if (xe_mmio_wait32(>->mmio, XE2_GLOBAL_INVAL, 0x1, 0x0, 500, NULL, true)) - xe_gt_err_once(gt, "Global invalidation timeout\n"); -+ - spin_unlock(>->global_invl_lock); - - xe_force_wake_put(gt_to_fw(gt), fw_ref); - } - -+/** -+ * xe_device_td_flush() - Flush transient L3 cache entries -+ * @xe: The device -+ * -+ * Display engine has direct access to memory and is never coherent with L3/L4 -+ * caches (or CPU caches), however KMD is responsible for specifically flushing -+ * transient L3 GPU cache entries prior to the flip sequence to ensure scanout -+ * can happen from such a surface without seeing corruption. -+ * -+ * Display surfaces can be tagged as transient by mapping it using one of the -+ * various L3:XD PAT index modes on Xe2. -+ * -+ * Note: On non-discrete xe2 platforms, like LNL, the entire L3 cache is flushed -+ * at the end of each submission via PIPE_CONTROL for compute/render, since SA -+ * Media is not coherent with L3 and we want to support render-vs-media -+ * usescases. For other engines like copy/blt the HW internally forces uncached -+ * behaviour, hence why we can skip the TDF on such platforms. -+ */ -+void xe_device_td_flush(struct xe_device *xe) -+{ -+ struct xe_gt *root_gt; -+ -+ if (!IS_DGFX(xe) || GRAPHICS_VER(xe) < 20) -+ return; -+ -+ root_gt = xe_root_mmio_gt(xe); -+ if (XE_WA(root_gt, 16023588340)) { -+ /* A transient flush is not sufficient: flush the L2 */ -+ xe_device_l2_flush(xe); -+ } else { -+ xe_guc_pc_apply_flush_freq_limit(&root_gt->uc.guc.pc); -+ tdf_request_sync(xe); -+ xe_guc_pc_remove_flush_freq_limit(&root_gt->uc.guc.pc); -+ } -+} -+ - u32 xe_device_ccs_bytes(struct xe_device *xe, u64 size) - { - return xe_device_has_flat_ccs(xe) ? -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_device_sysfs.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_device_sysfs.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_device_sysfs.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_device_sysfs.c 2025-10-22 13:53:56.483169296 -0400 -@@ -166,7 +166,7 @@ int xe_device_sysfs_init(struct xe_devic - return ret; - } - -- if (xe->info.platform == XE_BATTLEMAGE) { -+ if (xe->info.platform == XE_BATTLEMAGE && !IS_SRIOV_VF(xe)) { - ret = sysfs_create_files(&dev->kobj, auto_link_downgrade_attrs); - if (ret) - return ret; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_device_types.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_device_types.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_device_types.h 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_device_types.h 2025-10-22 13:53:56.483169296 -0400 -@@ -529,6 +529,12 @@ struct xe_device { - - /** @pm_notifier: Our PM notifier to perform actions in response to various PM events. */ - struct notifier_block pm_notifier; -+ /** @pm_block: Completion to block validating tasks on suspend / hibernate prepare */ -+ struct completion pm_block; -+ /** @rebind_resume_list: List of wq items to kick on resume. */ -+ struct list_head rebind_resume_list; -+ /** @rebind_resume_lock: Lock to protect the rebind_resume_list */ -+ struct mutex rebind_resume_lock; - - /** @pmt: Support the PMT driver callback interface */ - struct { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_dma_buf.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_dma_buf.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_dma_buf.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_dma_buf.c 2025-10-22 13:53:56.483169296 -0400 -@@ -72,7 +72,7 @@ static int xe_dma_buf_pin(struct dma_buf - return ret; - } - -- ret = xe_bo_pin_external(bo); -+ ret = xe_bo_pin_external(bo, true); - xe_assert(xe, !ret); - - return 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_drv.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_drv.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_drv.h 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_drv.h 2025-10-22 13:53:56.487169276 -0400 -@@ -9,7 +9,7 @@ - #include - - #define DRIVER_NAME "xe" --#define DRIVER_DESC "Intel Xe Graphics" -+#define DRIVER_DESC "Intel Xe2 Graphics" - - /* Interface history: - * -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_exec.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_exec.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_exec.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_exec.c 2025-10-22 13:53:56.487169276 -0400 -@@ -237,6 +237,15 @@ retry: - goto err_unlock_list; - } - -+ /* -+ * It's OK to block interruptible here with the vm lock held, since -+ * on task freezing during suspend / hibernate, the call will -+ * return -ERESTARTSYS and the IOCTL will be rerun. -+ */ -+ err = wait_for_completion_interruptible(&xe->pm_block); -+ if (err) -+ goto err_unlock_list; -+ - vm_exec.vm = &vm->gpuvm; - vm_exec.flags = DRM_EXEC_INTERRUPTIBLE_WAIT; - if (xe_vm_in_lr_mode(vm)) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_execlist.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_execlist.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_execlist.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_execlist.c 2025-10-22 13:53:56.487169276 -0400 -@@ -385,10 +385,20 @@ err_free: - return err; - } - --static void execlist_exec_queue_fini_async(struct work_struct *w) -+static void execlist_exec_queue_fini(struct xe_exec_queue *q) -+{ -+ struct xe_execlist_exec_queue *exl = q->execlist; -+ -+ drm_sched_entity_fini(&exl->entity); -+ drm_sched_fini(&exl->sched); -+ -+ kfree(exl); -+} -+ -+static void execlist_exec_queue_destroy_async(struct work_struct *w) - { - struct xe_execlist_exec_queue *ee = -- container_of(w, struct xe_execlist_exec_queue, fini_async); -+ container_of(w, struct xe_execlist_exec_queue, destroy_async); - struct xe_exec_queue *q = ee->q; - struct xe_execlist_exec_queue *exl = q->execlist; - struct xe_device *xe = gt_to_xe(q->gt); -@@ -401,10 +411,6 @@ static void execlist_exec_queue_fini_asy - list_del(&exl->active_link); - spin_unlock_irqrestore(&exl->port->lock, flags); - -- drm_sched_entity_fini(&exl->entity); -- drm_sched_fini(&exl->sched); -- kfree(exl); -- - xe_exec_queue_fini(q); - } - -@@ -413,10 +419,10 @@ static void execlist_exec_queue_kill(str - /* NIY */ - } - --static void execlist_exec_queue_fini(struct xe_exec_queue *q) -+static void execlist_exec_queue_destroy(struct xe_exec_queue *q) - { -- INIT_WORK(&q->execlist->fini_async, execlist_exec_queue_fini_async); -- queue_work(system_unbound_wq, &q->execlist->fini_async); -+ INIT_WORK(&q->execlist->destroy_async, execlist_exec_queue_destroy_async); -+ queue_work(system_unbound_wq, &q->execlist->destroy_async); - } - - static int execlist_exec_queue_set_priority(struct xe_exec_queue *q, -@@ -467,6 +473,7 @@ static const struct xe_exec_queue_ops ex - .init = execlist_exec_queue_init, - .kill = execlist_exec_queue_kill, - .fini = execlist_exec_queue_fini, -+ .destroy = execlist_exec_queue_destroy, - .set_priority = execlist_exec_queue_set_priority, - .set_timeslice = execlist_exec_queue_set_timeslice, - .set_preempt_timeout = execlist_exec_queue_set_preempt_timeout, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_execlist_types.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_execlist_types.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_execlist_types.h 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_execlist_types.h 2025-10-22 13:53:56.487169276 -0400 -@@ -42,7 +42,7 @@ struct xe_execlist_exec_queue { - - bool has_run; - -- struct work_struct fini_async; -+ struct work_struct destroy_async; - - enum xe_exec_queue_priority active_priority; - struct list_head active_link; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_exec_queue.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_exec_queue.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_exec_queue.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_exec_queue.c 2025-10-22 13:53:56.487169276 -0400 -@@ -151,6 +151,16 @@ err_lrc: - return err; - } - -+static void __xe_exec_queue_fini(struct xe_exec_queue *q) -+{ -+ int i; -+ -+ q->ops->fini(q); -+ -+ for (i = 0; i < q->width; ++i) -+ xe_lrc_put(q->lrc[i]); -+} -+ - struct xe_exec_queue *xe_exec_queue_create(struct xe_device *xe, struct xe_vm *vm, - u32 logical_mask, u16 width, - struct xe_hw_engine *hwe, u32 flags, -@@ -181,11 +191,13 @@ struct xe_exec_queue *xe_exec_queue_crea - if (xe_exec_queue_uses_pxp(q)) { - err = xe_pxp_exec_queue_add(xe->pxp, q); - if (err) -- goto err_post_alloc; -+ goto err_post_init; - } - - return q; - -+err_post_init: -+ __xe_exec_queue_fini(q); - err_post_alloc: - __xe_exec_queue_free(q); - return ERR_PTR(err); -@@ -283,13 +295,11 @@ void xe_exec_queue_destroy(struct kref * - xe_exec_queue_put(eq); - } - -- q->ops->fini(q); -+ q->ops->destroy(q); - } - - void xe_exec_queue_fini(struct xe_exec_queue *q) - { -- int i; -- - /* - * Before releasing our ref to lrc and xef, accumulate our run ticks - * and wakeup any waiters. -@@ -298,9 +308,7 @@ void xe_exec_queue_fini(struct xe_exec_q - if (q->xef && atomic_dec_and_test(&q->xef->exec_queue.pending_removal)) - wake_up_var(&q->xef->exec_queue.pending_removal); - -- for (i = 0; i < q->width; ++i) -- xe_lrc_put(q->lrc[i]); -- -+ __xe_exec_queue_fini(q); - __xe_exec_queue_free(q); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_exec_queue_types.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_exec_queue_types.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_exec_queue_types.h 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_exec_queue_types.h 2025-10-22 13:53:56.487169276 -0400 -@@ -166,8 +166,14 @@ struct xe_exec_queue_ops { - int (*init)(struct xe_exec_queue *q); - /** @kill: Kill inflight submissions for backend */ - void (*kill)(struct xe_exec_queue *q); -- /** @fini: Fini exec queue for submission backend */ -+ /** @fini: Undoes the init() for submission backend */ - void (*fini)(struct xe_exec_queue *q); -+ /** -+ * @destroy: Destroy exec queue for submission backend. The backend -+ * function must call xe_exec_queue_fini() (which will in turn call the -+ * fini() backend function) to ensure the queue is properly cleaned up. -+ */ -+ void (*destroy)(struct xe_exec_queue *q); - /** @set_priority: Set priority for exec queue */ - int (*set_priority)(struct xe_exec_queue *q, - enum xe_exec_queue_priority priority); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_ggtt.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_ggtt.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_ggtt.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_ggtt.c 2025-10-22 13:53:56.487169276 -0400 -@@ -201,6 +201,13 @@ static const struct xe_ggtt_pt_ops xelpg - .ggtt_set_pte = xe_ggtt_set_pte_and_flush, - }; - -+static void dev_fini_ggtt(void *arg) -+{ -+ struct xe_ggtt *ggtt = arg; -+ -+ drain_workqueue(ggtt->wq); -+} -+ - /** - * xe_ggtt_init_early - Early GGTT initialization - * @ggtt: the &xe_ggtt to be initialized -@@ -257,6 +264,10 @@ int xe_ggtt_init_early(struct xe_ggtt *g - if (err) - return err; - -+ err = devm_add_action_or_reset(xe->drm.dev, dev_fini_ggtt, ggtt); -+ if (err) -+ return err; -+ - if (IS_SRIOV_VF(xe)) { - err = xe_gt_sriov_vf_prepare_ggtt(xe_tile_get_gt(ggtt->tile, 0)); - if (err) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_gt.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_gt.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_gt.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_gt.c 2025-10-22 13:53:56.487169276 -0400 -@@ -118,7 +118,7 @@ static void xe_gt_enable_host_l2_vram(st - xe_gt_mcr_multicast_write(gt, XE2_GAMREQSTRM_CTRL, reg); - } - -- xe_gt_mcr_multicast_write(gt, XEHPC_L3CLOS_MASK(3), 0x3); -+ xe_gt_mcr_multicast_write(gt, XEHPC_L3CLOS_MASK(3), 0xF); - xe_force_wake_put(gt_to_fw(gt), fw_ref); - } - -@@ -417,6 +417,8 @@ int xe_gt_init_early(struct xe_gt *gt) - if (err) - return err; - -+ xe_mocs_init_early(gt); -+ - return 0; - } - -@@ -630,17 +632,15 @@ int xe_gt_init(struct xe_gt *gt) - if (err) - return err; - -- err = xe_gt_pagefault_init(gt); -+ err = xe_gt_sysfs_init(gt); - if (err) - return err; - -- xe_mocs_init_early(gt); -- -- err = xe_gt_sysfs_init(gt); -+ err = gt_fw_domain_init(gt); - if (err) - return err; - -- err = gt_fw_domain_init(gt); -+ err = xe_gt_pagefault_init(gt); - if (err) - return err; - -@@ -839,6 +839,9 @@ static int gt_reset(struct xe_gt *gt) - goto err_out; - } - -+ if (IS_SRIOV_PF(gt_to_xe(gt))) -+ xe_gt_sriov_pf_stop_prepare(gt); -+ - xe_uc_gucrc_disable(>->uc); - xe_uc_stop_prepare(>->uc); - xe_gt_pagefault_reset(gt); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_gt.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_gt.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_gt.h 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_gt.h 2025-10-22 13:53:56.487169276 -0400 -@@ -24,7 +24,7 @@ - extern struct fault_attr gt_reset_failure; - static inline bool xe_fault_inject_gt_reset(void) - { -- return should_fail(>_reset_failure, 1); -+ return IS_ENABLED(CONFIG_DEBUG_FS) && should_fail(>_reset_failure, 1); - } - - struct xe_gt *xe_gt_alloc(struct xe_tile *tile); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_gt_pagefault.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_gt_pagefault.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_gt_pagefault.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_gt_pagefault.c 2025-10-22 13:53:56.487169276 -0400 -@@ -444,6 +444,7 @@ static int xe_alloc_pf_queue(struct xe_g - #define PF_MULTIPLIER 8 - pf_queue->num_dw = - (num_eus + XE_NUM_HW_ENGINES) * PF_MSG_LEN_DW * PF_MULTIPLIER; -+ pf_queue->num_dw = roundup_pow_of_two(pf_queue->num_dw); - #undef PF_MULTIPLIER - - pf_queue->gt = gt; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_gt_sriov_pf.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_gt_sriov_pf.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_gt_sriov_pf.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_gt_sriov_pf.c 2025-10-22 13:53:56.487169276 -0400 -@@ -47,9 +47,16 @@ static int pf_alloc_metadata(struct xe_g - - static void pf_init_workers(struct xe_gt *gt) - { -+ xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); - INIT_WORK(>->sriov.pf.workers.restart, pf_worker_restart_func); - } - -+static void pf_fini_workers(struct xe_gt *gt) -+{ -+ xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); -+ disable_work_sync(>->sriov.pf.workers.restart); -+} -+ - /** - * xe_gt_sriov_pf_init_early - Prepare SR-IOV PF data structures on PF. - * @gt: the &xe_gt to initialize -@@ -79,6 +86,21 @@ int xe_gt_sriov_pf_init_early(struct xe_ - return 0; - } - -+static void pf_fini_action(void *arg) -+{ -+ struct xe_gt *gt = arg; -+ -+ pf_fini_workers(gt); -+} -+ -+static int pf_init_late(struct xe_gt *gt) -+{ -+ struct xe_device *xe = gt_to_xe(gt); -+ -+ xe_gt_assert(gt, IS_SRIOV_PF(xe)); -+ return devm_add_action_or_reset(xe->drm.dev, pf_fini_action, gt); -+} -+ - /** - * xe_gt_sriov_pf_init - Prepare SR-IOV PF data structures on PF. - * @gt: the &xe_gt to initialize -@@ -95,7 +117,15 @@ int xe_gt_sriov_pf_init(struct xe_gt *gt - if (err) - return err; - -- return xe_gt_sriov_pf_migration_init(gt); -+ err = xe_gt_sriov_pf_migration_init(gt); -+ if (err) -+ return err; -+ -+ err = pf_init_late(gt); -+ if (err) -+ return err; -+ -+ return 0; - } - - static bool pf_needs_enable_ggtt_guest_update(struct xe_device *xe) -@@ -172,6 +202,25 @@ void xe_gt_sriov_pf_sanitize_hw(struct x - pf_clear_vf_scratch_regs(gt, vfid); - } - -+static void pf_cancel_restart(struct xe_gt *gt) -+{ -+ xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); -+ -+ if (cancel_work_sync(>->sriov.pf.workers.restart)) -+ xe_gt_sriov_dbg_verbose(gt, "pending restart canceled!\n"); -+} -+ -+/** -+ * xe_gt_sriov_pf_stop_prepare() - Prepare to stop SR-IOV support. -+ * @gt: the &xe_gt -+ * -+ * This function can only be called on the PF. -+ */ -+void xe_gt_sriov_pf_stop_prepare(struct xe_gt *gt) -+{ -+ pf_cancel_restart(gt); -+} -+ - static void pf_restart(struct xe_gt *gt) - { - struct xe_device *xe = gt_to_xe(gt); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c 2025-10-22 13:53:56.487169276 -0400 -@@ -1600,7 +1600,6 @@ static u64 pf_estimate_fair_lmem(struct - u64 fair; - - fair = div_u64(available, num_vfs); -- fair = rounddown_pow_of_two(fair); /* XXX: ttm_vram_mgr & drm_buddy limitation */ - fair = ALIGN_DOWN(fair, alignment); - #ifdef MAX_FAIR_LMEM - fair = min_t(u64, MAX_FAIR_LMEM, fair); -@@ -2364,6 +2363,21 @@ int xe_gt_sriov_pf_config_restore(struct - return err; - } - -+static int pf_push_self_config(struct xe_gt *gt) -+{ -+ int err; -+ -+ err = pf_push_full_vf_config(gt, PFID); -+ if (err) { -+ xe_gt_sriov_err(gt, "Failed to push self configuration (%pe)\n", -+ ERR_PTR(err)); -+ return err; -+ } -+ -+ xe_gt_sriov_dbg_verbose(gt, "self configuration completed\n"); -+ return 0; -+} -+ - static void fini_config(void *arg) - { - struct xe_gt *gt = arg; -@@ -2387,9 +2401,17 @@ static void fini_config(void *arg) - int xe_gt_sriov_pf_config_init(struct xe_gt *gt) - { - struct xe_device *xe = gt_to_xe(gt); -+ int err; - - xe_gt_assert(gt, IS_SRIOV_PF(xe)); - -+ mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); -+ err = pf_push_self_config(gt); -+ mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); -+ -+ if (err) -+ return err; -+ - return devm_add_action_or_reset(xe->drm.dev, fini_config, gt); - } - -@@ -2407,6 +2429,10 @@ void xe_gt_sriov_pf_config_restart(struc - unsigned int n, total_vfs = xe_sriov_pf_get_totalvfs(gt_to_xe(gt)); - unsigned int fail = 0, skip = 0; - -+ mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); -+ pf_push_self_config(gt); -+ mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); -+ - for (n = 1; n <= total_vfs; n++) { - if (xe_gt_sriov_pf_config_is_empty(gt, n)) - skip++; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_gt_sriov_pf.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_gt_sriov_pf.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_gt_sriov_pf.h 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_gt_sriov_pf.h 2025-10-22 13:53:56.487169276 -0400 -@@ -13,6 +13,7 @@ int xe_gt_sriov_pf_init_early(struct xe_ - int xe_gt_sriov_pf_init(struct xe_gt *gt); - void xe_gt_sriov_pf_init_hw(struct xe_gt *gt); - void xe_gt_sriov_pf_sanitize_hw(struct xe_gt *gt, unsigned int vfid); -+void xe_gt_sriov_pf_stop_prepare(struct xe_gt *gt); - void xe_gt_sriov_pf_restart(struct xe_gt *gt); - #else - static inline int xe_gt_sriov_pf_init_early(struct xe_gt *gt) -@@ -29,6 +30,10 @@ static inline void xe_gt_sriov_pf_init_h - { - } - -+static inline void xe_gt_sriov_pf_stop_prepare(struct xe_gt *gt) -+{ -+} -+ - static inline void xe_gt_sriov_pf_restart(struct xe_gt *gt) - { - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c 2025-10-22 13:53:56.487169276 -0400 -@@ -138,6 +138,14 @@ void xe_gt_tlb_invalidation_reset(struct - int pending_seqno; - - /* -+ * we can get here before the CTs are even initialized if we're wedging -+ * very early, in which case there are not going to be any pending -+ * fences so we can bail immediately. -+ */ -+ if (!xe_guc_ct_initialized(>->uc.guc.ct)) -+ return; -+ -+ /* - * CT channel is already disabled at this point. No new TLB requests can - * appear. - */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_guc_ct.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_guc_ct.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_guc_ct.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_guc_ct.c 2025-10-22 13:53:56.487169276 -0400 -@@ -34,6 +34,11 @@ - #include "xe_pm.h" - #include "xe_trace_guc.h" - -+static void receive_g2h(struct xe_guc_ct *ct); -+static void g2h_worker_func(struct work_struct *w); -+static void safe_mode_worker_func(struct work_struct *w); -+static void ct_exit_safe_mode(struct xe_guc_ct *ct); -+ - #if IS_ENABLED(CONFIG_DRM_XE_DEBUG) - enum { - /* Internal states, not error conditions */ -@@ -186,14 +191,11 @@ static void guc_ct_fini(struct drm_devic - { - struct xe_guc_ct *ct = arg; - -+ ct_exit_safe_mode(ct); - destroy_workqueue(ct->g2h_wq); - xa_destroy(&ct->fence_lookup); - } - --static void receive_g2h(struct xe_guc_ct *ct); --static void g2h_worker_func(struct work_struct *w); --static void safe_mode_worker_func(struct work_struct *w); -- - static void primelockdep(struct xe_guc_ct *ct) - { - if (!IS_ENABLED(CONFIG_LOCKDEP)) -@@ -514,6 +516,9 @@ void xe_guc_ct_disable(struct xe_guc_ct - */ - void xe_guc_ct_stop(struct xe_guc_ct *ct) - { -+ if (!xe_guc_ct_initialized(ct)) -+ return; -+ - xe_guc_ct_set_state(ct, XE_GUC_CT_STATE_STOPPED); - stop_g2h_handler(ct); - } -@@ -760,7 +765,7 @@ static int __guc_ct_send_locked(struct x - u16 seqno; - int ret; - -- xe_gt_assert(gt, ct->state != XE_GUC_CT_STATE_NOT_INITIALIZED); -+ xe_gt_assert(gt, xe_guc_ct_initialized(ct)); - xe_gt_assert(gt, !g2h_len || !g2h_fence); - xe_gt_assert(gt, !num_g2h || !g2h_fence); - xe_gt_assert(gt, !g2h_len || num_g2h); -@@ -1344,7 +1349,7 @@ static int g2h_read(struct xe_guc_ct *ct - u32 action; - u32 *hxg; - -- xe_gt_assert(gt, ct->state != XE_GUC_CT_STATE_NOT_INITIALIZED); -+ xe_gt_assert(gt, xe_guc_ct_initialized(ct)); - lockdep_assert_held(&ct->fast_lock); - - if (ct->state == XE_GUC_CT_STATE_DISABLED) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_guc_ct.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_guc_ct.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_guc_ct.h 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_guc_ct.h 2025-10-22 13:53:56.487169276 -0400 -@@ -22,6 +22,11 @@ void xe_guc_ct_snapshot_print(struct xe_ - void xe_guc_ct_snapshot_free(struct xe_guc_ct_snapshot *snapshot); - void xe_guc_ct_print(struct xe_guc_ct *ct, struct drm_printer *p, bool want_ctb); - -+static inline bool xe_guc_ct_initialized(struct xe_guc_ct *ct) -+{ -+ return ct->state != XE_GUC_CT_STATE_NOT_INITIALIZED; -+} -+ - static inline bool xe_guc_ct_enabled(struct xe_guc_ct *ct) - { - return ct->state == XE_GUC_CT_STATE_ENABLED; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h 2025-10-22 13:53:56.487169276 -0400 -@@ -20,6 +20,8 @@ struct xe_exec_queue; - struct xe_guc_exec_queue { - /** @q: Backpointer to parent xe_exec_queue */ - struct xe_exec_queue *q; -+ /** @rcu: For safe freeing of exported dma fences */ -+ struct rcu_head rcu; - /** @sched: GPU scheduler for this xe_exec_queue */ - struct xe_gpu_scheduler sched; - /** @entity: Scheduler entity for this xe_exec_queue */ -@@ -33,8 +35,8 @@ struct xe_guc_exec_queue { - struct xe_sched_msg static_msgs[MAX_STATIC_MSG_TYPE]; - /** @lr_tdr: long running TDR worker */ - struct work_struct lr_tdr; -- /** @fini_async: do final fini async from this worker */ -- struct work_struct fini_async; -+ /** @destroy_async: do final destroy async from this worker */ -+ struct work_struct destroy_async; - /** @resume_time: time of last resume */ - u64 resume_time; - /** @state: GuC specific state for this xe_exec_queue */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_guc_pc.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_guc_pc.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_guc_pc.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_guc_pc.c 2025-10-22 13:53:56.487169276 -0400 -@@ -5,8 +5,11 @@ - - #include "xe_guc_pc.h" - -+#include - #include -+#include - #include -+#include - - #include - #include -@@ -51,9 +54,12 @@ - - #define LNL_MERT_FREQ_CAP 800 - #define BMG_MERT_FREQ_CAP 2133 -+#define BMG_MIN_FREQ 1200 -+#define BMG_MERT_FLUSH_FREQ_CAP 2600 - - #define SLPC_RESET_TIMEOUT_MS 5 /* roughly 5ms, but no need for precision */ - #define SLPC_RESET_EXTENDED_TIMEOUT_MS 1000 /* To be used only at pc_start */ -+#define SLPC_ACT_FREQ_TIMEOUT_MS 100 - - /** - * DOC: GuC Power Conservation (PC) -@@ -141,6 +147,36 @@ static int wait_for_pc_state(struct xe_g - return -ETIMEDOUT; - } - -+static int wait_for_flush_complete(struct xe_guc_pc *pc) -+{ -+ const unsigned long timeout = msecs_to_jiffies(30); -+ -+ if (!wait_var_event_timeout(&pc->flush_freq_limit, -+ !atomic_read(&pc->flush_freq_limit), -+ timeout)) -+ return -ETIMEDOUT; -+ -+ return 0; -+} -+ -+static int wait_for_act_freq_limit(struct xe_guc_pc *pc, u32 freq) -+{ -+ int timeout_us = SLPC_ACT_FREQ_TIMEOUT_MS * USEC_PER_MSEC; -+ int slept, wait = 10; -+ -+ for (slept = 0; slept < timeout_us;) { -+ if (xe_guc_pc_get_act_freq(pc) <= freq) -+ return 0; -+ -+ usleep_range(wait, wait << 1); -+ slept += wait; -+ wait <<= 1; -+ if (slept + wait > timeout_us) -+ wait = timeout_us - slept; -+ } -+ -+ return -ETIMEDOUT; -+} - static int pc_action_reset(struct xe_guc_pc *pc) - { - struct xe_guc_ct *ct = pc_to_ct(pc); -@@ -553,6 +589,25 @@ u32 xe_guc_pc_get_rpn_freq(struct xe_guc - return pc->rpn_freq; - } - -+static int xe_guc_pc_get_min_freq_locked(struct xe_guc_pc *pc, u32 *freq) -+{ -+ int ret; -+ -+ lockdep_assert_held(&pc->freq_lock); -+ -+ /* Might be in the middle of a gt reset */ -+ if (!pc->freq_ready) -+ return -EAGAIN; -+ -+ ret = pc_action_query_task_state(pc); -+ if (ret) -+ return ret; -+ -+ *freq = pc_get_min_freq(pc); -+ -+ return 0; -+} -+ - /** - * xe_guc_pc_get_min_freq - Get the min operational frequency - * @pc: The GuC PC -@@ -563,26 +618,28 @@ u32 xe_guc_pc_get_rpn_freq(struct xe_guc - */ - int xe_guc_pc_get_min_freq(struct xe_guc_pc *pc, u32 *freq) - { -+ guard(mutex)(&pc->freq_lock); -+ -+ return xe_guc_pc_get_min_freq_locked(pc, freq); -+} -+ -+static int xe_guc_pc_set_min_freq_locked(struct xe_guc_pc *pc, u32 freq) -+{ - int ret; - -- xe_device_assert_mem_access(pc_to_xe(pc)); -+ lockdep_assert_held(&pc->freq_lock); - -- mutex_lock(&pc->freq_lock); -- if (!pc->freq_ready) { -- /* Might be in the middle of a gt reset */ -- ret = -EAGAIN; -- goto out; -- } -+ /* Might be in the middle of a gt reset */ -+ if (!pc->freq_ready) -+ return -EAGAIN; - -- ret = pc_action_query_task_state(pc); -+ ret = pc_set_min_freq(pc, freq); - if (ret) -- goto out; -+ return ret; - -- *freq = pc_get_min_freq(pc); -+ pc->user_requested_min = freq; - --out: -- mutex_unlock(&pc->freq_lock); -- return ret; -+ return 0; - } - - /** -@@ -596,24 +653,28 @@ out: - */ - int xe_guc_pc_set_min_freq(struct xe_guc_pc *pc, u32 freq) - { -+ guard(mutex)(&pc->freq_lock); -+ -+ return xe_guc_pc_set_min_freq_locked(pc, freq); -+} -+ -+static int xe_guc_pc_get_max_freq_locked(struct xe_guc_pc *pc, u32 *freq) -+{ - int ret; - -- mutex_lock(&pc->freq_lock); -- if (!pc->freq_ready) { -- /* Might be in the middle of a gt reset */ -- ret = -EAGAIN; -- goto out; -- } -+ lockdep_assert_held(&pc->freq_lock); - -- ret = pc_set_min_freq(pc, freq); -+ /* Might be in the middle of a gt reset */ -+ if (!pc->freq_ready) -+ return -EAGAIN; -+ -+ ret = pc_action_query_task_state(pc); - if (ret) -- goto out; -+ return ret; - -- pc->user_requested_min = freq; -+ *freq = pc_get_max_freq(pc); - --out: -- mutex_unlock(&pc->freq_lock); -- return ret; -+ return 0; - } - - /** -@@ -626,24 +687,28 @@ out: - */ - int xe_guc_pc_get_max_freq(struct xe_guc_pc *pc, u32 *freq) - { -+ guard(mutex)(&pc->freq_lock); -+ -+ return xe_guc_pc_get_max_freq_locked(pc, freq); -+} -+ -+static int xe_guc_pc_set_max_freq_locked(struct xe_guc_pc *pc, u32 freq) -+{ - int ret; - -- mutex_lock(&pc->freq_lock); -- if (!pc->freq_ready) { -- /* Might be in the middle of a gt reset */ -- ret = -EAGAIN; -- goto out; -- } -+ lockdep_assert_held(&pc->freq_lock); - -- ret = pc_action_query_task_state(pc); -+ /* Might be in the middle of a gt reset */ -+ if (!pc->freq_ready) -+ return -EAGAIN; -+ -+ ret = pc_set_max_freq(pc, freq); - if (ret) -- goto out; -+ return ret; - -- *freq = pc_get_max_freq(pc); -+ pc->user_requested_max = freq; - --out: -- mutex_unlock(&pc->freq_lock); -- return ret; -+ return 0; - } - - /** -@@ -657,24 +722,14 @@ out: - */ - int xe_guc_pc_set_max_freq(struct xe_guc_pc *pc, u32 freq) - { -- int ret; -- -- mutex_lock(&pc->freq_lock); -- if (!pc->freq_ready) { -- /* Might be in the middle of a gt reset */ -- ret = -EAGAIN; -- goto out; -+ if (XE_WA(pc_to_gt(pc), 22019338487)) { -+ if (wait_for_flush_complete(pc) != 0) -+ return -EAGAIN; - } - -- ret = pc_set_max_freq(pc, freq); -- if (ret) -- goto out; -- -- pc->user_requested_max = freq; -+ guard(mutex)(&pc->freq_lock); - --out: -- mutex_unlock(&pc->freq_lock); -- return ret; -+ return xe_guc_pc_set_max_freq_locked(pc, freq); - } - - /** -@@ -817,6 +872,7 @@ void xe_guc_pc_init_early(struct xe_guc_ - - static int pc_adjust_freq_bounds(struct xe_guc_pc *pc) - { -+ struct xe_tile *tile = gt_to_tile(pc_to_gt(pc)); - int ret; - - lockdep_assert_held(&pc->freq_lock); -@@ -843,6 +899,9 @@ static int pc_adjust_freq_bounds(struct - if (pc_get_min_freq(pc) > pc->rp0_freq) - ret = pc_set_min_freq(pc, pc->rp0_freq); - -+ if (XE_WA(tile->primary_gt, 14022085890)) -+ ret = pc_set_min_freq(pc, max(BMG_MIN_FREQ, pc_get_min_freq(pc))); -+ - out: - return ret; - } -@@ -868,30 +927,117 @@ static int pc_adjust_requested_freq(stru - return ret; - } - --static int pc_set_mert_freq_cap(struct xe_guc_pc *pc) -+static bool needs_flush_freq_limit(struct xe_guc_pc *pc) - { -- int ret = 0; -+ struct xe_gt *gt = pc_to_gt(pc); - -- if (XE_WA(pc_to_gt(pc), 22019338487)) { -- /* -- * Get updated min/max and stash them. -- */ -- ret = xe_guc_pc_get_min_freq(pc, &pc->stashed_min_freq); -- if (!ret) -- ret = xe_guc_pc_get_max_freq(pc, &pc->stashed_max_freq); -- if (ret) -- return ret; -+ return XE_WA(gt, 22019338487) && -+ pc->rp0_freq > BMG_MERT_FLUSH_FREQ_CAP; -+} -+ -+/** -+ * xe_guc_pc_apply_flush_freq_limit() - Limit max GT freq during L2 flush -+ * @pc: the xe_guc_pc object -+ * -+ * As per the WA, reduce max GT frequency during L2 cache flush -+ */ -+void xe_guc_pc_apply_flush_freq_limit(struct xe_guc_pc *pc) -+{ -+ struct xe_gt *gt = pc_to_gt(pc); -+ u32 max_freq; -+ int ret; -+ -+ if (!needs_flush_freq_limit(pc)) -+ return; -+ -+ guard(mutex)(&pc->freq_lock); -+ -+ ret = xe_guc_pc_get_max_freq_locked(pc, &max_freq); -+ if (!ret && max_freq > BMG_MERT_FLUSH_FREQ_CAP) { -+ ret = pc_set_max_freq(pc, BMG_MERT_FLUSH_FREQ_CAP); -+ if (ret) { -+ xe_gt_err_once(gt, "Failed to cap max freq on flush to %u, %pe\n", -+ BMG_MERT_FLUSH_FREQ_CAP, ERR_PTR(ret)); -+ return; -+ } -+ -+ atomic_set(&pc->flush_freq_limit, 1); - - /* -- * Ensure min and max are bound by MERT_FREQ_CAP until driver loads. -+ * If user has previously changed max freq, stash that value to -+ * restore later, otherwise use the current max. New user -+ * requests wait on flush. - */ -- mutex_lock(&pc->freq_lock); -- ret = pc_set_min_freq(pc, min(pc->rpe_freq, pc_max_freq_cap(pc))); -- if (!ret) -- ret = pc_set_max_freq(pc, min(pc->rp0_freq, pc_max_freq_cap(pc))); -- mutex_unlock(&pc->freq_lock); -+ if (pc->user_requested_max != 0) -+ pc->stashed_max_freq = pc->user_requested_max; -+ else -+ pc->stashed_max_freq = max_freq; - } - -+ /* -+ * Wait for actual freq to go below the flush cap: even if the previous -+ * max was below cap, the current one might still be above it -+ */ -+ ret = wait_for_act_freq_limit(pc, BMG_MERT_FLUSH_FREQ_CAP); -+ if (ret) -+ xe_gt_err_once(gt, "Actual freq did not reduce to %u, %pe\n", -+ BMG_MERT_FLUSH_FREQ_CAP, ERR_PTR(ret)); -+} -+ -+/** -+ * xe_guc_pc_remove_flush_freq_limit() - Remove max GT freq limit after L2 flush completes. -+ * @pc: the xe_guc_pc object -+ * -+ * Retrieve the previous GT max frequency value. -+ */ -+void xe_guc_pc_remove_flush_freq_limit(struct xe_guc_pc *pc) -+{ -+ struct xe_gt *gt = pc_to_gt(pc); -+ int ret = 0; -+ -+ if (!needs_flush_freq_limit(pc)) -+ return; -+ -+ if (!atomic_read(&pc->flush_freq_limit)) -+ return; -+ -+ mutex_lock(&pc->freq_lock); -+ -+ ret = pc_set_max_freq(>->uc.guc.pc, pc->stashed_max_freq); -+ if (ret) -+ xe_gt_err_once(gt, "Failed to restore max freq %u:%d", -+ pc->stashed_max_freq, ret); -+ -+ atomic_set(&pc->flush_freq_limit, 0); -+ mutex_unlock(&pc->freq_lock); -+ wake_up_var(&pc->flush_freq_limit); -+} -+ -+static int pc_set_mert_freq_cap(struct xe_guc_pc *pc) -+{ -+ int ret; -+ -+ if (!XE_WA(pc_to_gt(pc), 22019338487)) -+ return 0; -+ -+ guard(mutex)(&pc->freq_lock); -+ -+ /* -+ * Get updated min/max and stash them. -+ */ -+ ret = xe_guc_pc_get_min_freq_locked(pc, &pc->stashed_min_freq); -+ if (!ret) -+ ret = xe_guc_pc_get_max_freq_locked(pc, &pc->stashed_max_freq); -+ if (ret) -+ return ret; -+ -+ /* -+ * Ensure min and max are bound by MERT_FREQ_CAP until driver loads. -+ */ -+ ret = pc_set_min_freq(pc, min(pc->rpe_freq, pc_max_freq_cap(pc))); -+ if (!ret) -+ ret = pc_set_max_freq(pc, min(pc->rp0_freq, pc_max_freq_cap(pc))); -+ - return ret; - } - -@@ -1068,7 +1214,7 @@ int xe_guc_pc_start(struct xe_guc_pc *pc - goto out; - } - -- memset(pc->bo->vmap.vaddr, 0, size); -+ xe_map_memset(xe, &pc->bo->vmap, 0, 0, size); - slpc_shared_data_write(pc, header.size, size); - - earlier = ktime_get(); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_guc_pc.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_guc_pc.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_guc_pc.h 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_guc_pc.h 2025-10-22 13:53:56.487169276 -0400 -@@ -38,5 +38,7 @@ u64 xe_guc_pc_mc6_residency(struct xe_gu - void xe_guc_pc_init_early(struct xe_guc_pc *pc); - int xe_guc_pc_restore_stashed_freq(struct xe_guc_pc *pc); - void xe_guc_pc_raise_unslice(struct xe_guc_pc *pc); -+void xe_guc_pc_apply_flush_freq_limit(struct xe_guc_pc *pc); -+void xe_guc_pc_remove_flush_freq_limit(struct xe_guc_pc *pc); - - #endif /* _XE_GUC_PC_H_ */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_guc_pc_types.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_guc_pc_types.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_guc_pc_types.h 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_guc_pc_types.h 2025-10-22 13:53:56.487169276 -0400 -@@ -15,6 +15,8 @@ - struct xe_guc_pc { - /** @bo: GGTT buffer object that is shared with GuC PC */ - struct xe_bo *bo; -+ /** @flush_freq_limit: 1 when max freq changes are limited by driver */ -+ atomic_t flush_freq_limit; - /** @rp0_freq: HW RP0 frequency - The Maximum one */ - u32 rp0_freq; - /** @rpa_freq: HW RPa frequency - The Achievable one */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_guc_submit.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_guc_submit.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_guc_submit.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_guc_submit.c 2025-10-22 13:53:56.487169276 -0400 -@@ -891,12 +891,13 @@ static void xe_guc_exec_queue_lr_cleanup - struct xe_exec_queue *q = ge->q; - struct xe_guc *guc = exec_queue_to_guc(q); - struct xe_gpu_scheduler *sched = &ge->sched; -- bool wedged; -+ bool wedged = false; - - xe_gt_assert(guc_to_gt(guc), xe_exec_queue_is_lr(q)); - trace_xe_exec_queue_lr_cleanup(q); - -- wedged = guc_submit_hint_wedged(exec_queue_to_guc(q)); -+ if (!exec_queue_killed(q)) -+ wedged = guc_submit_hint_wedged(exec_queue_to_guc(q)); - - /* Kill the run_job / process_msg entry points */ - xe_sched_submission_stop(sched); -@@ -1070,7 +1071,7 @@ guc_exec_queue_timedout_job(struct drm_s - int err = -ETIME; - pid_t pid = -1; - int i = 0; -- bool wedged, skip_timeout_check; -+ bool wedged = false, skip_timeout_check; - - /* - * TDR has fired before free job worker. Common if exec queue -@@ -1116,7 +1117,8 @@ guc_exec_queue_timedout_job(struct drm_s - * doesn't work for SRIOV. For now assuming timeouts in wedged mode are - * genuine timeouts. - */ -- wedged = guc_submit_hint_wedged(exec_queue_to_guc(q)); -+ if (!exec_queue_killed(q)) -+ wedged = guc_submit_hint_wedged(exec_queue_to_guc(q)); - - /* Engine state now stable, disable scheduling to check timestamp */ - if (!wedged && exec_queue_registered(q)) { -@@ -1267,44 +1269,57 @@ rearm: - return DRM_GPU_SCHED_STAT_NOMINAL; - } - --static void __guc_exec_queue_fini_async(struct work_struct *w) -+static void guc_exec_queue_fini(struct xe_exec_queue *q) -+{ -+ struct xe_guc_exec_queue *ge = q->guc; -+ struct xe_guc *guc = exec_queue_to_guc(q); -+ -+ release_guc_id(guc, q); -+ xe_sched_entity_fini(&ge->entity); -+ xe_sched_fini(&ge->sched); -+ -+ /* -+ * RCU free due sched being exported via DRM scheduler fences -+ * (timeline name). -+ */ -+ kfree_rcu(ge, rcu); -+} -+ -+static void __guc_exec_queue_destroy_async(struct work_struct *w) - { - struct xe_guc_exec_queue *ge = -- container_of(w, struct xe_guc_exec_queue, fini_async); -+ container_of(w, struct xe_guc_exec_queue, destroy_async); - struct xe_exec_queue *q = ge->q; - struct xe_guc *guc = exec_queue_to_guc(q); - - xe_pm_runtime_get(guc_to_xe(guc)); - trace_xe_exec_queue_destroy(q); - -- release_guc_id(guc, q); - if (xe_exec_queue_is_lr(q)) - cancel_work_sync(&ge->lr_tdr); - /* Confirm no work left behind accessing device structures */ - cancel_delayed_work_sync(&ge->sched.base.work_tdr); -- xe_sched_entity_fini(&ge->entity); -- xe_sched_fini(&ge->sched); - -- kfree(ge); - xe_exec_queue_fini(q); -+ - xe_pm_runtime_put(guc_to_xe(guc)); - } - --static void guc_exec_queue_fini_async(struct xe_exec_queue *q) -+static void guc_exec_queue_destroy_async(struct xe_exec_queue *q) - { - struct xe_guc *guc = exec_queue_to_guc(q); - struct xe_device *xe = guc_to_xe(guc); - -- INIT_WORK(&q->guc->fini_async, __guc_exec_queue_fini_async); -+ INIT_WORK(&q->guc->destroy_async, __guc_exec_queue_destroy_async); - - /* We must block on kernel engines so slabs are empty on driver unload */ - if (q->flags & EXEC_QUEUE_FLAG_PERMANENT || exec_queue_wedged(q)) -- __guc_exec_queue_fini_async(&q->guc->fini_async); -+ __guc_exec_queue_destroy_async(&q->guc->destroy_async); - else -- queue_work(xe->destroy_wq, &q->guc->fini_async); -+ queue_work(xe->destroy_wq, &q->guc->destroy_async); - } - --static void __guc_exec_queue_fini(struct xe_guc *guc, struct xe_exec_queue *q) -+static void __guc_exec_queue_destroy(struct xe_guc *guc, struct xe_exec_queue *q) - { - /* - * Might be done from within the GPU scheduler, need to do async as we -@@ -1313,7 +1328,7 @@ static void __guc_exec_queue_fini(struct - * this we and don't really care when everything is fini'd, just that it - * is. - */ -- guc_exec_queue_fini_async(q); -+ guc_exec_queue_destroy_async(q); - } - - static void __guc_exec_queue_process_msg_cleanup(struct xe_sched_msg *msg) -@@ -1327,7 +1342,7 @@ static void __guc_exec_queue_process_msg - if (exec_queue_registered(q)) - disable_scheduling_deregister(guc, q); - else -- __guc_exec_queue_fini(guc, q); -+ __guc_exec_queue_destroy(guc, q); - } - - static bool guc_exec_queue_allowed_to_change_state(struct xe_exec_queue *q) -@@ -1468,6 +1483,7 @@ static int guc_exec_queue_init(struct xe - - q->guc = ge; - ge->q = q; -+ init_rcu_head(&ge->rcu); - init_waitqueue_head(&ge->suspend_wait); - - for (i = 0; i < MAX_STATIC_MSG_TYPE; ++i) -@@ -1559,14 +1575,14 @@ static bool guc_exec_queue_try_add_msg(s - #define STATIC_MSG_CLEANUP 0 - #define STATIC_MSG_SUSPEND 1 - #define STATIC_MSG_RESUME 2 --static void guc_exec_queue_fini(struct xe_exec_queue *q) -+static void guc_exec_queue_destroy(struct xe_exec_queue *q) - { - struct xe_sched_msg *msg = q->guc->static_msgs + STATIC_MSG_CLEANUP; - - if (!(q->flags & EXEC_QUEUE_FLAG_PERMANENT) && !exec_queue_wedged(q)) - guc_exec_queue_add_msg(q, msg, CLEANUP); - else -- __guc_exec_queue_fini(exec_queue_to_guc(q), q); -+ __guc_exec_queue_destroy(exec_queue_to_guc(q), q); - } - - static int guc_exec_queue_set_priority(struct xe_exec_queue *q, -@@ -1696,6 +1712,7 @@ static const struct xe_exec_queue_ops gu - .init = guc_exec_queue_init, - .kill = guc_exec_queue_kill, - .fini = guc_exec_queue_fini, -+ .destroy = guc_exec_queue_destroy, - .set_priority = guc_exec_queue_set_priority, - .set_timeslice = guc_exec_queue_set_timeslice, - .set_preempt_timeout = guc_exec_queue_set_preempt_timeout, -@@ -1717,7 +1734,7 @@ static void guc_exec_queue_stop(struct x - if (exec_queue_extra_ref(q) || xe_exec_queue_is_lr(q)) - xe_exec_queue_put(q); - else if (exec_queue_destroyed(q)) -- __guc_exec_queue_fini(guc, q); -+ __guc_exec_queue_destroy(guc, q); - } - if (q->guc->suspend_pending) { - set_exec_queue_suspended(q); -@@ -1762,6 +1779,9 @@ int xe_guc_submit_reset_prepare(struct x - { - int ret; - -+ if (!guc->submission_state.initialized) -+ return 0; -+ - /* - * Using an atomic here rather than submission_state.lock as this - * function can be called while holding the CT lock (engine reset -@@ -1971,7 +1991,7 @@ static void handle_deregister_done(struc - if (exec_queue_extra_ref(q) || xe_exec_queue_is_lr(q)) - xe_exec_queue_put(q); - else -- __guc_exec_queue_fini(guc, q); -+ __guc_exec_queue_destroy(guc, q); - } - - int xe_guc_deregister_done_handler(struct xe_guc *guc, u32 *msg, u32 len) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_hw_fence.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_hw_fence.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_hw_fence.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_hw_fence.c 2025-10-22 13:53:56.487169276 -0400 -@@ -100,6 +100,9 @@ void xe_hw_fence_irq_finish(struct xe_hw - spin_unlock_irqrestore(&irq->lock, flags); - dma_fence_end_signalling(tmp); - } -+ -+ /* Safe release of the irq->lock used in dma_fence_init. */ -+ synchronize_rcu(); - } - - void xe_hw_fence_irq_run(struct xe_hw_fence_irq *irq) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_hwmon.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_hwmon.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_hwmon.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_hwmon.c 2025-10-22 13:53:56.487169276 -0400 -@@ -159,8 +159,8 @@ static int xe_hwmon_pcode_read_power_lim - return ret; - } - --static int xe_hwmon_pcode_write_power_limit(const struct xe_hwmon *hwmon, u32 attr, u8 channel, -- u32 uval) -+static int xe_hwmon_pcode_rmw_power_limit(const struct xe_hwmon *hwmon, u32 attr, u8 channel, -+ u32 clr, u32 set) - { - struct xe_tile *root_tile = xe_device_get_root_tile(hwmon->xe); - u32 val0, val1; -@@ -179,7 +179,7 @@ static int xe_hwmon_pcode_write_power_li - channel, val0, val1, ret); - - if (attr == PL1_HWMON_ATTR) -- val0 = uval; -+ val0 = (val0 & ~clr) | set; - else - return -EIO; - -@@ -329,6 +329,7 @@ static int xe_hwmon_power_max_write(stru - int ret = 0; - u32 reg_val; - struct xe_reg rapl_limit; -+ u64 max_supp_power_limit = 0; - - mutex_lock(&hwmon->hwmon_lock); - -@@ -339,7 +340,7 @@ static int xe_hwmon_power_max_write(stru - if (hwmon->xe->info.has_mbx_power_limits) { - drm_dbg(&hwmon->xe->drm, "disabling %s on channel %d\n", - PWR_ATTR_TO_STR(attr), channel); -- xe_hwmon_pcode_write_power_limit(hwmon, attr, channel, 0); -+ xe_hwmon_pcode_rmw_power_limit(hwmon, attr, channel, PWR_LIM_EN, 0); - xe_hwmon_pcode_read_power_limit(hwmon, attr, channel, ®_val); - } else { - reg_val = xe_mmio_rmw32(mmio, rapl_limit, PWR_LIM_EN, 0); -@@ -353,6 +354,20 @@ static int xe_hwmon_power_max_write(stru - goto unlock; - } - -+ /* -+ * If the sysfs value exceeds the maximum pcode supported power limit value, clamp it to -+ * the supported maximum (U12.3 format). -+ * This is to avoid truncation during reg_val calculation below and ensure the valid -+ * power limit is sent for pcode which would clamp it to card-supported value. -+ */ -+ max_supp_power_limit = ((PWR_LIM_VAL) >> hwmon->scl_shift_power) * SF_POWER; -+ if (value > max_supp_power_limit) { -+ value = max_supp_power_limit; -+ drm_info(&hwmon->xe->drm, -+ "Power limit clamped as selected %s exceeds channel %d limit\n", -+ PWR_ATTR_TO_STR(attr), channel); -+ } -+ - /* Computation in 64-bits to avoid overflow. Round to nearest. */ - reg_val = DIV_ROUND_CLOSEST_ULL((u64)value << hwmon->scl_shift_power, SF_POWER); - reg_val = PWR_LIM_EN | REG_FIELD_PREP(PWR_LIM_VAL, reg_val); -@@ -370,10 +385,9 @@ static int xe_hwmon_power_max_write(stru - } - - if (hwmon->xe->info.has_mbx_power_limits) -- ret = xe_hwmon_pcode_write_power_limit(hwmon, attr, channel, reg_val); -+ ret = xe_hwmon_pcode_rmw_power_limit(hwmon, attr, channel, PWR_LIM, reg_val); - else -- reg_val = xe_mmio_rmw32(mmio, rapl_limit, PWR_LIM_EN | PWR_LIM_VAL, -- reg_val); -+ reg_val = xe_mmio_rmw32(mmio, rapl_limit, PWR_LIM, reg_val); - unlock: - mutex_unlock(&hwmon->hwmon_lock); - return ret; -@@ -563,14 +577,11 @@ xe_hwmon_power_max_interval_store(struct - - mutex_lock(&hwmon->hwmon_lock); - -- if (hwmon->xe->info.has_mbx_power_limits) { -- ret = xe_hwmon_pcode_read_power_limit(hwmon, power_attr, channel, (u32 *)&r); -- r = (r & ~PWR_LIM_TIME) | rxy; -- xe_hwmon_pcode_write_power_limit(hwmon, power_attr, channel, r); -- } else { -+ if (hwmon->xe->info.has_mbx_power_limits) -+ xe_hwmon_pcode_rmw_power_limit(hwmon, power_attr, channel, PWR_LIM_TIME, rxy); -+ else - r = xe_mmio_rmw32(mmio, xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, channel), - PWR_LIM_TIME, rxy); -- } - - mutex_unlock(&hwmon->hwmon_lock); - -@@ -701,9 +712,23 @@ static int xe_hwmon_power_curr_crit_writ - { - int ret; - u32 uval; -+ u64 max_crit_power_curr = 0; - - mutex_lock(&hwmon->hwmon_lock); - -+ /* -+ * If the sysfs value exceeds the pcode mailbox cmd POWER_SETUP_SUBCOMMAND_WRITE_I1 -+ * max supported value, clamp it to the command's max (U10.6 format). -+ * This is to avoid truncation during uval calculation below and ensure the valid power -+ * limit is sent for pcode which would clamp it to card-supported value. -+ */ -+ max_crit_power_curr = (POWER_SETUP_I1_DATA_MASK >> POWER_SETUP_I1_SHIFT) * scale_factor; -+ if (value > max_crit_power_curr) { -+ value = max_crit_power_curr; -+ drm_info(&hwmon->xe->drm, -+ "Power limit clamped as selected exceeds channel %d limit\n", -+ channel); -+ } - uval = DIV_ROUND_CLOSEST_ULL(value << POWER_SETUP_I1_SHIFT, scale_factor); - ret = xe_hwmon_pcode_write_i1(hwmon, uval); - -@@ -1138,12 +1163,12 @@ xe_hwmon_get_preregistration_info(struct - } else { - drm_info(&hwmon->xe->drm, "Using mailbox commands for power limits\n"); - /* Write default limits to read from pcode from now on. */ -- xe_hwmon_pcode_write_power_limit(hwmon, PL1_HWMON_ATTR, -- CHANNEL_CARD, -- hwmon->pl1_on_boot[CHANNEL_CARD]); -- xe_hwmon_pcode_write_power_limit(hwmon, PL1_HWMON_ATTR, -- CHANNEL_PKG, -- hwmon->pl1_on_boot[CHANNEL_PKG]); -+ xe_hwmon_pcode_rmw_power_limit(hwmon, PL1_HWMON_ATTR, -+ CHANNEL_CARD, PWR_LIM | PWR_LIM_TIME, -+ hwmon->pl1_on_boot[CHANNEL_CARD]); -+ xe_hwmon_pcode_rmw_power_limit(hwmon, PL1_HWMON_ATTR, -+ CHANNEL_PKG, PWR_LIM | PWR_LIM_TIME, -+ hwmon->pl1_on_boot[CHANNEL_PKG]); - hwmon->scl_shift_power = PWR_UNIT; - hwmon->scl_shift_energy = ENERGY_UNIT; - hwmon->scl_shift_time = TIME_UNIT; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_lmtt.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_lmtt.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_lmtt.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_lmtt.c 2025-10-22 13:53:56.487169276 -0400 -@@ -78,6 +78,9 @@ static struct xe_lmtt_pt *lmtt_pt_alloc( - } - - lmtt_assert(lmtt, xe_bo_is_vram(bo)); -+ lmtt_debug(lmtt, "level=%u addr=%#llx\n", level, (u64)xe_bo_main_addr(bo, XE_PAGE_SIZE)); -+ -+ xe_map_memset(lmtt_to_xe(lmtt), &bo->vmap, 0, 0, bo->size); - - pt->level = level; - pt->bo = bo; -@@ -91,6 +94,9 @@ out: - - static void lmtt_pt_free(struct xe_lmtt_pt *pt) - { -+ lmtt_debug(&pt->bo->tile->sriov.pf.lmtt, "level=%u addr=%llx\n", -+ pt->level, (u64)xe_bo_main_addr(pt->bo, XE_PAGE_SIZE)); -+ - xe_bo_unpin_map_no_vm(pt->bo); - kfree(pt); - } -@@ -226,9 +232,14 @@ static void lmtt_write_pte(struct xe_lmt - - switch (lmtt->ops->lmtt_pte_size(level)) { - case sizeof(u32): -+ lmtt_assert(lmtt, !overflows_type(pte, u32)); -+ lmtt_assert(lmtt, !pte || !iosys_map_rd(&pt->bo->vmap, idx * sizeof(u32), u32)); -+ - xe_map_wr(lmtt_to_xe(lmtt), &pt->bo->vmap, idx * sizeof(u32), u32, pte); - break; - case sizeof(u64): -+ lmtt_assert(lmtt, !pte || !iosys_map_rd(&pt->bo->vmap, idx * sizeof(u64), u64)); -+ - xe_map_wr(lmtt_to_xe(lmtt), &pt->bo->vmap, idx * sizeof(u64), u64, pte); - break; - default: -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_lrc.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_lrc.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_lrc.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_lrc.c 2025-10-22 13:53:56.487169276 -0400 -@@ -40,6 +40,7 @@ - - #define LRC_PPHWSP_SIZE SZ_4K - #define LRC_INDIRECT_RING_STATE_SIZE SZ_4K -+#define LRC_WA_BB_SIZE SZ_4K - - static struct xe_device * - lrc_to_xe(struct xe_lrc *lrc) -@@ -910,7 +911,11 @@ static void xe_lrc_finish(struct xe_lrc - { - xe_hw_fence_ctx_finish(&lrc->fence_ctx); - xe_bo_unpin_map_no_vm(lrc->bo); -- xe_bo_unpin_map_no_vm(lrc->bb_per_ctx_bo); -+} -+ -+static size_t wa_bb_offset(struct xe_lrc *lrc) -+{ -+ return lrc->bo->size - LRC_WA_BB_SIZE; - } - - /* -@@ -941,11 +946,19 @@ static void xe_lrc_finish(struct xe_lrc - * store it in the PPHSWP. - */ - #define CONTEXT_ACTIVE 1ULL --static void xe_lrc_setup_utilization(struct xe_lrc *lrc) -+static int xe_lrc_setup_utilization(struct xe_lrc *lrc) - { -- u32 *cmd; -+ const size_t max_size = LRC_WA_BB_SIZE; -+ u32 *cmd, *buf = NULL; - -- cmd = lrc->bb_per_ctx_bo->vmap.vaddr; -+ if (lrc->bo->vmap.is_iomem) { -+ buf = kmalloc(max_size, GFP_KERNEL); -+ if (!buf) -+ return -ENOMEM; -+ cmd = buf; -+ } else { -+ cmd = lrc->bo->vmap.vaddr + wa_bb_offset(lrc); -+ } - - *cmd++ = MI_STORE_REGISTER_MEM | MI_SRM_USE_GGTT | MI_SRM_ADD_CS_OFFSET; - *cmd++ = ENGINE_ID(0).addr; -@@ -966,9 +979,17 @@ static void xe_lrc_setup_utilization(str - - *cmd++ = MI_BATCH_BUFFER_END; - -- xe_lrc_write_ctx_reg(lrc, CTX_BB_PER_CTX_PTR, -- xe_bo_ggtt_addr(lrc->bb_per_ctx_bo) | 1); -+ if (buf) { -+ xe_map_memcpy_to(gt_to_xe(lrc->gt), &lrc->bo->vmap, -+ wa_bb_offset(lrc), buf, -+ (cmd - buf) * sizeof(*cmd)); -+ kfree(buf); -+ } -+ -+ xe_lrc_write_ctx_reg(lrc, CTX_BB_PER_CTX_PTR, xe_bo_ggtt_addr(lrc->bo) + -+ wa_bb_offset(lrc) + 1); - -+ return 0; - } - - #define PVC_CTX_ASID (0x2e + 1) -@@ -1004,20 +1025,13 @@ static int xe_lrc_init(struct xe_lrc *lr - * FIXME: Perma-pinning LRC as we don't yet support moving GGTT address - * via VM bind calls. - */ -- lrc->bo = xe_bo_create_pin_map(xe, tile, NULL, lrc_size, -+ lrc->bo = xe_bo_create_pin_map(xe, tile, NULL, -+ lrc_size + LRC_WA_BB_SIZE, - ttm_bo_type_kernel, - bo_flags); - if (IS_ERR(lrc->bo)) - return PTR_ERR(lrc->bo); - -- lrc->bb_per_ctx_bo = xe_bo_create_pin_map(xe, tile, NULL, SZ_4K, -- ttm_bo_type_kernel, -- bo_flags); -- if (IS_ERR(lrc->bb_per_ctx_bo)) { -- err = PTR_ERR(lrc->bb_per_ctx_bo); -- goto err_lrc_finish; -- } -- - lrc->size = lrc_size; - lrc->ring.size = ring_size; - lrc->ring.tail = 0; -@@ -1125,7 +1139,9 @@ static int xe_lrc_init(struct xe_lrc *lr - map = __xe_lrc_start_seqno_map(lrc); - xe_map_write32(lrc_to_xe(lrc), &map, lrc->fence_ctx.next_seqno - 1); - -- xe_lrc_setup_utilization(lrc); -+ err = xe_lrc_setup_utilization(lrc); -+ if (err) -+ goto err_lrc_finish; - - return 0; - -@@ -1803,7 +1819,8 @@ struct xe_lrc_snapshot *xe_lrc_snapshot_ - snapshot->seqno = xe_lrc_seqno(lrc); - snapshot->lrc_bo = xe_bo_get(lrc->bo); - snapshot->lrc_offset = xe_lrc_pphwsp_offset(lrc); -- snapshot->lrc_size = lrc->bo->size - snapshot->lrc_offset; -+ snapshot->lrc_size = lrc->bo->size - snapshot->lrc_offset - -+ LRC_WA_BB_SIZE; - snapshot->lrc_snapshot = NULL; - snapshot->ctx_timestamp = lower_32_bits(xe_lrc_ctx_timestamp(lrc)); - snapshot->ctx_job_timestamp = xe_lrc_ctx_job_timestamp(lrc); -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_lrc_types.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_lrc_types.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_lrc_types.h 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_lrc_types.h 2025-10-22 13:53:56.487169276 -0400 -@@ -53,9 +53,6 @@ struct xe_lrc { - - /** @ctx_timestamp: readout value of CTX_TIMESTAMP on last update */ - u64 ctx_timestamp; -- -- /** @bb_per_ctx_bo: buffer object for per context batch wa buffer */ -- struct xe_bo *bb_per_ctx_bo; - }; - - struct xe_lrc_snapshot; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_migrate.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_migrate.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_migrate.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_migrate.c 2025-10-22 13:53:56.487169276 -0400 -@@ -82,7 +82,7 @@ struct xe_migrate { - * of the instruction. Subtracting the instruction header (1 dword) and - * address (2 dwords), that leaves 0x3FD dwords (0x1FE qwords) for PTE values. - */ --#define MAX_PTE_PER_SDI 0x1FE -+#define MAX_PTE_PER_SDI 0x1FEU - - /** - * xe_tile_migrate_exec_queue() - Get this tile's migrate exec queue. -@@ -408,7 +408,7 @@ struct xe_migrate *xe_migrate_init(struc - - /* Special layout, prepared below.. */ - vm = xe_vm_create(xe, XE_VM_FLAG_MIGRATION | -- XE_VM_FLAG_SET_TILE_ID(tile)); -+ XE_VM_FLAG_SET_TILE_ID(tile), NULL); - if (IS_ERR(vm)) - return ERR_CAST(vm); - -@@ -863,7 +863,7 @@ struct dma_fence *xe_migrate_copy(struct - if (src_is_vram && xe_migrate_allow_identity(src_L0, &src_it)) - xe_res_next(&src_it, src_L0); - else -- emit_pte(m, bb, src_L0_pt, src_is_vram, copy_system_ccs, -+ emit_pte(m, bb, src_L0_pt, src_is_vram, copy_system_ccs || use_comp_pat, - &src_it, src_L0, src); - - if (dst_is_vram && xe_migrate_allow_identity(src_L0, &dst_it)) -@@ -1553,15 +1553,17 @@ static u32 pte_update_cmd_size(u64 size) - u64 entries = DIV_U64_ROUND_UP(size, XE_PAGE_SIZE); - - XE_WARN_ON(size > MAX_PREEMPTDISABLE_TRANSFER); -+ - /* - * MI_STORE_DATA_IMM command is used to update page table. Each -- * instruction can update maximumly 0x1ff pte entries. To update -- * n (n <= 0x1ff) pte entries, we need: -- * 1 dword for the MI_STORE_DATA_IMM command header (opcode etc) -- * 2 dword for the page table's physical location -- * 2*n dword for value of pte to fill (each pte entry is 2 dwords) -+ * instruction can update maximumly MAX_PTE_PER_SDI pte entries. To -+ * update n (n <= MAX_PTE_PER_SDI) pte entries, we need: -+ * -+ * - 1 dword for the MI_STORE_DATA_IMM command header (opcode etc) -+ * - 2 dword for the page table's physical location -+ * - 2*n dword for value of pte to fill (each pte entry is 2 dwords) - */ -- num_dword = (1 + 2) * DIV_U64_ROUND_UP(entries, 0x1ff); -+ num_dword = (1 + 2) * DIV_U64_ROUND_UP(entries, MAX_PTE_PER_SDI); - num_dword += entries * 2; - - return num_dword; -@@ -1577,7 +1579,7 @@ static void build_pt_update_batch_sram(s - - ptes = DIV_ROUND_UP(size, XE_PAGE_SIZE); - while (ptes) { -- u32 chunk = min(0x1ffU, ptes); -+ u32 chunk = min(MAX_PTE_PER_SDI, ptes); - - bb->cs[bb->len++] = MI_STORE_DATA_IMM | MI_SDI_NUM_QW(chunk); - bb->cs[bb->len++] = pt_offset; -@@ -1815,18 +1817,22 @@ int xe_migrate_access_memory(struct xe_m - xe_bo_assert_held(bo); - - /* Use bounce buffer for small access and unaligned access */ -- if (len & XE_CACHELINE_MASK || -- ((uintptr_t)buf | offset) & XE_CACHELINE_MASK) { -+ if (!IS_ALIGNED(len, XE_CACHELINE_BYTES) || -+ !IS_ALIGNED((unsigned long)buf + offset, XE_CACHELINE_BYTES)) { - int buf_offset = 0; -+ void *bounce; -+ int err; -+ -+ BUILD_BUG_ON(!is_power_of_2(XE_CACHELINE_BYTES)); -+ bounce = kmalloc(XE_CACHELINE_BYTES, GFP_KERNEL); -+ if (!bounce) -+ return -ENOMEM; - - /* - * Less than ideal for large unaligned access but this should be - * fairly rare, can fixup if this becomes common. - */ - do { -- u8 bounce[XE_CACHELINE_BYTES]; -- void *ptr = (void *)bounce; -- int err; - int copy_bytes = min_t(int, bytes_left, - XE_CACHELINE_BYTES - - (offset & XE_CACHELINE_MASK)); -@@ -1835,22 +1841,22 @@ int xe_migrate_access_memory(struct xe_m - err = xe_migrate_access_memory(m, bo, - offset & - ~XE_CACHELINE_MASK, -- (void *)ptr, -- sizeof(bounce), 0); -+ bounce, -+ XE_CACHELINE_BYTES, 0); - if (err) -- return err; -+ break; - - if (write) { -- memcpy(ptr + ptr_offset, buf + buf_offset, copy_bytes); -+ memcpy(bounce + ptr_offset, buf + buf_offset, copy_bytes); - - err = xe_migrate_access_memory(m, bo, - offset & ~XE_CACHELINE_MASK, -- (void *)ptr, -- sizeof(bounce), 0); -+ bounce, -+ XE_CACHELINE_BYTES, write); - if (err) -- return err; -+ break; - } else { -- memcpy(buf + buf_offset, ptr + ptr_offset, -+ memcpy(buf + buf_offset, bounce + ptr_offset, - copy_bytes); - } - -@@ -1859,7 +1865,8 @@ int xe_migrate_access_memory(struct xe_m - offset += copy_bytes; - } while (bytes_left); - -- return 0; -+ kfree(bounce); -+ return err; - } - - dma_addr = xe_migrate_dma_map(xe, buf, len + page_offset, write); -@@ -1880,8 +1887,11 @@ int xe_migrate_access_memory(struct xe_m - else - current_bytes = min_t(int, bytes_left, cursor.size); - -- if (fence) -- dma_fence_put(fence); -+ if (current_bytes & ~PAGE_MASK) { -+ int pitch = 4; -+ -+ current_bytes = min_t(int, current_bytes, S16_MAX * pitch); -+ } - - __fence = xe_migrate_vram(m, current_bytes, - (unsigned long)buf & ~PAGE_MASK, -@@ -1890,11 +1900,15 @@ int xe_migrate_access_memory(struct xe_m - XE_MIGRATE_COPY_TO_VRAM : - XE_MIGRATE_COPY_TO_SRAM); - if (IS_ERR(__fence)) { -- if (fence) -+ if (fence) { - dma_fence_wait(fence, false); -+ dma_fence_put(fence); -+ } - fence = __fence; - goto out_err; - } -+ -+ dma_fence_put(fence); - fence = __fence; - - buf += current_bytes; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_module.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_module.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_module.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_module.c 2025-10-22 13:53:56.487169276 -0400 -@@ -20,7 +20,7 @@ - - struct xe_modparam xe_modparam = { - .probe_display = true, -- .guc_log_level = 3, -+ .guc_log_level = IS_ENABLED(CONFIG_DRM_XE_DEBUG) ? 3 : 1, - .force_probe = CONFIG_DRM_XE_FORCE_PROBE, - .wedged_mode = 1, - .svm_notifier_size = 512, -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_pci.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_pci.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_pci.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_pci.c 2025-10-22 13:53:56.487169276 -0400 -@@ -140,7 +140,6 @@ static const struct xe_graphics_desc gra - .has_asid = 1, \ - .has_atomic_enable_pte_bit = 1, \ - .has_flat_ccs = 1, \ -- .has_indirect_ring_state = 1, \ - .has_range_tlb_invalidation = 1, \ - .has_usm = 1, \ - .has_64bit_timestamp = 1, \ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_pm.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_pm.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_pm.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_pm.c 2025-10-22 13:53:56.487169276 -0400 -@@ -23,6 +23,7 @@ - #include "xe_pcode.h" - #include "xe_pxp.h" - #include "xe_trace.h" -+#include "xe_vm.h" - #include "xe_wa.h" - - /** -@@ -134,7 +135,7 @@ int xe_pm_suspend(struct xe_device *xe) - /* FIXME: Super racey... */ - err = xe_bo_evict_all(xe); - if (err) -- goto err_pxp; -+ goto err_display; - - for_each_gt(gt, xe, id) { - err = xe_gt_suspend(gt); -@@ -151,7 +152,6 @@ int xe_pm_suspend(struct xe_device *xe) - - err_display: - xe_display_pm_resume(xe); --err_pxp: - xe_pxp_pm_resume(xe->pxp); - err: - drm_dbg(&xe->drm, "Device suspend failed %d\n", err); -@@ -286,6 +286,19 @@ static u32 vram_threshold_value(struct x - return DEFAULT_VRAM_THRESHOLD; - } - -+static void xe_pm_wake_rebind_workers(struct xe_device *xe) -+{ -+ struct xe_vm *vm, *next; -+ -+ mutex_lock(&xe->rebind_resume_lock); -+ list_for_each_entry_safe(vm, next, &xe->rebind_resume_list, -+ preempt.pm_activate_link) { -+ list_del_init(&vm->preempt.pm_activate_link); -+ xe_vm_resume_rebind_worker(vm); -+ } -+ mutex_unlock(&xe->rebind_resume_lock); -+} -+ - static int xe_pm_notifier_callback(struct notifier_block *nb, - unsigned long action, void *data) - { -@@ -295,30 +308,30 @@ static int xe_pm_notifier_callback(struc - switch (action) { - case PM_HIBERNATION_PREPARE: - case PM_SUSPEND_PREPARE: -+ reinit_completion(&xe->pm_block); - xe_pm_runtime_get(xe); - err = xe_bo_evict_all_user(xe); -- if (err) { -+ if (err) - drm_dbg(&xe->drm, "Notifier evict user failed (%d)\n", err); -- xe_pm_runtime_put(xe); -- break; -- } - - err = xe_bo_notifier_prepare_all_pinned(xe); -- if (err) { -+ if (err) - drm_dbg(&xe->drm, "Notifier prepare pin failed (%d)\n", err); -- xe_pm_runtime_put(xe); -- } -+ /* -+ * Keep the runtime pm reference until post hibernation / post suspend to -+ * avoid a runtime suspend interfering with evicted objects or backup -+ * allocations. -+ */ - break; - case PM_POST_HIBERNATION: - case PM_POST_SUSPEND: -+ complete_all(&xe->pm_block); -+ xe_pm_wake_rebind_workers(xe); - xe_bo_notifier_unprepare_all_pinned(xe); - xe_pm_runtime_put(xe); - break; - } - -- if (err) -- return NOTIFY_BAD; -- - return NOTIFY_DONE; - } - -@@ -340,6 +353,14 @@ int xe_pm_init(struct xe_device *xe) - if (err) - return err; - -+ err = drmm_mutex_init(&xe->drm, &xe->rebind_resume_lock); -+ if (err) -+ goto err_unregister; -+ -+ init_completion(&xe->pm_block); -+ complete_all(&xe->pm_block); -+ INIT_LIST_HEAD(&xe->rebind_resume_list); -+ - /* For now suspend/resume is only allowed with GuC */ - if (!xe_device_uc_enabled(xe)) - return 0; -@@ -753,11 +774,13 @@ void xe_pm_assert_unbounded_bridge(struc - } - - /** -- * xe_pm_set_vram_threshold - Set a vram threshold for allowing/blocking D3Cold -+ * xe_pm_set_vram_threshold - Set a VRAM threshold for allowing/blocking D3Cold - * @xe: xe device instance -- * @threshold: VRAM size in bites for the D3cold threshold -+ * @threshold: VRAM size in MiB for the D3cold threshold - * -- * Returns 0 for success, negative error code otherwise. -+ * Return: -+ * * 0 - success -+ * * -EINVAL - invalid argument - */ - int xe_pm_set_vram_threshold(struct xe_device *xe, u32 threshold) - { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_pxp_submit.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_pxp_submit.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_pxp_submit.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_pxp_submit.c 2025-10-22 13:53:56.487169276 -0400 -@@ -101,7 +101,7 @@ static int allocate_gsc_client_resources - xe_assert(xe, hwe); - - /* PXP instructions must be issued from PPGTT */ -- vm = xe_vm_create(xe, XE_VM_FLAG_GSC); -+ vm = xe_vm_create(xe, XE_VM_FLAG_GSC, NULL); - if (IS_ERR(vm)) - return PTR_ERR(vm); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_query.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_query.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_query.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_query.c 2025-10-22 13:53:56.487169276 -0400 -@@ -368,6 +368,7 @@ static int query_gt_list(struct xe_devic - struct drm_xe_query_gt_list __user *query_ptr = - u64_to_user_ptr(query->data); - struct drm_xe_query_gt_list *gt_list; -+ int iter = 0; - u8 id; - - if (query->size == 0) { -@@ -385,12 +386,12 @@ static int query_gt_list(struct xe_devic - - for_each_gt(gt, xe, id) { - if (xe_gt_is_media_type(gt)) -- gt_list->gt_list[id].type = DRM_XE_QUERY_GT_TYPE_MEDIA; -+ gt_list->gt_list[iter].type = DRM_XE_QUERY_GT_TYPE_MEDIA; - else -- gt_list->gt_list[id].type = DRM_XE_QUERY_GT_TYPE_MAIN; -- gt_list->gt_list[id].tile_id = gt_to_tile(gt)->id; -- gt_list->gt_list[id].gt_id = gt->info.id; -- gt_list->gt_list[id].reference_clock = gt->info.reference_clock; -+ gt_list->gt_list[iter].type = DRM_XE_QUERY_GT_TYPE_MAIN; -+ gt_list->gt_list[iter].tile_id = gt_to_tile(gt)->id; -+ gt_list->gt_list[iter].gt_id = gt->info.id; -+ gt_list->gt_list[iter].reference_clock = gt->info.reference_clock; - /* - * The mem_regions indexes in the mask below need to - * directly identify the struct -@@ -406,19 +407,21 @@ static int query_gt_list(struct xe_devic - * assumption. - */ - if (!IS_DGFX(xe)) -- gt_list->gt_list[id].near_mem_regions = 0x1; -+ gt_list->gt_list[iter].near_mem_regions = 0x1; - else -- gt_list->gt_list[id].near_mem_regions = -+ gt_list->gt_list[iter].near_mem_regions = - BIT(gt_to_tile(gt)->id) << 1; -- gt_list->gt_list[id].far_mem_regions = xe->info.mem_region_mask ^ -- gt_list->gt_list[id].near_mem_regions; -+ gt_list->gt_list[iter].far_mem_regions = xe->info.mem_region_mask ^ -+ gt_list->gt_list[iter].near_mem_regions; - -- gt_list->gt_list[id].ip_ver_major = -+ gt_list->gt_list[iter].ip_ver_major = - REG_FIELD_GET(GMD_ID_ARCH_MASK, gt->info.gmdid); -- gt_list->gt_list[id].ip_ver_minor = -+ gt_list->gt_list[iter].ip_ver_minor = - REG_FIELD_GET(GMD_ID_RELEASE_MASK, gt->info.gmdid); -- gt_list->gt_list[id].ip_ver_rev = -+ gt_list->gt_list[iter].ip_ver_rev = - REG_FIELD_GET(GMD_ID_REVID, gt->info.gmdid); -+ -+ iter++; - } - - if (copy_to_user(query_ptr, gt_list, size)) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_ring_ops.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_ring_ops.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_ring_ops.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_ring_ops.c 2025-10-22 13:53:56.487169276 -0400 -@@ -110,13 +110,14 @@ static int emit_bb_start(u64 batch_addr, - return i; - } - --static int emit_flush_invalidate(u32 *dw, int i) -+static int emit_flush_invalidate(u32 addr, u32 val, u32 *dw, int i) - { - dw[i++] = MI_FLUSH_DW | MI_INVALIDATE_TLB | MI_FLUSH_DW_OP_STOREDW | -- MI_FLUSH_IMM_DW | MI_FLUSH_DW_STORE_INDEX; -- dw[i++] = LRC_PPHWSP_FLUSH_INVAL_SCRATCH_ADDR; -- dw[i++] = 0; -+ MI_FLUSH_IMM_DW; -+ -+ dw[i++] = addr | MI_FLUSH_DW_USE_GTT; - dw[i++] = 0; -+ dw[i++] = val; - - return i; - } -@@ -397,23 +398,20 @@ static void __emit_job_gen12_render_comp - static void emit_migration_job_gen12(struct xe_sched_job *job, - struct xe_lrc *lrc, u32 seqno) - { -+ u32 saddr = xe_lrc_start_seqno_ggtt_addr(lrc); - u32 dw[MAX_JOB_SIZE_DW], i = 0; - - i = emit_copy_timestamp(lrc, dw, i); - -- i = emit_store_imm_ggtt(xe_lrc_start_seqno_ggtt_addr(lrc), -- seqno, dw, i); -+ i = emit_store_imm_ggtt(saddr, seqno, dw, i); - - dw[i++] = MI_ARB_ON_OFF | MI_ARB_DISABLE; /* Enabled again below */ - - i = emit_bb_start(job->ptrs[0].batch_addr, BIT(8), dw, i); - -- if (!IS_SRIOV_VF(gt_to_xe(job->q->gt))) { -- /* XXX: Do we need this? Leaving for now. */ -- dw[i++] = preparser_disable(true); -- i = emit_flush_invalidate(dw, i); -- dw[i++] = preparser_disable(false); -- } -+ dw[i++] = preparser_disable(true); -+ i = emit_flush_invalidate(saddr, seqno, dw, i); -+ dw[i++] = preparser_disable(false); - - i = emit_bb_start(job->ptrs[1].batch_addr, BIT(8), dw, i); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_shrinker.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_shrinker.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_shrinker.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_shrinker.c 2025-10-22 13:53:56.487169276 -0400 -@@ -53,10 +53,10 @@ xe_shrinker_mod_pages(struct xe_shrinker - write_unlock(&shrinker->lock); - } - --static s64 xe_shrinker_walk(struct xe_device *xe, -- struct ttm_operation_ctx *ctx, -- const struct xe_bo_shrink_flags flags, -- unsigned long to_scan, unsigned long *scanned) -+static s64 __xe_shrinker_walk(struct xe_device *xe, -+ struct ttm_operation_ctx *ctx, -+ const struct xe_bo_shrink_flags flags, -+ unsigned long to_scan, unsigned long *scanned) - { - unsigned int mem_type; - s64 freed = 0, lret; -@@ -86,6 +86,48 @@ static s64 xe_shrinker_walk(struct xe_de - return freed; - } - -+/* -+ * Try shrinking idle objects without writeback first, then if not sufficient, -+ * try also non-idle objects and finally if that's not sufficient either, -+ * add writeback. This avoids stalls and explicit writebacks with light or -+ * moderate memory pressure. -+ */ -+static s64 xe_shrinker_walk(struct xe_device *xe, -+ struct ttm_operation_ctx *ctx, -+ const struct xe_bo_shrink_flags flags, -+ unsigned long to_scan, unsigned long *scanned) -+{ -+ bool no_wait_gpu = true; -+ struct xe_bo_shrink_flags save_flags = flags; -+ s64 lret, freed; -+ -+ swap(no_wait_gpu, ctx->no_wait_gpu); -+ save_flags.writeback = false; -+ lret = __xe_shrinker_walk(xe, ctx, save_flags, to_scan, scanned); -+ swap(no_wait_gpu, ctx->no_wait_gpu); -+ if (lret < 0 || *scanned >= to_scan) -+ return lret; -+ -+ freed = lret; -+ if (!ctx->no_wait_gpu) { -+ lret = __xe_shrinker_walk(xe, ctx, save_flags, to_scan, scanned); -+ if (lret < 0) -+ return lret; -+ freed += lret; -+ if (*scanned >= to_scan) -+ return freed; -+ } -+ -+ if (flags.writeback) { -+ lret = __xe_shrinker_walk(xe, ctx, flags, to_scan, scanned); -+ if (lret < 0) -+ return lret; -+ freed += lret; -+ } -+ -+ return freed; -+} -+ - static unsigned long - xe_shrinker_count(struct shrinker *shrink, struct shrink_control *sc) - { -@@ -192,6 +234,7 @@ static unsigned long xe_shrinker_scan(st - runtime_pm = xe_shrinker_runtime_pm_get(shrinker, true, 0, can_backup); - - shrink_flags.purge = false; -+ - lret = xe_shrinker_walk(shrinker->xe, &ctx, shrink_flags, - nr_to_scan, &nr_scanned); - if (lret >= 0) -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_survivability_mode.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_survivability_mode.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_survivability_mode.c 2025-10-22 13:53:23.247328972 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_survivability_mode.c 2025-10-22 13:53:56.487169276 -0400 -@@ -40,6 +40,8 @@ - * - * # echo 1 > /sys/kernel/config/xe/0000:03:00.0/survivability_mode - * -+ * It is the responsibility of the user to clear the mode once firmware flash is complete. -+ * - * Refer :ref:`xe_configfs` for more details on how to use configfs - * - * Survivability mode is indicated by the below admin-only readable sysfs which provides additional -@@ -146,7 +148,6 @@ static void xe_survivability_mode_fini(v - struct pci_dev *pdev = to_pci_dev(xe->drm.dev); - struct device *dev = &pdev->dev; - -- xe_configfs_clear_survivability_mode(pdev); - sysfs_remove_file(&dev->kobj, &dev_attr_survivability_mode.attr); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_svm.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_svm.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_svm.c 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_svm.c 2025-10-22 13:53:56.487169276 -0400 -@@ -764,7 +764,7 @@ static bool xe_svm_range_needs_migrate_t - return false; - } - -- if (range_size <= SZ_64K && !supports_4K_migration(vm->xe)) { -+ if (range_size < SZ_64K && !supports_4K_migration(vm->xe)) { - drm_dbg(&vm->xe->drm, "Platform doesn't support SZ_4K range migration\n"); - return false; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_sync.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_sync.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_sync.c 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_sync.c 2025-10-22 13:53:56.487169276 -0400 -@@ -77,6 +77,7 @@ static void user_fence_worker(struct wor - { - struct xe_user_fence *ufence = container_of(w, struct xe_user_fence, worker); - -+ WRITE_ONCE(ufence->signalled, 1); - if (mmget_not_zero(ufence->mm)) { - kthread_use_mm(ufence->mm); - if (copy_to_user(ufence->addr, &ufence->value, sizeof(ufence->value))) -@@ -91,7 +92,6 @@ static void user_fence_worker(struct wor - * Wake up waiters only after updating the ufence state, allowing the UMD - * to safely reuse the same ufence without encountering -EBUSY errors. - */ -- WRITE_ONCE(ufence->signalled, 1); - wake_up_all(&ufence->xe->ufence_wq); - user_fence_put(ufence); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_tile_sysfs.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_tile_sysfs.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_tile_sysfs.c 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_tile_sysfs.c 2025-10-22 13:53:56.487169276 -0400 -@@ -44,16 +44,18 @@ int xe_tile_sysfs_init(struct xe_tile *t - kt->tile = tile; - - err = kobject_add(&kt->base, &dev->kobj, "tile%d", tile->id); -- if (err) { -- kobject_put(&kt->base); -- return err; -- } -+ if (err) -+ goto err_object; - - tile->sysfs = &kt->base; - - err = xe_vram_freq_sysfs_init(tile); - if (err) -- return err; -+ goto err_object; - - return devm_add_action_or_reset(xe->drm.dev, tile_sysfs_fini, tile); -+ -+err_object: -+ kobject_put(&kt->base); -+ return err; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_uc_fw.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_uc_fw.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_uc_fw.c 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_uc_fw.c 2025-10-22 13:53:56.487169276 -0400 -@@ -114,10 +114,10 @@ struct fw_blobs_by_type { - #define XE_GT_TYPE_ANY XE_GT_TYPE_UNINITIALIZED - - #define XE_GUC_FIRMWARE_DEFS(fw_def, mmp_ver, major_ver) \ -- fw_def(BATTLEMAGE, GT_TYPE_ANY, major_ver(xe, guc, bmg, 70, 44, 1)) \ -- fw_def(LUNARLAKE, GT_TYPE_ANY, major_ver(xe, guc, lnl, 70, 44, 1)) \ -+ fw_def(BATTLEMAGE, GT_TYPE_ANY, major_ver(xe, guc, bmg, 70, 45, 2)) \ -+ fw_def(LUNARLAKE, GT_TYPE_ANY, major_ver(xe, guc, lnl, 70, 45, 2)) \ - fw_def(METEORLAKE, GT_TYPE_ANY, major_ver(i915, guc, mtl, 70, 44, 1)) \ -- fw_def(DG2, GT_TYPE_ANY, major_ver(i915, guc, dg2, 70, 44, 1)) \ -+ fw_def(DG2, GT_TYPE_ANY, major_ver(i915, guc, dg2, 70, 45, 2)) \ - fw_def(DG1, GT_TYPE_ANY, major_ver(i915, guc, dg1, 70, 44, 1)) \ - fw_def(ALDERLAKE_N, GT_TYPE_ANY, major_ver(i915, guc, tgl, 70, 44, 1)) \ - fw_def(ALDERLAKE_P, GT_TYPE_ANY, major_ver(i915, guc, adlp, 70, 44, 1)) \ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_vm.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_vm.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_vm.c 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_vm.c 2025-10-22 13:53:56.487169276 -0400 -@@ -240,8 +240,8 @@ int xe_vm_add_compute_exec_queue(struct - - pfence = xe_preempt_fence_create(q, q->lr.context, - ++q->lr.seqno); -- if (!pfence) { -- err = -ENOMEM; -+ if (IS_ERR(pfence)) { -+ err = PTR_ERR(pfence); - goto out_fini; - } - -@@ -393,6 +393,9 @@ static int xe_gpuvm_validate(struct drm_ - list_move_tail(&gpuva_to_vma(gpuva)->combined_links.rebind, - &vm->rebind_list); - -+ if (!try_wait_for_completion(&vm->xe->pm_block)) -+ return -EAGAIN; -+ - ret = xe_bo_validate(gem_to_xe_bo(vm_bo->obj), vm, false); - if (ret) - return ret; -@@ -479,6 +482,33 @@ static int xe_preempt_work_begin(struct - return xe_vm_validate_rebind(vm, exec, vm->preempt.num_exec_queues); - } - -+static bool vm_suspend_rebind_worker(struct xe_vm *vm) -+{ -+ struct xe_device *xe = vm->xe; -+ bool ret = false; -+ -+ mutex_lock(&xe->rebind_resume_lock); -+ if (!try_wait_for_completion(&vm->xe->pm_block)) { -+ ret = true; -+ list_move_tail(&vm->preempt.pm_activate_link, &xe->rebind_resume_list); -+ } -+ mutex_unlock(&xe->rebind_resume_lock); -+ -+ return ret; -+} -+ -+/** -+ * xe_vm_resume_rebind_worker() - Resume the rebind worker. -+ * @vm: The vm whose preempt worker to resume. -+ * -+ * Resume a preempt worker that was previously suspended by -+ * vm_suspend_rebind_worker(). -+ */ -+void xe_vm_resume_rebind_worker(struct xe_vm *vm) -+{ -+ queue_work(vm->xe->ordered_wq, &vm->preempt.rebind_work); -+} -+ - static void preempt_rebind_work_func(struct work_struct *w) - { - struct xe_vm *vm = container_of(w, struct xe_vm, preempt.rebind_work); -@@ -502,6 +532,11 @@ static void preempt_rebind_work_func(str - } - - retry: -+ if (!try_wait_for_completion(&vm->xe->pm_block) && vm_suspend_rebind_worker(vm)) { -+ up_write(&vm->lock); -+ return; -+ } -+ - if (xe_vm_userptr_check_repin(vm)) { - err = xe_vm_userptr_pin(vm); - if (err) -@@ -1582,8 +1617,12 @@ static int xe_vm_create_scratch(struct x - - for (i = MAX_HUGEPTE_LEVEL; i < vm->pt_root[id]->level; i++) { - vm->scratch_pt[id][i] = xe_pt_create(vm, tile, i); -- if (IS_ERR(vm->scratch_pt[id][i])) -- return PTR_ERR(vm->scratch_pt[id][i]); -+ if (IS_ERR(vm->scratch_pt[id][i])) { -+ int err = PTR_ERR(vm->scratch_pt[id][i]); -+ -+ vm->scratch_pt[id][i] = NULL; -+ return err; -+ } - - xe_pt_populate_empty(tile, vm, vm->scratch_pt[id][i]); - } -@@ -1612,7 +1651,7 @@ static void xe_vm_free_scratch(struct xe - } - } - --struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags) -+struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags, struct xe_file *xef) - { - struct drm_gem_object *vm_resv_obj; - struct xe_vm *vm; -@@ -1633,9 +1672,10 @@ struct xe_vm *xe_vm_create(struct xe_dev - vm->xe = xe; - - vm->size = 1ull << xe->info.va_bits; -- - vm->flags = flags; - -+ if (xef) -+ vm->xef = xe_file_get(xef); - /** - * GSC VMs are kernel-owned, only used for PXP ops and can sometimes be - * manipulated under the PXP mutex. However, the PXP mutex can be taken -@@ -1681,6 +1721,7 @@ struct xe_vm *xe_vm_create(struct xe_dev - if (flags & XE_VM_FLAG_LR_MODE) { - INIT_WORK(&vm->preempt.rebind_work, preempt_rebind_work_func); - xe_pm_runtime_get_noresume(xe); -+ INIT_LIST_HEAD(&vm->preempt.pm_activate_link); - } - - if (flags & XE_VM_FLAG_FAULT_MODE) { -@@ -1766,6 +1807,20 @@ struct xe_vm *xe_vm_create(struct xe_dev - if (number_tiles > 1) - vm->composite_fence_ctx = dma_fence_context_alloc(1); - -+ if (xef && xe->info.has_asid) { -+ u32 asid; -+ -+ down_write(&xe->usm.lock); -+ err = xa_alloc_cyclic(&xe->usm.asid_to_vm, &asid, vm, -+ XA_LIMIT(1, XE_MAX_ASID - 1), -+ &xe->usm.next_asid, GFP_KERNEL); -+ up_write(&xe->usm.lock); -+ if (err < 0) -+ goto err_unlock_close; -+ -+ vm->usm.asid = asid; -+ } -+ - trace_xe_vm_create(vm); - - return vm; -@@ -1786,6 +1841,8 @@ err_no_resv: - for_each_tile(tile, xe, id) - xe_range_fence_tree_fini(&vm->rftree[id]); - ttm_lru_bulk_move_fini(&xe->ttm, &vm->lru_bulk_move); -+ if (vm->xef) -+ xe_file_put(vm->xef); - kfree(vm); - if (flags & XE_VM_FLAG_LR_MODE) - xe_pm_runtime_put(xe); -@@ -1846,8 +1903,12 @@ void xe_vm_close_and_put(struct xe_vm *v - xe_assert(xe, !vm->preempt.num_exec_queues); - - xe_vm_close(vm); -- if (xe_vm_in_preempt_fence_mode(vm)) -+ if (xe_vm_in_preempt_fence_mode(vm)) { -+ mutex_lock(&xe->rebind_resume_lock); -+ list_del_init(&vm->preempt.pm_activate_link); -+ mutex_unlock(&xe->rebind_resume_lock); - flush_work(&vm->preempt.rebind_work); -+ } - if (xe_vm_in_fault_mode(vm)) - xe_svm_close(vm); - -@@ -2031,9 +2092,8 @@ int xe_vm_create_ioctl(struct drm_device - struct xe_device *xe = to_xe_device(dev); - struct xe_file *xef = to_xe_file(file); - struct drm_xe_vm_create *args = data; -- struct xe_tile *tile; - struct xe_vm *vm; -- u32 id, asid; -+ u32 id; - int err; - u32 flags = 0; - -@@ -2069,29 +2129,10 @@ int xe_vm_create_ioctl(struct drm_device - if (args->flags & DRM_XE_VM_CREATE_FLAG_FAULT_MODE) - flags |= XE_VM_FLAG_FAULT_MODE; - -- vm = xe_vm_create(xe, flags); -+ vm = xe_vm_create(xe, flags, xef); - if (IS_ERR(vm)) - return PTR_ERR(vm); - -- if (xe->info.has_asid) { -- down_write(&xe->usm.lock); -- err = xa_alloc_cyclic(&xe->usm.asid_to_vm, &asid, vm, -- XA_LIMIT(1, XE_MAX_ASID - 1), -- &xe->usm.next_asid, GFP_KERNEL); -- up_write(&xe->usm.lock); -- if (err < 0) -- goto err_close_and_put; -- -- vm->usm.asid = asid; -- } -- -- vm->xef = xe_file_get(xef); -- -- /* Record BO memory for VM pagetable created against client */ -- for_each_tile(tile, xe, id) -- if (vm->pt_root[id]) -- xe_drm_client_add_bo(vm->xef->client, vm->pt_root[id]->bo); -- - #if IS_ENABLED(CONFIG_DRM_XE_DEBUG_MEM) - /* Warning: Security issue - never enable by default */ - args->reserved[0] = xe_bo_main_addr(vm->pt_root[0]->bo, XE_PAGE_SIZE); -@@ -3203,6 +3244,7 @@ static int vm_bind_ioctl_check_args(stru - free_bind_ops: - if (args->num_binds > 1) - kvfree(*bind_ops); -+ *bind_ops = NULL; - return err; - } - -@@ -3308,7 +3350,7 @@ int xe_vm_bind_ioctl(struct drm_device * - struct xe_exec_queue *q = NULL; - u32 num_syncs, num_ufence = 0; - struct xe_sync_entry *syncs = NULL; -- struct drm_xe_vm_bind_op *bind_ops; -+ struct drm_xe_vm_bind_op *bind_ops = NULL; - struct xe_vma_ops vops; - struct dma_fence *fence; - int err; -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_vm.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_vm.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_vm.h 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_vm.h 2025-10-22 13:53:56.487169276 -0400 -@@ -26,7 +26,7 @@ struct xe_sync_entry; - struct xe_svm_range; - struct drm_exec; - --struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags); -+struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags, struct xe_file *xef); - - struct xe_vm *xe_vm_lookup(struct xe_file *xef, u32 id); - int xe_vma_cmp_vma_cb(const void *key, const struct rb_node *node); -@@ -268,6 +268,8 @@ struct dma_fence *xe_vm_bind_kernel_bo(s - struct xe_exec_queue *q, u64 addr, - enum xe_cache_level cache_lvl); - -+void xe_vm_resume_rebind_worker(struct xe_vm *vm); -+ - /** - * xe_vm_resv() - Return's the vm's reservation object - * @vm: The vm -@@ -310,22 +312,14 @@ void xe_vm_snapshot_free(struct xe_vm_sn - * Register this task as currently making bos resident for the vm. Intended - * to avoid eviction by the same task of shared bos bound to the vm. - * Call with the vm's resv lock held. -- * -- * Return: A pin cookie that should be used for xe_vm_clear_validating(). - */ --static inline struct pin_cookie xe_vm_set_validating(struct xe_vm *vm, -- bool allow_res_evict) -+static inline void xe_vm_set_validating(struct xe_vm *vm, bool allow_res_evict) - { -- struct pin_cookie cookie = {}; -- - if (vm && !allow_res_evict) { - xe_vm_assert_held(vm); -- cookie = lockdep_pin_lock(&xe_vm_resv(vm)->lock.base); - /* Pairs with READ_ONCE in xe_vm_is_validating() */ - WRITE_ONCE(vm->validating, current); - } -- -- return cookie; - } - - /** -@@ -333,17 +327,14 @@ static inline struct pin_cookie xe_vm_se - * @vm: Pointer to the vm or NULL - * @allow_res_evict: Eviction from @vm was allowed. Must be set to the same - * value as for xe_vm_set_validation(). -- * @cookie: Cookie obtained from xe_vm_set_validating(). - * - * Register this task as currently making bos resident for the vm. Intended - * to avoid eviction by the same task of shared bos bound to the vm. - * Call with the vm's resv lock held. - */ --static inline void xe_vm_clear_validating(struct xe_vm *vm, bool allow_res_evict, -- struct pin_cookie cookie) -+static inline void xe_vm_clear_validating(struct xe_vm *vm, bool allow_res_evict) - { - if (vm && !allow_res_evict) { -- lockdep_unpin_lock(&xe_vm_resv(vm)->lock.base, cookie); - /* Pairs with READ_ONCE in xe_vm_is_validating() */ - WRITE_ONCE(vm->validating, NULL); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_vm_types.h BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_vm_types.h ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_vm_types.h 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_vm_types.h 2025-10-22 13:53:56.487169276 -0400 -@@ -286,6 +286,11 @@ struct xe_vm { - * BOs - */ - struct work_struct rebind_work; -+ /** -+ * @preempt.pm_activate_link: Link to list of rebind workers to be -+ * kicked on resume. -+ */ -+ struct list_head pm_activate_link; - } preempt; - - /** @um: unified memory state */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_vsec.c BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_vsec.c ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_vsec.c 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_vsec.c 2025-10-22 13:53:56.487169276 -0400 -@@ -24,6 +24,7 @@ - #define BMG_DEVICE_ID 0xE2F8 - - static struct intel_vsec_header bmg_telemetry = { -+ .rev = 1, - .length = 0x10, - .id = VSEC_ID_TELEMETRY, - .num_entries = 2, -@@ -32,28 +33,19 @@ static struct intel_vsec_header bmg_tele - .offset = BMG_DISCOVERY_OFFSET, - }; - --static struct intel_vsec_header bmg_punit_crashlog = { -+static struct intel_vsec_header bmg_crashlog = { -+ .rev = 1, - .length = 0x10, - .id = VSEC_ID_CRASHLOG, -- .num_entries = 1, -- .entry_size = 4, -+ .num_entries = 2, -+ .entry_size = 6, - .tbir = 0, - .offset = BMG_DISCOVERY_OFFSET + 0x60, - }; - --static struct intel_vsec_header bmg_oobmsm_crashlog = { -- .length = 0x10, -- .id = VSEC_ID_CRASHLOG, -- .num_entries = 1, -- .entry_size = 4, -- .tbir = 0, -- .offset = BMG_DISCOVERY_OFFSET + 0x78, --}; -- - static struct intel_vsec_header *bmg_capabilities[] = { - &bmg_telemetry, -- &bmg_punit_crashlog, -- &bmg_oobmsm_crashlog, -+ &bmg_crashlog, - NULL - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_wa_oob.rules BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_wa_oob.rules ---- BPI-Router-Linux-kernel/drivers/gpu/drm/xe/xe_wa_oob.rules 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/gpu/drm/xe/xe_wa_oob.rules 2025-10-22 13:53:56.487169276 -0400 -@@ -21,7 +21,8 @@ - GRAPHICS_VERSION_RANGE(1270, 1274) - MEDIA_VERSION(1300) - PLATFORM(DG2) --14018094691 GRAPHICS_VERSION(2004) -+14018094691 GRAPHICS_VERSION_RANGE(2001, 2002) -+ GRAPHICS_VERSION(2004) - 14019882105 GRAPHICS_VERSION(2004), GRAPHICS_STEP(A0, B0) - 18024947630 GRAPHICS_VERSION(2001) - GRAPHICS_VERSION(2004) -@@ -37,10 +38,10 @@ - GRAPHICS_VERSION(2004) - GRAPHICS_VERSION_RANGE(3000, 3001) - 22019338487 MEDIA_VERSION(2000) -- GRAPHICS_VERSION(2001) -+ GRAPHICS_VERSION(2001), FUNC(xe_rtp_match_not_sriov_vf) - MEDIA_VERSION(3000), MEDIA_STEP(A0, B0), FUNC(xe_rtp_match_not_sriov_vf) - 22019338487_display PLATFORM(LUNARLAKE) --16023588340 GRAPHICS_VERSION(2001) -+16023588340 GRAPHICS_VERSION(2001), FUNC(xe_rtp_match_not_sriov_vf) - 14019789679 GRAPHICS_VERSION(1255) - GRAPHICS_VERSION_RANGE(1270, 2004) - no_media_l3 MEDIA_VERSION(3000) -@@ -59,3 +60,7 @@ no_media_l3 MEDIA_VERSION(3000) - MEDIA_VERSION_RANGE(1301, 3000) - 16026508708 GRAPHICS_VERSION_RANGE(1200, 3001) - MEDIA_VERSION_RANGE(1300, 3000) -+ -+# SoC workaround - currently applies to all platforms with the following -+# primary GT GMDID -+14022085890 GRAPHICS_VERSION(2001) -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/amd-sfh-hid/amd_sfh_client.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/amd-sfh-hid/amd_sfh_client.c ---- BPI-Router-Linux-kernel/drivers/hid/amd-sfh-hid/amd_sfh_client.c 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/amd-sfh-hid/amd_sfh_client.c 2025-10-22 13:53:56.487169276 -0400 -@@ -39,8 +39,12 @@ int amd_sfh_get_report(struct hid_device - struct amdtp_hid_data *hid_data = hid->driver_data; - struct amdtp_cl_data *cli_data = hid_data->cli_data; - struct request_list *req_list = &cli_data->req_list; -+ struct amd_input_data *in_data = cli_data->in_data; -+ struct amd_mp2_dev *mp2; - int i; - -+ mp2 = container_of(in_data, struct amd_mp2_dev, in_data); -+ guard(mutex)(&mp2->lock); - for (i = 0; i < cli_data->num_hid_devices; i++) { - if (cli_data->hid_sensor_hubs[i] == hid) { - struct request_list *new = kzalloc(sizeof(*new), GFP_KERNEL); -@@ -75,6 +79,8 @@ void amd_sfh_work(struct work_struct *wo - u8 report_id, node_type; - u8 report_size = 0; - -+ mp2 = container_of(in_data, struct amd_mp2_dev, in_data); -+ guard(mutex)(&mp2->lock); - req_node = list_last_entry(&req_list->list, struct request_list, list); - list_del(&req_node->list); - current_index = req_node->current_index; -@@ -83,7 +89,6 @@ void amd_sfh_work(struct work_struct *wo - node_type = req_node->report_type; - kfree(req_node); - -- mp2 = container_of(in_data, struct amd_mp2_dev, in_data); - mp2_ops = mp2->mp2_ops; - if (node_type == HID_FEATURE_REPORT) { - report_size = mp2_ops->get_feat_rep(sensor_index, report_id, -@@ -107,6 +112,8 @@ void amd_sfh_work(struct work_struct *wo - cli_data->cur_hid_dev = current_index; - cli_data->sensor_requested_cnt[current_index] = 0; - amdtp_hid_wakeup(cli_data->hid_sensor_hubs[current_index]); -+ if (!list_empty(&req_list->list)) -+ schedule_delayed_work(&cli_data->work, 0); - } - - void amd_sfh_work_buffer(struct work_struct *work) -@@ -117,9 +124,10 @@ void amd_sfh_work_buffer(struct work_str - u8 report_size; - int i; - -+ mp2 = container_of(in_data, struct amd_mp2_dev, in_data); -+ guard(mutex)(&mp2->lock); - for (i = 0; i < cli_data->num_hid_devices; i++) { - if (cli_data->sensor_sts[i] == SENSOR_ENABLED) { -- mp2 = container_of(in_data, struct amd_mp2_dev, in_data); - report_size = mp2->mp2_ops->get_in_rep(i, cli_data->sensor_idx[i], - cli_data->report_id[i], in_data); - hid_input_report(cli_data->hid_sensor_hubs[i], HID_INPUT_REPORT, -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/amd-sfh-hid/amd_sfh_common.h BPI-Router-Linux-kernel-6.16.12/drivers/hid/amd-sfh-hid/amd_sfh_common.h ---- BPI-Router-Linux-kernel/drivers/hid/amd-sfh-hid/amd_sfh_common.h 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/amd-sfh-hid/amd_sfh_common.h 2025-10-22 13:53:56.491169257 -0400 -@@ -10,6 +10,7 @@ - #ifndef AMD_SFH_COMMON_H - #define AMD_SFH_COMMON_H - -+#include - #include - #include "amd_sfh_hid.h" - -@@ -59,6 +60,8 @@ struct amd_mp2_dev { - u32 mp2_acs; - struct sfh_dev_status dev_en; - struct work_struct work; -+ /* mp2 to protect data */ -+ struct mutex lock; - u8 init_done; - u8 rver; - }; -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c ---- BPI-Router-Linux-kernel/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c 2025-10-22 13:53:56.491169257 -0400 -@@ -462,6 +462,10 @@ static int amd_mp2_pci_probe(struct pci_ - if (!privdata->cl_data) - return -ENOMEM; - -+ rc = devm_mutex_init(&pdev->dev, &privdata->lock); -+ if (rc) -+ return rc; -+ - privdata->sfh1_1_ops = (const struct amd_sfh1_1_ops *)id->driver_data; - if (privdata->sfh1_1_ops) { - if (boot_cpu_data.x86 >= 0x1A) -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/hid-apple.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-apple.c ---- BPI-Router-Linux-kernel/drivers/hid/hid-apple.c 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-apple.c 2025-10-22 13:53:56.491169257 -0400 -@@ -890,7 +890,8 @@ static int apple_magic_backlight_init(st - backlight->brightness = report_enum->report_id_hash[APPLE_MAGIC_REPORT_ID_BRIGHTNESS]; - backlight->power = report_enum->report_id_hash[APPLE_MAGIC_REPORT_ID_POWER]; - -- if (!backlight->brightness || !backlight->power) -+ if (!backlight->brightness || backlight->brightness->maxfield < 2 || -+ !backlight->power || backlight->power->maxfield < 2) - return -ENODEV; - - backlight->cdev.name = ":white:" LED_FUNCTION_KBD_BACKLIGHT; -@@ -933,10 +934,12 @@ static int apple_probe(struct hid_device - return ret; - } - -- timer_setup(&asc->battery_timer, apple_battery_timer_tick, 0); -- mod_timer(&asc->battery_timer, -- jiffies + msecs_to_jiffies(APPLE_BATTERY_TIMEOUT_MS)); -- apple_fetch_battery(hdev); -+ if (quirks & APPLE_RDESC_BATTERY) { -+ timer_setup(&asc->battery_timer, apple_battery_timer_tick, 0); -+ mod_timer(&asc->battery_timer, -+ jiffies + msecs_to_jiffies(APPLE_BATTERY_TIMEOUT_MS)); -+ apple_fetch_battery(hdev); -+ } - - if (quirks & APPLE_BACKLIGHT_CTL) - apple_backlight_init(hdev); -@@ -950,7 +953,9 @@ static int apple_probe(struct hid_device - return 0; - - out_err: -- timer_delete_sync(&asc->battery_timer); -+ if (quirks & APPLE_RDESC_BATTERY) -+ timer_delete_sync(&asc->battery_timer); -+ - hid_hw_stop(hdev); - return ret; - } -@@ -959,7 +964,8 @@ static void apple_remove(struct hid_devi - { - struct apple_sc *asc = hid_get_drvdata(hdev); - -- timer_delete_sync(&asc->battery_timer); -+ if (asc->quirks & APPLE_RDESC_BATTERY) -+ timer_delete_sync(&asc->battery_timer); - - hid_hw_stop(hdev); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/hid-appletb-kbd.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-appletb-kbd.c ---- BPI-Router-Linux-kernel/drivers/hid/hid-appletb-kbd.c 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-appletb-kbd.c 2025-10-22 13:53:56.491169257 -0400 -@@ -430,14 +430,20 @@ static int appletb_kbd_probe(struct hid_ - ret = appletb_kbd_set_mode(kbd, appletb_tb_def_mode); - if (ret) { - dev_err_probe(dev, ret, "Failed to set touchbar mode\n"); -- goto close_hw; -+ goto unregister_handler; - } - - hid_set_drvdata(hdev, kbd); - - return 0; - -+unregister_handler: -+ input_unregister_handler(&kbd->inp_handler); - close_hw: -+ if (kbd->backlight_dev) { -+ put_device(&kbd->backlight_dev->dev); -+ timer_delete_sync(&kbd->inactivity_timer); -+ } - hid_hw_close(hdev); - stop_hw: - hid_hw_stop(hdev); -@@ -451,7 +457,10 @@ static void appletb_kbd_remove(struct hi - appletb_kbd_set_mode(kbd, APPLETB_KBD_MODE_OFF); - - input_unregister_handler(&kbd->inp_handler); -- timer_delete_sync(&kbd->inactivity_timer); -+ if (kbd->backlight_dev) { -+ put_device(&kbd->backlight_dev->dev); -+ timer_delete_sync(&kbd->inactivity_timer); -+ } - - hid_hw_close(hdev); - hid_hw_stop(hdev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/hid-asus.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-asus.c ---- BPI-Router-Linux-kernel/drivers/hid/hid-asus.c 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-asus.c 2025-10-22 13:53:56.491169257 -0400 -@@ -974,7 +974,10 @@ static int asus_input_mapping(struct hid - case 0xc4: asus_map_key_clear(KEY_KBDILLUMUP); break; - case 0xc5: asus_map_key_clear(KEY_KBDILLUMDOWN); break; - case 0xc7: asus_map_key_clear(KEY_KBDILLUMTOGGLE); break; -+ case 0x4e: asus_map_key_clear(KEY_FN_ESC); break; -+ case 0x7e: asus_map_key_clear(KEY_EMOJI_PICKER); break; - -+ case 0x8b: asus_map_key_clear(KEY_PROG1); break; /* ProArt Creator Hub key */ - case 0x6b: asus_map_key_clear(KEY_F21); break; /* ASUS touchpad toggle */ - case 0x38: asus_map_key_clear(KEY_PROG1); break; /* ROG key */ - case 0xba: asus_map_key_clear(KEY_PROG2); break; /* Fn+C ASUS Splendid */ -@@ -1213,7 +1216,13 @@ static int asus_probe(struct hid_device - return ret; - } - -- if (!drvdata->input) { -+ /* -+ * Check that input registration succeeded. Checking that -+ * HID_CLAIMED_INPUT is set prevents a UAF when all input devices -+ * were freed during registration due to no usages being mapped, -+ * leaving drvdata->input pointing to freed memory. -+ */ -+ if (!drvdata->input || !(hdev->claimed & HID_CLAIMED_INPUT)) { - hid_err(hdev, "Asus input not registered\n"); - ret = -ENOMEM; - goto err_stop_hw; -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/hid-core.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-core.c ---- BPI-Router-Linux-kernel/drivers/hid/hid-core.c 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-core.c 2025-10-22 13:53:56.491169257 -0400 -@@ -66,8 +66,12 @@ static s32 snto32(__u32 value, unsigned - - static u32 s32ton(__s32 value, unsigned int n) - { -- s32 a = value >> (n - 1); -+ s32 a; - -+ if (!value || !n) -+ return 0; -+ -+ a = value >> (n - 1); - if (a && a != -1) - return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1; - return value & ((1 << n) - 1); -@@ -659,9 +663,9 @@ static int hid_parser_main(struct hid_pa - default: - if (item->tag >= HID_MAIN_ITEM_TAG_RESERVED_MIN && - item->tag <= HID_MAIN_ITEM_TAG_RESERVED_MAX) -- hid_warn(parser->device, "reserved main item tag 0x%x\n", item->tag); -+ hid_warn_ratelimited(parser->device, "reserved main item tag 0x%x\n", item->tag); - else -- hid_warn(parser->device, "unknown main item tag 0x%x\n", item->tag); -+ hid_warn_ratelimited(parser->device, "unknown main item tag 0x%x\n", item->tag); - ret = 0; - } - -@@ -1883,9 +1887,12 @@ u8 *hid_alloc_report_buf(struct hid_repo - /* - * 7 extra bytes are necessary to achieve proper functionality - * of implement() working on 8 byte chunks -+ * 1 extra byte for the report ID if it is null (not used) so -+ * we can reserve that extra byte in the first position of the buffer -+ * when sending it to .raw_request() - */ - -- u32 len = hid_report_len(report) + 7; -+ u32 len = hid_report_len(report) + 7 + (report->id == 0); - - return kzalloc(len, flags); - } -@@ -1973,7 +1980,7 @@ static struct hid_report *hid_get_report - int __hid_request(struct hid_device *hid, struct hid_report *report, - enum hid_class_request reqtype) - { -- char *buf; -+ char *buf, *data_buf; - int ret; - u32 len; - -@@ -1981,13 +1988,19 @@ int __hid_request(struct hid_device *hid - if (!buf) - return -ENOMEM; - -+ data_buf = buf; - len = hid_report_len(report); - -+ if (report->id == 0) { -+ /* reserve the first byte for the report ID */ -+ data_buf++; -+ len++; -+ } -+ - if (reqtype == HID_REQ_SET_REPORT) -- hid_output_report(report, buf); -+ hid_output_report(report, data_buf); - -- ret = hid->ll_driver->raw_request(hid, report->id, buf, len, -- report->type, reqtype); -+ ret = hid_hw_raw_request(hid, report->id, buf, len, report->type, reqtype); - if (ret < 0) { - dbg_hid("unable to complete request: %d\n", ret); - goto out; -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/hid-cp2112.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-cp2112.c ---- BPI-Router-Linux-kernel/drivers/hid/hid-cp2112.c 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-cp2112.c 2025-10-22 13:53:56.491169257 -0400 -@@ -229,10 +229,12 @@ static int cp2112_gpio_set_unlocked(stru - ret = hid_hw_raw_request(hdev, CP2112_GPIO_SET, buf, - CP2112_GPIO_SET_LENGTH, HID_FEATURE_REPORT, - HID_REQ_SET_REPORT); -- if (ret < 0) -+ if (ret != CP2112_GPIO_SET_LENGTH) { - hid_err(hdev, "error setting GPIO values: %d\n", ret); -+ return ret < 0 ? ret : -EIO; -+ } - -- return ret; -+ return 0; - } - - static int cp2112_gpio_set(struct gpio_chip *chip, unsigned int offset, -@@ -309,9 +311,7 @@ static int cp2112_gpio_direction_output( - * Set gpio value when output direction is already set, - * as specified in AN495, Rev. 0.2, cpt. 4.4 - */ -- cp2112_gpio_set_unlocked(dev, offset, value); -- -- return 0; -+ return cp2112_gpio_set_unlocked(dev, offset, value); - } - - static int cp2112_hid_get(struct hid_device *hdev, unsigned char report_number, -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/hid-debug.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-debug.c ---- BPI-Router-Linux-kernel/drivers/hid/hid-debug.c 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-debug.c 2025-10-22 13:53:56.491169257 -0400 -@@ -3298,8 +3298,8 @@ static const char *keys[KEY_MAX + 1] = { - [BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus", - [BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "ToolDoubleTap", - [BTN_TOOL_TRIPLETAP] = "ToolTripleTap", [BTN_TOOL_QUADTAP] = "ToolQuadrupleTap", -- [BTN_GEAR_DOWN] = "WheelBtn", -- [BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok", -+ [BTN_GEAR_DOWN] = "BtnGearDown", [BTN_GEAR_UP] = "BtnGearUp", -+ [KEY_OK] = "Ok", - [KEY_SELECT] = "Select", [KEY_GOTO] = "Goto", - [KEY_CLEAR] = "Clear", [KEY_POWER2] = "Power2", - [KEY_OPTION] = "Option", [KEY_INFO] = "Info", -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/hid-elecom.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-elecom.c ---- BPI-Router-Linux-kernel/drivers/hid/hid-elecom.c 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-elecom.c 2025-10-22 13:53:56.491169257 -0400 -@@ -89,7 +89,8 @@ static const __u8 *elecom_report_fixup(s - break; - case USB_DEVICE_ID_ELECOM_M_DT1URBK: - case USB_DEVICE_ID_ELECOM_M_DT1DRBK: -- case USB_DEVICE_ID_ELECOM_M_HT1URBK: -+ case USB_DEVICE_ID_ELECOM_M_HT1URBK_010C: -+ case USB_DEVICE_ID_ELECOM_M_HT1URBK_019B: - case USB_DEVICE_ID_ELECOM_M_HT1DRBK_010D: - /* - * Report descriptor format: -@@ -100,6 +101,7 @@ static const __u8 *elecom_report_fixup(s - */ - mouse_button_fixup(hdev, rdesc, *rsize, 12, 30, 14, 20, 8); - break; -+ case USB_DEVICE_ID_ELECOM_M_DT2DRBK: - case USB_DEVICE_ID_ELECOM_M_HT1DRBK_011C: - /* - * Report descriptor format: -@@ -122,7 +124,9 @@ static const struct hid_device_id elecom - { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1URBK) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1DRBK) }, -- { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT2DRBK) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK_010C) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK_019B) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK_010D) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK_011C) }, - { } -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/hid-ids.h BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-ids.h ---- BPI-Router-Linux-kernel/drivers/hid/hid-ids.h 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-ids.h 2025-10-22 13:53:56.491169257 -0400 -@@ -312,6 +312,8 @@ - #define USB_DEVICE_ID_ASUS_AK1D 0x1125 - #define USB_DEVICE_ID_CHICONY_TOSHIBA_WT10A 0x1408 - #define USB_DEVICE_ID_CHICONY_ACER_SWITCH12 0x1421 -+#define USB_DEVICE_ID_CHICONY_HP_5MP_CAMERA 0xb824 -+#define USB_DEVICE_ID_CHICONY_HP_5MP_CAMERA2 0xb82c - - #define USB_VENDOR_ID_CHUNGHWAT 0x2247 - #define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH 0x0001 -@@ -446,7 +448,9 @@ - #define USB_DEVICE_ID_ELECOM_M_XT4DRBK 0x00fd - #define USB_DEVICE_ID_ELECOM_M_DT1URBK 0x00fe - #define USB_DEVICE_ID_ELECOM_M_DT1DRBK 0x00ff --#define USB_DEVICE_ID_ELECOM_M_HT1URBK 0x010c -+#define USB_DEVICE_ID_ELECOM_M_DT2DRBK 0x018d -+#define USB_DEVICE_ID_ELECOM_M_HT1URBK_010C 0x010c -+#define USB_DEVICE_ID_ELECOM_M_HT1URBK_019B 0x019b - #define USB_DEVICE_ID_ELECOM_M_HT1DRBK_010D 0x010d - #define USB_DEVICE_ID_ELECOM_M_HT1DRBK_011C 0x011c - -@@ -819,6 +823,7 @@ - #define USB_DEVICE_ID_LENOVO_TPPRODOCK 0x6067 - #define USB_DEVICE_ID_LENOVO_X1_COVER 0x6085 - #define USB_DEVICE_ID_LENOVO_X1_TAB 0x60a3 -+#define USB_DEVICE_ID_LENOVO_X1_TAB2 0x60a4 - #define USB_DEVICE_ID_LENOVO_X1_TAB3 0x60b5 - #define USB_DEVICE_ID_LENOVO_X12_TAB 0x60fe - #define USB_DEVICE_ID_LENOVO_X12_TAB2 0x61ae -@@ -827,6 +832,8 @@ - #define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019 0x6019 - #define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_602E 0x602e - #define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6093 0x6093 -+#define USB_DEVICE_ID_LENOVO_LEGION_GO_DUAL_DINPUT 0x6184 -+#define USB_DEVICE_ID_LENOVO_LEGION_GO2_DUAL_DINPUT 0x61ed - - #define USB_VENDOR_ID_LETSKETCH 0x6161 - #define USB_DEVICE_ID_WP9620N 0x4d15 -@@ -900,6 +907,7 @@ - #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2 0xc534 - #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1 0xc539 - #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_1 0xc53f -+#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_2 0xc543 - #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_POWERPLAY 0xc53a - #define USB_DEVICE_ID_LOGITECH_BOLT_RECEIVER 0xc548 - #define USB_DEVICE_ID_SPACETRAVELLER 0xc623 -@@ -1525,4 +1533,7 @@ - #define USB_VENDOR_ID_SIGNOTEC 0x2133 - #define USB_DEVICE_ID_SIGNOTEC_VIEWSONIC_PD1011 0x0018 - -+#define USB_VENDOR_ID_SMARTLINKTECHNOLOGY 0x4c4a -+#define USB_DEVICE_ID_SMARTLINKTECHNOLOGY_4155 0x4155 -+ - #endif -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/hid-input.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-input.c ---- BPI-Router-Linux-kernel/drivers/hid/hid-input.c 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-input.c 2025-10-22 13:53:56.491169257 -0400 -@@ -595,13 +595,33 @@ static void hidinput_cleanup_battery(str - dev->battery = NULL; - } - --static void hidinput_update_battery(struct hid_device *dev, int value) -+static bool hidinput_update_battery_charge_status(struct hid_device *dev, -+ unsigned int usage, int value) -+{ -+ switch (usage) { -+ case HID_BAT_CHARGING: -+ dev->battery_charge_status = value ? -+ POWER_SUPPLY_STATUS_CHARGING : -+ POWER_SUPPLY_STATUS_DISCHARGING; -+ return true; -+ } -+ -+ return false; -+} -+ -+static void hidinput_update_battery(struct hid_device *dev, unsigned int usage, -+ int value) - { - int capacity; - - if (!dev->battery) - return; - -+ if (hidinput_update_battery_charge_status(dev, usage, value)) { -+ power_supply_changed(dev->battery); -+ return; -+ } -+ - if (value == 0 || value < dev->battery_min || value > dev->battery_max) - return; - -@@ -617,20 +637,6 @@ static void hidinput_update_battery(stru - power_supply_changed(dev->battery); - } - } -- --static bool hidinput_set_battery_charge_status(struct hid_device *dev, -- unsigned int usage, int value) --{ -- switch (usage) { -- case HID_BAT_CHARGING: -- dev->battery_charge_status = value ? -- POWER_SUPPLY_STATUS_CHARGING : -- POWER_SUPPLY_STATUS_DISCHARGING; -- return true; -- } -- -- return false; --} - #else /* !CONFIG_HID_BATTERY_STRENGTH */ - static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type, - struct hid_field *field, bool is_percentage) -@@ -642,14 +648,9 @@ static void hidinput_cleanup_battery(str - { - } - --static void hidinput_update_battery(struct hid_device *dev, int value) --{ --} -- --static bool hidinput_set_battery_charge_status(struct hid_device *dev, -- unsigned int usage, int value) -+static void hidinput_update_battery(struct hid_device *dev, unsigned int usage, -+ int value) - { -- return false; - } - #endif /* CONFIG_HID_BATTERY_STRENGTH */ - -@@ -1515,11 +1516,7 @@ void hidinput_hid_event(struct hid_devic - return; - - if (usage->type == EV_PWR) { -- bool handled = hidinput_set_battery_charge_status(hid, usage->hid, value); -- -- if (!handled) -- hidinput_update_battery(hid, value); -- -+ hidinput_update_battery(hid, usage->hid, value); - return; - } - -@@ -2343,7 +2340,7 @@ int hidinput_connect(struct hid_device * - } - - if (list_empty(&hid->inputs)) { -- hid_err(hid, "No inputs registered, leaving\n"); -+ hid_dbg(hid, "No inputs registered, leaving\n"); - goto out_unwind; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/hid-input-test.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-input-test.c ---- BPI-Router-Linux-kernel/drivers/hid/hid-input-test.c 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-input-test.c 2025-10-22 13:53:56.491169257 -0400 -@@ -7,7 +7,7 @@ - - #include - --static void hid_test_input_set_battery_charge_status(struct kunit *test) -+static void hid_test_input_update_battery_charge_status(struct kunit *test) - { - struct hid_device *dev; - bool handled; -@@ -15,15 +15,15 @@ static void hid_test_input_set_battery_c - dev = kunit_kzalloc(test, sizeof(*dev), GFP_KERNEL); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); - -- handled = hidinput_set_battery_charge_status(dev, HID_DG_HEIGHT, 0); -+ handled = hidinput_update_battery_charge_status(dev, HID_DG_HEIGHT, 0); - KUNIT_EXPECT_FALSE(test, handled); - KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_UNKNOWN); - -- handled = hidinput_set_battery_charge_status(dev, HID_BAT_CHARGING, 0); -+ handled = hidinput_update_battery_charge_status(dev, HID_BAT_CHARGING, 0); - KUNIT_EXPECT_TRUE(test, handled); - KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_DISCHARGING); - -- handled = hidinput_set_battery_charge_status(dev, HID_BAT_CHARGING, 1); -+ handled = hidinput_update_battery_charge_status(dev, HID_BAT_CHARGING, 1); - KUNIT_EXPECT_TRUE(test, handled); - KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_CHARGING); - } -@@ -63,7 +63,7 @@ static void hid_test_input_get_battery_p - } - - static struct kunit_case hid_input_tests[] = { -- KUNIT_CASE(hid_test_input_set_battery_charge_status), -+ KUNIT_CASE(hid_test_input_update_battery_charge_status), - KUNIT_CASE(hid_test_input_get_battery_property), - { } - }; -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/hid-lenovo.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-lenovo.c ---- BPI-Router-Linux-kernel/drivers/hid/hid-lenovo.c 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-lenovo.c 2025-10-22 13:53:56.491169257 -0400 -@@ -492,6 +492,7 @@ static int lenovo_input_mapping(struct h - case USB_DEVICE_ID_LENOVO_X12_TAB: - case USB_DEVICE_ID_LENOVO_X12_TAB2: - case USB_DEVICE_ID_LENOVO_X1_TAB: -+ case USB_DEVICE_ID_LENOVO_X1_TAB2: - case USB_DEVICE_ID_LENOVO_X1_TAB3: - return lenovo_input_mapping_x1_tab_kbd(hdev, hi, field, usage, bit, max); - default: -@@ -548,11 +549,14 @@ static void lenovo_features_set_cptkbd(s - - /* - * Tell the keyboard a driver understands it, and turn F7, F9, F11 into -- * regular keys -+ * regular keys (Compact only) - */ -- ret = lenovo_send_cmd_cptkbd(hdev, 0x01, 0x03); -- if (ret) -- hid_warn(hdev, "Failed to switch F7/9/11 mode: %d\n", ret); -+ if (hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD || -+ hdev->product == USB_DEVICE_ID_LENOVO_CBTKBD) { -+ ret = lenovo_send_cmd_cptkbd(hdev, 0x01, 0x03); -+ if (ret) -+ hid_warn(hdev, "Failed to switch F7/9/11 mode: %d\n", ret); -+ } - - /* Switch middle button to native mode */ - ret = lenovo_send_cmd_cptkbd(hdev, 0x09, 0x01); -@@ -605,6 +609,7 @@ static ssize_t attr_fn_lock_store(struct - case USB_DEVICE_ID_LENOVO_X12_TAB2: - case USB_DEVICE_ID_LENOVO_TP10UBKBD: - case USB_DEVICE_ID_LENOVO_X1_TAB: -+ case USB_DEVICE_ID_LENOVO_X1_TAB2: - case USB_DEVICE_ID_LENOVO_X1_TAB3: - ret = lenovo_led_set_tp10ubkbd(hdev, TP10UBKBD_FN_LOCK_LED, value); - if (ret) -@@ -861,6 +866,7 @@ static int lenovo_event(struct hid_devic - case USB_DEVICE_ID_LENOVO_X12_TAB2: - case USB_DEVICE_ID_LENOVO_TP10UBKBD: - case USB_DEVICE_ID_LENOVO_X1_TAB: -+ case USB_DEVICE_ID_LENOVO_X1_TAB2: - case USB_DEVICE_ID_LENOVO_X1_TAB3: - return lenovo_event_tp10ubkbd(hdev, field, usage, value); - default: -@@ -1144,6 +1150,7 @@ static int lenovo_led_brightness_set(str - case USB_DEVICE_ID_LENOVO_X12_TAB2: - case USB_DEVICE_ID_LENOVO_TP10UBKBD: - case USB_DEVICE_ID_LENOVO_X1_TAB: -+ case USB_DEVICE_ID_LENOVO_X1_TAB2: - case USB_DEVICE_ID_LENOVO_X1_TAB3: - ret = lenovo_led_set_tp10ubkbd(hdev, tp10ubkbd_led[led_nr], value); - break; -@@ -1384,6 +1391,7 @@ static int lenovo_probe(struct hid_devic - case USB_DEVICE_ID_LENOVO_X12_TAB2: - case USB_DEVICE_ID_LENOVO_TP10UBKBD: - case USB_DEVICE_ID_LENOVO_X1_TAB: -+ case USB_DEVICE_ID_LENOVO_X1_TAB2: - case USB_DEVICE_ID_LENOVO_X1_TAB3: - ret = lenovo_probe_tp10ubkbd(hdev); - break; -@@ -1473,6 +1481,7 @@ static void lenovo_remove(struct hid_dev - case USB_DEVICE_ID_LENOVO_X12_TAB2: - case USB_DEVICE_ID_LENOVO_TP10UBKBD: - case USB_DEVICE_ID_LENOVO_X1_TAB: -+ case USB_DEVICE_ID_LENOVO_X1_TAB2: - case USB_DEVICE_ID_LENOVO_X1_TAB3: - lenovo_remove_tp10ubkbd(hdev); - break; -@@ -1524,6 +1533,8 @@ static const struct hid_device_id lenovo - { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, - USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X1_TAB) }, - { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, -+ USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X1_TAB2) }, -+ { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, - USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X1_TAB3) }, - { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, - USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X12_TAB) }, -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/hid-logitech-dj.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-logitech-dj.c ---- BPI-Router-Linux-kernel/drivers/hid/hid-logitech-dj.c 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-logitech-dj.c 2025-10-22 13:53:56.491169257 -0400 -@@ -1983,6 +1983,10 @@ static const struct hid_device_id logi_d - HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, - USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_1), - .driver_data = recvr_type_gaming_hidpp}, -+ { /* Logitech lightspeed receiver (0xc543) */ -+ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, -+ USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_2), -+ .driver_data = recvr_type_gaming_hidpp}, - - { /* Logitech 27 MHz HID++ 1.0 receiver (0xc513) */ - HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER), -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/hid-logitech-hidpp.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-logitech-hidpp.c ---- BPI-Router-Linux-kernel/drivers/hid/hid-logitech-hidpp.c 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-logitech-hidpp.c 2025-10-22 13:53:56.491169257 -0400 -@@ -4596,6 +4596,8 @@ static const struct hid_device_id hidpp_ - HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC094) }, - { /* Logitech G Pro X Superlight 2 Gaming Mouse over USB */ - HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC09b) }, -+ { /* Logitech G PRO 2 LIGHTSPEED Wireless Mouse over USB */ -+ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xc09a) }, - - { /* G935 Gaming Headset */ - HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0x0a87), -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/hid-magicmouse.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-magicmouse.c ---- BPI-Router-Linux-kernel/drivers/hid/hid-magicmouse.c 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-magicmouse.c 2025-10-22 13:53:56.491169257 -0400 -@@ -791,17 +791,31 @@ static void magicmouse_enable_mt_work(st - hid_err(msc->hdev, "unable to request touch data (%d)\n", ret); - } - -+static bool is_usb_magicmouse2(__u32 vendor, __u32 product) -+{ -+ if (vendor != USB_VENDOR_ID_APPLE) -+ return false; -+ return product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 || -+ product == USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC; -+} -+ -+static bool is_usb_magictrackpad2(__u32 vendor, __u32 product) -+{ -+ if (vendor != USB_VENDOR_ID_APPLE) -+ return false; -+ return product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 || -+ product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC; -+} -+ - static int magicmouse_fetch_battery(struct hid_device *hdev) - { - #ifdef CONFIG_HID_BATTERY_STRENGTH - struct hid_report_enum *report_enum; - struct hid_report *report; - -- if (!hdev->battery || hdev->vendor != USB_VENDOR_ID_APPLE || -- (hdev->product != USB_DEVICE_ID_APPLE_MAGICMOUSE2 && -- hdev->product != USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC && -- hdev->product != USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 && -- hdev->product != USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC)) -+ if (!hdev->battery || -+ (!is_usb_magicmouse2(hdev->vendor, hdev->product) && -+ !is_usb_magictrackpad2(hdev->vendor, hdev->product))) - return -1; - - report_enum = &hdev->report_enum[hdev->battery_report_type]; -@@ -863,17 +877,17 @@ static int magicmouse_probe(struct hid_d - return ret; - } - -- timer_setup(&msc->battery_timer, magicmouse_battery_timer_tick, 0); -- mod_timer(&msc->battery_timer, -- jiffies + msecs_to_jiffies(USB_BATTERY_TIMEOUT_MS)); -- magicmouse_fetch_battery(hdev); -- -- if (id->vendor == USB_VENDOR_ID_APPLE && -- (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 || -- id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC || -- ((id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 || -- id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) && -- hdev->type != HID_TYPE_USBMOUSE))) -+ if (is_usb_magicmouse2(id->vendor, id->product) || -+ is_usb_magictrackpad2(id->vendor, id->product)) { -+ timer_setup(&msc->battery_timer, magicmouse_battery_timer_tick, 0); -+ mod_timer(&msc->battery_timer, -+ jiffies + msecs_to_jiffies(USB_BATTERY_TIMEOUT_MS)); -+ magicmouse_fetch_battery(hdev); -+ } -+ -+ if (is_usb_magicmouse2(id->vendor, id->product) || -+ (is_usb_magictrackpad2(id->vendor, id->product) && -+ hdev->type != HID_TYPE_USBMOUSE)) - return 0; - - if (!msc->input) { -@@ -936,7 +950,10 @@ static int magicmouse_probe(struct hid_d - - return 0; - err_stop_hw: -- timer_delete_sync(&msc->battery_timer); -+ if (is_usb_magicmouse2(id->vendor, id->product) || -+ is_usb_magictrackpad2(id->vendor, id->product)) -+ timer_delete_sync(&msc->battery_timer); -+ - hid_hw_stop(hdev); - return ret; - } -@@ -947,7 +964,9 @@ static void magicmouse_remove(struct hid - - if (msc) { - cancel_delayed_work_sync(&msc->work); -- timer_delete_sync(&msc->battery_timer); -+ if (is_usb_magicmouse2(hdev->vendor, hdev->product) || -+ is_usb_magictrackpad2(hdev->vendor, hdev->product)) -+ timer_delete_sync(&msc->battery_timer); - } - - hid_hw_stop(hdev); -@@ -964,11 +983,8 @@ static const __u8 *magicmouse_report_fix - * 0x05, 0x01, // Usage Page (Generic Desktop) 0 - * 0x09, 0x02, // Usage (Mouse) 2 - */ -- if (hdev->vendor == USB_VENDOR_ID_APPLE && -- (hdev->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 || -- hdev->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC || -- hdev->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 || -- hdev->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) && -+ if ((is_usb_magicmouse2(hdev->vendor, hdev->product) || -+ is_usb_magictrackpad2(hdev->vendor, hdev->product)) && - *rsize == 83 && rdesc[46] == 0x84 && rdesc[58] == 0x85) { - hid_info(hdev, - "fixing up magicmouse battery report descriptor\n"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/hid-mcp2221.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-mcp2221.c ---- BPI-Router-Linux-kernel/drivers/hid/hid-mcp2221.c 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-mcp2221.c 2025-10-22 13:53:56.491169257 -0400 -@@ -816,6 +816,10 @@ static int mcp2221_raw_event(struct hid_ - } - if (data[2] == MCP2221_I2C_READ_COMPL || - data[2] == MCP2221_I2C_READ_PARTIAL) { -+ if (!mcp->rxbuf || mcp->rxbuf_idx < 0 || data[3] > 60) { -+ mcp->status = -EINVAL; -+ break; -+ } - buf = mcp->rxbuf; - memcpy(&buf[mcp->rxbuf_idx], &data[4], data[3]); - mcp->rxbuf_idx = mcp->rxbuf_idx + data[3]; -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/hid-multitouch.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-multitouch.c ---- BPI-Router-Linux-kernel/drivers/hid/hid-multitouch.c 2025-10-22 13:53:23.251328952 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-multitouch.c 2025-10-22 13:53:56.491169257 -0400 -@@ -73,6 +73,7 @@ MODULE_LICENSE("GPL"); - #define MT_QUIRK_FORCE_MULTI_INPUT BIT(20) - #define MT_QUIRK_DISABLE_WAKEUP BIT(21) - #define MT_QUIRK_ORIENTATION_INVERT BIT(22) -+#define MT_QUIRK_APPLE_TOUCHBAR BIT(23) - - #define MT_INPUTMODE_TOUCHSCREEN 0x02 - #define MT_INPUTMODE_TOUCHPAD 0x03 -@@ -625,6 +626,7 @@ static struct mt_application *mt_find_ap - static struct mt_report_data *mt_allocate_report_data(struct mt_device *td, - struct hid_report *report) - { -+ struct mt_class *cls = &td->mtclass; - struct mt_report_data *rdata; - struct hid_field *field; - int r, n; -@@ -649,7 +651,11 @@ static struct mt_report_data *mt_allocat - - if (field->logical == HID_DG_FINGER || td->hdev->group != HID_GROUP_MULTITOUCH_WIN_8) { - for (n = 0; n < field->report_count; n++) { -- if (field->usage[n].hid == HID_DG_CONTACTID) { -+ unsigned int hid = field->usage[n].hid; -+ -+ if (hid == HID_DG_CONTACTID || -+ (cls->quirks & MT_QUIRK_APPLE_TOUCHBAR && -+ hid == HID_DG_TRANSDUCER_INDEX)) { - rdata->is_mt_collection = true; - break; - } -@@ -821,12 +827,31 @@ static int mt_touch_input_mapping(struct - - MT_STORE_FIELD(confidence_state); - return 1; -+ case HID_DG_TOUCH: -+ /* -+ * Legacy devices use TIPSWITCH and not TOUCH. -+ * One special case here is of the Apple Touch Bars. -+ * In these devices, the tip state is contained in -+ * fields with the HID_DG_TOUCH usage. -+ * Let's just ignore this field for other devices. -+ */ -+ if (!(cls->quirks & MT_QUIRK_APPLE_TOUCHBAR)) -+ return -1; -+ fallthrough; - case HID_DG_TIPSWITCH: - if (field->application != HID_GD_SYSTEM_MULTIAXIS) - input_set_capability(hi->input, - EV_KEY, BTN_TOUCH); - MT_STORE_FIELD(tip_state); - return 1; -+ case HID_DG_TRANSDUCER_INDEX: -+ /* -+ * Contact ID in case of Apple Touch Bars is contained -+ * in fields with HID_DG_TRANSDUCER_INDEX usage. -+ */ -+ if (!(cls->quirks & MT_QUIRK_APPLE_TOUCHBAR)) -+ return 0; -+ fallthrough; - case HID_DG_CONTACTID: - MT_STORE_FIELD(contactid); - app->touches_by_report++; -@@ -883,10 +908,6 @@ static int mt_touch_input_mapping(struct - case HID_DG_CONTACTMAX: - /* contact max are global to the report */ - return -1; -- case HID_DG_TOUCH: -- /* Legacy devices use TIPSWITCH and not TOUCH. -- * Let's just ignore this field. */ -- return -1; - } - /* let hid-input decide for the others */ - return 0; -@@ -1314,6 +1335,13 @@ static int mt_touch_input_configured(str - struct input_dev *input = hi->input; - int ret; - -+ /* -+ * HID_DG_CONTACTMAX field is not present on Apple Touch Bars, -+ * but the maximum contact count is greater than the default. -+ */ -+ if (cls->quirks & MT_QUIRK_APPLE_TOUCHBAR && cls->maxcontacts) -+ td->maxcontacts = cls->maxcontacts; -+ - if (!td->maxcontacts) - td->maxcontacts = MT_DEFAULT_MAXCONTACT; - -@@ -1321,6 +1349,13 @@ static int mt_touch_input_configured(str - if (td->serial_maybe) - mt_post_parse_default_settings(td, app); - -+ /* -+ * The application for Apple Touch Bars is HID_DG_TOUCHPAD, -+ * but these devices are direct. -+ */ -+ if (cls->quirks & MT_QUIRK_APPLE_TOUCHBAR) -+ app->mt_flags |= INPUT_MT_DIRECT; -+ - if (cls->is_indirect) - app->mt_flags |= INPUT_MT_POINTER; - -@@ -1461,6 +1496,14 @@ static const __u8 *mt_report_fixup(struc - if (hdev->vendor == I2C_VENDOR_ID_GOODIX && - (hdev->product == I2C_DEVICE_ID_GOODIX_01E8 || - hdev->product == I2C_DEVICE_ID_GOODIX_01E9)) { -+ if (*size < 608) { -+ dev_info( -+ &hdev->dev, -+ "GT7868Q fixup: report descriptor is only %u bytes, skipping\n", -+ *size); -+ return rdesc; -+ } -+ - if (rdesc[607] == 0x15) { - rdesc[607] = 0x25; - dev_info( -@@ -2132,12 +2175,18 @@ static const struct hid_device_id mt_dev - HID_DEVICE(BUS_I2C, HID_GROUP_GENERIC, - USB_VENDOR_ID_LG, I2C_DEVICE_ID_LG_7010) }, - -- /* Lenovo X1 TAB Gen 2 */ -+ /* Lenovo X1 TAB Gen 1 */ - { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT, - HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8, - USB_VENDOR_ID_LENOVO, - USB_DEVICE_ID_LENOVO_X1_TAB) }, - -+ /* Lenovo X1 TAB Gen 2 */ -+ { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT, -+ HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8, -+ USB_VENDOR_ID_LENOVO, -+ USB_DEVICE_ID_LENOVO_X1_TAB2) }, -+ - /* Lenovo X1 TAB Gen 3 */ - { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT, - HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8, -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/hid-nintendo.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-nintendo.c ---- BPI-Router-Linux-kernel/drivers/hid/hid-nintendo.c 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-nintendo.c 2025-10-22 13:53:56.491169257 -0400 -@@ -308,6 +308,7 @@ enum joycon_ctlr_state { - JOYCON_CTLR_STATE_INIT, - JOYCON_CTLR_STATE_READ, - JOYCON_CTLR_STATE_REMOVED, -+ JOYCON_CTLR_STATE_SUSPENDED, - }; - - /* Controller type received as part of device info */ -@@ -2750,14 +2751,46 @@ static void nintendo_hid_remove(struct h - - static int nintendo_hid_resume(struct hid_device *hdev) - { -- int ret = joycon_init(hdev); -+ struct joycon_ctlr *ctlr = hid_get_drvdata(hdev); -+ int ret; -+ -+ hid_dbg(hdev, "resume\n"); -+ if (!joycon_using_usb(ctlr)) { -+ hid_dbg(hdev, "no-op resume for bt ctlr\n"); -+ ctlr->ctlr_state = JOYCON_CTLR_STATE_READ; -+ return 0; -+ } - -+ ret = joycon_init(hdev); - if (ret) -- hid_err(hdev, "Failed to restore controller after resume"); -+ hid_err(hdev, -+ "Failed to restore controller after resume: %d\n", -+ ret); -+ else -+ ctlr->ctlr_state = JOYCON_CTLR_STATE_READ; - - return ret; - } - -+static int nintendo_hid_suspend(struct hid_device *hdev, pm_message_t message) -+{ -+ struct joycon_ctlr *ctlr = hid_get_drvdata(hdev); -+ -+ hid_dbg(hdev, "suspend: %d\n", message.event); -+ /* -+ * Avoid any blocking loops in suspend/resume transitions. -+ * -+ * joycon_enforce_subcmd_rate() can result in repeated retries if for -+ * whatever reason the controller stops providing input reports. -+ * -+ * This has been observed with bluetooth controllers which lose -+ * connectivity prior to suspend (but not long enough to result in -+ * complete disconnection). -+ */ -+ ctlr->ctlr_state = JOYCON_CTLR_STATE_SUSPENDED; -+ return 0; -+} -+ - #endif - - static const struct hid_device_id nintendo_hid_devices[] = { -@@ -2796,6 +2829,7 @@ static struct hid_driver nintendo_hid_dr - - #ifdef CONFIG_PM - .resume = nintendo_hid_resume, -+ .suspend = nintendo_hid_suspend, - #endif - }; - static int __init nintendo_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/hid-ntrig.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-ntrig.c ---- BPI-Router-Linux-kernel/drivers/hid/hid-ntrig.c 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-ntrig.c 2025-10-22 13:53:56.491169257 -0400 -@@ -144,6 +144,9 @@ static void ntrig_report_version(struct - struct usb_device *usb_dev = hid_to_usb_dev(hdev); - unsigned char *data = kmalloc(8, GFP_KERNEL); - -+ if (!hid_is_usb(hdev)) -+ return; -+ - if (!data) - goto err_free; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/hid-quirks.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-quirks.c ---- BPI-Router-Linux-kernel/drivers/hid/hid-quirks.c 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/hid-quirks.c 2025-10-22 13:53:56.491169257 -0400 -@@ -124,6 +124,8 @@ static const struct hid_device_id hid_qu - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2), HID_QUIRK_MULTI_INPUT }, - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_T609A), HID_QUIRK_MULTI_INPUT }, - { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_ODDOR_HANDBRAKE), HID_QUIRK_ALWAYS_POLL }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_LEGION_GO_DUAL_DINPUT), HID_QUIRK_MULTI_INPUT }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_LEGION_GO2_DUAL_DINPUT), HID_QUIRK_MULTI_INPUT }, - { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_OPTICAL_USB_MOUSE_600E), HID_QUIRK_ALWAYS_POLL }, - { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D), HID_QUIRK_ALWAYS_POLL }, - { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019), HID_QUIRK_ALWAYS_POLL }, -@@ -410,7 +412,9 @@ static const struct hid_device_id hid_ha - { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_XT4DRBK) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1URBK) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT1DRBK) }, -- { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_DT2DRBK) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK_010C) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1URBK_019B) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK_010D) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_M_HT1DRBK_011C) }, - #endif -@@ -757,6 +761,8 @@ static const struct hid_device_id hid_ig - { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) }, - { HID_USB_DEVICE(USB_VENDOR_ID_AXENTIA, USB_DEVICE_ID_AXENTIA_FM_RADIO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_HP_5MP_CAMERA) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_HP_5MP_CAMERA2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CIDC, 0x0103) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI4713) }, -@@ -904,6 +910,7 @@ static const struct hid_device_id hid_ig - #endif - { HID_USB_DEVICE(USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K) }, - { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_HP_5MP_CAMERA_5473) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_SMARTLINKTECHNOLOGY, USB_DEVICE_ID_SMARTLINKTECHNOLOGY_4155) }, - { } - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/intel-ish-hid/ipc/hw-ish.h BPI-Router-Linux-kernel-6.16.12/drivers/hid/intel-ish-hid/ipc/hw-ish.h ---- BPI-Router-Linux-kernel/drivers/hid/intel-ish-hid/ipc/hw-ish.h 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/intel-ish-hid/ipc/hw-ish.h 2025-10-22 13:53:56.491169257 -0400 -@@ -38,6 +38,7 @@ - #define PCI_DEVICE_ID_INTEL_ISH_LNL_M 0xA845 - #define PCI_DEVICE_ID_INTEL_ISH_PTL_H 0xE345 - #define PCI_DEVICE_ID_INTEL_ISH_PTL_P 0xE445 -+#define PCI_DEVICE_ID_INTEL_ISH_WCL 0x4D45 - - #define REVISION_ID_CHT_A0 0x6 - #define REVISION_ID_CHT_Ax_SI 0x0 -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/intel-ish-hid/ipc/pci-ish.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/intel-ish-hid/ipc/pci-ish.c ---- BPI-Router-Linux-kernel/drivers/hid/intel-ish-hid/ipc/pci-ish.c 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/intel-ish-hid/ipc/pci-ish.c 2025-10-22 13:53:56.491169257 -0400 -@@ -27,10 +27,12 @@ enum ishtp_driver_data_index { - ISHTP_DRIVER_DATA_NONE, - ISHTP_DRIVER_DATA_LNL_M, - ISHTP_DRIVER_DATA_PTL, -+ ISHTP_DRIVER_DATA_WCL, - }; - - #define ISH_FW_GEN_LNL_M "lnlm" - #define ISH_FW_GEN_PTL "ptl" -+#define ISH_FW_GEN_WCL "wcl" - - #define ISH_FIRMWARE_PATH(gen) "intel/ish/ish_" gen ".bin" - #define ISH_FIRMWARE_PATH_ALL "intel/ish/ish_*.bin" -@@ -42,6 +44,9 @@ static struct ishtp_driver_data ishtp_dr - [ISHTP_DRIVER_DATA_PTL] = { - .fw_generation = ISH_FW_GEN_PTL, - }, -+ [ISHTP_DRIVER_DATA_WCL] = { -+ .fw_generation = ISH_FW_GEN_WCL, -+ }, - }; - - static const struct pci_device_id ish_pci_tbl[] = { -@@ -67,9 +72,10 @@ static const struct pci_device_id ish_pc - {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_MTL_P)}, - {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_ARL_H)}, - {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_ARL_S)}, -- {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_LNL_M), .driver_data = ISHTP_DRIVER_DATA_LNL_M}, -- {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_PTL_H), .driver_data = ISHTP_DRIVER_DATA_PTL}, -- {PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ISH_PTL_P), .driver_data = ISHTP_DRIVER_DATA_PTL}, -+ {PCI_DEVICE_DATA(INTEL, ISH_LNL_M, ISHTP_DRIVER_DATA_LNL_M)}, -+ {PCI_DEVICE_DATA(INTEL, ISH_PTL_H, ISHTP_DRIVER_DATA_PTL)}, -+ {PCI_DEVICE_DATA(INTEL, ISH_PTL_P, ISHTP_DRIVER_DATA_PTL)}, -+ {PCI_DEVICE_DATA(INTEL, ISH_WCL, ISHTP_DRIVER_DATA_WCL)}, - {} - }; - MODULE_DEVICE_TABLE(pci, ish_pci_tbl); -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c ---- BPI-Router-Linux-kernel/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c 2025-10-22 13:53:56.491169257 -0400 -@@ -406,6 +406,7 @@ static struct quicki2c_device *quicki2c_ - */ - static void quicki2c_dev_deinit(struct quicki2c_device *qcdev) - { -+ thc_interrupt_quiesce(qcdev->thc_hw, true); - thc_interrupt_enable(qcdev->thc_hw, false); - thc_ltr_unconfig(qcdev->thc_hw); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h BPI-Router-Linux-kernel-6.16.12/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h ---- BPI-Router-Linux-kernel/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h 2025-10-22 13:53:56.491169257 -0400 -@@ -71,6 +71,7 @@ struct quicki2c_subip_acpi_parameter { - u16 device_address; - u64 connection_speed; - u8 addressing_mode; -+ u8 reserved; - } __packed; - - /** -@@ -120,6 +121,7 @@ struct quicki2c_subip_acpi_config { - u64 HMTD; - u64 HMRD; - u64 HMSL; -+ u8 reserved; - }; - - struct device; -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c ---- BPI-Router-Linux-kernel/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c 2025-10-22 13:53:56.491169257 -0400 -@@ -4,6 +4,7 @@ - #include - #include - #include -+#include - - #include "intel-thc-dev.h" - #include "intel-thc-dma.h" -@@ -200,6 +201,9 @@ int quicki2c_set_report(struct quicki2c_ - - int quicki2c_reset(struct quicki2c_device *qcdev) - { -+ u16 input_reg = le16_to_cpu(qcdev->dev_desc.input_reg); -+ size_t read_len = HIDI2C_LENGTH_LEN; -+ u32 prd_len = read_len; - int ret; - - qcdev->reset_ack = false; -@@ -213,12 +217,32 @@ int quicki2c_reset(struct quicki2c_devic - - ret = wait_event_interruptible_timeout(qcdev->reset_ack_wq, qcdev->reset_ack, - HIDI2C_RESET_TIMEOUT * HZ); -- if (ret <= 0 || !qcdev->reset_ack) { -+ if (qcdev->reset_ack) -+ return 0; -+ -+ /* -+ * Manually read reset response if it wasn't received, in case reset interrupt -+ * was missed by touch device or THC hardware. -+ */ -+ ret = thc_tic_pio_read(qcdev->thc_hw, input_reg, read_len, &prd_len, -+ (u32 *)qcdev->input_buf); -+ if (ret) { -+ dev_err_once(qcdev->dev, "Read Reset Response failed, ret %d\n", ret); -+ return ret; -+ } -+ -+ /* -+ * Check response packet length, it's first 16 bits of packet. -+ * If response packet length is zero, it's reset response, otherwise not. -+ */ -+ if (get_unaligned_le16(qcdev->input_buf)) { - dev_err_once(qcdev->dev, - "Wait reset response timed out ret:%d timeout:%ds\n", - ret, HIDI2C_RESET_TIMEOUT); - return -ETIMEDOUT; - } - -+ qcdev->reset_ack = true; -+ - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c ---- BPI-Router-Linux-kernel/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c 2025-10-22 13:53:56.491169257 -0400 -@@ -961,6 +961,8 @@ static const struct pci_device_id quicks - {PCI_DEVICE_DATA(INTEL, THC_PTL_H_DEVICE_ID_SPI_PORT2, &ptl), }, - {PCI_DEVICE_DATA(INTEL, THC_PTL_U_DEVICE_ID_SPI_PORT1, &ptl), }, - {PCI_DEVICE_DATA(INTEL, THC_PTL_U_DEVICE_ID_SPI_PORT2, &ptl), }, -+ {PCI_DEVICE_DATA(INTEL, THC_WCL_DEVICE_ID_SPI_PORT1, &ptl), }, -+ {PCI_DEVICE_DATA(INTEL, THC_WCL_DEVICE_ID_SPI_PORT2, &ptl), }, - {} - }; - MODULE_DEVICE_TABLE(pci, quickspi_pci_tbl); -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-dev.h BPI-Router-Linux-kernel-6.16.12/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-dev.h ---- BPI-Router-Linux-kernel/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-dev.h 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-dev.h 2025-10-22 13:53:56.491169257 -0400 -@@ -19,6 +19,8 @@ - #define PCI_DEVICE_ID_INTEL_THC_PTL_H_DEVICE_ID_SPI_PORT2 0xE34B - #define PCI_DEVICE_ID_INTEL_THC_PTL_U_DEVICE_ID_SPI_PORT1 0xE449 - #define PCI_DEVICE_ID_INTEL_THC_PTL_U_DEVICE_ID_SPI_PORT2 0xE44B -+#define PCI_DEVICE_ID_INTEL_THC_WCL_DEVICE_ID_SPI_PORT1 0x4D49 -+#define PCI_DEVICE_ID_INTEL_THC_WCL_DEVICE_ID_SPI_PORT2 0x4D4B - - /* HIDSPI special ACPI parameters DSM methods */ - #define ACPI_QUICKSPI_REVISION_NUM 2 -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.c ---- BPI-Router-Linux-kernel/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.c 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dev.c 2025-10-22 13:53:56.491169257 -0400 -@@ -1539,7 +1539,7 @@ int thc_i2c_subip_regs_save(struct thc_d - - for (int i = 0; i < ARRAY_SIZE(i2c_subip_regs); i++) { - ret = thc_i2c_subip_pio_read(dev, i2c_subip_regs[i], -- &read_size, (u32 *)&dev->i2c_subip_regs + i); -+ &read_size, &dev->i2c_subip_regs[i]); - if (ret < 0) - return ret; - } -@@ -1562,7 +1562,7 @@ int thc_i2c_subip_regs_restore(struct th - - for (int i = 0; i < ARRAY_SIZE(i2c_subip_regs); i++) { - ret = thc_i2c_subip_pio_write(dev, i2c_subip_regs[i], -- write_size, (u32 *)&dev->i2c_subip_regs + i); -+ write_size, &dev->i2c_subip_regs[i]); - if (ret < 0) - return ret; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/wacom_sys.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/wacom_sys.c ---- BPI-Router-Linux-kernel/drivers/hid/wacom_sys.c 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/wacom_sys.c 2025-10-22 13:53:56.495169238 -0400 -@@ -2048,14 +2048,18 @@ static int wacom_initialize_remotes(stru - - remote->remote_dir = kobject_create_and_add("wacom_remote", - &wacom->hdev->dev.kobj); -- if (!remote->remote_dir) -+ if (!remote->remote_dir) { -+ kfifo_free(&remote->remote_fifo); - return -ENOMEM; -+ } - - error = sysfs_create_files(remote->remote_dir, remote_unpair_attrs); - - if (error) { - hid_err(wacom->hdev, - "cannot create sysfs group err: %d\n", error); -+ kfifo_free(&remote->remote_fifo); -+ kobject_put(remote->remote_dir); - return error; - } - -@@ -2901,6 +2905,7 @@ static void wacom_remove(struct hid_devi - hid_hw_stop(hdev); - - cancel_delayed_work_sync(&wacom->init_work); -+ cancel_delayed_work_sync(&wacom->aes_battery_work); - cancel_work_sync(&wacom->wireless_work); - cancel_work_sync(&wacom->battery_work); - cancel_work_sync(&wacom->remote_work); -diff -purNx .git BPI-Router-Linux-kernel/drivers/hid/wacom_wac.c BPI-Router-Linux-kernel-6.16.12/drivers/hid/wacom_wac.c ---- BPI-Router-Linux-kernel/drivers/hid/wacom_wac.c 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hid/wacom_wac.c 2025-10-22 13:53:56.495169238 -0400 -@@ -684,6 +684,7 @@ static bool wacom_is_art_pen(int tool_id - case 0x885: /* Intuos3 Marker Pen */ - case 0x804: /* Intuos4/5 13HD/24HD Marker Pen */ - case 0x10804: /* Intuos4/5 13HD/24HD Art Pen */ -+ case 0x204: /* Art Pen 2 */ - is_art_pen = true; - break; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/hv/channel.c BPI-Router-Linux-kernel-6.16.12/drivers/hv/channel.c ---- BPI-Router-Linux-kernel/drivers/hv/channel.c 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hv/channel.c 2025-10-22 13:53:56.495169238 -0400 -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - #include - #include - -diff -purNx .git BPI-Router-Linux-kernel/drivers/hv/channel_mgmt.c BPI-Router-Linux-kernel-6.16.12/drivers/hv/channel_mgmt.c ---- BPI-Router-Linux-kernel/drivers/hv/channel_mgmt.c 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hv/channel_mgmt.c 2025-10-22 13:53:56.495169238 -0400 -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - #include - #include - -diff -purNx .git BPI-Router-Linux-kernel/drivers/hv/connection.c BPI-Router-Linux-kernel-6.16.12/drivers/hv/connection.c ---- BPI-Router-Linux-kernel/drivers/hv/connection.c 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hv/connection.c 2025-10-22 13:53:56.495169238 -0400 -@@ -519,7 +519,10 @@ void vmbus_set_event(struct vmbus_channe - else - WARN_ON_ONCE(1); - } else { -- hv_do_fast_hypercall8(HVCALL_SIGNAL_EVENT, channel->sig_event); -+ u64 control = HVCALL_SIGNAL_EVENT; -+ -+ control |= hv_nested ? HV_HYPERCALL_NESTED : 0; -+ hv_do_fast_hypercall8(control, channel->sig_event); - } - } - EXPORT_SYMBOL_GPL(vmbus_set_event); -diff -purNx .git BPI-Router-Linux-kernel/drivers/hv/hv.c BPI-Router-Linux-kernel-6.16.12/drivers/hv/hv.c ---- BPI-Router-Linux-kernel/drivers/hv/hv.c 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hv/hv.c 2025-10-22 13:53:56.495169238 -0400 -@@ -85,8 +85,10 @@ int hv_post_message(union hv_connection_ - else - status = HV_STATUS_INVALID_PARAMETER; - } else { -- status = hv_do_hypercall(HVCALL_POST_MESSAGE, -- aligned_msg, NULL); -+ u64 control = HVCALL_POST_MESSAGE; -+ -+ control |= hv_nested ? HV_HYPERCALL_NESTED : 0; -+ status = hv_do_hypercall(control, aligned_msg, NULL); - } - - local_irq_restore(flags); -diff -purNx .git BPI-Router-Linux-kernel/drivers/hv/hv_proc.c BPI-Router-Linux-kernel-6.16.12/drivers/hv/hv_proc.c ---- BPI-Router-Linux-kernel/drivers/hv/hv_proc.c 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hv/hv_proc.c 2025-10-22 13:53:56.495169238 -0400 -@@ -6,6 +6,7 @@ - #include - #include - #include -+#include - #include - - /* -diff -purNx .git BPI-Router-Linux-kernel/drivers/hv/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/hv/Kconfig ---- BPI-Router-Linux-kernel/drivers/hv/Kconfig 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hv/Kconfig 2025-10-22 13:53:56.495169238 -0400 -@@ -9,7 +9,7 @@ config HYPERV - select PARAVIRT - select X86_HV_CALLBACK_VECTOR if X86 - select OF_EARLY_FLATTREE if OF -- select SYSFB if !HYPERV_VTL_MODE -+ select SYSFB if EFI && !HYPERV_VTL_MODE - help - Select this option to run Linux as a Hyper-V client operating - system. -diff -purNx .git BPI-Router-Linux-kernel/drivers/hv/mshv_common.c BPI-Router-Linux-kernel-6.16.12/drivers/hv/mshv_common.c ---- BPI-Router-Linux-kernel/drivers/hv/mshv_common.c 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hv/mshv_common.c 2025-10-22 13:53:56.495169238 -0400 -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - - #include "mshv.h" - -diff -purNx .git BPI-Router-Linux-kernel/drivers/hv/mshv_root_hv_call.c BPI-Router-Linux-kernel-6.16.12/drivers/hv/mshv_root_hv_call.c ---- BPI-Router-Linux-kernel/drivers/hv/mshv_root_hv_call.c 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hv/mshv_root_hv_call.c 2025-10-22 13:53:56.495169238 -0400 -@@ -9,6 +9,7 @@ - - #include - #include -+#include - #include - - #include "mshv_root.h" -diff -purNx .git BPI-Router-Linux-kernel/drivers/hv/ring_buffer.c BPI-Router-Linux-kernel-6.16.12/drivers/hv/ring_buffer.c ---- BPI-Router-Linux-kernel/drivers/hv/ring_buffer.c 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hv/ring_buffer.c 2025-10-22 13:53:56.495169238 -0400 -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - #include - - #include "hyperv_vmbus.h" -diff -purNx .git BPI-Router-Linux-kernel/drivers/hv/vmbus_drv.c BPI-Router-Linux-kernel-6.16.12/drivers/hv/vmbus_drv.c ---- BPI-Router-Linux-kernel/drivers/hv/vmbus_drv.c 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hv/vmbus_drv.c 2025-10-22 13:53:56.495169238 -0400 -@@ -2509,7 +2509,7 @@ static int vmbus_acpi_add(struct platfor - return 0; - } - #endif -- -+#ifndef HYPERVISOR_CALLBACK_VECTOR - static int vmbus_set_irq(struct platform_device *pdev) - { - struct irq_data *data; -@@ -2534,6 +2534,7 @@ static int vmbus_set_irq(struct platform - - return 0; - } -+#endif - - static int vmbus_device_add(struct platform_device *pdev) - { -@@ -2549,11 +2550,11 @@ static int vmbus_device_add(struct platf - if (ret) - return ret; - -- if (!__is_defined(HYPERVISOR_CALLBACK_VECTOR)) -- ret = vmbus_set_irq(pdev); -+#ifndef HYPERVISOR_CALLBACK_VECTOR -+ ret = vmbus_set_irq(pdev); - if (ret) - return ret; -- -+#endif - for_each_of_range(&parser, &range) { - struct resource *res; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/hwmon/corsair-cpro.c BPI-Router-Linux-kernel-6.16.12/drivers/hwmon/corsair-cpro.c ---- BPI-Router-Linux-kernel/drivers/hwmon/corsair-cpro.c 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hwmon/corsair-cpro.c 2025-10-22 13:53:56.495169238 -0400 -@@ -89,6 +89,7 @@ struct ccp_device { - struct mutex mutex; /* whenever buffer is used, lock before send_usb_cmd */ - u8 *cmd_buffer; - u8 *buffer; -+ int buffer_recv_size; /* number of received bytes in buffer */ - int target[6]; - DECLARE_BITMAP(temp_cnct, NUM_TEMP_SENSORS); - DECLARE_BITMAP(fan_cnct, NUM_FANS); -@@ -146,6 +147,9 @@ static int send_usb_cmd(struct ccp_devic - if (!t) - return -ETIMEDOUT; - -+ if (ccp->buffer_recv_size != IN_BUFFER_SIZE) -+ return -EPROTO; -+ - return ccp_get_errno(ccp); - } - -@@ -157,6 +161,7 @@ static int ccp_raw_event(struct hid_devi - spin_lock(&ccp->wait_input_report_lock); - if (!completion_done(&ccp->wait_input_report)) { - memcpy(ccp->buffer, data, min(IN_BUFFER_SIZE, size)); -+ ccp->buffer_recv_size = size; - complete_all(&ccp->wait_input_report); - } - spin_unlock(&ccp->wait_input_report_lock); -diff -purNx .git BPI-Router-Linux-kernel/drivers/hwmon/emc2305.c BPI-Router-Linux-kernel-6.16.12/drivers/hwmon/emc2305.c ---- BPI-Router-Linux-kernel/drivers/hwmon/emc2305.c 2025-10-22 13:53:23.255328933 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hwmon/emc2305.c 2025-10-22 13:53:56.495169238 -0400 -@@ -299,6 +299,12 @@ static int emc2305_set_single_tz(struct - dev_err(dev, "Failed to register cooling device %s\n", emc2305_fan_name[idx]); - return PTR_ERR(data->cdev_data[cdev_idx].cdev); - } -+ -+ if (data->cdev_data[cdev_idx].cur_state > 0) -+ /* Update pwm when temperature is above trips */ -+ pwm = EMC2305_PWM_STATE2DUTY(data->cdev_data[cdev_idx].cur_state, -+ data->max_state, EMC2305_FAN_MAX); -+ - /* Set minimal PWM speed. */ - if (data->pwm_separate) { - ret = emc2305_set_pwm(dev, pwm, cdev_idx); -@@ -312,10 +318,10 @@ static int emc2305_set_single_tz(struct - } - } - data->cdev_data[cdev_idx].cur_state = -- EMC2305_PWM_DUTY2STATE(data->pwm_min[cdev_idx], data->max_state, -+ EMC2305_PWM_DUTY2STATE(pwm, data->max_state, - EMC2305_FAN_MAX); - data->cdev_data[cdev_idx].last_hwmon_state = -- EMC2305_PWM_DUTY2STATE(data->pwm_min[cdev_idx], data->max_state, -+ EMC2305_PWM_DUTY2STATE(pwm, data->max_state, - EMC2305_FAN_MAX); - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/hwmon/ftsteutates.c BPI-Router-Linux-kernel-6.16.12/drivers/hwmon/ftsteutates.c ---- BPI-Router-Linux-kernel/drivers/hwmon/ftsteutates.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hwmon/ftsteutates.c 2025-10-22 13:53:56.495169238 -0400 -@@ -423,13 +423,16 @@ static int fts_read(struct device *dev, - break; - case hwmon_pwm: - switch (attr) { -- case hwmon_pwm_auto_channels_temp: -- if (data->fan_source[channel] == FTS_FAN_SOURCE_INVALID) -+ case hwmon_pwm_auto_channels_temp: { -+ u8 fan_source = data->fan_source[channel]; -+ -+ if (fan_source == FTS_FAN_SOURCE_INVALID || fan_source >= BITS_PER_LONG) - *val = 0; - else -- *val = BIT(data->fan_source[channel]); -+ *val = BIT(fan_source); - - return 0; -+ } - default: - break; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/hwmon/gsc-hwmon.c BPI-Router-Linux-kernel-6.16.12/drivers/hwmon/gsc-hwmon.c ---- BPI-Router-Linux-kernel/drivers/hwmon/gsc-hwmon.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hwmon/gsc-hwmon.c 2025-10-22 13:53:56.495169238 -0400 -@@ -64,7 +64,7 @@ static ssize_t pwm_auto_point_temp_show( - return ret; - - ret = regs[0] | regs[1] << 8; -- return sprintf(buf, "%d\n", ret * 10); -+ return sprintf(buf, "%d\n", ret * 100); - } - - static ssize_t pwm_auto_point_temp_store(struct device *dev, -@@ -99,7 +99,7 @@ static ssize_t pwm_auto_point_pwm_show(s - { - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - -- return sprintf(buf, "%d\n", 255 * (50 + (attr->index * 10))); -+ return sprintf(buf, "%d\n", 255 * (50 + (attr->index * 10)) / 100); - } - - static SENSOR_DEVICE_ATTR_RO(pwm1_auto_point1_pwm, pwm_auto_point_pwm, 0); -diff -purNx .git BPI-Router-Linux-kernel/drivers/hwmon/ina238.c BPI-Router-Linux-kernel-6.16.12/drivers/hwmon/ina238.c ---- BPI-Router-Linux-kernel/drivers/hwmon/ina238.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hwmon/ina238.c 2025-10-22 13:53:56.495169238 -0400 -@@ -97,7 +97,7 @@ - * Power (mW) = 0.2 * register value * 20000 / rshunt / 4 * gain - * (Specific for SQ52206) - * Power (mW) = 0.24 * register value * 20000 / rshunt / 4 * gain -- * Energy (mJ) = 16 * 0.24 * register value * 20000 / rshunt / 4 * gain -+ * Energy (uJ) = 16 * 0.24 * register value * 20000 / rshunt / 4 * gain * 1000 - */ - #define INA238_CALIBRATION_VALUE 16384 - #define INA238_FIXED_SHUNT 20000 -@@ -300,7 +300,7 @@ static int ina238_write_in(struct device - regval = clamp_val(val, -163, 163); - regval = (regval * 1000 * 4) / - (INA238_SHUNT_VOLTAGE_LSB * data->gain); -- regval = clamp_val(regval, S16_MIN, S16_MAX); -+ regval = clamp_val(regval, S16_MIN, S16_MAX) & 0xffff; - - switch (attr) { - case hwmon_in_max: -@@ -426,9 +426,10 @@ static int ina238_write_power(struct dev - * Unsigned postive values. Compared against the 24-bit power register, - * lower 8-bits are truncated. Same conversion to/from uW as POWER - * register. -+ * The first clamp_val() is to establish a baseline to avoid overflows. - */ -- regval = clamp_val(val, 0, LONG_MAX); -- regval = div_u64(val * 4 * 100 * data->rshunt, data->config->power_calculate_factor * -+ regval = clamp_val(val, 0, LONG_MAX / 2); -+ regval = div_u64(regval * 4 * 100 * data->rshunt, data->config->power_calculate_factor * - 1000ULL * INA238_FIXED_SHUNT * data->gain); - regval = clamp_val(regval >> 8, 0, U16_MAX); - -@@ -481,7 +482,7 @@ static int ina238_write_temp(struct devi - return -EOPNOTSUPP; - - /* Signed */ -- regval = clamp_val(val, -40000, 125000); -+ val = clamp_val(val, -40000, 125000); - regval = div_s64(val * 10000, data->config->temp_lsb) << data->config->temp_shift; - regval = clamp_val(regval, S16_MIN, S16_MAX) & (0xffff << data->config->temp_shift); - -@@ -500,9 +501,9 @@ static ssize_t energy1_input_show(struct - if (ret) - return ret; - -- /* result in mJ */ -- energy = div_u64(regval * INA238_FIXED_SHUNT * data->gain * 16 * -- data->config->power_calculate_factor, 4 * 100 * data->rshunt); -+ /* result in uJ */ -+ energy = div_u64(regval * INA238_FIXED_SHUNT * data->gain * 16 * 10 * -+ data->config->power_calculate_factor, 4 * data->rshunt); - - return sysfs_emit(buf, "%llu\n", energy); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/hwmon/ltc4282.c BPI-Router-Linux-kernel-6.16.12/drivers/hwmon/ltc4282.c ---- BPI-Router-Linux-kernel/drivers/hwmon/ltc4282.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hwmon/ltc4282.c 2025-10-22 13:53:56.495169238 -0400 -@@ -1512,13 +1512,6 @@ static int ltc4282_setup(struct ltc4282_ - } - - if (device_property_read_bool(dev, "adi,fault-log-enable")) { -- ret = regmap_set_bits(st->map, LTC4282_ADC_CTRL, -- LTC4282_FAULT_LOG_EN_MASK); -- if (ret) -- return ret; -- } -- -- if (device_property_read_bool(dev, "adi,fault-log-enable")) { - ret = regmap_set_bits(st->map, LTC4282_ADC_CTRL, LTC4282_FAULT_LOG_EN_MASK); - if (ret) - return ret; -diff -purNx .git BPI-Router-Linux-kernel/drivers/hwmon/mlxreg-fan.c BPI-Router-Linux-kernel-6.16.12/drivers/hwmon/mlxreg-fan.c ---- BPI-Router-Linux-kernel/drivers/hwmon/mlxreg-fan.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hwmon/mlxreg-fan.c 2025-10-22 13:53:56.495169238 -0400 -@@ -561,15 +561,14 @@ static int mlxreg_fan_cooling_config(str - if (!pwm->connected) - continue; - pwm->fan = fan; -+ /* Set minimal PWM speed. */ -+ pwm->last_hwmon_state = MLXREG_FAN_PWM_DUTY2STATE(MLXREG_FAN_MIN_DUTY); - pwm->cdev = devm_thermal_of_cooling_device_register(dev, NULL, mlxreg_fan_name[i], - pwm, &mlxreg_fan_cooling_ops); - if (IS_ERR(pwm->cdev)) { - dev_err(dev, "Failed to register cooling device\n"); - return PTR_ERR(pwm->cdev); - } -- -- /* Set minimal PWM speed. */ -- pwm->last_hwmon_state = MLXREG_FAN_PWM_DUTY2STATE(MLXREG_FAN_MIN_DUTY); - } - - return 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/hwmon/occ/common.c BPI-Router-Linux-kernel-6.16.12/drivers/hwmon/occ/common.c ---- BPI-Router-Linux-kernel/drivers/hwmon/occ/common.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hwmon/occ/common.c 2025-10-22 13:53:56.495169238 -0400 -@@ -459,12 +459,10 @@ static ssize_t occ_show_power_1(struct d - return sysfs_emit(buf, "%llu\n", val); - } - --static u64 occ_get_powr_avg(u64 *accum, u32 *samples) -+static u64 occ_get_powr_avg(u64 accum, u32 samples) - { -- u64 divisor = get_unaligned_be32(samples); -- -- return (divisor == 0) ? 0 : -- div64_u64(get_unaligned_be64(accum) * 1000000ULL, divisor); -+ return (samples == 0) ? 0 : -+ mul_u64_u32_div(accum, 1000000UL, samples); - } - - static ssize_t occ_show_power_2(struct device *dev, -@@ -489,8 +487,8 @@ static ssize_t occ_show_power_2(struct d - get_unaligned_be32(&power->sensor_id), - power->function_id, power->apss_channel); - case 1: -- val = occ_get_powr_avg(&power->accumulator, -- &power->update_tag); -+ val = occ_get_powr_avg(get_unaligned_be64(&power->accumulator), -+ get_unaligned_be32(&power->update_tag)); - break; - case 2: - val = (u64)get_unaligned_be32(&power->update_tag) * -@@ -527,8 +525,8 @@ static ssize_t occ_show_power_a0(struct - return sysfs_emit(buf, "%u_system\n", - get_unaligned_be32(&power->sensor_id)); - case 1: -- val = occ_get_powr_avg(&power->system.accumulator, -- &power->system.update_tag); -+ val = occ_get_powr_avg(get_unaligned_be64(&power->system.accumulator), -+ get_unaligned_be32(&power->system.update_tag)); - break; - case 2: - val = (u64)get_unaligned_be32(&power->system.update_tag) * -@@ -541,8 +539,8 @@ static ssize_t occ_show_power_a0(struct - return sysfs_emit(buf, "%u_proc\n", - get_unaligned_be32(&power->sensor_id)); - case 5: -- val = occ_get_powr_avg(&power->proc.accumulator, -- &power->proc.update_tag); -+ val = occ_get_powr_avg(get_unaligned_be64(&power->proc.accumulator), -+ get_unaligned_be32(&power->proc.update_tag)); - break; - case 6: - val = (u64)get_unaligned_be32(&power->proc.update_tag) * -@@ -555,8 +553,8 @@ static ssize_t occ_show_power_a0(struct - return sysfs_emit(buf, "%u_vdd\n", - get_unaligned_be32(&power->sensor_id)); - case 9: -- val = occ_get_powr_avg(&power->vdd.accumulator, -- &power->vdd.update_tag); -+ val = occ_get_powr_avg(get_unaligned_be64(&power->vdd.accumulator), -+ get_unaligned_be32(&power->vdd.update_tag)); - break; - case 10: - val = (u64)get_unaligned_be32(&power->vdd.update_tag) * -@@ -569,8 +567,8 @@ static ssize_t occ_show_power_a0(struct - return sysfs_emit(buf, "%u_vdn\n", - get_unaligned_be32(&power->sensor_id)); - case 13: -- val = occ_get_powr_avg(&power->vdn.accumulator, -- &power->vdn.update_tag); -+ val = occ_get_powr_avg(get_unaligned_be64(&power->vdn.accumulator), -+ get_unaligned_be32(&power->vdn.update_tag)); - break; - case 14: - val = (u64)get_unaligned_be32(&power->vdn.update_tag) * -@@ -747,29 +745,30 @@ static ssize_t occ_show_extended(struct - } - - /* -- * Some helper macros to make it easier to define an occ_attribute. Since these -- * are dynamically allocated, we shouldn't use the existing kernel macros which -+ * A helper to make it easier to define an occ_attribute. Since these -+ * are dynamically allocated, we cannot use the existing kernel macros which - * stringify the name argument. - */ --#define ATTR_OCC(_name, _mode, _show, _store) { \ -- .attr = { \ -- .name = _name, \ -- .mode = VERIFY_OCTAL_PERMISSIONS(_mode), \ -- }, \ -- .show = _show, \ -- .store = _store, \ --} -+static void occ_init_attribute(struct occ_attribute *attr, int mode, -+ ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf), -+ ssize_t (*store)(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t count), -+ int nr, int index, const char *fmt, ...) -+{ -+ va_list args; - --#define SENSOR_ATTR_OCC(_name, _mode, _show, _store, _nr, _index) { \ -- .dev_attr = ATTR_OCC(_name, _mode, _show, _store), \ -- .index = _index, \ -- .nr = _nr, \ -+ va_start(args, fmt); -+ vsnprintf(attr->name, sizeof(attr->name), fmt, args); -+ va_end(args); -+ -+ attr->sensor.dev_attr.attr.name = attr->name; -+ attr->sensor.dev_attr.attr.mode = mode; -+ attr->sensor.dev_attr.show = show; -+ attr->sensor.dev_attr.store = store; -+ attr->sensor.index = index; -+ attr->sensor.nr = nr; - } - --#define OCC_INIT_ATTR(_name, _mode, _show, _store, _nr, _index) \ -- ((struct sensor_device_attribute_2) \ -- SENSOR_ATTR_OCC(_name, _mode, _show, _store, _nr, _index)) -- - /* - * Allocate and instatiate sensor_device_attribute_2s. It's most efficient to - * use our own instead of the built-in hwmon attribute types. -@@ -855,14 +854,15 @@ static int occ_setup_sensor_attrs(struct - sensors->extended.num_sensors = 0; - } - -- occ->attrs = devm_kzalloc(dev, sizeof(*occ->attrs) * num_attrs, -+ occ->attrs = devm_kcalloc(dev, num_attrs, sizeof(*occ->attrs), - GFP_KERNEL); - if (!occ->attrs) - return -ENOMEM; - - /* null-terminated list */ -- occ->group.attrs = devm_kzalloc(dev, sizeof(*occ->group.attrs) * -- num_attrs + 1, GFP_KERNEL); -+ occ->group.attrs = devm_kcalloc(dev, num_attrs + 1, -+ sizeof(*occ->group.attrs), -+ GFP_KERNEL); - if (!occ->group.attrs) - return -ENOMEM; - -@@ -872,43 +872,33 @@ static int occ_setup_sensor_attrs(struct - s = i + 1; - temp = ((struct temp_sensor_2 *)sensors->temp.data) + i; - -- snprintf(attr->name, sizeof(attr->name), "temp%d_label", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_temp, NULL, -- 0, i); -+ occ_init_attribute(attr, 0444, show_temp, NULL, -+ 0, i, "temp%d_label", s); - attr++; - - if (sensors->temp.version == 2 && - temp->fru_type == OCC_FRU_TYPE_VRM) { -- snprintf(attr->name, sizeof(attr->name), -- "temp%d_alarm", s); -+ occ_init_attribute(attr, 0444, show_temp, NULL, -+ 1, i, "temp%d_alarm", s); - } else { -- snprintf(attr->name, sizeof(attr->name), -- "temp%d_input", s); -+ occ_init_attribute(attr, 0444, show_temp, NULL, -+ 1, i, "temp%d_input", s); - } - -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_temp, NULL, -- 1, i); - attr++; - - if (sensors->temp.version > 1) { -- snprintf(attr->name, sizeof(attr->name), -- "temp%d_fru_type", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, -- show_temp, NULL, 2, i); -+ occ_init_attribute(attr, 0444, show_temp, NULL, -+ 2, i, "temp%d_fru_type", s); - attr++; - -- snprintf(attr->name, sizeof(attr->name), -- "temp%d_fault", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, -- show_temp, NULL, 3, i); -+ occ_init_attribute(attr, 0444, show_temp, NULL, -+ 3, i, "temp%d_fault", s); - attr++; - - if (sensors->temp.version == 0x10) { -- snprintf(attr->name, sizeof(attr->name), -- "temp%d_max", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, -- show_temp, NULL, -- 4, i); -+ occ_init_attribute(attr, 0444, show_temp, NULL, -+ 4, i, "temp%d_max", s); - attr++; - } - } -@@ -917,14 +907,12 @@ static int occ_setup_sensor_attrs(struct - for (i = 0; i < sensors->freq.num_sensors; ++i) { - s = i + 1; - -- snprintf(attr->name, sizeof(attr->name), "freq%d_label", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_freq, NULL, -- 0, i); -+ occ_init_attribute(attr, 0444, show_freq, NULL, -+ 0, i, "freq%d_label", s); - attr++; - -- snprintf(attr->name, sizeof(attr->name), "freq%d_input", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_freq, NULL, -- 1, i); -+ occ_init_attribute(attr, 0444, show_freq, NULL, -+ 1, i, "freq%d_input", s); - attr++; - } - -@@ -940,32 +928,24 @@ static int occ_setup_sensor_attrs(struct - s = (i * 4) + 1; - - for (j = 0; j < 4; ++j) { -- snprintf(attr->name, sizeof(attr->name), -- "power%d_label", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, -- show_power, NULL, -- nr++, i); -+ occ_init_attribute(attr, 0444, show_power, -+ NULL, nr++, i, -+ "power%d_label", s); - attr++; - -- snprintf(attr->name, sizeof(attr->name), -- "power%d_average", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, -- show_power, NULL, -- nr++, i); -+ occ_init_attribute(attr, 0444, show_power, -+ NULL, nr++, i, -+ "power%d_average", s); - attr++; - -- snprintf(attr->name, sizeof(attr->name), -- "power%d_average_interval", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, -- show_power, NULL, -- nr++, i); -+ occ_init_attribute(attr, 0444, show_power, -+ NULL, nr++, i, -+ "power%d_average_interval", s); - attr++; - -- snprintf(attr->name, sizeof(attr->name), -- "power%d_input", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, -- show_power, NULL, -- nr++, i); -+ occ_init_attribute(attr, 0444, show_power, -+ NULL, nr++, i, -+ "power%d_input", s); - attr++; - - s++; -@@ -977,28 +957,20 @@ static int occ_setup_sensor_attrs(struct - for (i = 0; i < sensors->power.num_sensors; ++i) { - s = i + 1; - -- snprintf(attr->name, sizeof(attr->name), -- "power%d_label", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, -- show_power, NULL, 0, i); -+ occ_init_attribute(attr, 0444, show_power, NULL, -+ 0, i, "power%d_label", s); - attr++; - -- snprintf(attr->name, sizeof(attr->name), -- "power%d_average", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, -- show_power, NULL, 1, i); -+ occ_init_attribute(attr, 0444, show_power, NULL, -+ 1, i, "power%d_average", s); - attr++; - -- snprintf(attr->name, sizeof(attr->name), -- "power%d_average_interval", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, -- show_power, NULL, 2, i); -+ occ_init_attribute(attr, 0444, show_power, NULL, -+ 2, i, "power%d_average_interval", s); - attr++; - -- snprintf(attr->name, sizeof(attr->name), -- "power%d_input", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, -- show_power, NULL, 3, i); -+ occ_init_attribute(attr, 0444, show_power, NULL, -+ 3, i, "power%d_input", s); - attr++; - } - -@@ -1006,56 +978,43 @@ static int occ_setup_sensor_attrs(struct - } - - if (sensors->caps.num_sensors >= 1) { -- snprintf(attr->name, sizeof(attr->name), "power%d_label", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL, -- 0, 0); -+ occ_init_attribute(attr, 0444, show_caps, NULL, -+ 0, 0, "power%d_label", s); - attr++; - -- snprintf(attr->name, sizeof(attr->name), "power%d_cap", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL, -- 1, 0); -+ occ_init_attribute(attr, 0444, show_caps, NULL, -+ 1, 0, "power%d_cap", s); - attr++; - -- snprintf(attr->name, sizeof(attr->name), "power%d_input", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL, -- 2, 0); -+ occ_init_attribute(attr, 0444, show_caps, NULL, -+ 2, 0, "power%d_input", s); - attr++; - -- snprintf(attr->name, sizeof(attr->name), -- "power%d_cap_not_redundant", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL, -- 3, 0); -+ occ_init_attribute(attr, 0444, show_caps, NULL, -+ 3, 0, "power%d_cap_not_redundant", s); - attr++; - -- snprintf(attr->name, sizeof(attr->name), "power%d_cap_max", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL, -- 4, 0); -+ occ_init_attribute(attr, 0444, show_caps, NULL, -+ 4, 0, "power%d_cap_max", s); - attr++; - -- snprintf(attr->name, sizeof(attr->name), "power%d_cap_min", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL, -- 5, 0); -+ occ_init_attribute(attr, 0444, show_caps, NULL, -+ 5, 0, "power%d_cap_min", s); - attr++; - -- snprintf(attr->name, sizeof(attr->name), "power%d_cap_user", -- s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0644, show_caps, -- occ_store_caps_user, 6, 0); -+ occ_init_attribute(attr, 0644, show_caps, occ_store_caps_user, -+ 6, 0, "power%d_cap_user", s); - attr++; - - if (sensors->caps.version > 1) { -- snprintf(attr->name, sizeof(attr->name), -- "power%d_cap_user_source", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, -- show_caps, NULL, 7, 0); -+ occ_init_attribute(attr, 0444, show_caps, NULL, -+ 7, 0, "power%d_cap_user_source", s); - attr++; - - if (sensors->caps.version > 2) { -- snprintf(attr->name, sizeof(attr->name), -- "power%d_cap_min_soft", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, -- show_caps, NULL, -- 8, 0); -+ occ_init_attribute(attr, 0444, show_caps, NULL, -+ 8, 0, -+ "power%d_cap_min_soft", s); - attr++; - } - } -@@ -1064,19 +1023,16 @@ static int occ_setup_sensor_attrs(struct - for (i = 0; i < sensors->extended.num_sensors; ++i) { - s = i + 1; - -- snprintf(attr->name, sizeof(attr->name), "extn%d_label", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, -- occ_show_extended, NULL, 0, i); -+ occ_init_attribute(attr, 0444, occ_show_extended, NULL, -+ 0, i, "extn%d_label", s); - attr++; - -- snprintf(attr->name, sizeof(attr->name), "extn%d_flags", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, -- occ_show_extended, NULL, 1, i); -+ occ_init_attribute(attr, 0444, occ_show_extended, NULL, -+ 1, i, "extn%d_flags", s); - attr++; - -- snprintf(attr->name, sizeof(attr->name), "extn%d_input", s); -- attr->sensor = OCC_INIT_ATTR(attr->name, 0444, -- occ_show_extended, NULL, 2, i); -+ occ_init_attribute(attr, 0444, occ_show_extended, NULL, -+ 2, i, "extn%d_input", s); - attr++; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/hwmon/pmbus/ucd9000.c BPI-Router-Linux-kernel-6.16.12/drivers/hwmon/pmbus/ucd9000.c ---- BPI-Router-Linux-kernel/drivers/hwmon/pmbus/ucd9000.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/hwmon/pmbus/ucd9000.c 2025-10-22 13:53:56.495169238 -0400 -@@ -226,15 +226,15 @@ static int ucd9000_gpio_set(struct gpio_ - } - - if (value) { -- if (ret & UCD9000_GPIO_CONFIG_STATUS) -+ if (ret & UCD9000_GPIO_CONFIG_OUT_VALUE) - return 0; - -- ret |= UCD9000_GPIO_CONFIG_STATUS; -+ ret |= UCD9000_GPIO_CONFIG_OUT_VALUE; - } else { -- if (!(ret & UCD9000_GPIO_CONFIG_STATUS)) -+ if (!(ret & UCD9000_GPIO_CONFIG_OUT_VALUE)) - return 0; - -- ret &= ~UCD9000_GPIO_CONFIG_STATUS; -+ ret &= ~UCD9000_GPIO_CONFIG_OUT_VALUE; - } - - ret |= UCD9000_GPIO_CONFIG_ENABLE; -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/algos/i2c-algo-bit.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/algos/i2c-algo-bit.c ---- BPI-Router-Linux-kernel/drivers/i2c/algos/i2c-algo-bit.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/algos/i2c-algo-bit.c 2025-10-22 13:53:56.495169238 -0400 -@@ -619,8 +619,8 @@ static u32 bit_func(struct i2c_adapter * - /* -----exported algorithm data: ------------------------------------- */ - - const struct i2c_algorithm i2c_bit_algo = { -- .master_xfer = bit_xfer, -- .master_xfer_atomic = bit_xfer_atomic, -+ .xfer = bit_xfer, -+ .xfer_atomic = bit_xfer_atomic, - .functionality = bit_func, - }; - EXPORT_SYMBOL(i2c_bit_algo); -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/algos/i2c-algo-pca.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/algos/i2c-algo-pca.c ---- BPI-Router-Linux-kernel/drivers/i2c/algos/i2c-algo-pca.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/algos/i2c-algo-pca.c 2025-10-22 13:53:56.495169238 -0400 -@@ -361,8 +361,8 @@ static u32 pca_func(struct i2c_adapter * - } - - static const struct i2c_algorithm pca_algo = { -- .master_xfer = pca_xfer, -- .functionality = pca_func, -+ .xfer = pca_xfer, -+ .functionality = pca_func, - }; - - static unsigned int pca_probe_chip(struct i2c_adapter *adap) -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/algos/i2c-algo-pcf.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/algos/i2c-algo-pcf.c ---- BPI-Router-Linux-kernel/drivers/i2c/algos/i2c-algo-pcf.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/algos/i2c-algo-pcf.c 2025-10-22 13:53:56.495169238 -0400 -@@ -389,8 +389,8 @@ static u32 pcf_func(struct i2c_adapter * - - /* exported algorithm data: */ - static const struct i2c_algorithm pcf_algo = { -- .master_xfer = pcf_xfer, -- .functionality = pcf_func, -+ .xfer = pcf_xfer, -+ .functionality = pcf_func, - }; - - /* -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-amd-mp2-plat.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-amd-mp2-plat.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-amd-mp2-plat.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-amd-mp2-plat.c 2025-10-22 13:53:56.495169238 -0400 -@@ -179,7 +179,7 @@ static u32 i2c_amd_func(struct i2c_adapt - } - - static const struct i2c_algorithm i2c_amd_algorithm = { -- .master_xfer = i2c_amd_xfer, -+ .xfer = i2c_amd_xfer, - .functionality = i2c_amd_func, - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-aspeed.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-aspeed.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-aspeed.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-aspeed.c 2025-10-22 13:53:56.495169238 -0400 -@@ -814,11 +814,11 @@ static int aspeed_i2c_unreg_slave(struct - #endif /* CONFIG_I2C_SLAVE */ - - static const struct i2c_algorithm aspeed_i2c_algo = { -- .master_xfer = aspeed_i2c_master_xfer, -- .functionality = aspeed_i2c_functionality, -+ .xfer = aspeed_i2c_master_xfer, -+ .functionality = aspeed_i2c_functionality, - #if IS_ENABLED(CONFIG_I2C_SLAVE) -- .reg_slave = aspeed_i2c_reg_slave, -- .unreg_slave = aspeed_i2c_unreg_slave, -+ .reg_slave = aspeed_i2c_reg_slave, -+ .unreg_slave = aspeed_i2c_unreg_slave, - #endif /* CONFIG_I2C_SLAVE */ - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-at91-master.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-at91-master.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-at91-master.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-at91-master.c 2025-10-22 13:53:56.495169238 -0400 -@@ -739,8 +739,8 @@ static u32 at91_twi_func(struct i2c_adap - } - - static const struct i2c_algorithm at91_twi_algorithm = { -- .master_xfer = at91_twi_xfer, -- .functionality = at91_twi_func, -+ .xfer = at91_twi_xfer, -+ .functionality = at91_twi_func, - }; - - static int at91_twi_configure_dma(struct at91_twi_dev *dev, u32 phy_addr) -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-axxia.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-axxia.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-axxia.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-axxia.c 2025-10-22 13:53:56.495169238 -0400 -@@ -706,7 +706,7 @@ static int axxia_i2c_unreg_slave(struct - } - - static const struct i2c_algorithm axxia_i2c_algo = { -- .master_xfer = axxia_i2c_xfer, -+ .xfer = axxia_i2c_xfer, - .functionality = axxia_i2c_func, - .reg_slave = axxia_i2c_reg_slave, - .unreg_slave = axxia_i2c_unreg_slave, -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-bcm-iproc.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-bcm-iproc.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-bcm-iproc.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-bcm-iproc.c 2025-10-22 13:53:56.495169238 -0400 -@@ -1041,7 +1041,7 @@ static int bcm_iproc_i2c_unreg_slave(str - } - - static struct i2c_algorithm bcm_iproc_algo = { -- .master_xfer = bcm_iproc_i2c_xfer, -+ .xfer = bcm_iproc_i2c_xfer, - .functionality = bcm_iproc_i2c_functionality, - .reg_slave = bcm_iproc_i2c_reg_slave, - .unreg_slave = bcm_iproc_i2c_unreg_slave, -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-cadence.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-cadence.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-cadence.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-cadence.c 2025-10-22 13:53:56.495169238 -0400 -@@ -1231,12 +1231,12 @@ static int cdns_unreg_slave(struct i2c_c - #endif - - static const struct i2c_algorithm cdns_i2c_algo = { -- .master_xfer = cdns_i2c_master_xfer, -- .master_xfer_atomic = cdns_i2c_master_xfer_atomic, -- .functionality = cdns_i2c_func, -+ .xfer = cdns_i2c_master_xfer, -+ .xfer_atomic = cdns_i2c_master_xfer_atomic, -+ .functionality = cdns_i2c_func, - #if IS_ENABLED(CONFIG_I2C_SLAVE) -- .reg_slave = cdns_reg_slave, -- .unreg_slave = cdns_unreg_slave, -+ .reg_slave = cdns_reg_slave, -+ .unreg_slave = cdns_unreg_slave, - #endif - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-cgbc.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-cgbc.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-cgbc.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-cgbc.c 2025-10-22 13:53:56.495169238 -0400 -@@ -331,8 +331,8 @@ static u32 cgbc_i2c_func(struct i2c_adap - } - - static const struct i2c_algorithm cgbc_i2c_algorithm = { -- .master_xfer = cgbc_i2c_xfer, -- .functionality = cgbc_i2c_func, -+ .xfer = cgbc_i2c_xfer, -+ .functionality = cgbc_i2c_func, - }; - - static struct i2c_algo_cgbc_data cgbc_i2c_algo_data[] = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-designware-amdisp.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-designware-amdisp.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-designware-amdisp.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-designware-amdisp.c 2025-10-22 13:53:56.495169238 -0400 -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include - - #include "i2c-designware-core.h" - -@@ -62,6 +63,7 @@ static int amd_isp_dw_i2c_plat_probe(str - - adap = &isp_i2c_dev->adapter; - adap->owner = THIS_MODULE; -+ scnprintf(adap->name, sizeof(adap->name), AMDISP_I2C_ADAP_NAME); - ACPI_COMPANION_SET(&adap->dev, ACPI_COMPANION(&pdev->dev)); - adap->dev.of_node = pdev->dev.of_node; - /* use dynamically allocated adapter id */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-designware-master.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-designware-master.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-designware-master.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-designware-master.c 2025-10-22 13:53:56.495169238 -0400 -@@ -363,6 +363,7 @@ static int amd_i2c_dw_xfer_quirk(struct - - dev->msgs = msgs; - dev->msgs_num = num_msgs; -+ dev->msg_write_idx = 0; - i2c_dw_xfer_init(dev); - - /* Initiate messages read/write transaction */ -@@ -1042,8 +1043,9 @@ int i2c_dw_probe_master(struct dw_i2c_de - if (ret) - return ret; - -- snprintf(adap->name, sizeof(adap->name), -- "Synopsys DesignWare I2C adapter"); -+ if (!adap->name[0]) -+ scnprintf(adap->name, sizeof(adap->name), -+ "Synopsys DesignWare I2C adapter"); - adap->retries = 3; - adap->algo = &i2c_dw_algo; - adap->quirks = &i2c_dw_quirks; -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-designware-platdrv.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-designware-platdrv.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-designware-platdrv.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-designware-platdrv.c 2025-10-22 13:53:56.495169238 -0400 -@@ -101,7 +101,7 @@ static int bt1_i2c_request_regs(struct d - } - #endif - --static int txgbe_i2c_request_regs(struct dw_i2c_dev *dev) -+static int dw_i2c_get_parent_regmap(struct dw_i2c_dev *dev) - { - dev->map = dev_get_regmap(dev->dev->parent, NULL); - if (!dev->map) -@@ -123,12 +123,15 @@ static int dw_i2c_plat_request_regs(stru - struct platform_device *pdev = to_platform_device(dev->dev); - int ret; - -+ if (device_is_compatible(dev->dev, "intel,xe-i2c")) -+ return dw_i2c_get_parent_regmap(dev); -+ - switch (dev->flags & MODEL_MASK) { - case MODEL_BAIKAL_BT1: - ret = bt1_i2c_request_regs(dev); - break; - case MODEL_WANGXUN_SP: -- ret = txgbe_i2c_request_regs(dev); -+ ret = dw_i2c_get_parent_regmap(dev); - break; - default: - dev->base = devm_platform_ioremap_resource(pdev, 0); -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-eg20t.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-eg20t.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-eg20t.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-eg20t.c 2025-10-22 13:53:56.495169238 -0400 -@@ -690,7 +690,7 @@ static u32 pch_i2c_func(struct i2c_adapt - } - - static const struct i2c_algorithm pch_algorithm = { -- .master_xfer = pch_i2c_xfer, -+ .xfer = pch_i2c_xfer, - .functionality = pch_i2c_func - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-emev2.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-emev2.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-emev2.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-emev2.c 2025-10-22 13:53:56.495169238 -0400 -@@ -351,10 +351,10 @@ static int em_i2c_unreg_slave(struct i2c - } - - static const struct i2c_algorithm em_i2c_algo = { -- .master_xfer = em_i2c_xfer, -+ .xfer = em_i2c_xfer, - .functionality = em_i2c_func, -- .reg_slave = em_i2c_reg_slave, -- .unreg_slave = em_i2c_unreg_slave, -+ .reg_slave = em_i2c_reg_slave, -+ .unreg_slave = em_i2c_unreg_slave, - }; - - static int em_i2c_probe(struct platform_device *pdev) -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-exynos5.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-exynos5.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-exynos5.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-exynos5.c 2025-10-22 13:53:56.495169238 -0400 -@@ -879,9 +879,9 @@ static u32 exynos5_i2c_func(struct i2c_a - } - - static const struct i2c_algorithm exynos5_i2c_algorithm = { -- .master_xfer = exynos5_i2c_xfer, -- .master_xfer_atomic = exynos5_i2c_xfer_atomic, -- .functionality = exynos5_i2c_func, -+ .xfer = exynos5_i2c_xfer, -+ .xfer_atomic = exynos5_i2c_xfer_atomic, -+ .functionality = exynos5_i2c_func, - }; - - static int exynos5_i2c_probe(struct platform_device *pdev) -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-gxp.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-gxp.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-gxp.c 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-gxp.c 2025-10-22 13:53:56.495169238 -0400 -@@ -184,11 +184,11 @@ static int gxp_i2c_unreg_slave(struct i2 - #endif - - static const struct i2c_algorithm gxp_i2c_algo = { -- .master_xfer = gxp_i2c_master_xfer, -+ .xfer = gxp_i2c_master_xfer, - .functionality = gxp_i2c_func, - #if IS_ENABLED(CONFIG_I2C_SLAVE) -- .reg_slave = gxp_i2c_reg_slave, -- .unreg_slave = gxp_i2c_unreg_slave, -+ .reg_slave = gxp_i2c_reg_slave, -+ .unreg_slave = gxp_i2c_unreg_slave, - #endif - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-i801.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-i801.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-i801.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-i801.c 2025-10-22 13:53:56.499169218 -0400 -@@ -1052,7 +1052,7 @@ static const struct pci_device_id i801_i - { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_SOC_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_PCH_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, -- { PCI_DEVICE_DATA(INTEL, BIRCH_STREAM_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, -+ { PCI_DEVICE_DATA(INTEL, BIRCH_STREAM_SMBUS, FEATURES_ICH5) }, - { PCI_DEVICE_DATA(INTEL, ARROW_LAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, PANTHER_LAKE_H_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, - { PCI_DEVICE_DATA(INTEL, PANTHER_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-img-scb.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-img-scb.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-img-scb.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-img-scb.c 2025-10-22 13:53:56.499169218 -0400 -@@ -1143,7 +1143,7 @@ static u32 img_i2c_func(struct i2c_adapt - } - - static const struct i2c_algorithm img_i2c_algo = { -- .master_xfer = img_i2c_xfer, -+ .xfer = img_i2c_xfer, - .functionality = img_i2c_func, - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-imx.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-imx.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-imx.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-imx.c 2025-10-22 13:53:56.499169218 -0400 -@@ -1008,7 +1008,7 @@ static inline int i2c_imx_isr_read(struc - /* setup bus to read data */ - temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); - temp &= ~I2CR_MTX; -- if (i2c_imx->msg->len - 1) -+ if ((i2c_imx->msg->len - 1) || (i2c_imx->msg->flags & I2C_M_RECV_LEN)) - temp &= ~I2CR_TXAK; - - imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); -@@ -1063,6 +1063,7 @@ static inline void i2c_imx_isr_read_bloc - wake_up(&i2c_imx->queue); - } - i2c_imx->msg->len += len; -+ i2c_imx->msg->buf[i2c_imx->msg_buf_idx++] = len; - } - - static irqreturn_t i2c_imx_master_isr(struct imx_i2c_struct *i2c_imx, unsigned int status) -@@ -1692,11 +1693,11 @@ static u32 i2c_imx_func(struct i2c_adapt - } - - static const struct i2c_algorithm i2c_imx_algo = { -- .master_xfer = i2c_imx_xfer, -- .master_xfer_atomic = i2c_imx_xfer_atomic, -+ .xfer = i2c_imx_xfer, -+ .xfer_atomic = i2c_imx_xfer_atomic, - .functionality = i2c_imx_func, -- .reg_slave = i2c_imx_reg_slave, -- .unreg_slave = i2c_imx_unreg_slave, -+ .reg_slave = i2c_imx_reg_slave, -+ .unreg_slave = i2c_imx_unreg_slave, - }; - - static int i2c_imx_probe(struct platform_device *pdev) -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-imx-lpi2c.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-imx-lpi2c.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-imx-lpi2c.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-imx-lpi2c.c 2025-10-22 13:53:56.499169218 -0400 -@@ -1268,10 +1268,10 @@ static u32 lpi2c_imx_func(struct i2c_ada - } - - static const struct i2c_algorithm lpi2c_imx_algo = { -- .master_xfer = lpi2c_imx_xfer, -- .functionality = lpi2c_imx_func, -- .reg_target = lpi2c_imx_register_target, -- .unreg_target = lpi2c_imx_unregister_target, -+ .xfer = lpi2c_imx_xfer, -+ .functionality = lpi2c_imx_func, -+ .reg_target = lpi2c_imx_register_target, -+ .unreg_target = lpi2c_imx_unregister_target, - }; - - static const struct of_device_id lpi2c_imx_of_match[] = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-k1.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-k1.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-k1.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-k1.c 2025-10-22 13:53:56.499169218 -0400 -@@ -477,7 +477,7 @@ static int spacemit_i2c_xfer(struct i2c_ - - ret = spacemit_i2c_wait_bus_idle(i2c); - if (!ret) -- spacemit_i2c_xfer_msg(i2c); -+ ret = spacemit_i2c_xfer_msg(i2c); - else if (ret < 0) - dev_dbg(i2c->dev, "i2c transfer error: %d\n", ret); - else -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-keba.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-keba.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-keba.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-keba.c 2025-10-22 13:53:56.499169218 -0400 -@@ -500,7 +500,7 @@ static u32 ki2c_func(struct i2c_adapter - } - - static const struct i2c_algorithm ki2c_algo = { -- .master_xfer = ki2c_xfer, -+ .xfer = ki2c_xfer, - .functionality = ki2c_func, - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-mchp-pci1xxxx.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-mchp-pci1xxxx.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-mchp-pci1xxxx.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-mchp-pci1xxxx.c 2025-10-22 13:53:56.499169218 -0400 -@@ -1048,7 +1048,7 @@ static u32 pci1xxxx_i2c_get_funcs(struct - } - - static const struct i2c_algorithm pci1xxxx_i2c_algo = { -- .master_xfer = pci1xxxx_i2c_xfer, -+ .xfer = pci1xxxx_i2c_xfer, - .functionality = pci1xxxx_i2c_get_funcs, - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-meson.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-meson.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-meson.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-meson.c 2025-10-22 13:53:56.499169218 -0400 -@@ -448,8 +448,8 @@ static u32 meson_i2c_func(struct i2c_ada - } - - static const struct i2c_algorithm meson_i2c_algorithm = { -- .master_xfer = meson_i2c_xfer, -- .master_xfer_atomic = meson_i2c_xfer_atomic, -+ .xfer = meson_i2c_xfer, -+ .xfer_atomic = meson_i2c_xfer_atomic, - .functionality = meson_i2c_func, - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-microchip-corei2c.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-microchip-corei2c.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-microchip-corei2c.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-microchip-corei2c.c 2025-10-22 13:53:56.499169218 -0400 -@@ -435,6 +435,7 @@ static int mchp_corei2c_smbus_xfer(struc - u8 tx_buf[I2C_SMBUS_BLOCK_MAX + 2]; - u8 rx_buf[I2C_SMBUS_BLOCK_MAX + 1]; - int num_msgs = 1; -+ int ret; - - msgs[CORE_I2C_SMBUS_MSG_WR].addr = addr; - msgs[CORE_I2C_SMBUS_MSG_WR].flags = 0; -@@ -505,7 +506,10 @@ static int mchp_corei2c_smbus_xfer(struc - return -EOPNOTSUPP; - } - -- mchp_corei2c_xfer(&idev->adapter, msgs, num_msgs); -+ ret = mchp_corei2c_xfer(&idev->adapter, msgs, num_msgs); -+ if (ret < 0) -+ return ret; -+ - if (read_write == I2C_SMBUS_WRITE || size <= I2C_SMBUS_BYTE_DATA) - return 0; - -@@ -526,7 +530,7 @@ static int mchp_corei2c_smbus_xfer(struc - } - - static const struct i2c_algorithm mchp_corei2c_algo = { -- .master_xfer = mchp_corei2c_xfer, -+ .xfer = mchp_corei2c_xfer, - .functionality = mchp_corei2c_func, - .smbus_xfer = mchp_corei2c_smbus_xfer, - }; -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-mt65xx.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-mt65xx.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-mt65xx.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-mt65xx.c 2025-10-22 13:53:56.499169218 -0400 -@@ -1342,7 +1342,7 @@ static u32 mtk_i2c_functionality(struct - } - - static const struct i2c_algorithm mtk_i2c_algorithm = { -- .master_xfer = mtk_i2c_transfer, -+ .xfer = mtk_i2c_transfer, - .functionality = mtk_i2c_functionality, - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-mxs.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-mxs.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-mxs.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-mxs.c 2025-10-22 13:53:56.499169218 -0400 -@@ -687,7 +687,7 @@ static irqreturn_t mxs_i2c_isr(int this_ - } - - static const struct i2c_algorithm mxs_i2c_algo = { -- .master_xfer = mxs_i2c_xfer, -+ .xfer = mxs_i2c_xfer, - .functionality = mxs_i2c_func, - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-nomadik.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-nomadik.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-nomadik.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-nomadik.c 2025-10-22 13:53:56.499169218 -0400 -@@ -996,8 +996,8 @@ static unsigned int nmk_i2c_functionalit - } - - static const struct i2c_algorithm nmk_i2c_algo = { -- .master_xfer = nmk_i2c_xfer, -- .functionality = nmk_i2c_functionality -+ .xfer = nmk_i2c_xfer, -+ .functionality = nmk_i2c_functionality - }; - - static void nmk_i2c_of_probe(struct device_node *np, -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-npcm7xx.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-npcm7xx.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-npcm7xx.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-npcm7xx.c 2025-10-22 13:53:56.499169218 -0400 -@@ -2470,11 +2470,11 @@ static const struct i2c_adapter_quirks n - }; - - static const struct i2c_algorithm npcm_i2c_algo = { -- .master_xfer = npcm_i2c_master_xfer, -+ .xfer = npcm_i2c_master_xfer, - .functionality = npcm_i2c_functionality, - #if IS_ENABLED(CONFIG_I2C_SLAVE) -- .reg_slave = npcm_i2c_reg_slave, -- .unreg_slave = npcm_i2c_unreg_slave, -+ .reg_slave = npcm_i2c_reg_slave, -+ .unreg_slave = npcm_i2c_unreg_slave, - #endif - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-omap.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-omap.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-omap.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-omap.c 2025-10-22 13:53:56.499169218 -0400 -@@ -1201,9 +1201,9 @@ omap_i2c_isr_thread(int this_irq, void * - } - - static const struct i2c_algorithm omap_i2c_algo = { -- .master_xfer = omap_i2c_xfer_irq, -- .master_xfer_atomic = omap_i2c_xfer_polling, -- .functionality = omap_i2c_func, -+ .xfer = omap_i2c_xfer_irq, -+ .xfer_atomic = omap_i2c_xfer_polling, -+ .functionality = omap_i2c_func, - }; - - static const struct i2c_adapter_quirks omap_i2c_quirks = { -@@ -1461,18 +1461,20 @@ omap_i2c_probe(struct platform_device *p - if (IS_ERR(mux_state)) { - r = PTR_ERR(mux_state); - dev_dbg(&pdev->dev, "failed to get I2C mux: %d\n", r); -- goto err_disable_pm; -+ goto err_put_pm; - } - omap->mux_state = mux_state; - r = mux_state_select(omap->mux_state); - if (r) { - dev_err(&pdev->dev, "failed to select I2C mux: %d\n", r); -- goto err_disable_pm; -+ goto err_put_pm; - } - } - - /* reset ASAP, clearing any IRQs */ -- omap_i2c_init(omap); -+ r = omap_i2c_init(omap); -+ if (r) -+ goto err_mux_state_deselect; - - if (omap->rev < OMAP_I2C_OMAP1_REV_2) - r = devm_request_irq(&pdev->dev, omap->irq, omap_i2c_omap1_isr, -@@ -1515,9 +1517,13 @@ omap_i2c_probe(struct platform_device *p - - err_unuse_clocks: - omap_i2c_write_reg(omap, OMAP_I2C_CON_REG, 0); -- pm_runtime_dont_use_autosuspend(omap->dev); -+err_mux_state_deselect: -+ if (omap->mux_state) -+ mux_state_deselect(omap->mux_state); -+err_put_pm: - pm_runtime_put_sync(omap->dev); - err_disable_pm: -+ pm_runtime_dont_use_autosuspend(omap->dev); - pm_runtime_disable(&pdev->dev); - - return r; -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-piix4.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-piix4.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-piix4.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-piix4.c 2025-10-22 13:53:56.499169218 -0400 -@@ -34,7 +34,7 @@ - #include - #include - #include --#include -+#include - - #include "i2c-piix4.h" - -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-pnx.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-pnx.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-pnx.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-pnx.c 2025-10-22 13:53:56.499169218 -0400 -@@ -580,7 +580,7 @@ static u32 i2c_pnx_func(struct i2c_adapt - } - - static const struct i2c_algorithm pnx_algorithm = { -- .master_xfer = i2c_pnx_xfer, -+ .xfer = i2c_pnx_xfer, - .functionality = i2c_pnx_func, - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-pxa.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-pxa.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-pxa.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-pxa.c 2025-10-22 13:53:56.499169218 -0400 -@@ -1154,11 +1154,11 @@ static u32 i2c_pxa_functionality(struct - } - - static const struct i2c_algorithm i2c_pxa_algorithm = { -- .master_xfer = i2c_pxa_xfer, -- .functionality = i2c_pxa_functionality, -+ .xfer = i2c_pxa_xfer, -+ .functionality = i2c_pxa_functionality, - #ifdef CONFIG_I2C_PXA_SLAVE -- .reg_slave = i2c_pxa_slave_reg, -- .unreg_slave = i2c_pxa_slave_unreg, -+ .reg_slave = i2c_pxa_slave_reg, -+ .unreg_slave = i2c_pxa_slave_unreg, - #endif - }; - -@@ -1244,11 +1244,11 @@ static int i2c_pxa_pio_xfer(struct i2c_a - } - - static const struct i2c_algorithm i2c_pxa_pio_algorithm = { -- .master_xfer = i2c_pxa_pio_xfer, -- .functionality = i2c_pxa_functionality, -+ .xfer = i2c_pxa_pio_xfer, -+ .functionality = i2c_pxa_functionality, - #ifdef CONFIG_I2C_PXA_SLAVE -- .reg_slave = i2c_pxa_slave_reg, -- .unreg_slave = i2c_pxa_slave_unreg, -+ .reg_slave = i2c_pxa_slave_reg, -+ .unreg_slave = i2c_pxa_slave_unreg, - #endif - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-qcom-cci.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-qcom-cci.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-qcom-cci.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-qcom-cci.c 2025-10-22 13:53:56.499169218 -0400 -@@ -462,8 +462,8 @@ static u32 cci_func(struct i2c_adapter * - } - - static const struct i2c_algorithm cci_algo = { -- .master_xfer = cci_xfer, -- .functionality = cci_func, -+ .xfer = cci_xfer, -+ .functionality = cci_func, - }; - - static int cci_enable_clocks(struct cci *cci) -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-qcom-geni.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-qcom-geni.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-qcom-geni.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-qcom-geni.c 2025-10-22 13:53:56.499169218 -0400 -@@ -155,9 +155,9 @@ static const struct geni_i2c_clk_fld gen - - /* source_clock = 32 MHz */ - static const struct geni_i2c_clk_fld geni_i2c_clk_map_32mhz[] = { -- { I2C_MAX_STANDARD_MODE_FREQ, 8, 14, 18, 40 }, -- { I2C_MAX_FAST_MODE_FREQ, 4, 3, 11, 20 }, -- { I2C_MAX_FAST_MODE_PLUS_FREQ, 2, 3, 6, 15 }, -+ { I2C_MAX_STANDARD_MODE_FREQ, 8, 14, 18, 38 }, -+ { I2C_MAX_FAST_MODE_FREQ, 4, 3, 9, 19 }, -+ { I2C_MAX_FAST_MODE_PLUS_FREQ, 2, 3, 5, 15 }, - {} - }; - -@@ -727,8 +727,8 @@ static u32 geni_i2c_func(struct i2c_adap - } - - static const struct i2c_algorithm geni_i2c_algo = { -- .master_xfer = geni_i2c_xfer, -- .functionality = geni_i2c_func, -+ .xfer = geni_i2c_xfer, -+ .functionality = geni_i2c_func, - }; - - #ifdef CONFIG_ACPI -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-qup.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-qup.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-qup.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-qup.c 2025-10-22 13:53:56.499169218 -0400 -@@ -452,8 +452,10 @@ static int qup_i2c_bus_active(struct qup - if (!(status & I2C_STATUS_BUS_ACTIVE)) - break; - -- if (time_after(jiffies, timeout)) -+ if (time_after(jiffies, timeout)) { - ret = -ETIMEDOUT; -+ break; -+ } - - usleep_range(len, len * 2); - } -@@ -1634,13 +1636,13 @@ static u32 qup_i2c_func(struct i2c_adapt - } - - static const struct i2c_algorithm qup_i2c_algo = { -- .master_xfer = qup_i2c_xfer, -- .functionality = qup_i2c_func, -+ .xfer = qup_i2c_xfer, -+ .functionality = qup_i2c_func, - }; - - static const struct i2c_algorithm qup_i2c_algo_v2 = { -- .master_xfer = qup_i2c_xfer_v2, -- .functionality = qup_i2c_func, -+ .xfer = qup_i2c_xfer_v2, -+ .functionality = qup_i2c_func, - }; - - /* -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-rcar.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-rcar.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-rcar.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-rcar.c 2025-10-22 13:53:56.499169218 -0400 -@@ -1084,11 +1084,11 @@ static u32 rcar_i2c_func(struct i2c_adap - } - - static const struct i2c_algorithm rcar_i2c_algo = { -- .master_xfer = rcar_i2c_master_xfer, -- .master_xfer_atomic = rcar_i2c_master_xfer_atomic, -- .functionality = rcar_i2c_func, -- .reg_slave = rcar_reg_slave, -- .unreg_slave = rcar_unreg_slave, -+ .xfer = rcar_i2c_master_xfer, -+ .xfer_atomic = rcar_i2c_master_xfer_atomic, -+ .functionality = rcar_i2c_func, -+ .reg_slave = rcar_reg_slave, -+ .unreg_slave = rcar_unreg_slave, - }; - - static const struct i2c_adapter_quirks rcar_i2c_quirks = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-robotfuzz-osif.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-robotfuzz-osif.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-robotfuzz-osif.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-robotfuzz-osif.c 2025-10-22 13:53:56.499169218 -0400 -@@ -111,6 +111,11 @@ static u32 osif_func(struct i2c_adapter - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; - } - -+/* prevent invalid 0-length usb_control_msg */ -+static const struct i2c_adapter_quirks osif_quirks = { -+ .flags = I2C_AQ_NO_ZERO_LEN_READ, -+}; -+ - static const struct i2c_algorithm osif_algorithm = { - .xfer = osif_xfer, - .functionality = osif_func, -@@ -143,6 +148,7 @@ static int osif_probe(struct usb_interfa - - priv->adapter.owner = THIS_MODULE; - priv->adapter.class = I2C_CLASS_HWMON; -+ priv->adapter.quirks = &osif_quirks; - priv->adapter.algo = &osif_algorithm; - priv->adapter.algo_data = priv; - snprintf(priv->adapter.name, sizeof(priv->adapter.name), -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-rtl9300.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-rtl9300.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-rtl9300.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-rtl9300.c 2025-10-22 13:53:56.499169218 -0400 -@@ -99,6 +99,9 @@ static int rtl9300_i2c_config_xfer(struc - { - u32 val, mask; - -+ if (len < 1 || len > 16) -+ return -EINVAL; -+ - val = chan->bus_freq << RTL9300_I2C_MST_CTRL2_SCL_FREQ_OFS; - mask = RTL9300_I2C_MST_CTRL2_SCL_FREQ_MASK; - -@@ -143,10 +146,10 @@ static int rtl9300_i2c_write(struct rtl9 - return -EIO; - - for (i = 0; i < len; i++) { -- if (i % 4 == 0) -- vals[i/4] = 0; -- vals[i/4] <<= 8; -- vals[i/4] |= buf[i]; -+ unsigned int shift = (i % 4) * 8; -+ unsigned int reg = i / 4; -+ -+ vals[reg] |= buf[i] << shift; - } - - return regmap_bulk_write(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_DATA_WORD0, -@@ -175,7 +178,7 @@ static int rtl9300_i2c_execute_xfer(stru - return ret; - - ret = regmap_read_poll_timeout(i2c->regmap, i2c->reg_base + RTL9300_I2C_MST_CTRL1, -- val, !(val & RTL9300_I2C_MST_CTRL1_I2C_TRIG), 100, 2000); -+ val, !(val & RTL9300_I2C_MST_CTRL1_I2C_TRIG), 100, 100000); - if (ret) - return ret; - -@@ -222,15 +225,6 @@ static int rtl9300_i2c_smbus_xfer(struct - } - - switch (size) { -- case I2C_SMBUS_QUICK: -- ret = rtl9300_i2c_config_xfer(i2c, chan, addr, 0); -- if (ret) -- goto out_unlock; -- ret = rtl9300_i2c_reg_addr_set(i2c, 0, 0); -- if (ret) -- goto out_unlock; -- break; -- - case I2C_SMBUS_BYTE: - if (read_write == I2C_SMBUS_WRITE) { - ret = rtl9300_i2c_config_xfer(i2c, chan, addr, 0); -@@ -281,15 +275,19 @@ static int rtl9300_i2c_smbus_xfer(struct - ret = rtl9300_i2c_reg_addr_set(i2c, command, 1); - if (ret) - goto out_unlock; -- ret = rtl9300_i2c_config_xfer(i2c, chan, addr, data->block[0]); -+ if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX) { -+ ret = -EINVAL; -+ goto out_unlock; -+ } -+ ret = rtl9300_i2c_config_xfer(i2c, chan, addr, data->block[0] + 1); - if (ret) - goto out_unlock; - if (read_write == I2C_SMBUS_WRITE) { -- ret = rtl9300_i2c_write(i2c, &data->block[1], data->block[0]); -+ ret = rtl9300_i2c_write(i2c, &data->block[0], data->block[0] + 1); - if (ret) - goto out_unlock; - } -- len = data->block[0]; -+ len = data->block[0] + 1; - break; - - default: -@@ -308,9 +306,9 @@ out_unlock: - - static u32 rtl9300_i2c_func(struct i2c_adapter *a) - { -- return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | -- I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | -- I2C_FUNC_SMBUS_BLOCK_DATA; -+ return I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | -+ I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA | -+ I2C_FUNC_SMBUS_I2C_BLOCK; - } - - static const struct i2c_algorithm rtl9300_i2c_algo = { -@@ -319,7 +317,7 @@ static const struct i2c_algorithm rtl930 - }; - - static struct i2c_adapter_quirks rtl9300_i2c_quirks = { -- .flags = I2C_AQ_NO_CLK_STRETCH, -+ .flags = I2C_AQ_NO_CLK_STRETCH | I2C_AQ_NO_ZERO_LEN, - .max_read_len = 16, - .max_write_len = 16, - }; -@@ -349,7 +347,7 @@ static int rtl9300_i2c_probe(struct plat - - platform_set_drvdata(pdev, i2c); - -- if (device_get_child_node_count(dev) >= RTL9300_I2C_MUX_NCHAN) -+ if (device_get_child_node_count(dev) > RTL9300_I2C_MUX_NCHAN) - return dev_err_probe(dev, -EINVAL, "Too many channels\n"); - - device_for_each_child_node(dev, child) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-s3c2410.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-s3c2410.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-s3c2410.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-s3c2410.c 2025-10-22 13:53:56.499169218 -0400 -@@ -800,9 +800,9 @@ static u32 s3c24xx_i2c_func(struct i2c_a - - /* i2c bus registration info */ - static const struct i2c_algorithm s3c24xx_i2c_algorithm = { -- .master_xfer = s3c24xx_i2c_xfer, -- .master_xfer_atomic = s3c24xx_i2c_xfer_atomic, -- .functionality = s3c24xx_i2c_func, -+ .xfer = s3c24xx_i2c_xfer, -+ .xfer_atomic = s3c24xx_i2c_xfer_atomic, -+ .functionality = s3c24xx_i2c_func, - }; - - /* -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-sh7760.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-sh7760.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-sh7760.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-sh7760.c 2025-10-22 13:53:56.499169218 -0400 -@@ -379,8 +379,8 @@ static u32 sh7760_i2c_func(struct i2c_ad - } - - static const struct i2c_algorithm sh7760_i2c_algo = { -- .master_xfer = sh7760_i2c_master_xfer, -- .functionality = sh7760_i2c_func, -+ .xfer = sh7760_i2c_master_xfer, -+ .functionality = sh7760_i2c_func, - }; - - /* calculate CCR register setting for a desired scl clock. SCL clock is -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-sh_mobile.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-sh_mobile.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-sh_mobile.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-sh_mobile.c 2025-10-22 13:53:56.499169218 -0400 -@@ -740,8 +740,8 @@ static u32 sh_mobile_i2c_func(struct i2c - - static const struct i2c_algorithm sh_mobile_i2c_algorithm = { - .functionality = sh_mobile_i2c_func, -- .master_xfer = sh_mobile_i2c_xfer, -- .master_xfer_atomic = sh_mobile_i2c_xfer_atomic, -+ .xfer = sh_mobile_i2c_xfer, -+ .xfer_atomic = sh_mobile_i2c_xfer_atomic, - }; - - static const struct i2c_adapter_quirks sh_mobile_i2c_quirks = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-stm32.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-stm32.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-stm32.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-stm32.c 2025-10-22 13:53:56.499169218 -0400 -@@ -102,7 +102,6 @@ int stm32_i2c_prep_dma_xfer(struct devic - void *dma_async_param) - { - struct dma_async_tx_descriptor *txdesc; -- struct device *chan_dev; - int ret; - - if (rd_wr) { -@@ -116,11 +115,10 @@ int stm32_i2c_prep_dma_xfer(struct devic - } - - dma->dma_len = len; -- chan_dev = dma->chan_using->device->dev; - -- dma->dma_buf = dma_map_single(chan_dev, buf, dma->dma_len, -+ dma->dma_buf = dma_map_single(dev, buf, dma->dma_len, - dma->dma_data_dir); -- if (dma_mapping_error(chan_dev, dma->dma_buf)) { -+ if (dma_mapping_error(dev, dma->dma_buf)) { - dev_err(dev, "DMA mapping failed\n"); - return -EINVAL; - } -@@ -150,7 +148,7 @@ int stm32_i2c_prep_dma_xfer(struct devic - return 0; - - err: -- dma_unmap_single(chan_dev, dma->dma_buf, dma->dma_len, -+ dma_unmap_single(dev, dma->dma_buf, dma->dma_len, - dma->dma_data_dir); - return ret; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-stm32f7.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-stm32f7.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-stm32f7.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-stm32f7.c 2025-10-22 13:53:56.499169218 -0400 -@@ -739,12 +739,13 @@ static void stm32f7_i2c_disable_dma_req( - - static void stm32f7_i2c_dma_callback(void *arg) - { -- struct stm32f7_i2c_dev *i2c_dev = (struct stm32f7_i2c_dev *)arg; -+ struct stm32f7_i2c_dev *i2c_dev = arg; - struct stm32_i2c_dma *dma = i2c_dev->dma; -- struct device *dev = dma->chan_using->device->dev; - - stm32f7_i2c_disable_dma_req(i2c_dev); -- dma_unmap_single(dev, dma->dma_buf, dma->dma_len, dma->dma_data_dir); -+ dmaengine_terminate_async(dma->chan_using); -+ dma_unmap_single(i2c_dev->dev, dma->dma_buf, dma->dma_len, -+ dma->dma_data_dir); - complete(&dma->dma_complete); - } - -@@ -1510,7 +1511,6 @@ static irqreturn_t stm32f7_i2c_handle_is - u16 addr = f7_msg->addr; - void __iomem *base = i2c_dev->base; - struct device *dev = i2c_dev->dev; -- struct stm32_i2c_dma *dma = i2c_dev->dma; - - /* Bus error */ - if (status & STM32F7_I2C_ISR_BERR) { -@@ -1551,10 +1551,8 @@ static irqreturn_t stm32f7_i2c_handle_is - } - - /* Disable dma */ -- if (i2c_dev->use_dma) { -- stm32f7_i2c_disable_dma_req(i2c_dev); -- dmaengine_terminate_async(dma->chan_using); -- } -+ if (i2c_dev->use_dma) -+ stm32f7_i2c_dma_callback(i2c_dev); - - i2c_dev->master_mode = false; - complete(&i2c_dev->complete); -@@ -1600,7 +1598,6 @@ static irqreturn_t stm32f7_i2c_isr_event - { - struct stm32f7_i2c_dev *i2c_dev = data; - struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg; -- struct stm32_i2c_dma *dma = i2c_dev->dma; - void __iomem *base = i2c_dev->base; - u32 status, mask; - int ret; -@@ -1619,10 +1616,8 @@ static irqreturn_t stm32f7_i2c_isr_event - dev_dbg(i2c_dev->dev, "<%s>: Receive NACK (addr %x)\n", - __func__, f7_msg->addr); - writel_relaxed(STM32F7_I2C_ICR_NACKCF, base + STM32F7_I2C_ICR); -- if (i2c_dev->use_dma) { -- stm32f7_i2c_disable_dma_req(i2c_dev); -- dmaengine_terminate_async(dma->chan_using); -- } -+ if (i2c_dev->use_dma) -+ stm32f7_i2c_dma_callback(i2c_dev); - f7_msg->result = -ENXIO; - } - -@@ -1640,8 +1635,7 @@ static irqreturn_t stm32f7_i2c_isr_event - ret = wait_for_completion_timeout(&i2c_dev->dma->dma_complete, HZ); - if (!ret) { - dev_dbg(i2c_dev->dev, "<%s>: Timed out\n", __func__); -- stm32f7_i2c_disable_dma_req(i2c_dev); -- dmaengine_terminate_async(dma->chan_using); -+ stm32f7_i2c_dma_callback(i2c_dev); - f7_msg->result = -ETIMEDOUT; - } - } -@@ -2151,8 +2145,8 @@ static u32 stm32f7_i2c_func(struct i2c_a - } - - static const struct i2c_algorithm stm32f7_i2c_algo = { -- .master_xfer = stm32f7_i2c_xfer, -- .master_xfer_atomic = stm32f7_i2c_xfer_atomic, -+ .xfer = stm32f7_i2c_xfer, -+ .xfer_atomic = stm32f7_i2c_xfer_atomic, - .smbus_xfer = stm32f7_i2c_smbus_xfer, - .functionality = stm32f7_i2c_func, - .reg_slave = stm32f7_i2c_reg_slave, -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-synquacer.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-synquacer.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-synquacer.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-synquacer.c 2025-10-22 13:53:56.499169218 -0400 -@@ -520,8 +520,8 @@ static u32 synquacer_i2c_functionality(s - } - - static const struct i2c_algorithm synquacer_i2c_algo = { -- .master_xfer = synquacer_i2c_xfer, -- .functionality = synquacer_i2c_functionality, -+ .xfer = synquacer_i2c_xfer, -+ .functionality = synquacer_i2c_functionality, - }; - - static const struct i2c_adapter synquacer_i2c_ops = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-tegra.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-tegra.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-tegra.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-tegra.c 2025-10-22 13:53:56.499169218 -0400 -@@ -607,7 +607,6 @@ static int tegra_i2c_wait_for_config_loa - static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) - { - u32 val, clk_divisor, clk_multiplier, tsu_thd, tlow, thigh, non_hs_mode; -- acpi_handle handle = ACPI_HANDLE(i2c_dev->dev); - struct i2c_timings *t = &i2c_dev->timings; - int err; - -@@ -619,11 +618,7 @@ static int tegra_i2c_init(struct tegra_i - * emit a noisy warning on error, which won't stay unnoticed and - * won't hose machine entirely. - */ -- if (handle) -- err = acpi_evaluate_object(handle, "_RST", NULL, NULL); -- else -- err = reset_control_reset(i2c_dev->rst); -- -+ err = device_reset(i2c_dev->dev); - WARN_ON_ONCE(err); - - if (IS_DVC(i2c_dev)) -@@ -1440,9 +1435,9 @@ static u32 tegra_i2c_func(struct i2c_ada - } - - static const struct i2c_algorithm tegra_i2c_algo = { -- .master_xfer = tegra_i2c_xfer, -- .master_xfer_atomic = tegra_i2c_xfer_atomic, -- .functionality = tegra_i2c_func, -+ .xfer = tegra_i2c_xfer, -+ .xfer_atomic = tegra_i2c_xfer_atomic, -+ .functionality = tegra_i2c_func, - }; - - /* payload size is only 12 bit */ -@@ -1666,19 +1661,6 @@ static void tegra_i2c_parse_dt(struct te - i2c_dev->is_vi = true; - } - --static int tegra_i2c_init_reset(struct tegra_i2c_dev *i2c_dev) --{ -- if (ACPI_HANDLE(i2c_dev->dev)) -- return 0; -- -- i2c_dev->rst = devm_reset_control_get_exclusive(i2c_dev->dev, "i2c"); -- if (IS_ERR(i2c_dev->rst)) -- return dev_err_probe(i2c_dev->dev, PTR_ERR(i2c_dev->rst), -- "failed to get reset control\n"); -- -- return 0; --} -- - static int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev) - { - int err; -@@ -1788,10 +1770,6 @@ static int tegra_i2c_probe(struct platfo - - tegra_i2c_parse_dt(i2c_dev); - -- err = tegra_i2c_init_reset(i2c_dev); -- if (err) -- return err; -- - err = tegra_i2c_init_clocks(i2c_dev); - if (err) - return err; -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-tiny-usb.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-tiny-usb.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-tiny-usb.c 2025-10-22 13:53:23.263328895 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-tiny-usb.c 2025-10-22 13:53:56.499169218 -0400 -@@ -139,6 +139,11 @@ out: - return ret; - } - -+/* prevent invalid 0-length usb_control_msg */ -+static const struct i2c_adapter_quirks usb_quirks = { -+ .flags = I2C_AQ_NO_ZERO_LEN_READ, -+}; -+ - /* This is the actual algorithm we define */ - static const struct i2c_algorithm usb_algorithm = { - .xfer = usb_xfer, -@@ -247,6 +252,7 @@ static int i2c_tiny_usb_probe(struct usb - /* setup i2c adapter description */ - dev->adapter.owner = THIS_MODULE; - dev->adapter.class = I2C_CLASS_HWMON; -+ dev->adapter.quirks = &usb_quirks; - dev->adapter.algo = &usb_algorithm; - dev->adapter.algo_data = dev; - snprintf(dev->adapter.name, sizeof(dev->adapter.name), -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-virtio.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-virtio.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-virtio.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-virtio.c 2025-10-22 13:53:56.499169218 -0400 -@@ -116,15 +116,16 @@ static int virtio_i2c_complete_reqs(stru - for (i = 0; i < num; i++) { - struct virtio_i2c_req *req = &reqs[i]; - -- wait_for_completion(&req->completion); -- -- if (!failed && req->in_hdr.status != VIRTIO_I2C_MSG_OK) -- failed = true; -+ if (!failed) { -+ if (wait_for_completion_interruptible(&req->completion)) -+ failed = true; -+ else if (req->in_hdr.status != VIRTIO_I2C_MSG_OK) -+ failed = true; -+ else -+ j++; -+ } - - i2c_put_dma_safe_msg_buf(reqs[i].buf, &msgs[i], !failed); -- -- if (!failed) -- j++; - } - - return j; -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-xiic.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-xiic.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-xiic.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-xiic.c 2025-10-22 13:53:56.499169218 -0400 -@@ -1398,8 +1398,8 @@ static u32 xiic_func(struct i2c_adapter - } - - static const struct i2c_algorithm xiic_algorithm = { -- .master_xfer = xiic_xfer, -- .master_xfer_atomic = xiic_xfer_atomic, -+ .xfer = xiic_xfer, -+ .xfer_atomic = xiic_xfer_atomic, - .functionality = xiic_func, - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-xlp9xx.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-xlp9xx.c ---- BPI-Router-Linux-kernel/drivers/i2c/busses/i2c-xlp9xx.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/i2c-xlp9xx.c 2025-10-22 13:53:56.499169218 -0400 -@@ -452,7 +452,7 @@ static u32 xlp9xx_i2c_functionality(stru - } - - static const struct i2c_algorithm xlp9xx_i2c_algo = { -- .master_xfer = xlp9xx_i2c_xfer, -+ .xfer = xlp9xx_i2c_xfer, - .functionality = xlp9xx_i2c_functionality, - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/busses/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/Kconfig ---- BPI-Router-Linux-kernel/drivers/i2c/busses/Kconfig 2025-10-22 13:53:23.259328915 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/busses/Kconfig 2025-10-22 13:53:56.495169238 -0400 -@@ -200,7 +200,7 @@ config I2C_ISMT - - config I2C_PIIX4 - tristate "Intel PIIX4 and compatible (ATI/AMD/Serverworks/Broadcom/SMSC)" -- depends on PCI && HAS_IOPORT && X86 -+ depends on PCI && HAS_IOPORT - select I2C_SMBUS - help - If you say yes to this option, support will be included for the Intel -@@ -1530,7 +1530,7 @@ config I2C_XGENE_SLIMPRO - - config SCx200_ACB - tristate "Geode ACCESS.bus support" -- depends on X86_32 && PCI -+ depends on X86_32 && PCI && HAS_IOPORT - help - Enable the use of the ACCESS.bus controllers on the Geode SCx200 and - SC1100 processors and the CS5535 and CS5536 Geode companion devices. -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/i2c-atr.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/i2c-atr.c ---- BPI-Router-Linux-kernel/drivers/i2c/i2c-atr.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/i2c-atr.c 2025-10-22 13:53:56.499169218 -0400 -@@ -738,7 +738,7 @@ struct i2c_atr *i2c_atr_new(struct i2c_a - atr->flags = flags; - - if (parent->algo->master_xfer) -- atr->algo.master_xfer = i2c_atr_master_xfer; -+ atr->algo.xfer = i2c_atr_master_xfer; - if (parent->algo->smbus_xfer) - atr->algo.smbus_xfer = i2c_atr_smbus_xfer; - atr->algo.functionality = i2c_atr_functionality; -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/i2c-core-acpi.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/i2c-core-acpi.c ---- BPI-Router-Linux-kernel/drivers/i2c/i2c-core-acpi.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/i2c-core-acpi.c 2025-10-22 13:53:56.503169199 -0400 -@@ -370,6 +370,7 @@ static const struct acpi_device_id i2c_a - * the device works without issues on Windows at what is expected to be - * a 400KHz frequency. The root cause of the issue is not known. - */ -+ { "DLL0945", 0 }, - { "ELAN06FA", 0 }, - {} - }; -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/i2c-core-base.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/i2c-core-base.c ---- BPI-Router-Linux-kernel/drivers/i2c/i2c-core-base.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/i2c-core-base.c 2025-10-22 13:53:56.503169199 -0400 -@@ -1066,7 +1066,13 @@ void i2c_unregister_device(struct i2c_cl - of_node_clear_flag(to_of_node(fwnode), OF_POPULATED); - else if (is_acpi_device_node(fwnode)) - acpi_device_clear_enumerated(to_acpi_device_node(fwnode)); -- fwnode_handle_put(fwnode); -+ -+ /* -+ * If the primary fwnode is a software node it is free-ed by -+ * device_remove_software_node() below, avoid double-free. -+ */ -+ if (!is_software_node(fwnode)) -+ fwnode_handle_put(fwnode); - - device_remove_software_node(&client->dev); - device_unregister(&client->dev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/i2c-mux.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/i2c-mux.c ---- BPI-Router-Linux-kernel/drivers/i2c/i2c-mux.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/i2c-mux.c 2025-10-22 13:53:56.503169199 -0400 -@@ -293,12 +293,12 @@ int i2c_mux_add_adapter(struct i2c_mux_c - */ - if (parent->algo->master_xfer) { - if (muxc->mux_locked) -- priv->algo.master_xfer = i2c_mux_master_xfer; -+ priv->algo.xfer = i2c_mux_master_xfer; - else -- priv->algo.master_xfer = __i2c_mux_master_xfer; -+ priv->algo.xfer = __i2c_mux_master_xfer; - } - if (parent->algo->master_xfer_atomic) -- priv->algo.master_xfer_atomic = priv->algo.master_xfer; -+ priv->algo.xfer_atomic = priv->algo.master_xfer; - - if (parent->algo->smbus_xfer) { - if (muxc->mux_locked) -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/muxes/i2c-demux-pinctrl.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/muxes/i2c-demux-pinctrl.c ---- BPI-Router-Linux-kernel/drivers/i2c/muxes/i2c-demux-pinctrl.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/muxes/i2c-demux-pinctrl.c 2025-10-22 13:53:56.503169199 -0400 -@@ -95,9 +95,9 @@ static int i2c_demux_activate_master(str - priv->cur_chan = new_chan; - - /* Now fill out current adapter structure. cur_chan must be up to date */ -- priv->algo.master_xfer = i2c_demux_master_xfer; -+ priv->algo.xfer = i2c_demux_master_xfer; - if (adap->algo->master_xfer_atomic) -- priv->algo.master_xfer_atomic = i2c_demux_master_xfer; -+ priv->algo.xfer_atomic = i2c_demux_master_xfer; - priv->algo.functionality = i2c_demux_functionality; - - snprintf(priv->cur_adap.name, sizeof(priv->cur_adap.name), -diff -purNx .git BPI-Router-Linux-kernel/drivers/i2c/muxes/i2c-mux-mule.c BPI-Router-Linux-kernel-6.16.12/drivers/i2c/muxes/i2c-mux-mule.c ---- BPI-Router-Linux-kernel/drivers/i2c/muxes/i2c-mux-mule.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i2c/muxes/i2c-mux-mule.c 2025-10-22 13:53:56.503169199 -0400 -@@ -47,7 +47,6 @@ static int mule_i2c_mux_probe(struct pla - struct mule_i2c_reg_mux *priv; - struct i2c_client *client; - struct i2c_mux_core *muxc; -- struct device_node *dev; - unsigned int readback; - int ndev, ret; - bool old_fw; -@@ -95,7 +94,7 @@ static int mule_i2c_mux_probe(struct pla - "Failed to register mux remove\n"); - - /* Create device adapters */ -- for_each_child_of_node(mux_dev->of_node, dev) { -+ for_each_child_of_node_scoped(mux_dev->of_node, dev) { - u32 reg; - - ret = of_property_read_u32(dev, "reg", ®); -diff -purNx .git BPI-Router-Linux-kernel/drivers/i3c/internals.h BPI-Router-Linux-kernel-6.16.12/drivers/i3c/internals.h ---- BPI-Router-Linux-kernel/drivers/i3c/internals.h 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i3c/internals.h 2025-10-22 13:53:56.503169199 -0400 -@@ -9,6 +9,7 @@ - #define I3C_INTERNALS_H - - #include -+#include - - void i3c_bus_normaluse_lock(struct i3c_bus *bus); - void i3c_bus_normaluse_unlock(struct i3c_bus *bus); -diff -purNx .git BPI-Router-Linux-kernel/drivers/i3c/master/svc-i3c-master.c BPI-Router-Linux-kernel-6.16.12/drivers/i3c/master/svc-i3c-master.c ---- BPI-Router-Linux-kernel/drivers/i3c/master/svc-i3c-master.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i3c/master/svc-i3c-master.c 2025-10-22 13:53:56.503169199 -0400 -@@ -104,6 +104,7 @@ - #define SVC_I3C_MDATACTRL_TXTRIG_FIFO_NOT_FULL GENMASK(5, 4) - #define SVC_I3C_MDATACTRL_RXTRIG_FIFO_NOT_EMPTY 0 - #define SVC_I3C_MDATACTRL_RXCOUNT(x) FIELD_GET(GENMASK(28, 24), (x)) -+#define SVC_I3C_MDATACTRL_TXCOUNT(x) FIELD_GET(GENMASK(20, 16), (x)) - #define SVC_I3C_MDATACTRL_TXFULL BIT(30) - #define SVC_I3C_MDATACTRL_RXEMPTY BIT(31) - -@@ -1304,14 +1305,19 @@ static int svc_i3c_master_xfer(struct sv - * FIFO start filling as soon as possible after EmitStartAddr. - */ - if (svc_has_quirk(master, SVC_I3C_QUIRK_FIFO_EMPTY) && !rnw && xfer_len) { -- u32 end = xfer_len > SVC_I3C_FIFO_SIZE ? 0 : SVC_I3C_MWDATAB_END; -- u32 len = min_t(u32, xfer_len, SVC_I3C_FIFO_SIZE); -+ u32 space, end, len; - -- writesb(master->regs + SVC_I3C_MWDATAB1, out, len - 1); -- /* Mark END bit if this is the last byte */ -- writel(out[len - 1] | end, master->regs + SVC_I3C_MWDATAB); -- xfer_len -= len; -- out += len; -+ reg = readl(master->regs + SVC_I3C_MDATACTRL); -+ space = SVC_I3C_FIFO_SIZE - SVC_I3C_MDATACTRL_TXCOUNT(reg); -+ if (space) { -+ end = xfer_len > space ? 0 : SVC_I3C_MWDATAB_END; -+ len = min_t(u32, xfer_len, space); -+ writesb(master->regs + SVC_I3C_MWDATAB1, out, len - 1); -+ /* Mark END bit if this is the last byte */ -+ writel(out[len - 1] | end, master->regs + SVC_I3C_MWDATAB); -+ xfer_len -= len; -+ out += len; -+ } - } - - ret = readl_poll_timeout(master->regs + SVC_I3C_MSTATUS, reg, -diff -purNx .git BPI-Router-Linux-kernel/drivers/i3c/master.c BPI-Router-Linux-kernel-6.16.12/drivers/i3c/master.c ---- BPI-Router-Linux-kernel/drivers/i3c/master.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/i3c/master.c 2025-10-22 13:53:56.503169199 -0400 -@@ -1439,7 +1439,7 @@ static int i3c_master_retrieve_dev_info( - - if (dev->info.bcr & I3C_BCR_HDR_CAP) { - ret = i3c_master_gethdrcap_locked(master, &dev->info); -- if (ret) -+ if (ret && ret != -ENOTSUPP) - return ret; - } - -@@ -2467,6 +2467,8 @@ static int i3c_i2c_notifier_call(struct - case BUS_NOTIFY_DEL_DEVICE: - ret = i3c_master_i2c_detach(adap, client); - break; -+ default: -+ ret = -EINVAL; - } - i3c_bus_maintenance_unlock(&master->bus); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/idle/intel_idle.c BPI-Router-Linux-kernel-6.16.12/drivers/idle/intel_idle.c ---- BPI-Router-Linux-kernel/drivers/idle/intel_idle.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/idle/intel_idle.c 2025-10-22 13:53:56.503169199 -0400 -@@ -152,8 +152,8 @@ static __always_inline int __intel_idle( - int index, bool irqoff) - { - struct cpuidle_state *state = &drv->states[index]; -- unsigned long eax = flg2MWAIT(state->flags); -- unsigned long ecx = 1*irqoff; /* break on interrupt flag */ -+ unsigned int eax = flg2MWAIT(state->flags); -+ unsigned int ecx = 1*irqoff; /* break on interrupt flag */ - - mwait_idle_with_hints(eax, ecx); - -@@ -226,9 +226,9 @@ static __cpuidle int intel_idle_xstate(s - static __cpuidle int intel_idle_s2idle(struct cpuidle_device *dev, - struct cpuidle_driver *drv, int index) - { -- unsigned long ecx = 1; /* break on interrupt flag */ - struct cpuidle_state *state = &drv->states[index]; -- unsigned long eax = flg2MWAIT(state->flags); -+ unsigned int eax = flg2MWAIT(state->flags); -+ unsigned int ecx = 1; /* break on interrupt flag */ - - if (state->flags & CPUIDLE_FLAG_INIT_XSTATE) - fpu_idle_fpregs(); -@@ -1679,7 +1679,7 @@ static const struct x86_cpu_id intel_idl - }; - - static const struct x86_cpu_id intel_mwait_ids[] __initconst = { -- X86_MATCH_VENDOR_FAM_FEATURE(INTEL, 6, X86_FEATURE_MWAIT, NULL), -+ X86_MATCH_VENDOR_FAM_FEATURE(INTEL, X86_FAMILY_ANY, X86_FEATURE_MWAIT, NULL), - {} - }; - -@@ -2507,6 +2507,8 @@ static int __init intel_idle_init(void) - pr_debug("Local APIC timer is reliable in %s\n", - boot_cpu_has(X86_FEATURE_ARAT) ? "all C-states" : "C1"); - -+ arch_cpu_rescan_dead_smt_siblings(); -+ - return 0; - - hp_setup_fail: -@@ -2518,7 +2520,7 @@ init_driver_fail: - return retval; - - } --device_initcall(intel_idle_init); -+subsys_initcall_sync(intel_idle_init); - - /* - * We are not really modular, but we used to support that. Meaning we also -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/accel/fxls8962af-core.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/accel/fxls8962af-core.c ---- BPI-Router-Linux-kernel/drivers/iio/accel/fxls8962af-core.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/accel/fxls8962af-core.c 2025-10-22 13:53:56.503169199 -0400 -@@ -877,6 +877,8 @@ static int fxls8962af_buffer_predisable( - if (ret) - return ret; - -+ synchronize_irq(data->irq); -+ - ret = __fxls8962af_fifo_set_mode(data, false); - - if (data->enable_event) -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/accel/sca3300.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/accel/sca3300.c ---- BPI-Router-Linux-kernel/drivers/iio/accel/sca3300.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/accel/sca3300.c 2025-10-22 13:53:56.503169199 -0400 -@@ -479,7 +479,7 @@ static irqreturn_t sca3300_trigger_handl - struct iio_dev *indio_dev = pf->indio_dev; - struct sca3300_data *data = iio_priv(indio_dev); - int bit, ret, val, i = 0; -- IIO_DECLARE_BUFFER_WITH_TS(s16, channels, SCA3300_SCAN_MAX); -+ IIO_DECLARE_BUFFER_WITH_TS(s16, channels, SCA3300_SCAN_MAX) = { }; - - iio_for_each_active_channel(indio_dev, bit) { - ret = sca3300_read_reg(data, indio_dev->channels[bit].address, &val); -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/accel/st_accel_core.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/accel/st_accel_core.c ---- BPI-Router-Linux-kernel/drivers/iio/accel/st_accel_core.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/accel/st_accel_core.c 2025-10-22 13:53:56.503169199 -0400 -@@ -1353,6 +1353,7 @@ static int apply_acpi_orientation(struct - union acpi_object *ont; - union acpi_object *elements; - acpi_status status; -+ struct device *parent = indio_dev->dev.parent; - int ret = -EINVAL; - unsigned int val; - int i, j; -@@ -1371,7 +1372,7 @@ static int apply_acpi_orientation(struct - }; - - -- adev = ACPI_COMPANION(indio_dev->dev.parent); -+ adev = ACPI_COMPANION(parent); - if (!adev) - return -ENXIO; - -@@ -1380,8 +1381,7 @@ static int apply_acpi_orientation(struct - if (status == AE_NOT_FOUND) { - return -ENXIO; - } else if (ACPI_FAILURE(status)) { -- dev_warn(&indio_dev->dev, "failed to execute _ONT: %d\n", -- status); -+ dev_warn(parent, "failed to execute _ONT: %d\n", status); - return status; - } - -@@ -1457,12 +1457,12 @@ static int apply_acpi_orientation(struct - } - - ret = 0; -- dev_info(&indio_dev->dev, "computed mount matrix from ACPI\n"); -+ dev_info(parent, "computed mount matrix from ACPI\n"); - - out: - kfree(buffer.pointer); - if (ret) -- dev_dbg(&indio_dev->dev, -+ dev_dbg(parent, - "failed to apply ACPI orientation data: %d\n", ret); - - return ret; -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/adc/ad7124.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/ad7124.c ---- BPI-Router-Linux-kernel/drivers/iio/adc/ad7124.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/ad7124.c 2025-10-22 13:53:56.503169199 -0400 -@@ -855,7 +855,7 @@ enum { - static int ad7124_syscalib_locked(struct ad7124_state *st, const struct iio_chan_spec *chan) - { - struct device *dev = &st->sd.spi->dev; -- struct ad7124_channel *ch = &st->channels[chan->channel]; -+ struct ad7124_channel *ch = &st->channels[chan->address]; - int ret; - - if (ch->syscalib_mode == AD7124_SYSCALIB_ZERO_SCALE) { -@@ -871,8 +871,8 @@ static int ad7124_syscalib_locked(struct - if (ret < 0) - return ret; - -- dev_dbg(dev, "offset for channel %d after zero-scale calibration: 0x%x\n", -- chan->channel, ch->cfg.calibration_offset); -+ dev_dbg(dev, "offset for channel %lu after zero-scale calibration: 0x%x\n", -+ chan->address, ch->cfg.calibration_offset); - } else { - ch->cfg.calibration_gain = st->gain_default; - -@@ -886,8 +886,8 @@ static int ad7124_syscalib_locked(struct - if (ret < 0) - return ret; - -- dev_dbg(dev, "gain for channel %d after full-scale calibration: 0x%x\n", -- chan->channel, ch->cfg.calibration_gain); -+ dev_dbg(dev, "gain for channel %lu after full-scale calibration: 0x%x\n", -+ chan->address, ch->cfg.calibration_gain); - } - - return 0; -@@ -930,7 +930,7 @@ static int ad7124_set_syscalib_mode(stru - { - struct ad7124_state *st = iio_priv(indio_dev); - -- st->channels[chan->channel].syscalib_mode = mode; -+ st->channels[chan->address].syscalib_mode = mode; - - return 0; - } -@@ -940,7 +940,7 @@ static int ad7124_get_syscalib_mode(stru - { - struct ad7124_state *st = iio_priv(indio_dev); - -- return st->channels[chan->channel].syscalib_mode; -+ return st->channels[chan->address].syscalib_mode; - } - - static const struct iio_enum ad7124_syscalib_mode_enum = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/adc/ad7173.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/ad7173.c ---- BPI-Router-Linux-kernel/drivers/iio/adc/ad7173.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/ad7173.c 2025-10-22 13:53:56.503169199 -0400 -@@ -200,7 +200,7 @@ struct ad7173_channel_config { - /* - * Following fields are used to compare equality. If you - * make adaptations in it, you most likely also have to adapt -- * ad7173_find_live_config(), too. -+ * ad7173_is_setup_equal(), too. - */ - struct_group(config_props, - bool bipolar; -@@ -319,7 +319,7 @@ static int ad7173_set_syscalib_mode(stru - { - struct ad7173_state *st = iio_priv(indio_dev); - -- st->channels[chan->channel].syscalib_mode = mode; -+ st->channels[chan->address].syscalib_mode = mode; - - return 0; - } -@@ -329,7 +329,7 @@ static int ad7173_get_syscalib_mode(stru - { - struct ad7173_state *st = iio_priv(indio_dev); - -- return st->channels[chan->channel].syscalib_mode; -+ return st->channels[chan->address].syscalib_mode; - } - - static ssize_t ad7173_write_syscalib(struct iio_dev *indio_dev, -@@ -348,7 +348,7 @@ static ssize_t ad7173_write_syscalib(str - if (!iio_device_claim_direct(indio_dev)) - return -EBUSY; - -- mode = st->channels[chan->channel].syscalib_mode; -+ mode = st->channels[chan->address].syscalib_mode; - if (sys_calib) { - if (mode == AD7173_SYSCALIB_ZERO_SCALE) - ret = ad_sd_calibrate(&st->sd, AD7173_MODE_CAL_SYS_ZERO, -@@ -392,13 +392,12 @@ static int ad7173_calibrate_all(struct a - if (indio_dev->channels[i].type != IIO_VOLTAGE) - continue; - -- ret = ad_sd_calibrate(&st->sd, AD7173_MODE_CAL_INT_ZERO, st->channels[i].ain); -+ ret = ad_sd_calibrate(&st->sd, AD7173_MODE_CAL_INT_ZERO, i); - if (ret < 0) - return ret; - - if (st->info->has_internal_fs_calibration) { -- ret = ad_sd_calibrate(&st->sd, AD7173_MODE_CAL_INT_FULL, -- st->channels[i].ain); -+ ret = ad_sd_calibrate(&st->sd, AD7173_MODE_CAL_INT_FULL, i); - if (ret < 0) - return ret; - } -@@ -563,12 +562,19 @@ static void ad7173_reset_usage_cnts(stru - st->config_usage_counter = 0; - } - --static struct ad7173_channel_config * --ad7173_find_live_config(struct ad7173_state *st, struct ad7173_channel_config *cfg) -+/** -+ * ad7173_is_setup_equal - Compare two channel setups -+ * @cfg1: First channel configuration -+ * @cfg2: Second channel configuration -+ * -+ * Compares all configuration options that affect the registers connected to -+ * SETUP_SEL, namely CONFIGx, FILTERx, GAINx and OFFSETx. -+ * -+ * Returns: true if the setups are identical, false otherwise -+ */ -+static bool ad7173_is_setup_equal(const struct ad7173_channel_config *cfg1, -+ const struct ad7173_channel_config *cfg2) - { -- struct ad7173_channel_config *cfg_aux; -- int i; -- - /* - * This is just to make sure that the comparison is adapted after - * struct ad7173_channel_config was changed. -@@ -581,14 +587,22 @@ ad7173_find_live_config(struct ad7173_st - u8 ref_sel; - })); - -+ return cfg1->bipolar == cfg2->bipolar && -+ cfg1->input_buf == cfg2->input_buf && -+ cfg1->odr == cfg2->odr && -+ cfg1->ref_sel == cfg2->ref_sel; -+} -+ -+static struct ad7173_channel_config * -+ad7173_find_live_config(struct ad7173_state *st, struct ad7173_channel_config *cfg) -+{ -+ struct ad7173_channel_config *cfg_aux; -+ int i; -+ - for (i = 0; i < st->num_channels; i++) { - cfg_aux = &st->channels[i].cfg; - -- if (cfg_aux->live && -- cfg->bipolar == cfg_aux->bipolar && -- cfg->input_buf == cfg_aux->input_buf && -- cfg->odr == cfg_aux->odr && -- cfg->ref_sel == cfg_aux->ref_sel) -+ if (cfg_aux->live && ad7173_is_setup_equal(cfg, cfg_aux)) - return cfg_aux; - } - return NULL; -@@ -772,10 +786,26 @@ static const struct ad_sigma_delta_info - .num_slots = 8, - }; - -+static const struct ad_sigma_delta_info ad7173_sigma_delta_info_16_slots = { -+ .set_channel = ad7173_set_channel, -+ .append_status = ad7173_append_status, -+ .disable_all = ad7173_disable_all, -+ .disable_one = ad7173_disable_one, -+ .set_mode = ad7173_set_mode, -+ .has_registers = true, -+ .has_named_irqs = true, -+ .addr_shift = 0, -+ .read_mask = BIT(6), -+ .status_ch_mask = GENMASK(3, 0), -+ .data_reg = AD7173_REG_DATA, -+ .num_resetclks = 64, -+ .num_slots = 16, -+}; -+ - static const struct ad7173_device_info ad4111_device_info = { - .name = "ad4111", - .id = AD4111_ID, -- .sd_info = &ad7173_sigma_delta_info_8_slots, -+ .sd_info = &ad7173_sigma_delta_info_16_slots, - .num_voltage_in_div = 8, - .num_channels = 16, - .num_configs = 8, -@@ -797,7 +827,7 @@ static const struct ad7173_device_info a - static const struct ad7173_device_info ad4112_device_info = { - .name = "ad4112", - .id = AD4112_ID, -- .sd_info = &ad7173_sigma_delta_info_8_slots, -+ .sd_info = &ad7173_sigma_delta_info_16_slots, - .num_voltage_in_div = 8, - .num_channels = 16, - .num_configs = 8, -@@ -818,7 +848,7 @@ static const struct ad7173_device_info a - static const struct ad7173_device_info ad4113_device_info = { - .name = "ad4113", - .id = AD4113_ID, -- .sd_info = &ad7173_sigma_delta_info_8_slots, -+ .sd_info = &ad7173_sigma_delta_info_16_slots, - .num_voltage_in_div = 8, - .num_channels = 16, - .num_configs = 8, -@@ -837,7 +867,7 @@ static const struct ad7173_device_info a - static const struct ad7173_device_info ad4114_device_info = { - .name = "ad4114", - .id = AD4114_ID, -- .sd_info = &ad7173_sigma_delta_info_8_slots, -+ .sd_info = &ad7173_sigma_delta_info_16_slots, - .num_voltage_in_div = 16, - .num_channels = 16, - .num_configs = 8, -@@ -856,7 +886,7 @@ static const struct ad7173_device_info a - static const struct ad7173_device_info ad4115_device_info = { - .name = "ad4115", - .id = AD4115_ID, -- .sd_info = &ad7173_sigma_delta_info_8_slots, -+ .sd_info = &ad7173_sigma_delta_info_16_slots, - .num_voltage_in_div = 16, - .num_channels = 16, - .num_configs = 8, -@@ -875,7 +905,7 @@ static const struct ad7173_device_info a - static const struct ad7173_device_info ad4116_device_info = { - .name = "ad4116", - .id = AD4116_ID, -- .sd_info = &ad7173_sigma_delta_info_8_slots, -+ .sd_info = &ad7173_sigma_delta_info_16_slots, - .num_voltage_in_div = 11, - .num_channels = 16, - .num_configs = 8, -@@ -894,7 +924,7 @@ static const struct ad7173_device_info a - static const struct ad7173_device_info ad7172_2_device_info = { - .name = "ad7172-2", - .id = AD7172_2_ID, -- .sd_info = &ad7173_sigma_delta_info_8_slots, -+ .sd_info = &ad7173_sigma_delta_info_4_slots, - .num_voltage_in = 5, - .num_channels = 4, - .num_configs = 4, -@@ -927,7 +957,7 @@ static const struct ad7173_device_info a - static const struct ad7173_device_info ad7173_8_device_info = { - .name = "ad7173-8", - .id = AD7173_ID, -- .sd_info = &ad7173_sigma_delta_info_8_slots, -+ .sd_info = &ad7173_sigma_delta_info_16_slots, - .num_voltage_in = 17, - .num_channels = 16, - .num_configs = 8, -@@ -944,7 +974,7 @@ static const struct ad7173_device_info a - static const struct ad7173_device_info ad7175_2_device_info = { - .name = "ad7175-2", - .id = AD7175_2_ID, -- .sd_info = &ad7173_sigma_delta_info_8_slots, -+ .sd_info = &ad7173_sigma_delta_info_4_slots, - .num_voltage_in = 5, - .num_channels = 4, - .num_configs = 4, -@@ -961,7 +991,7 @@ static const struct ad7173_device_info a - static const struct ad7173_device_info ad7175_8_device_info = { - .name = "ad7175-8", - .id = AD7175_8_ID, -- .sd_info = &ad7173_sigma_delta_info_8_slots, -+ .sd_info = &ad7173_sigma_delta_info_16_slots, - .num_voltage_in = 17, - .num_channels = 16, - .num_configs = 8, -@@ -1214,7 +1244,7 @@ static int ad7173_update_scan_mode(struc - const unsigned long *scan_mask) - { - struct ad7173_state *st = iio_priv(indio_dev); -- int i, ret; -+ int i, j, k, ret; - - for (i = 0; i < indio_dev->num_channels; i++) { - if (test_bit(i, scan_mask)) -@@ -1225,6 +1255,54 @@ static int ad7173_update_scan_mode(struc - return ret; - } - -+ /* -+ * On some chips, there are more channels that setups, so if there were -+ * more unique setups requested than the number of available slots, -+ * ad7173_set_channel() will have written over some of the slots. We -+ * can detect this by making sure each assigned cfg_slot matches the -+ * requested configuration. If it doesn't, we know that the slot was -+ * overwritten by a different channel. -+ */ -+ for_each_set_bit(i, scan_mask, indio_dev->num_channels) { -+ const struct ad7173_channel_config *cfg1, *cfg2; -+ -+ cfg1 = &st->channels[i].cfg; -+ -+ for_each_set_bit(j, scan_mask, indio_dev->num_channels) { -+ cfg2 = &st->channels[j].cfg; -+ -+ /* -+ * Only compare configs that are assigned to the same -+ * SETUP_SEL slot and don't compare channel to itself. -+ */ -+ if (i == j || cfg1->cfg_slot != cfg2->cfg_slot) -+ continue; -+ -+ /* -+ * If we find two different configs trying to use the -+ * same SETUP_SEL slot, then we know that the that we -+ * have too many unique configurations requested for -+ * the available slots and at least one was overwritten. -+ */ -+ if (!ad7173_is_setup_equal(cfg1, cfg2)) { -+ /* -+ * At this point, there isn't a way to tell -+ * which setups are actually programmed in the -+ * ADC anymore, so we could read them back to -+ * see, but it is simpler to just turn off all -+ * of the live flags so that everything gets -+ * reprogramed on the next attempt read a sample. -+ */ -+ for (k = 0; k < st->num_channels; k++) -+ st->channels[k].cfg.live = false; -+ -+ dev_err(&st->sd.spi->dev, -+ "Too many unique channel configurations requested for scan\n"); -+ return -EINVAL; -+ } -+ } -+ } -+ - return 0; - } - -@@ -1580,6 +1658,7 @@ static int ad7173_fw_parse_channel_confi - chan_st_priv->cfg.bipolar = false; - chan_st_priv->cfg.input_buf = st->info->has_input_buf; - chan_st_priv->cfg.ref_sel = AD7173_SETUP_REF_SEL_INT_REF; -+ chan_st_priv->cfg.odr = st->info->odr_start_value; - chan_st_priv->cfg.openwire_comp_chan = -1; - st->adc_mode |= AD7173_ADC_MODE_REF_EN; - if (st->info->data_reg_only_16bit) -@@ -1646,7 +1725,7 @@ static int ad7173_fw_parse_channel_confi - chan->scan_index = chan_index; - chan->channel = ain[0]; - chan_st_priv->cfg.input_buf = st->info->has_input_buf; -- chan_st_priv->cfg.odr = 0; -+ chan_st_priv->cfg.odr = st->info->odr_start_value; - chan_st_priv->cfg.openwire_comp_chan = -1; - - chan_st_priv->cfg.bipolar = fwnode_property_read_bool(child, "bipolar"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/adc/ad7380.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/ad7380.c ---- BPI-Router-Linux-kernel/drivers/iio/adc/ad7380.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/ad7380.c 2025-10-22 13:53:56.503169199 -0400 -@@ -873,6 +873,7 @@ static const struct ad7380_chip_info ada - .has_hardware_gain = true, - .available_scan_masks = ad7380_4_channel_scan_masks, - .timing_specs = &ad7380_4_timing, -+ .max_conversion_rate_hz = 4 * MEGA, - }; - - static const struct spi_offload_config ad7380_offload_config = { -@@ -1953,8 +1954,9 @@ static int ad7380_probe(struct spi_devic - - if (st->chip_info->has_hardware_gain) { - device_for_each_child_node_scoped(dev, node) { -- unsigned int channel, gain; -+ unsigned int channel; - int gain_idx; -+ u16 gain; - - ret = fwnode_property_read_u32(node, "reg", &channel); - if (ret) -@@ -1966,7 +1968,7 @@ static int ad7380_probe(struct spi_devic - "Invalid channel number %i\n", - channel); - -- ret = fwnode_property_read_u32(node, "adi,gain-milli", -+ ret = fwnode_property_read_u16(node, "adi,gain-milli", - &gain); - if (ret && ret != -EINVAL) - return dev_err_probe(dev, ret, -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/adc/ad7768-1.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/ad7768-1.c ---- BPI-Router-Linux-kernel/drivers/iio/adc/ad7768-1.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/ad7768-1.c 2025-10-22 13:53:56.503169199 -0400 -@@ -252,6 +252,24 @@ static const struct regmap_config ad7768 - .max_register = AD7768_REG24_COEFF_DATA, - }; - -+static int ad7768_send_sync_pulse(struct ad7768_state *st) -+{ -+ /* -+ * The datasheet specifies a minimum SYNC_IN pulse width of 1.5 × Tmclk, -+ * where Tmclk is the MCLK period. The supported MCLK frequencies range -+ * from 0.6 MHz to 17 MHz, which corresponds to a minimum SYNC_IN pulse -+ * width of approximately 2.5 µs in the worst-case scenario (0.6 MHz). -+ * -+ * Add a delay to ensure the pulse width is always sufficient to -+ * trigger synchronization. -+ */ -+ gpiod_set_value_cansleep(st->gpio_sync_in, 1); -+ fsleep(3); -+ gpiod_set_value_cansleep(st->gpio_sync_in, 0); -+ -+ return 0; -+} -+ - static int ad7768_set_mode(struct ad7768_state *st, - enum ad7768_conv_mode mode) - { -@@ -339,10 +357,7 @@ static int ad7768_set_dig_fil(struct ad7 - return ret; - - /* A sync-in pulse is required every time the filter dec rate changes */ -- gpiod_set_value(st->gpio_sync_in, 1); -- gpiod_set_value(st->gpio_sync_in, 0); -- -- return 0; -+ return ad7768_send_sync_pulse(st); - } - - static int ad7768_set_freq(struct ad7768_state *st, -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/adc/ad7949.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/ad7949.c ---- BPI-Router-Linux-kernel/drivers/iio/adc/ad7949.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/ad7949.c 2025-10-22 13:53:56.503169199 -0400 -@@ -308,7 +308,6 @@ static void ad7949_disable_reg(void *reg - - static int ad7949_spi_probe(struct spi_device *spi) - { -- u32 spi_ctrl_mask = spi->controller->bits_per_word_mask; - struct device *dev = &spi->dev; - const struct ad7949_adc_spec *spec; - struct ad7949_adc_chip *ad7949_adc; -@@ -337,11 +336,11 @@ static int ad7949_spi_probe(struct spi_d - ad7949_adc->resolution = spec->resolution; - - /* Set SPI bits per word */ -- if (spi_ctrl_mask & SPI_BPW_MASK(ad7949_adc->resolution)) { -+ if (spi_is_bpw_supported(spi, ad7949_adc->resolution)) { - spi->bits_per_word = ad7949_adc->resolution; -- } else if (spi_ctrl_mask == SPI_BPW_MASK(16)) { -+ } else if (spi_is_bpw_supported(spi, 16)) { - spi->bits_per_word = 16; -- } else if (spi_ctrl_mask == SPI_BPW_MASK(8)) { -+ } else if (spi_is_bpw_supported(spi, 8)) { - spi->bits_per_word = 8; - } else { - dev_err(dev, "unable to find common BPW with spi controller\n"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/adc/adi-axi-adc.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/adi-axi-adc.c ---- BPI-Router-Linux-kernel/drivers/iio/adc/adi-axi-adc.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/adi-axi-adc.c 2025-10-22 13:53:56.503169199 -0400 -@@ -445,7 +445,7 @@ static int axi_adc_raw_read(struct iio_b - static int ad7606_bus_reg_read(struct iio_backend *back, u32 reg, u32 *val) - { - struct adi_axi_adc_state *st = iio_backend_get_priv(back); -- int addr; -+ u32 addr, reg_val; - - guard(mutex)(&st->lock); - -@@ -455,7 +455,9 @@ static int ad7606_bus_reg_read(struct ii - */ - addr = FIELD_PREP(ADI_AXI_REG_ADDRESS_MASK, reg) | ADI_AXI_REG_READ_BIT; - axi_adc_raw_write(back, addr); -- axi_adc_raw_read(back, val); -+ axi_adc_raw_read(back, ®_val); -+ -+ *val = FIELD_GET(ADI_AXI_REG_VALUE_MASK, reg_val); - - /* Write 0x0 on the bus to get back to ADC mode */ - axi_adc_raw_write(back, 0); -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/adc/ad_sigma_delta.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/ad_sigma_delta.c ---- BPI-Router-Linux-kernel/drivers/iio/adc/ad_sigma_delta.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/ad_sigma_delta.c 2025-10-22 13:53:56.503169199 -0400 -@@ -489,7 +489,7 @@ static int ad_sd_buffer_postenable(struc - return ret; - } - -- samples_buf_size = ALIGN(slot * indio_dev->channels[0].scan_type.storagebits, 8); -+ samples_buf_size = ALIGN(slot * indio_dev->channels[0].scan_type.storagebits / 8, 8); - samples_buf_size += sizeof(int64_t); - samples_buf = devm_krealloc(&sigma_delta->spi->dev, sigma_delta->samples_buf, - samples_buf_size, GFP_KERNEL); -@@ -520,7 +520,7 @@ err_unlock: - return ret; - } - --static int ad_sd_buffer_postdisable(struct iio_dev *indio_dev) -+static int ad_sd_buffer_predisable(struct iio_dev *indio_dev) - { - struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev); - -@@ -644,7 +644,7 @@ static bool ad_sd_validate_scan_mask(str - - static const struct iio_buffer_setup_ops ad_sd_buffer_setup_ops = { - .postenable = &ad_sd_buffer_postenable, -- .postdisable = &ad_sd_buffer_postdisable, -+ .predisable = &ad_sd_buffer_predisable, - .validate_scan_mask = &ad_sd_validate_scan_mask, - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/adc/axp20x_adc.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/axp20x_adc.c ---- BPI-Router-Linux-kernel/drivers/iio/adc/axp20x_adc.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/axp20x_adc.c 2025-10-22 13:53:56.503169199 -0400 -@@ -187,6 +187,7 @@ static struct iio_map axp717_maps[] = { - .consumer_channel = "batt_chrg_i", - .adc_channel_label = "batt_chrg_i", - }, -+ { } - }; - - /* -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/adc/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/Kconfig ---- BPI-Router-Linux-kernel/drivers/iio/adc/Kconfig 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/Kconfig 2025-10-22 13:53:56.503169199 -0400 -@@ -1257,7 +1257,7 @@ config RN5T618_ADC - - config ROHM_BD79124 - tristate "Rohm BD79124 ADC driver" -- depends on I2C -+ depends on I2C && GPIOLIB - select REGMAP_I2C - select IIO_ADC_HELPER - help -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/adc/max1363.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/max1363.c ---- BPI-Router-Linux-kernel/drivers/iio/adc/max1363.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/max1363.c 2025-10-22 13:53:56.503169199 -0400 -@@ -511,10 +511,10 @@ static const struct iio_event_spec max13 - MAX1363_CHAN_U(1, _s1, 1, bits, ev_spec, num_ev_spec), \ - MAX1363_CHAN_U(2, _s2, 2, bits, ev_spec, num_ev_spec), \ - MAX1363_CHAN_U(3, _s3, 3, bits, ev_spec, num_ev_spec), \ -- MAX1363_CHAN_B(0, 1, d0m1, 4, bits, ev_spec, num_ev_spec), \ -- MAX1363_CHAN_B(2, 3, d2m3, 5, bits, ev_spec, num_ev_spec), \ -- MAX1363_CHAN_B(1, 0, d1m0, 6, bits, ev_spec, num_ev_spec), \ -- MAX1363_CHAN_B(3, 2, d3m2, 7, bits, ev_spec, num_ev_spec), \ -+ MAX1363_CHAN_B(0, 1, d0m1, 12, bits, ev_spec, num_ev_spec), \ -+ MAX1363_CHAN_B(2, 3, d2m3, 13, bits, ev_spec, num_ev_spec), \ -+ MAX1363_CHAN_B(1, 0, d1m0, 18, bits, ev_spec, num_ev_spec), \ -+ MAX1363_CHAN_B(3, 2, d3m2, 19, bits, ev_spec, num_ev_spec), \ - IIO_CHAN_SOFT_TIMESTAMP(8) \ - } - -@@ -532,23 +532,23 @@ static const struct iio_chan_spec max136 - /* Applies to max1236, max1237 */ - static const enum max1363_modes max1236_mode_list[] = { - _s0, _s1, _s2, _s3, -- s0to1, s0to2, s0to3, -+ s0to1, s0to2, s2to3, s0to3, - d0m1, d2m3, d1m0, d3m2, - d0m1to2m3, d1m0to3m2, -- s2to3, - }; - - /* Applies to max1238, max1239 */ - static const enum max1363_modes max1238_mode_list[] = { - _s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s10, _s11, - s0to1, s0to2, s0to3, s0to4, s0to5, s0to6, -+ s6to7, s6to8, s6to9, s6to10, s6to11, - s0to7, s0to8, s0to9, s0to10, s0to11, - d0m1, d2m3, d4m5, d6m7, d8m9, d10m11, - d1m0, d3m2, d5m4, d7m6, d9m8, d11m10, -- d0m1to2m3, d0m1to4m5, d0m1to6m7, d0m1to8m9, d0m1to10m11, -- d1m0to3m2, d1m0to5m4, d1m0to7m6, d1m0to9m8, d1m0to11m10, -- s6to7, s6to8, s6to9, s6to10, s6to11, -- d6m7to8m9, d6m7to10m11, d7m6to9m8, d7m6to11m10, -+ d0m1to2m3, d0m1to4m5, d0m1to6m7, d6m7to8m9, -+ d0m1to8m9, d6m7to10m11, d0m1to10m11, d1m0to3m2, -+ d1m0to5m4, d1m0to7m6, d7m6to9m8, d1m0to9m8, -+ d7m6to11m10, d1m0to11m10, - }; - - #define MAX1363_12X_CHANS(bits) { \ -@@ -584,16 +584,15 @@ static const struct iio_chan_spec max123 - - static const enum max1363_modes max11607_mode_list[] = { - _s0, _s1, _s2, _s3, -- s0to1, s0to2, s0to3, -- s2to3, -+ s0to1, s0to2, s2to3, -+ s0to3, - d0m1, d2m3, d1m0, d3m2, - d0m1to2m3, d1m0to3m2, - }; - - static const enum max1363_modes max11608_mode_list[] = { - _s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, -- s0to1, s0to2, s0to3, s0to4, s0to5, s0to6, s0to7, -- s6to7, -+ s0to1, s0to2, s0to3, s0to4, s0to5, s0to6, s6to7, s0to7, - d0m1, d2m3, d4m5, d6m7, - d1m0, d3m2, d5m4, d7m6, - d0m1to2m3, d0m1to4m5, d0m1to6m7, -@@ -609,14 +608,14 @@ static const enum max1363_modes max11608 - MAX1363_CHAN_U(5, _s5, 5, bits, NULL, 0), \ - MAX1363_CHAN_U(6, _s6, 6, bits, NULL, 0), \ - MAX1363_CHAN_U(7, _s7, 7, bits, NULL, 0), \ -- MAX1363_CHAN_B(0, 1, d0m1, 8, bits, NULL, 0), \ -- MAX1363_CHAN_B(2, 3, d2m3, 9, bits, NULL, 0), \ -- MAX1363_CHAN_B(4, 5, d4m5, 10, bits, NULL, 0), \ -- MAX1363_CHAN_B(6, 7, d6m7, 11, bits, NULL, 0), \ -- MAX1363_CHAN_B(1, 0, d1m0, 12, bits, NULL, 0), \ -- MAX1363_CHAN_B(3, 2, d3m2, 13, bits, NULL, 0), \ -- MAX1363_CHAN_B(5, 4, d5m4, 14, bits, NULL, 0), \ -- MAX1363_CHAN_B(7, 6, d7m6, 15, bits, NULL, 0), \ -+ MAX1363_CHAN_B(0, 1, d0m1, 12, bits, NULL, 0), \ -+ MAX1363_CHAN_B(2, 3, d2m3, 13, bits, NULL, 0), \ -+ MAX1363_CHAN_B(4, 5, d4m5, 14, bits, NULL, 0), \ -+ MAX1363_CHAN_B(6, 7, d6m7, 15, bits, NULL, 0), \ -+ MAX1363_CHAN_B(1, 0, d1m0, 18, bits, NULL, 0), \ -+ MAX1363_CHAN_B(3, 2, d3m2, 19, bits, NULL, 0), \ -+ MAX1363_CHAN_B(5, 4, d5m4, 20, bits, NULL, 0), \ -+ MAX1363_CHAN_B(7, 6, d7m6, 21, bits, NULL, 0), \ - IIO_CHAN_SOFT_TIMESTAMP(16) \ - } - static const struct iio_chan_spec max11602_channels[] = MAX1363_8X_CHANS(8); -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/adc/rzg2l_adc.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/rzg2l_adc.c ---- BPI-Router-Linux-kernel/drivers/iio/adc/rzg2l_adc.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/rzg2l_adc.c 2025-10-22 13:53:56.503169199 -0400 -@@ -89,7 +89,6 @@ struct rzg2l_adc { - struct completion completion; - struct mutex lock; - u16 last_val[RZG2L_ADC_MAX_CHANNELS]; -- bool was_rpm_active; - }; - - /** -@@ -428,6 +427,8 @@ static int rzg2l_adc_probe(struct platfo - if (!indio_dev) - return -ENOMEM; - -+ platform_set_drvdata(pdev, indio_dev); -+ - adc = iio_priv(indio_dev); - - adc->hw_params = device_get_match_data(dev); -@@ -460,8 +461,6 @@ static int rzg2l_adc_probe(struct platfo - if (ret) - return ret; - -- platform_set_drvdata(pdev, indio_dev); -- - ret = rzg2l_adc_hw_init(dev, adc); - if (ret) - return dev_err_probe(&pdev->dev, ret, -@@ -541,14 +540,9 @@ static int rzg2l_adc_suspend(struct devi - }; - int ret; - -- if (pm_runtime_suspended(dev)) { -- adc->was_rpm_active = false; -- } else { -- ret = pm_runtime_force_suspend(dev); -- if (ret) -- return ret; -- adc->was_rpm_active = true; -- } -+ ret = pm_runtime_force_suspend(dev); -+ if (ret) -+ return ret; - - ret = reset_control_bulk_assert(ARRAY_SIZE(resets), resets); - if (ret) -@@ -557,9 +551,7 @@ static int rzg2l_adc_suspend(struct devi - return 0; - - rpm_restore: -- if (adc->was_rpm_active) -- pm_runtime_force_resume(dev); -- -+ pm_runtime_force_resume(dev); - return ret; - } - -@@ -577,11 +569,9 @@ static int rzg2l_adc_resume(struct devic - if (ret) - return ret; - -- if (adc->was_rpm_active) { -- ret = pm_runtime_force_resume(dev); -- if (ret) -- goto resets_restore; -- } -+ ret = pm_runtime_force_resume(dev); -+ if (ret) -+ goto resets_restore; - - ret = rzg2l_adc_hw_init(dev, adc); - if (ret) -@@ -590,10 +580,7 @@ static int rzg2l_adc_resume(struct devic - return 0; - - rpm_restore: -- if (adc->was_rpm_active) { -- pm_runtime_mark_last_busy(dev); -- pm_runtime_put_autosuspend(dev); -- } -+ pm_runtime_force_suspend(dev); - resets_restore: - reset_control_bulk_assert(ARRAY_SIZE(resets), resets); - return ret; -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/adc/stm32-adc-core.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/stm32-adc-core.c ---- BPI-Router-Linux-kernel/drivers/iio/adc/stm32-adc-core.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/adc/stm32-adc-core.c 2025-10-22 13:53:56.503169199 -0400 -@@ -430,10 +430,9 @@ static int stm32_adc_irq_probe(struct pl - return -ENOMEM; - } - -- for (i = 0; i < priv->cfg->num_irqs; i++) { -- irq_set_chained_handler(priv->irq[i], stm32_adc_irq_handler); -- irq_set_handler_data(priv->irq[i], priv); -- } -+ for (i = 0; i < priv->cfg->num_irqs; i++) -+ irq_set_chained_handler_and_data(priv->irq[i], -+ stm32_adc_irq_handler, priv); - - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/common/st_sensors/st_sensors_core.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/common/st_sensors/st_sensors_core.c ---- BPI-Router-Linux-kernel/drivers/iio/common/st_sensors/st_sensors_core.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/common/st_sensors/st_sensors_core.c 2025-10-22 13:53:56.503169199 -0400 -@@ -154,7 +154,7 @@ static int st_sensors_set_fullscale(stru - return err; - - st_accel_set_fullscale_error: -- dev_err(&indio_dev->dev, "failed to set new fullscale.\n"); -+ dev_err(indio_dev->dev.parent, "failed to set new fullscale.\n"); - return err; - } - -@@ -231,8 +231,7 @@ int st_sensors_power_enable(struct iio_d - ARRAY_SIZE(regulator_names), - regulator_names); - if (err) -- return dev_err_probe(&indio_dev->dev, err, -- "unable to enable supplies\n"); -+ return dev_err_probe(parent, err, "unable to enable supplies\n"); - - return 0; - } -@@ -241,13 +240,14 @@ EXPORT_SYMBOL_NS(st_sensors_power_enable - static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev, - struct st_sensors_platform_data *pdata) - { -+ struct device *parent = indio_dev->dev.parent; - struct st_sensor_data *sdata = iio_priv(indio_dev); - - /* Sensor does not support interrupts */ - if (!sdata->sensor_settings->drdy_irq.int1.addr && - !sdata->sensor_settings->drdy_irq.int2.addr) { - if (pdata->drdy_int_pin) -- dev_info(&indio_dev->dev, -+ dev_info(parent, - "DRDY on pin INT%d specified, but sensor does not support interrupts\n", - pdata->drdy_int_pin); - return 0; -@@ -256,29 +256,27 @@ static int st_sensors_set_drdy_int_pin(s - switch (pdata->drdy_int_pin) { - case 1: - if (!sdata->sensor_settings->drdy_irq.int1.mask) { -- dev_err(&indio_dev->dev, -- "DRDY on INT1 not available.\n"); -+ dev_err(parent, "DRDY on INT1 not available.\n"); - return -EINVAL; - } - sdata->drdy_int_pin = 1; - break; - case 2: - if (!sdata->sensor_settings->drdy_irq.int2.mask) { -- dev_err(&indio_dev->dev, -- "DRDY on INT2 not available.\n"); -+ dev_err(parent, "DRDY on INT2 not available.\n"); - return -EINVAL; - } - sdata->drdy_int_pin = 2; - break; - default: -- dev_err(&indio_dev->dev, "DRDY on pdata not valid.\n"); -+ dev_err(parent, "DRDY on pdata not valid.\n"); - return -EINVAL; - } - - if (pdata->open_drain) { - if (!sdata->sensor_settings->drdy_irq.int1.addr_od && - !sdata->sensor_settings->drdy_irq.int2.addr_od) -- dev_err(&indio_dev->dev, -+ dev_err(parent, - "open drain requested but unsupported.\n"); - else - sdata->int_pin_open_drain = true; -@@ -336,6 +334,7 @@ EXPORT_SYMBOL_NS(st_sensors_dev_name_pro - int st_sensors_init_sensor(struct iio_dev *indio_dev, - struct st_sensors_platform_data *pdata) - { -+ struct device *parent = indio_dev->dev.parent; - struct st_sensor_data *sdata = iio_priv(indio_dev); - struct st_sensors_platform_data *of_pdata; - int err = 0; -@@ -343,7 +342,7 @@ int st_sensors_init_sensor(struct iio_de - mutex_init(&sdata->odr_lock); - - /* If OF/DT pdata exists, it will take precedence of anything else */ -- of_pdata = st_sensors_dev_probe(indio_dev->dev.parent, pdata); -+ of_pdata = st_sensors_dev_probe(parent, pdata); - if (IS_ERR(of_pdata)) - return PTR_ERR(of_pdata); - if (of_pdata) -@@ -370,7 +369,7 @@ int st_sensors_init_sensor(struct iio_de - if (err < 0) - return err; - } else -- dev_info(&indio_dev->dev, "Full-scale not possible\n"); -+ dev_info(parent, "Full-scale not possible\n"); - - err = st_sensors_set_odr(indio_dev, sdata->odr); - if (err < 0) -@@ -405,7 +404,7 @@ int st_sensors_init_sensor(struct iio_de - mask = sdata->sensor_settings->drdy_irq.int2.mask_od; - } - -- dev_info(&indio_dev->dev, -+ dev_info(parent, - "set interrupt line to open drain mode on pin %d\n", - sdata->drdy_int_pin); - err = st_sensors_write_data_with_mask(indio_dev, addr, -@@ -593,21 +592,20 @@ EXPORT_SYMBOL_NS(st_sensors_get_settings - int st_sensors_verify_id(struct iio_dev *indio_dev) - { - struct st_sensor_data *sdata = iio_priv(indio_dev); -+ struct device *parent = indio_dev->dev.parent; - int wai, err; - - if (sdata->sensor_settings->wai_addr) { - err = regmap_read(sdata->regmap, - sdata->sensor_settings->wai_addr, &wai); - if (err < 0) { -- dev_err(&indio_dev->dev, -- "failed to read Who-Am-I register.\n"); -- return err; -+ return dev_err_probe(parent, err, -+ "failed to read Who-Am-I register.\n"); - } - - if (sdata->sensor_settings->wai != wai) { -- dev_warn(&indio_dev->dev, -- "%s: WhoAmI mismatch (0x%x).\n", -- indio_dev->name, wai); -+ dev_warn(parent, "%s: WhoAmI mismatch (0x%x).\n", -+ indio_dev->name, wai); - } - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/common/st_sensors/st_sensors_trigger.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/common/st_sensors/st_sensors_trigger.c ---- BPI-Router-Linux-kernel/drivers/iio/common/st_sensors/st_sensors_trigger.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/common/st_sensors/st_sensors_trigger.c 2025-10-22 13:53:56.503169199 -0400 -@@ -127,7 +127,7 @@ int st_sensors_allocate_trigger(struct i - sdata->trig = devm_iio_trigger_alloc(parent, "%s-trigger", - indio_dev->name); - if (sdata->trig == NULL) { -- dev_err(&indio_dev->dev, "failed to allocate iio trigger.\n"); -+ dev_err(parent, "failed to allocate iio trigger.\n"); - return -ENOMEM; - } - -@@ -143,7 +143,7 @@ int st_sensors_allocate_trigger(struct i - case IRQF_TRIGGER_FALLING: - case IRQF_TRIGGER_LOW: - if (!sdata->sensor_settings->drdy_irq.addr_ihl) { -- dev_err(&indio_dev->dev, -+ dev_err(parent, - "falling/low specified for IRQ but hardware supports only rising/high: will request rising/high\n"); - if (irq_trig == IRQF_TRIGGER_FALLING) - irq_trig = IRQF_TRIGGER_RISING; -@@ -156,21 +156,19 @@ int st_sensors_allocate_trigger(struct i - sdata->sensor_settings->drdy_irq.mask_ihl, 1); - if (err < 0) - return err; -- dev_info(&indio_dev->dev, -+ dev_info(parent, - "interrupts on the falling edge or active low level\n"); - } - break; - case IRQF_TRIGGER_RISING: -- dev_info(&indio_dev->dev, -- "interrupts on the rising edge\n"); -+ dev_info(parent, "interrupts on the rising edge\n"); - break; - case IRQF_TRIGGER_HIGH: -- dev_info(&indio_dev->dev, -- "interrupts active high level\n"); -+ dev_info(parent, "interrupts active high level\n"); - break; - default: - /* This is the most preferred mode, if possible */ -- dev_err(&indio_dev->dev, -+ dev_err(parent, - "unsupported IRQ trigger specified (%lx), enforce rising edge\n", irq_trig); - irq_trig = IRQF_TRIGGER_RISING; - } -@@ -179,7 +177,7 @@ int st_sensors_allocate_trigger(struct i - if (irq_trig == IRQF_TRIGGER_FALLING || - irq_trig == IRQF_TRIGGER_RISING) { - if (!sdata->sensor_settings->drdy_irq.stat_drdy.addr) { -- dev_err(&indio_dev->dev, -+ dev_err(parent, - "edge IRQ not supported w/o stat register.\n"); - return -EOPNOTSUPP; - } -@@ -214,13 +212,13 @@ int st_sensors_allocate_trigger(struct i - sdata->trig->name, - sdata->trig); - if (err) { -- dev_err(&indio_dev->dev, "failed to request trigger IRQ.\n"); -+ dev_err(parent, "failed to request trigger IRQ.\n"); - return err; - } - - err = devm_iio_trigger_register(parent, sdata->trig); - if (err < 0) { -- dev_err(&indio_dev->dev, "failed to register iio trigger.\n"); -+ dev_err(parent, "failed to register iio trigger.\n"); - return err; - } - indio_dev->trig = iio_trigger_get(sdata->trig); -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/dac/ad3530r.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/dac/ad3530r.c ---- BPI-Router-Linux-kernel/drivers/iio/dac/ad3530r.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/dac/ad3530r.c 2025-10-22 13:53:56.503169199 -0400 -@@ -166,7 +166,9 @@ static ssize_t ad3530r_set_dac_powerdown - AD3530R_OUTPUT_OPERATING_MODE_0 : - AD3530R_OUTPUT_OPERATING_MODE_1; - pdmode = powerdown ? st->chan[chan->channel].powerdown_mode : 0; -- mask = AD3530R_OP_MODE_CHAN_MSK(chan->channel); -+ mask = chan->channel < AD3531R_MAX_CHANNELS ? -+ AD3530R_OP_MODE_CHAN_MSK(chan->channel) : -+ AD3530R_OP_MODE_CHAN_MSK(chan->channel - 4); - val = field_prep(mask, pdmode); - - ret = regmap_update_bits(st->regmap, reg, mask, val); -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/imu/bno055/bno055.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/imu/bno055/bno055.c ---- BPI-Router-Linux-kernel/drivers/iio/imu/bno055/bno055.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/imu/bno055/bno055.c 2025-10-22 13:53:56.503169199 -0400 -@@ -118,6 +118,7 @@ struct bno055_sysfs_attr { - int len; - int *fusion_vals; - int *hw_xlate; -+ int hw_xlate_len; - int type; - }; - -@@ -170,20 +171,24 @@ static int bno055_gyr_scale_vals[] = { - 1000, 1877467, 2000, 1877467, - }; - -+static int bno055_gyr_scale_hw_xlate[] = {0, 1, 2, 3, 4}; - static struct bno055_sysfs_attr bno055_gyr_scale = { - .vals = bno055_gyr_scale_vals, - .len = ARRAY_SIZE(bno055_gyr_scale_vals), - .fusion_vals = (int[]){1, 900}, -- .hw_xlate = (int[]){4, 3, 2, 1, 0}, -+ .hw_xlate = bno055_gyr_scale_hw_xlate, -+ .hw_xlate_len = ARRAY_SIZE(bno055_gyr_scale_hw_xlate), - .type = IIO_VAL_FRACTIONAL, - }; - - static int bno055_gyr_lpf_vals[] = {12, 23, 32, 47, 64, 116, 230, 523}; -+static int bno055_gyr_lpf_hw_xlate[] = {5, 4, 7, 3, 6, 2, 1, 0}; - static struct bno055_sysfs_attr bno055_gyr_lpf = { - .vals = bno055_gyr_lpf_vals, - .len = ARRAY_SIZE(bno055_gyr_lpf_vals), - .fusion_vals = (int[]){32}, -- .hw_xlate = (int[]){5, 4, 7, 3, 6, 2, 1, 0}, -+ .hw_xlate = bno055_gyr_lpf_hw_xlate, -+ .hw_xlate_len = ARRAY_SIZE(bno055_gyr_lpf_hw_xlate), - .type = IIO_VAL_INT, - }; - -@@ -561,7 +566,7 @@ static int bno055_get_regmask(struct bno - - idx = (hwval & mask) >> shift; - if (attr->hw_xlate) -- for (i = 0; i < attr->len; i++) -+ for (i = 0; i < attr->hw_xlate_len; i++) - if (attr->hw_xlate[i] == idx) { - idx = i; - break; -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c ---- BPI-Router-Linux-kernel/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c 2025-10-22 13:53:56.503169199 -0400 -@@ -177,7 +177,7 @@ static const struct iio_chan_spec inv_ic - */ - struct inv_icm42600_accel_buffer { - struct inv_icm42600_fifo_sensor_data accel; -- int16_t temp; -+ s16 temp; - aligned_s64 timestamp; - }; - -@@ -241,7 +241,7 @@ out_unlock: - - static int inv_icm42600_accel_read_sensor(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, -- int16_t *val) -+ s16 *val) - { - struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); - struct inv_icm42600_sensor_state *accel_st = iio_priv(indio_dev); -@@ -284,7 +284,7 @@ static int inv_icm42600_accel_read_senso - if (ret) - goto exit; - -- *val = (int16_t)be16_to_cpup(data); -+ *val = (s16)be16_to_cpup(data); - if (*val == INV_ICM42600_DATA_INVALID) - ret = -EINVAL; - exit: -@@ -492,11 +492,11 @@ static int inv_icm42600_accel_read_offse - int *val, int *val2) - { - struct device *dev = regmap_get_device(st->map); -- int64_t val64; -- int32_t bias; -+ s64 val64; -+ s32 bias; - unsigned int reg; -- int16_t offset; -- uint8_t data[2]; -+ s16 offset; -+ u8 data[2]; - int ret; - - if (chan->type != IIO_ACCEL) -@@ -550,7 +550,7 @@ static int inv_icm42600_accel_read_offse - * result in micro (1000000) - * (offset * 5 * 9.806650 * 1000000) / 10000 - */ -- val64 = (int64_t)offset * 5LL * 9806650LL; -+ val64 = (s64)offset * 5LL * 9806650LL; - /* for rounding, add + or - divisor (10000) divided by 2 */ - if (val64 >= 0) - val64 += 10000LL / 2LL; -@@ -568,10 +568,10 @@ static int inv_icm42600_accel_write_offs - int val, int val2) - { - struct device *dev = regmap_get_device(st->map); -- int64_t val64; -- int32_t min, max; -+ s64 val64; -+ s32 min, max; - unsigned int reg, regval; -- int16_t offset; -+ s16 offset; - int ret; - - if (chan->type != IIO_ACCEL) -@@ -596,7 +596,7 @@ static int inv_icm42600_accel_write_offs - inv_icm42600_accel_calibbias[1]; - max = inv_icm42600_accel_calibbias[4] * 1000000L + - inv_icm42600_accel_calibbias[5]; -- val64 = (int64_t)val * 1000000LL + (int64_t)val2; -+ val64 = (s64)val * 1000000LL + (s64)val2; - if (val64 < min || val64 > max) - return -EINVAL; - -@@ -671,7 +671,7 @@ static int inv_icm42600_accel_read_raw(s - int *val, int *val2, long mask) - { - struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); -- int16_t data; -+ s16 data; - int ret; - - switch (chan->type) { -@@ -902,7 +902,8 @@ int inv_icm42600_accel_parse_fifo(struct - const int8_t *temp; - unsigned int odr; - int64_t ts_val; -- struct inv_icm42600_accel_buffer buffer; -+ /* buffer is copied to userspace, zeroing it to avoid any data leak */ -+ struct inv_icm42600_accel_buffer buffer = { }; - - /* parse all fifo packets */ - for (i = 0, no = 0; i < st->fifo.count; i += size, ++no) { -@@ -921,8 +922,6 @@ int inv_icm42600_accel_parse_fifo(struct - inv_sensors_timestamp_apply_odr(ts, st->fifo.period, - st->fifo.nb.total, no); - -- /* buffer is copied to userspace, zeroing it to avoid any data leak */ -- memset(&buffer, 0, sizeof(buffer)); - memcpy(&buffer.accel, accel, sizeof(buffer.accel)); - /* convert 8 bits FIFO temperature in high resolution format */ - buffer.temp = temp ? (*temp * 64) : 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c ---- BPI-Router-Linux-kernel/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c 2025-10-22 13:53:56.503169199 -0400 -@@ -26,28 +26,28 @@ - #define INV_ICM42600_FIFO_HEADER_ODR_GYRO BIT(0) - - struct inv_icm42600_fifo_1sensor_packet { -- uint8_t header; -+ u8 header; - struct inv_icm42600_fifo_sensor_data data; -- int8_t temp; -+ s8 temp; - } __packed; - #define INV_ICM42600_FIFO_1SENSOR_PACKET_SIZE 8 - - struct inv_icm42600_fifo_2sensors_packet { -- uint8_t header; -+ u8 header; - struct inv_icm42600_fifo_sensor_data accel; - struct inv_icm42600_fifo_sensor_data gyro; -- int8_t temp; -+ s8 temp; - __be16 timestamp; - } __packed; - #define INV_ICM42600_FIFO_2SENSORS_PACKET_SIZE 16 - - ssize_t inv_icm42600_fifo_decode_packet(const void *packet, const void **accel, -- const void **gyro, const int8_t **temp, -+ const void **gyro, const s8 **temp, - const void **timestamp, unsigned int *odr) - { - const struct inv_icm42600_fifo_1sensor_packet *pack1 = packet; - const struct inv_icm42600_fifo_2sensors_packet *pack2 = packet; -- uint8_t header = *((const uint8_t *)packet); -+ u8 header = *((const u8 *)packet); - - /* FIFO empty */ - if (header & INV_ICM42600_FIFO_HEADER_MSG) { -@@ -100,7 +100,7 @@ ssize_t inv_icm42600_fifo_decode_packet( - - void inv_icm42600_buffer_update_fifo_period(struct inv_icm42600_state *st) - { -- uint32_t period_gyro, period_accel, period; -+ u32 period_gyro, period_accel, period; - - if (st->fifo.en & INV_ICM42600_SENSOR_GYRO) - period_gyro = inv_icm42600_odr_to_period(st->conf.gyro.odr); -@@ -204,8 +204,8 @@ int inv_icm42600_buffer_update_watermark - { - size_t packet_size, wm_size; - unsigned int wm_gyro, wm_accel, watermark; -- uint32_t period_gyro, period_accel, period; -- uint32_t latency_gyro, latency_accel, latency; -+ u32 period_gyro, period_accel, period; -+ u32 latency_gyro, latency_accel, latency; - bool restore; - __le16 raw_wm; - int ret; -@@ -459,7 +459,7 @@ int inv_icm42600_buffer_fifo_read(struct - __be16 *raw_fifo_count; - ssize_t i, size; - const void *accel, *gyro, *timestamp; -- const int8_t *temp; -+ const s8 *temp; - unsigned int odr; - int ret; - -@@ -550,7 +550,7 @@ int inv_icm42600_buffer_hwfifo_flush(str - struct inv_icm42600_sensor_state *gyro_st = iio_priv(st->indio_gyro); - struct inv_icm42600_sensor_state *accel_st = iio_priv(st->indio_accel); - struct inv_sensors_timestamp *ts; -- int64_t gyro_ts, accel_ts; -+ s64 gyro_ts, accel_ts; - int ret; - - gyro_ts = iio_get_time_ns(st->indio_gyro); -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h BPI-Router-Linux-kernel-6.16.12/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h ---- BPI-Router-Linux-kernel/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h 2025-10-22 13:53:56.503169199 -0400 -@@ -28,7 +28,7 @@ struct inv_icm42600_state; - struct inv_icm42600_fifo { - unsigned int on; - unsigned int en; -- uint32_t period; -+ u32 period; - struct { - unsigned int gyro; - unsigned int accel; -@@ -41,7 +41,7 @@ struct inv_icm42600_fifo { - size_t accel; - size_t total; - } nb; -- uint8_t data[2080] __aligned(IIO_DMA_MINALIGN); -+ u8 data[2080] __aligned(IIO_DMA_MINALIGN); - }; - - /* FIFO data packet */ -@@ -52,7 +52,7 @@ struct inv_icm42600_fifo_sensor_data { - } __packed; - #define INV_ICM42600_FIFO_DATA_INVALID -32768 - --static inline int16_t inv_icm42600_fifo_get_sensor_data(__be16 d) -+static inline s16 inv_icm42600_fifo_get_sensor_data(__be16 d) - { - return be16_to_cpu(d); - } -@@ -60,7 +60,7 @@ static inline int16_t inv_icm42600_fifo_ - static inline bool - inv_icm42600_fifo_is_data_valid(const struct inv_icm42600_fifo_sensor_data *s) - { -- int16_t x, y, z; -+ s16 x, y, z; - - x = inv_icm42600_fifo_get_sensor_data(s->x); - y = inv_icm42600_fifo_get_sensor_data(s->y); -@@ -75,7 +75,7 @@ inv_icm42600_fifo_is_data_valid(const st - } - - ssize_t inv_icm42600_fifo_decode_packet(const void *packet, const void **accel, -- const void **gyro, const int8_t **temp, -+ const void **gyro, const s8 **temp, - const void **timestamp, unsigned int *odr); - - extern const struct iio_buffer_setup_ops inv_icm42600_buffer_ops; -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c ---- BPI-Router-Linux-kernel/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c 2025-10-22 13:53:23.271328857 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c 2025-10-22 13:53:56.503169199 -0400 -@@ -103,7 +103,7 @@ const struct regmap_config inv_icm42600_ - EXPORT_SYMBOL_NS_GPL(inv_icm42600_spi_regmap_config, "IIO_ICM42600"); - - struct inv_icm42600_hw { -- uint8_t whoami; -+ u8 whoami; - const char *name; - const struct inv_icm42600_conf *conf; - }; -@@ -188,9 +188,9 @@ inv_icm42600_get_mount_matrix(const stru - return &st->orientation; - } - --uint32_t inv_icm42600_odr_to_period(enum inv_icm42600_odr odr) -+u32 inv_icm42600_odr_to_period(enum inv_icm42600_odr odr) - { -- static uint32_t odr_periods[INV_ICM42600_ODR_NB] = { -+ static u32 odr_periods[INV_ICM42600_ODR_NB] = { - /* reserved values */ - 0, 0, 0, - /* 8kHz */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c ---- BPI-Router-Linux-kernel/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c 2025-10-22 13:53:23.271328857 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c 2025-10-22 13:53:56.503169199 -0400 -@@ -77,7 +77,7 @@ static const struct iio_chan_spec inv_ic - */ - struct inv_icm42600_gyro_buffer { - struct inv_icm42600_fifo_sensor_data gyro; -- int16_t temp; -+ s16 temp; - aligned_s64 timestamp; - }; - -@@ -139,7 +139,7 @@ out_unlock: - - static int inv_icm42600_gyro_read_sensor(struct inv_icm42600_state *st, - struct iio_chan_spec const *chan, -- int16_t *val) -+ s16 *val) - { - struct device *dev = regmap_get_device(st->map); - struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; -@@ -179,7 +179,7 @@ static int inv_icm42600_gyro_read_sensor - if (ret) - goto exit; - -- *val = (int16_t)be16_to_cpup(data); -+ *val = (s16)be16_to_cpup(data); - if (*val == INV_ICM42600_DATA_INVALID) - ret = -EINVAL; - exit: -@@ -399,11 +399,11 @@ static int inv_icm42600_gyro_read_offset - int *val, int *val2) - { - struct device *dev = regmap_get_device(st->map); -- int64_t val64; -- int32_t bias; -+ s64 val64; -+ s32 bias; - unsigned int reg; -- int16_t offset; -- uint8_t data[2]; -+ s16 offset; -+ u8 data[2]; - int ret; - - if (chan->type != IIO_ANGL_VEL) -@@ -457,7 +457,7 @@ static int inv_icm42600_gyro_read_offset - * result in nano (1000000000) - * (offset * 64 * Pi * 1000000000) / (2048 * 180) - */ -- val64 = (int64_t)offset * 64LL * 3141592653LL; -+ val64 = (s64)offset * 64LL * 3141592653LL; - /* for rounding, add + or - divisor (2048 * 180) divided by 2 */ - if (val64 >= 0) - val64 += 2048 * 180 / 2; -@@ -475,9 +475,9 @@ static int inv_icm42600_gyro_write_offse - int val, int val2) - { - struct device *dev = regmap_get_device(st->map); -- int64_t val64, min, max; -+ s64 val64, min, max; - unsigned int reg, regval; -- int16_t offset; -+ s16 offset; - int ret; - - if (chan->type != IIO_ANGL_VEL) -@@ -498,11 +498,11 @@ static int inv_icm42600_gyro_write_offse - } - - /* inv_icm42600_gyro_calibbias: min - step - max in nano */ -- min = (int64_t)inv_icm42600_gyro_calibbias[0] * 1000000000LL + -- (int64_t)inv_icm42600_gyro_calibbias[1]; -- max = (int64_t)inv_icm42600_gyro_calibbias[4] * 1000000000LL + -- (int64_t)inv_icm42600_gyro_calibbias[5]; -- val64 = (int64_t)val * 1000000000LL + (int64_t)val2; -+ min = (s64)inv_icm42600_gyro_calibbias[0] * 1000000000LL + -+ (s64)inv_icm42600_gyro_calibbias[1]; -+ max = (s64)inv_icm42600_gyro_calibbias[4] * 1000000000LL + -+ (s64)inv_icm42600_gyro_calibbias[5]; -+ val64 = (s64)val * 1000000000LL + (s64)val2; - if (val64 < min || val64 > max) - return -EINVAL; - -@@ -577,7 +577,7 @@ static int inv_icm42600_gyro_read_raw(st - int *val, int *val2, long mask) - { - struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); -- int16_t data; -+ s16 data; - int ret; - - switch (chan->type) { -@@ -803,10 +803,11 @@ int inv_icm42600_gyro_parse_fifo(struct - ssize_t i, size; - unsigned int no; - const void *accel, *gyro, *timestamp; -- const int8_t *temp; -+ const s8 *temp; - unsigned int odr; -- int64_t ts_val; -- struct inv_icm42600_gyro_buffer buffer; -+ s64 ts_val; -+ /* buffer is copied to userspace, zeroing it to avoid any data leak */ -+ struct inv_icm42600_gyro_buffer buffer = { }; - - /* parse all fifo packets */ - for (i = 0, no = 0; i < st->fifo.count; i += size, ++no) { -@@ -825,8 +826,6 @@ int inv_icm42600_gyro_parse_fifo(struct - inv_sensors_timestamp_apply_odr(ts, st->fifo.period, - st->fifo.nb.total, no); - -- /* buffer is copied to userspace, zeroing it to avoid any data leak */ -- memset(&buffer, 0, sizeof(buffer)); - memcpy(&buffer.gyro, gyro, sizeof(buffer.gyro)); - /* convert 8 bits FIFO temperature in high resolution format */ - buffer.temp = temp ? (*temp * 64) : 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/imu/inv_icm42600/inv_icm42600.h BPI-Router-Linux-kernel-6.16.12/drivers/iio/imu/inv_icm42600/inv_icm42600.h ---- BPI-Router-Linux-kernel/drivers/iio/imu/inv_icm42600/inv_icm42600.h 2025-10-22 13:53:23.267328876 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/imu/inv_icm42600/inv_icm42600.h 2025-10-22 13:53:56.503169199 -0400 -@@ -164,11 +164,11 @@ struct inv_icm42600_state { - struct inv_icm42600_suspended suspended; - struct iio_dev *indio_gyro; - struct iio_dev *indio_accel; -- uint8_t buffer[2] __aligned(IIO_DMA_MINALIGN); -+ u8 buffer[2] __aligned(IIO_DMA_MINALIGN); - struct inv_icm42600_fifo fifo; - struct { -- int64_t gyro; -- int64_t accel; -+ s64 gyro; -+ s64 accel; - } timestamp; - }; - -@@ -410,7 +410,7 @@ const struct iio_mount_matrix * - inv_icm42600_get_mount_matrix(const struct iio_dev *indio_dev, - const struct iio_chan_spec *chan); - --uint32_t inv_icm42600_odr_to_period(enum inv_icm42600_odr odr); -+u32 inv_icm42600_odr_to_period(enum inv_icm42600_odr odr); - - int inv_icm42600_set_accel_conf(struct inv_icm42600_state *st, - struct inv_icm42600_sensor_conf *conf, -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c ---- BPI-Router-Linux-kernel/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c 2025-10-22 13:53:23.271328857 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c 2025-10-22 13:53:56.503169199 -0400 -@@ -13,7 +13,7 @@ - #include "inv_icm42600.h" - #include "inv_icm42600_temp.h" - --static int inv_icm42600_temp_read(struct inv_icm42600_state *st, int16_t *temp) -+static int inv_icm42600_temp_read(struct inv_icm42600_state *st, s16 *temp) - { - struct device *dev = regmap_get_device(st->map); - __be16 *raw; -@@ -31,9 +31,13 @@ static int inv_icm42600_temp_read(struct - if (ret) - goto exit; - -- *temp = (int16_t)be16_to_cpup(raw); -+ *temp = (s16)be16_to_cpup(raw); -+ /* -+ * Temperature data is invalid if both accel and gyro are off. -+ * Return -EBUSY in this case. -+ */ - if (*temp == INV_ICM42600_DATA_INVALID) -- ret = -EINVAL; -+ ret = -EBUSY; - - exit: - mutex_unlock(&st->lock); -@@ -48,7 +52,7 @@ int inv_icm42600_temp_read_raw(struct ii - int *val, int *val2, long mask) - { - struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); -- int16_t temp; -+ s16 temp; - int ret; - - if (chan->type != IIO_TEMP) -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/industrialio-backend.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/industrialio-backend.c ---- BPI-Router-Linux-kernel/drivers/iio/industrialio-backend.c 2025-10-22 13:53:23.271328857 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/industrialio-backend.c 2025-10-22 13:53:56.503169199 -0400 -@@ -155,11 +155,14 @@ static ssize_t iio_backend_debugfs_write - ssize_t rc; - int ret; - -+ if (count >= sizeof(buf)) -+ return -ENOSPC; -+ - rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, userbuf, count); - if (rc < 0) - return rc; - -- buf[count] = '\0'; -+ buf[rc] = '\0'; - - ret = sscanf(buf, "%i %i", &back->cached_reg_addr, &val); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/industrialio-core.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/industrialio-core.c ---- BPI-Router-Linux-kernel/drivers/iio/industrialio-core.c 2025-10-22 13:53:23.271328857 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/industrialio-core.c 2025-10-22 13:53:56.503169199 -0400 -@@ -411,12 +411,15 @@ static ssize_t iio_debugfs_write_reg(str - char buf[80]; - int ret; - -+ if (count >= sizeof(buf)) -+ return -EINVAL; -+ - ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, userbuf, - count); - if (ret < 0) - return ret; - -- buf[count] = '\0'; -+ buf[ret] = '\0'; - - ret = sscanf(buf, "%i %i", ®, &val); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/light/as73211.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/light/as73211.c ---- BPI-Router-Linux-kernel/drivers/iio/light/as73211.c 2025-10-22 13:53:23.271328857 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/light/as73211.c 2025-10-22 13:53:56.503169199 -0400 -@@ -639,7 +639,7 @@ static irqreturn_t as73211_trigger_handl - struct { - __le16 chan[4]; - aligned_s64 ts; -- } scan; -+ } scan = { }; - int data_result, ret; - - mutex_lock(&data->mutex); -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/pressure/bmp280-core.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/pressure/bmp280-core.c ---- BPI-Router-Linux-kernel/drivers/iio/pressure/bmp280-core.c 2025-10-22 13:53:23.271328857 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/pressure/bmp280-core.c 2025-10-22 13:53:56.507169180 -0400 -@@ -3216,11 +3216,12 @@ int bmp280_common_probe(struct device *d - - /* Bring chip out of reset if there is an assigned GPIO line */ - gpiod = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); -+ if (IS_ERR(gpiod)) -+ return dev_err_probe(dev, PTR_ERR(gpiod), "failed to get reset GPIO\n"); -+ - /* Deassert the signal */ -- if (gpiod) { -- dev_info(dev, "release reset\n"); -- gpiod_set_value(gpiod, 0); -- } -+ dev_info(dev, "release reset\n"); -+ gpiod_set_value(gpiod, 0); - - data->regmap = regmap; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/proximity/isl29501.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/proximity/isl29501.c ---- BPI-Router-Linux-kernel/drivers/iio/proximity/isl29501.c 2025-10-22 13:53:23.271328857 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/proximity/isl29501.c 2025-10-22 13:53:56.507169180 -0400 -@@ -938,12 +938,18 @@ static irqreturn_t isl29501_trigger_hand - struct iio_dev *indio_dev = pf->indio_dev; - struct isl29501_private *isl29501 = iio_priv(indio_dev); - const unsigned long *active_mask = indio_dev->active_scan_mask; -- u32 buffer[4] __aligned(8) = {}; /* 1x16-bit + naturally aligned ts */ -+ u32 value; -+ struct { -+ u16 data; -+ aligned_s64 ts; -+ } scan = { }; - -- if (test_bit(ISL29501_DISTANCE_SCAN_INDEX, active_mask)) -- isl29501_register_read(isl29501, REG_DISTANCE, buffer); -+ if (test_bit(ISL29501_DISTANCE_SCAN_INDEX, active_mask)) { -+ isl29501_register_read(isl29501, REG_DISTANCE, &value); -+ scan.data = value; -+ } - -- iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp); -+ iio_push_to_buffers_with_timestamp(indio_dev, &scan, pf->timestamp); - iio_trigger_notify_done(indio_dev->trig); - - return IRQ_HANDLED; -diff -purNx .git BPI-Router-Linux-kernel/drivers/iio/temperature/maxim_thermocouple.c BPI-Router-Linux-kernel-6.16.12/drivers/iio/temperature/maxim_thermocouple.c ---- BPI-Router-Linux-kernel/drivers/iio/temperature/maxim_thermocouple.c 2025-10-22 13:53:23.271328857 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iio/temperature/maxim_thermocouple.c 2025-10-22 13:53:56.507169180 -0400 -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -121,8 +122,15 @@ struct maxim_thermocouple_data { - struct spi_device *spi; - const struct maxim_thermocouple_chip *chip; - char tc_type; -- -- u8 buffer[16] __aligned(IIO_DMA_MINALIGN); -+ /* Buffer for reading up to 2 hardware channels. */ -+ struct { -+ union { -+ __be16 raw16; -+ __be32 raw32; -+ __be16 raw[2]; -+ }; -+ aligned_s64 timestamp; -+ } buffer __aligned(IIO_DMA_MINALIGN); - }; - - static int maxim_thermocouple_read(struct maxim_thermocouple_data *data, -@@ -130,18 +138,16 @@ static int maxim_thermocouple_read(struc - { - unsigned int storage_bytes = data->chip->read_size; - unsigned int shift = chan->scan_type.shift + (chan->address * 8); -- __be16 buf16; -- __be32 buf32; - int ret; - - switch (storage_bytes) { - case 2: -- ret = spi_read(data->spi, (void *)&buf16, storage_bytes); -- *val = be16_to_cpu(buf16); -+ ret = spi_read(data->spi, &data->buffer.raw16, storage_bytes); -+ *val = be16_to_cpu(data->buffer.raw16); - break; - case 4: -- ret = spi_read(data->spi, (void *)&buf32, storage_bytes); -- *val = be32_to_cpu(buf32); -+ ret = spi_read(data->spi, &data->buffer.raw32, storage_bytes); -+ *val = be32_to_cpu(data->buffer.raw32); - break; - default: - ret = -EINVAL; -@@ -166,9 +172,9 @@ static irqreturn_t maxim_thermocouple_tr - struct maxim_thermocouple_data *data = iio_priv(indio_dev); - int ret; - -- ret = spi_read(data->spi, data->buffer, data->chip->read_size); -+ ret = spi_read(data->spi, data->buffer.raw, data->chip->read_size); - if (!ret) { -- iio_push_to_buffers_with_ts(indio_dev, data->buffer, -+ iio_push_to_buffers_with_ts(indio_dev, &data->buffer, - sizeof(data->buffer), - iio_get_time_ns(indio_dev)); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/core/cache.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/core/cache.c ---- BPI-Router-Linux-kernel/drivers/infiniband/core/cache.c 2025-10-22 13:53:23.271328857 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/core/cache.c 2025-10-22 13:53:56.507169180 -0400 -@@ -582,8 +582,8 @@ static int __ib_cache_gid_add(struct ib_ - out_unlock: - mutex_unlock(&table->lock); - if (ret) -- pr_warn("%s: unable to add gid %pI6 error=%d\n", -- __func__, gid->raw, ret); -+ pr_warn_ratelimited("%s: unable to add gid %pI6 error=%d\n", -+ __func__, gid->raw, ret); - return ret; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/core/counters.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/core/counters.c ---- BPI-Router-Linux-kernel/drivers/infiniband/core/counters.c 2025-10-22 13:53:23.271328857 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/core/counters.c 2025-10-22 13:53:56.507169180 -0400 -@@ -461,7 +461,7 @@ static struct ib_qp *rdma_counter_get_qp - return NULL; - - qp = container_of(res, struct ib_qp, res); -- if (qp->qp_type == IB_QPT_RAW_PACKET && !capable(CAP_NET_RAW)) -+ if (qp->qp_type == IB_QPT_RAW_PACKET && !rdma_dev_has_raw_cap(dev)) - goto err; - - return qp; -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/core/device.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/core/device.c ---- BPI-Router-Linux-kernel/drivers/infiniband/core/device.c 2025-10-22 13:53:23.271328857 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/core/device.c 2025-10-22 13:53:56.507169180 -0400 -@@ -145,6 +145,33 @@ bool rdma_dev_access_netns(const struct - } - EXPORT_SYMBOL(rdma_dev_access_netns); - -+/** -+ * rdma_dev_has_raw_cap() - Returns whether a specified rdma device has -+ * CAP_NET_RAW capability or not. -+ * -+ * @dev: Pointer to rdma device whose capability to be checked -+ * -+ * Returns true if a rdma device's owning user namespace has CAP_NET_RAW -+ * capability, otherwise false. When rdma subsystem is in legacy shared network, -+ * namespace mode, the default net namespace is considered. -+ */ -+bool rdma_dev_has_raw_cap(const struct ib_device *dev) -+{ -+ const struct net *net; -+ -+ /* Network namespace is the resource whose user namespace -+ * to be considered. When in shared mode, there is no reliable -+ * network namespace resource, so consider the default net namespace. -+ */ -+ if (ib_devices_shared_netns) -+ net = &init_net; -+ else -+ net = read_pnet(&dev->coredev.rdma_net); -+ -+ return ns_capable(net->user_ns, CAP_NET_RAW); -+} -+EXPORT_SYMBOL(rdma_dev_has_raw_cap); -+ - /* - * xarray has this behavior where it won't iterate over NULL values stored in - * allocated arrays. So we need our own iterator to see all values stored in -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/core/nldev.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/core/nldev.c ---- BPI-Router-Linux-kernel/drivers/infiniband/core/nldev.c 2025-10-22 13:53:23.271328857 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/core/nldev.c 2025-10-22 13:53:56.507169180 -0400 -@@ -255,7 +255,7 @@ EXPORT_SYMBOL(rdma_nl_put_driver_u64_hex - - bool rdma_nl_get_privileged_qkey(void) - { -- return privileged_qkey || capable(CAP_NET_RAW); -+ return privileged_qkey; - } - EXPORT_SYMBOL(rdma_nl_get_privileged_qkey); - -@@ -1469,10 +1469,11 @@ static const struct nldev_fill_res_entry - - }; - --static int res_get_common_doit(struct sk_buff *skb, struct nlmsghdr *nlh, -- struct netlink_ext_ack *extack, -- enum rdma_restrack_type res_type, -- res_fill_func_t fill_func) -+static noinline_for_stack int -+res_get_common_doit(struct sk_buff *skb, struct nlmsghdr *nlh, -+ struct netlink_ext_ack *extack, -+ enum rdma_restrack_type res_type, -+ res_fill_func_t fill_func) - { - const struct nldev_fill_res_entry *fe = &fill_entries[res_type]; - struct nlattr *tb[RDMA_NLDEV_ATTR_MAX]; -@@ -2263,10 +2264,10 @@ err: - return ret; - } - --static int stat_get_doit_default_counter(struct sk_buff *skb, -- struct nlmsghdr *nlh, -- struct netlink_ext_ack *extack, -- struct nlattr *tb[]) -+static noinline_for_stack int -+stat_get_doit_default_counter(struct sk_buff *skb, struct nlmsghdr *nlh, -+ struct netlink_ext_ack *extack, -+ struct nlattr *tb[]) - { - struct rdma_hw_stats *stats; - struct nlattr *table_attr; -@@ -2356,8 +2357,9 @@ err: - return ret; - } - --static int stat_get_doit_qp(struct sk_buff *skb, struct nlmsghdr *nlh, -- struct netlink_ext_ack *extack, struct nlattr *tb[]) -+static noinline_for_stack int -+stat_get_doit_qp(struct sk_buff *skb, struct nlmsghdr *nlh, -+ struct netlink_ext_ack *extack, struct nlattr *tb[]) - - { - static enum rdma_nl_counter_mode mode; -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/core/rdma_core.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/core/rdma_core.c ---- BPI-Router-Linux-kernel/drivers/infiniband/core/rdma_core.c 2025-10-22 13:53:23.271328857 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/core/rdma_core.c 2025-10-22 13:53:56.507169180 -0400 -@@ -1019,3 +1019,32 @@ void uverbs_finalize_object(struct ib_uo - WARN_ON(true); - } - } -+ -+/** -+ * rdma_uattrs_has_raw_cap() - Returns whether a rdma device linked to the -+ * uverbs attributes file has CAP_NET_RAW -+ * capability or not. -+ * -+ * @attrs: Pointer to uverbs attributes -+ * -+ * Returns true if a rdma device's owning user namespace has CAP_NET_RAW -+ * capability, otherwise false. -+ */ -+bool rdma_uattrs_has_raw_cap(const struct uverbs_attr_bundle *attrs) -+{ -+ struct ib_uverbs_file *ufile = attrs->ufile; -+ struct ib_ucontext *ucontext; -+ bool has_cap = false; -+ int srcu_key; -+ -+ srcu_key = srcu_read_lock(&ufile->device->disassociate_srcu); -+ ucontext = ib_uverbs_get_ucontext_file(ufile); -+ if (IS_ERR(ucontext)) -+ goto out; -+ has_cap = rdma_dev_has_raw_cap(ucontext->device); -+ -+out: -+ srcu_read_unlock(&ufile->device->disassociate_srcu, srcu_key); -+ return has_cap; -+} -+EXPORT_SYMBOL(rdma_uattrs_has_raw_cap); -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/core/umem_odp.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/core/umem_odp.c ---- BPI-Router-Linux-kernel/drivers/infiniband/core/umem_odp.c 2025-10-22 13:53:23.271328857 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/core/umem_odp.c 2025-10-22 13:53:56.507169180 -0400 -@@ -76,6 +76,17 @@ static int ib_init_umem_odp(struct ib_um - end = ALIGN(end, page_size); - if (unlikely(end < page_size)) - return -EOVERFLOW; -+ /* -+ * The mmu notifier can be called within reclaim contexts and takes the -+ * umem_mutex. This is rare to trigger in testing, teach lockdep about -+ * it. -+ */ -+ if (IS_ENABLED(CONFIG_LOCKDEP)) { -+ fs_reclaim_acquire(GFP_KERNEL); -+ mutex_lock(&umem_odp->umem_mutex); -+ mutex_unlock(&umem_odp->umem_mutex); -+ fs_reclaim_release(GFP_KERNEL); -+ } - - nr_entries = (end - start) >> PAGE_SHIFT; - if (!(nr_entries * PAGE_SIZE / page_size)) -@@ -104,7 +115,7 @@ static int ib_init_umem_odp(struct ib_um - - out_free_map: - if (ib_uses_virt_dma(dev)) -- kfree(map->pfn_list); -+ kvfree(map->pfn_list); - else - hmm_dma_map_free(dev->dma_device, map); - return ret; -@@ -276,7 +287,7 @@ static void ib_umem_odp_free(struct ib_u - mutex_unlock(&umem_odp->umem_mutex); - mmu_interval_notifier_remove(&umem_odp->notifier); - if (ib_uses_virt_dma(dev)) -- kfree(umem_odp->map.pfn_list); -+ kvfree(umem_odp->map.pfn_list); - else - hmm_dma_map_free(dev->dma_device, &umem_odp->map); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/core/uverbs_cmd.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/core/uverbs_cmd.c ---- BPI-Router-Linux-kernel/drivers/infiniband/core/uverbs_cmd.c 2025-10-22 13:53:23.271328857 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/core/uverbs_cmd.c 2025-10-22 13:53:56.507169180 -0400 -@@ -1451,7 +1451,7 @@ static int create_qp(struct uverbs_attr_ - } - - if (attr.create_flags & IB_QP_CREATE_SOURCE_QPN) { -- if (!capable(CAP_NET_RAW)) { -+ if (!rdma_uattrs_has_raw_cap(attrs)) { - ret = -EPERM; - goto err_put; - } -@@ -1877,7 +1877,8 @@ static int modify_qp(struct uverbs_attr_ - attr->path_mig_state = cmd->base.path_mig_state; - if (cmd->base.attr_mask & IB_QP_QKEY) { - if (cmd->base.qkey & IB_QP_SET_QKEY && -- !rdma_nl_get_privileged_qkey()) { -+ !(rdma_nl_get_privileged_qkey() || -+ rdma_uattrs_has_raw_cap(attrs))) { - ret = -EPERM; - goto release_qp; - } -@@ -3225,7 +3226,7 @@ static int ib_uverbs_ex_create_flow(stru - if (cmd.comp_mask) - return -EINVAL; - -- if (!capable(CAP_NET_RAW)) -+ if (!rdma_uattrs_has_raw_cap(attrs)) - return -EPERM; - - if (cmd.flow_attr.flags >= IB_FLOW_ATTR_FLAGS_RESERVED) -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/core/uverbs_std_types_qp.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/core/uverbs_std_types_qp.c ---- BPI-Router-Linux-kernel/drivers/infiniband/core/uverbs_std_types_qp.c 2025-10-22 13:53:23.271328857 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/core/uverbs_std_types_qp.c 2025-10-22 13:53:56.507169180 -0400 -@@ -133,7 +133,7 @@ static int UVERBS_HANDLER(UVERBS_METHOD_ - device = xrcd->device; - break; - case IB_UVERBS_QPT_RAW_PACKET: -- if (!capable(CAP_NET_RAW)) -+ if (!rdma_uattrs_has_raw_cap(attrs)) - return -EPERM; - fallthrough; - case IB_UVERBS_QPT_RC: -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/hw/bnxt_re/ib_verbs.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/bnxt_re/ib_verbs.c ---- BPI-Router-Linux-kernel/drivers/infiniband/hw/bnxt_re/ib_verbs.c 2025-10-22 13:53:23.275328838 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/bnxt_re/ib_verbs.c 2025-10-22 13:53:56.507169180 -0400 -@@ -1921,7 +1921,6 @@ int bnxt_re_modify_srq(struct ib_srq *ib - struct bnxt_re_srq *srq = container_of(ib_srq, struct bnxt_re_srq, - ib_srq); - struct bnxt_re_dev *rdev = srq->rdev; -- int rc; - - switch (srq_attr_mask) { - case IB_SRQ_MAX_WR: -@@ -1933,11 +1932,8 @@ int bnxt_re_modify_srq(struct ib_srq *ib - return -EINVAL; - - srq->qplib_srq.threshold = srq_attr->srq_limit; -- rc = bnxt_qplib_modify_srq(&rdev->qplib_res, &srq->qplib_srq); -- if (rc) { -- ibdev_err(&rdev->ibdev, "Modify HW SRQ failed!"); -- return rc; -- } -+ bnxt_qplib_srq_arm_db(&srq->qplib_srq.dbinfo, srq->qplib_srq.threshold); -+ - /* On success, update the shadow */ - srq->srq_limit = srq_attr->srq_limit; - /* No need to Build and send response back to udata */ -@@ -4738,7 +4734,7 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD - return err; - - err = uverbs_copy_to(attrs, BNXT_RE_TOGGLE_MEM_MMAP_OFFSET, -- &offset, sizeof(length)); -+ &offset, sizeof(offset)); - if (err) - return err; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/hw/bnxt_re/main.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/bnxt_re/main.c ---- BPI-Router-Linux-kernel/drivers/infiniband/hw/bnxt_re/main.c 2025-10-22 13:53:23.275328838 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/bnxt_re/main.c 2025-10-22 13:53:56.507169180 -0400 -@@ -2017,6 +2017,28 @@ static void bnxt_re_free_nqr_mem(struct - rdev->nqr = NULL; - } - -+/* When DEL_GID fails, driver is not freeing GID ctx memory. -+ * To avoid the memory leak, free the memory during unload -+ */ -+static void bnxt_re_free_gid_ctx(struct bnxt_re_dev *rdev) -+{ -+ struct bnxt_qplib_sgid_tbl *sgid_tbl = &rdev->qplib_res.sgid_tbl; -+ struct bnxt_re_gid_ctx *ctx, **ctx_tbl; -+ int i; -+ -+ if (!sgid_tbl->active) -+ return; -+ -+ ctx_tbl = sgid_tbl->ctx; -+ for (i = 0; i < sgid_tbl->max; i++) { -+ if (sgid_tbl->hw_id[i] == 0xFFFF) -+ continue; -+ -+ ctx = ctx_tbl[i]; -+ kfree(ctx); -+ } -+} -+ - static void bnxt_re_dev_uninit(struct bnxt_re_dev *rdev, u8 op_type) - { - u8 type; -@@ -2030,6 +2052,7 @@ static void bnxt_re_dev_uninit(struct bn - if (test_and_clear_bit(BNXT_RE_FLAG_QOS_WORK_REG, &rdev->flags)) - cancel_delayed_work_sync(&rdev->worker); - -+ bnxt_re_free_gid_ctx(rdev); - if (test_and_clear_bit(BNXT_RE_FLAG_RESOURCES_INITIALIZED, - &rdev->flags)) - bnxt_re_cleanup_res(rdev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/hw/bnxt_re/qplib_fp.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/bnxt_re/qplib_fp.c ---- BPI-Router-Linux-kernel/drivers/infiniband/hw/bnxt_re/qplib_fp.c 2025-10-22 13:53:23.275328838 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/bnxt_re/qplib_fp.c 2025-10-22 13:53:56.507169180 -0400 -@@ -705,9 +705,7 @@ int bnxt_qplib_create_srq(struct bnxt_qp - srq->dbinfo.db = srq->dpi->dbr; - srq->dbinfo.max_slot = 1; - srq->dbinfo.priv_db = res->dpi_tbl.priv_db; -- if (srq->threshold) -- bnxt_qplib_armen_db(&srq->dbinfo, DBC_DBC_TYPE_SRQ_ARMENA); -- srq->arm_req = false; -+ bnxt_qplib_armen_db(&srq->dbinfo, DBC_DBC_TYPE_SRQ_ARMENA); - - return 0; - fail: -@@ -717,24 +715,6 @@ fail: - return rc; - } - --int bnxt_qplib_modify_srq(struct bnxt_qplib_res *res, -- struct bnxt_qplib_srq *srq) --{ -- struct bnxt_qplib_hwq *srq_hwq = &srq->hwq; -- u32 count; -- -- count = __bnxt_qplib_get_avail(srq_hwq); -- if (count > srq->threshold) { -- srq->arm_req = false; -- bnxt_qplib_srq_arm_db(&srq->dbinfo, srq->threshold); -- } else { -- /* Deferred arming */ -- srq->arm_req = true; -- } -- -- return 0; --} -- - int bnxt_qplib_query_srq(struct bnxt_qplib_res *res, - struct bnxt_qplib_srq *srq) - { -@@ -776,7 +756,6 @@ int bnxt_qplib_post_srq_recv(struct bnxt - struct bnxt_qplib_hwq *srq_hwq = &srq->hwq; - struct rq_wqe *srqe; - struct sq_sge *hw_sge; -- u32 count = 0; - int i, next; - - spin_lock(&srq_hwq->lock); -@@ -808,15 +787,8 @@ int bnxt_qplib_post_srq_recv(struct bnxt - - bnxt_qplib_hwq_incr_prod(&srq->dbinfo, srq_hwq, srq->dbinfo.max_slot); - -- spin_lock(&srq_hwq->lock); -- count = __bnxt_qplib_get_avail(srq_hwq); -- spin_unlock(&srq_hwq->lock); - /* Ring DB */ - bnxt_qplib_ring_prod_db(&srq->dbinfo, DBC_DBC_TYPE_SRQ); -- if (srq->arm_req == true && count > srq->threshold) { -- srq->arm_req = false; -- bnxt_qplib_srq_arm_db(&srq->dbinfo, srq->threshold); -- } - - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/hw/bnxt_re/qplib_fp.h BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/bnxt_re/qplib_fp.h ---- BPI-Router-Linux-kernel/drivers/infiniband/hw/bnxt_re/qplib_fp.h 2025-10-22 13:53:23.275328838 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/bnxt_re/qplib_fp.h 2025-10-22 13:53:56.507169180 -0400 -@@ -543,8 +543,6 @@ int bnxt_qplib_enable_nq(struct pci_dev - srqn_handler_t srq_handler); - int bnxt_qplib_create_srq(struct bnxt_qplib_res *res, - struct bnxt_qplib_srq *srq); --int bnxt_qplib_modify_srq(struct bnxt_qplib_res *res, -- struct bnxt_qplib_srq *srq); - int bnxt_qplib_query_srq(struct bnxt_qplib_res *res, - struct bnxt_qplib_srq *srq); - void bnxt_qplib_destroy_srq(struct bnxt_qplib_res *res, -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/hw/bnxt_re/qplib_res.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/bnxt_re/qplib_res.c ---- BPI-Router-Linux-kernel/drivers/infiniband/hw/bnxt_re/qplib_res.c 2025-10-22 13:53:23.275328838 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/bnxt_re/qplib_res.c 2025-10-22 13:53:56.507169180 -0400 -@@ -121,6 +121,7 @@ static int __alloc_pbl(struct bnxt_qplib - pbl->pg_arr = vmalloc_array(pages, sizeof(void *)); - if (!pbl->pg_arr) - return -ENOMEM; -+ memset(pbl->pg_arr, 0, pages * sizeof(void *)); - - pbl->pg_map_arr = vmalloc_array(pages, sizeof(dma_addr_t)); - if (!pbl->pg_map_arr) { -@@ -128,6 +129,7 @@ static int __alloc_pbl(struct bnxt_qplib - pbl->pg_arr = NULL; - return -ENOMEM; - } -+ memset(pbl->pg_map_arr, 0, pages * sizeof(dma_addr_t)); - pbl->pg_count = 0; - pbl->pg_size = sginfo->pgsize; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/hw/erdma/erdma_verbs.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/erdma/erdma_verbs.c ---- BPI-Router-Linux-kernel/drivers/infiniband/hw/erdma/erdma_verbs.c 2025-10-22 13:53:23.275328838 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/erdma/erdma_verbs.c 2025-10-22 13:53:56.507169180 -0400 -@@ -629,7 +629,8 @@ err_free_mtt: - static void erdma_destroy_mtt_buf_sg(struct erdma_dev *dev, - struct erdma_mtt *mtt) - { -- dma_unmap_sg(&dev->pdev->dev, mtt->sglist, mtt->nsg, DMA_TO_DEVICE); -+ dma_unmap_sg(&dev->pdev->dev, mtt->sglist, -+ DIV_ROUND_UP(mtt->size, PAGE_SIZE), DMA_TO_DEVICE); - vfree(mtt->sglist); - } - -@@ -993,6 +994,8 @@ int erdma_create_qp(struct ib_qp *ibqp, - old_entry = xa_store(&dev->qp_xa, 1, qp, GFP_KERNEL); - if (xa_is_err(old_entry)) - ret = xa_err(old_entry); -+ else -+ qp->ibqp.qp_num = 1; - } else { - ret = xa_alloc_cyclic(&dev->qp_xa, &qp->ibqp.qp_num, qp, - XA_LIMIT(1, dev->attrs.max_qp - 1), -@@ -1030,7 +1033,9 @@ int erdma_create_qp(struct ib_qp *ibqp, - if (ret) - goto err_out_cmd; - } else { -- init_kernel_qp(dev, qp, attrs); -+ ret = init_kernel_qp(dev, qp, attrs); -+ if (ret) -+ goto err_out_xa; - } - - qp->attrs.max_send_sge = attrs->cap.max_send_sge; -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/hw/hfi1/affinity.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/hfi1/affinity.c ---- BPI-Router-Linux-kernel/drivers/infiniband/hw/hfi1/affinity.c 2025-10-22 13:53:23.275328838 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/hfi1/affinity.c 2025-10-22 13:53:56.507169180 -0400 -@@ -964,31 +964,35 @@ static void find_hw_thread_mask(uint hw_ - struct hfi1_affinity_node_list *affinity) - { - int possible, curr_cpu, i; -- uint num_cores_per_socket = node_affinity.num_online_cpus / -+ uint num_cores_per_socket; -+ -+ cpumask_copy(hw_thread_mask, &affinity->proc.mask); -+ -+ if (affinity->num_core_siblings == 0) -+ return; -+ -+ num_cores_per_socket = node_affinity.num_online_cpus / - affinity->num_core_siblings / - node_affinity.num_online_nodes; - -- cpumask_copy(hw_thread_mask, &affinity->proc.mask); -- if (affinity->num_core_siblings > 0) { -- /* Removing other siblings not needed for now */ -- possible = cpumask_weight(hw_thread_mask); -- curr_cpu = cpumask_first(hw_thread_mask); -- for (i = 0; -- i < num_cores_per_socket * node_affinity.num_online_nodes; -- i++) -- curr_cpu = cpumask_next(curr_cpu, hw_thread_mask); -- -- for (; i < possible; i++) { -- cpumask_clear_cpu(curr_cpu, hw_thread_mask); -- curr_cpu = cpumask_next(curr_cpu, hw_thread_mask); -- } -- -- /* Identifying correct HW threads within physical cores */ -- cpumask_shift_left(hw_thread_mask, hw_thread_mask, -- num_cores_per_socket * -- node_affinity.num_online_nodes * -- hw_thread_no); -+ /* Removing other siblings not needed for now */ -+ possible = cpumask_weight(hw_thread_mask); -+ curr_cpu = cpumask_first(hw_thread_mask); -+ for (i = 0; -+ i < num_cores_per_socket * node_affinity.num_online_nodes; -+ i++) -+ curr_cpu = cpumask_next(curr_cpu, hw_thread_mask); -+ -+ for (; i < possible; i++) { -+ cpumask_clear_cpu(curr_cpu, hw_thread_mask); -+ curr_cpu = cpumask_next(curr_cpu, hw_thread_mask); - } -+ -+ /* Identifying correct HW threads within physical cores */ -+ cpumask_shift_left(hw_thread_mask, hw_thread_mask, -+ num_cores_per_socket * -+ node_affinity.num_online_nodes * -+ hw_thread_no); - } - - int hfi1_get_proc_affinity(int node) -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/hw/hns/hns_roce_device.h BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/hns/hns_roce_device.h ---- BPI-Router-Linux-kernel/drivers/infiniband/hw/hns/hns_roce_device.h 2025-10-22 13:53:23.275328838 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/hns/hns_roce_device.h 2025-10-22 13:53:56.507169180 -0400 -@@ -856,6 +856,7 @@ struct hns_roce_caps { - u16 default_ceq_arm_st; - u8 cong_cap; - enum hns_roce_cong_type default_cong_type; -+ u32 max_ack_req_msg_len; - }; - - enum hns_roce_device_state { -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/hw/hns/hns_roce_hem.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/hns/hns_roce_hem.c ---- BPI-Router-Linux-kernel/drivers/infiniband/hw/hns/hns_roce_hem.c 2025-10-22 13:53:23.275328838 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/hns/hns_roce_hem.c 2025-10-22 13:53:56.507169180 -0400 -@@ -249,15 +249,12 @@ int hns_roce_calc_hem_mhop(struct hns_ro - } - - static struct hns_roce_hem *hns_roce_alloc_hem(struct hns_roce_dev *hr_dev, -- unsigned long hem_alloc_size, -- gfp_t gfp_mask) -+ unsigned long hem_alloc_size) - { - struct hns_roce_hem *hem; - int order; - void *buf; - -- WARN_ON(gfp_mask & __GFP_HIGHMEM); -- - order = get_order(hem_alloc_size); - if (PAGE_SIZE << order != hem_alloc_size) { - dev_err(hr_dev->dev, "invalid hem_alloc_size: %lu!\n", -@@ -265,13 +262,12 @@ static struct hns_roce_hem *hns_roce_all - return NULL; - } - -- hem = kmalloc(sizeof(*hem), -- gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN)); -+ hem = kmalloc(sizeof(*hem), GFP_KERNEL); - if (!hem) - return NULL; - - buf = dma_alloc_coherent(hr_dev->dev, hem_alloc_size, -- &hem->dma, gfp_mask); -+ &hem->dma, GFP_KERNEL); - if (!buf) - goto fail; - -@@ -378,7 +374,6 @@ static int alloc_mhop_hem(struct hns_roc - { - u32 bt_size = mhop->bt_chunk_size; - struct device *dev = hr_dev->dev; -- gfp_t flag; - u64 bt_ba; - u32 size; - int ret; -@@ -417,8 +412,7 @@ static int alloc_mhop_hem(struct hns_roc - * alloc bt space chunk for MTT/CQE. - */ - size = table->type < HEM_TYPE_MTT ? mhop->buf_chunk_size : bt_size; -- flag = GFP_KERNEL | __GFP_NOWARN; -- table->hem[index->buf] = hns_roce_alloc_hem(hr_dev, size, flag); -+ table->hem[index->buf] = hns_roce_alloc_hem(hr_dev, size); - if (!table->hem[index->buf]) { - ret = -ENOMEM; - goto err_alloc_hem; -@@ -546,9 +540,7 @@ int hns_roce_table_get(struct hns_roce_d - goto out; - } - -- table->hem[i] = hns_roce_alloc_hem(hr_dev, -- table->table_chunk_size, -- GFP_KERNEL | __GFP_NOWARN); -+ table->hem[i] = hns_roce_alloc_hem(hr_dev, table->table_chunk_size); - if (!table->hem[i]) { - ret = -ENOMEM; - goto out; -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/hw/hns/hns_roce_hw_v2.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/hns/hns_roce_hw_v2.c ---- BPI-Router-Linux-kernel/drivers/infiniband/hw/hns/hns_roce_hw_v2.c 2025-10-22 13:53:23.275328838 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/hns/hns_roce_hw_v2.c 2025-10-22 13:53:56.511169161 -0400 -@@ -2196,31 +2196,36 @@ static void apply_func_caps(struct hns_r - - static int hns_roce_query_caps(struct hns_roce_dev *hr_dev) - { -- struct hns_roce_cmq_desc desc[HNS_ROCE_QUERY_PF_CAPS_CMD_NUM]; -+ struct hns_roce_cmq_desc desc[HNS_ROCE_QUERY_PF_CAPS_CMD_NUM] = {}; - struct hns_roce_caps *caps = &hr_dev->caps; - struct hns_roce_query_pf_caps_a *resp_a; - struct hns_roce_query_pf_caps_b *resp_b; - struct hns_roce_query_pf_caps_c *resp_c; - struct hns_roce_query_pf_caps_d *resp_d; - struct hns_roce_query_pf_caps_e *resp_e; -+ struct hns_roce_query_pf_caps_f *resp_f; - enum hns_roce_opcode_type cmd; - int ctx_hop_num; - int pbl_hop_num; -+ int cmd_num; - int ret; - int i; - - cmd = hr_dev->is_vf ? HNS_ROCE_OPC_QUERY_VF_CAPS_NUM : - HNS_ROCE_OPC_QUERY_PF_CAPS_NUM; -+ cmd_num = hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08 ? -+ HNS_ROCE_QUERY_PF_CAPS_CMD_NUM_HIP08 : -+ HNS_ROCE_QUERY_PF_CAPS_CMD_NUM; - -- for (i = 0; i < HNS_ROCE_QUERY_PF_CAPS_CMD_NUM; i++) { -+ for (i = 0; i < cmd_num - 1; i++) { - hns_roce_cmq_setup_basic_desc(&desc[i], cmd, true); -- if (i < (HNS_ROCE_QUERY_PF_CAPS_CMD_NUM - 1)) -- desc[i].flag |= cpu_to_le16(HNS_ROCE_CMD_FLAG_NEXT); -- else -- desc[i].flag &= ~cpu_to_le16(HNS_ROCE_CMD_FLAG_NEXT); -+ desc[i].flag |= cpu_to_le16(HNS_ROCE_CMD_FLAG_NEXT); - } - -- ret = hns_roce_cmq_send(hr_dev, desc, HNS_ROCE_QUERY_PF_CAPS_CMD_NUM); -+ hns_roce_cmq_setup_basic_desc(&desc[cmd_num - 1], cmd, true); -+ desc[cmd_num - 1].flag &= ~cpu_to_le16(HNS_ROCE_CMD_FLAG_NEXT); -+ -+ ret = hns_roce_cmq_send(hr_dev, desc, cmd_num); - if (ret) - return ret; - -@@ -2229,6 +2234,7 @@ static int hns_roce_query_caps(struct hn - resp_c = (struct hns_roce_query_pf_caps_c *)desc[2].data; - resp_d = (struct hns_roce_query_pf_caps_d *)desc[3].data; - resp_e = (struct hns_roce_query_pf_caps_e *)desc[4].data; -+ resp_f = (struct hns_roce_query_pf_caps_f *)desc[5].data; - - caps->local_ca_ack_delay = resp_a->local_ca_ack_delay; - caps->max_sq_sg = le16_to_cpu(resp_a->max_sq_sg); -@@ -2293,6 +2299,8 @@ static int hns_roce_query_caps(struct hn - caps->reserved_srqs = hr_reg_read(resp_e, PF_CAPS_E_RSV_SRQS); - caps->reserved_lkey = hr_reg_read(resp_e, PF_CAPS_E_RSV_LKEYS); - -+ caps->max_ack_req_msg_len = le32_to_cpu(resp_f->max_ack_req_msg_len); -+ - caps->qpc_hop_num = ctx_hop_num; - caps->sccc_hop_num = ctx_hop_num; - caps->srqc_hop_num = ctx_hop_num; -@@ -2986,14 +2994,22 @@ static int hns_roce_v2_init(struct hns_r - { - int ret; - -+ if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08) { -+ ret = free_mr_init(hr_dev); -+ if (ret) { -+ dev_err(hr_dev->dev, "failed to init free mr!\n"); -+ return ret; -+ } -+ } -+ - /* The hns ROCEE requires the extdb info to be cleared before using */ - ret = hns_roce_clear_extdb_list_info(hr_dev); - if (ret) -- return ret; -+ goto err_clear_extdb_failed; - - ret = get_hem_table(hr_dev); - if (ret) -- return ret; -+ goto err_get_hem_table_failed; - - if (hr_dev->is_vf) - return 0; -@@ -3008,6 +3024,11 @@ static int hns_roce_v2_init(struct hns_r - - err_llm_init_failed: - put_hem_table(hr_dev); -+err_get_hem_table_failed: -+ hns_roce_function_clear(hr_dev); -+err_clear_extdb_failed: -+ if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08) -+ free_mr_exit(hr_dev); - - return ret; - } -@@ -3022,7 +3043,7 @@ static void hns_roce_v2_exit(struct hns_ - if (!hr_dev->is_vf) - hns_roce_free_link_table(hr_dev); - -- if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP09) -+ if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP09) - free_dip_entry(hr_dev); - } - -@@ -4560,7 +4581,9 @@ static int modify_qp_init_to_rtr(struct - dma_addr_t trrl_ba; - dma_addr_t irrl_ba; - enum ib_mtu ib_mtu; -+ u8 ack_req_freq; - const u8 *smac; -+ int lp_msg_len; - u8 lp_pktn_ini; - u64 *mtts; - u8 *dmac; -@@ -4643,7 +4666,8 @@ static int modify_qp_init_to_rtr(struct - return -EINVAL; - #define MIN_LP_MSG_LEN 1024 - /* mtu * (2 ^ lp_pktn_ini) should be in the range of 1024 to mtu */ -- lp_pktn_ini = ilog2(max(mtu, MIN_LP_MSG_LEN) / mtu); -+ lp_msg_len = max(mtu, MIN_LP_MSG_LEN); -+ lp_pktn_ini = ilog2(lp_msg_len / mtu); - - if (attr_mask & IB_QP_PATH_MTU) { - hr_reg_write(context, QPC_MTU, ib_mtu); -@@ -4653,8 +4677,22 @@ static int modify_qp_init_to_rtr(struct - hr_reg_write(context, QPC_LP_PKTN_INI, lp_pktn_ini); - hr_reg_clear(qpc_mask, QPC_LP_PKTN_INI); - -- /* ACK_REQ_FREQ should be larger than or equal to LP_PKTN_INI */ -- hr_reg_write(context, QPC_ACK_REQ_FREQ, lp_pktn_ini); -+ /* -+ * There are several constraints for ACK_REQ_FREQ: -+ * 1. mtu * (2 ^ ACK_REQ_FREQ) should not be too large, otherwise -+ * it may cause some unexpected retries when sending large -+ * payload. -+ * 2. ACK_REQ_FREQ should be larger than or equal to LP_PKTN_INI. -+ * 3. ACK_REQ_FREQ must be equal to LP_PKTN_INI when using LDCP -+ * or HC3 congestion control algorithm. -+ */ -+ if (hr_qp->cong_type == CONG_TYPE_LDCP || -+ hr_qp->cong_type == CONG_TYPE_HC3 || -+ hr_dev->caps.max_ack_req_msg_len < lp_msg_len) -+ ack_req_freq = lp_pktn_ini; -+ else -+ ack_req_freq = ilog2(hr_dev->caps.max_ack_req_msg_len / mtu); -+ hr_reg_write(context, QPC_ACK_REQ_FREQ, ack_req_freq); - hr_reg_clear(qpc_mask, QPC_ACK_REQ_FREQ); - - hr_reg_clear(qpc_mask, QPC_RX_REQ_PSN_ERR); -@@ -5349,11 +5387,10 @@ static int hns_roce_v2_modify_qp(struct - { - struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device); - struct hns_roce_qp *hr_qp = to_hr_qp(ibqp); -- struct hns_roce_v2_qp_context ctx[2]; -- struct hns_roce_v2_qp_context *context = ctx; -- struct hns_roce_v2_qp_context *qpc_mask = ctx + 1; -+ struct hns_roce_v2_qp_context *context; -+ struct hns_roce_v2_qp_context *qpc_mask; - struct ib_device *ibdev = &hr_dev->ib_dev; -- int ret; -+ int ret = -ENOMEM; - - if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS) - return -EOPNOTSUPP; -@@ -5364,7 +5401,11 @@ static int hns_roce_v2_modify_qp(struct - * we should set all bits of the relevant fields in context mask to - * 0 at the same time, else set them to 0x1. - */ -- memset(context, 0, hr_dev->caps.qpc_sz); -+ context = kvzalloc(sizeof(*context), GFP_KERNEL); -+ qpc_mask = kvzalloc(sizeof(*qpc_mask), GFP_KERNEL); -+ if (!context || !qpc_mask) -+ goto out; -+ - memset(qpc_mask, 0xff, hr_dev->caps.qpc_sz); - - ret = hns_roce_v2_set_abs_fields(ibqp, attr, attr_mask, cur_state, -@@ -5406,6 +5447,8 @@ static int hns_roce_v2_modify_qp(struct - clear_qp(hr_qp); - - out: -+ kvfree(qpc_mask); -+ kvfree(context); - return ret; - } - -@@ -5471,7 +5514,7 @@ out: - return ret; - } - --static int hns_roce_v2_query_sccc(struct hns_roce_dev *hr_dev, u32 qpn, -+static int hns_roce_v2_query_sccc(struct hns_roce_dev *hr_dev, u32 sccn, - void *buffer) - { - struct hns_roce_v2_scc_context *context; -@@ -5483,7 +5526,7 @@ static int hns_roce_v2_query_sccc(struct - return PTR_ERR(mailbox); - - ret = hns_roce_cmd_mbox(hr_dev, 0, mailbox->dma, HNS_ROCE_CMD_QUERY_SCCC, -- qpn); -+ sccn); - if (ret) - goto out; - -@@ -7044,21 +7087,11 @@ static int __hns_roce_hw_v2_init_instanc - goto error_failed_roce_init; - } - -- if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08) { -- ret = free_mr_init(hr_dev); -- if (ret) { -- dev_err(hr_dev->dev, "failed to init free mr!\n"); -- goto error_failed_free_mr_init; -- } -- } - - handle->priv = hr_dev; - - return 0; - --error_failed_free_mr_init: -- hns_roce_exit(hr_dev); -- - error_failed_roce_init: - kfree(hr_dev->priv); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/hw/hns/hns_roce_hw_v2.h BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/hns/hns_roce_hw_v2.h ---- BPI-Router-Linux-kernel/drivers/infiniband/hw/hns/hns_roce_hw_v2.h 2025-10-22 13:53:23.275328838 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/hns/hns_roce_hw_v2.h 2025-10-22 13:53:56.511169161 -0400 -@@ -1168,7 +1168,8 @@ struct hns_roce_cfg_gmv_tb_b { - #define GMV_TB_B_SMAC_H GMV_TB_B_FIELD_LOC(47, 32) - #define GMV_TB_B_SGID_IDX GMV_TB_B_FIELD_LOC(71, 64) - --#define HNS_ROCE_QUERY_PF_CAPS_CMD_NUM 5 -+#define HNS_ROCE_QUERY_PF_CAPS_CMD_NUM_HIP08 5 -+#define HNS_ROCE_QUERY_PF_CAPS_CMD_NUM 6 - struct hns_roce_query_pf_caps_a { - u8 number_ports; - u8 local_ca_ack_delay; -@@ -1280,6 +1281,11 @@ struct hns_roce_query_pf_caps_e { - __le16 aeq_period; - }; - -+struct hns_roce_query_pf_caps_f { -+ __le32 max_ack_req_msg_len; -+ __le32 rsv[5]; -+}; -+ - #define PF_CAPS_E_FIELD_LOC(h, l) \ - FIELD_LOC(struct hns_roce_query_pf_caps_e, h, l) - -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/hw/hns/hns_roce_main.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/hns/hns_roce_main.c ---- BPI-Router-Linux-kernel/drivers/infiniband/hw/hns/hns_roce_main.c 2025-10-22 13:53:23.275328838 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/hns/hns_roce_main.c 2025-10-22 13:53:56.511169161 -0400 -@@ -947,10 +947,7 @@ err_unmap_dmpt: - static void hns_roce_teardown_hca(struct hns_roce_dev *hr_dev) - { - hns_roce_cleanup_bitmap(hr_dev); -- -- if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_CQ_RECORD_DB || -- hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_QP_RECORD_DB) -- mutex_destroy(&hr_dev->pgdir_mutex); -+ mutex_destroy(&hr_dev->pgdir_mutex); - } - - /** -@@ -965,11 +962,11 @@ static int hns_roce_setup_hca(struct hns - - spin_lock_init(&hr_dev->sm_lock); - -- if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_CQ_RECORD_DB || -- hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_QP_RECORD_DB) { -- INIT_LIST_HEAD(&hr_dev->pgdir_list); -- mutex_init(&hr_dev->pgdir_mutex); -- } -+ INIT_LIST_HEAD(&hr_dev->qp_list); -+ spin_lock_init(&hr_dev->qp_list_lock); -+ -+ INIT_LIST_HEAD(&hr_dev->pgdir_list); -+ mutex_init(&hr_dev->pgdir_mutex); - - hns_roce_init_uar_table(hr_dev); - -@@ -1001,9 +998,7 @@ static int hns_roce_setup_hca(struct hns - - err_uar_table_free: - ida_destroy(&hr_dev->uar_ida.ida); -- if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_CQ_RECORD_DB || -- hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_QP_RECORD_DB) -- mutex_destroy(&hr_dev->pgdir_mutex); -+ mutex_destroy(&hr_dev->pgdir_mutex); - - return ret; - } -@@ -1132,9 +1127,6 @@ int hns_roce_init(struct hns_roce_dev *h - } - } - -- INIT_LIST_HEAD(&hr_dev->qp_list); -- spin_lock_init(&hr_dev->qp_list_lock); -- - ret = hns_roce_register_device(hr_dev); - if (ret) - goto error_failed_register_device; -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/hw/hns/hns_roce_restrack.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/hns/hns_roce_restrack.c ---- BPI-Router-Linux-kernel/drivers/infiniband/hw/hns/hns_roce_restrack.c 2025-10-22 13:53:23.275328838 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/hns/hns_roce_restrack.c 2025-10-22 13:53:56.511169161 -0400 -@@ -100,6 +100,7 @@ int hns_roce_fill_res_qp_entry_raw(struc - struct hns_roce_v2_qp_context qpc; - struct hns_roce_v2_scc_context sccc; - } context = {}; -+ u32 sccn = hr_qp->qpn; - int ret; - - if (!hr_dev->hw->query_qpc) -@@ -116,7 +117,13 @@ int hns_roce_fill_res_qp_entry_raw(struc - !hr_dev->hw->query_sccc) - goto out; - -- ret = hr_dev->hw->query_sccc(hr_dev, hr_qp->qpn, &context.sccc); -+ if (hr_qp->cong_type == CONG_TYPE_DIP) { -+ if (!hr_qp->dip) -+ goto out; -+ sccn = hr_qp->dip->dip_idx; -+ } -+ -+ ret = hr_dev->hw->query_sccc(hr_dev, sccn, &context.sccc); - if (ret) - ibdev_warn_ratelimited(&hr_dev->ib_dev, - "failed to query SCCC, ret = %d.\n", -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/hw/mana/qp.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/mana/qp.c ---- BPI-Router-Linux-kernel/drivers/infiniband/hw/mana/qp.c 2025-10-22 13:53:23.275328838 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/mana/qp.c 2025-10-22 13:53:56.511169161 -0400 -@@ -772,7 +772,7 @@ static int mana_ib_gd_modify_qp(struct i - req.ah_attr.dest_port = ROCE_V2_UDP_DPORT; - req.ah_attr.src_port = rdma_get_udp_sport(attr->ah_attr.grh.flow_label, - ibqp->qp_num, attr->dest_qp_num); -- req.ah_attr.traffic_class = attr->ah_attr.grh.traffic_class; -+ req.ah_attr.traffic_class = attr->ah_attr.grh.traffic_class >> 2; - req.ah_attr.hop_limit = attr->ah_attr.grh.hop_limit; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/hw/mlx5/counters.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/mlx5/counters.c ---- BPI-Router-Linux-kernel/drivers/infiniband/hw/mlx5/counters.c 2025-10-22 13:53:23.275328838 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/mlx5/counters.c 2025-10-22 13:53:56.511169161 -0400 -@@ -398,7 +398,7 @@ static int do_get_hw_stats(struct ib_dev - return ret; - - /* We don't expose device counters over Vports */ -- if (is_mdev_switchdev_mode(dev->mdev) && port_num != 0) -+ if (is_mdev_switchdev_mode(dev->mdev) && dev->is_rep && port_num != 0) - goto done; - - if (MLX5_CAP_PCAM_FEATURE(dev->mdev, rx_icrc_encapsulated_counter)) { -@@ -418,7 +418,7 @@ static int do_get_hw_stats(struct ib_dev - */ - goto done; - } -- ret = mlx5_lag_query_cong_counters(dev->mdev, -+ ret = mlx5_lag_query_cong_counters(mdev, - stats->value + - cnts->num_q_counters, - cnts->num_cong_counters, -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/hw/mlx5/devx.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/mlx5/devx.c ---- BPI-Router-Linux-kernel/drivers/infiniband/hw/mlx5/devx.c 2025-10-22 13:53:23.275328838 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/mlx5/devx.c 2025-10-22 13:53:56.511169161 -0400 -@@ -159,7 +159,7 @@ int mlx5_ib_devx_create(struct mlx5_ib_d - uctx = MLX5_ADDR_OF(create_uctx_in, in, uctx); - if (is_user && - (MLX5_CAP_GEN(dev->mdev, uctx_cap) & MLX5_UCTX_CAP_RAW_TX) && -- capable(CAP_NET_RAW)) -+ rdma_dev_has_raw_cap(&dev->ib_dev)) - cap |= MLX5_UCTX_CAP_RAW_TX; - if (is_user && - (MLX5_CAP_GEN(dev->mdev, uctx_cap) & -@@ -233,6 +233,7 @@ static u16 get_legacy_obj_type(u16 opcod - { - switch (opcode) { - case MLX5_CMD_OP_CREATE_RQ: -+ case MLX5_CMD_OP_CREATE_RMP: - return MLX5_EVENT_QUEUE_TYPE_RQ; - case MLX5_CMD_OP_CREATE_QP: - return MLX5_EVENT_QUEUE_TYPE_QP; -@@ -1958,6 +1959,7 @@ subscribe_event_xa_alloc(struct mlx5_dev - /* Level1 is valid for future use, no need to free */ - return -ENOMEM; - -+ INIT_LIST_HEAD(&obj_event->obj_sub_list); - err = xa_insert(&event->object_ids, - key_level2, - obj_event, -@@ -1966,7 +1968,6 @@ subscribe_event_xa_alloc(struct mlx5_dev - kfree(obj_event); - return err; - } -- INIT_LIST_HEAD(&obj_event->obj_sub_list); - } - - return 0; -@@ -2669,7 +2670,7 @@ static void devx_wait_async_destroy(stru - - void mlx5_ib_ufile_hw_cleanup(struct ib_uverbs_file *ufile) - { -- struct mlx5_async_cmd async_cmd[MAX_ASYNC_CMDS]; -+ struct mlx5_async_cmd *async_cmd; - struct ib_ucontext *ucontext = ufile->ucontext; - struct ib_device *device = ucontext->device; - struct mlx5_ib_dev *dev = to_mdev(device); -@@ -2678,6 +2679,10 @@ void mlx5_ib_ufile_hw_cleanup(struct ib_ - int head = 0; - int tail = 0; - -+ async_cmd = kcalloc(MAX_ASYNC_CMDS, sizeof(*async_cmd), GFP_KERNEL); -+ if (!async_cmd) -+ return; -+ - list_for_each_entry(uobject, &ufile->uobjects, list) { - WARN_ON(uverbs_try_lock_object(uobject, UVERBS_LOOKUP_WRITE)); - -@@ -2713,6 +2718,8 @@ void mlx5_ib_ufile_hw_cleanup(struct ib_ - devx_wait_async_destroy(&async_cmd[head % MAX_ASYNC_CMDS]); - head++; - } -+ -+ kfree(async_cmd); - } - - static ssize_t devx_async_cmd_event_read(struct file *filp, char __user *buf, -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/hw/mlx5/dm.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/mlx5/dm.c ---- BPI-Router-Linux-kernel/drivers/infiniband/hw/mlx5/dm.c 2025-10-22 13:53:23.275328838 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/mlx5/dm.c 2025-10-22 13:53:56.511169161 -0400 -@@ -282,7 +282,7 @@ static struct ib_dm *handle_alloc_dm_mem - int err; - u64 address; - -- if (!MLX5_CAP_DEV_MEM(dm_db->dev, memic)) -+ if (!dm_db || !MLX5_CAP_DEV_MEM(dm_db->dev, memic)) - return ERR_PTR(-EOPNOTSUPP); - - dm = kzalloc(sizeof(*dm), GFP_KERNEL); -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/hw/mlx5/fs.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/mlx5/fs.c ---- BPI-Router-Linux-kernel/drivers/infiniband/hw/mlx5/fs.c 2025-10-22 13:53:23.275328838 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/mlx5/fs.c 2025-10-22 13:53:56.511169161 -0400 -@@ -2458,7 +2458,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD - struct mlx5_ib_dev *dev; - u32 flags; - -- if (!capable(CAP_NET_RAW)) -+ if (!rdma_uattrs_has_raw_cap(attrs)) - return -EPERM; - - fs_matcher = uverbs_attr_get_obj(attrs, -@@ -2989,7 +2989,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD - u32 ft_id; - int err; - -- if (!capable(CAP_NET_RAW)) -+ if (!rdma_dev_has_raw_cap(&dev->ib_dev)) - return -EPERM; - - err = uverbs_get_const(&ib_uapi_ft_type, attrs, -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/hw/mlx5/main.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/mlx5/main.c ---- BPI-Router-Linux-kernel/drivers/infiniband/hw/mlx5/main.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/mlx5/main.c 2025-10-22 13:53:56.511169161 -0400 -@@ -1791,6 +1791,33 @@ static void deallocate_uars(struct mlx5_ - context->devx_uid); - } - -+static int mlx5_ib_enable_lb_mp(struct mlx5_core_dev *master, -+ struct mlx5_core_dev *slave) -+{ -+ int err; -+ -+ err = mlx5_nic_vport_update_local_lb(master, true); -+ if (err) -+ return err; -+ -+ err = mlx5_nic_vport_update_local_lb(slave, true); -+ if (err) -+ goto out; -+ -+ return 0; -+ -+out: -+ mlx5_nic_vport_update_local_lb(master, false); -+ return err; -+} -+ -+static void mlx5_ib_disable_lb_mp(struct mlx5_core_dev *master, -+ struct mlx5_core_dev *slave) -+{ -+ mlx5_nic_vport_update_local_lb(slave, false); -+ mlx5_nic_vport_update_local_lb(master, false); -+} -+ - int mlx5_ib_enable_lb(struct mlx5_ib_dev *dev, bool td, bool qp) - { - int err = 0; -@@ -3495,6 +3522,8 @@ static void mlx5_ib_unbind_slave_port(st - - lockdep_assert_held(&mlx5_ib_multiport_mutex); - -+ mlx5_ib_disable_lb_mp(ibdev->mdev, mpi->mdev); -+ - mlx5_core_mp_event_replay(ibdev->mdev, - MLX5_DRIVER_EVENT_AFFILIATION_REMOVED, - NULL); -@@ -3590,6 +3619,10 @@ static bool mlx5_ib_bind_slave_port(stru - MLX5_DRIVER_EVENT_AFFILIATION_DONE, - &key); - -+ err = mlx5_ib_enable_lb_mp(ibdev->mdev, mpi->mdev); -+ if (err) -+ goto unbind; -+ - return true; - - unbind: -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/hw/mlx5/mr.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/mlx5/mr.c ---- BPI-Router-Linux-kernel/drivers/infiniband/hw/mlx5/mr.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/mlx5/mr.c 2025-10-22 13:53:56.511169161 -0400 -@@ -2027,23 +2027,50 @@ void mlx5_ib_revoke_data_direct_mrs(stru - } - } - --static int mlx5_revoke_mr(struct mlx5_ib_mr *mr) -+static int mlx5_umr_revoke_mr_with_lock(struct mlx5_ib_mr *mr) - { -- struct mlx5_ib_dev *dev = to_mdev(mr->ibmr.device); -- struct mlx5_cache_ent *ent = mr->mmkey.cache_ent; -- bool is_odp = is_odp_mr(mr); - bool is_odp_dma_buf = is_dmabuf_mr(mr) && -- !to_ib_umem_dmabuf(mr->umem)->pinned; -- bool from_cache = !!ent; -- int ret = 0; -+ !to_ib_umem_dmabuf(mr->umem)->pinned; -+ bool is_odp = is_odp_mr(mr); -+ int ret; - - if (is_odp) - mutex_lock(&to_ib_umem_odp(mr->umem)->umem_mutex); - - if (is_odp_dma_buf) -- dma_resv_lock(to_ib_umem_dmabuf(mr->umem)->attach->dmabuf->resv, NULL); -+ dma_resv_lock(to_ib_umem_dmabuf(mr->umem)->attach->dmabuf->resv, -+ NULL); -+ -+ ret = mlx5r_umr_revoke_mr(mr); -+ -+ if (is_odp) { -+ if (!ret) -+ to_ib_umem_odp(mr->umem)->private = NULL; -+ mutex_unlock(&to_ib_umem_odp(mr->umem)->umem_mutex); -+ } -+ -+ if (is_odp_dma_buf) { -+ if (!ret) -+ to_ib_umem_dmabuf(mr->umem)->private = NULL; -+ dma_resv_unlock( -+ to_ib_umem_dmabuf(mr->umem)->attach->dmabuf->resv); -+ } - -- if (mr->mmkey.cacheable && !mlx5r_umr_revoke_mr(mr) && !cache_ent_find_and_store(dev, mr)) { -+ return ret; -+} -+ -+static int mlx5r_handle_mkey_cleanup(struct mlx5_ib_mr *mr) -+{ -+ bool is_odp_dma_buf = is_dmabuf_mr(mr) && -+ !to_ib_umem_dmabuf(mr->umem)->pinned; -+ struct mlx5_ib_dev *dev = to_mdev(mr->ibmr.device); -+ struct mlx5_cache_ent *ent = mr->mmkey.cache_ent; -+ bool is_odp = is_odp_mr(mr); -+ bool from_cache = !!ent; -+ int ret; -+ -+ if (mr->mmkey.cacheable && !mlx5_umr_revoke_mr_with_lock(mr) && -+ !cache_ent_find_and_store(dev, mr)) { - ent = mr->mmkey.cache_ent; - /* upon storing to a clean temp entry - schedule its cleanup */ - spin_lock_irq(&ent->mkeys_queue.lock); -@@ -2055,7 +2082,7 @@ static int mlx5_revoke_mr(struct mlx5_ib - ent->tmp_cleanup_scheduled = true; - } - spin_unlock_irq(&ent->mkeys_queue.lock); -- goto out; -+ return 0; - } - - if (ent) { -@@ -2064,8 +2091,14 @@ static int mlx5_revoke_mr(struct mlx5_ib - mr->mmkey.cache_ent = NULL; - spin_unlock_irq(&ent->mkeys_queue.lock); - } -+ -+ if (is_odp) -+ mutex_lock(&to_ib_umem_odp(mr->umem)->umem_mutex); -+ -+ if (is_odp_dma_buf) -+ dma_resv_lock(to_ib_umem_dmabuf(mr->umem)->attach->dmabuf->resv, -+ NULL); - ret = destroy_mkey(dev, mr); --out: - if (is_odp) { - if (!ret) - to_ib_umem_odp(mr->umem)->private = NULL; -@@ -2075,9 +2108,9 @@ out: - if (is_odp_dma_buf) { - if (!ret) - to_ib_umem_dmabuf(mr->umem)->private = NULL; -- dma_resv_unlock(to_ib_umem_dmabuf(mr->umem)->attach->dmabuf->resv); -+ dma_resv_unlock( -+ to_ib_umem_dmabuf(mr->umem)->attach->dmabuf->resv); - } -- - return ret; - } - -@@ -2126,7 +2159,7 @@ static int __mlx5_ib_dereg_mr(struct ib_ - } - - /* Stop DMA */ -- rc = mlx5_revoke_mr(mr); -+ rc = mlx5r_handle_mkey_cleanup(mr); - if (rc) - return rc; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/hw/mlx5/odp.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/mlx5/odp.c ---- BPI-Router-Linux-kernel/drivers/infiniband/hw/mlx5/odp.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/mlx5/odp.c 2025-10-22 13:53:56.511169161 -0400 -@@ -259,8 +259,8 @@ static void destroy_unused_implicit_chil - } - - if (MLX5_CAP_ODP(mr_to_mdev(mr)->mdev, mem_page_fault)) -- __xa_erase(&mr_to_mdev(mr)->odp_mkeys, -- mlx5_base_mkey(mr->mmkey.key)); -+ xa_erase(&mr_to_mdev(mr)->odp_mkeys, -+ mlx5_base_mkey(mr->mmkey.key)); - xa_unlock(&imr->implicit_children); - - /* Freeing a MR is a sleeping operation, so bounce to a work queue */ -@@ -532,8 +532,8 @@ static struct mlx5_ib_mr *implicit_get_c - } - - if (MLX5_CAP_ODP(dev->mdev, mem_page_fault)) { -- ret = __xa_store(&dev->odp_mkeys, mlx5_base_mkey(mr->mmkey.key), -- &mr->mmkey, GFP_KERNEL); -+ ret = xa_store(&dev->odp_mkeys, mlx5_base_mkey(mr->mmkey.key), -+ &mr->mmkey, GFP_KERNEL); - if (xa_is_err(ret)) { - ret = ERR_PTR(xa_err(ret)); - __xa_erase(&imr->implicit_children, idx); -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/hw/mlx5/umr.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/mlx5/umr.c ---- BPI-Router-Linux-kernel/drivers/infiniband/hw/mlx5/umr.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/hw/mlx5/umr.c 2025-10-22 13:53:56.511169161 -0400 -@@ -32,13 +32,15 @@ static __be64 get_umr_disable_mr_mask(vo - return cpu_to_be64(result); - } - --static __be64 get_umr_update_translation_mask(void) -+static __be64 get_umr_update_translation_mask(struct mlx5_ib_dev *dev) - { - u64 result; - - result = MLX5_MKEY_MASK_LEN | - MLX5_MKEY_MASK_PAGE_SIZE | - MLX5_MKEY_MASK_START_ADDR; -+ if (MLX5_CAP_GEN_2(dev->mdev, umr_log_entity_size_5)) -+ result |= MLX5_MKEY_MASK_PAGE_SIZE_5; - - return cpu_to_be64(result); - } -@@ -654,7 +656,7 @@ static void mlx5r_umr_final_update_xlt(s - flags & MLX5_IB_UPD_XLT_ENABLE || flags & MLX5_IB_UPD_XLT_ADDR; - - if (update_translation) { -- wqe->ctrl_seg.mkey_mask |= get_umr_update_translation_mask(); -+ wqe->ctrl_seg.mkey_mask |= get_umr_update_translation_mask(dev); - if (!mr->ibmr.length) - MLX5_SET(mkc, &wqe->mkey_seg, length64, 1); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/sw/rxe/rxe_net.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/sw/rxe/rxe_net.c ---- BPI-Router-Linux-kernel/drivers/infiniband/sw/rxe/rxe_net.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/sw/rxe/rxe_net.c 2025-10-22 13:53:56.511169161 -0400 -@@ -345,33 +345,15 @@ int rxe_prepare(struct rxe_av *av, struc - - static void rxe_skb_tx_dtor(struct sk_buff *skb) - { -- struct net_device *ndev = skb->dev; -- struct rxe_dev *rxe; -- unsigned int qp_index; -- struct rxe_qp *qp; -+ struct rxe_qp *qp = skb->sk->sk_user_data; - int skb_out; - -- rxe = rxe_get_dev_from_net(ndev); -- if (!rxe && is_vlan_dev(ndev)) -- rxe = rxe_get_dev_from_net(vlan_dev_real_dev(ndev)); -- if (WARN_ON(!rxe)) -- return; -- -- qp_index = (int)(uintptr_t)skb->sk->sk_user_data; -- if (!qp_index) -- return; -- -- qp = rxe_pool_get_index(&rxe->qp_pool, qp_index); -- if (!qp) -- goto put_dev; -- - skb_out = atomic_dec_return(&qp->skb_out); -- if (qp->need_req_skb && skb_out < RXE_INFLIGHT_SKBS_PER_QP_LOW) -+ if (unlikely(qp->need_req_skb && -+ skb_out < RXE_INFLIGHT_SKBS_PER_QP_LOW)) - rxe_sched_task(&qp->send_task); - - rxe_put(qp); --put_dev: -- ib_device_put(&rxe->ib_dev); - sock_put(skb->sk); - } - -@@ -383,6 +365,7 @@ static int rxe_send(struct sk_buff *skb, - sock_hold(sk); - skb->sk = sk; - skb->destructor = rxe_skb_tx_dtor; -+ rxe_get(pkt->qp); - atomic_inc(&pkt->qp->skb_out); - - if (skb->protocol == htons(ETH_P_IP)) -@@ -405,6 +388,7 @@ static int rxe_loopback(struct sk_buff * - sock_hold(sk); - skb->sk = sk; - skb->destructor = rxe_skb_tx_dtor; -+ rxe_get(pkt->qp); - atomic_inc(&pkt->qp->skb_out); - - if (skb->protocol == htons(ETH_P_IP)) -@@ -497,6 +481,9 @@ struct sk_buff *rxe_init_packet(struct r - goto out; - } - -+ /* Add time stamp to skb. */ -+ skb->tstamp = ktime_get(); -+ - skb_reserve(skb, hdr_len + LL_RESERVED_SPACE(ndev)); - - /* FIXME: hold reference to this netdev until life of this skb. */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/sw/rxe/rxe_qp.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/sw/rxe/rxe_qp.c ---- BPI-Router-Linux-kernel/drivers/infiniband/sw/rxe/rxe_qp.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/sw/rxe/rxe_qp.c 2025-10-22 13:53:56.511169161 -0400 -@@ -244,7 +244,7 @@ static int rxe_qp_init_req(struct rxe_de - err = sock_create_kern(&init_net, AF_INET, SOCK_DGRAM, 0, &qp->sk); - if (err < 0) - return err; -- qp->sk->sk->sk_user_data = (void *)(uintptr_t)qp->elem.index; -+ qp->sk->sk->sk_user_data = qp; - - /* pick a source UDP port number for this QP based on - * the source QPN. this spreads traffic for different QPs -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/sw/siw/siw_qp_tx.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/sw/siw/siw_qp_tx.c ---- BPI-Router-Linux-kernel/drivers/infiniband/sw/siw/siw_qp_tx.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/sw/siw/siw_qp_tx.c 2025-10-22 13:53:56.511169161 -0400 -@@ -332,18 +332,17 @@ static int siw_tcp_sendpages(struct sock - if (!sendpage_ok(page[i])) - msg.msg_flags &= ~MSG_SPLICE_PAGES; - bvec_set_page(&bvec, page[i], bytes, offset); -- iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, size); -+ iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, bytes); - - try_page_again: - lock_sock(sk); -- rv = tcp_sendmsg_locked(sk, &msg, size); -+ rv = tcp_sendmsg_locked(sk, &msg, bytes); - release_sock(sk); - - if (rv > 0) { - size -= rv; - sent += rv; - if (rv != bytes) { -- offset += rv; - bytes -= rv; - goto try_page_again; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/ulp/ipoib/ipoib_main.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/ulp/ipoib/ipoib_main.c ---- BPI-Router-Linux-kernel/drivers/infiniband/ulp/ipoib/ipoib_main.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/ulp/ipoib/ipoib_main.c 2025-10-22 13:53:56.511169161 -0400 -@@ -2577,6 +2577,8 @@ static struct net_device *ipoib_add_port - - ndev->rtnl_link_ops = ipoib_get_link_ops(); - -+ dev_net_set(ndev, rdma_dev_net(hca)); -+ - result = register_netdev(ndev); - if (result) { - pr_warn("%s: couldn't register ipoib port %d; error %d\n", -diff -purNx .git BPI-Router-Linux-kernel/drivers/infiniband/ulp/srp/ib_srp.c BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/ulp/srp/ib_srp.c ---- BPI-Router-Linux-kernel/drivers/infiniband/ulp/srp/ib_srp.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/infiniband/ulp/srp/ib_srp.c 2025-10-22 13:53:56.511169161 -0400 -@@ -3705,9 +3705,10 @@ static ssize_t add_target_store(struct d - target_host->max_id = 1; - target_host->max_lun = -1LL; - target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb; -- target_host->max_segment_size = ib_dma_max_seg_size(ibdev); - -- if (!(ibdev->attrs.kernel_cap_flags & IBK_SG_GAPS_REG)) -+ if (ibdev->attrs.kernel_cap_flags & IBK_SG_GAPS_REG) -+ target_host->max_segment_size = ib_dma_max_seg_size(ibdev); -+ else - target_host->virt_boundary_mask = ~srp_dev->mr_page_mask; - - target = host_to_target(target_host); -diff -purNx .git BPI-Router-Linux-kernel/drivers/input/joystick/fsia6b.c BPI-Router-Linux-kernel-6.16.12/drivers/input/joystick/fsia6b.c ---- BPI-Router-Linux-kernel/drivers/input/joystick/fsia6b.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/input/joystick/fsia6b.c 2025-10-22 13:53:56.511169161 -0400 -@@ -149,7 +149,7 @@ static int fsia6b_serio_connect(struct s - } - fsia6b->dev = input_dev; - -- snprintf(fsia6b->phys, sizeof(fsia6b->phys), "%s/input0", serio->phys); -+ scnprintf(fsia6b->phys, sizeof(fsia6b->phys), "%s/input0", serio->phys); - - input_dev->name = DRIVER_DESC; - input_dev->phys = fsia6b->phys; -diff -purNx .git BPI-Router-Linux-kernel/drivers/input/joystick/xpad.c BPI-Router-Linux-kernel-6.16.12/drivers/input/joystick/xpad.c ---- BPI-Router-Linux-kernel/drivers/input/joystick/xpad.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/input/joystick/xpad.c 2025-10-22 13:53:56.511169161 -0400 -@@ -172,6 +172,7 @@ static const struct xpad_device { - { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", 0, XTYPE_XBOX }, - { 0x046d, 0xca8a, "Logitech Precision Vibration Feedback Wheel", 0, XTYPE_XBOX }, - { 0x046d, 0xcaa3, "Logitech DriveFx Racing Wheel", 0, XTYPE_XBOX360 }, -+ { 0x0502, 0x1305, "Acer NGR200", 0, XTYPE_XBOX360 }, - { 0x056e, 0x2004, "Elecom JC-U3613M", 0, XTYPE_XBOX360 }, - { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", 0, XTYPE_XBOX }, - { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", 0, XTYPE_XBOX }, -@@ -421,6 +422,7 @@ static const struct xpad_device { - { 0x3537, 0x1010, "GameSir G7 SE", 0, XTYPE_XBOXONE }, - { 0x366c, 0x0005, "ByoWave Proteus Controller", MAP_SHARE_BUTTON, XTYPE_XBOXONE, FLAG_DELAY_INIT }, - { 0x3767, 0x0101, "Fanatec Speedster 3 Forceshock Wheel", 0, XTYPE_XBOX }, -+ { 0x37d7, 0x2501, "Flydigi Apex 5", 0, XTYPE_XBOX360 }, - { 0x413d, 0x2104, "Black Shark Green Ghost Gamepad", 0, XTYPE_XBOX360 }, - { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX }, - { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN } -@@ -524,6 +526,7 @@ static const struct usb_device_id xpad_t - XPAD_XBOX360_VENDOR(0x045e), /* Microsoft Xbox 360 controllers */ - XPAD_XBOXONE_VENDOR(0x045e), /* Microsoft Xbox One controllers */ - XPAD_XBOX360_VENDOR(0x046d), /* Logitech Xbox 360-style controllers */ -+ XPAD_XBOX360_VENDOR(0x0502), /* Acer Inc. Xbox 360 style controllers */ - XPAD_XBOX360_VENDOR(0x056e), /* Elecom JC-U3613M */ - XPAD_XBOX360_VENDOR(0x06a3), /* Saitek P3600 */ - XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz Xbox 360 controllers */ -@@ -576,6 +579,7 @@ static const struct usb_device_id xpad_t - XPAD_XBOX360_VENDOR(0x3537), /* GameSir Controllers */ - XPAD_XBOXONE_VENDOR(0x3537), /* GameSir Controllers */ - XPAD_XBOXONE_VENDOR(0x366c), /* ByoWave controllers */ -+ XPAD_XBOX360_VENDOR(0x37d7), /* Flydigi Controllers */ - XPAD_XBOX360_VENDOR(0x413d), /* Black Shark Green Ghost Controller */ - { } - }; -@@ -1344,11 +1348,12 @@ static int xpad_try_sending_next_out_pac - usb_anchor_urb(xpad->irq_out, &xpad->irq_out_anchor); - error = usb_submit_urb(xpad->irq_out, GFP_ATOMIC); - if (error) { -- dev_err(&xpad->intf->dev, -- "%s - usb_submit_urb failed with result %d\n", -- __func__, error); -+ if (error != -ENODEV) -+ dev_err(&xpad->intf->dev, -+ "%s - usb_submit_urb failed with result %d\n", -+ __func__, error); - usb_unanchor_urb(xpad->irq_out); -- return -EIO; -+ return error; - } - - xpad->irq_out_active = true; -diff -purNx .git BPI-Router-Linux-kernel/drivers/input/keyboard/atkbd.c BPI-Router-Linux-kernel-6.16.12/drivers/input/keyboard/atkbd.c ---- BPI-Router-Linux-kernel/drivers/input/keyboard/atkbd.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/input/keyboard/atkbd.c 2025-10-22 13:53:56.511169161 -0400 -@@ -1191,8 +1191,8 @@ static void atkbd_set_device_attrs(struc - "AT %s Set %d keyboard", - atkbd->translated ? "Translated" : "Raw", atkbd->set); - -- snprintf(atkbd->phys, sizeof(atkbd->phys), -- "%s/input0", atkbd->ps2dev.serio->phys); -+ scnprintf(atkbd->phys, sizeof(atkbd->phys), -+ "%s/input0", atkbd->ps2dev.serio->phys); - - input_dev->name = atkbd->name; - input_dev->phys = atkbd->phys; -diff -purNx .git BPI-Router-Linux-kernel/drivers/input/misc/cs40l50-vibra.c BPI-Router-Linux-kernel-6.16.12/drivers/input/misc/cs40l50-vibra.c ---- BPI-Router-Linux-kernel/drivers/input/misc/cs40l50-vibra.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/input/misc/cs40l50-vibra.c 2025-10-22 13:53:56.511169161 -0400 -@@ -238,6 +238,8 @@ static int cs40l50_upload_owt(struct cs4 - header.data_words = len / sizeof(u32); - - new_owt_effect_data = kmalloc(sizeof(header) + len, GFP_KERNEL); -+ if (!new_owt_effect_data) -+ return -ENOMEM; - - memcpy(new_owt_effect_data, &header, sizeof(header)); - memcpy(new_owt_effect_data + sizeof(header), work_data->custom_data, len); -diff -purNx .git BPI-Router-Linux-kernel/drivers/input/misc/gpio-beeper.c BPI-Router-Linux-kernel-6.16.12/drivers/input/misc/gpio-beeper.c ---- BPI-Router-Linux-kernel/drivers/input/misc/gpio-beeper.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/input/misc/gpio-beeper.c 2025-10-22 13:53:56.511169161 -0400 -@@ -94,7 +94,7 @@ static int gpio_beeper_probe(struct plat - - #ifdef CONFIG_OF - static const struct of_device_id gpio_beeper_of_match[] = { -- { .compatible = BEEPER_MODNAME, }, -+ { .compatible = "gpio-beeper", }, - { } - }; - MODULE_DEVICE_TABLE(of, gpio_beeper_of_match); -diff -purNx .git BPI-Router-Linux-kernel/drivers/input/misc/iqs626a.c BPI-Router-Linux-kernel-6.16.12/drivers/input/misc/iqs626a.c ---- BPI-Router-Linux-kernel/drivers/input/misc/iqs626a.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/input/misc/iqs626a.c 2025-10-22 13:53:56.511169161 -0400 -@@ -771,7 +771,7 @@ static int iqs626_parse_trackpad(struct - u8 *thresh = &sys_reg->tp_grp_reg.ch_reg_tp[i].thresh; - char tc_name[10]; - -- snprintf(tc_name, sizeof(tc_name), "channel-%d", i); -+ scnprintf(tc_name, sizeof(tc_name), "channel-%d", i); - - struct fwnode_handle *tc_node __free(fwnode_handle) = - fwnode_get_named_child_node(ch_node, tc_name); -diff -purNx .git BPI-Router-Linux-kernel/drivers/input/misc/iqs7222.c BPI-Router-Linux-kernel-6.16.12/drivers/input/misc/iqs7222.c ---- BPI-Router-Linux-kernel/drivers/input/misc/iqs7222.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/input/misc/iqs7222.c 2025-10-22 13:53:56.515169141 -0400 -@@ -301,6 +301,7 @@ struct iqs7222_dev_desc { - int allow_offset; - int event_offset; - int comms_offset; -+ int ext_chan; - bool legacy_gesture; - struct iqs7222_reg_grp_desc reg_grps[IQS7222_NUM_REG_GRPS]; - }; -@@ -315,6 +316,7 @@ static const struct iqs7222_dev_desc iqs - .allow_offset = 9, - .event_offset = 10, - .comms_offset = 12, -+ .ext_chan = 10, - .reg_grps = { - [IQS7222_REG_GRP_STAT] = { - .base = IQS7222_SYS_STATUS, -@@ -373,6 +375,7 @@ static const struct iqs7222_dev_desc iqs - .allow_offset = 9, - .event_offset = 10, - .comms_offset = 12, -+ .ext_chan = 10, - .legacy_gesture = true, - .reg_grps = { - [IQS7222_REG_GRP_STAT] = { -@@ -2244,7 +2247,7 @@ static int iqs7222_parse_chan(struct iqs - const struct iqs7222_dev_desc *dev_desc = iqs7222->dev_desc; - struct i2c_client *client = iqs7222->client; - int num_chan = dev_desc->reg_grps[IQS7222_REG_GRP_CHAN].num_row; -- int ext_chan = rounddown(num_chan, 10); -+ int ext_chan = dev_desc->ext_chan ? : num_chan; - int error, i; - u16 *chan_setup = iqs7222->chan_setup[chan_index]; - u16 *sys_setup = iqs7222->sys_setup; -@@ -2424,6 +2427,9 @@ static int iqs7222_parse_chan(struct iqs - if (error) - return error; - -+ if (!iqs7222->kp_type[chan_index][i]) -+ continue; -+ - if (!dev_desc->event_offset) - continue; - -@@ -2445,7 +2451,7 @@ static int iqs7222_parse_sldr(struct iqs - const struct iqs7222_dev_desc *dev_desc = iqs7222->dev_desc; - struct i2c_client *client = iqs7222->client; - int num_chan = dev_desc->reg_grps[IQS7222_REG_GRP_CHAN].num_row; -- int ext_chan = rounddown(num_chan, 10); -+ int ext_chan = dev_desc->ext_chan ? : num_chan; - int count, error, reg_offset, i; - u16 *event_mask = &iqs7222->sys_setup[dev_desc->event_offset]; - u16 *sldr_setup = iqs7222->sldr_setup[sldr_index]; -diff -purNx .git BPI-Router-Linux-kernel/drivers/input/mouse/alps.c BPI-Router-Linux-kernel-6.16.12/drivers/input/mouse/alps.c ---- BPI-Router-Linux-kernel/drivers/input/mouse/alps.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/input/mouse/alps.c 2025-10-22 13:53:56.515169141 -0400 -@@ -1408,9 +1408,9 @@ static int alps_do_register_bare_ps2_mou - return -ENOMEM; - } - -- snprintf(priv->phys3, sizeof(priv->phys3), "%s/%s", -- psmouse->ps2dev.serio->phys, -- (priv->dev2 ? "input2" : "input1")); -+ scnprintf(priv->phys3, sizeof(priv->phys3), "%s/%s", -+ psmouse->ps2dev.serio->phys, -+ (priv->dev2 ? "input2" : "input1")); - dev3->phys = priv->phys3; - - /* -@@ -3103,8 +3103,8 @@ int alps_init(struct psmouse *psmouse) - goto init_fail; - } - -- snprintf(priv->phys2, sizeof(priv->phys2), "%s/input1", -- psmouse->ps2dev.serio->phys); -+ scnprintf(priv->phys2, sizeof(priv->phys2), "%s/input1", -+ psmouse->ps2dev.serio->phys); - dev2->phys = priv->phys2; - - /* -diff -purNx .git BPI-Router-Linux-kernel/drivers/input/mouse/lifebook.c BPI-Router-Linux-kernel-6.16.12/drivers/input/mouse/lifebook.c ---- BPI-Router-Linux-kernel/drivers/input/mouse/lifebook.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/input/mouse/lifebook.c 2025-10-22 13:53:56.515169141 -0400 -@@ -279,8 +279,8 @@ static int lifebook_create_relative_devi - goto err_out; - - priv->dev2 = dev2; -- snprintf(priv->phys, sizeof(priv->phys), -- "%s/input1", psmouse->ps2dev.serio->phys); -+ scnprintf(priv->phys, sizeof(priv->phys), -+ "%s/input1", psmouse->ps2dev.serio->phys); - - dev2->phys = priv->phys; - dev2->name = "LBPS/2 Fujitsu Lifebook Touchpad"; -diff -purNx .git BPI-Router-Linux-kernel/drivers/input/mouse/psmouse-base.c BPI-Router-Linux-kernel-6.16.12/drivers/input/mouse/psmouse-base.c ---- BPI-Router-Linux-kernel/drivers/input/mouse/psmouse-base.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/input/mouse/psmouse-base.c 2025-10-22 13:53:56.515169141 -0400 -@@ -1600,7 +1600,7 @@ static int psmouse_connect(struct serio - psmouse_pre_receive_byte, psmouse_receive_byte); - INIT_DELAYED_WORK(&psmouse->resync_work, psmouse_resync); - psmouse->dev = input_dev; -- snprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys); -+ scnprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys); - - psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/input/serio/i8042-acpipnpio.h BPI-Router-Linux-kernel-6.16.12/drivers/input/serio/i8042-acpipnpio.h ---- BPI-Router-Linux-kernel/drivers/input/serio/i8042-acpipnpio.h 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/input/serio/i8042-acpipnpio.h 2025-10-22 13:53:56.515169141 -0400 -@@ -1155,6 +1155,20 @@ static const struct dmi_system_id i8042_ - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) - }, -+ { -+ .matches = { -+ DMI_MATCH(DMI_BOARD_NAME, "XxHP4NAx"), -+ }, -+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | -+ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) -+ }, -+ { -+ .matches = { -+ DMI_MATCH(DMI_BOARD_NAME, "XxKK4NAx_XxSP4NAx"), -+ }, -+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | -+ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) -+ }, - /* - * A lot of modern Clevo barebones have touchpad and/or keyboard issues - * after suspend fixable with the forcenorestore quirk. -diff -purNx .git BPI-Router-Linux-kernel/drivers/input/touchscreen/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/input/touchscreen/Kconfig ---- BPI-Router-Linux-kernel/drivers/input/touchscreen/Kconfig 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/input/touchscreen/Kconfig 2025-10-22 13:53:56.515169141 -0400 -@@ -105,7 +105,6 @@ config TOUCHSCREEN_ADC - - config TOUCHSCREEN_APPLE_Z2 - tristate "Apple Z2 touchscreens" -- default ARCH_APPLE - depends on SPI && (ARCH_APPLE || COMPILE_TEST) - help - Say Y here if you have an ARM Apple device with -diff -purNx .git BPI-Router-Linux-kernel/drivers/input/touchscreen/melfas_mip4.c BPI-Router-Linux-kernel-6.16.12/drivers/input/touchscreen/melfas_mip4.c ---- BPI-Router-Linux-kernel/drivers/input/touchscreen/melfas_mip4.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/input/touchscreen/melfas_mip4.c 2025-10-22 13:53:56.515169141 -0400 -@@ -1554,7 +1554,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(mip4_pm_ - - #ifdef CONFIG_OF - static const struct of_device_id mip4_of_match[] = { -- { .compatible = "melfas,"MIP4_DEVICE_NAME, }, -+ { .compatible = "melfas,mip4_ts", }, - { }, - }; - MODULE_DEVICE_TABLE(of, mip4_of_match); -diff -purNx .git BPI-Router-Linux-kernel/drivers/interconnect/core.c BPI-Router-Linux-kernel-6.16.12/drivers/interconnect/core.c ---- BPI-Router-Linux-kernel/drivers/interconnect/core.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/interconnect/core.c 2025-10-22 13:53:56.515169141 -0400 -@@ -20,7 +20,7 @@ - - #include "internal.h" - --#define ICC_DYN_ID_START 10000 -+#define ICC_DYN_ID_START 100000 - - #define CREATE_TRACE_POINTS - #include "trace.h" -@@ -819,6 +819,9 @@ static struct icc_node *icc_node_create_ - { - struct icc_node *node; - -+ if (id >= ICC_DYN_ID_START) -+ return ERR_PTR(-EINVAL); -+ - /* check if node already exists */ - node = node_find(id); - if (node) -@@ -906,11 +909,36 @@ void icc_node_destroy(int id) - return; - - kfree(node->links); -+ if (node->id >= ICC_DYN_ID_START) -+ kfree(node->name); - kfree(node); - } - EXPORT_SYMBOL_GPL(icc_node_destroy); - - /** -+ * icc_node_set_name() - set node name -+ * @node: node -+ * @provider: node provider -+ * @name: node name -+ * -+ * Return: 0 on success, or -ENOMEM on allocation failure -+ */ -+int icc_node_set_name(struct icc_node *node, const struct icc_provider *provider, const char *name) -+{ -+ if (node->id >= ICC_DYN_ID_START) { -+ node->name = kasprintf(GFP_KERNEL, "%s@%s", name, -+ dev_name(provider->dev)); -+ if (!node->name) -+ return -ENOMEM; -+ } else { -+ node->name = name; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(icc_node_set_name); -+ -+/** - * icc_link_nodes() - create link between two nodes - * @src_node: source node - * @dst_node: destination node -@@ -1038,10 +1066,6 @@ void icc_node_add(struct icc_node *node, - node->avg_bw = node->init_avg; - node->peak_bw = node->init_peak; - -- if (node->id >= ICC_DYN_ID_START) -- node->name = devm_kasprintf(provider->dev, GFP_KERNEL, "%s@%s", -- node->name, dev_name(provider->dev)); -- - if (node->avg_bw || node->peak_bw) { - if (provider->pre_aggregate) - provider->pre_aggregate(node); -diff -purNx .git BPI-Router-Linux-kernel/drivers/interconnect/icc-clk.c BPI-Router-Linux-kernel-6.16.12/drivers/interconnect/icc-clk.c ---- BPI-Router-Linux-kernel/drivers/interconnect/icc-clk.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/interconnect/icc-clk.c 2025-10-22 13:53:56.515169141 -0400 -@@ -117,6 +117,7 @@ struct icc_provider *icc_clk_register(st - - node->name = devm_kasprintf(dev, GFP_KERNEL, "%s_master", data[i].name); - if (!node->name) { -+ icc_node_destroy(node->id); - ret = -ENOMEM; - goto err; - } -@@ -135,6 +136,7 @@ struct icc_provider *icc_clk_register(st - - node->name = devm_kasprintf(dev, GFP_KERNEL, "%s_slave", data[i].name); - if (!node->name) { -+ icc_node_destroy(node->id); - ret = -ENOMEM; - goto err; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/interconnect/qcom/icc-rpmh.c BPI-Router-Linux-kernel-6.16.12/drivers/interconnect/qcom/icc-rpmh.c ---- BPI-Router-Linux-kernel/drivers/interconnect/qcom/icc-rpmh.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/interconnect/qcom/icc-rpmh.c 2025-10-22 13:53:56.515169141 -0400 -@@ -293,7 +293,12 @@ int qcom_icc_rpmh_probe(struct platform_ - goto err_remove_nodes; - } - -- node->name = qn->name; -+ ret = icc_node_set_name(node, provider, qn->name); -+ if (ret) { -+ icc_node_destroy(node->id); -+ goto err_remove_nodes; -+ } -+ - node->data = qn; - icc_node_add(node, provider); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/interconnect/qcom/osm-l3.c BPI-Router-Linux-kernel-6.16.12/drivers/interconnect/qcom/osm-l3.c ---- BPI-Router-Linux-kernel/drivers/interconnect/qcom/osm-l3.c 2025-10-22 13:53:23.279328818 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/interconnect/qcom/osm-l3.c 2025-10-22 13:53:56.515169141 -0400 -@@ -236,7 +236,12 @@ static int qcom_osm_l3_probe(struct plat - goto err; - } - -- node->name = qnodes[i]->name; -+ ret = icc_node_set_name(node, provider, qnodes[i]->name); -+ if (ret) { -+ icc_node_destroy(node->id); -+ goto err; -+ } -+ - /* Cast away const and add it back in qcom_osm_l3_set() */ - node->data = (void *)qnodes[i]; - icc_node_add(node, provider); -diff -purNx .git BPI-Router-Linux-kernel/drivers/interconnect/qcom/sc7280.c BPI-Router-Linux-kernel-6.16.12/drivers/interconnect/qcom/sc7280.c ---- BPI-Router-Linux-kernel/drivers/interconnect/qcom/sc7280.c 2025-10-22 13:53:23.283328800 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/interconnect/qcom/sc7280.c 2025-10-22 13:53:56.515169141 -0400 -@@ -238,6 +238,7 @@ static struct qcom_icc_node xm_pcie3_1 = - .id = SC7280_MASTER_PCIE_1, - .channels = 1, - .buswidth = 8, -+ .num_links = 1, - .links = { SC7280_SLAVE_ANOC_PCIE_GEM_NOC }, - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/interconnect/qcom/sc8180x.c BPI-Router-Linux-kernel-6.16.12/drivers/interconnect/qcom/sc8180x.c ---- BPI-Router-Linux-kernel/drivers/interconnect/qcom/sc8180x.c 2025-10-22 13:53:23.283328800 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/interconnect/qcom/sc8180x.c 2025-10-22 13:53:56.515169141 -0400 -@@ -1492,34 +1492,40 @@ static struct qcom_icc_bcm bcm_sh3 = { - - static struct qcom_icc_bcm bcm_sn0 = { - .name = "SN0", -+ .num_nodes = 1, - .nodes = { &slv_qns_gemnoc_sf } - }; - - static struct qcom_icc_bcm bcm_sn1 = { - .name = "SN1", -+ .num_nodes = 1, - .nodes = { &slv_qxs_imem } - }; - - static struct qcom_icc_bcm bcm_sn2 = { - .name = "SN2", - .keepalive = true, -+ .num_nodes = 1, - .nodes = { &slv_qns_gemnoc_gc } - }; - - static struct qcom_icc_bcm bcm_co2 = { - .name = "CO2", -+ .num_nodes = 1, - .nodes = { &mas_qnm_npu } - }; - - static struct qcom_icc_bcm bcm_sn3 = { - .name = "SN3", - .keepalive = true, -+ .num_nodes = 2, - .nodes = { &slv_srvc_aggre1_noc, - &slv_qns_cnoc } - }; - - static struct qcom_icc_bcm bcm_sn4 = { - .name = "SN4", -+ .num_nodes = 1, - .nodes = { &slv_qxs_pimem } - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/interconnect/qcom/sc8280xp.c BPI-Router-Linux-kernel-6.16.12/drivers/interconnect/qcom/sc8280xp.c ---- BPI-Router-Linux-kernel/drivers/interconnect/qcom/sc8280xp.c 2025-10-22 13:53:23.283328800 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/interconnect/qcom/sc8280xp.c 2025-10-22 13:53:56.515169141 -0400 -@@ -48,6 +48,7 @@ static struct qcom_icc_node qnm_a1noc_cf - .id = SC8280XP_MASTER_A1NOC_CFG, - .channels = 1, - .buswidth = 4, -+ .num_links = 1, - .links = { SC8280XP_SLAVE_SERVICE_A1NOC }, - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/interconnect/samsung/exynos.c BPI-Router-Linux-kernel-6.16.12/drivers/interconnect/samsung/exynos.c ---- BPI-Router-Linux-kernel/drivers/interconnect/samsung/exynos.c 2025-10-22 13:53:23.283328800 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/interconnect/samsung/exynos.c 2025-10-22 13:53:56.515169141 -0400 -@@ -134,6 +134,11 @@ static int exynos_generic_icc_probe(stru - priv->node = icc_node; - icc_node->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%pOFn", - bus_dev->of_node); -+ if (!icc_node->name) { -+ icc_node_destroy(pdev->id); -+ return -ENOMEM; -+ } -+ - if (of_property_read_u32(bus_dev->of_node, "samsung,data-clock-ratio", - &priv->bus_clk_ratio)) - priv->bus_clk_ratio = EXYNOS_ICC_DEFAULT_BUS_CLK_RATIO; -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/amd/amd_iommu_types.h BPI-Router-Linux-kernel-6.16.12/drivers/iommu/amd/amd_iommu_types.h ---- BPI-Router-Linux-kernel/drivers/iommu/amd/amd_iommu_types.h 2025-10-22 13:53:23.283328800 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/amd/amd_iommu_types.h 2025-10-22 13:53:56.515169141 -0400 -@@ -551,6 +551,7 @@ struct gcr3_tbl_info { - }; - - struct amd_io_pgtable { -+ seqcount_t seqcount; /* Protects root/mode update */ - struct io_pgtable pgtbl; - int mode; - u64 *root; -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/amd/init.c BPI-Router-Linux-kernel-6.16.12/drivers/iommu/amd/init.c ---- BPI-Router-Linux-kernel/drivers/iommu/amd/init.c 2025-10-22 13:53:23.283328800 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/amd/init.c 2025-10-22 13:53:56.515169141 -0400 -@@ -1450,12 +1450,12 @@ static int __init init_iommu_from_acpi(s - PCI_FUNC(e->devid)); - - devid = e->devid; -- for (dev_i = devid_start; dev_i <= devid; ++dev_i) { -- if (alias) -+ if (alias) { -+ for (dev_i = devid_start; dev_i <= devid; ++dev_i) - pci_seg->alias_table[dev_i] = devid_to; -+ set_dev_entry_from_acpi(iommu, devid_to, flags, ext_flags); - } - set_dev_entry_from_acpi_range(iommu, devid_start, devid, flags, ext_flags); -- set_dev_entry_from_acpi(iommu, devid_to, flags, ext_flags); - break; - case IVHD_DEV_SPECIAL: { - u8 handle, type; -@@ -3048,7 +3048,8 @@ static int __init early_amd_iommu_init(v - - if (!boot_cpu_has(X86_FEATURE_CX16)) { - pr_err("Failed to initialize. The CMPXCHG16B feature is required.\n"); -- return -EINVAL; -+ ret = -EINVAL; -+ goto out; - } - - /* -@@ -3596,7 +3597,7 @@ static int __init parse_ivrs_acpihid(cha - { - u32 seg = 0, bus, dev, fn; - char *hid, *uid, *p, *addr; -- char acpiid[ACPIID_LEN] = {0}; -+ char acpiid[ACPIID_LEN + 1] = { }; /* size with NULL terminator */ - int i; - - addr = strchr(str, '@'); -@@ -3622,7 +3623,7 @@ static int __init parse_ivrs_acpihid(cha - /* We have the '@', make it the terminator to get just the acpiid */ - *addr++ = 0; - -- if (strlen(str) > ACPIID_LEN + 1) -+ if (strlen(str) > ACPIID_LEN) - goto not_found; - - if (sscanf(str, "=%s", acpiid) != 1) -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/amd/iommu.c BPI-Router-Linux-kernel-6.16.12/drivers/iommu/amd/iommu.c ---- BPI-Router-Linux-kernel/drivers/iommu/amd/iommu.c 2025-10-22 13:53:23.283328800 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/amd/iommu.c 2025-10-22 13:53:56.515169141 -0400 -@@ -634,8 +634,8 @@ static inline void pdev_disable_cap_pasi - - static void pdev_enable_caps(struct pci_dev *pdev) - { -- pdev_enable_cap_ats(pdev); - pdev_enable_cap_pasid(pdev); -+ pdev_enable_cap_ats(pdev); - pdev_enable_cap_pri(pdev); - } - -@@ -2526,8 +2526,21 @@ static inline u64 dma_max_address(enum p - if (pgtable == PD_MODE_V1) - return ~0ULL; - -- /* V2 with 4/5 level page table */ -- return ((1ULL << PM_LEVEL_SHIFT(amd_iommu_gpt_level)) - 1); -+ /* -+ * V2 with 4/5 level page table. Note that "2.2.6.5 AMD64 4-Kbyte Page -+ * Translation" shows that the V2 table sign extends the top of the -+ * address space creating a reserved region in the middle of the -+ * translation, just like the CPU does. Further Vasant says the docs are -+ * incomplete and this only applies to non-zero PASIDs. If the AMDv2 -+ * page table is assigned to the 0 PASID then there is no sign extension -+ * check. -+ * -+ * Since the IOMMU must have a fixed geometry, and the core code does -+ * not understand sign extended addressing, we have to chop off the high -+ * bit to get consistent behavior with attachments of the domain to any -+ * PASID. -+ */ -+ return ((1ULL << (PM_LEVEL_SHIFT(amd_iommu_gpt_level) - 1)) - 1); - } - - static bool amd_iommu_hd_support(struct amd_iommu *iommu) -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/amd/io_pgtable.c BPI-Router-Linux-kernel-6.16.12/drivers/iommu/amd/io_pgtable.c ---- BPI-Router-Linux-kernel/drivers/iommu/amd/io_pgtable.c 2025-10-22 13:53:23.283328800 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/amd/io_pgtable.c 2025-10-22 13:53:56.515169141 -0400 -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - - #include - -@@ -130,8 +131,11 @@ static bool increase_address_space(struc - - *pte = PM_LEVEL_PDE(pgtable->mode, iommu_virt_to_phys(pgtable->root)); - -+ write_seqcount_begin(&pgtable->seqcount); - pgtable->root = pte; - pgtable->mode += 1; -+ write_seqcount_end(&pgtable->seqcount); -+ - amd_iommu_update_and_flush_device_table(domain); - - pte = NULL; -@@ -153,6 +157,7 @@ static u64 *alloc_pte(struct amd_io_pgta - { - unsigned long last_addr = address + (page_size - 1); - struct io_pgtable_cfg *cfg = &pgtable->pgtbl.cfg; -+ unsigned int seqcount; - int level, end_lvl; - u64 *pte, *page; - -@@ -170,8 +175,14 @@ static u64 *alloc_pte(struct amd_io_pgta - } - - -- level = pgtable->mode - 1; -- pte = &pgtable->root[PM_LEVEL_INDEX(level, address)]; -+ do { -+ seqcount = read_seqcount_begin(&pgtable->seqcount); -+ -+ level = pgtable->mode - 1; -+ pte = &pgtable->root[PM_LEVEL_INDEX(level, address)]; -+ } while (read_seqcount_retry(&pgtable->seqcount, seqcount)); -+ -+ - address = PAGE_SIZE_ALIGN(address, page_size); - end_lvl = PAGE_SIZE_LEVEL(page_size); - -@@ -249,6 +260,7 @@ static u64 *fetch_pte(struct amd_io_pgta - unsigned long *page_size) - { - int level; -+ unsigned int seqcount; - u64 *pte; - - *page_size = 0; -@@ -256,8 +268,12 @@ static u64 *fetch_pte(struct amd_io_pgta - if (address > PM_LEVEL_SIZE(pgtable->mode)) - return NULL; - -- level = pgtable->mode - 1; -- pte = &pgtable->root[PM_LEVEL_INDEX(level, address)]; -+ do { -+ seqcount = read_seqcount_begin(&pgtable->seqcount); -+ level = pgtable->mode - 1; -+ pte = &pgtable->root[PM_LEVEL_INDEX(level, address)]; -+ } while (read_seqcount_retry(&pgtable->seqcount, seqcount)); -+ - *page_size = PTE_LEVEL_PAGE_SIZE(level); - - while (level > 0) { -@@ -541,6 +557,7 @@ static struct io_pgtable *v1_alloc_pgtab - if (!pgtable->root) - return NULL; - pgtable->mode = PAGE_MODE_3_LEVEL; -+ seqcount_init(&pgtable->seqcount); - - cfg->pgsize_bitmap = amd_iommu_pgsize_bitmap; - cfg->ias = IOMMU_IN_ADDR_BIT_SIZE; -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/apple-dart.c BPI-Router-Linux-kernel-6.16.12/drivers/iommu/apple-dart.c ---- BPI-Router-Linux-kernel/drivers/iommu/apple-dart.c 2025-10-22 13:53:23.283328800 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/apple-dart.c 2025-10-22 13:53:56.515169141 -0400 -@@ -991,7 +991,6 @@ static const struct iommu_ops apple_dart - .of_xlate = apple_dart_of_xlate, - .def_domain_type = apple_dart_def_domain_type, - .get_resv_regions = apple_dart_get_resv_regions, -- .pgsize_bitmap = -1UL, /* Restricted during dart probe */ - .owner = THIS_MODULE, - .default_domain_ops = &(const struct iommu_domain_ops) { - .attach_dev = apple_dart_attach_dev_paging, -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c BPI-Router-Linux-kernel-6.16.12/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c ---- BPI-Router-Linux-kernel/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c 2025-10-22 13:53:23.283328800 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c 2025-10-22 13:53:56.515169141 -0400 -@@ -355,7 +355,8 @@ static int qcom_adreno_smmu_init_context - priv->set_prr_addr = NULL; - - if (of_device_is_compatible(np, "qcom,smmu-500") && -- of_device_is_compatible(np, "qcom,adreno-smmu")) { -+ !of_device_is_compatible(np, "qcom,sm8250-smmu-500") && -+ of_device_is_compatible(np, "qcom,adreno-smmu")) { - priv->set_prr_bit = qcom_adreno_smmu_set_prr_bit; - priv->set_prr_addr = qcom_adreno_smmu_set_prr_addr; - } -@@ -379,6 +380,7 @@ static const struct of_device_id qcom_sm - { .compatible = "qcom,sdm670-mdss" }, - { .compatible = "qcom,sdm845-mdss" }, - { .compatible = "qcom,sdm845-mss-pil" }, -+ { .compatible = "qcom,sm6115-mdss" }, - { .compatible = "qcom,sm6350-mdss" }, - { .compatible = "qcom,sm6375-mdss" }, - { .compatible = "qcom,sm8150-mdss" }, -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c BPI-Router-Linux-kernel-6.16.12/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c ---- BPI-Router-Linux-kernel/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 2025-10-22 13:53:23.283328800 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c 2025-10-22 13:53:56.515169141 -0400 -@@ -2906,8 +2906,8 @@ int arm_smmu_attach_prepare(struct arm_s - - master_domain = kzalloc(sizeof(*master_domain), GFP_KERNEL); - if (!master_domain) { -- kfree(state->vmaster); -- return -ENOMEM; -+ ret = -ENOMEM; -+ goto err_free_vmaster; - } - master_domain->domain = new_domain; - master_domain->master = master; -@@ -2941,7 +2941,6 @@ int arm_smmu_attach_prepare(struct arm_s - !arm_smmu_master_canwbs(master)) { - spin_unlock_irqrestore(&smmu_domain->devices_lock, - flags); -- kfree(state->vmaster); - ret = -EINVAL; - goto err_iopf; - } -@@ -2967,6 +2966,8 @@ err_iopf: - arm_smmu_disable_iopf(master, master_domain); - err_free_master_domain: - kfree(master_domain); -+err_free_vmaster: -+ kfree(state->vmaster); - return ret; - } - -@@ -2996,9 +2997,9 @@ void arm_smmu_attach_commit(struct arm_s - /* ATS is being switched off, invalidate the entire ATC */ - arm_smmu_atc_inv_master(master, IOMMU_NO_PASID); - } -- master->ats_enabled = state->ats_enabled; - - arm_smmu_remove_master_domain(master, state->old_domain, state->ssid); -+ master->ats_enabled = state->ats_enabled; - } - - static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/hyperv-iommu.c BPI-Router-Linux-kernel-6.16.12/drivers/iommu/hyperv-iommu.c ---- BPI-Router-Linux-kernel/drivers/iommu/hyperv-iommu.c 2025-10-22 13:53:23.283328800 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/hyperv-iommu.c 2025-10-22 13:53:56.515169141 -0400 -@@ -193,15 +193,13 @@ struct hyperv_root_ir_data { - static void - hyperv_root_ir_compose_msi_msg(struct irq_data *irq_data, struct msi_msg *msg) - { -- u64 status; -- u32 vector; -- struct irq_cfg *cfg; -- int ioapic_id; -- const struct cpumask *affinity; -- int cpu; -- struct hv_interrupt_entry entry; - struct hyperv_root_ir_data *data = irq_data->chip_data; -+ struct hv_interrupt_entry entry; -+ const struct cpumask *affinity; - struct IO_APIC_route_entry e; -+ struct irq_cfg *cfg; -+ int cpu, ioapic_id; -+ u32 vector; - - cfg = irqd_cfg(irq_data); - affinity = irq_data_get_effective_affinity_mask(irq_data); -@@ -214,23 +212,16 @@ hyperv_root_ir_compose_msi_msg(struct ir - && data->entry.ioapic_rte.as_uint64) { - entry = data->entry; - -- status = hv_unmap_ioapic_interrupt(ioapic_id, &entry); -- -- if (status != HV_STATUS_SUCCESS) -- hv_status_debug(status, "failed to unmap\n"); -+ (void)hv_unmap_ioapic_interrupt(ioapic_id, &entry); - - data->entry.ioapic_rte.as_uint64 = 0; - data->entry.source = 0; /* Invalid source */ - } - - -- status = hv_map_ioapic_interrupt(ioapic_id, data->is_level, cpu, -- vector, &entry); -- -- if (status != HV_STATUS_SUCCESS) { -- hv_status_err(status, "map failed\n"); -+ if (hv_map_ioapic_interrupt(ioapic_id, data->is_level, cpu, -+ vector, &entry)) - return; -- } - - data->entry = entry; - -@@ -322,10 +313,10 @@ static void hyperv_root_irq_remapping_fr - data = irq_data->chip_data; - e = &data->entry; - -- if (e->source == HV_DEVICE_TYPE_IOAPIC -- && e->ioapic_rte.as_uint64) -- hv_unmap_ioapic_interrupt(data->ioapic_id, -- &data->entry); -+ if (e->source == HV_DEVICE_TYPE_IOAPIC && -+ e->ioapic_rte.as_uint64) -+ (void)hv_unmap_ioapic_interrupt(data->ioapic_id, -+ &data->entry); - - kfree(data); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/intel/cache.c BPI-Router-Linux-kernel-6.16.12/drivers/iommu/intel/cache.c ---- BPI-Router-Linux-kernel/drivers/iommu/intel/cache.c 2025-10-22 13:53:23.283328800 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/intel/cache.c 2025-10-22 13:53:56.515169141 -0400 -@@ -40,9 +40,8 @@ static bool cache_tage_match(struct cach - } - - /* Assign a cache tag with specified type to domain. */ --static int cache_tag_assign(struct dmar_domain *domain, u16 did, -- struct device *dev, ioasid_t pasid, -- enum cache_tag_type type) -+int cache_tag_assign(struct dmar_domain *domain, u16 did, struct device *dev, -+ ioasid_t pasid, enum cache_tag_type type) - { - struct device_domain_info *info = dev_iommu_priv_get(dev); - struct intel_iommu *iommu = info->iommu; -@@ -371,7 +370,7 @@ static void cache_tag_flush_iotlb(struct - struct intel_iommu *iommu = tag->iommu; - u64 type = DMA_TLB_PSI_FLUSH; - -- if (domain->use_first_level) { -+ if (intel_domain_is_fs_paging(domain)) { - qi_batch_add_piotlb(iommu, tag->domain_id, tag->pasid, addr, - pages, ih, domain->qi_batch); - return; -@@ -423,22 +422,6 @@ static void cache_tag_flush_devtlb_psi(s - domain->qi_batch); - } - --static void cache_tag_flush_devtlb_all(struct dmar_domain *domain, struct cache_tag *tag) --{ -- struct intel_iommu *iommu = tag->iommu; -- struct device_domain_info *info; -- u16 sid; -- -- info = dev_iommu_priv_get(tag->dev); -- sid = PCI_DEVID(info->bus, info->devfn); -- -- qi_batch_add_dev_iotlb(iommu, sid, info->pfsid, info->ats_qdep, 0, -- MAX_AGAW_PFN_WIDTH, domain->qi_batch); -- if (info->dtlb_extra_inval) -- qi_batch_add_dev_iotlb(iommu, sid, info->pfsid, info->ats_qdep, 0, -- MAX_AGAW_PFN_WIDTH, domain->qi_batch); --} -- - /* - * Invalidates a range of IOVA from @start (inclusive) to @end (inclusive) - * when the memory mappings in the target domain have been modified. -@@ -509,7 +492,7 @@ void cache_tag_flush_all(struct dmar_dom - break; - case CACHE_TAG_DEVTLB: - case CACHE_TAG_NESTING_DEVTLB: -- cache_tag_flush_devtlb_all(domain, tag); -+ cache_tag_flush_devtlb_psi(domain, tag, 0, MAX_AGAW_PFN_WIDTH); - break; - } - -@@ -546,7 +529,8 @@ void cache_tag_flush_range_np(struct dma - qi_batch_flush_descs(iommu, domain->qi_batch); - iommu = tag->iommu; - -- if (!cap_caching_mode(iommu->cap) || domain->use_first_level) { -+ if (!cap_caching_mode(iommu->cap) || -+ intel_domain_is_fs_paging(domain)) { - iommu_flush_write_buffer(iommu); - continue; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/intel/iommu.c BPI-Router-Linux-kernel-6.16.12/drivers/iommu/intel/iommu.c ---- BPI-Router-Linux-kernel/drivers/iommu/intel/iommu.c 2025-10-22 13:53:23.283328800 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/intel/iommu.c 2025-10-22 13:53:56.515169141 -0400 -@@ -57,6 +57,8 @@ - static void __init check_tylersburg_isoch(void); - static int rwbf_quirk; - -+#define rwbf_required(iommu) (rwbf_quirk || cap_rwbf((iommu)->cap)) -+ - /* - * set to 1 to panic kernel if can't successfully enable VT-d - * (used when kernel is launched w/ TXT) -@@ -1391,7 +1393,6 @@ void domain_detach_iommu(struct dmar_dom - if (--info->refcnt == 0) { - ida_free(&iommu->domain_ida, info->did); - xa_erase(&domain->iommu_array, iommu->seq_id); -- domain->nid = NUMA_NO_NODE; - kfree(info); - } - } -@@ -1480,6 +1481,9 @@ static int domain_context_mapping_one(st - struct context_entry *context; - int ret; - -+ if (WARN_ON(!intel_domain_is_ss_paging(domain))) -+ return -EINVAL; -+ - pr_debug("Set context mapping for %02x:%02x.%d\n", - bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); - -@@ -1588,6 +1592,10 @@ static void switch_to_super_page(struct - unsigned long lvl_pages = lvl_to_nr_pages(level); - struct dma_pte *pte = NULL; - -+ if (WARN_ON(!IS_ALIGNED(start_pfn, lvl_pages) || -+ !IS_ALIGNED(end_pfn + 1, lvl_pages))) -+ return; -+ - while (start_pfn <= end_pfn) { - if (!pte) - pte = pfn_to_dma_pte(domain, start_pfn, &level, -@@ -1663,7 +1671,8 @@ __domain_mapping(struct dmar_domain *dom - unsigned long pages_to_remove; - - pteval |= DMA_PTE_LARGE_PAGE; -- pages_to_remove = min_t(unsigned long, nr_pages, -+ pages_to_remove = min_t(unsigned long, -+ round_down(nr_pages, lvl_pages), - nr_pte_to_next_page(pte) * lvl_pages); - end_pfn = iov_pfn + pages_to_remove - 1; - switch_to_super_page(domain, iov_pfn, end_pfn, largepage_lvl); -@@ -1819,12 +1828,14 @@ static int dmar_domain_attach_device(str - - if (!sm_supported(iommu)) - ret = domain_context_mapping(domain, dev); -- else if (domain->use_first_level) -+ else if (intel_domain_is_fs_paging(domain)) - ret = domain_setup_first_level(iommu, domain, dev, - IOMMU_NO_PASID, NULL); -- else -+ else if (intel_domain_is_ss_paging(domain)) - ret = domain_setup_second_level(iommu, domain, dev, - IOMMU_NO_PASID, NULL); -+ else if (WARN_ON(true)) -+ ret = -EINVAL; - - if (ret) - goto out_block_translation; -@@ -3286,10 +3297,14 @@ static struct dmar_domain *paging_domain - spin_lock_init(&domain->lock); - spin_lock_init(&domain->cache_lock); - xa_init(&domain->iommu_array); -+ INIT_LIST_HEAD(&domain->s1_domains); -+ spin_lock_init(&domain->s1_lock); - - domain->nid = dev_to_node(dev); - domain->use_first_level = first_stage; - -+ domain->domain.type = IOMMU_DOMAIN_UNMANAGED; -+ - /* calculate the address width */ - addr_width = agaw_to_width(iommu->agaw); - if (addr_width > cap_mgaw(iommu->cap)) -@@ -3331,62 +3346,92 @@ static struct dmar_domain *paging_domain - } - - static struct iommu_domain * --intel_iommu_domain_alloc_paging_flags(struct device *dev, u32 flags, -- const struct iommu_user_data *user_data) -+intel_iommu_domain_alloc_first_stage(struct device *dev, -+ struct intel_iommu *iommu, u32 flags) -+{ -+ struct dmar_domain *dmar_domain; -+ -+ if (flags & ~IOMMU_HWPT_ALLOC_PASID) -+ return ERR_PTR(-EOPNOTSUPP); -+ -+ /* Only SL is available in legacy mode */ -+ if (!sm_supported(iommu) || !ecap_flts(iommu->ecap)) -+ return ERR_PTR(-EOPNOTSUPP); -+ -+ dmar_domain = paging_domain_alloc(dev, true); -+ if (IS_ERR(dmar_domain)) -+ return ERR_CAST(dmar_domain); -+ -+ dmar_domain->domain.ops = &intel_fs_paging_domain_ops; -+ /* -+ * iotlb sync for map is only needed for legacy implementations that -+ * explicitly require flushing internal write buffers to ensure memory -+ * coherence. -+ */ -+ if (rwbf_required(iommu)) -+ dmar_domain->iotlb_sync_map = true; -+ -+ return &dmar_domain->domain; -+} -+ -+static struct iommu_domain * -+intel_iommu_domain_alloc_second_stage(struct device *dev, -+ struct intel_iommu *iommu, u32 flags) - { -- struct device_domain_info *info = dev_iommu_priv_get(dev); -- bool dirty_tracking = flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING; -- bool nested_parent = flags & IOMMU_HWPT_ALLOC_NEST_PARENT; -- struct intel_iommu *iommu = info->iommu; - struct dmar_domain *dmar_domain; -- struct iommu_domain *domain; -- bool first_stage; - - if (flags & - (~(IOMMU_HWPT_ALLOC_NEST_PARENT | IOMMU_HWPT_ALLOC_DIRTY_TRACKING | - IOMMU_HWPT_ALLOC_PASID))) - return ERR_PTR(-EOPNOTSUPP); -- if (nested_parent && !nested_supported(iommu)) -+ -+ if (((flags & IOMMU_HWPT_ALLOC_NEST_PARENT) && -+ !nested_supported(iommu)) || -+ ((flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING) && -+ !ssads_supported(iommu))) - return ERR_PTR(-EOPNOTSUPP); -- if (user_data || (dirty_tracking && !ssads_supported(iommu))) -+ -+ /* Legacy mode always supports second stage */ -+ if (sm_supported(iommu) && !ecap_slts(iommu->ecap)) - return ERR_PTR(-EOPNOTSUPP); - -+ dmar_domain = paging_domain_alloc(dev, false); -+ if (IS_ERR(dmar_domain)) -+ return ERR_CAST(dmar_domain); -+ -+ dmar_domain->domain.ops = &intel_ss_paging_domain_ops; -+ dmar_domain->nested_parent = flags & IOMMU_HWPT_ALLOC_NEST_PARENT; -+ -+ if (flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING) -+ dmar_domain->domain.dirty_ops = &intel_dirty_ops; -+ - /* -- * Always allocate the guest compatible page table unless -- * IOMMU_HWPT_ALLOC_NEST_PARENT or IOMMU_HWPT_ALLOC_DIRTY_TRACKING -- * is specified. -+ * Besides the internal write buffer flush, the caching mode used for -+ * legacy nested translation (which utilizes shadowing page tables) -+ * also requires iotlb sync on map. - */ -- if (nested_parent || dirty_tracking) { -- if (!sm_supported(iommu) || !ecap_slts(iommu->ecap)) -- return ERR_PTR(-EOPNOTSUPP); -- first_stage = false; -- } else { -- first_stage = first_level_by_default(iommu); -- } -+ if (rwbf_required(iommu) || cap_caching_mode(iommu->cap)) -+ dmar_domain->iotlb_sync_map = true; - -- dmar_domain = paging_domain_alloc(dev, first_stage); -- if (IS_ERR(dmar_domain)) -- return ERR_CAST(dmar_domain); -- domain = &dmar_domain->domain; -- domain->type = IOMMU_DOMAIN_UNMANAGED; -- domain->owner = &intel_iommu_ops; -- domain->ops = intel_iommu_ops.default_domain_ops; -- -- if (nested_parent) { -- dmar_domain->nested_parent = true; -- INIT_LIST_HEAD(&dmar_domain->s1_domains); -- spin_lock_init(&dmar_domain->s1_lock); -- } -- -- if (dirty_tracking) { -- if (dmar_domain->use_first_level) { -- iommu_domain_free(domain); -- return ERR_PTR(-EOPNOTSUPP); -- } -- domain->dirty_ops = &intel_dirty_ops; -- } -+ return &dmar_domain->domain; -+} - -- return domain; -+static struct iommu_domain * -+intel_iommu_domain_alloc_paging_flags(struct device *dev, u32 flags, -+ const struct iommu_user_data *user_data) -+{ -+ struct device_domain_info *info = dev_iommu_priv_get(dev); -+ struct intel_iommu *iommu = info->iommu; -+ struct iommu_domain *domain; -+ -+ if (user_data) -+ return ERR_PTR(-EOPNOTSUPP); -+ -+ /* Prefer first stage if possible by default. */ -+ domain = intel_iommu_domain_alloc_first_stage(dev, iommu, flags); -+ if (domain != ERR_PTR(-EOPNOTSUPP)) -+ return domain; -+ return intel_iommu_domain_alloc_second_stage(dev, iommu, flags); - } - - static void intel_iommu_domain_free(struct iommu_domain *domain) -@@ -3398,33 +3443,86 @@ static void intel_iommu_domain_free(stru - domain_exit(dmar_domain); - } - -+static int paging_domain_compatible_first_stage(struct dmar_domain *dmar_domain, -+ struct intel_iommu *iommu) -+{ -+ if (WARN_ON(dmar_domain->domain.dirty_ops || -+ dmar_domain->nested_parent)) -+ return -EINVAL; -+ -+ /* Only SL is available in legacy mode */ -+ if (!sm_supported(iommu) || !ecap_flts(iommu->ecap)) -+ return -EINVAL; -+ -+ /* Same page size support */ -+ if (!cap_fl1gp_support(iommu->cap) && -+ (dmar_domain->domain.pgsize_bitmap & SZ_1G)) -+ return -EINVAL; -+ -+ /* iotlb sync on map requirement */ -+ if ((rwbf_required(iommu)) && !dmar_domain->iotlb_sync_map) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static int -+paging_domain_compatible_second_stage(struct dmar_domain *dmar_domain, -+ struct intel_iommu *iommu) -+{ -+ unsigned int sslps = cap_super_page_val(iommu->cap); -+ -+ if (dmar_domain->domain.dirty_ops && !ssads_supported(iommu)) -+ return -EINVAL; -+ if (dmar_domain->nested_parent && !nested_supported(iommu)) -+ return -EINVAL; -+ -+ /* Legacy mode always supports second stage */ -+ if (sm_supported(iommu) && !ecap_slts(iommu->ecap)) -+ return -EINVAL; -+ -+ /* Same page size support */ -+ if (!(sslps & BIT(0)) && (dmar_domain->domain.pgsize_bitmap & SZ_2M)) -+ return -EINVAL; -+ if (!(sslps & BIT(1)) && (dmar_domain->domain.pgsize_bitmap & SZ_1G)) -+ return -EINVAL; -+ -+ /* iotlb sync on map requirement */ -+ if ((rwbf_required(iommu) || cap_caching_mode(iommu->cap)) && -+ !dmar_domain->iotlb_sync_map) -+ return -EINVAL; -+ -+ return 0; -+} -+ - int paging_domain_compatible(struct iommu_domain *domain, struct device *dev) - { - struct device_domain_info *info = dev_iommu_priv_get(dev); - struct dmar_domain *dmar_domain = to_dmar_domain(domain); - struct intel_iommu *iommu = info->iommu; -+ int ret = -EINVAL; - int addr_width; - -- if (WARN_ON_ONCE(!(domain->type & __IOMMU_DOMAIN_PAGING))) -- return -EPERM; -+ if (intel_domain_is_fs_paging(dmar_domain)) -+ ret = paging_domain_compatible_first_stage(dmar_domain, iommu); -+ else if (intel_domain_is_ss_paging(dmar_domain)) -+ ret = paging_domain_compatible_second_stage(dmar_domain, iommu); -+ else if (WARN_ON(true)) -+ ret = -EINVAL; -+ if (ret) -+ return ret; - -+ /* -+ * FIXME this is locked wrong, it needs to be under the -+ * dmar_domain->lock -+ */ - if (dmar_domain->force_snooping && !ecap_sc_support(iommu->ecap)) - return -EINVAL; - -- if (domain->dirty_ops && !ssads_supported(iommu)) -- return -EINVAL; -- - if (dmar_domain->iommu_coherency != - iommu_paging_structure_coherency(iommu)) - return -EINVAL; - -- if (dmar_domain->iommu_superpage != -- iommu_superpage_capability(iommu, dmar_domain->use_first_level)) -- return -EINVAL; -- -- if (dmar_domain->use_first_level && -- (!sm_supported(iommu) || !ecap_flts(iommu->ecap))) -- return -EINVAL; - - /* check if this iommu agaw is sufficient for max mapped address */ - addr_width = agaw_to_width(iommu->agaw); -@@ -3780,8 +3878,17 @@ static void intel_iommu_probe_finalize(s - !pci_enable_pasid(to_pci_dev(dev), info->pasid_supported & ~1)) - info->pasid_enabled = 1; - -- if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev)) -+ if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev)) { - iommu_enable_pci_ats(info); -+ /* Assign a DEVTLB cache tag to the default domain. */ -+ if (info->ats_enabled && info->domain) { -+ u16 did = domain_id_iommu(info->domain, iommu); -+ -+ if (cache_tag_assign(info->domain, did, dev, -+ IOMMU_NO_PASID, CACHE_TAG_DEVTLB)) -+ iommu_disable_pci_ats(info); -+ } -+ } - iommu_enable_pci_pri(info); - } - -@@ -3945,7 +4052,10 @@ static bool risky_device(struct pci_dev - static int intel_iommu_iotlb_sync_map(struct iommu_domain *domain, - unsigned long iova, size_t size) - { -- cache_tag_flush_range_np(to_dmar_domain(domain), iova, iova + size - 1); -+ struct dmar_domain *dmar_domain = to_dmar_domain(domain); -+ -+ if (dmar_domain->iotlb_sync_map) -+ cache_tag_flush_range_np(dmar_domain, iova, iova + size - 1); - - return 0; - } -@@ -3991,8 +4101,8 @@ static int blocking_domain_set_dev_pasid - { - struct device_domain_info *info = dev_iommu_priv_get(dev); - -- iopf_for_domain_remove(old, dev); - intel_pasid_tear_down_entry(info->iommu, dev, pasid, false); -+ iopf_for_domain_remove(old, dev); - domain_remove_dev_pasid(old, dev, pasid); - - return 0; -@@ -4069,12 +4179,15 @@ static int intel_iommu_set_dev_pasid(str - if (ret) - goto out_remove_dev_pasid; - -- if (dmar_domain->use_first_level) -+ if (intel_domain_is_fs_paging(dmar_domain)) - ret = domain_setup_first_level(iommu, dmar_domain, - dev, pasid, old); -- else -+ else if (intel_domain_is_ss_paging(dmar_domain)) - ret = domain_setup_second_level(iommu, dmar_domain, - dev, pasid, old); -+ else if (WARN_ON(true)) -+ ret = -EINVAL; -+ - if (ret) - goto out_unwind_iopf; - -@@ -4349,6 +4462,32 @@ static struct iommu_domain identity_doma - }, - }; - -+const struct iommu_domain_ops intel_fs_paging_domain_ops = { -+ .attach_dev = intel_iommu_attach_device, -+ .set_dev_pasid = intel_iommu_set_dev_pasid, -+ .map_pages = intel_iommu_map_pages, -+ .unmap_pages = intel_iommu_unmap_pages, -+ .iotlb_sync_map = intel_iommu_iotlb_sync_map, -+ .flush_iotlb_all = intel_flush_iotlb_all, -+ .iotlb_sync = intel_iommu_tlb_sync, -+ .iova_to_phys = intel_iommu_iova_to_phys, -+ .free = intel_iommu_domain_free, -+ .enforce_cache_coherency = intel_iommu_enforce_cache_coherency, -+}; -+ -+const struct iommu_domain_ops intel_ss_paging_domain_ops = { -+ .attach_dev = intel_iommu_attach_device, -+ .set_dev_pasid = intel_iommu_set_dev_pasid, -+ .map_pages = intel_iommu_map_pages, -+ .unmap_pages = intel_iommu_unmap_pages, -+ .iotlb_sync_map = intel_iommu_iotlb_sync_map, -+ .flush_iotlb_all = intel_flush_iotlb_all, -+ .iotlb_sync = intel_iommu_tlb_sync, -+ .iova_to_phys = intel_iommu_iova_to_phys, -+ .free = intel_iommu_domain_free, -+ .enforce_cache_coherency = intel_iommu_enforce_cache_coherency, -+}; -+ - const struct iommu_ops intel_iommu_ops = { - .blocked_domain = &blocking_domain, - .release_domain = &blocking_domain, -@@ -4365,20 +4504,7 @@ const struct iommu_ops intel_iommu_ops = - .device_group = intel_iommu_device_group, - .is_attach_deferred = intel_iommu_is_attach_deferred, - .def_domain_type = device_def_domain_type, -- .pgsize_bitmap = SZ_4K, - .page_response = intel_iommu_page_response, -- .default_domain_ops = &(const struct iommu_domain_ops) { -- .attach_dev = intel_iommu_attach_device, -- .set_dev_pasid = intel_iommu_set_dev_pasid, -- .map_pages = intel_iommu_map_pages, -- .unmap_pages = intel_iommu_unmap_pages, -- .iotlb_sync_map = intel_iommu_iotlb_sync_map, -- .flush_iotlb_all = intel_flush_iotlb_all, -- .iotlb_sync = intel_iommu_tlb_sync, -- .iova_to_phys = intel_iommu_iova_to_phys, -- .free = intel_iommu_domain_free, -- .enforce_cache_coherency = intel_iommu_enforce_cache_coherency, -- } - }; - - static void quirk_iommu_igfx(struct pci_dev *dev) -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/intel/iommu.h BPI-Router-Linux-kernel-6.16.12/drivers/iommu/intel/iommu.h ---- BPI-Router-Linux-kernel/drivers/iommu/intel/iommu.h 2025-10-22 13:53:23.283328800 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/intel/iommu.h 2025-10-22 13:53:56.515169141 -0400 -@@ -614,6 +614,9 @@ struct dmar_domain { - u8 has_mappings:1; /* Has mappings configured through - * iommu_map() interface. - */ -+ u8 iotlb_sync_map:1; /* Need to flush IOTLB cache or write -+ * buffer when creating mappings. -+ */ - - spinlock_t lock; /* Protect device tracking lists */ - struct list_head devices; /* all devices' list */ -@@ -1289,6 +1292,8 @@ struct cache_tag { - unsigned int users; - }; - -+int cache_tag_assign(struct dmar_domain *domain, u16 did, struct device *dev, -+ ioasid_t pasid, enum cache_tag_type type); - int cache_tag_assign_domain(struct dmar_domain *domain, - struct device *dev, ioasid_t pasid); - void cache_tag_unassign_domain(struct dmar_domain *domain, -@@ -1376,6 +1381,18 @@ struct context_entry *iommu_context_addr - u8 devfn, int alloc); - - extern const struct iommu_ops intel_iommu_ops; -+extern const struct iommu_domain_ops intel_fs_paging_domain_ops; -+extern const struct iommu_domain_ops intel_ss_paging_domain_ops; -+ -+static inline bool intel_domain_is_fs_paging(struct dmar_domain *domain) -+{ -+ return domain->domain.ops == &intel_fs_paging_domain_ops; -+} -+ -+static inline bool intel_domain_is_ss_paging(struct dmar_domain *domain) -+{ -+ return domain->domain.ops == &intel_ss_paging_domain_ops; -+} - - #ifdef CONFIG_INTEL_IOMMU - extern int intel_iommu_sm; -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/intel/nested.c BPI-Router-Linux-kernel-6.16.12/drivers/iommu/intel/nested.c ---- BPI-Router-Linux-kernel/drivers/iommu/intel/nested.c 2025-10-22 13:53:23.283328800 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/intel/nested.c 2025-10-22 13:53:56.515169141 -0400 -@@ -216,8 +216,7 @@ intel_iommu_domain_alloc_nested(struct d - /* Must be nested domain */ - if (user_data->type != IOMMU_HWPT_DATA_VTD_S1) - return ERR_PTR(-EOPNOTSUPP); -- if (parent->ops != intel_iommu_ops.default_domain_ops || -- !s2_domain->nested_parent) -+ if (!intel_domain_is_ss_paging(s2_domain) || !s2_domain->nested_parent) - return ERR_PTR(-EINVAL); - - ret = iommu_copy_struct_from_user(&vtd, user_data, -@@ -229,7 +228,6 @@ intel_iommu_domain_alloc_nested(struct d - if (!domain) - return ERR_PTR(-ENOMEM); - -- domain->use_first_level = true; - domain->s2_domain = s2_domain; - domain->s1_cfg = vtd; - domain->domain.ops = &intel_nested_domain_ops; -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/intel/svm.c BPI-Router-Linux-kernel-6.16.12/drivers/iommu/intel/svm.c ---- BPI-Router-Linux-kernel/drivers/iommu/intel/svm.c 2025-10-22 13:53:23.283328800 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/intel/svm.c 2025-10-22 13:53:56.519169122 -0400 -@@ -214,7 +214,6 @@ struct iommu_domain *intel_svm_domain_al - return ERR_PTR(-ENOMEM); - - domain->domain.ops = &intel_svm_domain_ops; -- domain->use_first_level = true; - INIT_LIST_HEAD(&domain->dev_pasids); - INIT_LIST_HEAD(&domain->cache_tags); - spin_lock_init(&domain->cache_lock); -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/iommufd/device.c BPI-Router-Linux-kernel-6.16.12/drivers/iommu/iommufd/device.c ---- BPI-Router-Linux-kernel/drivers/iommu/iommufd/device.c 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/iommufd/device.c 2025-10-22 13:53:56.519169122 -0400 -@@ -661,6 +661,8 @@ iommufd_hw_pagetable_detach(struct iommu - iopt_remove_reserved_iova(&hwpt_paging->ioas->iopt, idev->dev); - mutex_unlock(&igroup->lock); - -+ iommufd_hw_pagetable_put(idev->ictx, hwpt); -+ - /* Caller must destroy hwpt */ - return hwpt; - } -@@ -1007,7 +1009,6 @@ void iommufd_device_detach(struct iommuf - hwpt = iommufd_hw_pagetable_detach(idev, pasid); - if (!hwpt) - return; -- iommufd_hw_pagetable_put(idev->ictx, hwpt); - refcount_dec(&idev->obj.users); - } - EXPORT_SYMBOL_NS_GPL(iommufd_device_detach, "IOMMUFD"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/iommufd/eventq.c BPI-Router-Linux-kernel-6.16.12/drivers/iommu/iommufd/eventq.c ---- BPI-Router-Linux-kernel/drivers/iommu/iommufd/eventq.c 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/iommufd/eventq.c 2025-10-22 13:53:56.519169122 -0400 -@@ -393,12 +393,12 @@ static int iommufd_eventq_init(struct io - const struct file_operations *fops) - { - struct file *filep; -- int fdno; - - spin_lock_init(&eventq->lock); - INIT_LIST_HEAD(&eventq->deliver); - init_waitqueue_head(&eventq->wait_queue); - -+ /* The filep is fput() by the core code during failure */ - filep = anon_inode_getfile(name, fops, eventq, O_RDWR); - if (IS_ERR(filep)) - return PTR_ERR(filep); -@@ -408,10 +408,7 @@ static int iommufd_eventq_init(struct io - eventq->filep = filep; - refcount_inc(&eventq->obj.users); - -- fdno = get_unused_fd_flags(O_CLOEXEC); -- if (fdno < 0) -- fput(filep); -- return fdno; -+ return get_unused_fd_flags(O_CLOEXEC); - } - - static const struct file_operations iommufd_fault_fops = -@@ -455,7 +452,6 @@ int iommufd_fault_alloc(struct iommufd_u - return 0; - out_put_fdno: - put_unused_fd(fdno); -- fput(fault->common.filep); - out_abort: - iommufd_object_abort_and_destroy(ucmd->ictx, &fault->common.obj); - -@@ -542,7 +538,6 @@ int iommufd_veventq_alloc(struct iommufd - - out_put_fdno: - put_unused_fd(fdno); -- fput(veventq->common.filep); - out_abort: - iommufd_object_abort_and_destroy(ucmd->ictx, &veventq->common.obj); - out_unlock_veventqs: -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/iommufd/iommufd_private.h BPI-Router-Linux-kernel-6.16.12/drivers/iommu/iommufd/iommufd_private.h ---- BPI-Router-Linux-kernel/drivers/iommu/iommufd/iommufd_private.h 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/iommufd/iommufd_private.h 2025-10-22 13:53:56.519169122 -0400 -@@ -390,9 +390,8 @@ static inline void iommufd_hw_pagetable_ - if (hwpt->obj.type == IOMMUFD_OBJ_HWPT_PAGING) { - struct iommufd_hwpt_paging *hwpt_paging = to_hwpt_paging(hwpt); - -- lockdep_assert_not_held(&hwpt_paging->ioas->mutex); -- - if (hwpt_paging->auto_domain) { -+ lockdep_assert_not_held(&hwpt_paging->ioas->mutex); - iommufd_object_put_and_try_destroy(ictx, &hwpt->obj); - return; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/iommufd/io_pagetable.c BPI-Router-Linux-kernel-6.16.12/drivers/iommu/iommufd/io_pagetable.c ---- BPI-Router-Linux-kernel/drivers/iommu/iommufd/io_pagetable.c 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/iommufd/io_pagetable.c 2025-10-22 13:53:56.519169122 -0400 -@@ -70,36 +70,45 @@ struct iopt_area *iopt_area_contig_next( - return iter->area; - } - --static bool __alloc_iova_check_hole(struct interval_tree_double_span_iter *span, -- unsigned long length, -- unsigned long iova_alignment, -- unsigned long page_offset) -+static bool __alloc_iova_check_range(unsigned long *start, unsigned long last, -+ unsigned long length, -+ unsigned long iova_alignment, -+ unsigned long page_offset) - { -- if (span->is_used || span->last_hole - span->start_hole < length - 1) -+ unsigned long aligned_start; -+ -+ /* ALIGN_UP() */ -+ if (check_add_overflow(*start, iova_alignment - 1, &aligned_start)) - return false; -+ aligned_start &= ~(iova_alignment - 1); -+ aligned_start |= page_offset; - -- span->start_hole = ALIGN(span->start_hole, iova_alignment) | -- page_offset; -- if (span->start_hole > span->last_hole || -- span->last_hole - span->start_hole < length - 1) -+ if (aligned_start >= last || last - aligned_start < length - 1) - return false; -+ *start = aligned_start; - return true; - } - --static bool __alloc_iova_check_used(struct interval_tree_span_iter *span, -+static bool __alloc_iova_check_hole(struct interval_tree_double_span_iter *span, - unsigned long length, - unsigned long iova_alignment, - unsigned long page_offset) - { -- if (span->is_hole || span->last_used - span->start_used < length - 1) -+ if (span->is_used) - return false; -+ return __alloc_iova_check_range(&span->start_hole, span->last_hole, -+ length, iova_alignment, page_offset); -+} - -- span->start_used = ALIGN(span->start_used, iova_alignment) | -- page_offset; -- if (span->start_used > span->last_used || -- span->last_used - span->start_used < length - 1) -+static bool __alloc_iova_check_used(struct interval_tree_span_iter *span, -+ unsigned long length, -+ unsigned long iova_alignment, -+ unsigned long page_offset) -+{ -+ if (span->is_hole) - return false; -- return true; -+ return __alloc_iova_check_range(&span->start_used, span->last_used, -+ length, iova_alignment, page_offset); - } - - /* -@@ -743,8 +752,10 @@ again: - iommufd_access_notify_unmap(iopt, area_first, length); - /* Something is not responding to unmap requests. */ - tries++; -- if (WARN_ON(tries > 100)) -- return -EDEADLOCK; -+ if (WARN_ON(tries > 100)) { -+ rc = -EDEADLOCK; -+ goto out_unmapped; -+ } - goto again; - } - -@@ -766,6 +777,7 @@ again: - out_unlock_iova: - up_write(&iopt->iova_rwsem); - up_read(&iopt->domains_rwsem); -+out_unmapped: - if (unmapped) - *unmapped = unmapped_bytes; - return rc; -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/iommufd/main.c BPI-Router-Linux-kernel-6.16.12/drivers/iommu/iommufd/main.c ---- BPI-Router-Linux-kernel/drivers/iommu/iommufd/main.c 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/iommufd/main.c 2025-10-22 13:53:56.519169122 -0400 -@@ -23,6 +23,7 @@ - #include "iommufd_test.h" - - struct iommufd_object_ops { -+ size_t file_offset; - void (*destroy)(struct iommufd_object *obj); - void (*abort)(struct iommufd_object *obj); - }; -@@ -61,6 +62,10 @@ void iommufd_object_abort(struct iommufd - old = xas_store(&xas, NULL); - xa_unlock(&ictx->objects); - WARN_ON(old != XA_ZERO_ENTRY); -+ -+ if (WARN_ON(!refcount_dec_and_test(&obj->users))) -+ return; -+ - kfree(obj); - } - -@@ -71,10 +76,30 @@ void iommufd_object_abort(struct iommufd - void iommufd_object_abort_and_destroy(struct iommufd_ctx *ictx, - struct iommufd_object *obj) - { -- if (iommufd_object_ops[obj->type].abort) -- iommufd_object_ops[obj->type].abort(obj); -+ const struct iommufd_object_ops *ops = &iommufd_object_ops[obj->type]; -+ -+ if (ops->file_offset) { -+ struct file **filep = ((void *)obj) + ops->file_offset; -+ -+ /* -+ * A file should hold a users refcount while the file is open -+ * and put it back in its release. The file should hold a -+ * pointer to obj in their private data. Normal fput() is -+ * deferred to a workqueue and can get out of order with the -+ * following kfree(obj). Using the sync version ensures the -+ * release happens immediately. During abort we require the file -+ * refcount is one at this point - meaning the object alloc -+ * function cannot do anything to allow another thread to take a -+ * refcount prior to a guaranteed success. -+ */ -+ if (*filep) -+ __fput_sync(*filep); -+ } -+ -+ if (ops->abort) -+ ops->abort(obj); - else -- iommufd_object_ops[obj->type].destroy(obj); -+ ops->destroy(obj); - iommufd_object_abort(ictx, obj); - } - -@@ -493,6 +518,12 @@ void iommufd_ctx_put(struct iommufd_ctx - } - EXPORT_SYMBOL_NS_GPL(iommufd_ctx_put, "IOMMUFD"); - -+#define IOMMUFD_FILE_OFFSET(_struct, _filep, _obj) \ -+ .file_offset = (offsetof(_struct, _filep) + \ -+ BUILD_BUG_ON_ZERO(!__same_type( \ -+ struct file *, ((_struct *)NULL)->_filep)) + \ -+ BUILD_BUG_ON_ZERO(offsetof(_struct, _obj))) -+ - static const struct iommufd_object_ops iommufd_object_ops[] = { - [IOMMUFD_OBJ_ACCESS] = { - .destroy = iommufd_access_destroy_object, -@@ -502,6 +533,7 @@ static const struct iommufd_object_ops i - }, - [IOMMUFD_OBJ_FAULT] = { - .destroy = iommufd_fault_destroy, -+ IOMMUFD_FILE_OFFSET(struct iommufd_fault, common.filep, common.obj), - }, - [IOMMUFD_OBJ_HWPT_PAGING] = { - .destroy = iommufd_hwpt_paging_destroy, -@@ -520,6 +552,7 @@ static const struct iommufd_object_ops i - [IOMMUFD_OBJ_VEVENTQ] = { - .destroy = iommufd_veventq_destroy, - .abort = iommufd_veventq_abort, -+ IOMMUFD_FILE_OFFSET(struct iommufd_veventq, common.filep, common.obj), - }, - [IOMMUFD_OBJ_VIOMMU] = { - .destroy = iommufd_viommu_destroy, -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/iommufd/selftest.c BPI-Router-Linux-kernel-6.16.12/drivers/iommu/iommufd/selftest.c ---- BPI-Router-Linux-kernel/drivers/iommu/iommufd/selftest.c 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/iommufd/selftest.c 2025-10-22 13:53:56.519169122 -0400 -@@ -801,7 +801,6 @@ static const struct iommu_ops mock_ops = - .default_domain = &mock_blocking_domain, - .blocked_domain = &mock_blocking_domain, - .owner = THIS_MODULE, -- .pgsize_bitmap = MOCK_IO_PAGE_SIZE, - .hw_info = mock_domain_hw_info, - .domain_alloc_paging_flags = mock_domain_alloc_paging_flags, - .domain_alloc_nested = mock_domain_alloc_nested, -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/riscv/iommu.c BPI-Router-Linux-kernel-6.16.12/drivers/iommu/riscv/iommu.c ---- BPI-Router-Linux-kernel/drivers/iommu/riscv/iommu.c 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/riscv/iommu.c 2025-10-22 13:53:56.519169122 -0400 -@@ -1283,7 +1283,7 @@ static phys_addr_t riscv_iommu_iova_to_p - unsigned long *ptr; - - ptr = riscv_iommu_pte_fetch(domain, iova, &pte_size); -- if (_io_pte_none(*ptr) || !_io_pte_present(*ptr)) -+ if (!ptr) - return 0; - - return pfn_to_phys(__page_val_to_pfn(*ptr)) | (iova & (pte_size - 1)); -@@ -1533,7 +1533,6 @@ static void riscv_iommu_release_device(s - } - - static const struct iommu_ops riscv_iommu_ops = { -- .pgsize_bitmap = SZ_4K, - .of_xlate = riscv_iommu_of_xlate, - .identity_domain = &riscv_iommu_identity_domain, - .blocked_domain = &riscv_iommu_blocking_domain, -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/rockchip-iommu.c BPI-Router-Linux-kernel-6.16.12/drivers/iommu/rockchip-iommu.c ---- BPI-Router-Linux-kernel/drivers/iommu/rockchip-iommu.c 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/rockchip-iommu.c 2025-10-22 13:53:56.519169122 -0400 -@@ -1157,7 +1157,6 @@ static int rk_iommu_of_xlate(struct devi - return -ENOMEM; - - data->iommu = platform_get_drvdata(iommu_dev); -- data->iommu->domain = &rk_identity_domain; - dev_iommu_priv_set(dev, data); - - platform_device_put(iommu_dev); -@@ -1195,6 +1194,8 @@ static int rk_iommu_probe(struct platfor - if (!iommu) - return -ENOMEM; - -+ iommu->domain = &rk_identity_domain; -+ - platform_set_drvdata(pdev, iommu); - iommu->dev = dev; - iommu->num_mmu = 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/s390-iommu.c BPI-Router-Linux-kernel-6.16.12/drivers/iommu/s390-iommu.c ---- BPI-Router-Linux-kernel/drivers/iommu/s390-iommu.c 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/s390-iommu.c 2025-10-22 13:53:56.519169122 -0400 -@@ -611,6 +611,23 @@ static u64 get_iota_region_flag(struct s - } - } - -+static bool reg_ioat_propagate_error(int cc, u8 status) -+{ -+ /* -+ * If the device is in the error state the reset routine -+ * will register the IOAT of the newly set domain on re-enable -+ */ -+ if (cc == ZPCI_CC_ERR && status == ZPCI_PCI_ST_FUNC_NOT_AVAIL) -+ return false; -+ /* -+ * If the device was removed treat registration as success -+ * and let the subsequent error event trigger tear down. -+ */ -+ if (cc == ZPCI_CC_INVAL_HANDLE) -+ return false; -+ return cc != ZPCI_CC_OK; -+} -+ - static int s390_iommu_domain_reg_ioat(struct zpci_dev *zdev, - struct iommu_domain *domain, u8 *status) - { -@@ -695,7 +712,7 @@ static int s390_iommu_attach_device(stru - - /* If we fail now DMA remains blocked via blocking domain */ - cc = s390_iommu_domain_reg_ioat(zdev, domain, &status); -- if (cc && status != ZPCI_PCI_ST_FUNC_NOT_AVAIL) -+ if (reg_ioat_propagate_error(cc, status)) - return -EIO; - zdev->dma_table = s390_domain->dma_table; - zdev_s390_domain_update(zdev, domain); -@@ -1031,7 +1048,8 @@ struct zpci_iommu_ctrs *zpci_get_iommu_c - - lockdep_assert_held(&zdev->dom_lock); - -- if (zdev->s390_domain->type == IOMMU_DOMAIN_BLOCKED) -+ if (zdev->s390_domain->type == IOMMU_DOMAIN_BLOCKED || -+ zdev->s390_domain->type == IOMMU_DOMAIN_IDENTITY) - return NULL; - - s390_domain = to_s390_domain(zdev->s390_domain); -@@ -1122,12 +1140,7 @@ static int s390_attach_dev_identity(stru - - /* If we fail now DMA remains blocked via blocking domain */ - cc = s390_iommu_domain_reg_ioat(zdev, domain, &status); -- -- /* -- * If the device is undergoing error recovery the reset code -- * will re-establish the new domain. -- */ -- if (cc && status != ZPCI_PCI_ST_FUNC_NOT_AVAIL) -+ if (reg_ioat_propagate_error(cc, status)) - return -EIO; - - zdev_s390_domain_update(zdev, domain); -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/tegra-smmu.c BPI-Router-Linux-kernel-6.16.12/drivers/iommu/tegra-smmu.c ---- BPI-Router-Linux-kernel/drivers/iommu/tegra-smmu.c 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/tegra-smmu.c 2025-10-22 13:53:56.519169122 -0400 -@@ -559,11 +559,11 @@ static void tegra_smmu_set_pde(struct te - { - unsigned int pd_index = iova_pd_index(iova); - struct tegra_smmu *smmu = as->smmu; -- struct tegra_pd *pd = as->pd; -+ u32 *pd = &as->pd->val[pd_index]; - unsigned long offset = pd_index * sizeof(*pd); - - /* Set the page directory entry first */ -- pd->val[pd_index] = value; -+ *pd = value; - - /* The flush the page directory entry from caches */ - dma_sync_single_range_for_device(smmu->dev, as->pd_dma, offset, -diff -purNx .git BPI-Router-Linux-kernel/drivers/iommu/virtio-iommu.c BPI-Router-Linux-kernel-6.16.12/drivers/iommu/virtio-iommu.c ---- BPI-Router-Linux-kernel/drivers/iommu/virtio-iommu.c 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/iommu/virtio-iommu.c 2025-10-22 13:53:56.519169122 -0400 -@@ -998,8 +998,7 @@ static void viommu_get_resv_regions(stru - iommu_dma_get_resv_regions(dev, head); - } - --static struct iommu_ops viommu_ops; --static struct virtio_driver virtio_iommu_drv; -+static const struct bus_type *virtio_bus_type; - - static int viommu_match_node(struct device *dev, const void *data) - { -@@ -1008,8 +1007,9 @@ static int viommu_match_node(struct devi - - static struct viommu_dev *viommu_get_by_fwnode(struct fwnode_handle *fwnode) - { -- struct device *dev = driver_find_device(&virtio_iommu_drv.driver, NULL, -- fwnode, viommu_match_node); -+ struct device *dev = bus_find_device(virtio_bus_type, NULL, fwnode, -+ viommu_match_node); -+ - put_device(dev); - - return dev ? dev_to_virtio(dev)->priv : NULL; -@@ -1086,7 +1086,7 @@ static bool viommu_capable(struct device - } - } - --static struct iommu_ops viommu_ops = { -+static const struct iommu_ops viommu_ops = { - .capable = viommu_capable, - .domain_alloc_identity = viommu_domain_alloc_identity, - .domain_alloc_paging = viommu_domain_alloc_paging, -@@ -1160,6 +1160,9 @@ static int viommu_probe(struct virtio_de - if (!viommu) - return -ENOMEM; - -+ /* Borrow this for easy lookups later */ -+ virtio_bus_type = dev->bus; -+ - spin_lock_init(&viommu->request_lock); - ida_init(&viommu->domain_ids); - viommu->dev = dev; -@@ -1217,8 +1220,6 @@ static int viommu_probe(struct virtio_de - viommu->first_domain++; - } - -- viommu_ops.pgsize_bitmap = viommu->pgsize_bitmap; -- - virtio_device_ready(vdev); - - /* Populate the event queue with buffers */ -@@ -1231,10 +1232,10 @@ static int viommu_probe(struct virtio_de - if (ret) - goto err_free_vqs; - -- iommu_device_register(&viommu->iommu, &viommu_ops, parent_dev); -- - vdev->priv = viommu; - -+ iommu_device_register(&viommu->iommu, &viommu_ops, parent_dev); -+ - dev_info(dev, "input address: %u bits\n", - order_base_2(viommu->geometry.aperture_end)); - dev_info(dev, "page mask: %#llx\n", viommu->pgsize_bitmap); -diff -purNx .git BPI-Router-Linux-kernel/drivers/irqchip/irq-ath79-misc.c BPI-Router-Linux-kernel-6.16.12/drivers/irqchip/irq-ath79-misc.c ---- BPI-Router-Linux-kernel/drivers/irqchip/irq-ath79-misc.c 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/irqchip/irq-ath79-misc.c 2025-10-22 13:53:56.519169122 -0400 -@@ -15,6 +15,8 @@ - #include - #include - -+#include -+ - #define AR71XX_RESET_REG_MISC_INT_STATUS 0 - #define AR71XX_RESET_REG_MISC_INT_ENABLE 4 - -@@ -177,21 +179,3 @@ static int __init ar7240_misc_intc_of_in - - IRQCHIP_DECLARE(ar7240_misc_intc, "qca,ar7240-misc-intc", - ar7240_misc_intc_of_init); -- --void __init ath79_misc_irq_init(void __iomem *regs, int irq, -- int irq_base, bool is_ar71xx) --{ -- struct irq_domain *domain; -- -- if (is_ar71xx) -- ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask; -- else -- ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack; -- -- domain = irq_domain_create_legacy(NULL, ATH79_MISC_IRQ_COUNT, -- irq_base, 0, &misc_irq_domain_ops, regs); -- if (!domain) -- panic("Failed to create MISC irqdomain"); -- -- ath79_misc_intc_domain_init(domain, irq); --} -diff -purNx .git BPI-Router-Linux-kernel/drivers/irqchip/irq-mips-gic.c BPI-Router-Linux-kernel-6.16.12/drivers/irqchip/irq-mips-gic.c ---- BPI-Router-Linux-kernel/drivers/irqchip/irq-mips-gic.c 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/irqchip/irq-mips-gic.c 2025-10-22 13:53:56.519169122 -0400 -@@ -375,9 +375,13 @@ static int gic_set_affinity(struct irq_d - /* - * The GIC specifies that we can only route an interrupt to one VP(E), - * ie. CPU in Linux parlance, at a time. Therefore we always route to -- * the first online CPU in the mask. -+ * the first forced or online CPU in the mask. - */ -- cpu = cpumask_first_and(cpumask, cpu_online_mask); -+ if (force) -+ cpu = cpumask_first(cpumask); -+ else -+ cpu = cpumask_first_and(cpumask, cpu_online_mask); -+ - if (cpu >= NR_CPUS) - return -EINVAL; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/irqchip/irq-mvebu-gicp.c BPI-Router-Linux-kernel-6.16.12/drivers/irqchip/irq-mvebu-gicp.c ---- BPI-Router-Linux-kernel/drivers/irqchip/irq-mvebu-gicp.c 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/irqchip/irq-mvebu-gicp.c 2025-10-22 13:53:56.519169122 -0400 -@@ -177,6 +177,7 @@ static int mvebu_gicp_probe(struct platf - .ops = &gicp_domain_ops, - }; - struct mvebu_gicp *gicp; -+ void __iomem *base; - int ret, i; - - gicp = devm_kzalloc(&pdev->dev, sizeof(*gicp), GFP_KERNEL); -@@ -236,6 +237,15 @@ static int mvebu_gicp_probe(struct platf - return -ENODEV; - } - -+ base = ioremap(gicp->res->start, resource_size(gicp->res)); -+ if (!base) { -+ dev_err(&pdev->dev, "ioremap() failed. Unable to clear pending interrupts.\n"); -+ } else { -+ for (i = 0; i < 64; i++) -+ writel(i, base + GICP_CLRSPI_NSR_OFFSET); -+ iounmap(base); -+ } -+ - return msi_create_parent_irq_domain(&info, &gicp_msi_parent_ops) ? 0 : -ENOMEM; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/irqchip/irq-renesas-rzv2h.c BPI-Router-Linux-kernel-6.16.12/drivers/irqchip/irq-renesas-rzv2h.c ---- BPI-Router-Linux-kernel/drivers/irqchip/irq-renesas-rzv2h.c 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/irqchip/irq-renesas-rzv2h.c 2025-10-22 13:53:56.519169122 -0400 -@@ -427,7 +427,9 @@ static const struct irq_chip rzv2h_icu_c - .irq_retrigger = irq_chip_retrigger_hierarchy, - .irq_set_type = rzv2h_icu_set_type, - .irq_set_affinity = irq_chip_set_affinity_parent, -- .flags = IRQCHIP_SET_TYPE_MASKED, -+ .flags = IRQCHIP_MASK_ON_SUSPEND | -+ IRQCHIP_SET_TYPE_MASKED | -+ IRQCHIP_SKIP_SET_WAKE, - }; - - static int rzv2h_icu_alloc(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs, -diff -purNx .git BPI-Router-Linux-kernel/drivers/irqchip/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/irqchip/Kconfig ---- BPI-Router-Linux-kernel/drivers/irqchip/Kconfig 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/irqchip/Kconfig 2025-10-22 13:53:56.519169122 -0400 -@@ -74,6 +74,7 @@ config ARM_VIC_NR - - config IRQ_MSI_LIB - bool -+ select GENERIC_MSI_IRQ - - config ARMADA_370_XP_IRQ - bool -@@ -538,6 +539,7 @@ config IMX_MU_MSI - tristate "i.MX MU used as MSI controller" - depends on OF && HAS_IOMEM - depends on ARCH_MXC || COMPILE_TEST -+ depends on ARM || ARM64 - default m if ARCH_MXC - select IRQ_DOMAIN - select IRQ_DOMAIN_HIERARCHY -diff -purNx .git BPI-Router-Linux-kernel/drivers/isdn/hardware/mISDN/hfcpci.c BPI-Router-Linux-kernel-6.16.12/drivers/isdn/hardware/mISDN/hfcpci.c ---- BPI-Router-Linux-kernel/drivers/isdn/hardware/mISDN/hfcpci.c 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/isdn/hardware/mISDN/hfcpci.c 2025-10-22 13:53:56.519169122 -0400 -@@ -39,12 +39,13 @@ - - #include "hfc_pci.h" - -+static void hfcpci_softirq(struct timer_list *unused); - static const char *hfcpci_revision = "2.0"; - - static int HFC_cnt; - static uint debug; - static uint poll, tics; --static struct timer_list hfc_tl; -+static DEFINE_TIMER(hfc_tl, hfcpci_softirq); - static unsigned long hfc_jiffies; - - MODULE_AUTHOR("Karsten Keil"); -@@ -2305,8 +2306,7 @@ hfcpci_softirq(struct timer_list *unused - hfc_jiffies = jiffies + 1; - else - hfc_jiffies += tics; -- hfc_tl.expires = hfc_jiffies; -- add_timer(&hfc_tl); -+ mod_timer(&hfc_tl, hfc_jiffies); - } - - static int __init -@@ -2332,10 +2332,8 @@ HFC_init(void) - if (poll != HFCPCI_BTRANS_THRESHOLD) { - printk(KERN_INFO "%s: Using alternative poll value of %d\n", - __func__, poll); -- timer_setup(&hfc_tl, hfcpci_softirq, 0); -- hfc_tl.expires = jiffies + tics; -- hfc_jiffies = hfc_tl.expires; -- add_timer(&hfc_tl); -+ hfc_jiffies = jiffies + tics; -+ mod_timer(&hfc_tl, hfc_jiffies); - } else - tics = 0; /* indicate the use of controller's timer */ - -diff -purNx .git BPI-Router-Linux-kernel/drivers/isdn/mISDN/dsp_hwec.c BPI-Router-Linux-kernel-6.16.12/drivers/isdn/mISDN/dsp_hwec.c ---- BPI-Router-Linux-kernel/drivers/isdn/mISDN/dsp_hwec.c 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/isdn/mISDN/dsp_hwec.c 2025-10-22 13:53:56.519169122 -0400 -@@ -51,14 +51,14 @@ void dsp_hwec_enable(struct dsp *dsp, co - goto _do; - - { -- char *dup, *tok, *name, *val; -+ char *dup, *next, *tok, *name, *val; - int tmp; - -- dup = kstrdup(arg, GFP_ATOMIC); -+ dup = next = kstrdup(arg, GFP_ATOMIC); - if (!dup) - return; - -- while ((tok = strsep(&dup, ","))) { -+ while ((tok = strsep(&next, ","))) { - if (!strlen(tok)) - continue; - name = strsep(&tok, "="); -diff -purNx .git BPI-Router-Linux-kernel/drivers/leds/flash/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/leds/flash/Kconfig ---- BPI-Router-Linux-kernel/drivers/leds/flash/Kconfig 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/leds/flash/Kconfig 2025-10-22 13:53:56.519169122 -0400 -@@ -136,6 +136,7 @@ config LEDS_TPS6131X - tristate "LED support for TI TPS6131x flash LED driver" - depends on I2C && OF - depends on GPIOLIB -+ depends on V4L2_FLASH_LED_CLASS || !V4L2_FLASH_LED_CLASS - select REGMAP_I2C - help - This option enables support for Texas Instruments TPS61310/TPS61311 -diff -purNx .git BPI-Router-Linux-kernel/drivers/leds/flash/leds-qcom-flash.c BPI-Router-Linux-kernel-6.16.12/drivers/leds/flash/leds-qcom-flash.c ---- BPI-Router-Linux-kernel/drivers/leds/flash/leds-qcom-flash.c 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/leds/flash/leds-qcom-flash.c 2025-10-22 13:53:56.519169122 -0400 -@@ -117,7 +117,7 @@ enum { - REG_MAX_COUNT, - }; - --static struct reg_field mvflash_3ch_regs[REG_MAX_COUNT] = { -+static const struct reg_field mvflash_3ch_regs[REG_MAX_COUNT] = { - REG_FIELD(0x08, 0, 7), /* status1 */ - REG_FIELD(0x09, 0, 7), /* status2 */ - REG_FIELD(0x0a, 0, 7), /* status3 */ -@@ -132,7 +132,7 @@ static struct reg_field mvflash_3ch_regs - REG_FIELD(0x58, 0, 2), /* therm_thrsh3 */ - }; - --static struct reg_field mvflash_4ch_regs[REG_MAX_COUNT] = { -+static const struct reg_field mvflash_4ch_regs[REG_MAX_COUNT] = { - REG_FIELD(0x06, 0, 7), /* status1 */ - REG_FIELD(0x07, 0, 6), /* status2 */ - REG_FIELD(0x09, 0, 7), /* status3 */ -@@ -854,11 +854,17 @@ static int qcom_flash_led_probe(struct p - if (val == FLASH_SUBTYPE_3CH_PM8150_VAL || val == FLASH_SUBTYPE_3CH_PMI8998_VAL) { - flash_data->hw_type = QCOM_MVFLASH_3CH; - flash_data->max_channels = 3; -- regs = mvflash_3ch_regs; -+ regs = devm_kmemdup(dev, mvflash_3ch_regs, sizeof(mvflash_3ch_regs), -+ GFP_KERNEL); -+ if (!regs) -+ return -ENOMEM; - } else if (val == FLASH_SUBTYPE_4CH_VAL) { - flash_data->hw_type = QCOM_MVFLASH_4CH; - flash_data->max_channels = 4; -- regs = mvflash_4ch_regs; -+ regs = devm_kmemdup(dev, mvflash_4ch_regs, sizeof(mvflash_4ch_regs), -+ GFP_KERNEL); -+ if (!regs) -+ return -ENOMEM; - - rc = regmap_read(regmap, reg_base + FLASH_REVISION_REG, &val); - if (rc < 0) { -@@ -880,6 +886,7 @@ static int qcom_flash_led_probe(struct p - dev_err(dev, "Failed to allocate regmap field, rc=%d\n", rc); - return rc; - } -+ devm_kfree(dev, regs); /* devm_regmap_field_bulk_alloc() makes copies */ - - platform_set_drvdata(pdev, flash_data); - mutex_init(&flash_data->lock); -diff -purNx .git BPI-Router-Linux-kernel/drivers/leds/leds-lp50xx.c BPI-Router-Linux-kernel-6.16.12/drivers/leds/leds-lp50xx.c ---- BPI-Router-Linux-kernel/drivers/leds/leds-lp50xx.c 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/leds/leds-lp50xx.c 2025-10-22 13:53:56.519169122 -0400 -@@ -476,6 +476,7 @@ static int lp50xx_probe_dt(struct lp50xx - return -ENOMEM; - - fwnode_for_each_child_node(child, led_node) { -+ int multi_index; - ret = fwnode_property_read_u32(led_node, "color", - &color_id); - if (ret) { -@@ -483,8 +484,16 @@ static int lp50xx_probe_dt(struct lp50xx - dev_err(priv->dev, "Cannot read color\n"); - return ret; - } -+ ret = fwnode_property_read_u32(led_node, "reg", &multi_index); -+ if (ret != 0) { -+ dev_err(priv->dev, "reg must be set\n"); -+ return -EINVAL; -+ } else if (multi_index >= LP50XX_LEDS_PER_MODULE) { -+ dev_err(priv->dev, "reg %i out of range\n", multi_index); -+ return -EINVAL; -+ } - -- mc_led_info[num_colors].color_index = color_id; -+ mc_led_info[multi_index].color_index = color_id; - num_colors++; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/leds/leds-lp8860.c BPI-Router-Linux-kernel-6.16.12/drivers/leds/leds-lp8860.c ---- BPI-Router-Linux-kernel/drivers/leds/leds-lp8860.c 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/leds/leds-lp8860.c 2025-10-22 13:53:56.519169122 -0400 -@@ -307,7 +307,9 @@ static int lp8860_probe(struct i2c_clien - led->client = client; - led->led_dev.brightness_set_blocking = lp8860_brightness_set; - -- devm_mutex_init(&client->dev, &led->lock); -+ ret = devm_mutex_init(&client->dev, &led->lock); -+ if (ret) -+ return dev_err_probe(&client->dev, ret, "Failed to initialize lock\n"); - - led->regmap = devm_regmap_init_i2c(client, &lp8860_regmap_config); - if (IS_ERR(led->regmap)) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/leds/leds-pca955x.c BPI-Router-Linux-kernel-6.16.12/drivers/leds/leds-pca955x.c ---- BPI-Router-Linux-kernel/drivers/leds/leds-pca955x.c 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/leds/leds-pca955x.c 2025-10-22 13:53:56.519169122 -0400 -@@ -587,7 +587,7 @@ static int pca955x_probe(struct i2c_clie - struct pca955x_platform_data *pdata; - bool keep_psc0 = false; - bool set_default_label = false; -- char default_label[8]; -+ char default_label[4]; - int bit, err, reg; - - chip = i2c_get_match_data(client); -@@ -693,7 +693,7 @@ static int pca955x_probe(struct i2c_clie - } - - if (set_default_label) { -- snprintf(default_label, sizeof(default_label), "%u", i); -+ snprintf(default_label, sizeof(default_label), "%hhu", i); - init_data.default_label = default_label; - } else { - init_data.default_label = NULL; -diff -purNx .git BPI-Router-Linux-kernel/drivers/leds/trigger/ledtrig-netdev.c BPI-Router-Linux-kernel-6.16.12/drivers/leds/trigger/ledtrig-netdev.c ---- BPI-Router-Linux-kernel/drivers/leds/trigger/ledtrig-netdev.c 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/leds/trigger/ledtrig-netdev.c 2025-10-22 13:53:56.519169122 -0400 -@@ -68,7 +68,6 @@ struct led_netdev_data { - unsigned int last_activity; - - unsigned long mode; -- unsigned long blink_delay; - int link_speed; - __ETHTOOL_DECLARE_LINK_MODE_MASK(supported_link_modes); - u8 duplex; -@@ -87,10 +86,6 @@ static void set_baseline_state(struct le - /* Already validated, hw control is possible with the requested mode */ - if (trigger_data->hw_control) { - led_cdev->hw_control_set(led_cdev, trigger_data->mode); -- if (led_cdev->blink_set) { -- led_cdev->blink_set(led_cdev, &trigger_data->blink_delay, -- &trigger_data->blink_delay); -- } - - return; - } -@@ -459,11 +454,10 @@ static ssize_t interval_store(struct dev - size_t size) - { - struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); -- struct led_classdev *led_cdev = trigger_data->led_cdev; - unsigned long value; - int ret; - -- if (trigger_data->hw_control && !led_cdev->blink_set) -+ if (trigger_data->hw_control) - return -EINVAL; - - ret = kstrtoul(buf, 0, &value); -@@ -472,13 +466,9 @@ static ssize_t interval_store(struct dev - - /* impose some basic bounds on the timer interval */ - if (value >= 5 && value <= 10000) { -- if (trigger_data->hw_control) { -- trigger_data->blink_delay = value; -- } else { -- cancel_delayed_work_sync(&trigger_data->work); -+ cancel_delayed_work_sync(&trigger_data->work); - -- atomic_set(&trigger_data->interval, msecs_to_jiffies(value)); -- } -+ atomic_set(&trigger_data->interval, msecs_to_jiffies(value)); - set_baseline_state(trigger_data); /* resets timer */ - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/bcache/alloc.c BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/alloc.c ---- BPI-Router-Linux-kernel/drivers/md/bcache/alloc.c 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/alloc.c 2025-10-22 13:53:56.519169122 -0400 -@@ -164,61 +164,40 @@ static void bch_invalidate_one_bucket(st - * prio is worth 1/8th of what INITIAL_PRIO is worth. - */ - --static inline unsigned int new_bucket_prio(struct cache *ca, struct bucket *b) --{ -- unsigned int min_prio = (INITIAL_PRIO - ca->set->min_prio) / 8; -- -- return (b->prio - ca->set->min_prio + min_prio) * GC_SECTORS_USED(b); --} -- --static inline bool new_bucket_max_cmp(const void *l, const void *r, void *args) --{ -- struct bucket **lhs = (struct bucket **)l; -- struct bucket **rhs = (struct bucket **)r; -- struct cache *ca = args; -- -- return new_bucket_prio(ca, *lhs) > new_bucket_prio(ca, *rhs); --} -- --static inline bool new_bucket_min_cmp(const void *l, const void *r, void *args) --{ -- struct bucket **lhs = (struct bucket **)l; -- struct bucket **rhs = (struct bucket **)r; -- struct cache *ca = args; -+#define bucket_prio(b) \ -+({ \ -+ unsigned int min_prio = (INITIAL_PRIO - ca->set->min_prio) / 8; \ -+ \ -+ (b->prio - ca->set->min_prio + min_prio) * GC_SECTORS_USED(b); \ -+}) - -- return new_bucket_prio(ca, *lhs) < new_bucket_prio(ca, *rhs); --} -+#define bucket_max_cmp(l, r) (bucket_prio(l) < bucket_prio(r)) -+#define bucket_min_cmp(l, r) (bucket_prio(l) > bucket_prio(r)) - - static void invalidate_buckets_lru(struct cache *ca) - { - struct bucket *b; -- const struct min_heap_callbacks bucket_max_cmp_callback = { -- .less = new_bucket_max_cmp, -- .swp = NULL, -- }; -- const struct min_heap_callbacks bucket_min_cmp_callback = { -- .less = new_bucket_min_cmp, -- .swp = NULL, -- }; -+ ssize_t i; - -- ca->heap.nr = 0; -+ ca->heap.used = 0; - - for_each_bucket(b, ca) { - if (!bch_can_invalidate_bucket(ca, b)) - continue; - -- if (!min_heap_full(&ca->heap)) -- min_heap_push(&ca->heap, &b, &bucket_max_cmp_callback, ca); -- else if (!new_bucket_max_cmp(&b, min_heap_peek(&ca->heap), ca)) { -+ if (!heap_full(&ca->heap)) -+ heap_add(&ca->heap, b, bucket_max_cmp); -+ else if (bucket_max_cmp(b, heap_peek(&ca->heap))) { - ca->heap.data[0] = b; -- min_heap_sift_down(&ca->heap, 0, &bucket_max_cmp_callback, ca); -+ heap_sift(&ca->heap, 0, bucket_max_cmp); - } - } - -- min_heapify_all(&ca->heap, &bucket_min_cmp_callback, ca); -+ for (i = ca->heap.used / 2 - 1; i >= 0; --i) -+ heap_sift(&ca->heap, i, bucket_min_cmp); - - while (!fifo_full(&ca->free_inc)) { -- if (!ca->heap.nr) { -+ if (!heap_pop(&ca->heap, b, bucket_min_cmp)) { - /* - * We don't want to be calling invalidate_buckets() - * multiple times when it can't do anything -@@ -227,8 +206,6 @@ static void invalidate_buckets_lru(struc - wake_up_gc(ca->set); - return; - } -- b = min_heap_peek(&ca->heap)[0]; -- min_heap_pop(&ca->heap, &bucket_min_cmp_callback, ca); - - bch_invalidate_one_bucket(ca, b); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/bcache/bcache.h BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/bcache.h ---- BPI-Router-Linux-kernel/drivers/md/bcache/bcache.h 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/bcache.h 2025-10-22 13:53:56.519169122 -0400 -@@ -458,7 +458,7 @@ struct cache { - /* Allocation stuff: */ - struct bucket *buckets; - -- DEFINE_MIN_HEAP(struct bucket *, cache_heap) heap; -+ DECLARE_HEAP(struct bucket *, heap); - - /* - * If nonzero, we know we aren't going to find any buckets to invalidate -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/bcache/bset.c BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/bset.c ---- BPI-Router-Linux-kernel/drivers/md/bcache/bset.c 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/bset.c 2025-10-22 13:53:56.523169103 -0400 -@@ -54,11 +54,9 @@ void bch_dump_bucket(struct btree_keys * - int __bch_count_data(struct btree_keys *b) - { - unsigned int ret = 0; -- struct btree_iter iter; -+ struct btree_iter_stack iter; - struct bkey *k; - -- min_heap_init(&iter.heap, NULL, MAX_BSETS); -- - if (b->ops->is_extents) - for_each_key(b, k, &iter) - ret += KEY_SIZE(k); -@@ -69,11 +67,9 @@ void __bch_check_keys(struct btree_keys - { - va_list args; - struct bkey *k, *p = NULL; -- struct btree_iter iter; -+ struct btree_iter_stack iter; - const char *err; - -- min_heap_init(&iter.heap, NULL, MAX_BSETS); -- - for_each_key(b, k, &iter) { - if (b->ops->is_extents) { - err = "Keys out of order"; -@@ -114,9 +110,9 @@ bug: - - static void bch_btree_iter_next_check(struct btree_iter *iter) - { -- struct bkey *k = iter->heap.data->k, *next = bkey_next(k); -+ struct bkey *k = iter->data->k, *next = bkey_next(k); - -- if (next < iter->heap.data->end && -+ if (next < iter->data->end && - bkey_cmp(k, iter->b->ops->is_extents ? - &START_KEY(next) : next) > 0) { - bch_dump_bucket(iter->b); -@@ -883,14 +879,12 @@ unsigned int bch_btree_insert_key(struct - unsigned int status = BTREE_INSERT_STATUS_NO_INSERT; - struct bset *i = bset_tree_last(b)->data; - struct bkey *m, *prev = NULL; -- struct btree_iter iter; -+ struct btree_iter_stack iter; - struct bkey preceding_key_on_stack = ZERO_KEY; - struct bkey *preceding_key_p = &preceding_key_on_stack; - - BUG_ON(b->ops->is_extents && !KEY_SIZE(k)); - -- min_heap_init(&iter.heap, NULL, MAX_BSETS); -- - /* - * If k has preceding key, preceding_key_p will be set to address - * of k's preceding key; otherwise preceding_key_p will be set -@@ -901,9 +895,9 @@ unsigned int bch_btree_insert_key(struct - else - preceding_key(k, &preceding_key_p); - -- m = bch_btree_iter_init(b, &iter, preceding_key_p); -+ m = bch_btree_iter_stack_init(b, &iter, preceding_key_p); - -- if (b->ops->insert_fixup(b, k, &iter, replace_key)) -+ if (b->ops->insert_fixup(b, k, &iter.iter, replace_key)) - return status; - - status = BTREE_INSERT_STATUS_INSERT; -@@ -1083,94 +1077,79 @@ struct bkey *__bch_bset_search(struct bt - - /* Btree iterator */ - --typedef bool (new_btree_iter_cmp_fn)(const void *, const void *, void *); -+typedef bool (btree_iter_cmp_fn)(struct btree_iter_set, -+ struct btree_iter_set); - --static inline bool new_btree_iter_cmp(const void *l, const void *r, void __always_unused *args) -+static inline bool btree_iter_cmp(struct btree_iter_set l, -+ struct btree_iter_set r) - { -- const struct btree_iter_set *_l = l; -- const struct btree_iter_set *_r = r; -- -- return bkey_cmp(_l->k, _r->k) <= 0; -+ return bkey_cmp(l.k, r.k) > 0; - } - - static inline bool btree_iter_end(struct btree_iter *iter) - { -- return !iter->heap.nr; -+ return !iter->used; - } - - void bch_btree_iter_push(struct btree_iter *iter, struct bkey *k, - struct bkey *end) - { -- const struct min_heap_callbacks callbacks = { -- .less = new_btree_iter_cmp, -- .swp = NULL, -- }; -- - if (k != end) -- BUG_ON(!min_heap_push(&iter->heap, -- &((struct btree_iter_set) { k, end }), -- &callbacks, -- NULL)); -+ BUG_ON(!heap_add(iter, -+ ((struct btree_iter_set) { k, end }), -+ btree_iter_cmp)); - } - --static struct bkey *__bch_btree_iter_init(struct btree_keys *b, -- struct btree_iter *iter, -- struct bkey *search, -- struct bset_tree *start) -+static struct bkey *__bch_btree_iter_stack_init(struct btree_keys *b, -+ struct btree_iter_stack *iter, -+ struct bkey *search, -+ struct bset_tree *start) - { - struct bkey *ret = NULL; - -- iter->heap.size = ARRAY_SIZE(iter->heap.preallocated); -- iter->heap.nr = 0; -+ iter->iter.size = ARRAY_SIZE(iter->stack_data); -+ iter->iter.used = 0; - - #ifdef CONFIG_BCACHE_DEBUG -- iter->b = b; -+ iter->iter.b = b; - #endif - - for (; start <= bset_tree_last(b); start++) { - ret = bch_bset_search(b, start, search); -- bch_btree_iter_push(iter, ret, bset_bkey_last(start->data)); -+ bch_btree_iter_push(&iter->iter, ret, bset_bkey_last(start->data)); - } - - return ret; - } - --struct bkey *bch_btree_iter_init(struct btree_keys *b, -- struct btree_iter *iter, -+struct bkey *bch_btree_iter_stack_init(struct btree_keys *b, -+ struct btree_iter_stack *iter, - struct bkey *search) - { -- return __bch_btree_iter_init(b, iter, search, b->set); -+ return __bch_btree_iter_stack_init(b, iter, search, b->set); - } - - static inline struct bkey *__bch_btree_iter_next(struct btree_iter *iter, -- new_btree_iter_cmp_fn *cmp) -+ btree_iter_cmp_fn *cmp) - { - struct btree_iter_set b __maybe_unused; - struct bkey *ret = NULL; -- const struct min_heap_callbacks callbacks = { -- .less = cmp, -- .swp = NULL, -- }; - - if (!btree_iter_end(iter)) { - bch_btree_iter_next_check(iter); - -- ret = iter->heap.data->k; -- iter->heap.data->k = bkey_next(iter->heap.data->k); -+ ret = iter->data->k; -+ iter->data->k = bkey_next(iter->data->k); - -- if (iter->heap.data->k > iter->heap.data->end) { -+ if (iter->data->k > iter->data->end) { - WARN_ONCE(1, "bset was corrupt!\n"); -- iter->heap.data->k = iter->heap.data->end; -+ iter->data->k = iter->data->end; - } - -- if (iter->heap.data->k == iter->heap.data->end) { -- if (iter->heap.nr) { -- b = min_heap_peek(&iter->heap)[0]; -- min_heap_pop(&iter->heap, &callbacks, NULL); -- } -- } -+ if (iter->data->k == iter->data->end) -+ heap_pop(iter, b, cmp); - else -- min_heap_sift_down(&iter->heap, 0, &callbacks, NULL); -+ heap_sift(iter, 0, cmp); - } - - return ret; -@@ -1178,7 +1157,7 @@ static inline struct bkey *__bch_btree_i - - struct bkey *bch_btree_iter_next(struct btree_iter *iter) - { -- return __bch_btree_iter_next(iter, new_btree_iter_cmp); -+ return __bch_btree_iter_next(iter, btree_iter_cmp); - - } - -@@ -1216,18 +1195,16 @@ static void btree_mergesort(struct btree - struct btree_iter *iter, - bool fixup, bool remove_stale) - { -+ int i; - struct bkey *k, *last = NULL; - BKEY_PADDED(k) tmp; - bool (*bad)(struct btree_keys *, const struct bkey *) = remove_stale - ? bch_ptr_bad - : bch_ptr_invalid; -- const struct min_heap_callbacks callbacks = { -- .less = b->ops->sort_cmp, -- .swp = NULL, -- }; - - /* Heapify the iterator, using our comparison function */ -- min_heapify_all(&iter->heap, &callbacks, NULL); -+ for (i = iter->used / 2 - 1; i >= 0; --i) -+ heap_sift(iter, i, b->ops->sort_cmp); - - while (!btree_iter_end(iter)) { - if (b->ops->sort_fixup && fixup) -@@ -1316,11 +1293,10 @@ void bch_btree_sort_partial(struct btree - struct bset_sort_state *state) - { - size_t order = b->page_order, keys = 0; -- struct btree_iter iter; -+ struct btree_iter_stack iter; - int oldsize = bch_count_data(b); - -- min_heap_init(&iter.heap, NULL, MAX_BSETS); -- __bch_btree_iter_init(b, &iter, NULL, &b->set[start]); -+ __bch_btree_iter_stack_init(b, &iter, NULL, &b->set[start]); - - if (start) { - unsigned int i; -@@ -1331,7 +1307,7 @@ void bch_btree_sort_partial(struct btree - order = get_order(__set_bytes(b->set->data, keys)); - } - -- __btree_sort(b, &iter, start, order, false, state); -+ __btree_sort(b, &iter.iter, start, order, false, state); - - EBUG_ON(oldsize >= 0 && bch_count_data(b) != oldsize); - } -@@ -1347,13 +1323,11 @@ void bch_btree_sort_into(struct btree_ke - struct bset_sort_state *state) - { - uint64_t start_time = local_clock(); -- struct btree_iter iter; -- -- min_heap_init(&iter.heap, NULL, MAX_BSETS); -+ struct btree_iter_stack iter; - -- bch_btree_iter_init(b, &iter, NULL); -+ bch_btree_iter_stack_init(b, &iter, NULL); - -- btree_mergesort(b, new->set->data, &iter, false, true); -+ btree_mergesort(b, new->set->data, &iter.iter, false, true); - - bch_time_stats_update(&state->time, start_time); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/bcache/bset.h BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/bset.h ---- BPI-Router-Linux-kernel/drivers/md/bcache/bset.h 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/bset.h 2025-10-22 13:53:56.523169103 -0400 -@@ -187,9 +187,8 @@ struct bset_tree { - }; - - struct btree_keys_ops { -- bool (*sort_cmp)(const void *l, -- const void *r, -- void *args); -+ bool (*sort_cmp)(struct btree_iter_set l, -+ struct btree_iter_set r); - struct bkey *(*sort_fixup)(struct btree_iter *iter, - struct bkey *tmp); - bool (*insert_fixup)(struct btree_keys *b, -@@ -313,17 +312,23 @@ enum { - BTREE_INSERT_STATUS_FRONT_MERGE, - }; - --struct btree_iter_set { -- struct bkey *k, *end; --}; -- - /* Btree key iteration */ - - struct btree_iter { -+ size_t size, used; - #ifdef CONFIG_BCACHE_DEBUG - struct btree_keys *b; - #endif -- MIN_HEAP_PREALLOCATED(struct btree_iter_set, btree_iter_heap, MAX_BSETS) heap; -+ struct btree_iter_set { -+ struct bkey *k, *end; -+ } data[]; -+}; -+ -+/* Fixed-size btree_iter that can be allocated on the stack */ -+ -+struct btree_iter_stack { -+ struct btree_iter iter; -+ struct btree_iter_set stack_data[MAX_BSETS]; - }; - - typedef bool (*ptr_filter_fn)(struct btree_keys *b, const struct bkey *k); -@@ -335,9 +340,9 @@ struct bkey *bch_btree_iter_next_filter( - - void bch_btree_iter_push(struct btree_iter *iter, struct bkey *k, - struct bkey *end); --struct bkey *bch_btree_iter_init(struct btree_keys *b, -- struct btree_iter *iter, -- struct bkey *search); -+struct bkey *bch_btree_iter_stack_init(struct btree_keys *b, -+ struct btree_iter_stack *iter, -+ struct bkey *search); - - struct bkey *__bch_bset_search(struct btree_keys *b, struct bset_tree *t, - const struct bkey *search); -@@ -352,13 +357,14 @@ static inline struct bkey *bch_bset_sear - return search ? __bch_bset_search(b, t, search) : t->data->start; - } - --#define for_each_key_filter(b, k, iter, filter) \ -- for (bch_btree_iter_init((b), (iter), NULL); \ -- ((k) = bch_btree_iter_next_filter((iter), (b), filter));) -- --#define for_each_key(b, k, iter) \ -- for (bch_btree_iter_init((b), (iter), NULL); \ -- ((k) = bch_btree_iter_next(iter));) -+#define for_each_key_filter(b, k, stack_iter, filter) \ -+ for (bch_btree_iter_stack_init((b), (stack_iter), NULL); \ -+ ((k) = bch_btree_iter_next_filter(&((stack_iter)->iter), (b), \ -+ filter));) -+ -+#define for_each_key(b, k, stack_iter) \ -+ for (bch_btree_iter_stack_init((b), (stack_iter), NULL); \ -+ ((k) = bch_btree_iter_next(&((stack_iter)->iter)));) - - /* Sorting */ - -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/bcache/btree.c BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/btree.c ---- BPI-Router-Linux-kernel/drivers/md/bcache/btree.c 2025-10-22 13:53:23.291328761 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/btree.c 2025-10-22 13:53:56.523169103 -0400 -@@ -148,19 +148,19 @@ void bch_btree_node_read_done(struct btr - { - const char *err = "bad btree header"; - struct bset *i = btree_bset_first(b); -- struct btree_iter iter; -+ struct btree_iter *iter; - - /* - * c->fill_iter can allocate an iterator with more memory space - * than static MAX_BSETS. - * See the comment arount cache_set->fill_iter. - */ -- iter.heap.data = mempool_alloc(&b->c->fill_iter, GFP_NOIO); -- iter.heap.size = b->c->cache->sb.bucket_size / b->c->cache->sb.block_size; -- iter.heap.nr = 0; -+ iter = mempool_alloc(&b->c->fill_iter, GFP_NOIO); -+ iter->size = b->c->cache->sb.bucket_size / b->c->cache->sb.block_size; -+ iter->used = 0; - - #ifdef CONFIG_BCACHE_DEBUG -- iter.b = &b->keys; -+ iter->b = &b->keys; - #endif - - if (!i->seq) -@@ -198,7 +198,7 @@ void bch_btree_node_read_done(struct btr - if (i != b->keys.set[0].data && !i->keys) - goto err; - -- bch_btree_iter_push(&iter, i->start, bset_bkey_last(i)); -+ bch_btree_iter_push(iter, i->start, bset_bkey_last(i)); - - b->written += set_blocks(i, block_bytes(b->c->cache)); - } -@@ -210,7 +210,7 @@ void bch_btree_node_read_done(struct btr - if (i->seq == b->keys.set[0].data->seq) - goto err; - -- bch_btree_sort_and_fix_extents(&b->keys, &iter, &b->c->sort); -+ bch_btree_sort_and_fix_extents(&b->keys, iter, &b->c->sort); - - i = b->keys.set[0].data; - err = "short btree key"; -@@ -222,7 +222,7 @@ void bch_btree_node_read_done(struct btr - bch_bset_init_next(&b->keys, write_block(b), - bset_magic(&b->c->cache->sb)); - out: -- mempool_free(iter.heap.data, &b->c->fill_iter); -+ mempool_free(iter, &b->c->fill_iter); - return; - err: - set_btree_node_io_error(b); -@@ -1306,11 +1306,9 @@ static bool btree_gc_mark_node(struct bt - uint8_t stale = 0; - unsigned int keys = 0, good_keys = 0; - struct bkey *k; -- struct btree_iter iter; -+ struct btree_iter_stack iter; - struct bset_tree *t; - -- min_heap_init(&iter.heap, NULL, MAX_BSETS); -- - gc->nodes++; - - for_each_key_filter(&b->keys, k, &iter, bch_ptr_invalid) { -@@ -1569,11 +1567,9 @@ static int btree_gc_rewrite_node(struct - static unsigned int btree_gc_count_keys(struct btree *b) - { - struct bkey *k; -- struct btree_iter iter; -+ struct btree_iter_stack iter; - unsigned int ret = 0; - -- min_heap_init(&iter.heap, NULL, MAX_BSETS); -- - for_each_key_filter(&b->keys, k, &iter, bch_ptr_bad) - ret += bkey_u64s(k); - -@@ -1612,18 +1608,18 @@ static int btree_gc_recurse(struct btree - int ret = 0; - bool should_rewrite; - struct bkey *k; -- struct btree_iter iter; -+ struct btree_iter_stack iter; - struct gc_merge_info r[GC_MERGE_NODES]; - struct gc_merge_info *i, *last = r + ARRAY_SIZE(r) - 1; - -- min_heap_init(&iter.heap, NULL, MAX_BSETS); -- bch_btree_iter_init(&b->keys, &iter, &b->c->gc_done); -+ bch_btree_iter_stack_init(&b->keys, &iter, &b->c->gc_done); - - for (i = r; i < r + ARRAY_SIZE(r); i++) - i->b = ERR_PTR(-EINTR); - - while (1) { -- k = bch_btree_iter_next_filter(&iter, &b->keys, bch_ptr_bad); -+ k = bch_btree_iter_next_filter(&iter.iter, &b->keys, -+ bch_ptr_bad); - if (k) { - r->b = bch_btree_node_get(b->c, op, k, b->level - 1, - true, b); -@@ -1918,9 +1914,7 @@ static int bch_btree_check_recurse(struc - { - int ret = 0; - struct bkey *k, *p = NULL; -- struct btree_iter iter; -- -- min_heap_init(&iter.heap, NULL, MAX_BSETS); -+ struct btree_iter_stack iter; - - for_each_key_filter(&b->keys, k, &iter, bch_ptr_invalid) - bch_initial_mark_key(b->c, b->level, k); -@@ -1928,10 +1922,10 @@ static int bch_btree_check_recurse(struc - bch_initial_mark_key(b->c, b->level + 1, &b->key); - - if (b->level) { -- bch_btree_iter_init(&b->keys, &iter, NULL); -+ bch_btree_iter_stack_init(&b->keys, &iter, NULL); - - do { -- k = bch_btree_iter_next_filter(&iter, &b->keys, -+ k = bch_btree_iter_next_filter(&iter.iter, &b->keys, - bch_ptr_bad); - if (k) { - btree_node_prefetch(b, k); -@@ -1959,7 +1953,7 @@ static int bch_btree_check_thread(void * - struct btree_check_info *info = arg; - struct btree_check_state *check_state = info->state; - struct cache_set *c = check_state->c; -- struct btree_iter iter; -+ struct btree_iter_stack iter; - struct bkey *k, *p; - int cur_idx, prev_idx, skip_nr; - -@@ -1967,11 +1961,9 @@ static int bch_btree_check_thread(void * - cur_idx = prev_idx = 0; - ret = 0; - -- min_heap_init(&iter.heap, NULL, MAX_BSETS); -- - /* root node keys are checked before thread created */ -- bch_btree_iter_init(&c->root->keys, &iter, NULL); -- k = bch_btree_iter_next_filter(&iter, &c->root->keys, bch_ptr_bad); -+ bch_btree_iter_stack_init(&c->root->keys, &iter, NULL); -+ k = bch_btree_iter_next_filter(&iter.iter, &c->root->keys, bch_ptr_bad); - BUG_ON(!k); - - p = k; -@@ -1989,7 +1981,7 @@ static int bch_btree_check_thread(void * - skip_nr = cur_idx - prev_idx; - - while (skip_nr) { -- k = bch_btree_iter_next_filter(&iter, -+ k = bch_btree_iter_next_filter(&iter.iter, - &c->root->keys, - bch_ptr_bad); - if (k) -@@ -2062,11 +2054,9 @@ int bch_btree_check(struct cache_set *c) - int ret = 0; - int i; - struct bkey *k = NULL; -- struct btree_iter iter; -+ struct btree_iter_stack iter; - struct btree_check_state check_state; - -- min_heap_init(&iter.heap, NULL, MAX_BSETS); -- - /* check and mark root node keys */ - for_each_key_filter(&c->root->keys, k, &iter, bch_ptr_invalid) - bch_initial_mark_key(c, c->root->level, k); -@@ -2560,12 +2550,11 @@ static int bch_btree_map_nodes_recurse(s - - if (b->level) { - struct bkey *k; -- struct btree_iter iter; -+ struct btree_iter_stack iter; - -- min_heap_init(&iter.heap, NULL, MAX_BSETS); -- bch_btree_iter_init(&b->keys, &iter, from); -+ bch_btree_iter_stack_init(&b->keys, &iter, from); - -- while ((k = bch_btree_iter_next_filter(&iter, &b->keys, -+ while ((k = bch_btree_iter_next_filter(&iter.iter, &b->keys, - bch_ptr_bad))) { - ret = bcache_btree(map_nodes_recurse, k, b, - op, from, fn, flags); -@@ -2594,12 +2583,12 @@ int bch_btree_map_keys_recurse(struct bt - { - int ret = MAP_CONTINUE; - struct bkey *k; -- struct btree_iter iter; -+ struct btree_iter_stack iter; - -- min_heap_init(&iter.heap, NULL, MAX_BSETS); -- bch_btree_iter_init(&b->keys, &iter, from); -+ bch_btree_iter_stack_init(&b->keys, &iter, from); - -- while ((k = bch_btree_iter_next_filter(&iter, &b->keys, bch_ptr_bad))) { -+ while ((k = bch_btree_iter_next_filter(&iter.iter, &b->keys, -+ bch_ptr_bad))) { - ret = !b->level - ? fn(op, b, k) - : bcache_btree(map_keys_recurse, k, -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/bcache/extents.c BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/extents.c ---- BPI-Router-Linux-kernel/drivers/md/bcache/extents.c 2025-10-22 13:53:23.291328761 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/extents.c 2025-10-22 13:53:56.523169103 -0400 -@@ -33,16 +33,15 @@ static void sort_key_next(struct btree_i - i->k = bkey_next(i->k); - - if (i->k == i->end) -- *i = iter->heap.data[--iter->heap.nr]; -+ *i = iter->data[--iter->used]; - } - --static bool new_bch_key_sort_cmp(const void *l, const void *r, void *args) -+static bool bch_key_sort_cmp(struct btree_iter_set l, -+ struct btree_iter_set r) - { -- struct btree_iter_set *_l = (struct btree_iter_set *)l; -- struct btree_iter_set *_r = (struct btree_iter_set *)r; -- int64_t c = bkey_cmp(_l->k, _r->k); -+ int64_t c = bkey_cmp(l.k, r.k); - -- return !(c ? c > 0 : _l->k < _r->k); -+ return c ? c > 0 : l.k < r.k; - } - - static bool __ptr_invalid(struct cache_set *c, const struct bkey *k) -@@ -239,7 +238,7 @@ static bool bch_btree_ptr_insert_fixup(s - } - - const struct btree_keys_ops bch_btree_keys_ops = { -- .sort_cmp = new_bch_key_sort_cmp, -+ .sort_cmp = bch_key_sort_cmp, - .insert_fixup = bch_btree_ptr_insert_fixup, - .key_invalid = bch_btree_ptr_invalid, - .key_bad = bch_btree_ptr_bad, -@@ -256,28 +255,22 @@ const struct btree_keys_ops bch_btree_ke - * Necessary for btree_sort_fixup() - if there are multiple keys that compare - * equal in different sets, we have to process them newest to oldest. - */ -- --static bool new_bch_extent_sort_cmp(const void *l, const void *r, void __always_unused *args) -+static bool bch_extent_sort_cmp(struct btree_iter_set l, -+ struct btree_iter_set r) - { -- struct btree_iter_set *_l = (struct btree_iter_set *)l; -- struct btree_iter_set *_r = (struct btree_iter_set *)r; -- int64_t c = bkey_cmp(&START_KEY(_l->k), &START_KEY(_r->k)); -+ int64_t c = bkey_cmp(&START_KEY(l.k), &START_KEY(r.k)); - -- return !(c ? c > 0 : _l->k < _r->k); -+ return c ? c > 0 : l.k < r.k; - } - - static struct bkey *bch_extent_sort_fixup(struct btree_iter *iter, - struct bkey *tmp) - { -- const struct min_heap_callbacks callbacks = { -- .less = new_bch_extent_sort_cmp, -- .swp = NULL, -- }; -- while (iter->heap.nr > 1) { -- struct btree_iter_set *top = iter->heap.data, *i = top + 1; -+ while (iter->used > 1) { -+ struct btree_iter_set *top = iter->data, *i = top + 1; - -- if (iter->heap.nr > 2 && -- !new_bch_extent_sort_cmp(&i[0], &i[1], NULL)) -+ if (iter->used > 2 && -+ bch_extent_sort_cmp(i[0], i[1])) - i++; - - if (bkey_cmp(top->k, &START_KEY(i->k)) <= 0) -@@ -285,7 +278,7 @@ static struct bkey *bch_extent_sort_fixu - - if (!KEY_SIZE(i->k)) { - sort_key_next(iter, i); -- min_heap_sift_down(&iter->heap, i - top, &callbacks, NULL); -+ heap_sift(iter, i - top, bch_extent_sort_cmp); - continue; - } - -@@ -295,7 +288,7 @@ static struct bkey *bch_extent_sort_fixu - else - bch_cut_front(top->k, i->k); - -- min_heap_sift_down(&iter->heap, i - top, &callbacks, NULL); -+ heap_sift(iter, i - top, bch_extent_sort_cmp); - } else { - /* can't happen because of comparison func */ - BUG_ON(!bkey_cmp(&START_KEY(top->k), &START_KEY(i->k))); -@@ -305,7 +298,7 @@ static struct bkey *bch_extent_sort_fixu - - bch_cut_back(&START_KEY(i->k), tmp); - bch_cut_front(i->k, top->k); -- min_heap_sift_down(&iter->heap, 0, &callbacks, NULL); -+ heap_sift(iter, 0, bch_extent_sort_cmp); - - return tmp; - } else { -@@ -625,7 +618,7 @@ static bool bch_extent_merge(struct btre - } - - const struct btree_keys_ops bch_extent_keys_ops = { -- .sort_cmp = new_bch_extent_sort_cmp, -+ .sort_cmp = bch_extent_sort_cmp, - .sort_fixup = bch_extent_sort_fixup, - .insert_fixup = bch_extent_insert_fixup, - .key_invalid = bch_extent_invalid, -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/bcache/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/Kconfig ---- BPI-Router-Linux-kernel/drivers/md/bcache/Kconfig 2025-10-22 13:53:23.287328781 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/Kconfig 2025-10-22 13:53:56.519169122 -0400 -@@ -5,7 +5,6 @@ config BCACHE - select BLOCK_HOLDER_DEPRECATED if SYSFS - select CRC64 - select CLOSURES -- select MIN_HEAP - help - Allows a block device to be used as cache for other devices; uses - a btree for indexing and the layout is optimized for SSDs. -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/bcache/movinggc.c BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/movinggc.c ---- BPI-Router-Linux-kernel/drivers/md/bcache/movinggc.c 2025-10-22 13:53:23.291328761 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/movinggc.c 2025-10-22 13:53:56.523169103 -0400 -@@ -182,19 +182,16 @@ err: if (!IS_ERR_OR_NULL(w->private)) - closure_sync(&cl); - } - --static bool new_bucket_cmp(const void *l, const void *r, void __always_unused *args) -+static bool bucket_cmp(struct bucket *l, struct bucket *r) - { -- struct bucket **_l = (struct bucket **)l; -- struct bucket **_r = (struct bucket **)r; -- -- return GC_SECTORS_USED(*_l) >= GC_SECTORS_USED(*_r); -+ return GC_SECTORS_USED(l) < GC_SECTORS_USED(r); - } - - static unsigned int bucket_heap_top(struct cache *ca) - { - struct bucket *b; - -- return (b = min_heap_peek(&ca->heap)[0]) ? GC_SECTORS_USED(b) : 0; -+ return (b = heap_peek(&ca->heap)) ? GC_SECTORS_USED(b) : 0; - } - - void bch_moving_gc(struct cache_set *c) -@@ -202,10 +199,6 @@ void bch_moving_gc(struct cache_set *c) - struct cache *ca = c->cache; - struct bucket *b; - unsigned long sectors_to_move, reserve_sectors; -- const struct min_heap_callbacks callbacks = { -- .less = new_bucket_cmp, -- .swp = NULL, -- }; - - if (!c->copy_gc_enabled) - return; -@@ -216,7 +209,7 @@ void bch_moving_gc(struct cache_set *c) - reserve_sectors = ca->sb.bucket_size * - fifo_used(&ca->free[RESERVE_MOVINGGC]); - -- ca->heap.nr = 0; -+ ca->heap.used = 0; - - for_each_bucket(b, ca) { - if (GC_MARK(b) == GC_MARK_METADATA || -@@ -225,31 +218,25 @@ void bch_moving_gc(struct cache_set *c) - atomic_read(&b->pin)) - continue; - -- if (!min_heap_full(&ca->heap)) { -+ if (!heap_full(&ca->heap)) { - sectors_to_move += GC_SECTORS_USED(b); -- min_heap_push(&ca->heap, &b, &callbacks, NULL); -- } else if (!new_bucket_cmp(&b, min_heap_peek(&ca->heap), ca)) { -+ heap_add(&ca->heap, b, bucket_cmp); -+ } else if (bucket_cmp(b, heap_peek(&ca->heap))) { - sectors_to_move -= bucket_heap_top(ca); - sectors_to_move += GC_SECTORS_USED(b); - - ca->heap.data[0] = b; -- min_heap_sift_down(&ca->heap, 0, &callbacks, NULL); -+ heap_sift(&ca->heap, 0, bucket_cmp); - } - } - - while (sectors_to_move > reserve_sectors) { -- if (ca->heap.nr) { -- b = min_heap_peek(&ca->heap)[0]; -- min_heap_pop(&ca->heap, &callbacks, NULL); -- } -+ heap_pop(&ca->heap, b, bucket_cmp); - sectors_to_move -= GC_SECTORS_USED(b); - } - -- while (ca->heap.nr) { -- b = min_heap_peek(&ca->heap)[0]; -- min_heap_pop(&ca->heap, &callbacks, NULL); -+ while (heap_pop(&ca->heap, b, bucket_cmp)) - SET_GC_MOVE(b, 1); -- } - - mutex_unlock(&c->bucket_lock); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/bcache/super.c BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/super.c ---- BPI-Router-Linux-kernel/drivers/md/bcache/super.c 2025-10-22 13:53:23.291328761 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/super.c 2025-10-22 13:53:56.523169103 -0400 -@@ -1912,7 +1912,8 @@ struct cache_set *bch_cache_set_alloc(st - INIT_LIST_HEAD(&c->btree_cache_freed); - INIT_LIST_HEAD(&c->data_buckets); - -- iter_size = ((meta_bucket_pages(sb) * PAGE_SECTORS) / sb->block_size) * -+ iter_size = sizeof(struct btree_iter) + -+ ((meta_bucket_pages(sb) * PAGE_SECTORS) / sb->block_size) * - sizeof(struct btree_iter_set); - - c->devices = kcalloc(c->nr_uuids, sizeof(void *), GFP_KERNEL); -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/bcache/sysfs.c BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/sysfs.c ---- BPI-Router-Linux-kernel/drivers/md/bcache/sysfs.c 2025-10-22 13:53:23.291328761 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/sysfs.c 2025-10-22 13:53:56.523169103 -0400 -@@ -660,9 +660,7 @@ static unsigned int bch_root_usage(struc - unsigned int bytes = 0; - struct bkey *k; - struct btree *b; -- struct btree_iter iter; -- -- min_heap_init(&iter.heap, NULL, MAX_BSETS); -+ struct btree_iter_stack iter; - - goto lock_root; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/bcache/util.h BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/util.h ---- BPI-Router-Linux-kernel/drivers/md/bcache/util.h 2025-10-22 13:53:23.291328761 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/util.h 2025-10-22 13:53:56.523169103 -0400 -@@ -9,7 +9,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -31,10 +30,16 @@ struct closure; - - #endif - -+#define DECLARE_HEAP(type, name) \ -+ struct { \ -+ size_t size, used; \ -+ type *data; \ -+ } name -+ - #define init_heap(heap, _size, gfp) \ - ({ \ - size_t _bytes; \ -- (heap)->nr = 0; \ -+ (heap)->used = 0; \ - (heap)->size = (_size); \ - _bytes = (heap)->size * sizeof(*(heap)->data); \ - (heap)->data = kvmalloc(_bytes, (gfp) & GFP_KERNEL); \ -@@ -47,6 +52,64 @@ do { \ - (heap)->data = NULL; \ - } while (0) - -+#define heap_swap(h, i, j) swap((h)->data[i], (h)->data[j]) -+ -+#define heap_sift(h, i, cmp) \ -+do { \ -+ size_t _r, _j = i; \ -+ \ -+ for (; _j * 2 + 1 < (h)->used; _j = _r) { \ -+ _r = _j * 2 + 1; \ -+ if (_r + 1 < (h)->used && \ -+ cmp((h)->data[_r], (h)->data[_r + 1])) \ -+ _r++; \ -+ \ -+ if (cmp((h)->data[_r], (h)->data[_j])) \ -+ break; \ -+ heap_swap(h, _r, _j); \ -+ } \ -+} while (0) -+ -+#define heap_sift_down(h, i, cmp) \ -+do { \ -+ while (i) { \ -+ size_t p = (i - 1) / 2; \ -+ if (cmp((h)->data[i], (h)->data[p])) \ -+ break; \ -+ heap_swap(h, i, p); \ -+ i = p; \ -+ } \ -+} while (0) -+ -+#define heap_add(h, d, cmp) \ -+({ \ -+ bool _r = !heap_full(h); \ -+ if (_r) { \ -+ size_t _i = (h)->used++; \ -+ (h)->data[_i] = d; \ -+ \ -+ heap_sift_down(h, _i, cmp); \ -+ heap_sift(h, _i, cmp); \ -+ } \ -+ _r; \ -+}) -+ -+#define heap_pop(h, d, cmp) \ -+({ \ -+ bool _r = (h)->used; \ -+ if (_r) { \ -+ (d) = (h)->data[0]; \ -+ (h)->used--; \ -+ heap_swap(h, 0, (h)->used); \ -+ heap_sift(h, 0, cmp); \ -+ } \ -+ _r; \ -+}) -+ -+#define heap_peek(h) ((h)->used ? (h)->data[0] : NULL) -+ -+#define heap_full(h) ((h)->used == (h)->size) -+ - #define DECLARE_FIFO(type, name) \ - struct { \ - size_t front, back, size, mask; \ -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/bcache/writeback.c BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/writeback.c ---- BPI-Router-Linux-kernel/drivers/md/bcache/writeback.c 2025-10-22 13:53:23.291328761 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/bcache/writeback.c 2025-10-22 13:53:56.523169103 -0400 -@@ -908,16 +908,15 @@ static int bch_dirty_init_thread(void *a - struct dirty_init_thrd_info *info = arg; - struct bch_dirty_init_state *state = info->state; - struct cache_set *c = state->c; -- struct btree_iter iter; -+ struct btree_iter_stack iter; - struct bkey *k, *p; - int cur_idx, prev_idx, skip_nr; - - k = p = NULL; - prev_idx = 0; - -- min_heap_init(&iter.heap, NULL, MAX_BSETS); -- bch_btree_iter_init(&c->root->keys, &iter, NULL); -- k = bch_btree_iter_next_filter(&iter, &c->root->keys, bch_ptr_bad); -+ bch_btree_iter_stack_init(&c->root->keys, &iter, NULL); -+ k = bch_btree_iter_next_filter(&iter.iter, &c->root->keys, bch_ptr_bad); - BUG_ON(!k); - - p = k; -@@ -931,7 +930,7 @@ static int bch_dirty_init_thread(void *a - skip_nr = cur_idx - prev_idx; - - while (skip_nr) { -- k = bch_btree_iter_next_filter(&iter, -+ k = bch_btree_iter_next_filter(&iter.iter, - &c->root->keys, - bch_ptr_bad); - if (k) -@@ -980,13 +979,11 @@ void bch_sectors_dirty_init(struct bcach - int i; - struct btree *b = NULL; - struct bkey *k = NULL; -- struct btree_iter iter; -+ struct btree_iter_stack iter; - struct sectors_dirty_init op; - struct cache_set *c = d->c; - struct bch_dirty_init_state state; - -- min_heap_init(&iter.heap, NULL, MAX_BSETS); -- - retry_lock: - b = c->root; - rw_lock(0, b, b->level); -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/dm-bufio.c BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-bufio.c ---- BPI-Router-Linux-kernel/drivers/md/dm-bufio.c 2025-10-22 13:53:23.291328761 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-bufio.c 2025-10-22 13:53:56.523169103 -0400 -@@ -2742,7 +2742,11 @@ static unsigned long __evict_a_few(unsig - __make_buffer_clean(b); - __free_buffer_wake(b); - -- cond_resched(); -+ if (need_resched()) { -+ dm_bufio_unlock(c); -+ cond_resched(); -+ dm_bufio_lock(c); -+ } - } - - dm_bufio_unlock(c); -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/dm.c BPI-Router-Linux-kernel-6.16.12/drivers/md/dm.c ---- BPI-Router-Linux-kernel/drivers/md/dm.c 2025-10-22 13:53:23.291328761 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/dm.c 2025-10-22 13:53:56.523169103 -0400 -@@ -1293,8 +1293,9 @@ out: - /* - * A target may call dm_accept_partial_bio only from the map routine. It is - * allowed for all bio types except REQ_PREFLUSH, REQ_OP_ZONE_* zone management -- * operations, REQ_OP_ZONE_APPEND (zone append writes) and any bio serviced by -- * __send_duplicate_bios(). -+ * operations, zone append writes (native with REQ_OP_ZONE_APPEND or emulated -+ * with write BIOs flagged with BIO_EMULATES_ZONE_APPEND) and any bio serviced -+ * by __send_duplicate_bios(). - * - * dm_accept_partial_bio informs the dm that the target only wants to process - * additional n_sectors sectors of the bio and the rest of the data should be -@@ -1327,11 +1328,19 @@ void dm_accept_partial_bio(struct bio *b - unsigned int bio_sectors = bio_sectors(bio); - - BUG_ON(dm_tio_flagged(tio, DM_TIO_IS_DUPLICATE_BIO)); -- BUG_ON(op_is_zone_mgmt(bio_op(bio))); -- BUG_ON(bio_op(bio) == REQ_OP_ZONE_APPEND); - BUG_ON(bio_sectors > *tio->len_ptr); - BUG_ON(n_sectors > bio_sectors); - -+ if (static_branch_unlikely(&zoned_enabled) && -+ unlikely(bdev_is_zoned(bio->bi_bdev))) { -+ enum req_op op = bio_op(bio); -+ -+ BUG_ON(op_is_zone_mgmt(op)); -+ BUG_ON(op == REQ_OP_WRITE); -+ BUG_ON(op == REQ_OP_WRITE_ZEROES); -+ BUG_ON(op == REQ_OP_ZONE_APPEND); -+ } -+ - *tio->len_ptr -= bio_sectors - n_sectors; - bio->bi_iter.bi_size = n_sectors << SECTOR_SHIFT; - -@@ -1776,19 +1785,35 @@ static void init_clone_info(struct clone - } - - #ifdef CONFIG_BLK_DEV_ZONED --static inline bool dm_zone_bio_needs_split(struct mapped_device *md, -- struct bio *bio) -+static inline bool dm_zone_bio_needs_split(struct bio *bio) - { - /* -- * For mapped device that need zone append emulation, we must -- * split any large BIO that straddles zone boundaries. -+ * Special case the zone operations that cannot or should not be split. - */ -- return dm_emulate_zone_append(md) && bio_straddles_zones(bio) && -- !bio_flagged(bio, BIO_ZONE_WRITE_PLUGGING); -+ switch (bio_op(bio)) { -+ case REQ_OP_ZONE_APPEND: -+ case REQ_OP_ZONE_FINISH: -+ case REQ_OP_ZONE_RESET: -+ case REQ_OP_ZONE_RESET_ALL: -+ return false; -+ default: -+ break; -+ } -+ -+ /* -+ * When mapped devices use the block layer zone write plugging, we must -+ * split any large BIO to the mapped device limits to not submit BIOs -+ * that span zone boundaries and to avoid potential deadlocks with -+ * queue freeze operations. -+ */ -+ return bio_needs_zone_write_plugging(bio) || bio_straddles_zones(bio); - } -+ - static inline bool dm_zone_plug_bio(struct mapped_device *md, struct bio *bio) - { -- return dm_emulate_zone_append(md) && blk_zone_plug_bio(bio, 0); -+ if (!bio_needs_zone_write_plugging(bio)) -+ return false; -+ return blk_zone_plug_bio(bio, 0); - } - - static blk_status_t __send_zone_reset_all_emulated(struct clone_info *ci, -@@ -1904,8 +1929,7 @@ static blk_status_t __send_zone_reset_al - } - - #else --static inline bool dm_zone_bio_needs_split(struct mapped_device *md, -- struct bio *bio) -+static inline bool dm_zone_bio_needs_split(struct bio *bio) - { - return false; - } -@@ -1932,9 +1956,7 @@ static void dm_split_and_process_bio(str - - is_abnormal = is_abnormal_io(bio); - if (static_branch_unlikely(&zoned_enabled)) { -- /* Special case REQ_OP_ZONE_RESET_ALL as it cannot be split. */ -- need_split = (bio_op(bio) != REQ_OP_ZONE_RESET_ALL) && -- (is_abnormal || dm_zone_bio_needs_split(md, bio)); -+ need_split = is_abnormal || dm_zone_bio_needs_split(bio); - } else { - need_split = is_abnormal; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/dm-crypt.c BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-crypt.c ---- BPI-Router-Linux-kernel/drivers/md/dm-crypt.c 2025-10-22 13:53:23.291328761 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-crypt.c 2025-10-22 13:53:56.523169103 -0400 -@@ -253,17 +253,35 @@ MODULE_PARM_DESC(max_read_size, "Maximum - static unsigned int max_write_size = 0; - module_param(max_write_size, uint, 0644); - MODULE_PARM_DESC(max_write_size, "Maximum size of a write request"); --static unsigned get_max_request_size(struct crypt_config *cc, bool wrt) -+ -+static unsigned get_max_request_sectors(struct dm_target *ti, struct bio *bio) - { -+ struct crypt_config *cc = ti->private; - unsigned val, sector_align; -- val = !wrt ? READ_ONCE(max_read_size) : READ_ONCE(max_write_size); -- if (likely(!val)) -- val = !wrt ? DM_CRYPT_DEFAULT_MAX_READ_SIZE : DM_CRYPT_DEFAULT_MAX_WRITE_SIZE; -- if (wrt || cc->used_tag_size) { -- if (unlikely(val > BIO_MAX_VECS << PAGE_SHIFT)) -- val = BIO_MAX_VECS << PAGE_SHIFT; -+ bool wrt = op_is_write(bio_op(bio)); -+ -+ if (wrt) { -+ /* -+ * For zoned devices, splitting write operations creates the -+ * risk of deadlocking queue freeze operations with zone write -+ * plugging BIO work when the reminder of a split BIO is -+ * issued. So always allow the entire BIO to proceed. -+ */ -+ if (ti->emulate_zone_append) -+ return bio_sectors(bio); -+ -+ val = min_not_zero(READ_ONCE(max_write_size), -+ DM_CRYPT_DEFAULT_MAX_WRITE_SIZE); -+ } else { -+ val = min_not_zero(READ_ONCE(max_read_size), -+ DM_CRYPT_DEFAULT_MAX_READ_SIZE); - } -- sector_align = max(bdev_logical_block_size(cc->dev->bdev), (unsigned)cc->sector_size); -+ -+ if (wrt || cc->used_tag_size) -+ val = min(val, BIO_MAX_VECS << PAGE_SHIFT); -+ -+ sector_align = max(bdev_logical_block_size(cc->dev->bdev), -+ (unsigned)cc->sector_size); - val = round_down(val, sector_align); - if (unlikely(!val)) - val = sector_align; -@@ -517,7 +535,10 @@ static int crypt_iv_lmk_one(struct crypt - { - struct iv_lmk_private *lmk = &cc->iv_gen_private.lmk; - SHASH_DESC_ON_STACK(desc, lmk->hash_tfm); -- struct md5_state md5state; -+ union { -+ struct md5_state md5state; -+ u8 state[CRYPTO_MD5_STATESIZE]; -+ } u; - __le32 buf[4]; - int i, r; - -@@ -548,13 +569,13 @@ static int crypt_iv_lmk_one(struct crypt - return r; - - /* No MD5 padding here */ -- r = crypto_shash_export(desc, &md5state); -+ r = crypto_shash_export(desc, &u.md5state); - if (r) - return r; - - for (i = 0; i < MD5_HASH_WORDS; i++) -- __cpu_to_le32s(&md5state.hash[i]); -- memcpy(iv, &md5state.hash, cc->iv_size); -+ __cpu_to_le32s(&u.md5state.hash[i]); -+ memcpy(iv, &u.md5state.hash, cc->iv_size); - - return 0; - } -@@ -3493,7 +3514,7 @@ static int crypt_map(struct dm_target *t - /* - * Check if bio is too large, split as needed. - */ -- max_sectors = get_max_request_size(cc, bio_data_dir(bio) == WRITE); -+ max_sectors = get_max_request_sectors(ti, bio); - if (unlikely(bio_sectors(bio) > max_sectors)) - dm_accept_partial_bio(bio, max_sectors); - -@@ -3730,6 +3751,17 @@ static void crypt_io_hints(struct dm_tar - max_t(unsigned int, limits->physical_block_size, cc->sector_size); - limits->io_min = max_t(unsigned int, limits->io_min, cc->sector_size); - limits->dma_alignment = limits->logical_block_size - 1; -+ -+ /* -+ * For zoned dm-crypt targets, there will be no internal splitting of -+ * write BIOs to avoid exceeding BIO_MAX_VECS vectors per BIO. But -+ * without respecting this limit, crypt_alloc_buffer() will trigger a -+ * BUG(). Avoid this by forcing DM core to split write BIOs to this -+ * limit. -+ */ -+ if (ti->emulate_zone_append) -+ limits->max_hw_sectors = min(limits->max_hw_sectors, -+ BIO_MAX_VECS << PAGE_SECTORS_SHIFT); - } - - static struct target_type crypt_target = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/dm-flakey.c BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-flakey.c ---- BPI-Router-Linux-kernel/drivers/md/dm-flakey.c 2025-10-22 13:53:23.291328761 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-flakey.c 2025-10-22 13:53:56.523169103 -0400 -@@ -215,16 +215,19 @@ static int parse_features(struct dm_arg_ - } - - if (test_bit(DROP_WRITES, &fc->flags) && -- (fc->corrupt_bio_rw == WRITE || fc->random_write_corrupt)) { -+ ((fc->corrupt_bio_byte && fc->corrupt_bio_rw == WRITE) || -+ fc->random_write_corrupt)) { - ti->error = "drop_writes is incompatible with random_write_corrupt or corrupt_bio_byte with the WRITE flag set"; - return -EINVAL; - - } else if (test_bit(ERROR_WRITES, &fc->flags) && -- (fc->corrupt_bio_rw == WRITE || fc->random_write_corrupt)) { -+ ((fc->corrupt_bio_byte && fc->corrupt_bio_rw == WRITE) || -+ fc->random_write_corrupt)) { - ti->error = "error_writes is incompatible with random_write_corrupt or corrupt_bio_byte with the WRITE flag set"; - return -EINVAL; - } else if (test_bit(ERROR_READS, &fc->flags) && -- (fc->corrupt_bio_rw == READ || fc->random_read_corrupt)) { -+ ((fc->corrupt_bio_byte && fc->corrupt_bio_rw == READ) || -+ fc->random_read_corrupt)) { - ti->error = "error_reads is incompatible with random_read_corrupt or corrupt_bio_byte with the READ flag set"; - return -EINVAL; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/dm-integrity.c BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-integrity.c ---- BPI-Router-Linux-kernel/drivers/md/dm-integrity.c 2025-10-22 13:53:23.291328761 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-integrity.c 2025-10-22 13:53:56.523169103 -0400 -@@ -133,7 +133,7 @@ struct journal_sector { - commit_id_t commit_id; - }; - --#define MAX_TAG_SIZE (JOURNAL_SECTOR_DATA - JOURNAL_MAC_PER_SECTOR - offsetof(struct journal_entry, last_bytes[MAX_SECTORS_PER_BLOCK])) -+#define MAX_TAG_SIZE 255 - - #define METADATA_PADDING_SECTORS 8 - -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/dm-ps-historical-service-time.c BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-ps-historical-service-time.c ---- BPI-Router-Linux-kernel/drivers/md/dm-ps-historical-service-time.c 2025-10-22 13:53:23.291328761 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-ps-historical-service-time.c 2025-10-22 13:53:56.523169103 -0400 -@@ -541,8 +541,10 @@ static int __init dm_hst_init(void) - { - int r = dm_register_path_selector(&hst_ps); - -- if (r < 0) -+ if (r < 0) { - DMERR("register failed %d", r); -+ return r; -+ } - - DMINFO("version " HST_VERSION " loaded"); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/dm-ps-queue-length.c BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-ps-queue-length.c ---- BPI-Router-Linux-kernel/drivers/md/dm-ps-queue-length.c 2025-10-22 13:53:23.291328761 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-ps-queue-length.c 2025-10-22 13:53:56.523169103 -0400 -@@ -260,8 +260,10 @@ static int __init dm_ql_init(void) - { - int r = dm_register_path_selector(&ql_ps); - -- if (r < 0) -+ if (r < 0) { - DMERR("register failed %d", r); -+ return r; -+ } - - DMINFO("version " QL_VERSION " loaded"); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/dm-ps-round-robin.c BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-ps-round-robin.c ---- BPI-Router-Linux-kernel/drivers/md/dm-ps-round-robin.c 2025-10-22 13:53:23.291328761 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-ps-round-robin.c 2025-10-22 13:53:56.523169103 -0400 -@@ -220,8 +220,10 @@ static int __init dm_rr_init(void) - { - int r = dm_register_path_selector(&rr_ps); - -- if (r < 0) -+ if (r < 0) { - DMERR("register failed %d", r); -+ return r; -+ } - - DMINFO("version " RR_VERSION " loaded"); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/dm-ps-service-time.c BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-ps-service-time.c ---- BPI-Router-Linux-kernel/drivers/md/dm-ps-service-time.c 2025-10-22 13:53:23.291328761 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-ps-service-time.c 2025-10-22 13:53:56.523169103 -0400 -@@ -341,8 +341,10 @@ static int __init dm_st_init(void) - { - int r = dm_register_path_selector(&st_ps); - -- if (r < 0) -+ if (r < 0) { - DMERR("register failed %d", r); -+ return r; -+ } - - DMINFO("version " ST_VERSION " loaded"); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/dm-raid.c BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-raid.c ---- BPI-Router-Linux-kernel/drivers/md/dm-raid.c 2025-10-22 13:53:23.291328761 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-raid.c 2025-10-22 13:53:56.523169103 -0400 -@@ -439,7 +439,7 @@ static bool rs_is_reshapable(struct raid - /* Return true, if raid set in @rs is recovering */ - static bool rs_is_recovering(struct raid_set *rs) - { -- return rs->md.recovery_cp < rs->md.dev_sectors; -+ return rs->md.resync_offset < rs->md.dev_sectors; - } - - /* Return true, if raid set in @rs is reshaping */ -@@ -769,7 +769,7 @@ static struct raid_set *raid_set_alloc(s - rs->md.layout = raid_type->algorithm; - rs->md.new_layout = rs->md.layout; - rs->md.delta_disks = 0; -- rs->md.recovery_cp = MaxSector; -+ rs->md.resync_offset = MaxSector; - - for (i = 0; i < raid_devs; i++) - md_rdev_init(&rs->dev[i].rdev); -@@ -913,7 +913,7 @@ static int parse_dev_params(struct raid_ - rs->md.external = 0; - rs->md.persistent = 1; - rs->md.major_version = 2; -- } else if (rebuild && !rs->md.recovery_cp) { -+ } else if (rebuild && !rs->md.resync_offset) { - /* - * Without metadata, we will not be able to tell if the array - * is in-sync or not - we must assume it is not. Therefore, -@@ -1696,20 +1696,20 @@ static void rs_setup_recovery(struct rai - { - /* raid0 does not recover */ - if (rs_is_raid0(rs)) -- rs->md.recovery_cp = MaxSector; -+ rs->md.resync_offset = MaxSector; - /* - * A raid6 set has to be recovered either - * completely or for the grown part to - * ensure proper parity and Q-Syndrome - */ - else if (rs_is_raid6(rs)) -- rs->md.recovery_cp = dev_sectors; -+ rs->md.resync_offset = dev_sectors; - /* - * Other raid set types may skip recovery - * depending on the 'nosync' flag. - */ - else -- rs->md.recovery_cp = test_bit(__CTR_FLAG_NOSYNC, &rs->ctr_flags) -+ rs->md.resync_offset = test_bit(__CTR_FLAG_NOSYNC, &rs->ctr_flags) - ? MaxSector : dev_sectors; - } - -@@ -2144,7 +2144,7 @@ static void super_sync(struct mddev *mdd - sb->events = cpu_to_le64(mddev->events); - - sb->disk_recovery_offset = cpu_to_le64(rdev->recovery_offset); -- sb->array_resync_offset = cpu_to_le64(mddev->recovery_cp); -+ sb->array_resync_offset = cpu_to_le64(mddev->resync_offset); - - sb->level = cpu_to_le32(mddev->level); - sb->layout = cpu_to_le32(mddev->layout); -@@ -2335,18 +2335,18 @@ static int super_init_validation(struct - } - - if (!test_bit(__CTR_FLAG_NOSYNC, &rs->ctr_flags)) -- mddev->recovery_cp = le64_to_cpu(sb->array_resync_offset); -+ mddev->resync_offset = le64_to_cpu(sb->array_resync_offset); - - /* - * During load, we set FirstUse if a new superblock was written. - * There are two reasons we might not have a superblock: - * 1) The raid set is brand new - in which case, all of the - * devices must have their In_sync bit set. Also, -- * recovery_cp must be 0, unless forced. -+ * resync_offset must be 0, unless forced. - * 2) This is a new device being added to an old raid set - * and the new device needs to be rebuilt - in which - * case the In_sync bit will /not/ be set and -- * recovery_cp must be MaxSector. -+ * resync_offset must be MaxSector. - * 3) This is/are a new device(s) being added to an old - * raid set during takeover to a higher raid level - * to provide capacity for redundancy or during reshape -@@ -2391,8 +2391,8 @@ static int super_init_validation(struct - new_devs > 1 ? "s" : ""); - return -EINVAL; - } else if (!test_bit(__CTR_FLAG_REBUILD, &rs->ctr_flags) && rs_is_recovering(rs)) { -- DMERR("'rebuild' specified while raid set is not in-sync (recovery_cp=%llu)", -- (unsigned long long) mddev->recovery_cp); -+ DMERR("'rebuild' specified while raid set is not in-sync (resync_offset=%llu)", -+ (unsigned long long) mddev->resync_offset); - return -EINVAL; - } else if (rs_is_reshaping(rs)) { - DMERR("'rebuild' specified while raid set is being reshaped (reshape_position=%llu)", -@@ -2407,7 +2407,7 @@ static int super_init_validation(struct - */ - sb_retrieve_failed_devices(sb, failed_devices); - rdev_for_each(r, mddev) { -- if (test_bit(Journal, &rdev->flags) || -+ if (test_bit(Journal, &r->flags) || - !r->sb_page) - continue; - sb2 = page_address(r->sb_page); -@@ -2697,11 +2697,11 @@ static int rs_adjust_data_offsets(struct - } - out: - /* -- * Raise recovery_cp in case data_offset != 0 to -+ * Raise resync_offset in case data_offset != 0 to - * avoid false recovery positives in the constructor. - */ -- if (rs->md.recovery_cp < rs->md.dev_sectors) -- rs->md.recovery_cp += rs->dev[0].rdev.data_offset; -+ if (rs->md.resync_offset < rs->md.dev_sectors) -+ rs->md.resync_offset += rs->dev[0].rdev.data_offset; - - /* Adjust data offsets on all rdevs but on any raid4/5/6 journal device */ - rdev_for_each(rdev, &rs->md) { -@@ -2756,7 +2756,7 @@ static int rs_setup_takeover(struct raid - } - - clear_bit(MD_ARRAY_FIRST_USE, &mddev->flags); -- mddev->recovery_cp = MaxSector; -+ mddev->resync_offset = MaxSector; - - while (d--) { - rdev = &rs->dev[d].rdev; -@@ -2764,7 +2764,7 @@ static int rs_setup_takeover(struct raid - if (test_bit(d, (void *) rs->rebuild_disks)) { - clear_bit(In_sync, &rdev->flags); - clear_bit(Faulty, &rdev->flags); -- mddev->recovery_cp = rdev->recovery_offset = 0; -+ mddev->resync_offset = rdev->recovery_offset = 0; - /* Bitmap has to be created when we do an "up" takeover */ - set_bit(MD_ARRAY_FIRST_USE, &mddev->flags); - } -@@ -3222,7 +3222,7 @@ size_check: - if (r) - goto bad; - -- rs_setup_recovery(rs, rs->md.recovery_cp < rs->md.dev_sectors ? rs->md.recovery_cp : rs->md.dev_sectors); -+ rs_setup_recovery(rs, rs->md.resync_offset < rs->md.dev_sectors ? rs->md.resync_offset : rs->md.dev_sectors); - } else { - /* This is no size change or it is shrinking, update size and record in superblocks */ - r = rs_set_dev_and_array_sectors(rs, rs->ti->len, false); -@@ -3446,7 +3446,7 @@ static sector_t rs_get_progress(struct r - - } else { - if (state == st_idle && !test_bit(MD_RECOVERY_INTR, &recovery)) -- r = mddev->recovery_cp; -+ r = mddev->resync_offset; - else - r = mddev->curr_resync_completed; - -@@ -3810,8 +3810,10 @@ static void raid_io_hints(struct dm_targ - struct raid_set *rs = ti->private; - unsigned int chunk_size_bytes = to_bytes(rs->md.chunk_sectors); - -- limits->io_min = chunk_size_bytes; -- limits->io_opt = chunk_size_bytes * mddev_data_stripes(rs); -+ if (chunk_size_bytes) { -+ limits->io_min = chunk_size_bytes; -+ limits->io_opt = chunk_size_bytes * mddev_data_stripes(rs); -+ } - } - - static void raid_presuspend(struct dm_target *ti) -@@ -4074,9 +4076,9 @@ static int raid_preresume(struct dm_targ - } - - /* Check for any resize/reshape on @rs and adjust/initiate */ -- if (mddev->recovery_cp && mddev->recovery_cp < MaxSector) { -+ if (mddev->resync_offset && mddev->resync_offset < MaxSector) { - set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery); -- mddev->resync_min = mddev->recovery_cp; -+ mddev->resync_min = mddev->resync_offset; - if (test_bit(RT_FLAG_RS_GROW, &rs->runtime_flags)) - mddev->resync_max_sectors = mddev->dev_sectors; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/dm-stripe.c BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-stripe.c ---- BPI-Router-Linux-kernel/drivers/md/dm-stripe.c 2025-10-22 13:53:23.291328761 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-stripe.c 2025-10-22 13:53:56.523169103 -0400 -@@ -456,10 +456,15 @@ static void stripe_io_hints(struct dm_ta - struct queue_limits *limits) - { - struct stripe_c *sc = ti->private; -- unsigned int chunk_size = sc->chunk_size << SECTOR_SHIFT; -+ unsigned int io_min, io_opt; - -- limits->io_min = chunk_size; -- limits->io_opt = chunk_size * sc->stripes; -+ limits->chunk_sectors = sc->chunk_size; -+ -+ if (!check_shl_overflow(sc->chunk_size, SECTOR_SHIFT, &io_min) && -+ !check_mul_overflow(io_min, sc->stripes, &io_opt)) { -+ limits->io_min = io_min; -+ limits->io_opt = io_opt; -+ } - } - - static struct target_type stripe_target = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/dm-table.c BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-table.c ---- BPI-Router-Linux-kernel/drivers/md/dm-table.c 2025-10-22 13:53:23.291328761 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-table.c 2025-10-22 13:53:56.523169103 -0400 -@@ -899,17 +899,17 @@ static bool dm_table_supports_dax(struct - return true; - } - --static int device_is_rq_stackable(struct dm_target *ti, struct dm_dev *dev, -- sector_t start, sector_t len, void *data) -+static int device_is_not_rq_stackable(struct dm_target *ti, struct dm_dev *dev, -+ sector_t start, sector_t len, void *data) - { - struct block_device *bdev = dev->bdev; - struct request_queue *q = bdev_get_queue(bdev); - - /* request-based cannot stack on partitions! */ - if (bdev_is_partition(bdev)) -- return false; -+ return true; - -- return queue_is_mq(q); -+ return !queue_is_mq(q); - } - - static int dm_table_determine_type(struct dm_table *t) -@@ -1005,7 +1005,7 @@ verify_rq_based: - - /* Non-request-stackable devices can't be used for request-based dm */ - if (!ti->type->iterate_devices || -- !ti->type->iterate_devices(ti, device_is_rq_stackable, NULL)) { -+ ti->type->iterate_devices(ti, device_is_not_rq_stackable, NULL)) { - DMERR("table load rejected: including non-request-stackable devices"); - return -EINVAL; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/dm-zoned-target.c BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-zoned-target.c ---- BPI-Router-Linux-kernel/drivers/md/dm-zoned-target.c 2025-10-22 13:53:23.291328761 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/dm-zoned-target.c 2025-10-22 13:53:56.523169103 -0400 -@@ -1062,7 +1062,7 @@ static int dmz_iterate_devices(struct dm - struct dmz_target *dmz = ti->private; - unsigned int zone_nr_sectors = dmz_zone_nr_sectors(dmz->metadata); - sector_t capacity; -- int i, r; -+ int i, r = 0; - - for (i = 0; i < dmz->nr_ddevs; i++) { - capacity = dmz->dev[i].capacity & ~(zone_nr_sectors - 1); -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/md-bitmap.c BPI-Router-Linux-kernel-6.16.12/drivers/md/md-bitmap.c ---- BPI-Router-Linux-kernel/drivers/md/md-bitmap.c 2025-10-22 13:53:23.291328761 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/md-bitmap.c 2025-10-22 13:53:56.523169103 -0400 -@@ -1987,12 +1987,12 @@ static void bitmap_dirty_bits(struct mdd - - md_bitmap_set_memory_bits(bitmap, sec, 1); - md_bitmap_file_set_bit(bitmap, sec); -- if (sec < bitmap->mddev->recovery_cp) -+ if (sec < bitmap->mddev->resync_offset) - /* We are asserting that the array is dirty, -- * so move the recovery_cp address back so -+ * so move the resync_offset address back so - * that it is obvious that it is dirty - */ -- bitmap->mddev->recovery_cp = sec; -+ bitmap->mddev->resync_offset = sec; - } - } - -@@ -2258,7 +2258,7 @@ static int bitmap_load(struct mddev *mdd - || bitmap->events_cleared == mddev->events) - /* no need to keep dirty bits to optimise a - * re-add of a missing device */ -- start = mddev->recovery_cp; -+ start = mddev->resync_offset; - - mutex_lock(&mddev->bitmap_info.mutex); - err = md_bitmap_init_from_disk(bitmap, start); -@@ -2366,8 +2366,7 @@ static int bitmap_get_stats(void *data, - - if (!bitmap) - return -ENOENT; -- if (!bitmap->mddev->bitmap_info.external && -- !bitmap->storage.sb_page) -+ if (!bitmap->storage.sb_page) - return -EINVAL; - sb = kmap_local_page(bitmap->storage.sb_page); - stats->sync_size = le64_to_cpu(sb->sync_size); -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/md.c BPI-Router-Linux-kernel-6.16.12/drivers/md/md.c ---- BPI-Router-Linux-kernel/drivers/md/md.c 2025-10-22 13:53:23.295328742 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/md.c 2025-10-22 13:53:56.527169084 -0400 -@@ -1402,13 +1402,13 @@ static int super_90_validate(struct mdde - mddev->layout = -1; - - if (sb->state & (1<recovery_cp = MaxSector; -+ mddev->resync_offset = MaxSector; - else { - if (sb->events_hi == sb->cp_events_hi && - sb->events_lo == sb->cp_events_lo) { -- mddev->recovery_cp = sb->recovery_cp; -+ mddev->resync_offset = sb->recovery_cp; - } else -- mddev->recovery_cp = 0; -+ mddev->resync_offset = 0; - } - - memcpy(mddev->uuid+0, &sb->set_uuid0, 4); -@@ -1534,10 +1534,10 @@ static void super_90_sync(struct mddev * - mddev->minor_version = sb->minor_version; - if (mddev->in_sync) - { -- sb->recovery_cp = mddev->recovery_cp; -+ sb->recovery_cp = mddev->resync_offset; - sb->cp_events_hi = (mddev->events>>32); - sb->cp_events_lo = (u32)mddev->events; -- if (mddev->recovery_cp == MaxSector) -+ if (mddev->resync_offset == MaxSector) - sb->state = (1<< MD_SB_CLEAN); - } else - sb->recovery_cp = 0; -@@ -1888,7 +1888,7 @@ static int super_1_validate(struct mddev - mddev->bitmap_info.default_space = (4096-1024) >> 9; - mddev->reshape_backwards = 0; - -- mddev->recovery_cp = le64_to_cpu(sb->resync_offset); -+ mddev->resync_offset = le64_to_cpu(sb->resync_offset); - memcpy(mddev->uuid, sb->set_uuid, 16); - - mddev->max_disks = (4096-256)/2; -@@ -2074,7 +2074,7 @@ static void super_1_sync(struct mddev *m - sb->utime = cpu_to_le64((__u64)mddev->utime); - sb->events = cpu_to_le64(mddev->events); - if (mddev->in_sync) -- sb->resync_offset = cpu_to_le64(mddev->recovery_cp); -+ sb->resync_offset = cpu_to_le64(mddev->resync_offset); - else if (test_bit(MD_JOURNAL_CLEAN, &mddev->flags)) - sb->resync_offset = cpu_to_le64(MaxSector); - else -@@ -2754,7 +2754,7 @@ repeat: - /* If this is just a dirty<->clean transition, and the array is clean - * and 'events' is odd, we can roll back to the previous clean state */ - if (nospares -- && (mddev->in_sync && mddev->recovery_cp == MaxSector) -+ && (mddev->in_sync && mddev->resync_offset == MaxSector) - && mddev->can_decrease_events - && mddev->events != 1) { - mddev->events--; -@@ -4290,9 +4290,9 @@ __ATTR(chunk_size, S_IRUGO|S_IWUSR, chun - static ssize_t - resync_start_show(struct mddev *mddev, char *page) - { -- if (mddev->recovery_cp == MaxSector) -+ if (mddev->resync_offset == MaxSector) - return sprintf(page, "none\n"); -- return sprintf(page, "%llu\n", (unsigned long long)mddev->recovery_cp); -+ return sprintf(page, "%llu\n", (unsigned long long)mddev->resync_offset); - } - - static ssize_t -@@ -4318,7 +4318,7 @@ resync_start_store(struct mddev *mddev, - err = -EBUSY; - - if (!err) { -- mddev->recovery_cp = n; -+ mddev->resync_offset = n; - if (mddev->pers) - set_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags); - } -@@ -4822,9 +4822,42 @@ out_unlock: - static struct md_sysfs_entry md_metadata = - __ATTR_PREALLOC(metadata_version, S_IRUGO|S_IWUSR, metadata_show, metadata_store); - -+static bool rdev_needs_recovery(struct md_rdev *rdev, sector_t sectors) -+{ -+ return rdev->raid_disk >= 0 && -+ !test_bit(Journal, &rdev->flags) && -+ !test_bit(Faulty, &rdev->flags) && -+ !test_bit(In_sync, &rdev->flags) && -+ rdev->recovery_offset < sectors; -+} -+ -+static enum sync_action md_get_active_sync_action(struct mddev *mddev) -+{ -+ struct md_rdev *rdev; -+ bool is_recover = false; -+ -+ if (mddev->resync_offset < MaxSector) -+ return ACTION_RESYNC; -+ -+ if (mddev->reshape_position != MaxSector) -+ return ACTION_RESHAPE; -+ -+ rcu_read_lock(); -+ rdev_for_each_rcu(rdev, mddev) { -+ if (rdev_needs_recovery(rdev, MaxSector)) { -+ is_recover = true; -+ break; -+ } -+ } -+ rcu_read_unlock(); -+ -+ return is_recover ? ACTION_RECOVER : ACTION_IDLE; -+} -+ - enum sync_action md_sync_action(struct mddev *mddev) - { - unsigned long recovery = mddev->recovery; -+ enum sync_action active_action; - - /* - * frozen has the highest priority, means running sync_thread will be -@@ -4848,8 +4881,17 @@ enum sync_action md_sync_action(struct m - !test_bit(MD_RECOVERY_NEEDED, &recovery)) - return ACTION_IDLE; - -- if (test_bit(MD_RECOVERY_RESHAPE, &recovery) || -- mddev->reshape_position != MaxSector) -+ /* -+ * Check if any sync operation (resync/recover/reshape) is -+ * currently active. This ensures that only one sync operation -+ * can run at a time. Returns the type of active operation, or -+ * ACTION_IDLE if none are active. -+ */ -+ active_action = md_get_active_sync_action(mddev); -+ if (active_action != ACTION_IDLE) -+ return active_action; -+ -+ if (test_bit(MD_RECOVERY_RESHAPE, &recovery)) - return ACTION_RESHAPE; - - if (test_bit(MD_RECOVERY_RECOVER, &recovery)) -@@ -6405,7 +6447,7 @@ static void md_clean(struct mddev *mddev - mddev->external_size = 0; - mddev->dev_sectors = 0; - mddev->raid_disks = 0; -- mddev->recovery_cp = 0; -+ mddev->resync_offset = 0; - mddev->resync_min = 0; - mddev->resync_max = MaxSector; - mddev->reshape_position = MaxSector; -@@ -7359,9 +7401,9 @@ int md_set_array_info(struct mddev *mdde - * openned - */ - if (info->state & (1<recovery_cp = MaxSector; -+ mddev->resync_offset = MaxSector; - else -- mddev->recovery_cp = 0; -+ mddev->resync_offset = 0; - mddev->persistent = ! info->not_persistent; - mddev->external = 0; - -@@ -8300,7 +8342,7 @@ static int status_resync(struct seq_file - seq_printf(seq, "\tresync=REMOTE"); - return 1; - } -- if (mddev->recovery_cp < MaxSector) { -+ if (mddev->resync_offset < MaxSector) { - seq_printf(seq, "\tresync=PENDING"); - return 1; - } -@@ -8943,7 +8985,7 @@ static sector_t md_sync_position(struct - return mddev->resync_min; - case ACTION_RESYNC: - if (!mddev->bitmap) -- return mddev->recovery_cp; -+ return mddev->resync_offset; - return 0; - case ACTION_RESHAPE: - /* -@@ -8959,11 +9001,7 @@ static sector_t md_sync_position(struct - start = MaxSector; - rcu_read_lock(); - rdev_for_each_rcu(rdev, mddev) -- if (rdev->raid_disk >= 0 && -- !test_bit(Journal, &rdev->flags) && -- !test_bit(Faulty, &rdev->flags) && -- !test_bit(In_sync, &rdev->flags) && -- rdev->recovery_offset < start) -+ if (rdev_needs_recovery(rdev, start)) - start = rdev->recovery_offset; - rcu_read_unlock(); - -@@ -9051,6 +9089,11 @@ void md_do_sync(struct md_thread *thread - } - - action = md_sync_action(mddev); -+ if (action == ACTION_FROZEN || action == ACTION_IDLE) { -+ set_bit(MD_RECOVERY_INTR, &mddev->recovery); -+ goto skip; -+ } -+ - desc = md_sync_action_name(action); - mddev->last_sync_action = action; - -@@ -9181,8 +9224,8 @@ void md_do_sync(struct md_thread *thread - atomic_read(&mddev->recovery_active) == 0); - mddev->curr_resync_completed = j; - if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && -- j > mddev->recovery_cp) -- mddev->recovery_cp = j; -+ j > mddev->resync_offset) -+ mddev->resync_offset = j; - update_time = jiffies; - set_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags); - sysfs_notify_dirent_safe(mddev->sysfs_completed); -@@ -9302,19 +9345,19 @@ void md_do_sync(struct md_thread *thread - mddev->curr_resync > MD_RESYNC_ACTIVE) { - if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { - if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { -- if (mddev->curr_resync >= mddev->recovery_cp) { -+ if (mddev->curr_resync >= mddev->resync_offset) { - pr_debug("md: checkpointing %s of %s.\n", - desc, mdname(mddev)); - if (test_bit(MD_RECOVERY_ERROR, - &mddev->recovery)) -- mddev->recovery_cp = -+ mddev->resync_offset = - mddev->curr_resync_completed; - else -- mddev->recovery_cp = -+ mddev->resync_offset = - mddev->curr_resync; - } - } else -- mddev->recovery_cp = MaxSector; -+ mddev->resync_offset = MaxSector; - } else { - if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) - mddev->curr_resync = MaxSector; -@@ -9322,12 +9365,8 @@ void md_do_sync(struct md_thread *thread - test_bit(MD_RECOVERY_RECOVER, &mddev->recovery)) { - rcu_read_lock(); - rdev_for_each_rcu(rdev, mddev) -- if (rdev->raid_disk >= 0 && -- mddev->delta_disks >= 0 && -- !test_bit(Journal, &rdev->flags) && -- !test_bit(Faulty, &rdev->flags) && -- !test_bit(In_sync, &rdev->flags) && -- rdev->recovery_offset < mddev->curr_resync) -+ if (mddev->delta_disks >= 0 && -+ rdev_needs_recovery(rdev, mddev->curr_resync)) - rdev->recovery_offset = mddev->curr_resync; - rcu_read_unlock(); - } -@@ -9418,6 +9457,12 @@ static bool rdev_is_spare(struct md_rdev - - static bool rdev_addable(struct md_rdev *rdev) - { -+ struct mddev *mddev; -+ -+ mddev = READ_ONCE(rdev->mddev); -+ if (!mddev) -+ return false; -+ - /* rdev is already used, don't add it again. */ - if (test_bit(Candidate, &rdev->flags) || rdev->raid_disk >= 0 || - test_bit(Faulty, &rdev->flags)) -@@ -9428,7 +9473,7 @@ static bool rdev_addable(struct md_rdev - return true; - - /* Allow to add if array is read-write. */ -- if (md_is_rdwr(rdev->mddev)) -+ if (md_is_rdwr(mddev)) - return true; - - /* -@@ -9456,17 +9501,11 @@ static bool md_spares_need_change(struct - return false; - } - --static int remove_and_add_spares(struct mddev *mddev, -- struct md_rdev *this) -+static int remove_spares(struct mddev *mddev, struct md_rdev *this) - { - struct md_rdev *rdev; -- int spares = 0; - int removed = 0; - -- if (this && test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) -- /* Mustn't remove devices when resync thread is running */ -- return 0; -- - rdev_for_each(rdev, mddev) { - if ((this == NULL || rdev == this) && rdev_removeable(rdev) && - !mddev->pers->hot_remove_disk(mddev, rdev)) { -@@ -9480,6 +9519,21 @@ static int remove_and_add_spares(struct - if (removed && mddev->kobj.sd) - sysfs_notify_dirent_safe(mddev->sysfs_degraded); - -+ return removed; -+} -+ -+static int remove_and_add_spares(struct mddev *mddev, -+ struct md_rdev *this) -+{ -+ struct md_rdev *rdev; -+ int spares = 0; -+ int removed = 0; -+ -+ if (this && test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) -+ /* Mustn't remove devices when resync thread is running */ -+ return 0; -+ -+ removed = remove_spares(mddev, this); - if (this && removed) - goto no_add; - -@@ -9521,7 +9575,8 @@ static bool md_choose_sync_action(struct - } - - /* Check if resync is in progress. */ -- if (mddev->recovery_cp < MaxSector) { -+ if (mddev->resync_offset < MaxSector) { -+ remove_spares(mddev, NULL); - set_bit(MD_RECOVERY_SYNC, &mddev->recovery); - clear_bit(MD_RECOVERY_RECOVER, &mddev->recovery); - return true; -@@ -9701,7 +9756,7 @@ void md_check_recovery(struct mddev *mdd - test_bit(MD_RECOVERY_DONE, &mddev->recovery) || - (mddev->external == 0 && mddev->safemode == 1) || - (mddev->safemode == 2 -- && !mddev->in_sync && mddev->recovery_cp == MaxSector) -+ && !mddev->in_sync && mddev->resync_offset == MaxSector) - )) - return; - -@@ -9758,8 +9813,8 @@ void md_check_recovery(struct mddev *mdd - * remove disk. - */ - rdev_for_each_safe(rdev, tmp, mddev) { -- if (test_and_clear_bit(ClusterRemove, &rdev->flags) && -- rdev->raid_disk < 0) -+ if (rdev->raid_disk < 0 && -+ test_and_clear_bit(ClusterRemove, &rdev->flags)) - md_kick_rdev_from_array(rdev); - } - } -@@ -10065,8 +10120,11 @@ static void check_sb_changes(struct mdde - - /* Check for change of roles in the active devices */ - rdev_for_each_safe(rdev2, tmp, mddev) { -- if (test_bit(Faulty, &rdev2->flags)) -+ if (test_bit(Faulty, &rdev2->flags)) { -+ if (test_bit(ClusterRemove, &rdev2->flags)) -+ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); - continue; -+ } - - /* Check if the roles changed */ - role = le16_to_cpu(sb->dev_roles[rdev2->desc_nr]); -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/md-cluster.c BPI-Router-Linux-kernel-6.16.12/drivers/md/md-cluster.c ---- BPI-Router-Linux-kernel/drivers/md/md-cluster.c 2025-10-22 13:53:23.291328761 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/md-cluster.c 2025-10-22 13:53:56.523169103 -0400 -@@ -337,11 +337,11 @@ static void recover_bitmaps(struct md_th - md_wakeup_thread(mddev->sync_thread); - - if (hi > 0) { -- if (lo < mddev->recovery_cp) -- mddev->recovery_cp = lo; -+ if (lo < mddev->resync_offset) -+ mddev->resync_offset = lo; - /* wake up thread to continue resync in case resync - * is not finished */ -- if (mddev->recovery_cp != MaxSector) { -+ if (mddev->resync_offset != MaxSector) { - /* - * clear the REMOTE flag since we will launch - * resync thread in current node. -@@ -863,9 +863,9 @@ static int gather_all_resync_info(struct - lockres_free(bm_lockres); - continue; - } -- if ((hi > 0) && (lo < mddev->recovery_cp)) { -+ if ((hi > 0) && (lo < mddev->resync_offset)) { - set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); -- mddev->recovery_cp = lo; -+ mddev->resync_offset = lo; - md_check_recovery(mddev); - } - -@@ -1027,7 +1027,7 @@ static int leave(struct mddev *mddev) - * Also, we should send BITMAP_NEEDS_SYNC message in - * case reshaping is interrupted. - */ -- if ((cinfo->slot_number > 0 && mddev->recovery_cp != MaxSector) || -+ if ((cinfo->slot_number > 0 && mddev->resync_offset != MaxSector) || - (mddev->reshape_position != MaxSector && - test_bit(MD_CLOSING, &mddev->flags))) - resync_bitmap(mddev); -@@ -1605,8 +1605,8 @@ static int gather_bitmaps(struct md_rdev - pr_warn("md-cluster: Could not gather bitmaps from slot %d", sn); - goto out; - } -- if ((hi > 0) && (lo < mddev->recovery_cp)) -- mddev->recovery_cp = lo; -+ if ((hi > 0) && (lo < mddev->resync_offset)) -+ mddev->resync_offset = lo; - } - out: - return err; -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/md.h BPI-Router-Linux-kernel-6.16.12/drivers/md/md.h ---- BPI-Router-Linux-kernel/drivers/md/md.h 2025-10-22 13:53:23.295328742 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/md.h 2025-10-22 13:53:56.527169084 -0400 -@@ -523,7 +523,7 @@ struct mddev { - unsigned long normal_io_events; /* IO event timestamp */ - atomic_t recovery_active; /* blocks scheduled, but not written */ - wait_queue_head_t recovery_wait; -- sector_t recovery_cp; -+ sector_t resync_offset; - sector_t resync_min; /* user requested sync - * starts here */ - sector_t resync_max; /* resync should pause -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/raid0.c BPI-Router-Linux-kernel-6.16.12/drivers/md/raid0.c ---- BPI-Router-Linux-kernel/drivers/md/raid0.c 2025-10-22 13:53:23.295328742 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/raid0.c 2025-10-22 13:53:56.527169084 -0400 -@@ -673,7 +673,7 @@ static void *raid0_takeover_raid45(struc - mddev->raid_disks--; - mddev->delta_disks = -1; - /* make sure it will be not marked as dirty */ -- mddev->recovery_cp = MaxSector; -+ mddev->resync_offset = MaxSector; - mddev_clear_unsupported_flags(mddev, UNSUPPORTED_MDDEV_FLAGS); - - create_strip_zones(mddev, &priv_conf); -@@ -716,7 +716,7 @@ static void *raid0_takeover_raid10(struc - mddev->raid_disks += mddev->delta_disks; - mddev->degraded = 0; - /* make sure it will be not marked as dirty */ -- mddev->recovery_cp = MaxSector; -+ mddev->resync_offset = MaxSector; - mddev_clear_unsupported_flags(mddev, UNSUPPORTED_MDDEV_FLAGS); - - create_strip_zones(mddev, &priv_conf); -@@ -759,7 +759,7 @@ static void *raid0_takeover_raid1(struct - mddev->delta_disks = 1 - mddev->raid_disks; - mddev->raid_disks = 1; - /* make sure it will be not marked as dirty */ -- mddev->recovery_cp = MaxSector; -+ mddev->resync_offset = MaxSector; - mddev_clear_unsupported_flags(mddev, UNSUPPORTED_MDDEV_FLAGS); - - create_strip_zones(mddev, &priv_conf); -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/raid10.c BPI-Router-Linux-kernel-6.16.12/drivers/md/raid10.c ---- BPI-Router-Linux-kernel/drivers/md/raid10.c 2025-10-22 13:53:23.295328742 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/raid10.c 2025-10-22 13:53:56.527169084 -0400 -@@ -1182,8 +1182,11 @@ static void raid10_read_request(struct m - } - } - -- if (!regular_request_wait(mddev, conf, bio, r10_bio->sectors)) -+ if (!regular_request_wait(mddev, conf, bio, r10_bio->sectors)) { -+ raid_end_bio_io(r10_bio); - return; -+ } -+ - rdev = read_balance(conf, r10_bio, &max_sectors); - if (!rdev) { - if (err_rdev) { -@@ -1221,6 +1224,7 @@ static void raid10_read_request(struct m - r10_bio->master_bio = bio; - } - read_bio = bio_alloc_clone(rdev->bdev, bio, gfp, &mddev->bio_set); -+ read_bio->bi_opf &= ~REQ_NOWAIT; - - r10_bio->devs[slot].bio = read_bio; - r10_bio->devs[slot].rdev = rdev; -@@ -1256,6 +1260,7 @@ static void raid10_write_one_disk(struct - conf->mirrors[devnum].rdev; - - mbio = bio_alloc_clone(rdev->bdev, bio, GFP_NOIO, &mddev->bio_set); -+ mbio->bi_opf &= ~REQ_NOWAIT; - if (replacement) - r10_bio->devs[n_copy].repl_bio = mbio; - else -@@ -1370,8 +1375,11 @@ static void raid10_write_request(struct - } - - sectors = r10_bio->sectors; -- if (!regular_request_wait(mddev, conf, bio, sectors)) -+ if (!regular_request_wait(mddev, conf, bio, sectors)) { -+ raid_end_bio_io(r10_bio); - return; -+ } -+ - if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) && - (mddev->reshape_backwards - ? (bio->bi_iter.bi_sector < conf->reshape_safe && -@@ -2109,7 +2117,7 @@ static int raid10_add_disk(struct mddev - int last = conf->geo.raid_disks - 1; - struct raid10_info *p; - -- if (mddev->recovery_cp < MaxSector) -+ if (mddev->resync_offset < MaxSector) - /* only hot-add to in-sync arrays, as recovery is - * very different from resync - */ -@@ -2438,15 +2446,12 @@ static void sync_request_write(struct md - * that are active - */ - for (i = 0; i < conf->copies; i++) { -- int d; -- - tbio = r10_bio->devs[i].repl_bio; - if (!tbio || !tbio->bi_end_io) - continue; - if (r10_bio->devs[i].bio->bi_end_io != end_sync_write - && r10_bio->devs[i].bio != fbio) - bio_copy_data(tbio, fbio); -- d = r10_bio->devs[i].devnum; - atomic_inc(&r10_bio->remaining); - submit_bio_noacct(tbio); - } -@@ -3180,7 +3185,7 @@ static sector_t raid10_sync_request(stru - * of a clean array, like RAID1 does. - */ - if (mddev->bitmap == NULL && -- mddev->recovery_cp == MaxSector && -+ mddev->resync_offset == MaxSector && - mddev->reshape_position == MaxSector && - !test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && - !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) && -@@ -4004,6 +4009,7 @@ static int raid10_set_queue_limits(struc - md_init_stacking_limits(&lim); - lim.max_write_zeroes_sectors = 0; - lim.io_min = mddev->chunk_sectors << 9; -+ lim.chunk_sectors = mddev->chunk_sectors; - lim.io_opt = lim.io_min * raid10_nr_stripes(conf); - lim.features |= BLK_FEAT_ATOMIC_WRITES; - err = mddev_stack_rdev_limits(mddev, &lim, MDDEV_STACK_INTEGRITY); -@@ -4139,7 +4145,7 @@ static int raid10_run(struct mddev *mdde - disk->recovery_disabled = mddev->recovery_disabled - 1; - } - -- if (mddev->recovery_cp != MaxSector) -+ if (mddev->resync_offset != MaxSector) - pr_notice("md/raid10:%s: not clean -- starting background reconstruction\n", - mdname(mddev)); - pr_info("md/raid10:%s: active with %d out of %d devices\n", -@@ -4239,8 +4245,8 @@ static int raid10_resize(struct mddev *m - - md_set_array_sectors(mddev, size); - if (sectors > mddev->dev_sectors && -- mddev->recovery_cp > oldsize) { -- mddev->recovery_cp = oldsize; -+ mddev->resync_offset > oldsize) { -+ mddev->resync_offset = oldsize; - set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); - } - calc_sectors(conf, sectors); -@@ -4269,7 +4275,7 @@ static void *raid10_takeover_raid0(struc - mddev->delta_disks = mddev->raid_disks; - mddev->raid_disks *= 2; - /* make sure it will be not marked as dirty */ -- mddev->recovery_cp = MaxSector; -+ mddev->resync_offset = MaxSector; - mddev->dev_sectors = size; - - conf = setup_conf(mddev); -@@ -5081,8 +5087,8 @@ static void raid10_finish_reshape(struct - return; - - if (mddev->delta_disks > 0) { -- if (mddev->recovery_cp > mddev->resync_max_sectors) { -- mddev->recovery_cp = mddev->resync_max_sectors; -+ if (mddev->resync_offset > mddev->resync_max_sectors) { -+ mddev->resync_offset = mddev->resync_max_sectors; - set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); - } - mddev->resync_max_sectors = mddev->array_sectors; -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/raid1-10.c BPI-Router-Linux-kernel-6.16.12/drivers/md/raid1-10.c ---- BPI-Router-Linux-kernel/drivers/md/raid1-10.c 2025-10-22 13:53:23.295328742 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/raid1-10.c 2025-10-22 13:53:56.527169084 -0400 -@@ -283,7 +283,7 @@ static inline int raid1_check_read_range - static inline bool raid1_should_read_first(struct mddev *mddev, - sector_t this_sector, int len) - { -- if ((mddev->recovery_cp < this_sector + len)) -+ if ((mddev->resync_offset < this_sector + len)) - return true; - - if (mddev_is_clustered(mddev) && -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/raid1.c BPI-Router-Linux-kernel-6.16.12/drivers/md/raid1.c ---- BPI-Router-Linux-kernel/drivers/md/raid1.c 2025-10-22 13:53:23.295328742 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/raid1.c 2025-10-22 13:53:56.527169084 -0400 -@@ -1226,7 +1226,7 @@ static void alloc_behind_master_bio(stru - int i = 0; - struct bio *behind_bio = NULL; - -- behind_bio = bio_alloc_bioset(NULL, vcnt, 0, GFP_NOIO, -+ behind_bio = bio_alloc_bioset(NULL, vcnt, bio->bi_opf, GFP_NOIO, - &r1_bio->mddev->bio_set); - - /* discard op, we don't support writezero/writesame yet */ -@@ -1399,7 +1399,7 @@ static void raid1_read_request(struct md - } - read_bio = bio_alloc_clone(mirror->rdev->bdev, bio, gfp, - &mddev->bio_set); -- -+ read_bio->bi_opf &= ~REQ_NOWAIT; - r1_bio->bios[rdisk] = read_bio; - - read_bio->bi_iter.bi_sector = r1_bio->sector + -@@ -1649,6 +1649,7 @@ static void raid1_write_request(struct m - wait_for_serialization(rdev, r1_bio); - } - -+ mbio->bi_opf &= ~REQ_NOWAIT; - r1_bio->bios[i] = mbio; - - mbio->bi_iter.bi_sector = (r1_bio->sector + rdev->data_offset); -@@ -2821,7 +2822,7 @@ static sector_t raid1_sync_request(struc - } - - if (mddev->bitmap == NULL && -- mddev->recovery_cp == MaxSector && -+ mddev->resync_offset == MaxSector && - !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) && - conf->fullsync == 0) { - *skipped = 1; -@@ -3281,9 +3282,9 @@ static int raid1_run(struct mddev *mddev - } - - if (conf->raid_disks - mddev->degraded == 1) -- mddev->recovery_cp = MaxSector; -+ mddev->resync_offset = MaxSector; - -- if (mddev->recovery_cp != MaxSector) -+ if (mddev->resync_offset != MaxSector) - pr_info("md/raid1:%s: not clean -- starting background reconstruction\n", - mdname(mddev)); - pr_info("md/raid1:%s: active with %d out of %d mirrors\n", -@@ -3344,8 +3345,8 @@ static int raid1_resize(struct mddev *md - - md_set_array_sectors(mddev, newsize); - if (sectors > mddev->dev_sectors && -- mddev->recovery_cp > mddev->dev_sectors) { -- mddev->recovery_cp = mddev->dev_sectors; -+ mddev->resync_offset > mddev->dev_sectors) { -+ mddev->resync_offset = mddev->dev_sectors; - set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); - } - mddev->dev_sectors = sectors; -@@ -3428,6 +3429,7 @@ static int raid1_reshape(struct mddev *m - /* ok, everything is stopped */ - oldpool = conf->r1bio_pool; - conf->r1bio_pool = newpool; -+ init_waitqueue_head(&conf->r1bio_pool.wait); - - for (d = d2 = 0; d < conf->raid_disks; d++) { - struct md_rdev *rdev = conf->mirrors[d].rdev; -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/raid5.c BPI-Router-Linux-kernel-6.16.12/drivers/md/raid5.c ---- BPI-Router-Linux-kernel/drivers/md/raid5.c 2025-10-22 13:53:23.295328742 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/raid5.c 2025-10-22 13:53:56.527169084 -0400 -@@ -3740,7 +3740,7 @@ static int want_replace(struct stripe_he - && !test_bit(Faulty, &rdev->flags) - && !test_bit(In_sync, &rdev->flags) - && (rdev->recovery_offset <= sh->sector -- || rdev->mddev->recovery_cp <= sh->sector)) -+ || rdev->mddev->resync_offset <= sh->sector)) - rv = 1; - return rv; - } -@@ -3832,7 +3832,7 @@ static int need_this_block(struct stripe - * is missing/faulty, then we need to read everything we can. - */ - if (!force_rcw && -- sh->sector < sh->raid_conf->mddev->recovery_cp) -+ sh->sector < sh->raid_conf->mddev->resync_offset) - /* reconstruct-write isn't being forced */ - return 0; - for (i = 0; i < s->failed && i < 2; i++) { -@@ -4097,7 +4097,7 @@ static int handle_stripe_dirtying(struct - int disks) - { - int rmw = 0, rcw = 0, i; -- sector_t recovery_cp = conf->mddev->recovery_cp; -+ sector_t resync_offset = conf->mddev->resync_offset; - - /* Check whether resync is now happening or should start. - * If yes, then the array is dirty (after unclean shutdown or -@@ -4107,14 +4107,14 @@ static int handle_stripe_dirtying(struct - * generate correct data from the parity. - */ - if (conf->rmw_level == PARITY_DISABLE_RMW || -- (recovery_cp < MaxSector && sh->sector >= recovery_cp && -+ (resync_offset < MaxSector && sh->sector >= resync_offset && - s->failed == 0)) { - /* Calculate the real rcw later - for now make it - * look like rcw is cheaper - */ - rcw = 1; rmw = 2; -- pr_debug("force RCW rmw_level=%u, recovery_cp=%llu sh->sector=%llu\n", -- conf->rmw_level, (unsigned long long)recovery_cp, -+ pr_debug("force RCW rmw_level=%u, resync_offset=%llu sh->sector=%llu\n", -+ conf->rmw_level, (unsigned long long)resync_offset, - (unsigned long long)sh->sector); - } else for (i = disks; i--; ) { - /* would I have to read this buffer for read_modify_write */ -@@ -4770,14 +4770,14 @@ static void analyse_stripe(struct stripe - if (test_bit(STRIPE_SYNCING, &sh->state)) { - /* If there is a failed device being replaced, - * we must be recovering. -- * else if we are after recovery_cp, we must be syncing -+ * else if we are after resync_offset, we must be syncing - * else if MD_RECOVERY_REQUESTED is set, we also are syncing. - * else we can only be replacing - * sync and recovery both need to read all devices, and so - * use the same flag. - */ - if (do_recovery || -- sh->sector >= conf->mddev->recovery_cp || -+ sh->sector >= conf->mddev->resync_offset || - test_bit(MD_RECOVERY_REQUESTED, &(conf->mddev->recovery))) - s->syncing = 1; - else -@@ -7780,7 +7780,7 @@ static int raid5_run(struct mddev *mddev - int first = 1; - int ret = -EIO; - -- if (mddev->recovery_cp != MaxSector) -+ if (mddev->resync_offset != MaxSector) - pr_notice("md/raid:%s: not clean -- starting background reconstruction\n", - mdname(mddev)); - -@@ -7921,7 +7921,7 @@ static int raid5_run(struct mddev *mddev - mdname(mddev)); - mddev->ro = 1; - set_disk_ro(mddev->gendisk, 1); -- } else if (mddev->recovery_cp == MaxSector) -+ } else if (mddev->resync_offset == MaxSector) - set_bit(MD_JOURNAL_CLEAN, &mddev->flags); - } - -@@ -7988,7 +7988,7 @@ static int raid5_run(struct mddev *mddev - mddev->resync_max_sectors = mddev->dev_sectors; - - if (mddev->degraded > dirty_parity_disks && -- mddev->recovery_cp != MaxSector) { -+ mddev->resync_offset != MaxSector) { - if (test_bit(MD_HAS_PPL, &mddev->flags)) - pr_crit("md/raid:%s: starting dirty degraded array with PPL.\n", - mdname(mddev)); -@@ -8328,8 +8328,8 @@ static int raid5_resize(struct mddev *md - - md_set_array_sectors(mddev, newsize); - if (sectors > mddev->dev_sectors && -- mddev->recovery_cp > mddev->dev_sectors) { -- mddev->recovery_cp = mddev->dev_sectors; -+ mddev->resync_offset > mddev->dev_sectors) { -+ mddev->resync_offset = mddev->dev_sectors; - set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); - } - mddev->dev_sectors = sectors; -@@ -8423,7 +8423,7 @@ static int raid5_start_reshape(struct md - return -EINVAL; - - /* raid5 can't handle concurrent reshape and recovery */ -- if (mddev->recovery_cp < MaxSector) -+ if (mddev->resync_offset < MaxSector) - return -EBUSY; - for (i = 0; i < conf->raid_disks; i++) - if (conf->disks[i].replacement) -@@ -8648,7 +8648,7 @@ static void *raid45_takeover_raid0(struc - mddev->raid_disks += 1; - mddev->delta_disks = 1; - /* make sure it will be not marked as dirty */ -- mddev->recovery_cp = MaxSector; -+ mddev->resync_offset = MaxSector; - - return setup_conf(mddev); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/md/raid5-ppl.c BPI-Router-Linux-kernel-6.16.12/drivers/md/raid5-ppl.c ---- BPI-Router-Linux-kernel/drivers/md/raid5-ppl.c 2025-10-22 13:53:23.295328742 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/md/raid5-ppl.c 2025-10-22 13:53:56.527169084 -0400 -@@ -1163,7 +1163,7 @@ static int ppl_load_distributed(struct p - le64_to_cpu(pplhdr->generation)); - - /* attempt to recover from log if we are starting a dirty array */ -- if (pplhdr && !mddev->pers && mddev->recovery_cp != MaxSector) -+ if (pplhdr && !mddev->pers && mddev->resync_offset != MaxSector) - ret = ppl_recover(log, pplhdr, pplhdr_offset); - - /* write empty header if we are starting the array */ -@@ -1422,14 +1422,14 @@ int ppl_init_log(struct r5conf *conf) - - if (ret) { - goto err; -- } else if (!mddev->pers && mddev->recovery_cp == 0 && -+ } else if (!mddev->pers && mddev->resync_offset == 0 && - ppl_conf->recovered_entries > 0 && - ppl_conf->mismatch_count == 0) { - /* - * If we are starting a dirty array and the recovery succeeds - * without any issues, set the array as clean. - */ -- mddev->recovery_cp = MaxSector; -+ mddev->resync_offset = MaxSector; - set_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags); - } else if (mddev->pers && ppl_conf->mismatch_count > 0) { - /* no mismatch allowed when enabling PPL for a running array */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/cec/usb/rainshadow/rainshadow-cec.c BPI-Router-Linux-kernel-6.16.12/drivers/media/cec/usb/rainshadow/rainshadow-cec.c ---- BPI-Router-Linux-kernel/drivers/media/cec/usb/rainshadow/rainshadow-cec.c 2025-10-22 13:53:23.295328742 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/cec/usb/rainshadow/rainshadow-cec.c 2025-10-22 13:53:56.527169084 -0400 -@@ -171,11 +171,12 @@ static irqreturn_t rain_interrupt(struct - { - struct rain *rain = serio_get_drvdata(serio); - -+ spin_lock(&rain->buf_lock); - if (rain->buf_len == DATA_SIZE) { -+ spin_unlock(&rain->buf_lock); - dev_warn_once(rain->dev, "buffer overflow\n"); - return IRQ_HANDLED; - } -- spin_lock(&rain->buf_lock); - rain->buf_len++; - rain->buf[rain->buf_wr_idx] = data; - rain->buf_wr_idx = (rain->buf_wr_idx + 1) & 0xff; -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/dvb-frontends/dib7000p.c BPI-Router-Linux-kernel-6.16.12/drivers/media/dvb-frontends/dib7000p.c ---- BPI-Router-Linux-kernel/drivers/media/dvb-frontends/dib7000p.c 2025-10-22 13:53:23.295328742 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/dvb-frontends/dib7000p.c 2025-10-22 13:53:56.527169084 -0400 -@@ -2193,6 +2193,8 @@ static int w7090p_tuner_write_serpar(str - struct dib7000p_state *state = i2c_get_adapdata(i2c_adap); - u8 n_overflow = 1; - u16 i = 1000; -+ if (msg[0].len < 3) -+ return -EOPNOTSUPP; - u16 serpar_num = msg[0].buf[0]; - - while (n_overflow == 1 && i) { -@@ -2212,6 +2214,8 @@ static int w7090p_tuner_read_serpar(stru - struct dib7000p_state *state = i2c_get_adapdata(i2c_adap); - u8 n_overflow = 1, n_empty = 1; - u16 i = 1000; -+ if (msg[0].len < 1 || msg[1].len < 2) -+ return -EOPNOTSUPP; - u16 serpar_num = msg[0].buf[0]; - u16 read_word; - -@@ -2256,8 +2260,12 @@ static int dib7090p_rw_on_apb(struct i2c - u16 word; - - if (num == 1) { /* write */ -+ if (msg[0].len < 3) -+ return -EOPNOTSUPP; - dib7000p_write_word(state, apb_address, ((msg[0].buf[1] << 8) | (msg[0].buf[2]))); - } else { -+ if (msg[1].len < 2) -+ return -EOPNOTSUPP; - word = dib7000p_read_word(state, apb_address); - msg[1].buf[0] = (word >> 8) & 0xff; - msg[1].buf[1] = (word) & 0xff; -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/i2c/hi556.c BPI-Router-Linux-kernel-6.16.12/drivers/media/i2c/hi556.c ---- BPI-Router-Linux-kernel/drivers/media/i2c/hi556.c 2025-10-22 13:53:23.295328742 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/i2c/hi556.c 2025-10-22 13:53:56.527169084 -0400 -@@ -756,21 +756,23 @@ static int hi556_test_pattern(struct hi5 - int ret; - u32 val; - -- if (pattern) { -- ret = hi556_read_reg(hi556, HI556_REG_ISP, -- HI556_REG_VALUE_08BIT, &val); -- if (ret) -- return ret; -+ ret = hi556_read_reg(hi556, HI556_REG_ISP, -+ HI556_REG_VALUE_08BIT, &val); -+ if (ret) -+ return ret; - -- ret = hi556_write_reg(hi556, HI556_REG_ISP, -- HI556_REG_VALUE_08BIT, -- val | HI556_REG_ISP_TPG_EN); -- if (ret) -- return ret; -- } -+ val = pattern ? (val | HI556_REG_ISP_TPG_EN) : -+ (val & ~HI556_REG_ISP_TPG_EN); -+ -+ ret = hi556_write_reg(hi556, HI556_REG_ISP, -+ HI556_REG_VALUE_08BIT, val); -+ if (ret) -+ return ret; -+ -+ val = pattern ? BIT(pattern - 1) : 0; - - return hi556_write_reg(hi556, HI556_REG_TEST_PATTERN, -- HI556_REG_VALUE_08BIT, pattern); -+ HI556_REG_VALUE_08BIT, val); - } - - static int hi556_set_ctrl(struct v4l2_ctrl *ctrl) -@@ -1321,7 +1323,12 @@ static int hi556_resume(struct device *d - return ret; - } - -- gpiod_set_value_cansleep(hi556->reset_gpio, 0); -+ if (hi556->reset_gpio) { -+ /* Assert reset for at least 2ms on back to back off-on */ -+ usleep_range(2000, 2200); -+ gpiod_set_value_cansleep(hi556->reset_gpio, 0); -+ } -+ - usleep_range(5000, 5500); - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/i2c/lt6911uxe.c BPI-Router-Linux-kernel-6.16.12/drivers/media/i2c/lt6911uxe.c ---- BPI-Router-Linux-kernel/drivers/media/i2c/lt6911uxe.c 2025-10-22 13:53:23.295328742 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/i2c/lt6911uxe.c 2025-10-22 13:53:56.527169084 -0400 -@@ -600,7 +600,7 @@ static int lt6911uxe_probe(struct i2c_cl - - v4l2_i2c_subdev_init(<6911uxe->sd, client, <6911uxe_subdev_ops); - -- lt6911uxe->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_IN); -+ lt6911uxe->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); - if (IS_ERR(lt6911uxe->reset_gpio)) - return dev_err_probe(dev, PTR_ERR(lt6911uxe->reset_gpio), - "failed to get reset gpio\n"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/i2c/mt9m114.c BPI-Router-Linux-kernel-6.16.12/drivers/media/i2c/mt9m114.c ---- BPI-Router-Linux-kernel/drivers/media/i2c/mt9m114.c 2025-10-22 13:53:23.295328742 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/i2c/mt9m114.c 2025-10-22 13:53:56.527169084 -0400 -@@ -1599,13 +1599,9 @@ static int mt9m114_ifp_get_frame_interva - if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE) - return -EINVAL; - -- mutex_lock(sensor->ifp.hdl.lock); -- - ival->numerator = 1; - ival->denominator = sensor->ifp.frame_rate; - -- mutex_unlock(sensor->ifp.hdl.lock); -- - return 0; - } - -@@ -1624,8 +1620,6 @@ static int mt9m114_ifp_set_frame_interva - if (interval->which != V4L2_SUBDEV_FORMAT_ACTIVE) - return -EINVAL; - -- mutex_lock(sensor->ifp.hdl.lock); -- - if (ival->numerator != 0 && ival->denominator != 0) - sensor->ifp.frame_rate = min_t(unsigned int, - ival->denominator / ival->numerator, -@@ -1639,8 +1633,6 @@ static int mt9m114_ifp_set_frame_interva - if (sensor->streaming) - ret = mt9m114_set_frame_rate(sensor); - -- mutex_unlock(sensor->ifp.hdl.lock); -- - return ret; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/i2c/ov2659.c BPI-Router-Linux-kernel-6.16.12/drivers/media/i2c/ov2659.c ---- BPI-Router-Linux-kernel/drivers/media/i2c/ov2659.c 2025-10-22 13:53:23.295328742 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/i2c/ov2659.c 2025-10-22 13:53:56.527169084 -0400 -@@ -1469,14 +1469,15 @@ static int ov2659_probe(struct i2c_clien - V4L2_CID_TEST_PATTERN, - ARRAY_SIZE(ov2659_test_pattern_menu) - 1, - 0, 0, ov2659_test_pattern_menu); -- ov2659->sd.ctrl_handler = &ov2659->ctrls; - - if (ov2659->ctrls.error) { - dev_err(&client->dev, "%s: control initialization error %d\n", - __func__, ov2659->ctrls.error); -+ v4l2_ctrl_handler_free(&ov2659->ctrls); - return ov2659->ctrls.error; - } - -+ ov2659->sd.ctrl_handler = &ov2659->ctrls; - sd = &ov2659->sd; - client->flags |= I2C_CLIENT_SCCB; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/i2c/tc358743.c BPI-Router-Linux-kernel-6.16.12/drivers/media/i2c/tc358743.c ---- BPI-Router-Linux-kernel/drivers/media/i2c/tc358743.c 2025-10-22 13:53:23.295328742 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/i2c/tc358743.c 2025-10-22 13:53:56.527169084 -0400 -@@ -114,7 +114,7 @@ static inline struct tc358743_state *to_ - - /* --------------- I2C --------------- */ - --static void i2c_rd(struct v4l2_subdev *sd, u16 reg, u8 *values, u32 n) -+static int i2c_rd(struct v4l2_subdev *sd, u16 reg, u8 *values, u32 n) - { - struct tc358743_state *state = to_state(sd); - struct i2c_client *client = state->i2c_client; -@@ -140,6 +140,7 @@ static void i2c_rd(struct v4l2_subdev *s - v4l2_err(sd, "%s: reading register 0x%x from 0x%x failed: %d\n", - __func__, reg, client->addr, err); - } -+ return err != ARRAY_SIZE(msgs); - } - - static void i2c_wr(struct v4l2_subdev *sd, u16 reg, u8 *values, u32 n) -@@ -196,15 +197,24 @@ static void i2c_wr(struct v4l2_subdev *s - } - } - --static noinline u32 i2c_rdreg(struct v4l2_subdev *sd, u16 reg, u32 n) -+static noinline u32 i2c_rdreg_err(struct v4l2_subdev *sd, u16 reg, u32 n, -+ int *err) - { -+ int error; - __le32 val = 0; - -- i2c_rd(sd, reg, (u8 __force *)&val, n); -+ error = i2c_rd(sd, reg, (u8 __force *)&val, n); -+ if (err) -+ *err = error; - - return le32_to_cpu(val); - } - -+static inline u32 i2c_rdreg(struct v4l2_subdev *sd, u16 reg, u32 n) -+{ -+ return i2c_rdreg_err(sd, reg, n, NULL); -+} -+ - static noinline void i2c_wrreg(struct v4l2_subdev *sd, u16 reg, u32 val, u32 n) - { - __le32 raw = cpu_to_le32(val); -@@ -233,6 +243,13 @@ static u16 i2c_rd16(struct v4l2_subdev * - return i2c_rdreg(sd, reg, 2); - } - -+static int i2c_rd16_err(struct v4l2_subdev *sd, u16 reg, u16 *value) -+{ -+ int err; -+ *value = i2c_rdreg_err(sd, reg, 2, &err); -+ return err; -+} -+ - static void i2c_wr16(struct v4l2_subdev *sd, u16 reg, u16 val) - { - i2c_wrreg(sd, reg, val, 2); -@@ -1691,12 +1708,23 @@ static int tc358743_enum_mbus_code(struc - return 0; - } - -+static u32 tc358743_g_colorspace(u32 code) -+{ -+ switch (code) { -+ case MEDIA_BUS_FMT_RGB888_1X24: -+ return V4L2_COLORSPACE_SRGB; -+ case MEDIA_BUS_FMT_UYVY8_1X16: -+ return V4L2_COLORSPACE_SMPTE170M; -+ default: -+ return 0; -+ } -+} -+ - static int tc358743_get_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *sd_state, - struct v4l2_subdev_format *format) - { - struct tc358743_state *state = to_state(sd); -- u8 vi_rep = i2c_rd8(sd, VI_REP); - - if (format->pad != 0) - return -EINVAL; -@@ -1706,23 +1734,7 @@ static int tc358743_get_fmt(struct v4l2_ - format->format.height = state->timings.bt.height; - format->format.field = V4L2_FIELD_NONE; - -- switch (vi_rep & MASK_VOUT_COLOR_SEL) { -- case MASK_VOUT_COLOR_RGB_FULL: -- case MASK_VOUT_COLOR_RGB_LIMITED: -- format->format.colorspace = V4L2_COLORSPACE_SRGB; -- break; -- case MASK_VOUT_COLOR_601_YCBCR_LIMITED: -- case MASK_VOUT_COLOR_601_YCBCR_FULL: -- format->format.colorspace = V4L2_COLORSPACE_SMPTE170M; -- break; -- case MASK_VOUT_COLOR_709_YCBCR_FULL: -- case MASK_VOUT_COLOR_709_YCBCR_LIMITED: -- format->format.colorspace = V4L2_COLORSPACE_REC709; -- break; -- default: -- format->format.colorspace = 0; -- break; -- } -+ format->format.colorspace = tc358743_g_colorspace(format->format.code); - - return 0; - } -@@ -1736,19 +1748,14 @@ static int tc358743_set_fmt(struct v4l2_ - u32 code = format->format.code; /* is overwritten by get_fmt */ - int ret = tc358743_get_fmt(sd, sd_state, format); - -- format->format.code = code; -+ if (code == MEDIA_BUS_FMT_RGB888_1X24 || -+ code == MEDIA_BUS_FMT_UYVY8_1X16) -+ format->format.code = code; -+ format->format.colorspace = tc358743_g_colorspace(format->format.code); - - if (ret) - return ret; - -- switch (code) { -- case MEDIA_BUS_FMT_RGB888_1X24: -- case MEDIA_BUS_FMT_UYVY8_1X16: -- break; -- default: -- return -EINVAL; -- } -- - if (format->which == V4L2_SUBDEV_FORMAT_TRY) - return 0; - -@@ -1972,8 +1979,19 @@ static int tc358743_probe_of(struct tc35 - state->pdata.refclk_hz = clk_get_rate(refclk); - state->pdata.ddc5v_delay = DDC5V_DELAY_100_MS; - state->pdata.enable_hdcp = false; -- /* A FIFO level of 16 should be enough for 2-lane 720p60 at 594 MHz. */ -- state->pdata.fifo_level = 16; -+ /* -+ * Ideally the FIFO trigger level should be set based on the input and -+ * output data rates, but the calculations required are buried in -+ * Toshiba's register settings spreadsheet. -+ * A value of 16 works with a 594Mbps data rate for 720p60 (using 2 -+ * lanes) and 1080p60 (using 4 lanes), but fails when the data rate -+ * is increased, or a lower pixel clock is used that result in CSI -+ * reading out faster than the data is arriving. -+ * -+ * A value of 374 works with both those modes at 594Mbps, and with most -+ * modes on 972Mbps. -+ */ -+ state->pdata.fifo_level = 374; - /* - * The PLL input clock is obtained by dividing refclk by pll_prd. - * It must be between 6 MHz and 40 MHz, lower frequency is better. -@@ -2061,6 +2079,7 @@ static int tc358743_probe(struct i2c_cli - struct tc358743_platform_data *pdata = client->dev.platform_data; - struct v4l2_subdev *sd; - u16 irq_mask = MASK_HDMI_MSK | MASK_CSI_MSK; -+ u16 chipid; - int err; - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) -@@ -2092,7 +2111,8 @@ static int tc358743_probe(struct i2c_cli - sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; - - /* i2c access */ -- if ((i2c_rd16(sd, CHIPID) & MASK_CHIPID) != 0) { -+ if (i2c_rd16_err(sd, CHIPID, &chipid) || -+ (chipid & MASK_CHIPID) != 0) { - v4l2_info(sd, "not a TC358743 on address 0x%x\n", - client->addr << 1); - return -ENODEV; -@@ -2205,10 +2225,10 @@ static int tc358743_probe(struct i2c_cli - err_work_queues: - cec_unregister_adapter(state->cec_adap); - if (!state->i2c_client->irq) { -- timer_delete(&state->timer); -+ timer_delete_sync(&state->timer); - flush_work(&state->work_i2c_poll); - } -- cancel_delayed_work(&state->delayed_work_enable_hotplug); -+ cancel_delayed_work_sync(&state->delayed_work_enable_hotplug); - mutex_destroy(&state->confctl_mutex); - err_hdl: - media_entity_cleanup(&sd->entity); -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/i2c/vd55g1.c BPI-Router-Linux-kernel-6.16.12/drivers/media/i2c/vd55g1.c ---- BPI-Router-Linux-kernel/drivers/media/i2c/vd55g1.c 2025-10-22 13:53:23.295328742 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/i2c/vd55g1.c 2025-10-22 13:53:56.527169084 -0400 -@@ -129,8 +129,8 @@ - #define VD55G1_FWPATCH_REVISION_MINOR 9 - #define VD55G1_XCLK_FREQ_MIN (6 * HZ_PER_MHZ) - #define VD55G1_XCLK_FREQ_MAX (27 * HZ_PER_MHZ) --#define VD55G1_MIPI_RATE_MIN (250 * HZ_PER_MHZ) --#define VD55G1_MIPI_RATE_MAX (1200 * HZ_PER_MHZ) -+#define VD55G1_MIPI_RATE_MIN (250 * MEGA) -+#define VD55G1_MIPI_RATE_MAX (1200 * MEGA) - - static const u8 patch_array[] = { - 0x44, 0x03, 0x09, 0x02, 0xe6, 0x01, 0x42, 0x00, 0xea, 0x01, 0x42, 0x00, -@@ -1038,8 +1038,6 @@ static int vd55g1_enable_streams(struct - if (ret < 0) - return ret; - -- vd55g1_write(sensor, VD55G1_REG_EXT_CLOCK, sensor->xclk_freq, &ret); -- - /* Configure output */ - vd55g1_write(sensor, VD55G1_REG_MIPI_DATA_RATE, - sensor->mipi_rate, &ret); -@@ -1084,7 +1082,7 @@ static int vd55g1_enable_streams(struct - - err_rpm_put: - pm_runtime_put(sensor->dev); -- return 0; -+ return -EINVAL; - } - - static int vd55g1_disable_streams(struct v4l2_subdev *sd, -@@ -1613,6 +1611,9 @@ static int vd55g1_power_on(struct device - goto disable_clock; - } - -+ /* Setup clock now to advance through system FSM states */ -+ vd55g1_write(sensor, VD55G1_REG_EXT_CLOCK, sensor->xclk_freq, &ret); -+ - ret = vd55g1_patch(sensor); - if (ret) { - dev_err(dev, "Sensor patch failed %d\n", ret); -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/pci/b2c2/flexcop-pci.c BPI-Router-Linux-kernel-6.16.12/drivers/media/pci/b2c2/flexcop-pci.c ---- BPI-Router-Linux-kernel/drivers/media/pci/b2c2/flexcop-pci.c 2025-10-22 13:53:23.295328742 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/pci/b2c2/flexcop-pci.c 2025-10-22 13:53:56.527169084 -0400 -@@ -411,7 +411,7 @@ static void flexcop_pci_remove(struct pc - struct flexcop_pci *fc_pci = pci_get_drvdata(pdev); - - if (irq_chk_intv > 0) -- cancel_delayed_work(&fc_pci->irq_check_work); -+ cancel_delayed_work_sync(&fc_pci->irq_check_work); - - flexcop_pci_dma_exit(fc_pci); - flexcop_device_exit(fc_pci->fc_dev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c BPI-Router-Linux-kernel-6.16.12/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c ---- BPI-Router-Linux-kernel/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c 2025-10-22 13:53:23.295328742 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c 2025-10-22 13:53:56.527169084 -0400 -@@ -354,9 +354,9 @@ static int ipu6_isys_csi2_enable_streams - remote_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]); - remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity); - -- sink_streams = v4l2_subdev_state_xlate_streams(state, CSI2_PAD_SRC, -- CSI2_PAD_SINK, -- &streams_mask); -+ sink_streams = -+ v4l2_subdev_state_xlate_streams(state, pad, CSI2_PAD_SINK, -+ &streams_mask); - - ret = ipu6_isys_csi2_calc_timing(csi2, &timing, CSI2_ACCINV); - if (ret) -@@ -384,9 +384,9 @@ static int ipu6_isys_csi2_disable_stream - struct media_pad *remote_pad; - u64 sink_streams; - -- sink_streams = v4l2_subdev_state_xlate_streams(state, CSI2_PAD_SRC, -- CSI2_PAD_SINK, -- &streams_mask); -+ sink_streams = -+ v4l2_subdev_state_xlate_streams(state, pad, CSI2_PAD_SINK, -+ &streams_mask); - - remote_pad = media_pad_remote_pad_first(&sd->entity.pads[CSI2_PAD_SINK]); - remote_sd = media_entity_to_v4l2_subdev(remote_pad->entity); -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/pci/intel/ipu-bridge.c BPI-Router-Linux-kernel-6.16.12/drivers/media/pci/intel/ipu-bridge.c ---- BPI-Router-Linux-kernel/drivers/media/pci/intel/ipu-bridge.c 2025-10-22 13:53:23.295328742 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/pci/intel/ipu-bridge.c 2025-10-22 13:53:56.527169084 -0400 -@@ -60,6 +60,8 @@ static const struct ipu_sensor_config ip - IPU_SENSOR_CONFIG("INT33BE", 1, 419200000), - /* Omnivision OV2740 */ - IPU_SENSOR_CONFIG("INT3474", 1, 180000000), -+ /* Omnivision OV5670 */ -+ IPU_SENSOR_CONFIG("INT3479", 1, 422400000), - /* Omnivision OV8865 */ - IPU_SENSOR_CONFIG("INT347A", 1, 360000000), - /* Omnivision OV7251 */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/pci/intel/ivsc/mei_ace.c BPI-Router-Linux-kernel-6.16.12/drivers/media/pci/intel/ivsc/mei_ace.c ---- BPI-Router-Linux-kernel/drivers/media/pci/intel/ivsc/mei_ace.c 2025-10-22 13:53:23.295328742 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/pci/intel/ivsc/mei_ace.c 2025-10-22 13:53:56.527169084 -0400 -@@ -529,6 +529,8 @@ static void mei_ace_remove(struct mei_cl - - ace_set_camera_owner(ace, ACE_CAMERA_IVSC); - -+ mei_cldev_disable(cldev); -+ - mutex_destroy(&ace->lock); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/pci/intel/ivsc/mei_csi.c BPI-Router-Linux-kernel-6.16.12/drivers/media/pci/intel/ivsc/mei_csi.c ---- BPI-Router-Linux-kernel/drivers/media/pci/intel/ivsc/mei_csi.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/pci/intel/ivsc/mei_csi.c 2025-10-22 13:53:56.527169084 -0400 -@@ -760,6 +760,8 @@ static void mei_csi_remove(struct mei_cl - - pm_runtime_disable(&cldev->dev); - -+ mei_cldev_disable(cldev); -+ - mutex_destroy(&csi->lock); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c ---- BPI-Router-Linux-kernel/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c 2025-10-22 13:53:56.527169084 -0400 -@@ -598,6 +598,27 @@ static void _bswap16(u16 *a) - *a = ((*a & 0x00FF) << 8) | ((*a & 0xFF00) >> 8); - } - -+static dma_addr_t mxc_jpeg_get_plane_dma_addr(struct vb2_buffer *buf, unsigned int plane_no) -+{ -+ if (plane_no >= buf->num_planes) -+ return 0; -+ return vb2_dma_contig_plane_dma_addr(buf, plane_no) + buf->planes[plane_no].data_offset; -+} -+ -+static void *mxc_jpeg_get_plane_vaddr(struct vb2_buffer *buf, unsigned int plane_no) -+{ -+ if (plane_no >= buf->num_planes) -+ return NULL; -+ return vb2_plane_vaddr(buf, plane_no) + buf->planes[plane_no].data_offset; -+} -+ -+static unsigned long mxc_jpeg_get_plane_payload(struct vb2_buffer *buf, unsigned int plane_no) -+{ -+ if (plane_no >= buf->num_planes) -+ return 0; -+ return vb2_get_plane_payload(buf, plane_no) - buf->planes[plane_no].data_offset; -+} -+ - static void print_mxc_buf(struct mxc_jpeg_dev *jpeg, struct vb2_buffer *buf, - unsigned long len) - { -@@ -610,11 +631,11 @@ static void print_mxc_buf(struct mxc_jpe - return; - - for (plane_no = 0; plane_no < buf->num_planes; plane_no++) { -- payload = vb2_get_plane_payload(buf, plane_no); -+ payload = mxc_jpeg_get_plane_payload(buf, plane_no); - if (len == 0) - len = payload; -- dma_addr = vb2_dma_contig_plane_dma_addr(buf, plane_no); -- vaddr = vb2_plane_vaddr(buf, plane_no); -+ dma_addr = mxc_jpeg_get_plane_dma_addr(buf, plane_no); -+ vaddr = mxc_jpeg_get_plane_vaddr(buf, plane_no); - v4l2_dbg(3, debug, &jpeg->v4l2_dev, - "plane %d (vaddr=%p dma_addr=%x payload=%ld):", - plane_no, vaddr, dma_addr, payload); -@@ -712,16 +733,15 @@ static void mxc_jpeg_addrs(struct mxc_jp - struct mxc_jpeg_q_data *q_data; - - q_data = mxc_jpeg_get_q_data(ctx, raw_buf->type); -- desc->buf_base0 = vb2_dma_contig_plane_dma_addr(raw_buf, 0); -+ desc->buf_base0 = mxc_jpeg_get_plane_dma_addr(raw_buf, 0); - desc->buf_base1 = 0; - if (img_fmt == STM_CTRL_IMAGE_FORMAT(MXC_JPEG_YUV420)) { - if (raw_buf->num_planes == 2) -- desc->buf_base1 = vb2_dma_contig_plane_dma_addr(raw_buf, 1); -+ desc->buf_base1 = mxc_jpeg_get_plane_dma_addr(raw_buf, 1); - else - desc->buf_base1 = desc->buf_base0 + q_data->sizeimage[0]; - } -- desc->stm_bufbase = vb2_dma_contig_plane_dma_addr(jpeg_buf, 0) + -- offset; -+ desc->stm_bufbase = mxc_jpeg_get_plane_dma_addr(jpeg_buf, 0) + offset; - } - - static bool mxc_jpeg_is_extended_sequential(const struct mxc_jpeg_fmt *fmt) -@@ -1029,8 +1049,8 @@ static irqreturn_t mxc_jpeg_dec_irq(int - vb2_set_plane_payload(&dst_buf->vb2_buf, 1, payload); - } - dev_dbg(dev, "Decoding finished, payload size: %ld + %ld\n", -- vb2_get_plane_payload(&dst_buf->vb2_buf, 0), -- vb2_get_plane_payload(&dst_buf->vb2_buf, 1)); -+ mxc_jpeg_get_plane_payload(&dst_buf->vb2_buf, 0), -+ mxc_jpeg_get_plane_payload(&dst_buf->vb2_buf, 1)); - } - - /* short preview of the results */ -@@ -1889,8 +1909,8 @@ static int mxc_jpeg_parse(struct mxc_jpe - struct mxc_jpeg_sof *psof = NULL; - struct mxc_jpeg_sos *psos = NULL; - struct mxc_jpeg_src_buf *jpeg_src_buf = vb2_to_mxc_buf(vb); -- u8 *src_addr = (u8 *)vb2_plane_vaddr(vb, 0); -- u32 size = vb2_get_plane_payload(vb, 0); -+ u8 *src_addr = (u8 *)mxc_jpeg_get_plane_vaddr(vb, 0); -+ u32 size = mxc_jpeg_get_plane_payload(vb, 0); - int ret; - - memset(&header, 0, sizeof(header)); -@@ -2027,6 +2047,11 @@ static int mxc_jpeg_buf_prepare(struct v - i, vb2_plane_size(vb, i), sizeimage); - return -EINVAL; - } -+ if (!IS_ALIGNED(mxc_jpeg_get_plane_dma_addr(vb, i), MXC_JPEG_ADDR_ALIGNMENT)) { -+ dev_err(dev, "planes[%d] address is not %d aligned\n", -+ i, MXC_JPEG_ADDR_ALIGNMENT); -+ return -EINVAL; -+ } - } - if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type)) { - vb2_set_plane_payload(vb, 0, 0); -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h ---- BPI-Router-Linux-kernel/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h 2025-10-22 13:53:56.527169084 -0400 -@@ -30,6 +30,7 @@ - #define MXC_JPEG_MAX_PLANES 2 - #define MXC_JPEG_PATTERN_WIDTH 128 - #define MXC_JPEG_PATTERN_HEIGHT 64 -+#define MXC_JPEG_ADDR_ALIGNMENT 16 - - enum mxc_jpeg_enc_state { - MXC_JPEG_ENCODING = 0, /* jpeg encode phase */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/camss/camss.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/camss/camss.c ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/camss/camss.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/camss/camss.c 2025-10-22 13:53:56.531169064 -0400 -@@ -2486,8 +2486,8 @@ static const struct resources_icc icc_re - static const struct camss_subdev_resources csiphy_res_x1e80100[] = { - /* CSIPHY0 */ - { -- .regulators = { "vdd-csiphy-0p8-supply", -- "vdd-csiphy-1p2-supply" }, -+ .regulators = { "vdd-csiphy-0p8", -+ "vdd-csiphy-1p2" }, - .clock = { "csiphy0", "csiphy0_timer" }, - .clock_rate = { { 300000000, 400000000, 480000000 }, - { 266666667, 400000000 } }, -@@ -2501,8 +2501,8 @@ static const struct camss_subdev_resourc - }, - /* CSIPHY1 */ - { -- .regulators = { "vdd-csiphy-0p8-supply", -- "vdd-csiphy-1p2-supply" }, -+ .regulators = { "vdd-csiphy-0p8", -+ "vdd-csiphy-1p2" }, - .clock = { "csiphy1", "csiphy1_timer" }, - .clock_rate = { { 300000000, 400000000, 480000000 }, - { 266666667, 400000000 } }, -@@ -2516,8 +2516,8 @@ static const struct camss_subdev_resourc - }, - /* CSIPHY2 */ - { -- .regulators = { "vdd-csiphy-0p8-supply", -- "vdd-csiphy-1p2-supply" }, -+ .regulators = { "vdd-csiphy-0p8", -+ "vdd-csiphy-1p2" }, - .clock = { "csiphy2", "csiphy2_timer" }, - .clock_rate = { { 300000000, 400000000, 480000000 }, - { 266666667, 400000000 } }, -@@ -2531,8 +2531,8 @@ static const struct camss_subdev_resourc - }, - /* CSIPHY4 */ - { -- .regulators = { "vdd-csiphy-0p8-supply", -- "vdd-csiphy-1p2-supply" }, -+ .regulators = { "vdd-csiphy-0p8", -+ "vdd-csiphy-1p2" }, - .clock = { "csiphy4", "csiphy4_timer" }, - .clock_rate = { { 300000000, 400000000, 480000000 }, - { 266666667, 400000000 } }, -@@ -3625,7 +3625,7 @@ static int camss_probe(struct platform_d - ret = v4l2_device_register(camss->dev, &camss->v4l2_dev); - if (ret < 0) { - dev_err(dev, "Failed to register V4L2 device: %d\n", ret); -- goto err_genpd_cleanup; -+ goto err_media_device_cleanup; - } - - v4l2_async_nf_init(&camss->notifier, &camss->v4l2_dev); -@@ -3680,6 +3680,8 @@ err_v4l2_device_unregister: - v4l2_device_unregister(&camss->v4l2_dev); - v4l2_async_nf_cleanup(&camss->notifier); - pm_runtime_disable(dev); -+err_media_device_cleanup: -+ media_device_cleanup(&camss->media_dev); - err_genpd_cleanup: - camss_genpd_cleanup(camss); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c 2025-10-22 13:53:56.531169064 -0400 -@@ -849,8 +849,7 @@ static int csiphy_init(struct csiphy_dev - regs->offset = 0x1000; - break; - default: -- WARN(1, "unknown csiphy version\n"); -- return -ENODEV; -+ break; - } - - return 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_buffer.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_buffer.c ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_buffer.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_buffer.c 2025-10-22 13:53:56.531169064 -0400 -@@ -376,7 +376,7 @@ int iris_destroy_internal_buffer(struct - return 0; - } - --int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane) -+static int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane, bool force) - { - const struct iris_platform_data *platform_data = inst->core->iris_platform_data; - struct iris_buffer *buf, *next; -@@ -396,6 +396,24 @@ int iris_destroy_internal_buffers(struct - for (i = 0; i < len; i++) { - buffers = &inst->buffers[internal_buf_type[i]]; - list_for_each_entry_safe(buf, next, &buffers->list, list) { -+ /* -+ * during stream on, skip destroying internal(DPB) buffer -+ * if firmware did not return it. -+ * during close, destroy all buffers irrespectively. -+ */ -+ if (!force && buf->attr & BUF_ATTR_QUEUED) -+ continue; -+ -+ ret = iris_destroy_internal_buffer(inst, buf); -+ if (ret) -+ return ret; -+ } -+ } -+ -+ if (force) { -+ buffers = &inst->buffers[BUF_PERSIST]; -+ -+ list_for_each_entry_safe(buf, next, &buffers->list, list) { - ret = iris_destroy_internal_buffer(inst, buf); - if (ret) - return ret; -@@ -405,6 +423,16 @@ int iris_destroy_internal_buffers(struct - return 0; - } - -+int iris_destroy_all_internal_buffers(struct iris_inst *inst, u32 plane) -+{ -+ return iris_destroy_internal_buffers(inst, plane, true); -+} -+ -+int iris_destroy_dequeued_internal_buffers(struct iris_inst *inst, u32 plane) -+{ -+ return iris_destroy_internal_buffers(inst, plane, false); -+} -+ - static int iris_release_internal_buffers(struct iris_inst *inst, - enum iris_buffer_type buffer_type) - { -@@ -593,10 +621,13 @@ int iris_vb2_buffer_done(struct iris_ins - - vb2 = &vbuf->vb2_buf; - -- if (buf->flags & V4L2_BUF_FLAG_ERROR) -+ if (buf->flags & V4L2_BUF_FLAG_ERROR) { - state = VB2_BUF_STATE_ERROR; -- else -- state = VB2_BUF_STATE_DONE; -+ vb2_set_plane_payload(vb2, 0, 0); -+ vb2->timestamp = 0; -+ v4l2_m2m_buf_done(vbuf, state); -+ return 0; -+ } - - vbuf->flags |= buf->flags; - -@@ -616,6 +647,8 @@ int iris_vb2_buffer_done(struct iris_ins - v4l2_m2m_mark_stopped(m2m_ctx); - } - } -+ -+ state = VB2_BUF_STATE_DONE; - vb2->timestamp = buf->timestamp; - v4l2_m2m_buf_done(vbuf, state); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_buffer.h BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_buffer.h ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_buffer.h 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_buffer.h 2025-10-22 13:53:56.531169064 -0400 -@@ -106,7 +106,8 @@ void iris_get_internal_buffers(struct ir - int iris_create_internal_buffers(struct iris_inst *inst, u32 plane); - int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane); - int iris_destroy_internal_buffer(struct iris_inst *inst, struct iris_buffer *buffer); --int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane); -+int iris_destroy_all_internal_buffers(struct iris_inst *inst, u32 plane); -+int iris_destroy_dequeued_internal_buffers(struct iris_inst *inst, u32 plane); - int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst); - int iris_alloc_and_queue_input_int_bufs(struct iris_inst *inst); - int iris_queue_buffer(struct iris_inst *inst, struct iris_buffer *buf); -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_ctrls.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_ctrls.c ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_ctrls.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_ctrls.c 2025-10-22 13:53:56.531169064 -0400 -@@ -17,8 +17,6 @@ static inline bool iris_valid_cap_id(enu - static enum platform_inst_fw_cap_type iris_get_cap_id(u32 id) - { - switch (id) { -- case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER: -- return DEBLOCK; - case V4L2_CID_MPEG_VIDEO_H264_PROFILE: - return PROFILE; - case V4L2_CID_MPEG_VIDEO_H264_LEVEL: -@@ -34,8 +32,6 @@ static u32 iris_get_v4l2_id(enum platfor - return 0; - - switch (cap_id) { -- case DEBLOCK: -- return V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER; - case PROFILE: - return V4L2_CID_MPEG_VIDEO_H264_PROFILE; - case LEVEL: -@@ -84,8 +80,6 @@ int iris_ctrls_init(struct iris_inst *in - if (iris_get_v4l2_id(cap[idx].cap_id)) - num_ctrls++; - } -- if (!num_ctrls) -- return -EINVAL; - - /* Adding 1 to num_ctrls to include V4L2_CID_MIN_BUFFERS_FOR_CAPTURE */ - -@@ -163,6 +157,7 @@ void iris_session_init_caps(struct iris_ - core->inst_fw_caps[cap_id].value = caps[i].value; - core->inst_fw_caps[cap_id].flags = caps[i].flags; - core->inst_fw_caps[cap_id].hfi_id = caps[i].hfi_id; -+ core->inst_fw_caps[cap_id].set = caps[i].set; - } - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_hfi_gen1_command.c 2025-10-22 13:53:56.531169064 -0400 -@@ -208,8 +208,10 @@ static int iris_hfi_gen1_session_stop(st - flush_pkt.flush_type = flush_type; - - ret = iris_hfi_queue_cmd_write(core, &flush_pkt, flush_pkt.shdr.hdr.size); -- if (!ret) -+ if (!ret) { -+ inst->flush_responses_pending++; - ret = iris_wait_for_session_response(inst, true); -+ } - } - - return ret; -@@ -490,14 +492,6 @@ iris_hfi_gen1_packet_session_set_propert - packet->shdr.hdr.size += sizeof(u32) + sizeof(*wm); - break; - } -- case HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER: { -- struct hfi_enable *en = prop_data; -- u32 *in = pdata; -- -- en->enable = *in; -- packet->shdr.hdr.size += sizeof(u32) + sizeof(*en); -- break; -- } - default: - return -EINVAL; - } -@@ -546,14 +540,15 @@ static int iris_hfi_gen1_set_resolution( - struct hfi_framesize fs; - int ret; - -- fs.buffer_type = HFI_BUFFER_INPUT; -- fs.width = inst->fmt_src->fmt.pix_mp.width; -- fs.height = inst->fmt_src->fmt.pix_mp.height; -- -- ret = hfi_gen1_set_property(inst, ptype, &fs, sizeof(fs)); -- if (ret) -- return ret; -- -+ if (!iris_drc_pending(inst)) { -+ fs.buffer_type = HFI_BUFFER_INPUT; -+ fs.width = inst->fmt_src->fmt.pix_mp.width; -+ fs.height = inst->fmt_src->fmt.pix_mp.height; -+ -+ ret = hfi_gen1_set_property(inst, ptype, &fs, sizeof(fs)); -+ if (ret) -+ return ret; -+ } - fs.buffer_type = HFI_BUFFER_OUTPUT2; - fs.width = inst->fmt_dst->fmt.pix_mp.width; - fs.height = inst->fmt_dst->fmt.pix_mp.height; -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_hfi_gen1_defines.h 2025-10-22 13:53:56.531169064 -0400 -@@ -65,7 +65,6 @@ - - #define HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS 0x202001 - --#define HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER 0x1200001 - #define HFI_PROPERTY_PARAM_VDEC_DPB_COUNTS 0x120300e - #define HFI_PROPERTY_CONFIG_VDEC_ENTROPY 0x1204004 - -@@ -117,6 +116,8 @@ - #define HFI_FRAME_NOTCODED 0x7f002000 - #define HFI_FRAME_YUV 0x7f004000 - #define HFI_UNUSED_PICT 0x10000000 -+#define HFI_BUFFERFLAG_DATACORRUPT 0x00000008 -+#define HFI_BUFFERFLAG_DROP_FRAME 0x20000000 - - struct hfi_pkt_hdr { - u32 size; -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_hfi_gen1_response.c 2025-10-22 13:53:56.531169064 -0400 -@@ -200,14 +200,14 @@ static void iris_hfi_gen1_event_seq_chan - - iris_hfi_gen1_read_changed_params(inst, pkt); - -- if (inst->state != IRIS_INST_ERROR) { -- reinit_completion(&inst->flush_completion); -+ if (inst->state != IRIS_INST_ERROR && !(inst->sub_state & IRIS_INST_SUB_FIRST_IPSC)) { - - flush_pkt.shdr.hdr.size = sizeof(struct hfi_session_flush_pkt); - flush_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FLUSH; - flush_pkt.shdr.session_id = inst->session_id; - flush_pkt.flush_type = HFI_FLUSH_OUTPUT; -- iris_hfi_queue_cmd_write(inst->core, &flush_pkt, flush_pkt.shdr.hdr.size); -+ if (!iris_hfi_queue_cmd_write(inst->core, &flush_pkt, flush_pkt.shdr.hdr.size)) -+ inst->flush_responses_pending++; - } - - iris_vdec_src_change(inst); -@@ -408,7 +408,9 @@ static void iris_hfi_gen1_session_ftb_do - flush_pkt.shdr.hdr.pkt_type = HFI_CMD_SESSION_FLUSH; - flush_pkt.shdr.session_id = inst->session_id; - flush_pkt.flush_type = HFI_FLUSH_OUTPUT; -- iris_hfi_queue_cmd_write(core, &flush_pkt, flush_pkt.shdr.hdr.size); -+ if (!iris_hfi_queue_cmd_write(core, &flush_pkt, flush_pkt.shdr.hdr.size)) -+ inst->flush_responses_pending++; -+ - iris_inst_sub_state_change_drain_last(inst); - - return; -@@ -481,6 +483,12 @@ static void iris_hfi_gen1_session_ftb_do - buf->attr |= BUF_ATTR_DEQUEUED; - buf->attr |= BUF_ATTR_BUFFER_DONE; - -+ if (hfi_flags & HFI_BUFFERFLAG_DATACORRUPT) -+ flags |= V4L2_BUF_FLAG_ERROR; -+ -+ if (hfi_flags & HFI_BUFFERFLAG_DROP_FRAME) -+ flags |= V4L2_BUF_FLAG_ERROR; -+ - buf->flags |= flags; - - iris_vb2_buffer_done(inst, buf); -@@ -558,7 +566,6 @@ static void iris_hfi_gen1_handle_respons - const struct iris_hfi_gen1_response_pkt_info *pkt_info; - struct device *dev = core->dev; - struct hfi_session_pkt *pkt; -- struct completion *done; - struct iris_inst *inst; - bool found = false; - u32 i; -@@ -619,9 +626,12 @@ static void iris_hfi_gen1_handle_respons - if (shdr->error_type != HFI_ERR_NONE) - iris_inst_change_state(inst, IRIS_INST_ERROR); - -- done = pkt_info->pkt == HFI_MSG_SESSION_FLUSH ? -- &inst->flush_completion : &inst->completion; -- complete(done); -+ if (pkt_info->pkt == HFI_MSG_SESSION_FLUSH) { -+ if (!(--inst->flush_responses_pending)) -+ complete(&inst->flush_completion); -+ } else { -+ complete(&inst->completion); -+ } - } - mutex_unlock(&inst->lock); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c 2025-10-22 13:53:56.531169064 -0400 -@@ -178,7 +178,7 @@ static int iris_hfi_gen2_set_crop_offset - sizeof(u64)); - } - --static int iris_hfi_gen2_set_bit_dpeth(struct iris_inst *inst) -+static int iris_hfi_gen2_set_bit_depth(struct iris_inst *inst) - { - struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - u32 port = iris_hfi_gen2_get_port(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); -@@ -378,7 +378,7 @@ static int iris_hfi_gen2_session_set_con - {HFI_PROP_BITSTREAM_RESOLUTION, iris_hfi_gen2_set_bitstream_resolution }, - {HFI_PROP_CROP_OFFSETS, iris_hfi_gen2_set_crop_offsets }, - {HFI_PROP_CODED_FRAMES, iris_hfi_gen2_set_coded_frames }, -- {HFI_PROP_LUMA_CHROMA_BIT_DEPTH, iris_hfi_gen2_set_bit_dpeth }, -+ {HFI_PROP_LUMA_CHROMA_BIT_DEPTH, iris_hfi_gen2_set_bit_depth }, - {HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT, iris_hfi_gen2_set_min_output_count }, - {HFI_PROP_PIC_ORDER_CNT_TYPE, iris_hfi_gen2_set_picture_order_count }, - {HFI_PROP_SIGNAL_COLOR_INFO, iris_hfi_gen2_set_colorspace }, -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c 2025-10-22 13:53:56.531169064 -0400 -@@ -265,7 +265,8 @@ static int iris_hfi_gen2_handle_system_e - { - struct iris_inst *instance; - -- dev_err(core->dev, "received system error of type %#x\n", pkt->type); -+ if (pkt) -+ dev_err(core->dev, "received system error of type %#x\n", pkt->type); - - core->state = IRIS_CORE_ERROR; - -@@ -377,6 +378,11 @@ static int iris_hfi_gen2_handle_output_b - - buf->flags = iris_hfi_gen2_get_driver_buffer_flags(inst, hfi_buffer->flags); - -+ if (!buf->data_size && inst->state == IRIS_INST_STREAMING && -+ !(hfi_buffer->flags & HFI_BUF_FW_FLAG_LAST)) { -+ buf->flags |= V4L2_BUF_FLAG_ERROR; -+ } -+ - return 0; - } - -@@ -636,9 +642,6 @@ static int iris_hfi_gen2_handle_session_ - { - struct iris_inst_hfi_gen2 *inst_hfi_gen2 = to_iris_inst_hfi_gen2(inst); - -- if (pkt->port != HFI_PORT_BITSTREAM) -- return 0; -- - if (pkt->flags & HFI_FW_FLAGS_INFORMATION) - return 0; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_hfi_queue.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_hfi_queue.c ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_hfi_queue.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_hfi_queue.c 2025-10-22 13:53:56.531169064 -0400 -@@ -113,7 +113,7 @@ int iris_hfi_queue_cmd_write_locked(stru - { - struct iris_iface_q_info *q_info = &core->command_queue; - -- if (core->state == IRIS_CORE_ERROR) -+ if (core->state == IRIS_CORE_ERROR || core->state == IRIS_CORE_DEINIT) - return -EINVAL; - - if (!iris_hfi_queue_write(q_info, pkt, pkt_size)) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_instance.h BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_instance.h ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_instance.h 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_instance.h 2025-10-22 13:53:56.531169064 -0400 -@@ -27,6 +27,7 @@ - * @crop: structure of crop info - * @completion: structure of signal completions - * @flush_completion: structure of signal completions for flush cmd -+ * @flush_responses_pending: counter to track number of pending flush responses - * @fw_caps: array of supported instance firmware capabilities - * @buffers: array of different iris buffers - * @fw_min_count: minimnum count of buffers needed by fw -@@ -57,6 +58,7 @@ struct iris_inst { - struct iris_hfi_rect_desc crop; - struct completion completion; - struct completion flush_completion; -+ u32 flush_responses_pending; - struct platform_inst_fw_cap fw_caps[INST_FW_CAP_MAX]; - struct iris_buffers buffers[BUF_TYPE_MAX]; - u32 fw_min_count; -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_platform_common.h BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_platform_common.h ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_platform_common.h 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_platform_common.h 2025-10-22 13:53:56.531169064 -0400 -@@ -89,7 +89,7 @@ enum platform_inst_fw_cap_type { - CODED_FRAMES, - BIT_DEPTH, - RAP_FRAME, -- DEBLOCK, -+ TIER, - INST_FW_CAP_MAX, - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_platform_sm8250.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_platform_sm8250.c ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_platform_sm8250.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_platform_sm8250.c 2025-10-22 13:53:56.531169064 -0400 -@@ -30,15 +30,6 @@ static struct platform_inst_fw_cap inst_ - .hfi_id = HFI_PROPERTY_PARAM_WORK_MODE, - .set = iris_set_stage, - }, -- { -- .cap_id = DEBLOCK, -- .min = 0, -- .max = 1, -- .step_or_mask = 1, -- .value = 0, -- .hfi_id = HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER, -- .set = iris_set_u32, -- }, - }; - - static struct platform_inst_caps platform_inst_cap_sm8250 = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_state.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_state.c ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_state.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_state.c 2025-10-22 13:53:56.531169064 -0400 -@@ -245,7 +245,7 @@ int iris_inst_sub_state_change_pause(str - return iris_inst_change_sub_state(inst, 0, set_sub_state); - } - --static inline bool iris_drc_pending(struct iris_inst *inst) -+bool iris_drc_pending(struct iris_inst *inst) - { - return inst->sub_state & IRIS_INST_SUB_DRC && - inst->sub_state & IRIS_INST_SUB_DRC_LAST; -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_state.h BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_state.h ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_state.h 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_state.h 2025-10-22 13:53:56.531169064 -0400 -@@ -140,5 +140,6 @@ int iris_inst_sub_state_change_drain_las - int iris_inst_sub_state_change_drc_last(struct iris_inst *inst); - int iris_inst_sub_state_change_pause(struct iris_inst *inst, u32 plane); - bool iris_allow_cmd(struct iris_inst *inst, u32 cmd); -+bool iris_drc_pending(struct iris_inst *inst); - - #endif -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_vb2.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_vb2.c ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_vb2.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_vb2.c 2025-10-22 13:53:56.531169064 -0400 -@@ -259,13 +259,14 @@ int iris_vb2_buf_prepare(struct vb2_buff - return -EINVAL; - } - -- if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && -- vb2_plane_size(vb, 0) < iris_get_buffer_size(inst, BUF_OUTPUT)) -- return -EINVAL; -- if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && -- vb2_plane_size(vb, 0) < iris_get_buffer_size(inst, BUF_INPUT)) -- return -EINVAL; -- -+ if (!(inst->sub_state & IRIS_INST_SUB_DRC)) { -+ if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && -+ vb2_plane_size(vb, 0) < iris_get_buffer_size(inst, BUF_OUTPUT)) -+ return -EINVAL; -+ if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && -+ vb2_plane_size(vb, 0) < iris_get_buffer_size(inst, BUF_INPUT)) -+ return -EINVAL; -+ } - return 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_vdec.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_vdec.c ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_vdec.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_vdec.c 2025-10-22 13:53:56.531169064 -0400 -@@ -171,6 +171,11 @@ int iris_vdec_s_fmt(struct iris_inst *in - output_fmt->fmt.pix_mp.ycbcr_enc = f->fmt.pix_mp.ycbcr_enc; - output_fmt->fmt.pix_mp.quantization = f->fmt.pix_mp.quantization; - -+ /* Update capture format based on new ip w/h */ -+ output_fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, 128); -+ output_fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 32); -+ inst->buffers[BUF_OUTPUT].size = iris_get_buffer_size(inst, BUF_OUTPUT); -+ - inst->crop.left = 0; - inst->crop.top = 0; - inst->crop.width = f->fmt.pix_mp.width; -@@ -408,7 +413,7 @@ int iris_vdec_streamon_input(struct iris - - iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - -- ret = iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); -+ ret = iris_destroy_dequeued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); - if (ret) - return ret; - -@@ -496,7 +501,7 @@ int iris_vdec_streamon_output(struct iri - - iris_get_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); - -- ret = iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); -+ ret = iris_destroy_dequeued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); - if (ret) - return ret; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_vidc.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_vidc.c ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/iris/iris_vidc.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/iris/iris_vidc.c 2025-10-22 13:53:56.531169064 -0400 -@@ -221,6 +221,33 @@ static void iris_session_close(struct ir - iris_wait_for_session_response(inst, false); - } - -+static void iris_check_num_queued_internal_buffers(struct iris_inst *inst, u32 plane) -+{ -+ const struct iris_platform_data *platform_data = inst->core->iris_platform_data; -+ struct iris_buffer *buf, *next; -+ struct iris_buffers *buffers; -+ const u32 *internal_buf_type; -+ u32 internal_buffer_count, i; -+ u32 count = 0; -+ -+ if (V4L2_TYPE_IS_OUTPUT(plane)) { -+ internal_buf_type = platform_data->dec_ip_int_buf_tbl; -+ internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size; -+ } else { -+ internal_buf_type = platform_data->dec_op_int_buf_tbl; -+ internal_buffer_count = platform_data->dec_op_int_buf_tbl_size; -+ } -+ -+ for (i = 0; i < internal_buffer_count; i++) { -+ buffers = &inst->buffers[internal_buf_type[i]]; -+ list_for_each_entry_safe(buf, next, &buffers->list, list) -+ count++; -+ if (count) -+ dev_err(inst->core->dev, "%d buffer of type %d not released", -+ count, internal_buf_type[i]); -+ } -+} -+ - int iris_close(struct file *filp) - { - struct iris_inst *inst = iris_get_inst(filp, NULL); -@@ -233,8 +260,10 @@ int iris_close(struct file *filp) - iris_session_close(inst); - iris_inst_change_state(inst, IRIS_INST_DEINIT); - iris_v4l2_fh_deinit(inst); -- iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); -- iris_destroy_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); -+ iris_destroy_all_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); -+ iris_destroy_all_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); -+ iris_check_num_queued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); -+ iris_check_num_queued_internal_buffers(inst, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); - iris_remove_session(inst); - mutex_unlock(&inst->lock); - mutex_destroy(&inst->ctx_q_lock); -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/venus/core.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/venus/core.c ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/venus/core.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/venus/core.c 2025-10-22 13:53:56.531169064 -0400 -@@ -424,13 +424,13 @@ static int venus_probe(struct platform_d - INIT_DELAYED_WORK(&core->work, venus_sys_error_handler); - init_waitqueue_head(&core->sys_err_done); - -- ret = devm_request_threaded_irq(dev, core->irq, hfi_isr, venus_isr_thread, -- IRQF_TRIGGER_HIGH | IRQF_ONESHOT, -- "venus", core); -+ ret = hfi_create(core, &venus_core_ops); - if (ret) - goto err_core_put; - -- ret = hfi_create(core, &venus_core_ops); -+ ret = devm_request_threaded_irq(dev, core->irq, hfi_isr, venus_isr_thread, -+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT, -+ "venus", core); - if (ret) - goto err_core_put; - -@@ -709,11 +709,11 @@ static const struct venus_resources msm8 - }; - - static const struct freq_tbl msm8998_freq_table[] = { -- { 1944000, 465000000 }, /* 4k UHD @ 60 (decode only) */ -- { 972000, 465000000 }, /* 4k UHD @ 30 */ -- { 489600, 360000000 }, /* 1080p @ 60 */ -- { 244800, 186000000 }, /* 1080p @ 30 */ -- { 108000, 100000000 }, /* 720p @ 30 */ -+ { 1728000, 533000000 }, /* 4k UHD @ 60 (decode only) */ -+ { 1036800, 444000000 }, /* 2k @ 120 */ -+ { 829440, 355200000 }, /* 4k @ 44 */ -+ { 489600, 269330000 },/* 4k @ 30 */ -+ { 108000, 200000000 }, /* 1080p @ 60 */ - }; - - static const struct reg_val msm8998_reg_preset[] = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/venus/core.h BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/venus/core.h ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/venus/core.h 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/venus/core.h 2025-10-22 13:53:56.531169064 -0400 -@@ -28,6 +28,8 @@ - #define VIDC_RESETS_NUM_MAX 2 - #define VIDC_MAX_HIER_CODING_LAYER 6 - -+#define VENUS_MAX_FPS 240 -+ - extern int venus_fw_debug; - - struct freq_tbl { -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/venus/hfi_msgs.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/venus/hfi_msgs.c ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/venus/hfi_msgs.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/venus/hfi_msgs.c 2025-10-22 13:53:56.531169064 -0400 -@@ -33,8 +33,9 @@ static void event_seq_changed(struct ven - struct hfi_buffer_requirements *bufreq; - struct hfi_extradata_input_crop *crop; - struct hfi_dpb_counts *dpb_count; -+ u32 ptype, rem_bytes; -+ u32 size_read = 0; - u8 *data_ptr; -- u32 ptype; - - inst->error = HFI_ERR_NONE; - -@@ -44,86 +45,118 @@ static void event_seq_changed(struct ven - break; - default: - inst->error = HFI_ERR_SESSION_INVALID_PARAMETER; -- goto done; -+ inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event); -+ return; - } - - event.event_type = pkt->event_data1; - - num_properties_changed = pkt->event_data2; -- if (!num_properties_changed) { -- inst->error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES; -- goto done; -- } -+ if (!num_properties_changed) -+ goto error; - - data_ptr = (u8 *)&pkt->ext_event_data[0]; -+ rem_bytes = pkt->shdr.hdr.size - sizeof(*pkt); -+ - do { -+ if (rem_bytes < sizeof(u32)) -+ goto error; - ptype = *((u32 *)data_ptr); -+ -+ data_ptr += sizeof(u32); -+ rem_bytes -= sizeof(u32); -+ - switch (ptype) { - case HFI_PROPERTY_PARAM_FRAME_SIZE: -- data_ptr += sizeof(u32); -+ if (rem_bytes < sizeof(struct hfi_framesize)) -+ goto error; -+ - frame_sz = (struct hfi_framesize *)data_ptr; - event.width = frame_sz->width; - event.height = frame_sz->height; -- data_ptr += sizeof(*frame_sz); -+ size_read = sizeof(struct hfi_framesize); - break; - case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT: -- data_ptr += sizeof(u32); -+ if (rem_bytes < sizeof(struct hfi_profile_level)) -+ goto error; -+ - profile_level = (struct hfi_profile_level *)data_ptr; - event.profile = profile_level->profile; - event.level = profile_level->level; -- data_ptr += sizeof(*profile_level); -+ size_read = sizeof(struct hfi_profile_level); - break; - case HFI_PROPERTY_PARAM_VDEC_PIXEL_BITDEPTH: -- data_ptr += sizeof(u32); -+ if (rem_bytes < sizeof(struct hfi_bit_depth)) -+ goto error; -+ - pixel_depth = (struct hfi_bit_depth *)data_ptr; - event.bit_depth = pixel_depth->bit_depth; -- data_ptr += sizeof(*pixel_depth); -+ size_read = sizeof(struct hfi_bit_depth); - break; - case HFI_PROPERTY_PARAM_VDEC_PIC_STRUCT: -- data_ptr += sizeof(u32); -+ if (rem_bytes < sizeof(struct hfi_pic_struct)) -+ goto error; -+ - pic_struct = (struct hfi_pic_struct *)data_ptr; - event.pic_struct = pic_struct->progressive_only; -- data_ptr += sizeof(*pic_struct); -+ size_read = sizeof(struct hfi_pic_struct); - break; - case HFI_PROPERTY_PARAM_VDEC_COLOUR_SPACE: -- data_ptr += sizeof(u32); -+ if (rem_bytes < sizeof(struct hfi_colour_space)) -+ goto error; -+ - colour_info = (struct hfi_colour_space *)data_ptr; - event.colour_space = colour_info->colour_space; -- data_ptr += sizeof(*colour_info); -+ size_read = sizeof(struct hfi_colour_space); - break; - case HFI_PROPERTY_CONFIG_VDEC_ENTROPY: -- data_ptr += sizeof(u32); -+ if (rem_bytes < sizeof(u32)) -+ goto error; -+ - event.entropy_mode = *(u32 *)data_ptr; -- data_ptr += sizeof(u32); -+ size_read = sizeof(u32); - break; - case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS: -- data_ptr += sizeof(u32); -+ if (rem_bytes < sizeof(struct hfi_buffer_requirements)) -+ goto error; -+ - bufreq = (struct hfi_buffer_requirements *)data_ptr; - event.buf_count = hfi_bufreq_get_count_min(bufreq, ver); -- data_ptr += sizeof(*bufreq); -+ size_read = sizeof(struct hfi_buffer_requirements); - break; - case HFI_INDEX_EXTRADATA_INPUT_CROP: -- data_ptr += sizeof(u32); -+ if (rem_bytes < sizeof(struct hfi_extradata_input_crop)) -+ goto error; -+ - crop = (struct hfi_extradata_input_crop *)data_ptr; - event.input_crop.left = crop->left; - event.input_crop.top = crop->top; - event.input_crop.width = crop->width; - event.input_crop.height = crop->height; -- data_ptr += sizeof(*crop); -+ size_read = sizeof(struct hfi_extradata_input_crop); - break; - case HFI_PROPERTY_PARAM_VDEC_DPB_COUNTS: -- data_ptr += sizeof(u32); -+ if (rem_bytes < sizeof(struct hfi_dpb_counts)) -+ goto error; -+ - dpb_count = (struct hfi_dpb_counts *)data_ptr; - event.buf_count = dpb_count->fw_min_cnt; -- data_ptr += sizeof(*dpb_count); -+ size_read = sizeof(struct hfi_dpb_counts); - break; - default: -+ size_read = 0; - break; - } -+ data_ptr += size_read; -+ rem_bytes -= size_read; - num_properties_changed--; - } while (num_properties_changed > 0); - --done: -+ inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event); -+ return; -+ -+error: -+ inst->error = HFI_ERR_SESSION_INSUFFICIENT_RESOURCES; - inst->ops->event_notify(inst, EVT_SYS_EVENT_CHANGE, &event); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/venus/hfi_venus.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/venus/hfi_venus.c ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/venus/hfi_venus.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/venus/hfi_venus.c 2025-10-22 13:53:56.531169064 -0400 -@@ -239,6 +239,7 @@ static int venus_write_queue(struct venu - static int venus_read_queue(struct venus_hfi_device *hdev, - struct iface_queue *queue, void *pkt, u32 *tx_req) - { -+ struct hfi_pkt_hdr *pkt_hdr = NULL; - struct hfi_queue_header *qhdr; - u32 dwords, new_rd_idx; - u32 rd_idx, wr_idx, type, qsize; -@@ -304,6 +305,9 @@ static int venus_read_queue(struct venus - memcpy(pkt, rd_ptr, len); - memcpy(pkt + len, queue->qmem.kva, new_rd_idx << 2); - } -+ pkt_hdr = (struct hfi_pkt_hdr *)(pkt); -+ if ((pkt_hdr->size >> 2) != dwords) -+ return -EINVAL; - } else { - /* bad packet received, dropping */ - new_rd_idx = qhdr->write_idx; -@@ -1678,6 +1682,7 @@ void venus_hfi_destroy(struct venus_core - venus_interface_queues_release(hdev); - mutex_destroy(&hdev->lock); - kfree(hdev); -+ disable_irq(core->irq); - core->ops = NULL; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/venus/vdec.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/venus/vdec.c ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/venus/vdec.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/venus/vdec.c 2025-10-22 13:53:56.531169064 -0400 -@@ -481,11 +481,10 @@ static int vdec_s_parm(struct file *file - us_per_frame = timeperframe->numerator * (u64)USEC_PER_SEC; - do_div(us_per_frame, timeperframe->denominator); - -- if (!us_per_frame) -- return -EINVAL; -- -+ us_per_frame = clamp(us_per_frame, 1, USEC_PER_SEC); - fps = (u64)USEC_PER_SEC; - do_div(fps, us_per_frame); -+ fps = min(VENUS_MAX_FPS, fps); - - inst->fps = fps; - inst->timeperframe = *timeperframe; -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/qcom/venus/venc.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/venus/venc.c ---- BPI-Router-Linux-kernel/drivers/media/platform/qcom/venus/venc.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/qcom/venus/venc.c 2025-10-22 13:53:56.531169064 -0400 -@@ -411,11 +411,10 @@ static int venc_s_parm(struct file *file - us_per_frame = timeperframe->numerator * (u64)USEC_PER_SEC; - do_div(us_per_frame, timeperframe->denominator); - -- if (!us_per_frame) -- return -EINVAL; -- -+ us_per_frame = clamp(us_per_frame, 1, USEC_PER_SEC); - fps = (u64)USEC_PER_SEC; - do_div(fps, us_per_frame); -+ fps = min(VENUS_MAX_FPS, fps); - - inst->timeperframe = *timeperframe; - inst->fps = fps; -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/raspberrypi/pisp_be/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/raspberrypi/pisp_be/Kconfig ---- BPI-Router-Linux-kernel/drivers/media/platform/raspberrypi/pisp_be/Kconfig 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/raspberrypi/pisp_be/Kconfig 2025-10-22 13:53:56.531169064 -0400 -@@ -3,6 +3,7 @@ config VIDEO_RASPBERRYPI_PISP_BE - depends on V4L_PLATFORM_DRIVERS - depends on VIDEO_DEV - depends on ARCH_BCM2835 || COMPILE_TEST -+ depends on PM - select VIDEO_V4L2_SUBDEV_API - select MEDIA_CONTROLLER - select VIDEOBUF2_DMA_CONTIG -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c ---- BPI-Router-Linux-kernel/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/raspberrypi/pisp_be/pisp_be.c 2025-10-22 13:53:56.531169064 -0400 -@@ -1726,7 +1726,7 @@ static int pispbe_probe(struct platform_ - pm_runtime_use_autosuspend(pispbe->dev); - pm_runtime_enable(pispbe->dev); - -- ret = pispbe_runtime_resume(pispbe->dev); -+ ret = pm_runtime_resume_and_get(pispbe->dev); - if (ret) - goto pm_runtime_disable_err; - -@@ -1748,7 +1748,7 @@ static int pispbe_probe(struct platform_ - disable_devs_err: - pispbe_destroy_devices(pispbe); - pm_runtime_suspend_err: -- pispbe_runtime_suspend(pispbe->dev); -+ pm_runtime_put(pispbe->dev); - pm_runtime_disable_err: - pm_runtime_dont_use_autosuspend(pispbe->dev); - pm_runtime_disable(pispbe->dev); -@@ -1762,7 +1762,6 @@ static void pispbe_remove(struct platfor - - pispbe_destroy_devices(pispbe); - -- pispbe_runtime_suspend(pispbe->dev); - pm_runtime_dont_use_autosuspend(pispbe->dev); - pm_runtime_disable(pispbe->dev); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/raspberrypi/rp1-cfe/cfe.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/raspberrypi/rp1-cfe/cfe.c ---- BPI-Router-Linux-kernel/drivers/media/platform/raspberrypi/rp1-cfe/cfe.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/raspberrypi/rp1-cfe/cfe.c 2025-10-22 13:53:56.531169064 -0400 -@@ -1024,9 +1024,6 @@ static int cfe_queue_setup(struct vb2_qu - cfe_dbg(cfe, "%s: [%s] type:%u\n", __func__, node_desc[node->id].name, - node->buffer_queue.type); - -- if (vq->max_num_buffers + *nbuffers < 3) -- *nbuffers = 3 - vq->max_num_buffers; -- - if (*nplanes) { - if (sizes[0] < size) { - cfe_err(cfe, "sizes[0] %i < size %u\n", sizes[0], size); -@@ -1998,6 +1995,7 @@ static int cfe_register_node(struct cfe_ - q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - q->lock = &node->lock; - q->min_queued_buffers = 1; -+ q->min_reqbufs_allocation = 3; - q->dev = &cfe->pdev->dev; - - ret = vb2_queue_init(q); -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/st/stm32/stm32-csi.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/st/stm32/stm32-csi.c ---- BPI-Router-Linux-kernel/drivers/media/platform/st/stm32/stm32-csi.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/st/stm32/stm32-csi.c 2025-10-22 13:53:56.531169064 -0400 -@@ -443,8 +443,7 @@ static void stm32_csi_phy_reg_write(stru - static int stm32_csi_start(struct stm32_csi_dev *csidev, - struct v4l2_subdev_state *state) - { -- struct media_pad *src_pad = -- &csidev->s_subdev->entity.pads[csidev->s_subdev_pad_nb]; -+ struct media_pad *src_pad; - const struct stm32_csi_mbps_phy_reg *phy_regs = NULL; - struct v4l2_mbus_framefmt *sink_fmt; - const struct stm32_csi_fmts *fmt; -@@ -466,6 +465,7 @@ static int stm32_csi_start(struct stm32_ - if (!csidev->s_subdev) - return -EIO; - -+ src_pad = &csidev->s_subdev->entity.pads[csidev->s_subdev_pad_nb]; - link_freq = v4l2_get_link_freq(src_pad, - fmt->bpp, 2 * csidev->num_lanes); - if (link_freq < 0) -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c ---- BPI-Router-Linux-kernel/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c 2025-10-22 13:53:56.531169064 -0400 -@@ -619,6 +619,7 @@ static void ti_csi2rx_dma_callback(void - - if (ti_csi2rx_start_dma(csi, buf)) { - dev_err(csi->dev, "Failed to queue the next buffer for DMA\n"); -+ list_del(&buf->list); - vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); - } else { - list_move_tail(&buf->list, &dma->submitted); -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/platform/verisilicon/rockchip_vpu_hw.c BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/verisilicon/rockchip_vpu_hw.c ---- BPI-Router-Linux-kernel/drivers/media/platform/verisilicon/rockchip_vpu_hw.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/platform/verisilicon/rockchip_vpu_hw.c 2025-10-22 13:53:56.531169064 -0400 -@@ -17,7 +17,6 @@ - - #define RK3066_ACLK_MAX_FREQ (300 * 1000 * 1000) - #define RK3288_ACLK_MAX_FREQ (400 * 1000 * 1000) --#define RK3588_ACLK_MAX_FREQ (300 * 1000 * 1000) - - #define ROCKCHIP_VPU981_MIN_SIZE 64 - -@@ -454,13 +453,6 @@ static int rk3066_vpu_hw_init(struct han - return 0; - } - --static int rk3588_vpu981_hw_init(struct hantro_dev *vpu) --{ -- /* Bump ACLKs to max. possible freq. to improve performance. */ -- clk_set_rate(vpu->clocks[0].clk, RK3588_ACLK_MAX_FREQ); -- return 0; --} -- - static int rockchip_vpu_hw_init(struct hantro_dev *vpu) - { - /* Bump ACLK to max. possible freq. to improve performance. */ -@@ -821,7 +813,6 @@ const struct hantro_variant rk3588_vpu98 - .codec_ops = rk3588_vpu981_codec_ops, - .irqs = rk3588_vpu981_irqs, - .num_irqs = ARRAY_SIZE(rk3588_vpu981_irqs), -- .init = rk3588_vpu981_hw_init, - .clk_names = rk3588_vpu981_vpu_clk_names, - .num_clocks = ARRAY_SIZE(rk3588_vpu981_vpu_clk_names) - }; -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/rc/imon.c BPI-Router-Linux-kernel-6.16.12/drivers/media/rc/imon.c ---- BPI-Router-Linux-kernel/drivers/media/rc/imon.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/rc/imon.c 2025-10-22 13:53:56.531169064 -0400 -@@ -536,7 +536,9 @@ static int display_open(struct inode *in - - mutex_lock(&ictx->lock); - -- if (!ictx->display_supported) { -+ if (ictx->disconnected) { -+ retval = -ENODEV; -+ } else if (!ictx->display_supported) { - pr_err("display not supported by device\n"); - retval = -ENODEV; - } else if (ictx->display_isopen) { -@@ -598,6 +600,9 @@ static int send_packet(struct imon_conte - int retval = 0; - struct usb_ctrlrequest *control_req = NULL; - -+ if (ictx->disconnected) -+ return -ENODEV; -+ - /* Check if we need to use control or interrupt urb */ - if (!ictx->tx_control) { - pipe = usb_sndintpipe(ictx->usbdev_intf0, -@@ -949,12 +954,14 @@ static ssize_t vfd_write(struct file *fi - static const unsigned char vfd_packet6[] = { - 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF }; - -- if (ictx->disconnected) -- return -ENODEV; -- - if (mutex_lock_interruptible(&ictx->lock)) - return -ERESTARTSYS; - -+ if (ictx->disconnected) { -+ retval = -ENODEV; -+ goto exit; -+ } -+ - if (!ictx->dev_present_intf0) { - pr_err_ratelimited("no iMON device present\n"); - retval = -ENODEV; -@@ -1029,11 +1036,13 @@ static ssize_t lcd_write(struct file *fi - int retval = 0; - struct imon_context *ictx = file->private_data; - -- if (ictx->disconnected) -- return -ENODEV; -- - mutex_lock(&ictx->lock); - -+ if (ictx->disconnected) { -+ retval = -ENODEV; -+ goto exit; -+ } -+ - if (!ictx->display_supported) { - pr_err_ratelimited("no iMON display present\n"); - retval = -ENODEV; -@@ -2499,7 +2508,11 @@ static void imon_disconnect(struct usb_i - int ifnum; - - ictx = usb_get_intfdata(interface); -+ -+ mutex_lock(&ictx->lock); - ictx->disconnected = true; -+ mutex_unlock(&ictx->lock); -+ - dev = ictx->dev; - ifnum = interface->cur_altsetting->desc.bInterfaceNumber; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/test-drivers/vivid/vivid-ctrls.c BPI-Router-Linux-kernel-6.16.12/drivers/media/test-drivers/vivid/vivid-ctrls.c ---- BPI-Router-Linux-kernel/drivers/media/test-drivers/vivid/vivid-ctrls.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/test-drivers/vivid/vivid-ctrls.c 2025-10-22 13:53:56.531169064 -0400 -@@ -244,7 +244,8 @@ static const struct v4l2_ctrl_config viv - .min = 0x00, - .max = 0xff, - .step = 1, -- .dims = { 640 / PIXEL_ARRAY_DIV, 360 / PIXEL_ARRAY_DIV }, -+ .dims = { DIV_ROUND_UP(360, PIXEL_ARRAY_DIV), -+ DIV_ROUND_UP(640, PIXEL_ARRAY_DIV) }, - }; - - static const struct v4l2_ctrl_config vivid_ctrl_s32_array = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/test-drivers/vivid/vivid-vid-cap.c BPI-Router-Linux-kernel-6.16.12/drivers/media/test-drivers/vivid/vivid-vid-cap.c ---- BPI-Router-Linux-kernel/drivers/media/test-drivers/vivid/vivid-vid-cap.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/test-drivers/vivid/vivid-vid-cap.c 2025-10-22 13:53:56.531169064 -0400 -@@ -454,8 +454,8 @@ void vivid_update_format_cap(struct vivi - if (keep_controls) - return; - -- dims[0] = roundup(dev->src_rect.width, PIXEL_ARRAY_DIV); -- dims[1] = roundup(dev->src_rect.height, PIXEL_ARRAY_DIV); -+ dims[0] = DIV_ROUND_UP(dev->src_rect.height, PIXEL_ARRAY_DIV); -+ dims[1] = DIV_ROUND_UP(dev->src_rect.width, PIXEL_ARRAY_DIV); - v4l2_ctrl_modify_dimensions(dev->pixel_array, dims); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/tuners/xc5000.c BPI-Router-Linux-kernel-6.16.12/drivers/media/tuners/xc5000.c ---- BPI-Router-Linux-kernel/drivers/media/tuners/xc5000.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/tuners/xc5000.c 2025-10-22 13:53:56.531169064 -0400 -@@ -1304,7 +1304,7 @@ static void xc5000_release(struct dvb_fr - mutex_lock(&xc5000_list_mutex); - - if (priv) { -- cancel_delayed_work(&priv->timer_sleep); -+ cancel_delayed_work_sync(&priv->timer_sleep); - hybrid_tuner_release_state(priv); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/usb/gspca/vicam.c BPI-Router-Linux-kernel-6.16.12/drivers/media/usb/gspca/vicam.c ---- BPI-Router-Linux-kernel/drivers/media/usb/gspca/vicam.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/usb/gspca/vicam.c 2025-10-22 13:53:56.531169064 -0400 -@@ -227,6 +227,7 @@ static int sd_init(struct gspca_dev *gsp - const struct ihex_binrec *rec; - const struct firmware *fw; - u8 *firmware_buf; -+ int len; - - ret = request_ihex_firmware(&fw, VICAM_FIRMWARE, - &gspca_dev->dev->dev); -@@ -241,9 +242,14 @@ static int sd_init(struct gspca_dev *gsp - goto exit; - } - for (rec = (void *)fw->data; rec; rec = ihex_next_binrec(rec)) { -- memcpy(firmware_buf, rec->data, be16_to_cpu(rec->len)); -+ len = be16_to_cpu(rec->len); -+ if (len > PAGE_SIZE) { -+ ret = -EINVAL; -+ break; -+ } -+ memcpy(firmware_buf, rec->data, len); - ret = vicam_control_msg(gspca_dev, 0xff, 0, 0, firmware_buf, -- be16_to_cpu(rec->len)); -+ len); - if (ret < 0) - break; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/usb/hdpvr/hdpvr-i2c.c BPI-Router-Linux-kernel-6.16.12/drivers/media/usb/hdpvr/hdpvr-i2c.c ---- BPI-Router-Linux-kernel/drivers/media/usb/hdpvr/hdpvr-i2c.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/usb/hdpvr/hdpvr-i2c.c 2025-10-22 13:53:56.531169064 -0400 -@@ -165,10 +165,16 @@ static const struct i2c_algorithm hdpvr_ - .functionality = hdpvr_functionality, - }; - -+/* prevent invalid 0-length usb_control_msg */ -+static const struct i2c_adapter_quirks hdpvr_quirks = { -+ .flags = I2C_AQ_NO_ZERO_LEN_READ, -+}; -+ - static const struct i2c_adapter hdpvr_i2c_adapter_template = { - .name = "Hauppauge HD PVR I2C", - .owner = THIS_MODULE, - .algo = &hdpvr_algo, -+ .quirks = &hdpvr_quirks, - }; - - static int hdpvr_activate_ir(struct hdpvr_device *dev) -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/usb/usbtv/usbtv-video.c BPI-Router-Linux-kernel-6.16.12/drivers/media/usb/usbtv/usbtv-video.c ---- BPI-Router-Linux-kernel/drivers/media/usb/usbtv/usbtv-video.c 2025-10-22 13:53:23.299328723 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/usb/usbtv/usbtv-video.c 2025-10-22 13:53:56.531169064 -0400 -@@ -73,6 +73,10 @@ static int usbtv_configure_for_norm(stru - } - - if (params) { -+ if (vb2_is_busy(&usbtv->vb2q) && -+ (usbtv->width != params->cap_width || -+ usbtv->height != params->cap_height)) -+ return -EBUSY; - usbtv->width = params->cap_width; - usbtv->height = params->cap_height; - usbtv->n_chunks = usbtv->width * usbtv->height -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/usb/uvc/uvc_ctrl.c BPI-Router-Linux-kernel-6.16.12/drivers/media/usb/uvc/uvc_ctrl.c ---- BPI-Router-Linux-kernel/drivers/media/usb/uvc/uvc_ctrl.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/usb/uvc/uvc_ctrl.c 2025-10-22 13:53:56.531169064 -0400 -@@ -1483,14 +1483,28 @@ static u32 uvc_get_ctrl_bitmap(struct uv - return ~0; - } - -+/* -+ * Maximum retry count to avoid spurious errors with controls. Increasing this -+ * value does no seem to produce better results in the tested hardware. -+ */ -+#define MAX_QUERY_RETRIES 2 -+ - static int __uvc_queryctrl_boundaries(struct uvc_video_chain *chain, - struct uvc_control *ctrl, - struct uvc_control_mapping *mapping, - struct v4l2_query_ext_ctrl *v4l2_ctrl) - { - if (!ctrl->cached) { -- int ret = uvc_ctrl_populate_cache(chain, ctrl); -- if (ret < 0) -+ unsigned int retries; -+ int ret; -+ -+ for (retries = 0; retries < MAX_QUERY_RETRIES; retries++) { -+ ret = uvc_ctrl_populate_cache(chain, ctrl); -+ if (ret != -EIO) -+ break; -+ } -+ -+ if (ret) - return ret; - } - -@@ -1567,6 +1581,7 @@ static int __uvc_query_v4l2_ctrl(struct - { - struct uvc_control_mapping *master_map = NULL; - struct uvc_control *master_ctrl = NULL; -+ int ret; - - memset(v4l2_ctrl, 0, sizeof(*v4l2_ctrl)); - v4l2_ctrl->id = mapping->id; -@@ -1587,18 +1602,31 @@ static int __uvc_query_v4l2_ctrl(struct - __uvc_find_control(ctrl->entity, mapping->master_id, - &master_map, &master_ctrl, 0, 0); - if (master_ctrl && (master_ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) { -+ unsigned int retries; - s32 val; - int ret; - - if (WARN_ON(uvc_ctrl_mapping_is_compound(master_map))) - return -EIO; - -- ret = __uvc_ctrl_get(chain, master_ctrl, master_map, &val); -- if (ret < 0) -- return ret; -+ for (retries = 0; retries < MAX_QUERY_RETRIES; retries++) { -+ ret = __uvc_ctrl_get(chain, master_ctrl, master_map, -+ &val); -+ if (!ret) -+ break; -+ if (ret < 0 && ret != -EIO) -+ return ret; -+ } - -- if (val != mapping->master_manual) -- v4l2_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; -+ if (ret == -EIO) { -+ dev_warn_ratelimited(&chain->dev->udev->dev, -+ "UVC non compliance: Error %d querying master control %x (%s)\n", -+ ret, master_map->id, -+ uvc_map_get_name(master_map)); -+ } else { -+ if (val != mapping->master_manual) -+ v4l2_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; -+ } - } - - v4l2_ctrl->elem_size = uvc_mapping_v4l2_size(mapping); -@@ -1613,7 +1641,18 @@ static int __uvc_query_v4l2_ctrl(struct - return 0; - } - -- return __uvc_queryctrl_boundaries(chain, ctrl, mapping, v4l2_ctrl); -+ ret = __uvc_queryctrl_boundaries(chain, ctrl, mapping, v4l2_ctrl); -+ if (ret && !mapping->disabled) { -+ dev_warn(&chain->dev->udev->dev, -+ "UVC non compliance: permanently disabling control %x (%s), due to error %d\n", -+ mapping->id, uvc_map_get_name(mapping), ret); -+ mapping->disabled = true; -+ } -+ -+ if (mapping->disabled) -+ v4l2_ctrl->flags |= V4L2_CTRL_FLAG_DISABLED; -+ -+ return 0; - } - - int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain, -@@ -2033,18 +2072,24 @@ static int uvc_ctrl_add_event(struct v4l - goto done; - } - -- list_add_tail(&sev->node, &mapping->ev_subs); - if (sev->flags & V4L2_EVENT_SUB_FL_SEND_INITIAL) { - struct v4l2_event ev; - u32 changes = V4L2_EVENT_CTRL_CH_FLAGS; - s32 val = 0; - -+ ret = uvc_pm_get(handle->chain->dev); -+ if (ret) -+ goto done; -+ - if (uvc_ctrl_mapping_is_compound(mapping) || - __uvc_ctrl_get(handle->chain, ctrl, mapping, &val) == 0) - changes |= V4L2_EVENT_CTRL_CH_VALUE; - - uvc_ctrl_fill_event(handle->chain, &ev, ctrl, mapping, val, - changes); -+ -+ uvc_pm_put(handle->chain->dev); -+ - /* - * Mark the queue as active, allowing this initial event to be - * accepted. -@@ -2053,6 +2098,8 @@ static int uvc_ctrl_add_event(struct v4l - v4l2_event_queue_fh(sev->fh, &ev); - } - -+ list_add_tail(&sev->node, &mapping->ev_subs); -+ - done: - mutex_unlock(&handle->chain->ctrl_mutex); - return ret; -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/usb/uvc/uvc_driver.c BPI-Router-Linux-kernel-6.16.12/drivers/media/usb/uvc/uvc_driver.c ---- BPI-Router-Linux-kernel/drivers/media/usb/uvc/uvc_driver.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/usb/uvc/uvc_driver.c 2025-10-22 13:53:56.531169064 -0400 -@@ -137,6 +137,9 @@ struct uvc_entity *uvc_entity_by_id(stru - { - struct uvc_entity *entity; - -+ if (id == UVC_INVALID_ENTITY_ID) -+ return NULL; -+ - list_for_each_entry(entity, &dev->entities, list) { - if (entity->id == id) - return entity; -@@ -344,6 +347,9 @@ static int uvc_parse_format(struct uvc_d - u8 ftype; - int ret; - -+ if (buflen < 4) -+ return -EINVAL; -+ - format->type = buffer[2]; - format->index = buffer[3]; - format->frames = frames; -@@ -792,14 +798,27 @@ static const u8 uvc_media_transport_inpu - UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT; - static const u8 uvc_processing_guid[16] = UVC_GUID_UVC_PROCESSING; - --static struct uvc_entity *uvc_alloc_entity(u16 type, u16 id, -- unsigned int num_pads, unsigned int extra_size) -+static struct uvc_entity *uvc_alloc_new_entity(struct uvc_device *dev, u16 type, -+ u16 id, unsigned int num_pads, -+ unsigned int extra_size) - { - struct uvc_entity *entity; - unsigned int num_inputs; - unsigned int size; - unsigned int i; - -+ /* Per UVC 1.1+ spec 3.7.2, the ID should be non-zero. */ -+ if (id == 0) { -+ dev_err(&dev->intf->dev, "Found Unit with invalid ID 0\n"); -+ id = UVC_INVALID_ENTITY_ID; -+ } -+ -+ /* Per UVC 1.1+ spec 3.7.2, the ID is unique. */ -+ if (uvc_entity_by_id(dev, id)) { -+ dev_err(&dev->intf->dev, "Found multiple Units with ID %u\n", id); -+ id = UVC_INVALID_ENTITY_ID; -+ } -+ - extra_size = roundup(extra_size, sizeof(*entity->pads)); - if (num_pads) - num_inputs = type & UVC_TERM_OUTPUT ? num_pads : num_pads - 1; -@@ -809,7 +828,7 @@ static struct uvc_entity *uvc_alloc_enti - + num_inputs; - entity = kzalloc(size, GFP_KERNEL); - if (entity == NULL) -- return NULL; -+ return ERR_PTR(-ENOMEM); - - entity->id = id; - entity->type = type; -@@ -921,10 +940,10 @@ static int uvc_parse_vendor_control(stru - break; - } - -- unit = uvc_alloc_entity(UVC_VC_EXTENSION_UNIT, buffer[3], -- p + 1, 2*n); -- if (unit == NULL) -- return -ENOMEM; -+ unit = uvc_alloc_new_entity(dev, UVC_VC_EXTENSION_UNIT, -+ buffer[3], p + 1, 2 * n); -+ if (IS_ERR(unit)) -+ return PTR_ERR(unit); - - memcpy(unit->guid, &buffer[4], 16); - unit->extension.bNumControls = buffer[20]; -@@ -1033,10 +1052,10 @@ static int uvc_parse_standard_control(st - return -EINVAL; - } - -- term = uvc_alloc_entity(type | UVC_TERM_INPUT, buffer[3], -- 1, n + p); -- if (term == NULL) -- return -ENOMEM; -+ term = uvc_alloc_new_entity(dev, type | UVC_TERM_INPUT, -+ buffer[3], 1, n + p); -+ if (IS_ERR(term)) -+ return PTR_ERR(term); - - if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) { - term->camera.bControlSize = n; -@@ -1092,10 +1111,10 @@ static int uvc_parse_standard_control(st - return 0; - } - -- term = uvc_alloc_entity(type | UVC_TERM_OUTPUT, buffer[3], -- 1, 0); -- if (term == NULL) -- return -ENOMEM; -+ term = uvc_alloc_new_entity(dev, type | UVC_TERM_OUTPUT, -+ buffer[3], 1, 0); -+ if (IS_ERR(term)) -+ return PTR_ERR(term); - - memcpy(term->baSourceID, &buffer[7], 1); - -@@ -1114,9 +1133,10 @@ static int uvc_parse_standard_control(st - return -EINVAL; - } - -- unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, 0); -- if (unit == NULL) -- return -ENOMEM; -+ unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3], -+ p + 1, 0); -+ if (IS_ERR(unit)) -+ return PTR_ERR(unit); - - memcpy(unit->baSourceID, &buffer[5], p); - -@@ -1136,9 +1156,9 @@ static int uvc_parse_standard_control(st - return -EINVAL; - } - -- unit = uvc_alloc_entity(buffer[2], buffer[3], 2, n); -- if (unit == NULL) -- return -ENOMEM; -+ unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3], 2, n); -+ if (IS_ERR(unit)) -+ return PTR_ERR(unit); - - memcpy(unit->baSourceID, &buffer[4], 1); - unit->processing.wMaxMultiplier = -@@ -1165,9 +1185,10 @@ static int uvc_parse_standard_control(st - return -EINVAL; - } - -- unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, n); -- if (unit == NULL) -- return -ENOMEM; -+ unit = uvc_alloc_new_entity(dev, buffer[2], buffer[3], -+ p + 1, n); -+ if (IS_ERR(unit)) -+ return PTR_ERR(unit); - - memcpy(unit->guid, &buffer[4], 16); - unit->extension.bNumControls = buffer[20]; -@@ -1312,9 +1333,10 @@ static int uvc_gpio_parse(struct uvc_dev - return dev_err_probe(&dev->intf->dev, irq, - "No IRQ for privacy GPIO\n"); - -- unit = uvc_alloc_entity(UVC_EXT_GPIO_UNIT, UVC_EXT_GPIO_UNIT_ID, 0, 1); -- if (!unit) -- return -ENOMEM; -+ unit = uvc_alloc_new_entity(dev, UVC_EXT_GPIO_UNIT, -+ UVC_EXT_GPIO_UNIT_ID, 0, 1); -+ if (IS_ERR(unit)) -+ return PTR_ERR(unit); - - unit->gpio.gpio_privacy = gpio_privacy; - unit->gpio.irq = irq; -@@ -2514,6 +2536,15 @@ static const struct uvc_device_info uvc_ - * Sort these by vendor/product ID. - */ - static const struct usb_device_id uvc_ids[] = { -+ /* HP Webcam HD 2300 */ -+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE -+ | USB_DEVICE_ID_MATCH_INT_INFO, -+ .idVendor = 0x03f0, -+ .idProduct = 0xe207, -+ .bInterfaceClass = USB_CLASS_VIDEO, -+ .bInterfaceSubClass = 1, -+ .bInterfaceProtocol = 0, -+ .driver_info = (kernel_ulong_t)&uvc_quirk_stream_no_fid }, - /* Quanta ACER HD User Facing */ - { .match_flags = USB_DEVICE_ID_MATCH_DEVICE - | USB_DEVICE_ID_MATCH_INT_INFO, -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/usb/uvc/uvc_video.c BPI-Router-Linux-kernel-6.16.12/drivers/media/usb/uvc/uvc_video.c ---- BPI-Router-Linux-kernel/drivers/media/usb/uvc/uvc_video.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/usb/uvc/uvc_video.c 2025-10-22 13:53:56.531169064 -0400 -@@ -262,6 +262,15 @@ static void uvc_fixup_video_ctrl(struct - - ctrl->dwMaxPayloadTransferSize = bandwidth; - } -+ -+ if (stream->intf->num_altsetting > 1 && -+ ctrl->dwMaxPayloadTransferSize > stream->maxpsize) { -+ dev_warn_ratelimited(&stream->intf->dev, -+ "UVC non compliance: the max payload transmission size (%u) exceeds the size of the ep max packet (%u). Using the max size.\n", -+ ctrl->dwMaxPayloadTransferSize, -+ stream->maxpsize); -+ ctrl->dwMaxPayloadTransferSize = stream->maxpsize; -+ } - } - - static size_t uvc_video_ctrl_size(struct uvc_streaming *stream) -@@ -1433,12 +1442,6 @@ static void uvc_video_decode_meta(struct - if (!meta_buf || length == 2) - return; - -- if (meta_buf->length - meta_buf->bytesused < -- length + sizeof(meta->ns) + sizeof(meta->sof)) { -- meta_buf->error = 1; -- return; -- } -- - has_pts = mem[1] & UVC_STREAM_PTS; - has_scr = mem[1] & UVC_STREAM_SCR; - -@@ -1459,6 +1462,12 @@ static void uvc_video_decode_meta(struct - !memcmp(scr, stream->clock.last_scr, 6))) - return; - -+ if (meta_buf->length - meta_buf->bytesused < -+ length + sizeof(meta->ns) + sizeof(meta->sof)) { -+ meta_buf->error = 1; -+ return; -+ } -+ - meta = (struct uvc_meta_buf *)((u8 *)meta_buf->mem + meta_buf->bytesused); - local_irq_save(flags); - time = uvc_video_get_time(); -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/usb/uvc/uvcvideo.h BPI-Router-Linux-kernel-6.16.12/drivers/media/usb/uvc/uvcvideo.h ---- BPI-Router-Linux-kernel/drivers/media/usb/uvc/uvcvideo.h 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/usb/uvc/uvcvideo.h 2025-10-22 13:53:56.531169064 -0400 -@@ -41,6 +41,8 @@ - #define UVC_EXT_GPIO_UNIT 0x7ffe - #define UVC_EXT_GPIO_UNIT_ID 0x100 - -+#define UVC_INVALID_ENTITY_ID 0xffff -+ - /* ------------------------------------------------------------------------ - * Driver specific constants. - */ -@@ -134,6 +136,8 @@ struct uvc_control_mapping { - s32 master_manual; - u32 slave_ids[2]; - -+ bool disabled; -+ - const struct uvc_control_mapping *(*filter_mapping) - (struct uvc_video_chain *chain, - struct uvc_control *ctrl); -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/v4l2-core/v4l2-common.c BPI-Router-Linux-kernel-6.16.12/drivers/media/v4l2-core/v4l2-common.c ---- BPI-Router-Linux-kernel/drivers/media/v4l2-core/v4l2-common.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/v4l2-core/v4l2-common.c 2025-10-22 13:53:56.531169064 -0400 -@@ -323,6 +323,12 @@ const struct v4l2_format_info *v4l2_form - { .format = V4L2_PIX_FMT_NV61M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_P012M, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 2, 4, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2 }, - -+ /* Tiled YUV formats, non contiguous variant */ -+ { .format = V4L2_PIX_FMT_NV12MT, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2, -+ .block_w = { 64, 32, 0, 0 }, .block_h = { 32, 16, 0, 0 }}, -+ { .format = V4L2_PIX_FMT_NV12MT_16X16, .pixel_enc = V4L2_PIXEL_ENC_YUV, .mem_planes = 2, .comp_planes = 2, .bpp = { 1, 2, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 2, .vdiv = 2, -+ .block_w = { 16, 8, 0, 0 }, .block_h = { 16, 8, 0, 0 }}, -+ - /* Bayer RGB formats */ - { .format = V4L2_PIX_FMT_SBGGR8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, - { .format = V4L2_PIX_FMT_SGBRG8, .pixel_enc = V4L2_PIXEL_ENC_BAYER, .mem_planes = 1, .comp_planes = 1, .bpp = { 1, 0, 0, 0 }, .bpp_div = { 1, 1, 1, 1 }, .hdiv = 1, .vdiv = 1 }, -@@ -505,10 +511,10 @@ s64 __v4l2_get_link_freq_ctrl(struct v4l - - freq = div_u64(v4l2_ctrl_g_ctrl_int64(ctrl) * mul, div); - -- pr_warn("%s: Link frequency estimated using pixel rate: result might be inaccurate\n", -- __func__); -- pr_warn("%s: Consider implementing support for V4L2_CID_LINK_FREQ in the transmitter driver\n", -- __func__); -+ pr_warn_once("%s: Link frequency estimated using pixel rate: result might be inaccurate\n", -+ __func__); -+ pr_warn_once("%s: Consider implementing support for V4L2_CID_LINK_FREQ in the transmitter driver\n", -+ __func__); - } - - return freq > 0 ? freq : -EINVAL; -diff -purNx .git BPI-Router-Linux-kernel/drivers/media/v4l2-core/v4l2-ctrls-core.c BPI-Router-Linux-kernel-6.16.12/drivers/media/v4l2-core/v4l2-ctrls-core.c ---- BPI-Router-Linux-kernel/drivers/media/v4l2-core/v4l2-ctrls-core.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/media/v4l2-core/v4l2-ctrls-core.c 2025-10-22 13:53:56.535169045 -0400 -@@ -968,12 +968,12 @@ static int std_validate_compound(const s - - p_h264_sps->flags &= - ~V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS; -- -- if (p_h264_sps->chroma_format_idc < 3) -- p_h264_sps->flags &= -- ~V4L2_H264_SPS_FLAG_SEPARATE_COLOUR_PLANE; - } - -+ if (p_h264_sps->chroma_format_idc < 3) -+ p_h264_sps->flags &= -+ ~V4L2_H264_SPS_FLAG_SEPARATE_COLOUR_PLANE; -+ - if (p_h264_sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY) - p_h264_sps->flags &= - ~V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD; -@@ -1661,7 +1661,6 @@ void v4l2_ctrl_handler_free(struct v4l2_ - kvfree(hdl->buckets); - hdl->buckets = NULL; - hdl->cached = NULL; -- hdl->error = 0; - mutex_unlock(hdl->lock); - mutex_destroy(&hdl->_lock); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/memstick/core/memstick.c BPI-Router-Linux-kernel-6.16.12/drivers/memstick/core/memstick.c ---- BPI-Router-Linux-kernel/drivers/memstick/core/memstick.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/memstick/core/memstick.c 2025-10-22 13:53:56.535169045 -0400 -@@ -324,7 +324,7 @@ EXPORT_SYMBOL(memstick_init_req); - static int h_memstick_read_dev_id(struct memstick_dev *card, - struct memstick_request **mrq) - { -- struct ms_id_register id_reg; -+ struct ms_id_register id_reg = {}; - - if (!(*mrq)) { - memstick_init_req(&card->current_mrq, MS_TPC_READ_REG, &id_reg, -@@ -555,7 +555,6 @@ EXPORT_SYMBOL(memstick_add_host); - */ - void memstick_remove_host(struct memstick_host *host) - { -- host->removing = 1; - flush_workqueue(workqueue); - mutex_lock(&host->lock); - if (host->card) -diff -purNx .git BPI-Router-Linux-kernel/drivers/memstick/host/rtsx_usb_ms.c BPI-Router-Linux-kernel-6.16.12/drivers/memstick/host/rtsx_usb_ms.c ---- BPI-Router-Linux-kernel/drivers/memstick/host/rtsx_usb_ms.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/memstick/host/rtsx_usb_ms.c 2025-10-22 13:53:56.535169045 -0400 -@@ -812,6 +812,7 @@ static void rtsx_usb_ms_drv_remove(struc - int err; - - host->eject = true; -+ msh->removing = true; - cancel_work_sync(&host->handle_req); - cancel_delayed_work_sync(&host->poll_card); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/mfd/88pm860x-core.c BPI-Router-Linux-kernel-6.16.12/drivers/mfd/88pm860x-core.c ---- BPI-Router-Linux-kernel/drivers/mfd/88pm860x-core.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mfd/88pm860x-core.c 2025-10-22 13:53:56.535169045 -0400 -@@ -573,7 +573,6 @@ static int device_irq_init(struct pm860x - unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; - int data, mask, ret = -EINVAL; - int nr_irqs, irq_base = -1; -- struct device_node *node = i2c->dev.of_node; - - mask = PM8607_B0_MISC1_INV_INT | PM8607_B0_MISC1_INT_CLEAR - | PM8607_B0_MISC1_INT_MASK; -@@ -624,7 +623,7 @@ static int device_irq_init(struct pm860x - ret = -EBUSY; - goto out; - } -- irq_domain_create_legacy(of_fwnode_handle(node), nr_irqs, chip->irq_base, 0, -+ irq_domain_create_legacy(dev_fwnode(&i2c->dev), nr_irqs, chip->irq_base, 0, - &pm860x_irq_domain_ops, chip); - chip->core_irq = i2c->irq; - if (!chip->core_irq) -diff -purNx .git BPI-Router-Linux-kernel/drivers/mfd/axp20x.c BPI-Router-Linux-kernel-6.16.12/drivers/mfd/axp20x.c ---- BPI-Router-Linux-kernel/drivers/mfd/axp20x.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mfd/axp20x.c 2025-10-22 13:53:56.535169045 -0400 -@@ -1053,7 +1053,8 @@ static const struct mfd_cell axp152_cell - }; - - static struct mfd_cell axp313a_cells[] = { -- MFD_CELL_NAME("axp20x-regulator"), -+ /* AXP323 is sometimes paired with AXP717 as sub-PMIC */ -+ MFD_CELL_BASIC("axp20x-regulator", NULL, NULL, 0, 1), - MFD_CELL_RES("axp313a-pek", axp313a_pek_resources), - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/mfd/cros_ec_dev.c BPI-Router-Linux-kernel-6.16.12/drivers/mfd/cros_ec_dev.c ---- BPI-Router-Linux-kernel/drivers/mfd/cros_ec_dev.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mfd/cros_ec_dev.c 2025-10-22 13:53:56.535169045 -0400 -@@ -87,7 +87,6 @@ static const struct mfd_cell cros_ec_sen - }; - - static const struct mfd_cell cros_usbpd_charger_cells[] = { -- { .name = "cros-charge-control", }, - { .name = "cros-usbpd-charger", }, - { .name = "cros-usbpd-logger", }, - }; -@@ -112,6 +111,10 @@ static const struct mfd_cell cros_ec_ucs - { .name = "cros_ec_ucsi", }, - }; - -+static const struct mfd_cell cros_ec_charge_control_cells[] = { -+ { .name = "cros-charge-control", }, -+}; -+ - static const struct cros_feature_to_cells cros_subdevices[] = { - { - .id = EC_FEATURE_CEC, -@@ -148,6 +151,11 @@ static const struct cros_feature_to_cell - .mfd_cells = cros_ec_keyboard_leds_cells, - .num_cells = ARRAY_SIZE(cros_ec_keyboard_leds_cells), - }, -+ { -+ .id = EC_FEATURE_CHARGER, -+ .mfd_cells = cros_ec_charge_control_cells, -+ .num_cells = ARRAY_SIZE(cros_ec_charge_control_cells), -+ }, - }; - - static const struct mfd_cell cros_ec_platform_cells[] = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/mfd/max8925-core.c BPI-Router-Linux-kernel-6.16.12/drivers/mfd/max8925-core.c ---- BPI-Router-Linux-kernel/drivers/mfd/max8925-core.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mfd/max8925-core.c 2025-10-22 13:53:56.535169045 -0400 -@@ -656,7 +656,6 @@ static int max8925_irq_init(struct max89 - { - unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; - int ret; -- struct device_node *node = chip->dev->of_node; - - /* clear all interrupts */ - max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ1); -@@ -682,8 +681,9 @@ static int max8925_irq_init(struct max89 - return -EBUSY; - } - -- irq_domain_create_legacy(of_fwnode_handle(node), MAX8925_NR_IRQS, chip->irq_base, 0, -- &max8925_irq_domain_ops, chip); -+ irq_domain_create_legacy(dev_fwnode(chip->dev), MAX8925_NR_IRQS, -+ chip->irq_base, 0, &max8925_irq_domain_ops, -+ chip); - - /* request irq handler for pmic main irq*/ - chip->core_irq = irq; -diff -purNx .git BPI-Router-Linux-kernel/drivers/mfd/mt6397-core.c BPI-Router-Linux-kernel-6.16.12/drivers/mfd/mt6397-core.c ---- BPI-Router-Linux-kernel/drivers/mfd/mt6397-core.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mfd/mt6397-core.c 2025-10-22 13:53:56.535169045 -0400 -@@ -136,7 +136,7 @@ static const struct mfd_cell mt6323_devs - .name = "mt6323-led", - .of_compatible = "mediatek,mt6323-led" - }, { -- .name = "mtk-pmic-keys", -+ .name = "mt6323-keys", - .num_resources = ARRAY_SIZE(mt6323_keys_resources), - .resources = mt6323_keys_resources, - .of_compatible = "mediatek,mt6323-keys" -@@ -153,7 +153,7 @@ static const struct mfd_cell mt6328_devs - .name = "mt6328-regulator", - .of_compatible = "mediatek,mt6328-regulator" - }, { -- .name = "mtk-pmic-keys", -+ .name = "mt6328-keys", - .num_resources = ARRAY_SIZE(mt6328_keys_resources), - .resources = mt6328_keys_resources, - .of_compatible = "mediatek,mt6328-keys" -@@ -175,7 +175,7 @@ static const struct mfd_cell mt6357_devs - .name = "mt6357-sound", - .of_compatible = "mediatek,mt6357-sound" - }, { -- .name = "mtk-pmic-keys", -+ .name = "mt6357-keys", - .num_resources = ARRAY_SIZE(mt6357_keys_resources), - .resources = mt6357_keys_resources, - .of_compatible = "mediatek,mt6357-keys" -@@ -196,7 +196,7 @@ static const struct mfd_cell mt6331_mt63 - .name = "mt6332-regulator", - .of_compatible = "mediatek,mt6332-regulator" - }, { -- .name = "mtk-pmic-keys", -+ .name = "mt6331-keys", - .num_resources = ARRAY_SIZE(mt6331_keys_resources), - .resources = mt6331_keys_resources, - .of_compatible = "mediatek,mt6331-keys" -@@ -240,7 +240,7 @@ static const struct mfd_cell mt6359_devs - }, - { .name = "mt6359-sound", }, - { -- .name = "mtk-pmic-keys", -+ .name = "mt6359-keys", - .num_resources = ARRAY_SIZE(mt6359_keys_resources), - .resources = mt6359_keys_resources, - .of_compatible = "mediatek,mt6359-keys" -@@ -272,7 +272,7 @@ static const struct mfd_cell mt6397_devs - .name = "mt6397-pinctrl", - .of_compatible = "mediatek,mt6397-pinctrl", - }, { -- .name = "mtk-pmic-keys", -+ .name = "mt6397-keys", - .num_resources = ARRAY_SIZE(mt6397_keys_resources), - .resources = mt6397_keys_resources, - .of_compatible = "mediatek,mt6397-keys" -diff -purNx .git BPI-Router-Linux-kernel/drivers/mfd/tps65219.c BPI-Router-Linux-kernel-6.16.12/drivers/mfd/tps65219.c ---- BPI-Router-Linux-kernel/drivers/mfd/tps65219.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mfd/tps65219.c 2025-10-22 13:53:56.535169045 -0400 -@@ -190,7 +190,7 @@ static const struct resource tps65219_re - - static const struct mfd_cell tps65214_cells[] = { - MFD_CELL_RES("tps65214-regulator", tps65214_regulator_resources), -- MFD_CELL_NAME("tps65215-gpio"), -+ MFD_CELL_NAME("tps65214-gpio"), - }; - - static const struct mfd_cell tps65215_cells[] = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/mfd/twl4030-irq.c BPI-Router-Linux-kernel-6.16.12/drivers/mfd/twl4030-irq.c ---- BPI-Router-Linux-kernel/drivers/mfd/twl4030-irq.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mfd/twl4030-irq.c 2025-10-22 13:53:56.535169045 -0400 -@@ -676,7 +676,6 @@ int twl4030_init_irq(struct device *dev, - static struct irq_chip twl4030_irq_chip; - int status, i; - int irq_base, irq_end, nr_irqs; -- struct device_node *node = dev->of_node; - - /* - * TWL core and pwr interrupts must be contiguous because -@@ -691,7 +690,7 @@ int twl4030_init_irq(struct device *dev, - return irq_base; - } - -- irq_domain_create_legacy(of_fwnode_handle(node), nr_irqs, irq_base, 0, -+ irq_domain_create_legacy(dev_fwnode(dev), nr_irqs, irq_base, 0, - &irq_domain_simple_ops, NULL); - - irq_end = irq_base + TWL4030_CORE_NR_IRQS; -diff -purNx .git BPI-Router-Linux-kernel/drivers/misc/amd-sbi/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/misc/amd-sbi/Kconfig ---- BPI-Router-Linux-kernel/drivers/misc/amd-sbi/Kconfig 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/misc/amd-sbi/Kconfig 2025-10-22 13:53:56.535169045 -0400 -@@ -2,6 +2,7 @@ - config AMD_SBRMI_I2C - tristate "AMD side band RMI support" - depends on I2C -+ select REGMAP_I2C - help - Side band RMI over I2C support for AMD out of band management. - -diff -purNx .git BPI-Router-Linux-kernel/drivers/misc/amd-sbi/rmi-core.c BPI-Router-Linux-kernel-6.16.12/drivers/misc/amd-sbi/rmi-core.c ---- BPI-Router-Linux-kernel/drivers/misc/amd-sbi/rmi-core.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/misc/amd-sbi/rmi-core.c 2025-10-22 13:53:56.535169045 -0400 -@@ -42,7 +42,6 @@ - #define RD_MCA_CMD 0x86 - - /* CPUID MCAMSR mask & index */ --#define CPUID_MCA_THRD_MASK GENMASK(15, 0) - #define CPUID_MCA_THRD_INDEX 32 - #define CPUID_MCA_FUNC_MASK GENMASK(31, 0) - #define CPUID_EXT_FUNC_INDEX 56 -@@ -129,7 +128,7 @@ static int rmi_cpuid_read(struct sbrmi_d - goto exit_unlock; - } - -- thread = msg->cpu_in_out << CPUID_MCA_THRD_INDEX & CPUID_MCA_THRD_MASK; -+ thread = msg->cpu_in_out >> CPUID_MCA_THRD_INDEX; - - /* Thread > 127, Thread128 CS register, 1'b1 needs to be set to 1 */ - if (thread > 127) { -@@ -210,7 +209,7 @@ static int rmi_mca_msr_read(struct sbrmi - goto exit_unlock; - } - -- thread = msg->mcamsr_in_out << CPUID_MCA_THRD_INDEX & CPUID_MCA_THRD_MASK; -+ thread = msg->mcamsr_in_out >> CPUID_MCA_THRD_INDEX; - - /* Thread > 127, Thread128 CS register, 1'b1 needs to be set to 1 */ - if (thread > 127) { -@@ -321,6 +320,10 @@ int rmi_mailbox_xfer(struct sbrmi_data * - ret = regmap_read(data->regmap, SBRMI_OUTBNDMSG7, &ec); - if (ret || ec) - goto exit_clear_alert; -+ -+ /* Clear the input value before updating the output data */ -+ msg->mb_in_out = 0; -+ - /* - * For a read operation, the initiator (BMC) reads the firmware - * response Command Data Out[31:0] from SBRMI::OutBndMsg_inst[4:1] -@@ -373,7 +376,8 @@ static int apml_rmi_reg_xfer(struct sbrm - mutex_unlock(&data->lock); - - if (msg.rflag && !ret) -- return copy_to_user(arg, &msg, sizeof(struct apml_reg_xfer_msg)); -+ if (copy_to_user(arg, &msg, sizeof(struct apml_reg_xfer_msg))) -+ return -EFAULT; - return ret; - } - -@@ -391,7 +395,9 @@ static int apml_mailbox_xfer(struct sbrm - if (ret && ret != -EPROTOTYPE) - return ret; - -- return copy_to_user(arg, &msg, sizeof(struct apml_mbox_msg)); -+ if (copy_to_user(arg, &msg, sizeof(struct apml_mbox_msg))) -+ return -EFAULT; -+ return ret; - } - - static int apml_cpuid_xfer(struct sbrmi_data *data, struct apml_cpuid_msg __user *arg) -@@ -408,7 +414,9 @@ static int apml_cpuid_xfer(struct sbrmi_ - if (ret && ret != -EPROTOTYPE) - return ret; - -- return copy_to_user(arg, &msg, sizeof(struct apml_cpuid_msg)); -+ if (copy_to_user(arg, &msg, sizeof(struct apml_cpuid_msg))) -+ return -EFAULT; -+ return ret; - } - - static int apml_mcamsr_xfer(struct sbrmi_data *data, struct apml_mcamsr_msg __user *arg) -@@ -425,7 +433,9 @@ static int apml_mcamsr_xfer(struct sbrmi - if (ret && ret != -EPROTOTYPE) - return ret; - -- return copy_to_user(arg, &msg, sizeof(struct apml_mcamsr_msg)); -+ if (copy_to_user(arg, &msg, sizeof(struct apml_mcamsr_msg))) -+ return -EFAULT; -+ return ret; - } - - static long sbrmi_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) -diff -purNx .git BPI-Router-Linux-kernel/drivers/misc/cardreader/rtsx_usb.c BPI-Router-Linux-kernel-6.16.12/drivers/misc/cardreader/rtsx_usb.c ---- BPI-Router-Linux-kernel/drivers/misc/cardreader/rtsx_usb.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/misc/cardreader/rtsx_usb.c 2025-10-22 13:53:56.535169045 -0400 -@@ -698,6 +698,12 @@ static void rtsx_usb_disconnect(struct u - } - - #ifdef CONFIG_PM -+static int rtsx_usb_resume_child(struct device *dev, void *data) -+{ -+ pm_request_resume(dev); -+ return 0; -+} -+ - static int rtsx_usb_suspend(struct usb_interface *intf, pm_message_t message) - { - struct rtsx_ucr *ucr = -@@ -713,8 +719,10 @@ static int rtsx_usb_suspend(struct usb_i - mutex_unlock(&ucr->dev_mutex); - - /* Defer the autosuspend if card exists */ -- if (val & (SD_CD | MS_CD)) -+ if (val & (SD_CD | MS_CD)) { -+ device_for_each_child(&intf->dev, NULL, rtsx_usb_resume_child); - return -EAGAIN; -+ } - } else { - /* There is an ongoing operation*/ - return -EAGAIN; -@@ -724,12 +732,6 @@ static int rtsx_usb_suspend(struct usb_i - return 0; - } - --static int rtsx_usb_resume_child(struct device *dev, void *data) --{ -- pm_request_resume(dev); -- return 0; --} -- - static int rtsx_usb_resume(struct usb_interface *intf) - { - device_for_each_child(&intf->dev, NULL, rtsx_usb_resume_child); -diff -purNx .git BPI-Router-Linux-kernel/drivers/misc/mei/bus.c BPI-Router-Linux-kernel-6.16.12/drivers/misc/mei/bus.c ---- BPI-Router-Linux-kernel/drivers/misc/mei/bus.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/misc/mei/bus.c 2025-10-22 13:53:56.535169045 -0400 -@@ -1301,10 +1301,16 @@ static void mei_dev_bus_put(struct mei_d - static void mei_cl_bus_dev_release(struct device *dev) - { - struct mei_cl_device *cldev = to_mei_cl_device(dev); -+ struct mei_device *mdev = cldev->cl->dev; -+ struct mei_cl *cl; - - mei_cl_flush_queues(cldev->cl, NULL); - mei_me_cl_put(cldev->me_cl); - mei_dev_bus_put(cldev->bus); -+ -+ list_for_each_entry(cl, &mdev->file_list, link) -+ WARN_ON(cl == cldev->cl); -+ - kfree(cldev->cl); - kfree(cldev); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/misc/mei/platform-vsc.c BPI-Router-Linux-kernel-6.16.12/drivers/misc/mei/platform-vsc.c ---- BPI-Router-Linux-kernel/drivers/misc/mei/platform-vsc.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/misc/mei/platform-vsc.c 2025-10-22 13:53:56.535169045 -0400 -@@ -256,6 +256,9 @@ static int mei_vsc_hw_reset(struct mei_d - - vsc_tp_reset(hw->tp); - -+ if (!intr_enable) -+ return 0; -+ - return vsc_tp_init(hw->tp, mei_dev->dev); - } - -@@ -377,6 +380,8 @@ err_stop: - err_cancel: - mei_cancel_work(mei_dev); - -+ vsc_tp_register_event_cb(tp, NULL, NULL); -+ - mei_disable_interrupts(mei_dev); - - return ret; -@@ -385,11 +390,14 @@ err_cancel: - static void mei_vsc_remove(struct platform_device *pdev) - { - struct mei_device *mei_dev = platform_get_drvdata(pdev); -+ struct mei_vsc_hw *hw = mei_dev_to_vsc_hw(mei_dev); - - pm_runtime_disable(mei_dev->dev); - - mei_stop(mei_dev); - -+ vsc_tp_register_event_cb(hw->tp, NULL, NULL); -+ - mei_disable_interrupts(mei_dev); - - mei_deregister(mei_dev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/misc/mei/vsc-tp.c BPI-Router-Linux-kernel-6.16.12/drivers/misc/mei/vsc-tp.c ---- BPI-Router-Linux-kernel/drivers/misc/mei/vsc-tp.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/misc/mei/vsc-tp.c 2025-10-22 13:53:56.535169045 -0400 -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - - #include "vsc-tp.h" - -@@ -76,12 +77,12 @@ struct vsc_tp { - - atomic_t assert_cnt; - wait_queue_head_t xfer_wait; -+ struct work_struct event_work; - - vsc_tp_event_cb_t event_notify; - void *event_notify_context; -- -- /* used to protect command download */ -- struct mutex mutex; -+ struct mutex event_notify_mutex; /* protects event_notify + context */ -+ struct mutex mutex; /* protects command download */ - }; - - /* GPIO resources */ -@@ -106,17 +107,19 @@ static irqreturn_t vsc_tp_isr(int irq, v - - wake_up(&tp->xfer_wait); - -- return IRQ_WAKE_THREAD; -+ schedule_work(&tp->event_work); -+ -+ return IRQ_HANDLED; - } - --static irqreturn_t vsc_tp_thread_isr(int irq, void *data) -+static void vsc_tp_event_work(struct work_struct *work) - { -- struct vsc_tp *tp = data; -+ struct vsc_tp *tp = container_of(work, struct vsc_tp, event_work); -+ -+ guard(mutex)(&tp->event_notify_mutex); - - if (tp->event_notify) - tp->event_notify(tp->event_notify_context); -- -- return IRQ_HANDLED; - } - - /* wakeup firmware and wait for response */ -@@ -399,6 +402,8 @@ EXPORT_SYMBOL_NS_GPL(vsc_tp_need_read, " - int vsc_tp_register_event_cb(struct vsc_tp *tp, vsc_tp_event_cb_t event_cb, - void *context) - { -+ guard(mutex)(&tp->event_notify_mutex); -+ - tp->event_notify = event_cb; - tp->event_notify_context = context; - -@@ -407,37 +412,6 @@ int vsc_tp_register_event_cb(struct vsc_ - EXPORT_SYMBOL_NS_GPL(vsc_tp_register_event_cb, "VSC_TP"); - - /** -- * vsc_tp_request_irq - request irq for vsc_tp device -- * @tp: vsc_tp device handle -- */ --int vsc_tp_request_irq(struct vsc_tp *tp) --{ -- struct spi_device *spi = tp->spi; -- struct device *dev = &spi->dev; -- int ret; -- -- irq_set_status_flags(spi->irq, IRQ_DISABLE_UNLAZY); -- ret = request_threaded_irq(spi->irq, vsc_tp_isr, vsc_tp_thread_isr, -- IRQF_TRIGGER_FALLING | IRQF_ONESHOT, -- dev_name(dev), tp); -- if (ret) -- return ret; -- -- return 0; --} --EXPORT_SYMBOL_NS_GPL(vsc_tp_request_irq, "VSC_TP"); -- --/** -- * vsc_tp_free_irq - free irq for vsc_tp device -- * @tp: vsc_tp device handle -- */ --void vsc_tp_free_irq(struct vsc_tp *tp) --{ -- free_irq(tp->spi->irq, tp); --} --EXPORT_SYMBOL_NS_GPL(vsc_tp_free_irq, "VSC_TP"); -- --/** - * vsc_tp_intr_synchronize - synchronize vsc_tp interrupt - * @tp: vsc_tp device handle - */ -@@ -523,13 +497,15 @@ static int vsc_tp_probe(struct spi_devic - tp->spi = spi; - - irq_set_status_flags(spi->irq, IRQ_DISABLE_UNLAZY); -- ret = request_threaded_irq(spi->irq, vsc_tp_isr, vsc_tp_thread_isr, -+ ret = request_threaded_irq(spi->irq, NULL, vsc_tp_isr, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - dev_name(dev), tp); - if (ret) - return ret; - - mutex_init(&tp->mutex); -+ mutex_init(&tp->event_notify_mutex); -+ INIT_WORK(&tp->event_work, vsc_tp_event_work); - - /* only one child acpi device */ - ret = acpi_dev_for_each_child(ACPI_COMPANION(dev), -@@ -552,10 +528,12 @@ static int vsc_tp_probe(struct spi_devic - return 0; - - err_destroy_lock: -- mutex_destroy(&tp->mutex); -- - free_irq(spi->irq, tp); - -+ cancel_work_sync(&tp->event_work); -+ mutex_destroy(&tp->event_notify_mutex); -+ mutex_destroy(&tp->mutex); -+ - return ret; - } - -@@ -565,9 +543,11 @@ static void vsc_tp_remove(struct spi_dev - - platform_device_unregister(tp->pdev); - -- mutex_destroy(&tp->mutex); -- - free_irq(spi->irq, tp); -+ -+ cancel_work_sync(&tp->event_work); -+ mutex_destroy(&tp->event_notify_mutex); -+ mutex_destroy(&tp->mutex); - } - - static void vsc_tp_shutdown(struct spi_device *spi) -diff -purNx .git BPI-Router-Linux-kernel/drivers/misc/mei/vsc-tp.h BPI-Router-Linux-kernel-6.16.12/drivers/misc/mei/vsc-tp.h ---- BPI-Router-Linux-kernel/drivers/misc/mei/vsc-tp.h 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/misc/mei/vsc-tp.h 2025-10-22 13:53:56.535169045 -0400 -@@ -37,9 +37,6 @@ int vsc_tp_xfer(struct vsc_tp *tp, u8 cm - int vsc_tp_register_event_cb(struct vsc_tp *tp, vsc_tp_event_cb_t event_cb, - void *context); - --int vsc_tp_request_irq(struct vsc_tp *tp); --void vsc_tp_free_irq(struct vsc_tp *tp); -- - void vsc_tp_intr_enable(struct vsc_tp *tp); - void vsc_tp_intr_disable(struct vsc_tp *tp); - void vsc_tp_intr_synchronize(struct vsc_tp *tp); -diff -purNx .git BPI-Router-Linux-kernel/drivers/misc/sram.c BPI-Router-Linux-kernel-6.16.12/drivers/misc/sram.c ---- BPI-Router-Linux-kernel/drivers/misc/sram.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/misc/sram.c 2025-10-22 13:53:56.535169045 -0400 -@@ -28,7 +28,8 @@ static ssize_t sram_read(struct file *fi - { - struct sram_partition *part; - -- part = container_of(attr, struct sram_partition, battr); -+ /* Cast away the const as the attribute is part of a larger structure */ -+ part = (struct sram_partition *)container_of(attr, struct sram_partition, battr); - - mutex_lock(&part->lock); - memcpy_fromio(buf, part->base + pos, count); -@@ -43,7 +44,8 @@ static ssize_t sram_write(struct file *f - { - struct sram_partition *part; - -- part = container_of(attr, struct sram_partition, battr); -+ /* Cast away the const as the attribute is part of a larger structure */ -+ part = (struct sram_partition *)container_of(attr, struct sram_partition, battr); - - mutex_lock(&part->lock); - memcpy_toio(part->base + pos, buf, count); -@@ -164,8 +166,8 @@ static void sram_free_partitions(struct - static int sram_reserve_cmp(void *priv, const struct list_head *a, - const struct list_head *b) - { -- struct sram_reserve *ra = list_entry(a, struct sram_reserve, list); -- struct sram_reserve *rb = list_entry(b, struct sram_reserve, list); -+ const struct sram_reserve *ra = list_entry(a, struct sram_reserve, list); -+ const struct sram_reserve *rb = list_entry(b, struct sram_reserve, list); - - return ra->start - rb->start; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/mmc/core/quirks.h BPI-Router-Linux-kernel-6.16.12/drivers/mmc/core/quirks.h ---- BPI-Router-Linux-kernel/drivers/mmc/core/quirks.h 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mmc/core/quirks.h 2025-10-22 13:53:56.535169045 -0400 -@@ -44,6 +44,12 @@ static const struct mmc_fixup __maybe_un - 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd, - MMC_QUIRK_NO_UHS_DDR50_TUNING, EXT_CSD_REV_ANY), - -+ /* -+ * Some SD cards reports discard support while they don't -+ */ -+ MMC_FIXUP(CID_NAME_ANY, CID_MANFID_SANDISK_SD, 0x5344, add_quirk_sd, -+ MMC_QUIRK_BROKEN_SD_DISCARD), -+ - END_FIXUP - }; - -@@ -147,12 +153,6 @@ static const struct mmc_fixup __maybe_un - MMC_FIXUP("M62704", CID_MANFID_KINGSTON, 0x0100, add_quirk_mmc, - MMC_QUIRK_TRIM_BROKEN), - -- /* -- * Some SD cards reports discard support while they don't -- */ -- MMC_FIXUP(CID_NAME_ANY, CID_MANFID_SANDISK_SD, 0x5344, add_quirk_sd, -- MMC_QUIRK_BROKEN_SD_DISCARD), -- - END_FIXUP - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/mmc/core/sd_uhs2.c BPI-Router-Linux-kernel-6.16.12/drivers/mmc/core/sd_uhs2.c ---- BPI-Router-Linux-kernel/drivers/mmc/core/sd_uhs2.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mmc/core/sd_uhs2.c 2025-10-22 13:53:56.535169045 -0400 -@@ -91,8 +91,8 @@ static int sd_uhs2_phy_init(struct mmc_h - - err = host->ops->uhs2_control(host, UHS2_PHY_INIT); - if (err) { -- pr_err("%s: failed to initial phy for UHS-II!\n", -- mmc_hostname(host)); -+ pr_debug("%s: failed to initial phy for UHS-II!\n", -+ mmc_hostname(host)); - } - - return err; -diff -purNx .git BPI-Router-Linux-kernel/drivers/mmc/host/bcm2835.c BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/bcm2835.c ---- BPI-Router-Linux-kernel/drivers/mmc/host/bcm2835.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/bcm2835.c 2025-10-22 13:53:56.535169045 -0400 -@@ -503,7 +503,8 @@ void bcm2835_prepare_dma(struct bcm2835_ - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - - if (!desc) { -- dma_unmap_sg(dma_chan->device->dev, data->sg, sg_len, dir_data); -+ dma_unmap_sg(dma_chan->device->dev, data->sg, data->sg_len, -+ dir_data); - return; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/mmc/host/mtk-sd.c BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/mtk-sd.c ---- BPI-Router-Linux-kernel/drivers/mmc/host/mtk-sd.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/mtk-sd.c 2025-10-22 13:53:56.535169045 -0400 -@@ -846,12 +846,18 @@ static inline void msdc_dma_setup(struct - static void msdc_prepare_data(struct msdc_host *host, struct mmc_data *data) - { - if (!(data->host_cookie & MSDC_PREPARE_FLAG)) { -- data->host_cookie |= MSDC_PREPARE_FLAG; - data->sg_count = dma_map_sg(host->dev, data->sg, data->sg_len, - mmc_get_dma_dir(data)); -+ if (data->sg_count) -+ data->host_cookie |= MSDC_PREPARE_FLAG; - } - } - -+static bool msdc_data_prepared(struct mmc_data *data) -+{ -+ return data->host_cookie & MSDC_PREPARE_FLAG; -+} -+ - static void msdc_unprepare_data(struct msdc_host *host, struct mmc_data *data) - { - if (data->host_cookie & MSDC_ASYNC_FLAG) -@@ -1483,8 +1489,19 @@ static void msdc_ops_request(struct mmc_ - WARN_ON(!host->hsq_en && host->mrq); - host->mrq = mrq; - -- if (mrq->data) -+ if (mrq->data) { - msdc_prepare_data(host, mrq->data); -+ if (!msdc_data_prepared(mrq->data)) { -+ host->mrq = NULL; -+ /* -+ * Failed to prepare DMA area, fail fast before -+ * starting any commands. -+ */ -+ mrq->cmd->error = -ENOSPC; -+ mmc_request_done(mmc_from_priv(host), mrq); -+ return; -+ } -+ } - - /* if SBC is required, we have HW option and SW option. - * if HW option is enabled, and SBC does not have "special" flags, -diff -purNx .git BPI-Router-Linux-kernel/drivers/mmc/host/mvsdio.c BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/mvsdio.c ---- BPI-Router-Linux-kernel/drivers/mmc/host/mvsdio.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/mvsdio.c 2025-10-22 13:53:56.535169045 -0400 -@@ -292,7 +292,7 @@ static u32 mvsd_finish_data(struct mvsd_ - host->pio_ptr = NULL; - host->pio_size = 0; - } else { -- dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_frags, -+ dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, - mmc_get_dma_dir(data)); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/mmc/host/rtsx_usb_sdmmc.c BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/rtsx_usb_sdmmc.c ---- BPI-Router-Linux-kernel/drivers/mmc/host/rtsx_usb_sdmmc.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/rtsx_usb_sdmmc.c 2025-10-22 13:53:56.535169045 -0400 -@@ -1029,9 +1029,7 @@ static int sd_set_power_mode(struct rtsx - err = sd_power_on(host); - } - -- if (!err) -- host->power_mode = power_mode; -- -+ host->power_mode = power_mode; - return err; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/mmc/host/sdhci_am654.c BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/sdhci_am654.c ---- BPI-Router-Linux-kernel/drivers/mmc/host/sdhci_am654.c 2025-10-22 13:53:23.307328685 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/sdhci_am654.c 2025-10-22 13:53:56.535169045 -0400 -@@ -156,6 +156,7 @@ struct sdhci_am654_data { - - #define SDHCI_AM654_QUIRK_FORCE_CDTEST BIT(0) - #define SDHCI_AM654_QUIRK_SUPPRESS_V1P8_ENA BIT(1) -+#define SDHCI_AM654_QUIRK_DISABLE_HS400 BIT(2) - }; - - struct window { -@@ -613,7 +614,8 @@ static const struct sdhci_ops sdhci_am65 - static const struct sdhci_pltfm_data sdhci_am654_pdata = { - .ops = &sdhci_am654_ops, - .quirks = SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12, -- .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, -+ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | -+ SDHCI_QUIRK2_DISABLE_HW_TIMEOUT, - }; - - static const struct sdhci_am654_driver_data sdhci_am654_sr1_drvdata = { -@@ -643,7 +645,8 @@ static const struct sdhci_ops sdhci_j721 - static const struct sdhci_pltfm_data sdhci_j721e_8bit_pdata = { - .ops = &sdhci_j721e_8bit_ops, - .quirks = SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12, -- .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, -+ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | -+ SDHCI_QUIRK2_DISABLE_HW_TIMEOUT, - }; - - static const struct sdhci_am654_driver_data sdhci_j721e_8bit_drvdata = { -@@ -667,7 +670,8 @@ static const struct sdhci_ops sdhci_j721 - static const struct sdhci_pltfm_data sdhci_j721e_4bit_pdata = { - .ops = &sdhci_j721e_4bit_ops, - .quirks = SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12, -- .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, -+ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | -+ SDHCI_QUIRK2_DISABLE_HW_TIMEOUT, - }; - - static const struct sdhci_am654_driver_data sdhci_j721e_4bit_drvdata = { -@@ -762,6 +766,7 @@ static int sdhci_am654_init(struct sdhci - { - struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host); -+ struct device *dev = mmc_dev(host->mmc); - u32 ctl_cfg_2 = 0; - u32 mask; - u32 val; -@@ -817,6 +822,12 @@ static int sdhci_am654_init(struct sdhci - if (ret) - goto err_cleanup_host; - -+ if (sdhci_am654->quirks & SDHCI_AM654_QUIRK_DISABLE_HS400 && -+ host->mmc->caps2 & (MMC_CAP2_HS400 | MMC_CAP2_HS400_ES)) { -+ dev_info(dev, "HS400 mode not supported on this silicon revision, disabling it\n"); -+ host->mmc->caps2 &= ~(MMC_CAP2_HS400 | MMC_CAP2_HS400_ES); -+ } -+ - ret = __sdhci_add_host(host); - if (ret) - goto err_cleanup_host; -@@ -880,6 +891,12 @@ static int sdhci_am654_get_of_property(s - return 0; - } - -+static const struct soc_device_attribute sdhci_am654_descope_hs400[] = { -+ { .family = "AM62PX", .revision = "SR1.0" }, -+ { .family = "AM62PX", .revision = "SR1.1" }, -+ { /* sentinel */ } -+}; -+ - static const struct of_device_id sdhci_am654_of_match[] = { - { - .compatible = "ti,am654-sdhci-5.1", -@@ -972,6 +989,10 @@ static int sdhci_am654_probe(struct plat - goto err_pltfm_free; - } - -+ soc = soc_device_match(sdhci_am654_descope_hs400); -+ if (soc) -+ sdhci_am654->quirks |= SDHCI_AM654_QUIRK_DISABLE_HS400; -+ - host->mmc_host_ops.start_signal_voltage_switch = sdhci_am654_start_signal_voltage_switch; - host->mmc_host_ops.execute_tuning = sdhci_am654_execute_tuning; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/mmc/host/sdhci.c BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/sdhci.c ---- BPI-Router-Linux-kernel/drivers/mmc/host/sdhci.c 2025-10-22 13:53:23.307328685 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/sdhci.c 2025-10-22 13:53:56.535169045 -0400 -@@ -2065,15 +2065,10 @@ void sdhci_set_clock(struct sdhci_host * - - host->mmc->actual_clock = 0; - -- clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); -- if (clk & SDHCI_CLOCK_CARD_EN) -- sdhci_writew(host, clk & ~SDHCI_CLOCK_CARD_EN, -- SDHCI_CLOCK_CONTROL); -+ sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); - -- if (clock == 0) { -- sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); -+ if (clock == 0) - return; -- } - - clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); - sdhci_enable_clk(host, clk); -@@ -2372,23 +2367,6 @@ void sdhci_set_ios_common(struct mmc_hos - (ios->power_mode == MMC_POWER_UP) && - !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) - sdhci_enable_preset_value(host, false); -- -- if (!ios->clock || ios->clock != host->clock) { -- host->ops->set_clock(host, ios->clock); -- host->clock = ios->clock; -- -- if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK && -- host->clock) { -- host->timeout_clk = mmc->actual_clock ? -- mmc->actual_clock / 1000 : -- host->clock / 1000; -- mmc->max_busy_timeout = -- host->ops->get_max_timeout_count ? -- host->ops->get_max_timeout_count(host) : -- 1 << 27; -- mmc->max_busy_timeout /= host->timeout_clk; -- } -- } - } - EXPORT_SYMBOL_GPL(sdhci_set_ios_common); - -@@ -2415,6 +2393,23 @@ void sdhci_set_ios(struct mmc_host *mmc, - - sdhci_set_ios_common(mmc, ios); - -+ if (!ios->clock || ios->clock != host->clock) { -+ host->ops->set_clock(host, ios->clock); -+ host->clock = ios->clock; -+ -+ if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK && -+ host->clock) { -+ host->timeout_clk = mmc->actual_clock ? -+ mmc->actual_clock / 1000 : -+ host->clock / 1000; -+ mmc->max_busy_timeout = -+ host->ops->get_max_timeout_count ? -+ host->ops->get_max_timeout_count(host) : -+ 1 << 27; -+ mmc->max_busy_timeout /= host->timeout_clk; -+ } -+ } -+ - if (host->ops->set_power) - host->ops->set_power(host, ios->power_mode, ios->vdd); - else -diff -purNx .git BPI-Router-Linux-kernel/drivers/mmc/host/sdhci-cadence.c BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/sdhci-cadence.c ---- BPI-Router-Linux-kernel/drivers/mmc/host/sdhci-cadence.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/sdhci-cadence.c 2025-10-22 13:53:56.535169045 -0400 -@@ -433,6 +433,13 @@ static const struct sdhci_cdns_drv_data - }, - }; - -+static const struct sdhci_cdns_drv_data sdhci_eyeq_drv_data = { -+ .pltfm_data = { -+ .ops = &sdhci_cdns_ops, -+ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, -+ }, -+}; -+ - static const struct sdhci_cdns_drv_data sdhci_cdns_drv_data = { - .pltfm_data = { - .ops = &sdhci_cdns_ops, -@@ -595,6 +602,10 @@ static const struct of_device_id sdhci_c - .compatible = "amd,pensando-elba-sd4hc", - .data = &sdhci_elba_drv_data, - }, -+ { -+ .compatible = "mobileye,eyeq-sd4hc", -+ .data = &sdhci_eyeq_drv_data, -+ }, - { .compatible = "cdns,sd4hc" }, - { /* sentinel */ } - }; -diff -purNx .git BPI-Router-Linux-kernel/drivers/mmc/host/sdhci-esdhc-imx.c BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/sdhci-esdhc-imx.c ---- BPI-Router-Linux-kernel/drivers/mmc/host/sdhci-esdhc-imx.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/sdhci-esdhc-imx.c 2025-10-22 13:53:56.535169045 -0400 -@@ -2039,12 +2039,20 @@ static int sdhci_esdhc_suspend(struct de - ret = sdhci_enable_irq_wakeups(host); - if (!ret) - dev_warn(dev, "Failed to enable irq wakeup\n"); -+ } else { -+ /* -+ * For the device which works as wakeup source, no need -+ * to change the pinctrl to sleep state. -+ * e.g. For SDIO device, the interrupt share with data pin, -+ * but the pinctrl sleep state may config the data pin to -+ * other function like GPIO function to save power in PM, -+ * which finally block the SDIO wakeup function. -+ */ -+ ret = pinctrl_pm_select_sleep_state(dev); -+ if (ret) -+ return ret; - } - -- ret = pinctrl_pm_select_sleep_state(dev); -- if (ret) -- return ret; -- - ret = mmc_gpio_set_cd_wake(host->mmc, true); - - /* -diff -purNx .git BPI-Router-Linux-kernel/drivers/mmc/host/sdhci.h BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/sdhci.h ---- BPI-Router-Linux-kernel/drivers/mmc/host/sdhci.h 2025-10-22 13:53:23.307328685 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/sdhci.h 2025-10-22 13:53:56.535169045 -0400 -@@ -900,4 +900,20 @@ void sdhci_switch_external_dma(struct sd - void sdhci_set_data_timeout_irq(struct sdhci_host *host, bool enable); - void __sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd); - -+#if defined(CONFIG_DYNAMIC_DEBUG) || \ -+ (defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE)) -+#define SDHCI_DBG_ANYWAY 0 -+#elif defined(DEBUG) -+#define SDHCI_DBG_ANYWAY 1 -+#else -+#define SDHCI_DBG_ANYWAY 0 -+#endif -+ -+#define sdhci_dbg_dumpregs(host, fmt) \ -+do { \ -+ DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \ -+ if (DYNAMIC_DEBUG_BRANCH(descriptor) || SDHCI_DBG_ANYWAY) \ -+ sdhci_dumpregs(host); \ -+} while (0) -+ - #endif /* __SDHCI_HW_H */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/mmc/host/sdhci-msm.c BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/sdhci-msm.c ---- BPI-Router-Linux-kernel/drivers/mmc/host/sdhci-msm.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/sdhci-msm.c 2025-10-22 13:53:56.535169045 -0400 -@@ -1564,6 +1564,7 @@ static void sdhci_msm_check_power_status - { - struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); -+ struct mmc_host *mmc = host->mmc; - bool done = false; - u32 val = SWITCHABLE_SIGNALING_VOLTAGE; - const struct sdhci_msm_offset *msm_offset = -@@ -1621,6 +1622,12 @@ static void sdhci_msm_check_power_status - "%s: pwr_irq for req: (%d) timed out\n", - mmc_hostname(host->mmc), req_type); - } -+ -+ if ((req_type & REQ_BUS_ON) && mmc->card && !mmc->ops->get_cd(mmc)) { -+ sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); -+ host->pwr = 0; -+ } -+ - pr_debug("%s: %s: request %d done\n", mmc_hostname(host->mmc), - __func__, req_type); - } -@@ -1679,6 +1686,13 @@ static void sdhci_msm_handle_pwr_irq(str - udelay(10); - } - -+ if ((irq_status & CORE_PWRCTL_BUS_ON) && mmc->card && -+ !mmc->ops->get_cd(mmc)) { -+ msm_host_writel(msm_host, CORE_PWRCTL_BUS_FAIL, host, -+ msm_offset->core_pwrctl_ctl); -+ return; -+ } -+ - /* Handle BUS ON/OFF*/ - if (irq_status & CORE_PWRCTL_BUS_ON) { - pwr_state = REQ_BUS_ON; -diff -purNx .git BPI-Router-Linux-kernel/drivers/mmc/host/sdhci-of-arasan.c BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/sdhci-of-arasan.c ---- BPI-Router-Linux-kernel/drivers/mmc/host/sdhci-of-arasan.c 2025-10-22 13:53:23.303328703 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/sdhci-of-arasan.c 2025-10-22 13:53:56.535169045 -0400 -@@ -99,6 +99,9 @@ - #define HIWORD_UPDATE(val, mask, shift) \ - ((val) << (shift) | (mask) << ((shift) + 16)) - -+#define CD_STABLE_TIMEOUT_US 1000000 -+#define CD_STABLE_MAX_SLEEP_US 10 -+ - /** - * struct sdhci_arasan_soc_ctl_field - Field used in sdhci_arasan_soc_ctl_map - * -@@ -206,12 +209,15 @@ struct sdhci_arasan_data { - * 19MHz instead - */ - #define SDHCI_ARASAN_QUIRK_CLOCK_25_BROKEN BIT(2) -+/* Enable CD stable check before power-up */ -+#define SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE BIT(3) - }; - - struct sdhci_arasan_of_data { - const struct sdhci_arasan_soc_ctl_map *soc_ctl_map; - const struct sdhci_pltfm_data *pdata; - const struct sdhci_arasan_clk_ops *clk_ops; -+ u32 quirks; - }; - - static const struct sdhci_arasan_soc_ctl_map rk3399_soc_ctl_map = { -@@ -514,6 +520,24 @@ static int sdhci_arasan_voltage_switch(s - return -EINVAL; - } - -+static void sdhci_arasan_set_power_and_bus_voltage(struct sdhci_host *host, unsigned char mode, -+ unsigned short vdd) -+{ -+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); -+ struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host); -+ u32 reg; -+ -+ /* -+ * Ensure that the card detect logic has stabilized before powering up, this is -+ * necessary after a host controller reset. -+ */ -+ if (mode == MMC_POWER_UP && sdhci_arasan->quirks & SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE) -+ read_poll_timeout(sdhci_readl, reg, reg & SDHCI_CD_STABLE, CD_STABLE_MAX_SLEEP_US, -+ CD_STABLE_TIMEOUT_US, false, host, SDHCI_PRESENT_STATE); -+ -+ sdhci_set_power_and_bus_voltage(host, mode, vdd); -+} -+ - static const struct sdhci_ops sdhci_arasan_ops = { - .set_clock = sdhci_arasan_set_clock, - .get_max_clock = sdhci_pltfm_clk_get_max_clock, -@@ -521,7 +545,7 @@ static const struct sdhci_ops sdhci_aras - .set_bus_width = sdhci_set_bus_width, - .reset = sdhci_arasan_reset, - .set_uhs_signaling = sdhci_set_uhs_signaling, -- .set_power = sdhci_set_power_and_bus_voltage, -+ .set_power = sdhci_arasan_set_power_and_bus_voltage, - .hw_reset = sdhci_arasan_hw_reset, - }; - -@@ -570,7 +594,7 @@ static const struct sdhci_ops sdhci_aras - .set_bus_width = sdhci_set_bus_width, - .reset = sdhci_arasan_reset, - .set_uhs_signaling = sdhci_set_uhs_signaling, -- .set_power = sdhci_set_power_and_bus_voltage, -+ .set_power = sdhci_arasan_set_power_and_bus_voltage, - .irq = sdhci_arasan_cqhci_irq, - }; - -@@ -1447,6 +1471,7 @@ static const struct sdhci_arasan_clk_ops - static struct sdhci_arasan_of_data sdhci_arasan_zynqmp_data = { - .pdata = &sdhci_arasan_zynqmp_pdata, - .clk_ops = &zynqmp_clk_ops, -+ .quirks = SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE, - }; - - static const struct sdhci_arasan_clk_ops versal_clk_ops = { -@@ -1457,6 +1482,7 @@ static const struct sdhci_arasan_clk_ops - static struct sdhci_arasan_of_data sdhci_arasan_versal_data = { - .pdata = &sdhci_arasan_zynqmp_pdata, - .clk_ops = &versal_clk_ops, -+ .quirks = SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE, - }; - - static const struct sdhci_arasan_clk_ops versal_net_clk_ops = { -@@ -1467,6 +1493,7 @@ static const struct sdhci_arasan_clk_ops - static struct sdhci_arasan_of_data sdhci_arasan_versal_net_data = { - .pdata = &sdhci_arasan_versal_net_pdata, - .clk_ops = &versal_net_clk_ops, -+ .quirks = SDHCI_ARASAN_QUIRK_ENSURE_CD_STABLE, - }; - - static struct sdhci_arasan_of_data intel_keembay_emmc_data = { -@@ -1945,6 +1972,8 @@ static int sdhci_arasan_probe(struct pla - if (of_device_is_compatible(np, "rockchip,rk3399-sdhci-5.1")) - sdhci_arasan_update_clockmultiplier(host, 0x0); - -+ sdhci_arasan->quirks |= data->quirks; -+ - if (of_device_is_compatible(np, "intel,keembay-sdhci-5.1-emmc") || - of_device_is_compatible(np, "intel,keembay-sdhci-5.1-sd") || - of_device_is_compatible(np, "intel,keembay-sdhci-5.1-sdio")) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/mmc/host/sdhci-of-k1.c BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/sdhci-of-k1.c ---- BPI-Router-Linux-kernel/drivers/mmc/host/sdhci-of-k1.c 2025-10-22 13:53:23.307328685 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/sdhci-of-k1.c 2025-10-22 13:53:56.535169045 -0400 -@@ -276,7 +276,8 @@ static int spacemit_sdhci_probe(struct p - - host->mmc->caps |= MMC_CAP_NEED_RSP_BUSY; - -- if (spacemit_sdhci_get_clocks(dev, pltfm_host)) -+ ret = spacemit_sdhci_get_clocks(dev, pltfm_host); -+ if (ret) - goto err_pltfm; - - ret = sdhci_add_host(host); -diff -purNx .git BPI-Router-Linux-kernel/drivers/mmc/host/sdhci-pci-core.c BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/sdhci-pci-core.c ---- BPI-Router-Linux-kernel/drivers/mmc/host/sdhci-pci-core.c 2025-10-22 13:53:23.307328685 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/sdhci-pci-core.c 2025-10-22 13:53:56.535169045 -0400 -@@ -913,7 +913,8 @@ static bool glk_broken_cqhci(struct sdhc - { - return slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_GLK_EMMC && - (dmi_match(DMI_BIOS_VENDOR, "LENOVO") || -- dmi_match(DMI_SYS_VENDOR, "IRBIS")); -+ dmi_match(DMI_SYS_VENDOR, "IRBIS") || -+ dmi_match(DMI_SYS_VENDOR, "Positivo Tecnologia SA")); - } - - static bool jsl_broken_hs400es(struct sdhci_pci_slot *slot) -diff -purNx .git BPI-Router-Linux-kernel/drivers/mmc/host/sdhci-pci-gli.c BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/sdhci-pci-gli.c ---- BPI-Router-Linux-kernel/drivers/mmc/host/sdhci-pci-gli.c 2025-10-22 13:53:23.307328685 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/sdhci-pci-gli.c 2025-10-22 13:53:56.535169045 -0400 -@@ -283,10 +283,26 @@ - #define PCIE_GLI_9767_UHS2_CTL2_ZC_VALUE 0xb - #define PCIE_GLI_9767_UHS2_CTL2_ZC_CTL BIT(6) - #define PCIE_GLI_9767_UHS2_CTL2_ZC_CTL_VALUE 0x1 -+#define PCIE_GLI_9767_UHS2_CTL2_FORCE_PHY_RESETN BIT(13) -+#define PCIE_GLI_9767_UHS2_CTL2_FORCE_RESETN_VALUE BIT(14) - - #define GLI_MAX_TUNING_LOOP 40 - - /* Genesys Logic chipset */ -+static void sdhci_gli_mask_replay_timer_timeout(struct pci_dev *pdev) -+{ -+ int aer; -+ u32 value; -+ -+ /* mask the replay timer timeout of AER */ -+ aer = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); -+ if (aer) { -+ pci_read_config_dword(pdev, aer + PCI_ERR_COR_MASK, &value); -+ value |= PCI_ERR_COR_REP_TIMER; -+ pci_write_config_dword(pdev, aer + PCI_ERR_COR_MASK, value); -+ } -+} -+ - static inline void gl9750_wt_on(struct sdhci_host *host) - { - u32 wt_value; -@@ -607,7 +623,6 @@ static void gl9750_hw_setting(struct sdh - { - struct sdhci_pci_slot *slot = sdhci_priv(host); - struct pci_dev *pdev; -- int aer; - u32 value; - - pdev = slot->chip->pdev; -@@ -626,12 +641,7 @@ static void gl9750_hw_setting(struct sdh - pci_set_power_state(pdev, PCI_D0); - - /* mask the replay timer timeout of AER */ -- aer = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); -- if (aer) { -- pci_read_config_dword(pdev, aer + PCI_ERR_COR_MASK, &value); -- value |= PCI_ERR_COR_REP_TIMER; -- pci_write_config_dword(pdev, aer + PCI_ERR_COR_MASK, value); -- } -+ sdhci_gli_mask_replay_timer_timeout(pdev); - - gl9750_wt_off(host); - } -@@ -806,7 +816,6 @@ static void sdhci_gl9755_set_clock(struc - static void gl9755_hw_setting(struct sdhci_pci_slot *slot) - { - struct pci_dev *pdev = slot->chip->pdev; -- int aer; - u32 value; - - gl9755_wt_on(pdev); -@@ -841,12 +850,7 @@ static void gl9755_hw_setting(struct sdh - pci_set_power_state(pdev, PCI_D0); - - /* mask the replay timer timeout of AER */ -- aer = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); -- if (aer) { -- pci_read_config_dword(pdev, aer + PCI_ERR_COR_MASK, &value); -- value |= PCI_ERR_COR_REP_TIMER; -- pci_write_config_dword(pdev, aer + PCI_ERR_COR_MASK, value); -- } -+ sdhci_gli_mask_replay_timer_timeout(pdev); - - gl9755_wt_off(pdev); - } -@@ -1177,6 +1181,65 @@ static void gl9767_set_low_power_negotia - gl9767_vhs_read(pdev); - } - -+static void sdhci_gl9767_uhs2_phy_reset(struct sdhci_host *host, bool assert) -+{ -+ struct sdhci_pci_slot *slot = sdhci_priv(host); -+ struct pci_dev *pdev = slot->chip->pdev; -+ u32 value, set, clr; -+ -+ if (assert) { -+ /* Assert reset, set RESETN and clean RESETN_VALUE */ -+ set = PCIE_GLI_9767_UHS2_CTL2_FORCE_PHY_RESETN; -+ clr = PCIE_GLI_9767_UHS2_CTL2_FORCE_RESETN_VALUE; -+ } else { -+ /* De-assert reset, clean RESETN and set RESETN_VALUE */ -+ set = PCIE_GLI_9767_UHS2_CTL2_FORCE_RESETN_VALUE; -+ clr = PCIE_GLI_9767_UHS2_CTL2_FORCE_PHY_RESETN; -+ } -+ -+ gl9767_vhs_write(pdev); -+ pci_read_config_dword(pdev, PCIE_GLI_9767_UHS2_CTL2, &value); -+ value |= set; -+ pci_write_config_dword(pdev, PCIE_GLI_9767_UHS2_CTL2, value); -+ value &= ~clr; -+ pci_write_config_dword(pdev, PCIE_GLI_9767_UHS2_CTL2, value); -+ gl9767_vhs_read(pdev); -+} -+ -+static void __gl9767_uhs2_set_power(struct sdhci_host *host, unsigned char mode, unsigned short vdd) -+{ -+ u8 pwr = 0; -+ -+ if (mode != MMC_POWER_OFF) { -+ pwr = sdhci_get_vdd_value(vdd); -+ if (!pwr) -+ WARN(1, "%s: Invalid vdd %#x\n", -+ mmc_hostname(host->mmc), vdd); -+ pwr |= SDHCI_VDD2_POWER_180; -+ } -+ -+ if (host->pwr == pwr) -+ return; -+ -+ host->pwr = pwr; -+ -+ if (pwr == 0) { -+ sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); -+ } else { -+ sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); -+ -+ pwr |= SDHCI_POWER_ON; -+ sdhci_writeb(host, pwr & 0xf, SDHCI_POWER_CONTROL); -+ usleep_range(5000, 6250); -+ -+ /* Assert reset */ -+ sdhci_gl9767_uhs2_phy_reset(host, true); -+ pwr |= SDHCI_VDD2_POWER_ON; -+ sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); -+ usleep_range(5000, 6250); -+ } -+} -+ - static void sdhci_gl9767_set_clock(struct sdhci_host *host, unsigned int clock) - { - struct sdhci_pci_slot *slot = sdhci_priv(host); -@@ -1203,6 +1266,11 @@ static void sdhci_gl9767_set_clock(struc - } - - sdhci_enable_clk(host, clk); -+ -+ if (mmc_card_uhs2(host->mmc)) -+ /* De-assert reset */ -+ sdhci_gl9767_uhs2_phy_reset(host, false); -+ - gl9767_set_low_power_negotiation(pdev, true); - } - -@@ -1474,7 +1542,7 @@ static void sdhci_gl9767_set_power(struc - gl9767_vhs_read(pdev); - - sdhci_gli_overcurrent_event_enable(host, false); -- sdhci_uhs2_set_power(host, mode, vdd); -+ __gl9767_uhs2_set_power(host, mode, vdd); - sdhci_gli_overcurrent_event_enable(host, true); - } else { - gl9767_vhs_write(pdev); -@@ -1751,7 +1819,7 @@ cleanup: - return ret; - } - --static void gli_set_gl9763e(struct sdhci_pci_slot *slot) -+static void gl9763e_hw_setting(struct sdhci_pci_slot *slot) - { - struct pci_dev *pdev = slot->chip->pdev; - u32 value; -@@ -1780,6 +1848,9 @@ static void gli_set_gl9763e(struct sdhci - value |= FIELD_PREP(GLI_9763E_HS400_RXDLY, GLI_9763E_HS400_RXDLY_5); - pci_write_config_dword(pdev, PCIE_GLI_9763E_CLKRXDLY, value); - -+ /* mask the replay timer timeout of AER */ -+ sdhci_gli_mask_replay_timer_timeout(pdev); -+ - pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); - value &= ~GLI_9763E_VHS_REV; - value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_R); -@@ -1923,7 +1994,7 @@ static int gli_probe_slot_gl9763e(struct - gli_pcie_enable_msi(slot); - host->mmc_host_ops.hs400_enhanced_strobe = - gl9763e_hs400_enhanced_strobe; -- gli_set_gl9763e(slot); -+ gl9763e_hw_setting(slot); - sdhci_enable_v4_mode(host); - - return 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/mmc/host/sdhci-uhs2.c BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/sdhci-uhs2.c ---- BPI-Router-Linux-kernel/drivers/mmc/host/sdhci-uhs2.c 2025-10-22 13:53:23.307328685 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mmc/host/sdhci-uhs2.c 2025-10-22 13:53:56.535169045 -0400 -@@ -99,8 +99,8 @@ void sdhci_uhs2_reset(struct sdhci_host - /* hw clears the bit when it's done */ - if (read_poll_timeout_atomic(sdhci_readw, val, !(val & mask), 10, - UHS2_RESET_TIMEOUT_100MS, true, host, SDHCI_UHS2_SW_RESET)) { -- pr_warn("%s: %s: Reset 0x%x never completed. %s: clean reset bit.\n", __func__, -- mmc_hostname(host->mmc), (int)mask, mmc_hostname(host->mmc)); -+ pr_debug("%s: %s: Reset 0x%x never completed. %s: clean reset bit.\n", __func__, -+ mmc_hostname(host->mmc), (int)mask, mmc_hostname(host->mmc)); - sdhci_writeb(host, 0, SDHCI_UHS2_SW_RESET); - return; - } -@@ -295,7 +295,8 @@ static void __sdhci_uhs2_set_ios(struct - else - sdhci_uhs2_set_power(host, ios->power_mode, ios->vdd); - -- sdhci_set_clock(host, host->clock); -+ host->ops->set_clock(host, ios->clock); -+ host->clock = ios->clock; - } - - static int sdhci_uhs2_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -@@ -335,8 +336,8 @@ static int sdhci_uhs2_interface_detect(s - if (read_poll_timeout(sdhci_readl, val, (val & SDHCI_UHS2_IF_DETECT), - 100, UHS2_INTERFACE_DETECT_TIMEOUT_100MS, true, - host, SDHCI_PRESENT_STATE)) { -- pr_warn("%s: not detect UHS2 interface in 100ms.\n", mmc_hostname(host->mmc)); -- sdhci_dumpregs(host); -+ pr_debug("%s: not detect UHS2 interface in 100ms.\n", mmc_hostname(host->mmc)); -+ sdhci_dbg_dumpregs(host, "UHS2 interface detect timeout in 100ms"); - return -EIO; - } - -@@ -345,8 +346,8 @@ static int sdhci_uhs2_interface_detect(s - - if (read_poll_timeout(sdhci_readl, val, (val & SDHCI_UHS2_LANE_SYNC), - 100, UHS2_LANE_SYNC_TIMEOUT_150MS, true, host, SDHCI_PRESENT_STATE)) { -- pr_warn("%s: UHS2 Lane sync fail in 150ms.\n", mmc_hostname(host->mmc)); -- sdhci_dumpregs(host); -+ pr_debug("%s: UHS2 Lane sync fail in 150ms.\n", mmc_hostname(host->mmc)); -+ sdhci_dbg_dumpregs(host, "UHS2 Lane sync fail in 150ms"); - return -EIO; - } - -@@ -417,12 +418,12 @@ static int sdhci_uhs2_do_detect_init(str - host->ops->uhs2_pre_detect_init(host); - - if (sdhci_uhs2_interface_detect(host)) { -- pr_warn("%s: cannot detect UHS2 interface.\n", mmc_hostname(host->mmc)); -+ pr_debug("%s: cannot detect UHS2 interface.\n", mmc_hostname(host->mmc)); - return -EIO; - } - - if (sdhci_uhs2_init(host)) { -- pr_warn("%s: UHS2 init fail.\n", mmc_hostname(host->mmc)); -+ pr_debug("%s: UHS2 init fail.\n", mmc_hostname(host->mmc)); - return -EIO; - } - -@@ -504,8 +505,8 @@ static int sdhci_uhs2_check_dormant(stru - if (read_poll_timeout(sdhci_readl, val, (val & SDHCI_UHS2_IN_DORMANT_STATE), - 100, UHS2_CHECK_DORMANT_TIMEOUT_100MS, true, host, - SDHCI_PRESENT_STATE)) { -- pr_warn("%s: UHS2 IN_DORMANT fail in 100ms.\n", mmc_hostname(host->mmc)); -- sdhci_dumpregs(host); -+ pr_debug("%s: UHS2 IN_DORMANT fail in 100ms.\n", mmc_hostname(host->mmc)); -+ sdhci_dbg_dumpregs(host, "UHS2 IN_DORMANT fail in 100ms"); - return -EIO; - } - return 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/most/core.c BPI-Router-Linux-kernel-6.16.12/drivers/most/core.c ---- BPI-Router-Linux-kernel/drivers/most/core.c 2025-10-22 13:53:23.307328685 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/most/core.c 2025-10-22 13:53:56.535169045 -0400 -@@ -538,8 +538,8 @@ static struct most_channel *get_channel( - dev = bus_find_device_by_name(&mostbus, NULL, mdev); - if (!dev) - return NULL; -- put_device(dev); - iface = dev_get_drvdata(dev); -+ put_device(dev); - list_for_each_entry_safe(c, tmp, &iface->p->channel_list, list) { - if (!strcmp(dev_name(&c->dev), mdev_ch)) - return c; -diff -purNx .git BPI-Router-Linux-kernel/drivers/mtd/ftl.c BPI-Router-Linux-kernel-6.16.12/drivers/mtd/ftl.c ---- BPI-Router-Linux-kernel/drivers/mtd/ftl.c 2025-10-22 13:53:23.307328685 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mtd/ftl.c 2025-10-22 13:53:56.535169045 -0400 -@@ -344,7 +344,7 @@ static int erase_xfer(partition_t *part, - return -ENOMEM; - - erase->addr = xfer->Offset; -- erase->len = 1 << part->header.EraseUnitSize; -+ erase->len = 1ULL << part->header.EraseUnitSize; - - ret = mtd_erase(part->mbd.mtd, erase); - if (!ret) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/mtd/mtdchar.c BPI-Router-Linux-kernel-6.16.12/drivers/mtd/mtdchar.c ---- BPI-Router-Linux-kernel/drivers/mtd/mtdchar.c 2025-10-22 13:53:23.307328685 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mtd/mtdchar.c 2025-10-22 13:53:56.539169026 -0400 -@@ -559,7 +559,7 @@ static int mtdchar_blkpg_ioctl(struct mt - /* Sanitize user input */ - p.devname[BLKPG_DEVNAMELTH - 1] = '\0'; - -- return mtd_add_partition(mtd, p.devname, p.start, p.length, NULL); -+ return mtd_add_partition(mtd, p.devname, p.start, p.length); - - case BLKPG_DEL_PARTITION: - -diff -purNx .git BPI-Router-Linux-kernel/drivers/mtd/mtdcore.c BPI-Router-Linux-kernel-6.16.12/drivers/mtd/mtdcore.c ---- BPI-Router-Linux-kernel/drivers/mtd/mtdcore.c 2025-10-22 13:53:23.307328685 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mtd/mtdcore.c 2025-10-22 13:53:56.539169026 -0400 -@@ -68,13 +68,7 @@ static struct class mtd_class = { - .pm = MTD_CLS_PM_OPS, - }; - --static struct class mtd_master_class = { -- .name = "mtd_master", -- .pm = MTD_CLS_PM_OPS, --}; -- - static DEFINE_IDR(mtd_idr); --static DEFINE_IDR(mtd_master_idr); - - /* These are exported solely for the purpose of mtd_blkdevs.c. You - should not use them for _anything_ else */ -@@ -89,9 +83,8 @@ EXPORT_SYMBOL_GPL(__mtd_next_device); - - static LIST_HEAD(mtd_notifiers); - --#define MTD_MASTER_DEVS 255 -+ - #define MTD_DEVT(index) MKDEV(MTD_CHAR_MAJOR, (index)*2) --static dev_t mtd_master_devt; - - /* REVISIT once MTD uses the driver model better, whoever allocates - * the mtd_info will probably want to use the release() hook... -@@ -111,17 +104,6 @@ static void mtd_release(struct device *d - device_destroy(&mtd_class, index + 1); - } - --static void mtd_master_release(struct device *dev) --{ -- struct mtd_info *mtd = dev_get_drvdata(dev); -- -- idr_remove(&mtd_master_idr, mtd->index); -- of_node_put(mtd_get_of_node(mtd)); -- -- if (mtd_is_partition(mtd)) -- release_mtd_partition(mtd); --} -- - static void mtd_device_release(struct kref *kref) - { - struct mtd_info *mtd = container_of(kref, struct mtd_info, refcnt); -@@ -385,11 +367,6 @@ static const struct device_type mtd_devt - .release = mtd_release, - }; - --static const struct device_type mtd_master_devtype = { -- .name = "mtd_master", -- .release = mtd_master_release, --}; -- - static bool mtd_expert_analysis_mode; - - #ifdef CONFIG_DEBUG_FS -@@ -657,13 +634,13 @@ exit_parent: - /** - * add_mtd_device - register an MTD device - * @mtd: pointer to new MTD device info structure -- * @partitioned: create partitioned device - * - * Add a device to the list of MTD devices present in the system, and - * notify each currently active MTD 'user' of its arrival. Returns - * zero on success or non-zero on failure. - */ --int add_mtd_device(struct mtd_info *mtd, bool partitioned) -+ -+int add_mtd_device(struct mtd_info *mtd) - { - struct device_node *np = mtd_get_of_node(mtd); - struct mtd_info *master = mtd_get_master(mtd); -@@ -710,17 +687,10 @@ int add_mtd_device(struct mtd_info *mtd, - ofidx = -1; - if (np) - ofidx = of_alias_get_id(np, "mtd"); -- if (partitioned) { -- if (ofidx >= 0) -- i = idr_alloc(&mtd_idr, mtd, ofidx, ofidx + 1, GFP_KERNEL); -- else -- i = idr_alloc(&mtd_idr, mtd, 0, 0, GFP_KERNEL); -- } else { -- if (ofidx >= 0) -- i = idr_alloc(&mtd_master_idr, mtd, ofidx, ofidx + 1, GFP_KERNEL); -- else -- i = idr_alloc(&mtd_master_idr, mtd, 0, 0, GFP_KERNEL); -- } -+ if (ofidx >= 0) -+ i = idr_alloc(&mtd_idr, mtd, ofidx, ofidx + 1, GFP_KERNEL); -+ else -+ i = idr_alloc(&mtd_idr, mtd, 0, 0, GFP_KERNEL); - if (i < 0) { - error = i; - goto fail_locked; -@@ -768,18 +738,10 @@ int add_mtd_device(struct mtd_info *mtd, - /* Caller should have set dev.parent to match the - * physical device, if appropriate. - */ -- if (partitioned) { -- mtd->dev.type = &mtd_devtype; -- mtd->dev.class = &mtd_class; -- mtd->dev.devt = MTD_DEVT(i); -- dev_set_name(&mtd->dev, "mtd%d", i); -- error = dev_set_name(&mtd->dev, "mtd%d", i); -- } else { -- mtd->dev.type = &mtd_master_devtype; -- mtd->dev.class = &mtd_master_class; -- mtd->dev.devt = MKDEV(MAJOR(mtd_master_devt), i); -- error = dev_set_name(&mtd->dev, "mtd_master%d", i); -- } -+ mtd->dev.type = &mtd_devtype; -+ mtd->dev.class = &mtd_class; -+ mtd->dev.devt = MTD_DEVT(i); -+ error = dev_set_name(&mtd->dev, "mtd%d", i); - if (error) - goto fail_devname; - dev_set_drvdata(&mtd->dev, mtd); -@@ -787,7 +749,6 @@ int add_mtd_device(struct mtd_info *mtd, - of_node_get(mtd_get_of_node(mtd)); - error = device_register(&mtd->dev); - if (error) { -- pr_err("mtd: %s device_register fail %d\n", mtd->name, error); - put_device(&mtd->dev); - goto fail_added; - } -@@ -799,13 +760,10 @@ int add_mtd_device(struct mtd_info *mtd, - - mtd_debugfs_populate(mtd); - -- if (partitioned) { -- device_create(&mtd_class, mtd->dev.parent, MTD_DEVT(i) + 1, NULL, -- "mtd%dro", i); -- } -+ device_create(&mtd_class, mtd->dev.parent, MTD_DEVT(i) + 1, NULL, -+ "mtd%dro", i); - -- pr_debug("mtd: Giving out %spartitioned device %d to %s\n", -- partitioned ? "" : "un-", i, mtd->name); -+ pr_debug("mtd: Giving out device %d to %s\n", i, mtd->name); - /* No need to get a refcount on the module containing - the notifier, since we hold the mtd_table_mutex */ - list_for_each_entry(not, &mtd_notifiers, list) -@@ -813,16 +771,13 @@ int add_mtd_device(struct mtd_info *mtd, - - mutex_unlock(&mtd_table_mutex); - -- if (partitioned) { -- if (of_property_read_bool(mtd_get_of_node(mtd), "linux,rootfs")) { -- if (IS_BUILTIN(CONFIG_MTD)) { -- pr_info("mtd: setting mtd%d (%s) as root device\n", -- mtd->index, mtd->name); -- ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, mtd->index); -- } else { -- pr_warn("mtd: can't set mtd%d (%s) as root device - mtd must be builtin\n", -- mtd->index, mtd->name); -- } -+ if (of_property_read_bool(mtd_get_of_node(mtd), "linux,rootfs")) { -+ if (IS_BUILTIN(CONFIG_MTD)) { -+ pr_info("mtd: setting mtd%d (%s) as root device\n", mtd->index, mtd->name); -+ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, mtd->index); -+ } else { -+ pr_warn("mtd: can't set mtd%d (%s) as root device - mtd must be builtin\n", -+ mtd->index, mtd->name); - } - } - -@@ -838,10 +793,7 @@ fail_nvmem_add: - fail_added: - of_node_put(mtd_get_of_node(mtd)); - fail_devname: -- if (partitioned) -- idr_remove(&mtd_idr, i); -- else -- idr_remove(&mtd_master_idr, i); -+ idr_remove(&mtd_idr, i); - fail_locked: - mutex_unlock(&mtd_table_mutex); - return error; -@@ -859,14 +811,12 @@ fail_locked: - - int del_mtd_device(struct mtd_info *mtd) - { -- struct mtd_notifier *not; -- struct idr *idr; - int ret; -+ struct mtd_notifier *not; - - mutex_lock(&mtd_table_mutex); - -- idr = mtd->dev.class == &mtd_class ? &mtd_idr : &mtd_master_idr; -- if (idr_find(idr, mtd->index) != mtd) { -+ if (idr_find(&mtd_idr, mtd->index) != mtd) { - ret = -ENODEV; - goto out_error; - } -@@ -1106,7 +1056,6 @@ int mtd_device_parse_register(struct mtd - const struct mtd_partition *parts, - int nr_parts) - { -- struct mtd_info *parent; - int ret, err; - - mtd_set_dev_defaults(mtd); -@@ -1115,30 +1064,25 @@ int mtd_device_parse_register(struct mtd - if (ret) - goto out; - -- ret = add_mtd_device(mtd, false); -- if (ret) -- goto out; -- - if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) { -- ret = mtd_add_partition(mtd, mtd->name, 0, MTDPART_SIZ_FULL, &parent); -+ ret = add_mtd_device(mtd); - if (ret) - goto out; -- -- } else { -- parent = mtd; - } - - /* Prefer parsed partitions over driver-provided fallback */ -- ret = parse_mtd_partitions(parent, types, parser_data); -+ ret = parse_mtd_partitions(mtd, types, parser_data); - if (ret == -EPROBE_DEFER) - goto out; - - if (ret > 0) - ret = 0; - else if (nr_parts) -- ret = add_mtd_partitions(parent, parts, nr_parts); -- else if (!IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) -- ret = mtd_add_partition(parent, mtd->name, 0, MTDPART_SIZ_FULL, NULL); -+ ret = add_mtd_partitions(mtd, parts, nr_parts); -+ else if (!device_is_registered(&mtd->dev)) -+ ret = add_mtd_device(mtd); -+ else -+ ret = 0; - - if (ret) - goto out; -@@ -1158,14 +1102,13 @@ int mtd_device_parse_register(struct mtd - register_reboot_notifier(&mtd->reboot_notifier); - } - -- return 0; - out: -- nvmem_unregister(mtd->otp_user_nvmem); -- nvmem_unregister(mtd->otp_factory_nvmem); -- -- del_mtd_partitions(mtd); -+ if (ret) { -+ nvmem_unregister(mtd->otp_user_nvmem); -+ nvmem_unregister(mtd->otp_factory_nvmem); -+ } - -- if (device_is_registered(&mtd->dev)) { -+ if (ret && device_is_registered(&mtd->dev)) { - err = del_mtd_device(mtd); - if (err) - pr_err("Error when deleting MTD device (%d)\n", err); -@@ -1324,7 +1267,8 @@ int __get_mtd_device(struct mtd_info *mt - mtd = mtd->parent; - } - -- kref_get(&master->refcnt); -+ if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) -+ kref_get(&master->refcnt); - - return 0; - } -@@ -1418,7 +1362,8 @@ void __put_mtd_device(struct mtd_info *m - mtd = parent; - } - -- kref_put(&master->refcnt, mtd_device_release); -+ if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) -+ kref_put(&master->refcnt, mtd_device_release); - - module_put(master->owner); - -@@ -2585,16 +2530,6 @@ static int __init init_mtd(void) - if (ret) - goto err_reg; - -- ret = class_register(&mtd_master_class); -- if (ret) -- goto err_reg2; -- -- ret = alloc_chrdev_region(&mtd_master_devt, 0, MTD_MASTER_DEVS, "mtd_master"); -- if (ret < 0) { -- pr_err("unable to allocate char dev region\n"); -- goto err_chrdev; -- } -- - mtd_bdi = mtd_bdi_init("mtd"); - if (IS_ERR(mtd_bdi)) { - ret = PTR_ERR(mtd_bdi); -@@ -2619,10 +2554,6 @@ out_procfs: - bdi_unregister(mtd_bdi); - bdi_put(mtd_bdi); - err_bdi: -- unregister_chrdev_region(mtd_master_devt, MTD_MASTER_DEVS); --err_chrdev: -- class_unregister(&mtd_master_class); --err_reg2: - class_unregister(&mtd_class); - err_reg: - pr_err("Error registering mtd class or bdi: %d\n", ret); -@@ -2636,12 +2567,9 @@ static void __exit cleanup_mtd(void) - if (proc_mtd) - remove_proc_entry("mtd", NULL); - class_unregister(&mtd_class); -- class_unregister(&mtd_master_class); -- unregister_chrdev_region(mtd_master_devt, MTD_MASTER_DEVS); - bdi_unregister(mtd_bdi); - bdi_put(mtd_bdi); - idr_destroy(&mtd_idr); -- idr_destroy(&mtd_master_idr); - } - - module_init(init_mtd); -diff -purNx .git BPI-Router-Linux-kernel/drivers/mtd/mtdcore.h BPI-Router-Linux-kernel-6.16.12/drivers/mtd/mtdcore.h ---- BPI-Router-Linux-kernel/drivers/mtd/mtdcore.h 2025-10-22 13:53:23.307328685 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mtd/mtdcore.h 2025-10-22 13:53:56.539169026 -0400 -@@ -8,7 +8,7 @@ extern struct mutex mtd_table_mutex; - extern struct backing_dev_info *mtd_bdi; - - struct mtd_info *__mtd_next_device(int i); --int __must_check add_mtd_device(struct mtd_info *mtd, bool partitioned); -+int __must_check add_mtd_device(struct mtd_info *mtd); - int del_mtd_device(struct mtd_info *mtd); - int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int); - int del_mtd_partitions(struct mtd_info *); -diff -purNx .git BPI-Router-Linux-kernel/drivers/mtd/mtdpart.c BPI-Router-Linux-kernel-6.16.12/drivers/mtd/mtdpart.c ---- BPI-Router-Linux-kernel/drivers/mtd/mtdpart.c 2025-10-22 13:53:23.307328685 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mtd/mtdpart.c 2025-10-22 13:53:56.539169026 -0400 -@@ -86,7 +86,8 @@ static struct mtd_info *allocate_partiti - * parent conditional on that option. Note, this is a way to - * distinguish between the parent and its partitions in sysfs. - */ -- child->dev.parent = &parent->dev; -+ child->dev.parent = IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) || mtd_is_partition(parent) ? -+ &parent->dev : parent->dev.parent; - child->dev.of_node = part->of_node; - child->parent = parent; - child->part.offset = part->offset; -@@ -242,7 +243,7 @@ static int mtd_add_partition_attrs(struc - } - - int mtd_add_partition(struct mtd_info *parent, const char *name, -- long long offset, long long length, struct mtd_info **out) -+ long long offset, long long length) - { - struct mtd_info *master = mtd_get_master(parent); - u64 parent_size = mtd_is_partition(parent) ? -@@ -275,15 +276,12 @@ int mtd_add_partition(struct mtd_info *p - list_add_tail(&child->part.node, &parent->partitions); - mutex_unlock(&master->master.partitions_lock); - -- ret = add_mtd_device(child, true); -+ ret = add_mtd_device(child); - if (ret) - goto err_remove_part; - - mtd_add_partition_attrs(child); - -- if (out) -- *out = child; -- - return 0; - - err_remove_part: -@@ -415,7 +413,7 @@ int add_mtd_partitions(struct mtd_info * - list_add_tail(&child->part.node, &parent->partitions); - mutex_unlock(&master->master.partitions_lock); - -- ret = add_mtd_device(child, true); -+ ret = add_mtd_device(child); - if (ret) { - mutex_lock(&master->master.partitions_lock); - list_del(&child->part.node); -@@ -592,6 +590,9 @@ static int mtd_part_of_parse(struct mtd_ - int ret, err = 0; - - dev = &master->dev; -+ /* Use parent device (controller) if the top level MTD is not registered */ -+ if (!IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) && !mtd_is_partition(master)) -+ dev = master->dev.parent; - - np = mtd_get_of_node(master); - if (mtd_is_partition(master)) -@@ -710,7 +711,6 @@ int parse_mtd_partitions(struct mtd_info - if (ret < 0 && !err) - err = ret; - } -- - return err; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/mtd/nand/qpic_common.c BPI-Router-Linux-kernel-6.16.12/drivers/mtd/nand/qpic_common.c ---- BPI-Router-Linux-kernel/drivers/mtd/nand/qpic_common.c 2025-10-22 13:53:23.307328685 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mtd/nand/qpic_common.c 2025-10-22 13:53:56.539169026 -0400 -@@ -57,14 +57,15 @@ qcom_alloc_bam_transaction(struct qcom_n - bam_txn_buf += sizeof(*bam_txn); - - bam_txn->bam_ce = bam_txn_buf; -- bam_txn_buf += -- sizeof(*bam_txn->bam_ce) * QPIC_PER_CW_CMD_ELEMENTS * num_cw; -+ bam_txn->bam_ce_nitems = QPIC_PER_CW_CMD_ELEMENTS * num_cw; -+ bam_txn_buf += sizeof(*bam_txn->bam_ce) * bam_txn->bam_ce_nitems; - - bam_txn->cmd_sgl = bam_txn_buf; -- bam_txn_buf += -- sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL * num_cw; -+ bam_txn->cmd_sgl_nitems = QPIC_PER_CW_CMD_SGL * num_cw; -+ bam_txn_buf += sizeof(*bam_txn->cmd_sgl) * bam_txn->cmd_sgl_nitems; - - bam_txn->data_sgl = bam_txn_buf; -+ bam_txn->data_sgl_nitems = QPIC_PER_CW_DATA_SGL * num_cw; - - init_completion(&bam_txn->txn_done); - -@@ -238,6 +239,11 @@ int qcom_prep_bam_dma_desc_cmd(struct qc - struct bam_transaction *bam_txn = nandc->bam_txn; - u32 offset; - -+ if (bam_txn->bam_ce_pos + size > bam_txn->bam_ce_nitems) { -+ dev_err(nandc->dev, "BAM %s array is full\n", "CE"); -+ return -EINVAL; -+ } -+ - bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_pos]; - - /* fill the command desc */ -@@ -258,6 +264,12 @@ int qcom_prep_bam_dma_desc_cmd(struct qc - - /* use the separate sgl after this command */ - if (flags & NAND_BAM_NEXT_SGL) { -+ if (bam_txn->cmd_sgl_pos >= bam_txn->cmd_sgl_nitems) { -+ dev_err(nandc->dev, "BAM %s array is full\n", -+ "CMD sgl"); -+ return -EINVAL; -+ } -+ - bam_ce_buffer = &bam_txn->bam_ce[bam_txn->bam_ce_start]; - bam_ce_size = (bam_txn->bam_ce_pos - - bam_txn->bam_ce_start) * -@@ -297,10 +309,20 @@ int qcom_prep_bam_dma_desc_data(struct q - struct bam_transaction *bam_txn = nandc->bam_txn; - - if (read) { -+ if (bam_txn->rx_sgl_pos >= bam_txn->data_sgl_nitems) { -+ dev_err(nandc->dev, "BAM %s array is full\n", "RX sgl"); -+ return -EINVAL; -+ } -+ - sg_set_buf(&bam_txn->data_sgl[bam_txn->rx_sgl_pos], - vaddr, size); - bam_txn->rx_sgl_pos++; - } else { -+ if (bam_txn->tx_sgl_pos >= bam_txn->data_sgl_nitems) { -+ dev_err(nandc->dev, "BAM %s array is full\n", "TX sgl"); -+ return -EINVAL; -+ } -+ - sg_set_buf(&bam_txn->data_sgl[bam_txn->tx_sgl_pos], - vaddr, size); - bam_txn->tx_sgl_pos++; -diff -purNx .git BPI-Router-Linux-kernel/drivers/mtd/nand/raw/atmel/nand-controller.c BPI-Router-Linux-kernel-6.16.12/drivers/mtd/nand/raw/atmel/nand-controller.c ---- BPI-Router-Linux-kernel/drivers/mtd/nand/raw/atmel/nand-controller.c 2025-10-22 13:53:23.307328685 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mtd/nand/raw/atmel/nand-controller.c 2025-10-22 13:53:56.539169026 -0400 -@@ -373,7 +373,7 @@ static int atmel_nand_dma_transfer(struc - dma_cookie_t cookie; - - buf_dma = dma_map_single(nc->dev, buf, len, dir); -- if (dma_mapping_error(nc->dev, dev_dma)) { -+ if (dma_mapping_error(nc->dev, buf_dma)) { - dev_err(nc->dev, - "Failed to prepare a buffer for DMA access\n"); - goto err; -@@ -1378,13 +1378,23 @@ static int atmel_smc_nand_prepare_smccon - return ret; - - /* -+ * Read setup timing depends on the operation done on the NAND: -+ * -+ * NRD_SETUP = max(tAR, tCLR) -+ */ -+ timeps = max(conf->timings.sdr.tAR_min, conf->timings.sdr.tCLR_min); -+ ncycles = DIV_ROUND_UP(timeps, mckperiodps); -+ totalcycles += ncycles; -+ ret = atmel_smc_cs_conf_set_setup(smcconf, ATMEL_SMC_NRD_SHIFT, ncycles); -+ if (ret) -+ return ret; -+ -+ /* - * The read cycle timing is directly matching tRC, but is also - * dependent on the setup and hold timings we calculated earlier, - * which gives: - * -- * NRD_CYCLE = max(tRC, NRD_PULSE + NRD_HOLD) -- * -- * NRD_SETUP is always 0. -+ * NRD_CYCLE = max(tRC, NRD_SETUP + NRD_PULSE + NRD_HOLD) - */ - ncycles = DIV_ROUND_UP(conf->timings.sdr.tRC_min, mckperiodps); - ncycles = max(totalcycles, ncycles); -diff -purNx .git BPI-Router-Linux-kernel/drivers/mtd/nand/raw/atmel/pmecc.c BPI-Router-Linux-kernel-6.16.12/drivers/mtd/nand/raw/atmel/pmecc.c ---- BPI-Router-Linux-kernel/drivers/mtd/nand/raw/atmel/pmecc.c 2025-10-22 13:53:23.307328685 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mtd/nand/raw/atmel/pmecc.c 2025-10-22 13:53:56.539169026 -0400 -@@ -143,6 +143,7 @@ struct atmel_pmecc_caps { - int nstrengths; - int el_offset; - bool correct_erased_chunks; -+ bool clk_ctrl; - }; - - struct atmel_pmecc { -@@ -843,6 +844,10 @@ static struct atmel_pmecc *atmel_pmecc_c - if (IS_ERR(pmecc->regs.errloc)) - return ERR_CAST(pmecc->regs.errloc); - -+ /* pmecc data setup time */ -+ if (caps->clk_ctrl) -+ writel(PMECC_CLK_133MHZ, pmecc->regs.base + ATMEL_PMECC_CLK); -+ - /* Disable all interrupts before registering the PMECC handler. */ - writel(0xffffffff, pmecc->regs.base + ATMEL_PMECC_IDR); - atmel_pmecc_reset(pmecc); -@@ -896,6 +901,7 @@ static struct atmel_pmecc_caps at91sam9g - .strengths = atmel_pmecc_strengths, - .nstrengths = 5, - .el_offset = 0x8c, -+ .clk_ctrl = true, - }; - - static struct atmel_pmecc_caps sama5d4_caps = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/mtd/nand/raw/fsmc_nand.c BPI-Router-Linux-kernel-6.16.12/drivers/mtd/nand/raw/fsmc_nand.c ---- BPI-Router-Linux-kernel/drivers/mtd/nand/raw/fsmc_nand.c 2025-10-22 13:53:23.307328685 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mtd/nand/raw/fsmc_nand.c 2025-10-22 13:53:56.539169026 -0400 -@@ -503,6 +503,8 @@ static int dma_xfer(struct fsmc_nand_dat - - dma_dev = chan->device; - dma_addr = dma_map_single(dma_dev->dev, buffer, len, direction); -+ if (dma_mapping_error(dma_dev->dev, dma_addr)) -+ return -EINVAL; - - if (direction == DMA_TO_DEVICE) { - dma_src = dma_addr; -diff -purNx .git BPI-Router-Linux-kernel/drivers/mtd/nand/raw/nuvoton-ma35d1-nand-controller.c BPI-Router-Linux-kernel-6.16.12/drivers/mtd/nand/raw/nuvoton-ma35d1-nand-controller.c ---- BPI-Router-Linux-kernel/drivers/mtd/nand/raw/nuvoton-ma35d1-nand-controller.c 2025-10-22 13:53:23.307328685 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mtd/nand/raw/nuvoton-ma35d1-nand-controller.c 2025-10-22 13:53:56.539169026 -0400 -@@ -935,10 +935,10 @@ static void ma35_chips_cleanup(struct ma - - static int ma35_nand_chips_init(struct device *dev, struct ma35_nand_info *nand) - { -- struct device_node *np = dev->of_node, *nand_np; -+ struct device_node *np = dev->of_node; - int ret; - -- for_each_child_of_node(np, nand_np) { -+ for_each_child_of_node_scoped(np, nand_np) { - ret = ma35_nand_chip_init(dev, nand, nand_np); - if (ret) { - ma35_chips_cleanup(nand); -diff -purNx .git BPI-Router-Linux-kernel/drivers/mtd/nand/raw/renesas-nand-controller.c BPI-Router-Linux-kernel-6.16.12/drivers/mtd/nand/raw/renesas-nand-controller.c ---- BPI-Router-Linux-kernel/drivers/mtd/nand/raw/renesas-nand-controller.c 2025-10-22 13:53:23.307328685 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mtd/nand/raw/renesas-nand-controller.c 2025-10-22 13:53:56.539169026 -0400 -@@ -426,6 +426,9 @@ static int rnandc_read_page_hw_ecc(struc - /* Configure DMA */ - dma_addr = dma_map_single(rnandc->dev, rnandc->buf, mtd->writesize, - DMA_FROM_DEVICE); -+ if (dma_mapping_error(rnandc->dev, dma_addr)) -+ return -ENOMEM; -+ - writel(dma_addr, rnandc->regs + DMA_ADDR_LOW_REG); - writel(mtd->writesize, rnandc->regs + DMA_CNT_REG); - writel(DMA_TLVL_MAX, rnandc->regs + DMA_TLVL_REG); -@@ -606,6 +609,9 @@ static int rnandc_write_page_hw_ecc(stru - /* Configure DMA */ - dma_addr = dma_map_single(rnandc->dev, (void *)rnandc->buf, mtd->writesize, - DMA_TO_DEVICE); -+ if (dma_mapping_error(rnandc->dev, dma_addr)) -+ return -ENOMEM; -+ - writel(dma_addr, rnandc->regs + DMA_ADDR_LOW_REG); - writel(mtd->writesize, rnandc->regs + DMA_CNT_REG); - writel(DMA_TLVL_MAX, rnandc->regs + DMA_TLVL_REG); -diff -purNx .git BPI-Router-Linux-kernel/drivers/mtd/nand/raw/rockchip-nand-controller.c BPI-Router-Linux-kernel-6.16.12/drivers/mtd/nand/raw/rockchip-nand-controller.c ---- BPI-Router-Linux-kernel/drivers/mtd/nand/raw/rockchip-nand-controller.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mtd/nand/raw/rockchip-nand-controller.c 2025-10-22 13:53:56.539169026 -0400 -@@ -656,9 +656,16 @@ static int rk_nfc_write_page_hwecc(struc - - dma_data = dma_map_single(nfc->dev, (void *)nfc->page_buf, - mtd->writesize, DMA_TO_DEVICE); -+ if (dma_mapping_error(nfc->dev, dma_data)) -+ return -ENOMEM; -+ - dma_oob = dma_map_single(nfc->dev, nfc->oob_buf, - ecc->steps * oob_step, - DMA_TO_DEVICE); -+ if (dma_mapping_error(nfc->dev, dma_oob)) { -+ dma_unmap_single(nfc->dev, dma_data, mtd->writesize, DMA_TO_DEVICE); -+ return -ENOMEM; -+ } - - reinit_completion(&nfc->done); - writel(INT_DMA, nfc->regs + nfc->cfg->int_en_off); -@@ -772,9 +779,17 @@ static int rk_nfc_read_page_hwecc(struct - dma_data = dma_map_single(nfc->dev, nfc->page_buf, - mtd->writesize, - DMA_FROM_DEVICE); -+ if (dma_mapping_error(nfc->dev, dma_data)) -+ return -ENOMEM; -+ - dma_oob = dma_map_single(nfc->dev, nfc->oob_buf, - ecc->steps * oob_step, - DMA_FROM_DEVICE); -+ if (dma_mapping_error(nfc->dev, dma_oob)) { -+ dma_unmap_single(nfc->dev, dma_data, mtd->writesize, -+ DMA_FROM_DEVICE); -+ return -ENOMEM; -+ } - - /* - * The first blocks (4, 8 or 16 depending on the device) -diff -purNx .git BPI-Router-Linux-kernel/drivers/mtd/nand/raw/stm32_fmc2_nand.c BPI-Router-Linux-kernel-6.16.12/drivers/mtd/nand/raw/stm32_fmc2_nand.c ---- BPI-Router-Linux-kernel/drivers/mtd/nand/raw/stm32_fmc2_nand.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mtd/nand/raw/stm32_fmc2_nand.c 2025-10-22 13:53:56.539169026 -0400 -@@ -272,6 +272,7 @@ struct stm32_fmc2_nfc { - struct sg_table dma_data_sg; - struct sg_table dma_ecc_sg; - u8 *ecc_buf; -+ dma_addr_t dma_ecc_addr; - int dma_ecc_len; - u32 tx_dma_max_burst; - u32 rx_dma_max_burst; -@@ -902,17 +903,10 @@ static int stm32_fmc2_nfc_xfer(struct na - - if (!write_data && !raw) { - /* Configure DMA ECC status */ -- p = nfc->ecc_buf; - for_each_sg(nfc->dma_ecc_sg.sgl, sg, eccsteps, s) { -- sg_set_buf(sg, p, nfc->dma_ecc_len); -- p += nfc->dma_ecc_len; -- } -- -- ret = dma_map_sg(nfc->dev, nfc->dma_ecc_sg.sgl, -- eccsteps, dma_data_dir); -- if (!ret) { -- ret = -EIO; -- goto err_unmap_data; -+ sg_dma_address(sg) = nfc->dma_ecc_addr + -+ s * nfc->dma_ecc_len; -+ sg_dma_len(sg) = nfc->dma_ecc_len; - } - - desc_ecc = dmaengine_prep_slave_sg(nfc->dma_ecc_ch, -@@ -921,7 +915,7 @@ static int stm32_fmc2_nfc_xfer(struct na - DMA_PREP_INTERRUPT); - if (!desc_ecc) { - ret = -ENOMEM; -- goto err_unmap_ecc; -+ goto err_unmap_data; - } - - reinit_completion(&nfc->dma_ecc_complete); -@@ -929,7 +923,7 @@ static int stm32_fmc2_nfc_xfer(struct na - desc_ecc->callback_param = &nfc->dma_ecc_complete; - ret = dma_submit_error(dmaengine_submit(desc_ecc)); - if (ret) -- goto err_unmap_ecc; -+ goto err_unmap_data; - - dma_async_issue_pending(nfc->dma_ecc_ch); - } -@@ -949,7 +943,7 @@ static int stm32_fmc2_nfc_xfer(struct na - if (!write_data && !raw) - dmaengine_terminate_all(nfc->dma_ecc_ch); - ret = -ETIMEDOUT; -- goto err_unmap_ecc; -+ goto err_unmap_data; - } - - /* Wait DMA data transfer completion */ -@@ -969,11 +963,6 @@ static int stm32_fmc2_nfc_xfer(struct na - } - } - --err_unmap_ecc: -- if (!write_data && !raw) -- dma_unmap_sg(nfc->dev, nfc->dma_ecc_sg.sgl, -- eccsteps, dma_data_dir); -- - err_unmap_data: - dma_unmap_sg(nfc->dev, nfc->dma_data_sg.sgl, eccsteps, dma_data_dir); - -@@ -996,9 +985,21 @@ static int stm32_fmc2_nfc_seq_write(stru - - /* Write oob */ - if (oob_required) { -- ret = nand_change_write_column_op(chip, mtd->writesize, -- chip->oob_poi, mtd->oobsize, -- false); -+ unsigned int offset_in_page = mtd->writesize; -+ const void *buf = chip->oob_poi; -+ unsigned int len = mtd->oobsize; -+ -+ if (!raw) { -+ struct mtd_oob_region oob_free; -+ -+ mtd_ooblayout_free(mtd, 0, &oob_free); -+ offset_in_page += oob_free.offset; -+ buf += oob_free.offset; -+ len = oob_free.length; -+ } -+ -+ ret = nand_change_write_column_op(chip, offset_in_page, -+ buf, len, false); - if (ret) - return ret; - } -@@ -1610,7 +1611,8 @@ static int stm32_fmc2_nfc_dma_setup(stru - return ret; - - /* Allocate a buffer to store ECC status registers */ -- nfc->ecc_buf = devm_kzalloc(nfc->dev, FMC2_MAX_ECC_BUF_LEN, GFP_KERNEL); -+ nfc->ecc_buf = dmam_alloc_coherent(nfc->dev, FMC2_MAX_ECC_BUF_LEN, -+ &nfc->dma_ecc_addr, GFP_KERNEL); - if (!nfc->ecc_buf) - return -ENOMEM; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/mtd/nand/spi/core.c BPI-Router-Linux-kernel-6.16.12/drivers/mtd/nand/spi/core.c ---- BPI-Router-Linux-kernel/drivers/mtd/nand/spi/core.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mtd/nand/spi/core.c 2025-10-22 13:53:56.539169026 -0400 -@@ -20,7 +20,7 @@ - #include - #include - --static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val) -+int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val) - { - struct spi_mem_op op = SPINAND_GET_FEATURE_1S_1S_1S_OP(reg, - spinand->scratchbuf); -@@ -688,7 +688,10 @@ int spinand_write_page(struct spinand_de - SPINAND_WRITE_INITIAL_DELAY_US, - SPINAND_WRITE_POLL_DELAY_US, - &status); -- if (!ret && (status & STATUS_PROG_FAILED)) -+ if (ret) -+ return ret; -+ -+ if (status & STATUS_PROG_FAILED) - return -EIO; - - return nand_ecc_finish_io_req(nand, (struct nand_page_io_req *)req); -@@ -1250,8 +1253,19 @@ static int spinand_id_detect(struct spin - - static int spinand_manufacturer_init(struct spinand_device *spinand) - { -- if (spinand->manufacturer->ops->init) -- return spinand->manufacturer->ops->init(spinand); -+ int ret; -+ -+ if (spinand->manufacturer->ops->init) { -+ ret = spinand->manufacturer->ops->init(spinand); -+ if (ret) -+ return ret; -+ } -+ -+ if (spinand->configure_chip) { -+ ret = spinand->configure_chip(spinand); -+ if (ret) -+ return ret; -+ } - - return 0; - } -@@ -1346,6 +1360,7 @@ int spinand_match_and_init(struct spinan - spinand->flags = table[i].flags; - spinand->id.len = 1 + table[i].devid.len; - spinand->select_target = table[i].select_target; -+ spinand->configure_chip = table[i].configure_chip; - spinand->set_cont_read = table[i].set_cont_read; - spinand->fact_otp = &table[i].fact_otp; - spinand->user_otp = &table[i].user_otp; -@@ -1585,6 +1600,7 @@ static void spinand_cleanup(struct spina - { - struct nand_device *nand = spinand_to_nand(spinand); - -+ nanddev_ecc_engine_cleanup(nand); - nanddev_cleanup(nand); - spinand_manufacturer_cleanup(spinand); - kfree(spinand->databuf); -diff -purNx .git BPI-Router-Linux-kernel/drivers/mtd/nand/spi/winbond.c BPI-Router-Linux-kernel-6.16.12/drivers/mtd/nand/spi/winbond.c ---- BPI-Router-Linux-kernel/drivers/mtd/nand/spi/winbond.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mtd/nand/spi/winbond.c 2025-10-22 13:53:56.539169026 -0400 -@@ -18,6 +18,9 @@ - - #define W25N04KV_STATUS_ECC_5_8_BITFLIPS (3 << 4) - -+#define W25N0XJW_SR4 0xD0 -+#define W25N0XJW_SR4_HS BIT(2) -+ - /* - * "X2" in the core is equivalent to "dual output" in the datasheets, - * "X4" in the core is equivalent to "quad output" in the datasheets. -@@ -25,7 +28,7 @@ - - static SPINAND_OP_VARIANTS(read_cache_octal_variants, - SPINAND_PAGE_READ_FROM_CACHE_1S_1D_8D_OP(0, 2, NULL, 0, 105 * HZ_PER_MHZ), -- SPINAND_PAGE_READ_FROM_CACHE_1S_8S_8S_OP(0, 16, NULL, 0, 86 * HZ_PER_MHZ), -+ SPINAND_PAGE_READ_FROM_CACHE_1S_8S_8S_OP(0, 16, NULL, 0, 162 * HZ_PER_MHZ), - SPINAND_PAGE_READ_FROM_CACHE_1S_1S_8S_OP(0, 1, NULL, 0, 133 * HZ_PER_MHZ), - SPINAND_PAGE_READ_FROM_CACHE_FAST_1S_1S_1S_OP(0, 1, NULL, 0), - SPINAND_PAGE_READ_FROM_CACHE_1S_1S_1S_OP(0, 1, NULL, 0)); -@@ -42,11 +45,13 @@ static SPINAND_OP_VARIANTS(update_cache_ - static SPINAND_OP_VARIANTS(read_cache_dual_quad_dtr_variants, - SPINAND_PAGE_READ_FROM_CACHE_1S_4D_4D_OP(0, 8, NULL, 0, 80 * HZ_PER_MHZ), - SPINAND_PAGE_READ_FROM_CACHE_1S_1D_4D_OP(0, 2, NULL, 0, 80 * HZ_PER_MHZ), -- SPINAND_PAGE_READ_FROM_CACHE_1S_4S_4S_OP(0, 2, NULL, 0), -+ SPINAND_PAGE_READ_FROM_CACHE_1S_4S_4S_OP(0, 4, NULL, 0, 0), -+ SPINAND_PAGE_READ_FROM_CACHE_1S_4S_4S_OP(0, 2, NULL, 0, 104 * HZ_PER_MHZ), - SPINAND_PAGE_READ_FROM_CACHE_1S_1S_4S_OP(0, 1, NULL, 0), - SPINAND_PAGE_READ_FROM_CACHE_1S_2D_2D_OP(0, 4, NULL, 0, 80 * HZ_PER_MHZ), - SPINAND_PAGE_READ_FROM_CACHE_1S_1D_2D_OP(0, 2, NULL, 0, 80 * HZ_PER_MHZ), -- SPINAND_PAGE_READ_FROM_CACHE_1S_2S_2S_OP(0, 1, NULL, 0), -+ SPINAND_PAGE_READ_FROM_CACHE_1S_2S_2S_OP(0, 2, NULL, 0, 0), -+ SPINAND_PAGE_READ_FROM_CACHE_1S_2S_2S_OP(0, 1, NULL, 0, 104 * HZ_PER_MHZ), - SPINAND_PAGE_READ_FROM_CACHE_1S_1S_2S_OP(0, 1, NULL, 0), - SPINAND_PAGE_READ_FROM_CACHE_1S_1D_1D_OP(0, 2, NULL, 0, 80 * HZ_PER_MHZ), - SPINAND_PAGE_READ_FROM_CACHE_FAST_1S_1S_1S_OP(0, 1, NULL, 0), -@@ -157,6 +162,36 @@ static const struct mtd_ooblayout_ops w2 - .free = w25n02kv_ooblayout_free, - }; - -+static int w25n01jw_ooblayout_ecc(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *region) -+{ -+ if (section > 3) -+ return -ERANGE; -+ -+ region->offset = (16 * section) + 12; -+ region->length = 4; -+ -+ return 0; -+} -+ -+static int w25n01jw_ooblayout_free(struct mtd_info *mtd, int section, -+ struct mtd_oob_region *region) -+{ -+ if (section > 3) -+ return -ERANGE; -+ -+ region->offset = (16 * section); -+ region->length = 12; -+ -+ /* Extract BBM */ -+ if (!section) { -+ region->offset += 2; -+ region->length -= 2; -+ } -+ -+ return 0; -+} -+ - static int w35n01jw_ooblayout_ecc(struct mtd_info *mtd, int section, - struct mtd_oob_region *region) - { -@@ -187,6 +222,11 @@ static int w35n01jw_ooblayout_free(struc - return 0; - } - -+static const struct mtd_ooblayout_ops w25n01jw_ooblayout = { -+ .ecc = w25n01jw_ooblayout_ecc, -+ .free = w25n01jw_ooblayout_free, -+}; -+ - static const struct mtd_ooblayout_ops w35n01jw_ooblayout = { - .ecc = w35n01jw_ooblayout_ecc, - .free = w35n01jw_ooblayout_free, -@@ -230,6 +270,40 @@ static int w25n02kv_ecc_get_status(struc - return -EINVAL; - } - -+static int w25n0xjw_hs_cfg(struct spinand_device *spinand) -+{ -+ const struct spi_mem_op *op; -+ bool hs; -+ u8 sr4; -+ int ret; -+ -+ op = spinand->op_templates.read_cache; -+ if (op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr) -+ hs = false; -+ else if (op->cmd.buswidth == 1 && op->addr.buswidth == 1 && -+ op->dummy.buswidth == 1 && op->data.buswidth == 1) -+ hs = false; -+ else if (!op->max_freq) -+ hs = true; -+ else -+ hs = false; -+ -+ ret = spinand_read_reg_op(spinand, W25N0XJW_SR4, &sr4); -+ if (ret) -+ return ret; -+ -+ if (hs) -+ sr4 |= W25N0XJW_SR4_HS; -+ else -+ sr4 &= ~W25N0XJW_SR4_HS; -+ -+ ret = spinand_write_reg_op(spinand, W25N0XJW_SR4, sr4); -+ if (ret) -+ return ret; -+ -+ return 0; -+} -+ - static const struct spinand_info winbond_spinand_table[] = { - /* 512M-bit densities */ - SPINAND_INFO("W25N512GW", /* 1.8V */ -@@ -268,7 +342,8 @@ static const struct spinand_info winbond - &write_cache_variants, - &update_cache_variants), - 0, -- SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)), -+ SPINAND_ECCINFO(&w25n01jw_ooblayout, NULL), -+ SPINAND_CONFIGURE_CHIP(w25n0xjw_hs_cfg)), - SPINAND_INFO("W25N01KV", /* 3.3V */ - SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xae, 0x21), - NAND_MEMORG(1, 2048, 96, 64, 1024, 20, 1, 1, 1), -@@ -289,7 +364,7 @@ static const struct spinand_info winbond - SPINAND_ECCINFO(&w35n01jw_ooblayout, NULL)), - SPINAND_INFO("W35N02JW", /* 1.8V */ - SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xdf, 0x22), -- NAND_MEMORG(1, 4096, 128, 64, 512, 10, 2, 1, 1), -+ NAND_MEMORG(1, 4096, 128, 64, 512, 10, 1, 2, 1), - NAND_ECCREQ(1, 512), - SPINAND_INFO_OP_VARIANTS(&read_cache_octal_variants, - &write_cache_octal_variants, -@@ -298,7 +373,7 @@ static const struct spinand_info winbond - SPINAND_ECCINFO(&w35n01jw_ooblayout, NULL)), - SPINAND_INFO("W35N04JW", /* 1.8V */ - SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xdf, 0x23), -- NAND_MEMORG(1, 4096, 128, 64, 512, 10, 4, 1, 1), -+ NAND_MEMORG(1, 4096, 128, 64, 512, 10, 1, 4, 1), - NAND_ECCREQ(1, 512), - SPINAND_INFO_OP_VARIANTS(&read_cache_octal_variants, - &write_cache_octal_variants, -@@ -324,7 +399,8 @@ static const struct spinand_info winbond - &write_cache_variants, - &update_cache_variants), - 0, -- SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)), -+ SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL), -+ SPINAND_CONFIGURE_CHIP(w25n0xjw_hs_cfg)), - SPINAND_INFO("W25N02KV", /* 3.3V */ - SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x22), - NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), -diff -purNx .git BPI-Router-Linux-kernel/drivers/mtd/spi-nor/spansion.c BPI-Router-Linux-kernel-6.16.12/drivers/mtd/spi-nor/spansion.c ---- BPI-Router-Linux-kernel/drivers/mtd/spi-nor/spansion.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mtd/spi-nor/spansion.c 2025-10-22 13:53:56.539169026 -0400 -@@ -17,6 +17,7 @@ - - #define SPINOR_OP_CLSR 0x30 /* Clear status register 1 */ - #define SPINOR_OP_CLPEF 0x82 /* Clear program/erase failure flags */ -+#define SPINOR_OP_CYPRESS_EX4B 0xB8 /* Exit 4-byte address mode */ - #define SPINOR_OP_CYPRESS_DIE_ERASE 0x61 /* Chip (die) erase */ - #define SPINOR_OP_RD_ANY_REG 0x65 /* Read any register */ - #define SPINOR_OP_WR_ANY_REG 0x71 /* Write any register */ -@@ -58,6 +59,13 @@ - SPI_MEM_OP_DUMMY(ndummy, 0), \ - SPI_MEM_OP_DATA_IN(1, buf, 0)) - -+#define CYPRESS_NOR_EN4B_EX4B_OP(enable) \ -+ SPI_MEM_OP(SPI_MEM_OP_CMD(enable ? SPINOR_OP_EN4B : \ -+ SPINOR_OP_CYPRESS_EX4B, 0), \ -+ SPI_MEM_OP_NO_ADDR, \ -+ SPI_MEM_OP_NO_DUMMY, \ -+ SPI_MEM_OP_NO_DATA) -+ - #define SPANSION_OP(opcode) \ - SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 0), \ - SPI_MEM_OP_NO_ADDR, \ -@@ -356,6 +364,20 @@ static int cypress_nor_quad_enable_volat - return 0; - } - -+static int cypress_nor_set_4byte_addr_mode(struct spi_nor *nor, bool enable) -+{ -+ int ret; -+ struct spi_mem_op op = CYPRESS_NOR_EN4B_EX4B_OP(enable); -+ -+ spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); -+ -+ ret = spi_mem_exec_op(nor->spimem, &op); -+ if (ret) -+ dev_dbg(nor->dev, "error %d setting 4-byte mode\n", ret); -+ -+ return ret; -+} -+ - /** - * cypress_nor_determine_addr_mode_by_sr1() - Determine current address mode - * (3 or 4-byte) by querying status -@@ -526,6 +548,9 @@ s25fs256t_post_bfpt_fixup(struct spi_nor - struct spi_mem_op op; - int ret; - -+ /* Assign 4-byte address mode method that is not determined in BFPT */ -+ nor->params->set_4byte_addr_mode = cypress_nor_set_4byte_addr_mode; -+ - ret = cypress_nor_set_addr_mode_nbytes(nor); - if (ret) - return ret; -@@ -591,6 +616,9 @@ s25hx_t_post_bfpt_fixup(struct spi_nor * - { - int ret; - -+ /* Assign 4-byte address mode method that is not determined in BFPT */ -+ nor->params->set_4byte_addr_mode = cypress_nor_set_4byte_addr_mode; -+ - ret = cypress_nor_set_addr_mode_nbytes(nor); - if (ret) - return ret; -@@ -718,6 +746,9 @@ static int s28hx_t_post_bfpt_fixup(struc - const struct sfdp_parameter_header *bfpt_header, - const struct sfdp_bfpt *bfpt) - { -+ /* Assign 4-byte address mode method that is not determined in BFPT */ -+ nor->params->set_4byte_addr_mode = cypress_nor_set_4byte_addr_mode; -+ - return cypress_nor_set_addr_mode_nbytes(nor); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/mtd/spi-nor/swp.c BPI-Router-Linux-kernel-6.16.12/drivers/mtd/spi-nor/swp.c ---- BPI-Router-Linux-kernel/drivers/mtd/spi-nor/swp.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mtd/spi-nor/swp.c 2025-10-22 13:53:56.539169026 -0400 -@@ -56,7 +56,6 @@ static u64 spi_nor_get_min_prot_length_s - static void spi_nor_get_locked_range_sr(struct spi_nor *nor, u8 sr, loff_t *ofs, - u64 *len) - { -- struct mtd_info *mtd = &nor->mtd; - u64 min_prot_len; - u8 mask = spi_nor_get_sr_bp_mask(nor); - u8 tb_mask = spi_nor_get_sr_tb_mask(nor); -@@ -77,13 +76,13 @@ static void spi_nor_get_locked_range_sr( - min_prot_len = spi_nor_get_min_prot_length_sr(nor); - *len = min_prot_len << (bp - 1); - -- if (*len > mtd->size) -- *len = mtd->size; -+ if (*len > nor->params->size) -+ *len = nor->params->size; - - if (nor->flags & SNOR_F_HAS_SR_TB && sr & tb_mask) - *ofs = 0; - else -- *ofs = mtd->size - *len; -+ *ofs = nor->params->size - *len; - } - - /* -@@ -158,7 +157,6 @@ static bool spi_nor_is_unlocked_sr(struc - */ - static int spi_nor_sr_lock(struct spi_nor *nor, loff_t ofs, u64 len) - { -- struct mtd_info *mtd = &nor->mtd; - u64 min_prot_len; - int ret, status_old, status_new; - u8 mask = spi_nor_get_sr_bp_mask(nor); -@@ -183,7 +181,7 @@ static int spi_nor_sr_lock(struct spi_no - can_be_bottom = false; - - /* If anything above us is unlocked, we can't use 'top' protection */ -- if (!spi_nor_is_locked_sr(nor, ofs + len, mtd->size - (ofs + len), -+ if (!spi_nor_is_locked_sr(nor, ofs + len, nor->params->size - (ofs + len), - status_old)) - can_be_top = false; - -@@ -195,11 +193,11 @@ static int spi_nor_sr_lock(struct spi_no - - /* lock_len: length of region that should end up locked */ - if (use_top) -- lock_len = mtd->size - ofs; -+ lock_len = nor->params->size - ofs; - else - lock_len = ofs + len; - -- if (lock_len == mtd->size) { -+ if (lock_len == nor->params->size) { - val = mask; - } else { - min_prot_len = spi_nor_get_min_prot_length_sr(nor); -@@ -248,7 +246,6 @@ static int spi_nor_sr_lock(struct spi_no - */ - static int spi_nor_sr_unlock(struct spi_nor *nor, loff_t ofs, u64 len) - { -- struct mtd_info *mtd = &nor->mtd; - u64 min_prot_len; - int ret, status_old, status_new; - u8 mask = spi_nor_get_sr_bp_mask(nor); -@@ -273,7 +270,7 @@ static int spi_nor_sr_unlock(struct spi_ - can_be_top = false; - - /* If anything above us is locked, we can't use 'bottom' protection */ -- if (!spi_nor_is_unlocked_sr(nor, ofs + len, mtd->size - (ofs + len), -+ if (!spi_nor_is_unlocked_sr(nor, ofs + len, nor->params->size - (ofs + len), - status_old)) - can_be_bottom = false; - -@@ -285,7 +282,7 @@ static int spi_nor_sr_unlock(struct spi_ - - /* lock_len: length of region that should remain locked */ - if (use_top) -- lock_len = mtd->size - (ofs + len); -+ lock_len = nor->params->size - (ofs + len); - else - lock_len = ofs; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/mux/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/mux/Kconfig ---- BPI-Router-Linux-kernel/drivers/mux/Kconfig 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/mux/Kconfig 2025-10-22 13:53:56.539169026 -0400 -@@ -48,6 +48,7 @@ config MUX_GPIO - config MUX_MMIO - tristate "MMIO/Regmap register bitfield-controlled Multiplexer" - depends on OF -+ select REGMAP_MMIO - help - MMIO/Regmap register bitfield-controlled Multiplexer controller. - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/bonding/bond_3ad.c BPI-Router-Linux-kernel-6.16.12/drivers/net/bonding/bond_3ad.c ---- BPI-Router-Linux-kernel/drivers/net/bonding/bond_3ad.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/bonding/bond_3ad.c 2025-10-22 13:53:56.539169026 -0400 -@@ -95,13 +95,13 @@ static int ad_marker_send(struct port *p - static void ad_mux_machine(struct port *port, bool *update_slave_arr); - static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port); - static void ad_tx_machine(struct port *port); --static void ad_periodic_machine(struct port *port, struct bond_params *bond_params); -+static void ad_periodic_machine(struct port *port); - static void ad_port_selection_logic(struct port *port, bool *update_slave_arr); - static void ad_agg_selection_logic(struct aggregator *aggregator, - bool *update_slave_arr); - static void ad_clear_agg(struct aggregator *aggregator); - static void ad_initialize_agg(struct aggregator *aggregator); --static void ad_initialize_port(struct port *port, int lacp_fast); -+static void ad_initialize_port(struct port *port, const struct bond_params *bond_params); - static void ad_enable_collecting(struct port *port); - static void ad_disable_distributing(struct port *port, - bool *update_slave_arr); -@@ -1296,10 +1296,16 @@ static void ad_rx_machine(struct lacpdu - * case of EXPIRED even if LINK_DOWN didn't arrive for - * the port. - */ -- port->partner_oper.port_state &= ~LACP_STATE_SYNCHRONIZATION; - port->sm_vars &= ~AD_PORT_MATCHED; -+ /* Based on IEEE 8021AX-2014, Figure 6-18 - Receive -+ * machine state diagram, the statue should be -+ * Partner_Oper_Port_State.Synchronization = FALSE; -+ * Partner_Oper_Port_State.LACP_Timeout = Short Timeout; -+ * start current_while_timer(Short Timeout); -+ * Actor_Oper_Port_State.Expired = TRUE; -+ */ -+ port->partner_oper.port_state &= ~LACP_STATE_SYNCHRONIZATION; - port->partner_oper.port_state |= LACP_STATE_LACP_TIMEOUT; -- port->partner_oper.port_state |= LACP_STATE_LACP_ACTIVITY; - port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(AD_SHORT_TIMEOUT)); - port->actor_oper_port_state |= LACP_STATE_EXPIRED; - port->sm_vars |= AD_PORT_CHURNED; -@@ -1405,11 +1411,10 @@ static void ad_tx_machine(struct port *p - /** - * ad_periodic_machine - handle a port's periodic state machine - * @port: the port we're looking at -- * @bond_params: bond parameters we will use - * - * Turn ntt flag on priodically to perform periodic transmission of lacpdu's. - */ --static void ad_periodic_machine(struct port *port, struct bond_params *bond_params) -+static void ad_periodic_machine(struct port *port) - { - periodic_states_t last_state; - -@@ -1418,8 +1423,7 @@ static void ad_periodic_machine(struct p - - /* check if port was reinitialized */ - if (((port->sm_vars & AD_PORT_BEGIN) || !(port->sm_vars & AD_PORT_LACP_ENABLED) || !port->is_enabled) || -- (!(port->actor_oper_port_state & LACP_STATE_LACP_ACTIVITY) && !(port->partner_oper.port_state & LACP_STATE_LACP_ACTIVITY)) || -- !bond_params->lacp_active) { -+ (!(port->actor_oper_port_state & LACP_STATE_LACP_ACTIVITY) && !(port->partner_oper.port_state & LACP_STATE_LACP_ACTIVITY))) { - port->sm_periodic_state = AD_NO_PERIODIC; - } - /* check if state machine should change state */ -@@ -1943,16 +1947,16 @@ static void ad_initialize_agg(struct agg - /** - * ad_initialize_port - initialize a given port's parameters - * @port: the port we're looking at -- * @lacp_fast: boolean. whether fast periodic should be used -+ * @bond_params: bond parameters we will use - */ --static void ad_initialize_port(struct port *port, int lacp_fast) -+static void ad_initialize_port(struct port *port, const struct bond_params *bond_params) - { - static const struct port_params tmpl = { - .system_priority = 0xffff, - .key = 1, - .port_number = 1, - .port_priority = 0xff, -- .port_state = 1, -+ .port_state = 0, - }; - static const struct lacpdu lacpdu = { - .subtype = 0x01, -@@ -1970,12 +1974,14 @@ static void ad_initialize_port(struct po - port->actor_port_priority = 0xff; - port->actor_port_aggregator_identifier = 0; - port->ntt = false; -- port->actor_admin_port_state = LACP_STATE_AGGREGATION | -- LACP_STATE_LACP_ACTIVITY; -- port->actor_oper_port_state = LACP_STATE_AGGREGATION | -- LACP_STATE_LACP_ACTIVITY; -+ port->actor_admin_port_state = LACP_STATE_AGGREGATION; -+ port->actor_oper_port_state = LACP_STATE_AGGREGATION; -+ if (bond_params->lacp_active) { -+ port->actor_admin_port_state |= LACP_STATE_LACP_ACTIVITY; -+ port->actor_oper_port_state |= LACP_STATE_LACP_ACTIVITY; -+ } - -- if (lacp_fast) -+ if (bond_params->lacp_fast) - port->actor_oper_port_state |= LACP_STATE_LACP_TIMEOUT; - - memcpy(&port->partner_admin, &tmpl, sizeof(tmpl)); -@@ -2187,7 +2193,7 @@ void bond_3ad_bind_slave(struct slave *s - /* port initialization */ - port = &(SLAVE_AD_INFO(slave)->port); - -- ad_initialize_port(port, bond->params.lacp_fast); -+ ad_initialize_port(port, &bond->params); - - port->slave = slave; - port->actor_port_number = SLAVE_AD_INFO(slave)->id; -@@ -2499,7 +2505,7 @@ void bond_3ad_state_machine_handler(stru - } - - ad_rx_machine(NULL, port); -- ad_periodic_machine(port, &bond->params); -+ ad_periodic_machine(port); - ad_port_selection_logic(port, &update_slave_arr); - ad_mux_machine(port, &update_slave_arr); - ad_tx_machine(port); -@@ -2868,6 +2874,31 @@ void bond_3ad_update_lacp_rate(struct bo - } - spin_unlock_bh(&bond->mode_lock); - } -+ -+/** -+ * bond_3ad_update_lacp_active - change the lacp active -+ * @bond: bonding struct -+ * -+ * Update actor_oper_port_state when lacp_active is modified. -+ */ -+void bond_3ad_update_lacp_active(struct bonding *bond) -+{ -+ struct port *port = NULL; -+ struct list_head *iter; -+ struct slave *slave; -+ int lacp_active; -+ -+ lacp_active = bond->params.lacp_active; -+ spin_lock_bh(&bond->mode_lock); -+ bond_for_each_slave(bond, slave, iter) { -+ port = &(SLAVE_AD_INFO(slave)->port); -+ if (lacp_active) -+ port->actor_oper_port_state |= LACP_STATE_LACP_ACTIVITY; -+ else -+ port->actor_oper_port_state &= ~LACP_STATE_LACP_ACTIVITY; -+ } -+ spin_unlock_bh(&bond->mode_lock); -+} - - size_t bond_3ad_stats_size(void) - { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/bonding/bond_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/bonding/bond_main.c ---- BPI-Router-Linux-kernel/drivers/net/bonding/bond_main.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/bonding/bond_main.c 2025-10-22 13:53:56.539169026 -0400 -@@ -2115,6 +2115,7 @@ int bond_enslave(struct net_device *bond - memcpy(ss.__data, bond_dev->dev_addr, bond_dev->addr_len); - } else if (bond->params.fail_over_mac == BOND_FOM_FOLLOW && - BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP && -+ bond_has_slaves(bond) && - memcmp(slave_dev->dev_addr, bond_dev->dev_addr, bond_dev->addr_len) == 0) { - /* Set slave to random address to avoid duplicate mac - * address in later fail over. -@@ -3338,7 +3339,6 @@ static void bond_ns_send_all(struct bond - /* Find out through which dev should the packet go */ - memset(&fl6, 0, sizeof(struct flowi6)); - fl6.daddr = targets[i]; -- fl6.flowi6_oif = bond->dev->ifindex; - - dst = ip6_route_output(dev_net(bond->dev), NULL, &fl6); - if (dst->error) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/bonding/bond_options.c BPI-Router-Linux-kernel-6.16.12/drivers/net/bonding/bond_options.c ---- BPI-Router-Linux-kernel/drivers/net/bonding/bond_options.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/bonding/bond_options.c 2025-10-22 13:53:56.539169026 -0400 -@@ -1637,6 +1637,7 @@ static int bond_option_lacp_active_set(s - netdev_dbg(bond->dev, "Setting LACP active to %s (%llu)\n", - newval->string, newval->value); - bond->params.lacp_active = newval->value; -+ bond_3ad_update_lacp_active(bond); - - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/can/dev/dev.c BPI-Router-Linux-kernel-6.16.12/drivers/net/can/dev/dev.c ---- BPI-Router-Linux-kernel/drivers/net/can/dev/dev.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/can/dev/dev.c 2025-10-22 13:53:56.539169026 -0400 -@@ -145,13 +145,16 @@ void can_change_state(struct net_device - EXPORT_SYMBOL_GPL(can_change_state); - - /* CAN device restart for bus-off recovery */ --static void can_restart(struct net_device *dev) -+static int can_restart(struct net_device *dev) - { - struct can_priv *priv = netdev_priv(dev); - struct sk_buff *skb; - struct can_frame *cf; - int err; - -+ if (!priv->do_set_mode) -+ return -EOPNOTSUPP; -+ - if (netif_carrier_ok(dev)) - netdev_err(dev, "Attempt to restart for bus-off recovery, but carrier is OK?\n"); - -@@ -173,10 +176,14 @@ static void can_restart(struct net_devic - if (err) { - netdev_err(dev, "Restart failed, error %pe\n", ERR_PTR(err)); - netif_carrier_off(dev); -+ -+ return err; - } else { - netdev_dbg(dev, "Restarted\n"); - priv->can_stats.restarts++; - } -+ -+ return 0; - } - - static void can_restart_work(struct work_struct *work) -@@ -201,9 +208,8 @@ int can_restart_now(struct net_device *d - return -EBUSY; - - cancel_delayed_work_sync(&priv->restart_work); -- can_restart(dev); - -- return 0; -+ return can_restart(dev); - } - - /* CAN bus-off -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/can/dev/netlink.c BPI-Router-Linux-kernel-6.16.12/drivers/net/can/dev/netlink.c ---- BPI-Router-Linux-kernel/drivers/net/can/dev/netlink.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/can/dev/netlink.c 2025-10-22 13:53:56.539169026 -0400 -@@ -285,6 +285,12 @@ static int can_changelink(struct net_dev - } - - if (data[IFLA_CAN_RESTART_MS]) { -+ if (!priv->do_set_mode) { -+ NL_SET_ERR_MSG(extack, -+ "Device doesn't support restart from Bus Off"); -+ return -EOPNOTSUPP; -+ } -+ - /* Do not allow changing restart delay while running */ - if (dev->flags & IFF_UP) - return -EBUSY; -@@ -292,6 +298,12 @@ static int can_changelink(struct net_dev - } - - if (data[IFLA_CAN_RESTART]) { -+ if (!priv->do_set_mode) { -+ NL_SET_ERR_MSG(extack, -+ "Device doesn't support restart from Bus Off"); -+ return -EOPNOTSUPP; -+ } -+ - /* Do not allow a restart while not running */ - if (!(dev->flags & IFF_UP)) - return -EINVAL; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/can/kvaser_pciefd.c BPI-Router-Linux-kernel-6.16.12/drivers/net/can/kvaser_pciefd.c ---- BPI-Router-Linux-kernel/drivers/net/can/kvaser_pciefd.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/can/kvaser_pciefd.c 2025-10-22 13:53:56.539169026 -0400 -@@ -982,6 +982,7 @@ static int kvaser_pciefd_setup_can_ctrls - can->completed_tx_bytes = 0; - can->bec.txerr = 0; - can->bec.rxerr = 0; -+ can->can.dev->dev_port = i; - - init_completion(&can->start_comp); - init_completion(&can->flush_comp); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/can/m_can/m_can.c BPI-Router-Linux-kernel-6.16.12/drivers/net/can/m_can/m_can.c ---- BPI-Router-Linux-kernel/drivers/net/can/m_can/m_can.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/can/m_can/m_can.c 2025-10-22 13:53:56.539169026 -0400 -@@ -665,7 +665,7 @@ static int m_can_handle_lost_msg(struct - struct can_frame *frame; - u32 timestamp = 0; - -- netdev_err(dev, "msg lost in rxf0\n"); -+ netdev_dbg(dev, "msg lost in rxf0\n"); - - stats->rx_errors++; - stats->rx_over_errors++; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/can/m_can/tcan4x5x-core.c BPI-Router-Linux-kernel-6.16.12/drivers/net/can/m_can/tcan4x5x-core.c ---- BPI-Router-Linux-kernel/drivers/net/can/m_can/tcan4x5x-core.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/can/m_can/tcan4x5x-core.c 2025-10-22 13:53:56.539169026 -0400 -@@ -343,21 +343,19 @@ static void tcan4x5x_get_dt_data(struct - of_property_read_bool(cdev->dev->of_node, "ti,nwkrq-voltage-vio"); - } - --static int tcan4x5x_get_gpios(struct m_can_classdev *cdev, -- const struct tcan4x5x_version_info *version_info) -+static int tcan4x5x_get_gpios(struct m_can_classdev *cdev) - { - struct tcan4x5x_priv *tcan4x5x = cdev_to_priv(cdev); - int ret; - -- if (version_info->has_wake_pin) { -- tcan4x5x->device_wake_gpio = devm_gpiod_get(cdev->dev, "device-wake", -- GPIOD_OUT_HIGH); -- if (IS_ERR(tcan4x5x->device_wake_gpio)) { -- if (PTR_ERR(tcan4x5x->device_wake_gpio) == -EPROBE_DEFER) -- return -EPROBE_DEFER; -+ tcan4x5x->device_wake_gpio = devm_gpiod_get_optional(cdev->dev, -+ "device-wake", -+ GPIOD_OUT_HIGH); -+ if (IS_ERR(tcan4x5x->device_wake_gpio)) { -+ if (PTR_ERR(tcan4x5x->device_wake_gpio) == -EPROBE_DEFER) -+ return -EPROBE_DEFER; - -- tcan4x5x_disable_wake(cdev); -- } -+ tcan4x5x->device_wake_gpio = NULL; - } - - tcan4x5x->reset_gpio = devm_gpiod_get_optional(cdev->dev, "reset", -@@ -369,14 +367,31 @@ static int tcan4x5x_get_gpios(struct m_c - if (ret) - return ret; - -- if (version_info->has_state_pin) { -- tcan4x5x->device_state_gpio = devm_gpiod_get_optional(cdev->dev, -- "device-state", -- GPIOD_IN); -- if (IS_ERR(tcan4x5x->device_state_gpio)) { -- tcan4x5x->device_state_gpio = NULL; -- tcan4x5x_disable_state(cdev); -- } -+ tcan4x5x->device_state_gpio = devm_gpiod_get_optional(cdev->dev, -+ "device-state", -+ GPIOD_IN); -+ if (IS_ERR(tcan4x5x->device_state_gpio)) -+ tcan4x5x->device_state_gpio = NULL; -+ -+ return 0; -+} -+ -+static int tcan4x5x_check_gpios(struct m_can_classdev *cdev, -+ const struct tcan4x5x_version_info *version_info) -+{ -+ struct tcan4x5x_priv *tcan4x5x = cdev_to_priv(cdev); -+ int ret; -+ -+ if (version_info->has_wake_pin && !tcan4x5x->device_wake_gpio) { -+ ret = tcan4x5x_disable_wake(cdev); -+ if (ret) -+ return ret; -+ } -+ -+ if (version_info->has_state_pin && !tcan4x5x->device_state_gpio) { -+ ret = tcan4x5x_disable_state(cdev); -+ if (ret) -+ return ret; - } - - return 0; -@@ -411,10 +426,11 @@ static int tcan4x5x_can_probe(struct spi - priv = cdev_to_priv(mcan_class); - - priv->power = devm_regulator_get_optional(&spi->dev, "vsup"); -- if (PTR_ERR(priv->power) == -EPROBE_DEFER) { -- ret = -EPROBE_DEFER; -- goto out_m_can_class_free_dev; -- } else { -+ if (IS_ERR(priv->power)) { -+ if (PTR_ERR(priv->power) == -EPROBE_DEFER) { -+ ret = -EPROBE_DEFER; -+ goto out_m_can_class_free_dev; -+ } - priv->power = NULL; - } - -@@ -467,15 +483,21 @@ static int tcan4x5x_can_probe(struct spi - goto out_m_can_class_free_dev; - } - -+ ret = tcan4x5x_get_gpios(mcan_class); -+ if (ret) { -+ dev_err(&spi->dev, "Getting gpios failed %pe\n", ERR_PTR(ret)); -+ goto out_power; -+ } -+ - version_info = tcan4x5x_find_version(priv); - if (IS_ERR(version_info)) { - ret = PTR_ERR(version_info); - goto out_power; - } - -- ret = tcan4x5x_get_gpios(mcan_class, version_info); -+ ret = tcan4x5x_check_gpios(mcan_class, version_info); - if (ret) { -- dev_err(&spi->dev, "Getting gpios failed %pe\n", ERR_PTR(ret)); -+ dev_err(&spi->dev, "Checking gpios failed %pe\n", ERR_PTR(ret)); - goto out_power; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/can/rcar/rcar_can.c BPI-Router-Linux-kernel-6.16.12/drivers/net/can/rcar/rcar_can.c ---- BPI-Router-Linux-kernel/drivers/net/can/rcar/rcar_can.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/can/rcar/rcar_can.c 2025-10-22 13:53:56.539169026 -0400 -@@ -861,7 +861,6 @@ static int __maybe_unused rcar_can_resum - { - struct net_device *ndev = dev_get_drvdata(dev); - struct rcar_can_priv *priv = netdev_priv(ndev); -- u16 ctlr; - int err; - - if (!netif_running(ndev)) -@@ -873,12 +872,7 @@ static int __maybe_unused rcar_can_resum - return err; - } - -- ctlr = readw(&priv->regs->ctlr); -- ctlr &= ~RCAR_CAN_CTLR_SLPM; -- writew(ctlr, &priv->regs->ctlr); -- ctlr &= ~RCAR_CAN_CTLR_CANM; -- writew(ctlr, &priv->regs->ctlr); -- priv->can.state = CAN_STATE_ERROR_ACTIVE; -+ rcar_can_start(ndev); - - netif_device_attach(ndev); - netif_start_queue(ndev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/can/rcar/rcar_canfd.c BPI-Router-Linux-kernel-6.16.12/drivers/net/can/rcar/rcar_canfd.c ---- BPI-Router-Linux-kernel/drivers/net/can/rcar/rcar_canfd.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/can/rcar/rcar_canfd.c 2025-10-22 13:53:56.539169026 -0400 -@@ -870,9 +870,6 @@ static int rcar_canfd_reset_controller(s - /* Reset Global error flags */ - rcar_canfd_write(gpriv->base, RCANFD_GERFL, 0x0); - -- /* Set the controller into appropriate mode */ -- rcar_canfd_set_mode(gpriv); -- - /* Transition all Channels to reset mode */ - for_each_set_bit(ch, &gpriv->channels_mask, gpriv->info->max_channels) { - rcar_canfd_clear_bit(gpriv->base, -@@ -892,6 +889,10 @@ static int rcar_canfd_reset_controller(s - return err; - } - } -+ -+ /* Set the controller into appropriate mode */ -+ rcar_canfd_set_mode(gpriv); -+ - return 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/can/sja1000/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/net/can/sja1000/Kconfig ---- BPI-Router-Linux-kernel/drivers/net/can/sja1000/Kconfig 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/can/sja1000/Kconfig 2025-10-22 13:53:56.539169026 -0400 -@@ -105,7 +105,7 @@ config CAN_SJA1000_PLATFORM - - config CAN_TSCAN1 - tristate "TS-CAN1 PC104 boards" -- depends on ISA -+ depends on (ISA && PC104) || (COMPILE_TEST && HAS_IOPORT) - help - This driver is for Technologic Systems' TSCAN-1 PC104 boards. - https://www.embeddedts.com/products/TS-CAN1 -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/can/spi/hi311x.c BPI-Router-Linux-kernel-6.16.12/drivers/net/can/spi/hi311x.c ---- BPI-Router-Linux-kernel/drivers/net/can/spi/hi311x.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/can/spi/hi311x.c 2025-10-22 13:53:56.539169026 -0400 -@@ -545,8 +545,6 @@ static int hi3110_stop(struct net_device - - priv->force_quit = 1; - free_irq(spi->irq, priv); -- destroy_workqueue(priv->wq); -- priv->wq = NULL; - - mutex_lock(&priv->hi3110_lock); - -@@ -770,34 +768,23 @@ static int hi3110_open(struct net_device - goto out_close; - } - -- priv->wq = alloc_workqueue("hi3110_wq", WQ_FREEZABLE | WQ_MEM_RECLAIM, -- 0); -- if (!priv->wq) { -- ret = -ENOMEM; -- goto out_free_irq; -- } -- INIT_WORK(&priv->tx_work, hi3110_tx_work_handler); -- INIT_WORK(&priv->restart_work, hi3110_restart_work_handler); -- - ret = hi3110_hw_reset(spi); - if (ret) -- goto out_free_wq; -+ goto out_free_irq; - - ret = hi3110_setup(net); - if (ret) -- goto out_free_wq; -+ goto out_free_irq; - - ret = hi3110_set_normal_mode(spi); - if (ret) -- goto out_free_wq; -+ goto out_free_irq; - - netif_wake_queue(net); - mutex_unlock(&priv->hi3110_lock); - - return 0; - -- out_free_wq: -- destroy_workqueue(priv->wq); - out_free_irq: - free_irq(spi->irq, priv); - hi3110_hw_sleep(spi); -@@ -812,6 +799,7 @@ static const struct net_device_ops hi311 - .ndo_open = hi3110_open, - .ndo_stop = hi3110_stop, - .ndo_start_xmit = hi3110_hard_start_xmit, -+ .ndo_change_mtu = can_change_mtu, - }; - - static const struct ethtool_ops hi3110_ethtool_ops = { -@@ -908,6 +896,15 @@ static int hi3110_can_probe(struct spi_d - if (ret) - goto out_clk; - -+ priv->wq = alloc_workqueue("hi3110_wq", WQ_FREEZABLE | WQ_MEM_RECLAIM, -+ 0); -+ if (!priv->wq) { -+ ret = -ENOMEM; -+ goto out_clk; -+ } -+ INIT_WORK(&priv->tx_work, hi3110_tx_work_handler); -+ INIT_WORK(&priv->restart_work, hi3110_restart_work_handler); -+ - priv->spi = spi; - mutex_init(&priv->hi3110_lock); - -@@ -943,6 +940,8 @@ static int hi3110_can_probe(struct spi_d - return 0; - - error_probe: -+ destroy_workqueue(priv->wq); -+ priv->wq = NULL; - hi3110_power_enable(priv->power, 0); - - out_clk: -@@ -963,6 +962,9 @@ static void hi3110_can_remove(struct spi - - hi3110_power_enable(priv->power, 0); - -+ destroy_workqueue(priv->wq); -+ priv->wq = NULL; -+ - clk_disable_unprepare(priv->clk); - - free_candev(net); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/can/sun4i_can.c BPI-Router-Linux-kernel-6.16.12/drivers/net/can/sun4i_can.c ---- BPI-Router-Linux-kernel/drivers/net/can/sun4i_can.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/can/sun4i_can.c 2025-10-22 13:53:56.539169026 -0400 -@@ -768,6 +768,7 @@ static const struct net_device_ops sun4i - .ndo_open = sun4ican_open, - .ndo_stop = sun4ican_close, - .ndo_start_xmit = sun4ican_start_xmit, -+ .ndo_change_mtu = can_change_mtu, - }; - - static const struct ethtool_ops sun4ican_ethtool_ops = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/can/ti_hecc.c BPI-Router-Linux-kernel-6.16.12/drivers/net/can/ti_hecc.c ---- BPI-Router-Linux-kernel/drivers/net/can/ti_hecc.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/can/ti_hecc.c 2025-10-22 13:53:56.539169026 -0400 -@@ -383,7 +383,7 @@ static void ti_hecc_start(struct net_dev - * overflows instead of the hardware silently dropping the - * messages. - */ -- mbx_mask = ~BIT(HECC_RX_LAST_MBOX); -+ mbx_mask = ~BIT_U32(HECC_RX_LAST_MBOX); - hecc_write(priv, HECC_CANOPC, mbx_mask); - - /* Enable interrupts */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/can/usb/etas_es58x/es58x_core.c BPI-Router-Linux-kernel-6.16.12/drivers/net/can/usb/etas_es58x/es58x_core.c ---- BPI-Router-Linux-kernel/drivers/net/can/usb/etas_es58x/es58x_core.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/can/usb/etas_es58x/es58x_core.c 2025-10-22 13:53:56.543169006 -0400 -@@ -7,7 +7,7 @@ - * - * Copyright (c) 2019 Robert Bosch Engineering and Business Solutions. All rights reserved. - * Copyright (c) 2020 ETAS K.K.. All rights reserved. -- * Copyright (c) 2020-2022 Vincent Mailhol -+ * Copyright (c) 2020-2025 Vincent Mailhol - */ - - #include -@@ -1977,6 +1977,7 @@ static const struct net_device_ops es58x - .ndo_stop = es58x_stop, - .ndo_start_xmit = es58x_start_xmit, - .ndo_eth_ioctl = can_eth_ioctl_hwts, -+ .ndo_change_mtu = can_change_mtu, - }; - - static const struct ethtool_ops es58x_ethtool_ops = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c BPI-Router-Linux-kernel-6.16.12/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c ---- BPI-Router-Linux-kernel/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c 2025-10-22 13:53:56.543169006 -0400 -@@ -852,6 +852,7 @@ static int kvaser_usb_init_one(struct kv - netdev->ethtool_ops = &kvaser_usb_ethtool_ops; - SET_NETDEV_DEV(netdev, &dev->intf->dev); - netdev->dev_id = channel; -+ netdev->dev_port = channel; - - dev->nets[channel] = priv; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/can/usb/mcba_usb.c BPI-Router-Linux-kernel-6.16.12/drivers/net/can/usb/mcba_usb.c ---- BPI-Router-Linux-kernel/drivers/net/can/usb/mcba_usb.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/can/usb/mcba_usb.c 2025-10-22 13:53:56.543169006 -0400 -@@ -761,6 +761,7 @@ static const struct net_device_ops mcba_ - .ndo_open = mcba_usb_open, - .ndo_stop = mcba_usb_close, - .ndo_start_xmit = mcba_usb_start_xmit, -+ .ndo_change_mtu = can_change_mtu, - }; - - static const struct ethtool_ops mcba_ethtool_ops = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/can/usb/peak_usb/pcan_usb_core.c BPI-Router-Linux-kernel-6.16.12/drivers/net/can/usb/peak_usb/pcan_usb_core.c ---- BPI-Router-Linux-kernel/drivers/net/can/usb/peak_usb/pcan_usb_core.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/can/usb/peak_usb/pcan_usb_core.c 2025-10-22 13:53:56.543169006 -0400 -@@ -111,7 +111,7 @@ void peak_usb_update_ts_now(struct peak_ - u32 delta_ts = time_ref->ts_dev_2 - time_ref->ts_dev_1; - - if (time_ref->ts_dev_2 < time_ref->ts_dev_1) -- delta_ts &= (1 << time_ref->adapter->ts_used_bits) - 1; -+ delta_ts &= (1ULL << time_ref->adapter->ts_used_bits) - 1; - - time_ref->ts_total += delta_ts; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/can/usb/peak_usb/pcan_usb_fd.c BPI-Router-Linux-kernel-6.16.12/drivers/net/can/usb/peak_usb/pcan_usb_fd.c ---- BPI-Router-Linux-kernel/drivers/net/can/usb/peak_usb/pcan_usb_fd.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/can/usb/peak_usb/pcan_usb_fd.c 2025-10-22 13:53:56.543169006 -0400 -@@ -49,7 +49,7 @@ struct __packed pcan_ufd_fw_info { - __le32 ser_no; /* S/N */ - __le32 flags; /* special functions */ - -- /* extended data when type == PCAN_USBFD_TYPE_EXT */ -+ /* extended data when type >= PCAN_USBFD_TYPE_EXT */ - u8 cmd_out_ep; /* ep for cmd */ - u8 cmd_in_ep; /* ep for replies */ - u8 data_out_ep[2]; /* ep for CANx TX */ -@@ -982,10 +982,11 @@ static int pcan_usb_fd_init(struct peak_ - dev->can.ctrlmode |= CAN_CTRLMODE_FD_NON_ISO; - } - -- /* if vendor rsp is of type 2, then it contains EP numbers to -- * use for cmds pipes. If not, then default EP should be used. -+ /* if vendor rsp type is greater than or equal to 2, then it -+ * contains EP numbers to use for cmds pipes. If not, then -+ * default EP should be used. - */ -- if (fw_info->type != cpu_to_le16(PCAN_USBFD_TYPE_EXT)) { -+ if (le16_to_cpu(fw_info->type) < PCAN_USBFD_TYPE_EXT) { - fw_info->cmd_out_ep = PCAN_USBPRO_EP_CMDOUT; - fw_info->cmd_in_ep = PCAN_USBPRO_EP_CMDIN; - } -@@ -1018,11 +1019,11 @@ static int pcan_usb_fd_init(struct peak_ - dev->can_channel_id = - le32_to_cpu(pdev->usb_if->fw_info.dev_id[dev->ctrl_idx]); - -- /* if vendor rsp is of type 2, then it contains EP numbers to -- * use for data pipes. If not, then statically defined EP are used -- * (see peak_usb_create_dev()). -+ /* if vendor rsp type is greater than or equal to 2, then it contains EP -+ * numbers to use for data pipes. If not, then statically defined EP are -+ * used (see peak_usb_create_dev()). - */ -- if (fw_info->type == cpu_to_le16(PCAN_USBFD_TYPE_EXT)) { -+ if (le16_to_cpu(fw_info->type) >= PCAN_USBFD_TYPE_EXT) { - dev->ep_msg_in = fw_info->data_in_ep; - dev->ep_msg_out = fw_info->data_out_ep[dev->ctrl_idx]; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/can/xilinx_can.c BPI-Router-Linux-kernel-6.16.12/drivers/net/can/xilinx_can.c ---- BPI-Router-Linux-kernel/drivers/net/can/xilinx_can.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/can/xilinx_can.c 2025-10-22 13:53:56.543169006 -0400 -@@ -690,14 +690,6 @@ static void xcan_write_frame(struct net_ - dlc |= XCAN_DLCR_EDL_MASK; - } - -- if (!(priv->devtype.flags & XCAN_FLAG_TX_MAILBOXES) && -- (priv->devtype.flags & XCAN_FLAG_TXFEMP)) -- can_put_echo_skb(skb, ndev, priv->tx_head % priv->tx_max, 0); -- else -- can_put_echo_skb(skb, ndev, 0, 0); -- -- priv->tx_head++; -- - priv->write_reg(priv, XCAN_FRAME_ID_OFFSET(frame_offset), id); - /* If the CAN frame is RTR frame this write triggers transmission - * (not on CAN FD) -@@ -730,6 +722,14 @@ static void xcan_write_frame(struct net_ - data[1]); - } - } -+ -+ if (!(priv->devtype.flags & XCAN_FLAG_TX_MAILBOXES) && -+ (priv->devtype.flags & XCAN_FLAG_TXFEMP)) -+ can_put_echo_skb(skb, ndev, priv->tx_head % priv->tx_max, 0); -+ else -+ can_put_echo_skb(skb, ndev, 0, 0); -+ -+ priv->tx_head++; - } - - /** -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/dsa/b53/b53_common.c BPI-Router-Linux-kernel-6.16.12/drivers/net/dsa/b53/b53_common.c ---- BPI-Router-Linux-kernel/drivers/net/dsa/b53/b53_common.c 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/dsa/b53/b53_common.c 2025-10-22 13:53:56.543169006 -0400 -@@ -361,18 +361,23 @@ static void b53_set_forwarding(struct b5 - - b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt); - -- /* Include IMP port in dumb forwarding mode -- */ -- b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, &mgmt); -- mgmt |= B53_MII_DUMB_FWDG_EN; -- b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, mgmt); -- -- /* Look at B53_UC_FWD_EN and B53_MC_FWD_EN to decide whether -- * frames should be flooded or not. -- */ -- b53_read8(dev, B53_CTRL_PAGE, B53_IP_MULTICAST_CTRL, &mgmt); -- mgmt |= B53_UC_FWD_EN | B53_MC_FWD_EN | B53_IPMC_FWD_EN; -- b53_write8(dev, B53_CTRL_PAGE, B53_IP_MULTICAST_CTRL, mgmt); -+ if (!is5325(dev)) { -+ /* Include IMP port in dumb forwarding mode */ -+ b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, &mgmt); -+ mgmt |= B53_MII_DUMB_FWDG_EN; -+ b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, mgmt); -+ -+ /* Look at B53_UC_FWD_EN and B53_MC_FWD_EN to decide whether -+ * frames should be flooded or not. -+ */ -+ b53_read8(dev, B53_CTRL_PAGE, B53_IP_MULTICAST_CTRL, &mgmt); -+ mgmt |= B53_UC_FWD_EN | B53_MC_FWD_EN | B53_IPMC_FWD_EN; -+ b53_write8(dev, B53_CTRL_PAGE, B53_IP_MULTICAST_CTRL, mgmt); -+ } else { -+ b53_read8(dev, B53_CTRL_PAGE, B53_IP_MULTICAST_CTRL, &mgmt); -+ mgmt |= B53_IP_MCAST_25; -+ b53_write8(dev, B53_CTRL_PAGE, B53_IP_MULTICAST_CTRL, mgmt); -+ } - } - - static void b53_enable_vlan(struct b53_device *dev, int port, bool enable, -@@ -529,6 +534,10 @@ void b53_imp_vlan_setup(struct dsa_switc - unsigned int i; - u16 pvlan; - -+ /* BCM5325 CPU port is at 8 */ -+ if ((is5325(dev) || is5365(dev)) && cpu_port == B53_CPU_PORT_25) -+ cpu_port = B53_CPU_PORT; -+ - /* Enable the IMP port to be in the same VLAN as the other ports - * on a per-port basis such that we only have Port i and IMP in - * the same VLAN. -@@ -579,6 +588,9 @@ static void b53_port_set_learning(struct - { - u16 reg; - -+ if (is5325(dev)) -+ return; -+ - b53_read16(dev, B53_CTRL_PAGE, B53_DIS_LEARNING, ®); - if (learning) - reg &= ~BIT(port); -@@ -615,6 +627,19 @@ int b53_setup_port(struct dsa_switch *ds - if (dsa_is_user_port(ds, port)) - b53_set_eap_mode(dev, port, EAP_MODE_SIMPLIFIED); - -+ if (is5325(dev) && -+ in_range(port, 1, 4)) { -+ u8 reg; -+ -+ b53_read8(dev, B53_CTRL_PAGE, B53_PD_MODE_CTRL_25, ®); -+ reg &= ~PD_MODE_POWER_DOWN_PORT(0); -+ if (dsa_is_unused_port(ds, port)) -+ reg |= PD_MODE_POWER_DOWN_PORT(port); -+ else -+ reg &= ~PD_MODE_POWER_DOWN_PORT(port); -+ b53_write8(dev, B53_CTRL_PAGE, B53_PD_MODE_CTRL_25, reg); -+ } -+ - return 0; - } - EXPORT_SYMBOL(b53_setup_port); -@@ -1204,9 +1229,15 @@ static int b53_setup(struct dsa_switch * - */ - ds->untag_vlan_aware_bridge_pvid = true; - -- /* Ageing time is set in seconds */ -- ds->ageing_time_min = 1 * 1000; -- ds->ageing_time_max = AGE_TIME_MAX * 1000; -+ if (dev->chip_id == BCM53101_DEVICE_ID) { -+ /* BCM53101 uses 0.5 second increments */ -+ ds->ageing_time_min = 1 * 500; -+ ds->ageing_time_max = AGE_TIME_MAX * 500; -+ } else { -+ /* Everything else uses 1 second increments */ -+ ds->ageing_time_min = 1 * 1000; -+ ds->ageing_time_max = AGE_TIME_MAX * 1000; -+ } - - ret = b53_reset_switch(dev); - if (ret) { -@@ -1257,6 +1288,8 @@ static void b53_force_link(struct b53_de - if (port == dev->imp_port) { - off = B53_PORT_OVERRIDE_CTRL; - val = PORT_OVERRIDE_EN; -+ } else if (is5325(dev)) { -+ return; - } else { - off = B53_GMII_PORT_OVERRIDE_CTRL(port); - val = GMII_PO_EN; -@@ -1281,6 +1314,8 @@ static void b53_force_port_config(struct - if (port == dev->imp_port) { - off = B53_PORT_OVERRIDE_CTRL; - val = PORT_OVERRIDE_EN; -+ } else if (is5325(dev)) { -+ return; - } else { - off = B53_GMII_PORT_OVERRIDE_CTRL(port); - val = GMII_PO_EN; -@@ -1311,10 +1346,19 @@ static void b53_force_port_config(struct - return; - } - -- if (rx_pause) -- reg |= PORT_OVERRIDE_RX_FLOW; -- if (tx_pause) -- reg |= PORT_OVERRIDE_TX_FLOW; -+ if (rx_pause) { -+ if (is5325(dev)) -+ reg |= PORT_OVERRIDE_LP_FLOW_25; -+ else -+ reg |= PORT_OVERRIDE_RX_FLOW; -+ } -+ -+ if (tx_pause) { -+ if (is5325(dev)) -+ reg |= PORT_OVERRIDE_LP_FLOW_25; -+ else -+ reg |= PORT_OVERRIDE_TX_FLOW; -+ } - - b53_write8(dev, B53_CTRL_PAGE, off, reg); - } -@@ -2034,9 +2078,6 @@ int b53_br_join(struct dsa_switch *ds, i - - b53_get_vlan_entry(dev, pvid, vl); - vl->members &= ~BIT(port); -- if (vl->members == BIT(cpu_port)) -- vl->members &= ~BIT(cpu_port); -- vl->untag = vl->members; - b53_set_vlan_entry(dev, pvid, vl); - } - -@@ -2115,8 +2156,7 @@ void b53_br_leave(struct dsa_switch *ds, - } - - b53_get_vlan_entry(dev, pvid, vl); -- vl->members |= BIT(port) | BIT(cpu_port); -- vl->untag |= BIT(port) | BIT(cpu_port); -+ vl->members |= BIT(port); - b53_set_vlan_entry(dev, pvid, vl); - } - } -@@ -2169,7 +2209,13 @@ int b53_br_flags_pre(struct dsa_switch * - struct switchdev_brport_flags flags, - struct netlink_ext_ack *extack) - { -- if (flags.mask & ~(BR_FLOOD | BR_MCAST_FLOOD | BR_LEARNING)) -+ struct b53_device *dev = ds->priv; -+ unsigned long mask = (BR_FLOOD | BR_MCAST_FLOOD); -+ -+ if (!is5325(dev)) -+ mask |= BR_LEARNING; -+ -+ if (flags.mask & ~mask) - return -EINVAL; - - return 0; -@@ -2408,7 +2454,10 @@ int b53_set_ageing_time(struct dsa_switc - else - reg = B53_AGING_TIME_CONTROL; - -- atc = DIV_ROUND_CLOSEST(msecs, 1000); -+ if (dev->chip_id == BCM53101_DEVICE_ID) -+ atc = DIV_ROUND_CLOSEST(msecs, 500); -+ else -+ atc = DIV_ROUND_CLOSEST(msecs, 1000); - - if (!is5325(dev) && !is5365(dev)) - atc |= AGE_CHANGE; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/dsa/b53/b53_regs.h BPI-Router-Linux-kernel-6.16.12/drivers/net/dsa/b53/b53_regs.h ---- BPI-Router-Linux-kernel/drivers/net/dsa/b53/b53_regs.h 2025-10-22 13:53:23.311328666 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/dsa/b53/b53_regs.h 2025-10-22 13:53:56.543169006 -0400 -@@ -95,17 +95,22 @@ - #define PORT_OVERRIDE_SPEED_10M (0 << PORT_OVERRIDE_SPEED_S) - #define PORT_OVERRIDE_SPEED_100M (1 << PORT_OVERRIDE_SPEED_S) - #define PORT_OVERRIDE_SPEED_1000M (2 << PORT_OVERRIDE_SPEED_S) -+#define PORT_OVERRIDE_LP_FLOW_25 BIT(3) /* BCM5325 only */ - #define PORT_OVERRIDE_RV_MII_25 BIT(4) /* BCM5325 only */ - #define PORT_OVERRIDE_RX_FLOW BIT(4) - #define PORT_OVERRIDE_TX_FLOW BIT(5) - #define PORT_OVERRIDE_SPEED_2000M BIT(6) /* BCM5301X only, requires setting 1000M */ - #define PORT_OVERRIDE_EN BIT(7) /* Use the register contents */ - --/* Power-down mode control */ -+/* Power-down mode control (8 bit) */ - #define B53_PD_MODE_CTRL_25 0x0f -+#define PD_MODE_PORT_MASK 0x1f -+/* Bit 0 also powers down the switch. */ -+#define PD_MODE_POWER_DOWN_PORT(i) BIT(i) - - /* IP Multicast control (8 bit) */ - #define B53_IP_MULTICAST_CTRL 0x21 -+#define B53_IP_MCAST_25 BIT(0) - #define B53_IPMC_FWD_EN BIT(1) - #define B53_UC_FWD_EN BIT(6) - #define B53_MC_FWD_EN BIT(7) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/dsa/lantiq_gswip.c BPI-Router-Linux-kernel-6.16.12/drivers/net/dsa/lantiq_gswip.c ---- BPI-Router-Linux-kernel/drivers/net/dsa/lantiq_gswip.c 2025-10-22 13:53:23.315328646 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/dsa/lantiq_gswip.c 2025-10-22 13:53:56.543169006 -0400 -@@ -685,18 +685,27 @@ static int gswip_add_single_port_br(stru - return 0; - } - --static int gswip_port_enable(struct dsa_switch *ds, int port, -- struct phy_device *phydev) -+static int gswip_port_setup(struct dsa_switch *ds, int port) - { - struct gswip_priv *priv = ds->priv; - int err; - - if (!dsa_is_cpu_port(ds, port)) { -- u32 mdio_phy = 0; -- - err = gswip_add_single_port_br(priv, port, true); - if (err) - return err; -+ } -+ -+ return 0; -+} -+ -+static int gswip_port_enable(struct dsa_switch *ds, int port, -+ struct phy_device *phydev) -+{ -+ struct gswip_priv *priv = ds->priv; -+ -+ if (!dsa_is_cpu_port(ds, port)) { -+ u32 mdio_phy = 0; - - if (phydev) - mdio_phy = phydev->mdio.addr & GSWIP_MDIO_PHY_ADDR_MASK; -@@ -1359,8 +1368,9 @@ static int gswip_port_fdb(struct dsa_swi - int i; - int err; - -+ /* Operation not supported on the CPU port, don't throw errors */ - if (!bridge) -- return -EINVAL; -+ return 0; - - for (i = max_ports; i < ARRAY_SIZE(priv->vlans); i++) { - if (priv->vlans[i].bridge == bridge) { -@@ -1829,6 +1839,7 @@ static const struct phylink_mac_ops gswi - static const struct dsa_switch_ops gswip_xrx200_switch_ops = { - .get_tag_protocol = gswip_get_tag_protocol, - .setup = gswip_setup, -+ .port_setup = gswip_port_setup, - .port_enable = gswip_port_enable, - .port_disable = gswip_port_disable, - .port_bridge_join = gswip_port_bridge_join, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/dsa/microchip/ksz8.c BPI-Router-Linux-kernel-6.16.12/drivers/net/dsa/microchip/ksz8.c ---- BPI-Router-Linux-kernel/drivers/net/dsa/microchip/ksz8.c 2025-10-22 13:53:23.315328646 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/dsa/microchip/ksz8.c 2025-10-22 13:53:56.543169006 -0400 -@@ -371,6 +371,9 @@ static void ksz8863_r_mib_pkt(struct ksz - addr -= dev->info->reg_mib_cnt; - ctrl_addr = addr ? KSZ8863_MIB_PACKET_DROPPED_TX_0 : - KSZ8863_MIB_PACKET_DROPPED_RX_0; -+ if (ksz_is_8895_family(dev) && -+ ctrl_addr == KSZ8863_MIB_PACKET_DROPPED_RX_0) -+ ctrl_addr = KSZ8895_MIB_PACKET_DROPPED_RX_0; - ctrl_addr += port; - ctrl_addr |= IND_ACC_TABLE(TABLE_MIB | TABLE_READ); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/dsa/microchip/ksz8_reg.h BPI-Router-Linux-kernel-6.16.12/drivers/net/dsa/microchip/ksz8_reg.h ---- BPI-Router-Linux-kernel/drivers/net/dsa/microchip/ksz8_reg.h 2025-10-22 13:53:23.315328646 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/dsa/microchip/ksz8_reg.h 2025-10-22 13:53:56.543169006 -0400 -@@ -784,7 +784,9 @@ - #define KSZ8795_MIB_TOTAL_TX_1 0x105 - - #define KSZ8863_MIB_PACKET_DROPPED_TX_0 0x100 --#define KSZ8863_MIB_PACKET_DROPPED_RX_0 0x105 -+#define KSZ8863_MIB_PACKET_DROPPED_RX_0 0x103 -+ -+#define KSZ8895_MIB_PACKET_DROPPED_RX_0 0x105 - - #define MIB_PACKET_DROPPED 0x0000FFFF - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/dsa/microchip/ksz_common.c BPI-Router-Linux-kernel-6.16.12/drivers/net/dsa/microchip/ksz_common.c ---- BPI-Router-Linux-kernel/drivers/net/dsa/microchip/ksz_common.c 2025-10-22 13:53:23.315328646 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/dsa/microchip/ksz_common.c 2025-10-22 13:53:56.543169006 -0400 -@@ -2347,6 +2347,12 @@ static void ksz_update_port_member(struc - dev->dev_ops->cfg_port_member(dev, i, val | cpu_port); - } - -+ /* HSR ports are setup once so need to use the assigned membership -+ * when the port is enabled. -+ */ -+ if (!port_member && p->stp_state == BR_STATE_FORWARDING && -+ (dev->hsr_ports & BIT(port))) -+ port_member = dev->hsr_ports; - dev->dev_ops->cfg_port_member(dev, port, port_member | cpu_port); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/dsa/mv88e6xxx/leds.c BPI-Router-Linux-kernel-6.16.12/drivers/net/dsa/mv88e6xxx/leds.c ---- BPI-Router-Linux-kernel/drivers/net/dsa/mv88e6xxx/leds.c 2025-10-22 13:53:23.315328646 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/dsa/mv88e6xxx/leds.c 2025-10-22 13:53:56.543169006 -0400 -@@ -779,7 +779,8 @@ int mv88e6xxx_port_setup_leds(struct mv8 - continue; - if (led_num > 1) { - dev_err(dev, "invalid LED specified port %d\n", port); -- return -EINVAL; -+ ret = -EINVAL; -+ goto err_put_led; - } - - if (led_num == 0) -@@ -823,17 +824,25 @@ int mv88e6xxx_port_setup_leds(struct mv8 - init_data.devname_mandatory = true; - init_data.devicename = kasprintf(GFP_KERNEL, "%s:0%d:0%d", chip->info->name, - port, led_num); -- if (!init_data.devicename) -- return -ENOMEM; -+ if (!init_data.devicename) { -+ ret = -ENOMEM; -+ goto err_put_led; -+ } - - ret = devm_led_classdev_register_ext(dev, l, &init_data); - kfree(init_data.devicename); - - if (ret) { - dev_err(dev, "Failed to init LED %d for port %d", led_num, port); -- return ret; -+ goto err_put_led; - } - } - -+ fwnode_handle_put(leds); - return 0; -+ -+err_put_led: -+ fwnode_handle_put(led); -+ fwnode_handle_put(leds); -+ return ret; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/agere/et131x.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/agere/et131x.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/agere/et131x.c 2025-10-22 13:53:23.315328646 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/agere/et131x.c 2025-10-22 13:53:56.543169006 -0400 -@@ -2459,6 +2459,10 @@ static int nic_send_packet(struct et131x - skb->data, - skb_headlen(skb), - DMA_TO_DEVICE); -+ if (dma_mapping_error(&adapter->pdev->dev, -+ dma_addr)) -+ return -ENOMEM; -+ - desc[frag].addr_lo = lower_32_bits(dma_addr); - desc[frag].addr_hi = upper_32_bits(dma_addr); - frag++; -@@ -2468,6 +2472,10 @@ static int nic_send_packet(struct et131x - skb->data, - skb_headlen(skb) / 2, - DMA_TO_DEVICE); -+ if (dma_mapping_error(&adapter->pdev->dev, -+ dma_addr)) -+ return -ENOMEM; -+ - desc[frag].addr_lo = lower_32_bits(dma_addr); - desc[frag].addr_hi = upper_32_bits(dma_addr); - frag++; -@@ -2478,6 +2486,10 @@ static int nic_send_packet(struct et131x - skb_headlen(skb) / 2, - skb_headlen(skb) / 2, - DMA_TO_DEVICE); -+ if (dma_mapping_error(&adapter->pdev->dev, -+ dma_addr)) -+ goto unmap_first_out; -+ - desc[frag].addr_lo = lower_32_bits(dma_addr); - desc[frag].addr_hi = upper_32_bits(dma_addr); - frag++; -@@ -2489,6 +2501,9 @@ static int nic_send_packet(struct et131x - 0, - desc[frag].len_vlan, - DMA_TO_DEVICE); -+ if (dma_mapping_error(&adapter->pdev->dev, dma_addr)) -+ goto unmap_out; -+ - desc[frag].addr_lo = lower_32_bits(dma_addr); - desc[frag].addr_hi = upper_32_bits(dma_addr); - frag++; -@@ -2578,6 +2593,27 @@ static int nic_send_packet(struct et131x - &adapter->regs->global.watchdog_timer); - } - return 0; -+ -+unmap_out: -+ // Unmap the body of the packet with map_page -+ while (--i) { -+ frag--; -+ dma_addr = desc[frag].addr_lo; -+ dma_addr |= (u64)desc[frag].addr_hi << 32; -+ dma_unmap_page(&adapter->pdev->dev, dma_addr, -+ desc[frag].len_vlan, DMA_TO_DEVICE); -+ } -+ -+unmap_first_out: -+ // Unmap the header with map_single -+ while (frag--) { -+ dma_addr = desc[frag].addr_lo; -+ dma_addr |= (u64)desc[frag].addr_hi << 32; -+ dma_unmap_single(&adapter->pdev->dev, dma_addr, -+ desc[frag].len_vlan, DMA_TO_DEVICE); -+ } -+ -+ return -ENOMEM; - } - - static int send_packet(struct sk_buff *skb, struct et131x_adapter *adapter) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/airoha/airoha_eth.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/airoha/airoha_eth.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/airoha/airoha_eth.c 2025-10-22 13:53:23.315328646 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/airoha/airoha_eth.c 2025-10-22 13:53:56.543169006 -0400 -@@ -1065,23 +1065,18 @@ static void airoha_qdma_cleanup_tx_queue - - static int airoha_qdma_init_hfwd_queues(struct airoha_qdma *qdma) - { -+ int size, index, num_desc = HW_DSCP_NUM; - struct airoha_eth *eth = qdma->eth; - int id = qdma - ð->qdma[0]; -+ u32 status, buf_size; - dma_addr_t dma_addr; - const char *name; -- int size, index; -- u32 status; -- -- size = HW_DSCP_NUM * sizeof(struct airoha_qdma_fwd_desc); -- if (!dmam_alloc_coherent(eth->dev, size, &dma_addr, GFP_KERNEL)) -- return -ENOMEM; -- -- airoha_qdma_wr(qdma, REG_FWD_DSCP_BASE, dma_addr); - - name = devm_kasprintf(eth->dev, GFP_KERNEL, "qdma%d-buf", id); - if (!name) - return -ENOMEM; - -+ buf_size = id ? AIROHA_MAX_PACKET_SIZE / 2 : AIROHA_MAX_PACKET_SIZE; - index = of_property_match_string(eth->dev->of_node, - "memory-region-names", name); - if (index >= 0) { -@@ -1099,8 +1094,12 @@ static int airoha_qdma_init_hfwd_queues( - rmem = of_reserved_mem_lookup(np); - of_node_put(np); - dma_addr = rmem->base; -+ /* Compute the number of hw descriptors according to the -+ * reserved memory size and the payload buffer size -+ */ -+ num_desc = div_u64(rmem->size, buf_size); - } else { -- size = AIROHA_MAX_PACKET_SIZE * HW_DSCP_NUM; -+ size = buf_size * num_desc; - if (!dmam_alloc_coherent(eth->dev, size, &dma_addr, - GFP_KERNEL)) - return -ENOMEM; -@@ -1108,15 +1107,21 @@ static int airoha_qdma_init_hfwd_queues( - - airoha_qdma_wr(qdma, REG_FWD_BUF_BASE, dma_addr); - -+ size = num_desc * sizeof(struct airoha_qdma_fwd_desc); -+ if (!dmam_alloc_coherent(eth->dev, size, &dma_addr, GFP_KERNEL)) -+ return -ENOMEM; -+ -+ airoha_qdma_wr(qdma, REG_FWD_DSCP_BASE, dma_addr); -+ /* QDMA0: 2KB. QDMA1: 1KB */ - airoha_qdma_rmw(qdma, REG_HW_FWD_DSCP_CFG, - HW_FWD_DSCP_PAYLOAD_SIZE_MASK, -- FIELD_PREP(HW_FWD_DSCP_PAYLOAD_SIZE_MASK, 0)); -+ FIELD_PREP(HW_FWD_DSCP_PAYLOAD_SIZE_MASK, !!id)); - airoha_qdma_rmw(qdma, REG_FWD_DSCP_LOW_THR, FWD_DSCP_LOW_THR_MASK, - FIELD_PREP(FWD_DSCP_LOW_THR_MASK, 128)); - airoha_qdma_rmw(qdma, REG_LMGR_INIT_CFG, - LMGR_INIT_START | LMGR_SRAM_MODE_MASK | - HW_FWD_DESC_NUM_MASK, -- FIELD_PREP(HW_FWD_DESC_NUM_MASK, HW_DSCP_NUM) | -+ FIELD_PREP(HW_FWD_DESC_NUM_MASK, num_desc) | - LMGR_INIT_START | LMGR_SRAM_MODE_MASK); - - return read_poll_timeout(airoha_qdma_rr, status, -@@ -2979,6 +2984,7 @@ static int airoha_probe(struct platform_ - error_napi_stop: - for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) - airoha_qdma_stop_napi(ð->qdma[i]); -+ airoha_ppe_deinit(eth); - error_hw_cleanup: - for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) - airoha_hw_cleanup(ð->qdma[i]); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/airoha/airoha_npu.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/airoha/airoha_npu.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/airoha/airoha_npu.c 2025-10-22 13:53:23.315328646 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/airoha/airoha_npu.c 2025-10-22 13:53:56.543169006 -0400 -@@ -401,12 +401,13 @@ struct airoha_npu *airoha_npu_get(struct - return ERR_PTR(-ENODEV); - - pdev = of_find_device_by_node(np); -- of_node_put(np); - - if (!pdev) { - dev_err(dev, "cannot find device node %s\n", np->name); -+ of_node_put(np); - return ERR_PTR(-ENODEV); - } -+ of_node_put(np); - - if (!try_module_get(THIS_MODULE)) { - dev_err(dev, "failed to get the device driver module\n"); -@@ -585,6 +586,8 @@ static struct platform_driver airoha_npu - }; - module_platform_driver(airoha_npu_driver); - -+MODULE_FIRMWARE(NPU_EN7581_FIRMWARE_DATA); -+MODULE_FIRMWARE(NPU_EN7581_FIRMWARE_RV32); - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Lorenzo Bianconi "); - MODULE_DESCRIPTION("Airoha Network Processor Unit driver"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/airoha/airoha_ppe.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/airoha/airoha_ppe.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/airoha/airoha_ppe.c 2025-10-22 13:53:23.315328646 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/airoha/airoha_ppe.c 2025-10-22 13:53:56.543169006 -0400 -@@ -498,9 +498,11 @@ static void airoha_ppe_foe_flow_stats_up - FIELD_PREP(AIROHA_FOE_IB2_NBQ, nbq); - } - --struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe, -- u32 hash) -+static struct airoha_foe_entry * -+airoha_ppe_foe_get_entry_locked(struct airoha_ppe *ppe, u32 hash) - { -+ lockdep_assert_held(&ppe_lock); -+ - if (hash < PPE_SRAM_NUM_ENTRIES) { - u32 *hwe = ppe->foe + hash * sizeof(struct airoha_foe_entry); - struct airoha_eth *eth = ppe->eth; -@@ -527,6 +529,18 @@ struct airoha_foe_entry *airoha_ppe_foe_ - return ppe->foe + hash * sizeof(struct airoha_foe_entry); - } - -+struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe, -+ u32 hash) -+{ -+ struct airoha_foe_entry *hwe; -+ -+ spin_lock_bh(&ppe_lock); -+ hwe = airoha_ppe_foe_get_entry_locked(ppe, hash); -+ spin_unlock_bh(&ppe_lock); -+ -+ return hwe; -+} -+ - static bool airoha_ppe_foe_compare_entry(struct airoha_flow_table_entry *e, - struct airoha_foe_entry *hwe) - { -@@ -641,7 +655,7 @@ airoha_ppe_foe_commit_subflow_entry(stru - struct airoha_flow_table_entry *f; - int type; - -- hwe_p = airoha_ppe_foe_get_entry(ppe, hash); -+ hwe_p = airoha_ppe_foe_get_entry_locked(ppe, hash); - if (!hwe_p) - return -EINVAL; - -@@ -693,7 +707,7 @@ static void airoha_ppe_foe_insert_entry( - - spin_lock_bh(&ppe_lock); - -- hwe = airoha_ppe_foe_get_entry(ppe, hash); -+ hwe = airoha_ppe_foe_get_entry_locked(ppe, hash); - if (!hwe) - goto unlock; - -@@ -712,10 +726,8 @@ static void airoha_ppe_foe_insert_entry( - continue; - } - -- if (commit_done || !airoha_ppe_foe_compare_entry(e, hwe)) { -- e->hash = 0xffff; -+ if (!airoha_ppe_foe_compare_entry(e, hwe)) - continue; -- } - - airoha_ppe_foe_commit_entry(ppe, &e->data, hash); - commit_done = true; -@@ -808,9 +820,11 @@ airoha_ppe_foe_flow_l2_entry_update(stru - u32 ib1, state; - int idle; - -- hwe = airoha_ppe_foe_get_entry(ppe, iter->hash); -- ib1 = READ_ONCE(hwe->ib1); -+ hwe = airoha_ppe_foe_get_entry_locked(ppe, iter->hash); -+ if (!hwe) -+ continue; - -+ ib1 = READ_ONCE(hwe->ib1); - state = FIELD_GET(AIROHA_FOE_IB1_BIND_STATE, ib1); - if (state != AIROHA_FOE_STATE_BIND) { - iter->hash = 0xffff; -@@ -843,7 +857,7 @@ static void airoha_ppe_foe_flow_entry_up - if (e->hash == 0xffff) - goto unlock; - -- hwe_p = airoha_ppe_foe_get_entry(ppe, e->hash); -+ hwe_p = airoha_ppe_foe_get_entry_locked(ppe, e->hash); - if (!hwe_p) - goto unlock; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/airoha/airoha_regs.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/airoha/airoha_regs.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/airoha/airoha_regs.h 2025-10-22 13:53:23.315328646 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/airoha/airoha_regs.h 2025-10-22 13:53:56.543169006 -0400 -@@ -614,8 +614,9 @@ - RX19_DONE_INT_MASK | RX18_DONE_INT_MASK | \ - RX17_DONE_INT_MASK | RX16_DONE_INT_MASK) - --#define RX_DONE_INT_MASK (RX_DONE_HIGH_INT_MASK | RX_DONE_LOW_INT_MASK) - #define RX_DONE_HIGH_OFFSET fls(RX_DONE_HIGH_INT_MASK) -+#define RX_DONE_INT_MASK \ -+ ((RX_DONE_HIGH_INT_MASK << RX_DONE_HIGH_OFFSET) | RX_DONE_LOW_INT_MASK) - - #define INT_RX2_MASK(_n) \ - ((RX_NO_CPU_DSCP_HIGH_INT_MASK & (_n)) | \ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/amd/xgbe/xgbe-common.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/amd/xgbe/xgbe-common.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/amd/xgbe/xgbe-common.h 2025-10-22 13:53:23.315328646 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/amd/xgbe/xgbe-common.h 2025-10-22 13:53:56.543169006 -0400 -@@ -1269,6 +1269,8 @@ - #define MDIO_VEND2_CTRL1_SS13 BIT(13) - #endif - -+#define XGBE_VEND2_MAC_AUTO_SW BIT(9) -+ - /* MDIO mask values */ - #define XGBE_AN_CL73_INT_CMPLT BIT(0) - #define XGBE_AN_CL73_INC_LINK BIT(1) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/amd/xgbe/xgbe.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/amd/xgbe/xgbe.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/amd/xgbe/xgbe.h 2025-10-22 13:53:23.315328646 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/amd/xgbe/xgbe.h 2025-10-22 13:53:56.547168987 -0400 -@@ -183,12 +183,12 @@ - #define XGBE_LINK_TIMEOUT 5 - #define XGBE_KR_TRAINING_WAIT_ITER 50 - --#define XGBE_SGMII_AN_LINK_STATUS BIT(1) -+#define XGBE_SGMII_AN_LINK_DUPLEX BIT(1) - #define XGBE_SGMII_AN_LINK_SPEED (BIT(2) | BIT(3)) - #define XGBE_SGMII_AN_LINK_SPEED_10 0x00 - #define XGBE_SGMII_AN_LINK_SPEED_100 0x04 - #define XGBE_SGMII_AN_LINK_SPEED_1000 0x08 --#define XGBE_SGMII_AN_LINK_DUPLEX BIT(4) -+#define XGBE_SGMII_AN_LINK_STATUS BIT(4) - - /* ECC correctable error notification window (seconds) */ - #define XGBE_ECC_LIMIT 60 -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c 2025-10-22 13:53:23.315328646 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c 2025-10-22 13:53:56.547168987 -0400 -@@ -266,6 +266,10 @@ static void xgbe_an37_set(struct xgbe_pr - reg |= MDIO_VEND2_CTRL1_AN_RESTART; - - XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_CTRL1, reg); -+ -+ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL); -+ reg |= XGBE_VEND2_MAC_AUTO_SW; -+ XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL, reg); - } - - static void xgbe_an37_restart(struct xgbe_prv_data *pdata) -@@ -894,6 +898,11 @@ static void xgbe_an37_init(struct xgbe_p - - netif_dbg(pdata, link, pdata->netdev, "CL37 AN (%s) initialized\n", - (pdata->an_mode == XGBE_AN_MODE_CL37) ? "BaseX" : "SGMII"); -+ -+ reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_CTRL1); -+ reg &= ~MDIO_AN_CTRL1_ENABLE; -+ XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_CTRL1, reg); -+ - } - - static void xgbe_an73_init(struct xgbe_prv_data *pdata) -@@ -1295,6 +1304,10 @@ static void xgbe_phy_status(struct xgbe_ - - pdata->phy.link = pdata->phy_if.phy_impl.link_status(pdata, - &an_restart); -+ /* bail out if the link status register read fails */ -+ if (pdata->phy.link < 0) -+ return; -+ - if (an_restart) { - xgbe_phy_config_aneg(pdata); - goto adjust_link; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c 2025-10-22 13:53:23.315328646 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c 2025-10-22 13:53:56.547168987 -0400 -@@ -2746,8 +2746,7 @@ static bool xgbe_phy_valid_speed(struct - static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart) - { - struct xgbe_phy_data *phy_data = pdata->phy_data; -- unsigned int reg; -- int ret; -+ int reg, ret; - - *an_restart = 0; - -@@ -2781,11 +2780,20 @@ static int xgbe_phy_link_status(struct x - return 0; - } - -- /* Link status is latched low, so read once to clear -- * and then read again to get current state -- */ -- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1); - reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1); -+ if (reg < 0) -+ return reg; -+ -+ /* Link status is latched low so that momentary link drops -+ * can be detected. If link was already down read again -+ * to get the latest state. -+ */ -+ -+ if (!pdata->phy.link && !(reg & MDIO_STAT1_LSTATUS)) { -+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1); -+ if (reg < 0) -+ return reg; -+ } - - if (pdata->en_rx_adap) { - /* if the link is available and adaptation is done, -@@ -2804,9 +2812,7 @@ static int xgbe_phy_link_status(struct x - xgbe_phy_set_mode(pdata, phy_data->cur_mode); - } - -- /* check again for the link and adaptation status */ -- reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1); -- if ((reg & MDIO_STAT1_LSTATUS) && pdata->rx_adapt_done) -+ if (pdata->rx_adapt_done) - return 1; - } else if (reg & MDIO_STAT1_LSTATUS) - return 1; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/aquantia/atlantic/aq_hw.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/aquantia/atlantic/aq_hw.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/aquantia/atlantic/aq_hw.h 2025-10-22 13:53:23.315328646 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/aquantia/atlantic/aq_hw.h 2025-10-22 13:53:56.547168987 -0400 -@@ -113,6 +113,8 @@ struct aq_stats_s { - #define AQ_HW_POWER_STATE_D0 0U - #define AQ_HW_POWER_STATE_D3 3U - -+#define AQ_FW_WAKE_ON_LINK_RTPM BIT(10) -+ - #define AQ_HW_FLAG_STARTED 0x00000004U - #define AQ_HW_FLAG_STOPPING 0x00000008U - #define AQ_HW_FLAG_RESETTING 0x00000010U -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c 2025-10-22 13:53:23.315328646 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c 2025-10-22 13:53:56.547168987 -0400 -@@ -462,6 +462,44 @@ static int aq_a2_fw_get_mac_temp(struct - return aq_a2_fw_get_phy_temp(self, temp); - } - -+static int aq_a2_fw_set_wol_params(struct aq_hw_s *self, const u8 *mac, u32 wol) -+{ -+ struct mac_address_aligned_s mac_address; -+ struct link_control_s link_control; -+ struct wake_on_lan_s wake_on_lan; -+ -+ memcpy(mac_address.aligned.mac_address, mac, ETH_ALEN); -+ hw_atl2_shared_buffer_write(self, mac_address, mac_address); -+ -+ memset(&wake_on_lan, 0, sizeof(wake_on_lan)); -+ -+ if (wol & WAKE_MAGIC) -+ wake_on_lan.wake_on_magic_packet = 1U; -+ -+ if (wol & (WAKE_PHY | AQ_FW_WAKE_ON_LINK_RTPM)) -+ wake_on_lan.wake_on_link_up = 1U; -+ -+ hw_atl2_shared_buffer_write(self, sleep_proxy, wake_on_lan); -+ -+ hw_atl2_shared_buffer_get(self, link_control, link_control); -+ link_control.mode = AQ_HOST_MODE_SLEEP_PROXY; -+ hw_atl2_shared_buffer_write(self, link_control, link_control); -+ -+ return hw_atl2_shared_buffer_finish_ack(self); -+} -+ -+static int aq_a2_fw_set_power(struct aq_hw_s *self, unsigned int power_state, -+ const u8 *mac) -+{ -+ u32 wol = self->aq_nic_cfg->wol; -+ int err = 0; -+ -+ if (wol) -+ err = aq_a2_fw_set_wol_params(self, mac, wol); -+ -+ return err; -+} -+ - static int aq_a2_fw_set_eee_rate(struct aq_hw_s *self, u32 speed) - { - struct link_options_s link_options; -@@ -605,6 +643,7 @@ const struct aq_fw_ops aq_a2_fw_ops = { - .set_state = aq_a2_fw_set_state, - .update_link_status = aq_a2_fw_update_link_status, - .update_stats = aq_a2_fw_update_stats, -+ .set_power = aq_a2_fw_set_power, - .get_mac_temp = aq_a2_fw_get_mac_temp, - .get_phy_temp = aq_a2_fw_get_phy_temp, - .set_eee_rate = aq_a2_fw_set_eee_rate, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/atheros/ag71xx.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/atheros/ag71xx.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/atheros/ag71xx.c 2025-10-22 13:53:23.319328627 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/atheros/ag71xx.c 2025-10-22 13:53:56.547168987 -0400 -@@ -1213,6 +1213,11 @@ static bool ag71xx_fill_rx_buf(struct ag - buf->rx.rx_buf = data; - buf->rx.dma_addr = dma_map_single(&ag->pdev->dev, data, ag->rx_buf_size, - DMA_FROM_DEVICE); -+ if (dma_mapping_error(&ag->pdev->dev, buf->rx.dma_addr)) { -+ skb_free_frag(data); -+ buf->rx.rx_buf = NULL; -+ return false; -+ } - desc->data = (u32)buf->rx.dma_addr + offset; - return true; - } -@@ -1511,6 +1516,10 @@ static netdev_tx_t ag71xx_hard_start_xmi - - dma_addr = dma_map_single(&ag->pdev->dev, skb->data, skb->len, - DMA_TO_DEVICE); -+ if (dma_mapping_error(&ag->pdev->dev, dma_addr)) { -+ netif_dbg(ag, tx_err, ndev, "DMA mapping error\n"); -+ goto err_drop; -+ } - - i = ring->curr & ring_mask; - desc = ag71xx_ring_desc(ring, i); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/atheros/atlx/atl1.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/atheros/atlx/atl1.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/atheros/atlx/atl1.c 2025-10-22 13:53:23.319328627 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/atheros/atlx/atl1.c 2025-10-22 13:53:56.547168987 -0400 -@@ -1861,14 +1861,21 @@ static u16 atl1_alloc_rx_buffers(struct - break; - } - -- buffer_info->alloced = 1; -- buffer_info->skb = skb; -- buffer_info->length = (u16) adapter->rx_buffer_len; - page = virt_to_page(skb->data); - offset = offset_in_page(skb->data); - buffer_info->dma = dma_map_page(&pdev->dev, page, offset, - adapter->rx_buffer_len, - DMA_FROM_DEVICE); -+ if (dma_mapping_error(&pdev->dev, buffer_info->dma)) { -+ kfree_skb(skb); -+ adapter->soft_stats.rx_dropped++; -+ break; -+ } -+ -+ buffer_info->alloced = 1; -+ buffer_info->skb = skb; -+ buffer_info->length = (u16)adapter->rx_buffer_len; -+ - rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma); - rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len); - rfd_desc->coalese = 0; -@@ -2183,8 +2190,8 @@ static int atl1_tx_csum(struct atl1_adap - return 0; - } - --static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, -- struct tx_packet_desc *ptpd) -+static bool atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, -+ struct tx_packet_desc *ptpd) - { - struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; - struct atl1_buffer *buffer_info; -@@ -2194,6 +2201,7 @@ static void atl1_tx_map(struct atl1_adap - unsigned int nr_frags; - unsigned int f; - int retval; -+ u16 first_mapped; - u16 next_to_use; - u16 data_len; - u8 hdr_len; -@@ -2201,6 +2209,7 @@ static void atl1_tx_map(struct atl1_adap - buf_len -= skb->data_len; - nr_frags = skb_shinfo(skb)->nr_frags; - next_to_use = atomic_read(&tpd_ring->next_to_use); -+ first_mapped = next_to_use; - buffer_info = &tpd_ring->buffer_info[next_to_use]; - BUG_ON(buffer_info->skb); - /* put skb in last TPD */ -@@ -2216,6 +2225,8 @@ static void atl1_tx_map(struct atl1_adap - buffer_info->dma = dma_map_page(&adapter->pdev->dev, page, - offset, hdr_len, - DMA_TO_DEVICE); -+ if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma)) -+ goto dma_err; - - if (++next_to_use == tpd_ring->count) - next_to_use = 0; -@@ -2242,6 +2253,9 @@ static void atl1_tx_map(struct atl1_adap - page, offset, - buffer_info->length, - DMA_TO_DEVICE); -+ if (dma_mapping_error(&adapter->pdev->dev, -+ buffer_info->dma)) -+ goto dma_err; - if (++next_to_use == tpd_ring->count) - next_to_use = 0; - } -@@ -2254,6 +2268,8 @@ static void atl1_tx_map(struct atl1_adap - buffer_info->dma = dma_map_page(&adapter->pdev->dev, page, - offset, buf_len, - DMA_TO_DEVICE); -+ if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma)) -+ goto dma_err; - if (++next_to_use == tpd_ring->count) - next_to_use = 0; - } -@@ -2277,6 +2293,9 @@ static void atl1_tx_map(struct atl1_adap - buffer_info->dma = skb_frag_dma_map(&adapter->pdev->dev, - frag, i * ATL1_MAX_TX_BUF_LEN, - buffer_info->length, DMA_TO_DEVICE); -+ if (dma_mapping_error(&adapter->pdev->dev, -+ buffer_info->dma)) -+ goto dma_err; - - if (++next_to_use == tpd_ring->count) - next_to_use = 0; -@@ -2285,6 +2304,22 @@ static void atl1_tx_map(struct atl1_adap - - /* last tpd's buffer-info */ - buffer_info->skb = skb; -+ -+ return true; -+ -+ dma_err: -+ while (first_mapped != next_to_use) { -+ buffer_info = &tpd_ring->buffer_info[first_mapped]; -+ dma_unmap_page(&adapter->pdev->dev, -+ buffer_info->dma, -+ buffer_info->length, -+ DMA_TO_DEVICE); -+ buffer_info->dma = 0; -+ -+ if (++first_mapped == tpd_ring->count) -+ first_mapped = 0; -+ } -+ return false; - } - - static void atl1_tx_queue(struct atl1_adapter *adapter, u16 count, -@@ -2355,10 +2390,8 @@ static netdev_tx_t atl1_xmit_frame(struc - - len = skb_headlen(skb); - -- if (unlikely(skb->len <= 0)) { -- dev_kfree_skb_any(skb); -- return NETDEV_TX_OK; -- } -+ if (unlikely(skb->len <= 0)) -+ goto drop_packet; - - nr_frags = skb_shinfo(skb)->nr_frags; - for (f = 0; f < nr_frags; f++) { -@@ -2371,10 +2404,9 @@ static netdev_tx_t atl1_xmit_frame(struc - if (mss) { - if (skb->protocol == htons(ETH_P_IP)) { - proto_hdr_len = skb_tcp_all_headers(skb); -- if (unlikely(proto_hdr_len > len)) { -- dev_kfree_skb_any(skb); -- return NETDEV_TX_OK; -- } -+ if (unlikely(proto_hdr_len > len)) -+ goto drop_packet; -+ - /* need additional TPD ? */ - if (proto_hdr_len != len) - count += (len - proto_hdr_len + -@@ -2406,23 +2438,26 @@ static netdev_tx_t atl1_xmit_frame(struc - } - - tso = atl1_tso(adapter, skb, ptpd); -- if (tso < 0) { -- dev_kfree_skb_any(skb); -- return NETDEV_TX_OK; -- } -+ if (tso < 0) -+ goto drop_packet; - - if (!tso) { - ret_val = atl1_tx_csum(adapter, skb, ptpd); -- if (ret_val < 0) { -- dev_kfree_skb_any(skb); -- return NETDEV_TX_OK; -- } -+ if (ret_val < 0) -+ goto drop_packet; - } - -- atl1_tx_map(adapter, skb, ptpd); -+ if (!atl1_tx_map(adapter, skb, ptpd)) -+ goto drop_packet; -+ - atl1_tx_queue(adapter, count, ptpd); - atl1_update_mailbox(adapter); - return NETDEV_TX_OK; -+ -+drop_packet: -+ adapter->soft_stats.tx_errors++; -+ dev_kfree_skb_any(skb); -+ return NETDEV_TX_OK; - } - - static int atl1_rings_clean(struct napi_struct *napi, int budget) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c 2025-10-22 13:53:23.319328627 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c 2025-10-22 13:53:56.547168987 -0400 -@@ -818,6 +818,9 @@ static void bcmasp_init_tx(struct bcmasp - /* Tx SPB */ - tx_spb_ctrl_wl(intf, ((intf->channel + 8) << TX_SPB_CTRL_XF_BID_SHIFT), - TX_SPB_CTRL_XF_CTRL2); -+ -+ if (intf->parent->tx_chan_offset) -+ tx_pause_ctrl_wl(intf, (1 << (intf->channel + 8)), TX_PAUSE_MAP_VECTOR); - tx_spb_top_wl(intf, 0x1e, TX_SPB_TOP_BLKOUT); - - tx_spb_dma_wq(intf, intf->tx_spb_dma_addr, TX_SPB_DMA_READ); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/broadcom/bnxt/bnxt.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/broadcom/bnxt/bnxt.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/broadcom/bnxt/bnxt.c 2025-10-22 13:53:23.319328627 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/broadcom/bnxt/bnxt.c 2025-10-22 13:53:56.547168987 -0400 -@@ -921,15 +921,21 @@ static struct page *__bnxt_alloc_rx_page - - static netmem_ref __bnxt_alloc_rx_netmem(struct bnxt *bp, dma_addr_t *mapping, - struct bnxt_rx_ring_info *rxr, -+ unsigned int *offset, - gfp_t gfp) - { - netmem_ref netmem; - -- netmem = page_pool_alloc_netmems(rxr->page_pool, gfp); -+ if (PAGE_SIZE > BNXT_RX_PAGE_SIZE) { -+ netmem = page_pool_alloc_frag_netmem(rxr->page_pool, offset, BNXT_RX_PAGE_SIZE, gfp); -+ } else { -+ netmem = page_pool_alloc_netmems(rxr->page_pool, gfp); -+ *offset = 0; -+ } - if (!netmem) - return 0; - -- *mapping = page_pool_get_dma_addr_netmem(netmem); -+ *mapping = page_pool_get_dma_addr_netmem(netmem) + *offset; - return netmem; - } - -@@ -1024,7 +1030,7 @@ static int bnxt_alloc_rx_netmem(struct b - dma_addr_t mapping; - netmem_ref netmem; - -- netmem = __bnxt_alloc_rx_netmem(bp, &mapping, rxr, gfp); -+ netmem = __bnxt_alloc_rx_netmem(bp, &mapping, rxr, &offset, gfp); - if (!netmem) - return -ENOMEM; - -@@ -2989,6 +2995,7 @@ static int __bnxt_poll_work(struct bnxt - { - struct bnxt_napi *bnapi = cpr->bnapi; - u32 raw_cons = cpr->cp_raw_cons; -+ bool flush_xdp = false; - u32 cons; - int rx_pkts = 0; - u8 event = 0; -@@ -3042,6 +3049,8 @@ static int __bnxt_poll_work(struct bnxt - else - rc = bnxt_force_rx_discard(bp, cpr, &raw_cons, - &event); -+ if (event & BNXT_REDIRECT_EVENT) -+ flush_xdp = true; - if (likely(rc >= 0)) - rx_pkts += rc; - /* Increment rx_pkts when rc is -ENOMEM to count towards -@@ -3066,7 +3075,7 @@ static int __bnxt_poll_work(struct bnxt - } - } - -- if (event & BNXT_REDIRECT_EVENT) { -+ if (flush_xdp) { - xdp_do_flush(); - event &= ~BNXT_REDIRECT_EVENT; - } -@@ -3800,14 +3809,15 @@ static int bnxt_alloc_rx_page_pool(struc - struct bnxt_rx_ring_info *rxr, - int numa_node) - { -+ const unsigned int agg_size_fac = PAGE_SIZE / BNXT_RX_PAGE_SIZE; -+ const unsigned int rx_size_fac = PAGE_SIZE / SZ_4K; - struct page_pool_params pp = { 0 }; - struct page_pool *pool; - -- pp.pool_size = bp->rx_agg_ring_size; -+ pp.pool_size = bp->rx_agg_ring_size / agg_size_fac; - if (BNXT_RX_PAGE_MODE(bp)) -- pp.pool_size += bp->rx_ring_size; -+ pp.pool_size += bp->rx_ring_size / rx_size_fac; - pp.nid = numa_node; -- pp.napi = &rxr->bnapi->napi; - pp.netdev = bp->dev; - pp.dev = &bp->pdev->dev; - pp.dma_dir = bp->rx_dir; -@@ -3823,7 +3833,7 @@ static int bnxt_alloc_rx_page_pool(struc - - rxr->need_head_pool = page_pool_is_unreadable(pool); - if (bnxt_separate_head_pool(rxr)) { -- pp.pool_size = max(bp->rx_ring_size, 1024); -+ pp.pool_size = min(bp->rx_ring_size / rx_size_fac, 1024); - pp.flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV; - pool = page_pool_create(&pp); - if (IS_ERR(pool)) -@@ -3839,6 +3849,12 @@ err_destroy_pp: - return PTR_ERR(pool); - } - -+static void bnxt_enable_rx_page_pool(struct bnxt_rx_ring_info *rxr) -+{ -+ page_pool_enable_direct_recycling(rxr->head_pool, &rxr->bnapi->napi); -+ page_pool_enable_direct_recycling(rxr->page_pool, &rxr->bnapi->napi); -+} -+ - static int bnxt_alloc_rx_agg_bmap(struct bnxt *bp, struct bnxt_rx_ring_info *rxr) - { - u16 mem_size; -@@ -3877,6 +3893,7 @@ static int bnxt_alloc_rx_rings(struct bn - rc = bnxt_alloc_rx_page_pool(bp, rxr, cpu_node); - if (rc) - return rc; -+ bnxt_enable_rx_page_pool(rxr); - - rc = xdp_rxq_info_reg(&rxr->xdp_rxq, bp->dev, i, 0); - if (rc < 0) -@@ -4373,7 +4390,7 @@ static void bnxt_alloc_one_rx_ring_netme - for (i = 0; i < bp->rx_agg_ring_size; i++) { - if (bnxt_alloc_rx_netmem(bp, rxr, prod, GFP_KERNEL)) { - netdev_warn(bp->dev, "init'ed rx ring %d with %d/%d pages only\n", -- ring_nr, i, bp->rx_ring_size); -+ ring_nr, i, bp->rx_agg_ring_size); - break; - } - prod = NEXT_RX_AGG(prod); -@@ -5308,7 +5325,7 @@ static void bnxt_free_ntp_fltrs(struct b - { - int i; - -- netdev_assert_locked(bp->dev); -+ netdev_assert_locked_or_invisible(bp->dev); - - /* Under netdev instance lock and all our NAPIs have been disabled. - * It's safe to delete the hash table. -@@ -7992,7 +8009,8 @@ static int __bnxt_reserve_rings(struct b - } - rx_rings = min_t(int, rx_rings, hwr.grp); - hwr.cp = min_t(int, hwr.cp, bp->cp_nr_rings); -- if (hwr.stat > bnxt_get_ulp_stat_ctxs(bp)) -+ if (bnxt_ulp_registered(bp->edev) && -+ hwr.stat > bnxt_get_ulp_stat_ctxs(bp)) - hwr.stat -= bnxt_get_ulp_stat_ctxs(bp); - hwr.cp = min_t(int, hwr.cp, hwr.stat); - rc = bnxt_trim_rings(bp, &rx_rings, &hwr.tx, hwr.cp, sh); -@@ -8000,6 +8018,11 @@ static int __bnxt_reserve_rings(struct b - hwr.rx = rx_rings << 1; - tx_cp = bnxt_num_tx_to_cp(bp, hwr.tx); - hwr.cp = sh ? max_t(int, tx_cp, rx_rings) : tx_cp + rx_rings; -+ if (hwr.tx != bp->tx_nr_rings) { -+ netdev_warn(bp->dev, -+ "Able to reserve only %d out of %d requested TX rings\n", -+ hwr.tx, bp->tx_nr_rings); -+ } - bp->tx_nr_rings = hwr.tx; - - /* If we cannot reserve all the RX rings, reset the RSS map only -@@ -10780,6 +10803,72 @@ void bnxt_del_one_rss_ctx(struct bnxt *b - bp->num_rss_ctx--; - } - -+static bool bnxt_vnic_has_rx_ring(struct bnxt *bp, struct bnxt_vnic_info *vnic, -+ int rxr_id) -+{ -+ u16 tbl_size = bnxt_get_rxfh_indir_size(bp->dev); -+ int i, vnic_rx; -+ -+ /* Ntuple VNIC always has all the rx rings. Any change of ring id -+ * must be updated because a future filter may use it. -+ */ -+ if (vnic->flags & BNXT_VNIC_NTUPLE_FLAG) -+ return true; -+ -+ for (i = 0; i < tbl_size; i++) { -+ if (vnic->flags & BNXT_VNIC_RSSCTX_FLAG) -+ vnic_rx = ethtool_rxfh_context_indir(vnic->rss_ctx)[i]; -+ else -+ vnic_rx = bp->rss_indir_tbl[i]; -+ -+ if (rxr_id == vnic_rx) -+ return true; -+ } -+ -+ return false; -+} -+ -+static int bnxt_set_vnic_mru_p5(struct bnxt *bp, struct bnxt_vnic_info *vnic, -+ u16 mru, int rxr_id) -+{ -+ int rc; -+ -+ if (!bnxt_vnic_has_rx_ring(bp, vnic, rxr_id)) -+ return 0; -+ -+ if (mru) { -+ rc = bnxt_hwrm_vnic_set_rss_p5(bp, vnic, true); -+ if (rc) { -+ netdev_err(bp->dev, "hwrm vnic %d set rss failure rc: %d\n", -+ vnic->vnic_id, rc); -+ return rc; -+ } -+ } -+ vnic->mru = mru; -+ bnxt_hwrm_vnic_update(bp, vnic, -+ VNIC_UPDATE_REQ_ENABLES_MRU_VALID); -+ -+ return 0; -+} -+ -+static int bnxt_set_rss_ctx_vnic_mru(struct bnxt *bp, u16 mru, int rxr_id) -+{ -+ struct ethtool_rxfh_context *ctx; -+ unsigned long context; -+ int rc; -+ -+ xa_for_each(&bp->dev->ethtool->rss_ctx, context, ctx) { -+ struct bnxt_rss_ctx *rss_ctx = ethtool_rxfh_context_priv(ctx); -+ struct bnxt_vnic_info *vnic = &rss_ctx->vnic; -+ -+ rc = bnxt_set_vnic_mru_p5(bp, vnic, mru, rxr_id); -+ if (rc) -+ return rc; -+ } -+ -+ return 0; -+} -+ - static void bnxt_hwrm_realloc_rss_ctx_vnic(struct bnxt *bp) - { - bool set_tpa = !!(bp->flags & BNXT_FLAG_TPA); -@@ -11538,11 +11627,9 @@ static void bnxt_free_irq(struct bnxt *b - - static int bnxt_request_irq(struct bnxt *bp) - { -+ struct cpu_rmap *rmap = NULL; - int i, j, rc = 0; - unsigned long flags = 0; --#ifdef CONFIG_RFS_ACCEL -- struct cpu_rmap *rmap; --#endif - - rc = bnxt_setup_int_mode(bp); - if (rc) { -@@ -11563,15 +11650,15 @@ static int bnxt_request_irq(struct bnxt - int map_idx = bnxt_cp_num_to_irq_num(bp, i); - struct bnxt_irq *irq = &bp->irq_tbl[map_idx]; - --#ifdef CONFIG_RFS_ACCEL -- if (rmap && bp->bnapi[i]->rx_ring) { -+ if (IS_ENABLED(CONFIG_RFS_ACCEL) && -+ rmap && bp->bnapi[i]->rx_ring) { - rc = irq_cpu_rmap_add(rmap, irq->vector); - if (rc) - netdev_warn(bp->dev, "failed adding irq rmap for ring %d\n", - j); - j++; - } --#endif -+ - rc = request_irq(irq->vector, irq->handler, flags, irq->name, - bp->bnapi[i]); - if (rc) -@@ -12763,6 +12850,17 @@ static int bnxt_set_xps_mapping(struct b - return rc; - } - -+static int bnxt_tx_nr_rings(struct bnxt *bp) -+{ -+ return bp->num_tc ? bp->tx_nr_rings_per_tc * bp->num_tc : -+ bp->tx_nr_rings_per_tc; -+} -+ -+static int bnxt_tx_nr_rings_per_tc(struct bnxt *bp) -+{ -+ return bp->num_tc ? bp->tx_nr_rings / bp->num_tc : bp->tx_nr_rings; -+} -+ - static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) - { - int rc = 0; -@@ -12780,6 +12878,13 @@ static int __bnxt_open_nic(struct bnxt * - if (rc) - return rc; - -+ /* Make adjustments if reserved TX rings are less than requested */ -+ bp->tx_nr_rings -= bp->tx_nr_rings_xdp; -+ bp->tx_nr_rings_per_tc = bnxt_tx_nr_rings_per_tc(bp); -+ if (bp->tx_nr_rings_xdp) { -+ bp->tx_nr_rings_xdp = bp->tx_nr_rings_per_tc; -+ bp->tx_nr_rings += bp->tx_nr_rings_xdp; -+ } - rc = bnxt_alloc_mem(bp, irq_re_init); - if (rc) { - netdev_err(bp->dev, "bnxt_alloc_mem err: %x\n", rc); -@@ -15927,6 +16032,7 @@ static int bnxt_queue_start(struct net_d - struct bnxt_vnic_info *vnic; - struct bnxt_napi *bnapi; - int i, rc; -+ u16 mru; - - rxr = &bp->rx_ring[idx]; - clone = qmem; -@@ -15974,24 +16080,19 @@ static int bnxt_queue_start(struct net_d - goto err_reset; - } - -+ bnxt_enable_rx_page_pool(rxr); - napi_enable_locked(&bnapi->napi); - bnxt_db_nq_arm(bp, &cpr->cp_db, cpr->cp_raw_cons); - -+ mru = bp->dev->mtu + ETH_HLEN + VLAN_HLEN; - for (i = 0; i < bp->nr_vnics; i++) { - vnic = &bp->vnic_info[i]; - -- rc = bnxt_hwrm_vnic_set_rss_p5(bp, vnic, true); -- if (rc) { -- netdev_err(bp->dev, "hwrm vnic %d set rss failure rc: %d\n", -- vnic->vnic_id, rc); -+ rc = bnxt_set_vnic_mru_p5(bp, vnic, mru, idx); -+ if (rc) - return rc; -- } -- vnic->mru = bp->dev->mtu + ETH_HLEN + VLAN_HLEN; -- bnxt_hwrm_vnic_update(bp, vnic, -- VNIC_UPDATE_REQ_ENABLES_MRU_VALID); - } -- -- return 0; -+ return bnxt_set_rss_ctx_vnic_mru(bp, mru, idx); - - err_reset: - netdev_err(bp->dev, "Unexpected HWRM error during queue start rc: %d\n", -@@ -16013,10 +16114,10 @@ static int bnxt_queue_stop(struct net_de - - for (i = 0; i < bp->nr_vnics; i++) { - vnic = &bp->vnic_info[i]; -- vnic->mru = 0; -- bnxt_hwrm_vnic_update(bp, vnic, -- VNIC_UPDATE_REQ_ENABLES_MRU_VALID); -+ -+ bnxt_set_vnic_mru_p5(bp, vnic, 0, idx); - } -+ bnxt_set_rss_ctx_vnic_mru(bp, 0, idx); - /* Make sure NAPI sees that the VNIC is disabled */ - synchronize_net(); - rxr = &bp->rx_ring[idx]; -@@ -16261,7 +16362,7 @@ static void bnxt_trim_dflt_sh_rings(stru - bp->cp_nr_rings = min_t(int, bp->tx_nr_rings_per_tc, bp->rx_nr_rings); - bp->rx_nr_rings = bp->cp_nr_rings; - bp->tx_nr_rings_per_tc = bp->cp_nr_rings; -- bp->tx_nr_rings = bp->tx_nr_rings_per_tc; -+ bp->tx_nr_rings = bnxt_tx_nr_rings(bp); - } - - static int bnxt_set_dflt_rings(struct bnxt *bp, bool sh) -@@ -16293,7 +16394,7 @@ static int bnxt_set_dflt_rings(struct bn - bnxt_trim_dflt_sh_rings(bp); - else - bp->cp_nr_rings = bp->tx_nr_rings_per_tc + bp->rx_nr_rings; -- bp->tx_nr_rings = bp->tx_nr_rings_per_tc; -+ bp->tx_nr_rings = bnxt_tx_nr_rings(bp); - - avail_msix = bnxt_get_max_func_irqs(bp) - bp->cp_nr_rings; - if (avail_msix >= BNXT_MIN_ROCE_CP_RINGS) { -@@ -16306,7 +16407,7 @@ static int bnxt_set_dflt_rings(struct bn - rc = __bnxt_reserve_rings(bp); - if (rc && rc != -ENODEV) - netdev_warn(bp->dev, "Unable to reserve tx rings\n"); -- bp->tx_nr_rings_per_tc = bp->tx_nr_rings; -+ bp->tx_nr_rings_per_tc = bnxt_tx_nr_rings_per_tc(bp); - if (sh) - bnxt_trim_dflt_sh_rings(bp); - -@@ -16315,7 +16416,7 @@ static int bnxt_set_dflt_rings(struct bn - rc = __bnxt_reserve_rings(bp); - if (rc && rc != -ENODEV) - netdev_warn(bp->dev, "2nd rings reservation failed.\n"); -- bp->tx_nr_rings_per_tc = bp->tx_nr_rings; -+ bp->tx_nr_rings_per_tc = bnxt_tx_nr_rings_per_tc(bp); - } - if (BNXT_CHIP_TYPE_NITRO_A0(bp)) { - bp->rx_nr_rings++; -@@ -16349,7 +16450,7 @@ static int bnxt_init_dflt_ring_mode(stru - if (rc) - goto init_dflt_ring_err; - -- bp->tx_nr_rings_per_tc = bp->tx_nr_rings; -+ bp->tx_nr_rings_per_tc = bnxt_tx_nr_rings_per_tc(bp); - - bnxt_set_dflt_rfs(bp); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c 2025-10-22 13:53:23.319328627 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/broadcom/bnxt/bnxt_coredump.c 2025-10-22 13:53:56.547168987 -0400 -@@ -368,23 +368,27 @@ static u32 bnxt_get_ctx_coredump(struct - if (!ctxm->mem_valid || !seg_id) - continue; - -- if (trace) -+ if (trace) { - extra_hlen = BNXT_SEG_RCD_LEN; -+ if (buf) { -+ u16 trace_type = bnxt_bstore_to_trace[type]; -+ -+ bnxt_fill_drv_seg_record(bp, &record, ctxm, -+ trace_type); -+ } -+ } -+ - if (buf) - data = buf + BNXT_SEG_HDR_LEN + extra_hlen; -+ - seg_len = bnxt_copy_ctx_mem(bp, ctxm, data, 0) + extra_hlen; - if (buf) { - bnxt_fill_coredump_seg_hdr(bp, &seg_hdr, NULL, seg_len, - 0, 0, 0, comp_id, seg_id); - memcpy(buf, &seg_hdr, BNXT_SEG_HDR_LEN); - buf += BNXT_SEG_HDR_LEN; -- if (trace) { -- u16 trace_type = bnxt_bstore_to_trace[type]; -- -- bnxt_fill_drv_seg_record(bp, &record, ctxm, -- trace_type); -+ if (trace) - memcpy(buf, &record, BNXT_SEG_RCD_LEN); -- } - buf += seg_len; - } - len += BNXT_SEG_HDR_LEN + seg_len; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c 2025-10-22 13:53:23.319328627 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c 2025-10-22 13:53:56.547168987 -0400 -@@ -487,7 +487,9 @@ static int bnxt_ets_validate(struct bnxt - - if ((ets->tc_tx_bw[i] || ets->tc_tsa[i]) && i > bp->max_tc) - return -EINVAL; -+ } - -+ for (i = 0; i < max_tc; i++) { - switch (ets->tc_tsa[i]) { - case IEEE_8021QAZ_TSA_STRICT: - break; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c 2025-10-22 13:53:23.319328627 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c 2025-10-22 13:53:56.547168987 -0400 -@@ -244,7 +244,7 @@ bnxt_tc_parse_pedit(struct bnxt *bp, str - offset < offset_of_ip6_daddr + 16) { - actions->nat.src_xlate = false; - idx = (offset - offset_of_ip6_daddr) / 4; -- actions->nat.l3.ipv6.saddr.s6_addr32[idx] = htonl(val); -+ actions->nat.l3.ipv6.daddr.s6_addr32[idx] = htonl(val); - } else { - netdev_err(bp->dev, - "%s: IPv6_hdr: Invalid pedit field\n", -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c 2025-10-22 13:53:23.319328627 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c 2025-10-22 13:53:56.547168987 -0400 -@@ -231,10 +231,9 @@ void bnxt_ulp_stop(struct bnxt *bp) - return; - - mutex_lock(&edev->en_dev_lock); -- if (!bnxt_ulp_registered(edev)) { -- mutex_unlock(&edev->en_dev_lock); -- return; -- } -+ if (!bnxt_ulp_registered(edev) || -+ (edev->flags & BNXT_EN_FLAG_ULP_STOPPED)) -+ goto ulp_stop_exit; - - edev->flags |= BNXT_EN_FLAG_ULP_STOPPED; - if (aux_priv) { -@@ -250,6 +249,7 @@ void bnxt_ulp_stop(struct bnxt *bp) - adrv->suspend(adev, pm); - } - } -+ulp_stop_exit: - mutex_unlock(&edev->en_dev_lock); - } - -@@ -258,19 +258,13 @@ void bnxt_ulp_start(struct bnxt *bp, int - struct bnxt_aux_priv *aux_priv = bp->aux_priv; - struct bnxt_en_dev *edev = bp->edev; - -- if (!edev) -- return; -- -- edev->flags &= ~BNXT_EN_FLAG_ULP_STOPPED; -- -- if (err) -+ if (!edev || err) - return; - - mutex_lock(&edev->en_dev_lock); -- if (!bnxt_ulp_registered(edev)) { -- mutex_unlock(&edev->en_dev_lock); -- return; -- } -+ if (!bnxt_ulp_registered(edev) || -+ !(edev->flags & BNXT_EN_FLAG_ULP_STOPPED)) -+ goto ulp_start_exit; - - if (edev->ulp_tbl->msix_requested) - bnxt_fill_msix_vecs(bp, edev->msix_entries); -@@ -287,6 +281,8 @@ void bnxt_ulp_start(struct bnxt *bp, int - adrv->resume(adev); - } - } -+ulp_start_exit: -+ edev->flags &= ~BNXT_EN_FLAG_ULP_STOPPED; - mutex_unlock(&edev->en_dev_lock); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c 2025-10-22 13:53:23.319328627 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c 2025-10-22 13:53:56.547168987 -0400 -@@ -115,7 +115,7 @@ static void __bnxt_xmit_xdp_redirect(str - tx_buf->action = XDP_REDIRECT; - tx_buf->xdpf = xdpf; - dma_unmap_addr_set(tx_buf, mapping, mapping); -- dma_unmap_len_set(tx_buf, len, 0); -+ dma_unmap_len_set(tx_buf, len, len); - } - - void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int budget) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/broadcom/cnic.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/broadcom/cnic.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/broadcom/cnic.c 2025-10-22 13:53:23.319328627 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/broadcom/cnic.c 2025-10-22 13:53:56.551168968 -0400 -@@ -4230,8 +4230,7 @@ static void cnic_cm_stop_bnx2x_hw(struct - - cnic_bnx2x_delete_wait(dev, 0); - -- cancel_delayed_work(&cp->delete_task); -- flush_workqueue(cnic_wq); -+ cancel_delayed_work_sync(&cp->delete_task); - - if (atomic_read(&cp->iscsi_conn) != 0) - netdev_warn(dev->netdev, "%d iSCSI connections not destroyed\n", -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/broadcom/genet/bcmgenet.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/broadcom/genet/bcmgenet.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/broadcom/genet/bcmgenet.c 2025-10-22 13:53:23.319328627 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/broadcom/genet/bcmgenet.c 2025-10-22 13:53:56.551168968 -0400 -@@ -4092,6 +4092,12 @@ static int bcmgenet_probe(struct platfor - for (i = 0; i <= priv->hw_params->rx_queues; i++) - priv->rx_rings[i].rx_max_coalesced_frames = 1; - -+ /* Initialize u64 stats seq counter for 32bit machines */ -+ for (i = 0; i <= priv->hw_params->rx_queues; i++) -+ u64_stats_init(&priv->rx_rings[i].stats64.syncp); -+ for (i = 0; i <= priv->hw_params->tx_queues; i++) -+ u64_stats_init(&priv->tx_rings[i].stats64.syncp); -+ - /* libphy will determine the link state */ - netif_carrier_off(dev); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/cadence/macb_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/cadence/macb_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/cadence/macb_main.c 2025-10-22 13:53:23.319328627 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/cadence/macb_main.c 2025-10-22 13:53:56.551168968 -0400 -@@ -1223,12 +1223,13 @@ static int macb_tx_complete(struct macb_ - { - struct macb *bp = queue->bp; - u16 queue_index = queue - bp->queues; -+ unsigned long flags; - unsigned int tail; - unsigned int head; - int packets = 0; - u32 bytes = 0; - -- spin_lock(&queue->tx_ptr_lock); -+ spin_lock_irqsave(&queue->tx_ptr_lock, flags); - head = queue->tx_head; - for (tail = queue->tx_tail; tail != head && packets < budget; tail++) { - struct macb_tx_skb *tx_skb; -@@ -1291,7 +1292,7 @@ static int macb_tx_complete(struct macb_ - CIRC_CNT(queue->tx_head, queue->tx_tail, - bp->tx_ring_size) <= MACB_TX_WAKEUP_THRESH(bp)) - netif_wake_subqueue(bp->dev, queue_index); -- spin_unlock(&queue->tx_ptr_lock); -+ spin_unlock_irqrestore(&queue->tx_ptr_lock, flags); - - return packets; - } -@@ -1707,8 +1708,9 @@ static void macb_tx_restart(struct macb_ - { - struct macb *bp = queue->bp; - unsigned int head_idx, tbqp; -+ unsigned long flags; - -- spin_lock(&queue->tx_ptr_lock); -+ spin_lock_irqsave(&queue->tx_ptr_lock, flags); - - if (queue->tx_head == queue->tx_tail) - goto out_tx_ptr_unlock; -@@ -1720,19 +1722,20 @@ static void macb_tx_restart(struct macb_ - if (tbqp == head_idx) - goto out_tx_ptr_unlock; - -- spin_lock_irq(&bp->lock); -+ spin_lock(&bp->lock); - macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART)); -- spin_unlock_irq(&bp->lock); -+ spin_unlock(&bp->lock); - - out_tx_ptr_unlock: -- spin_unlock(&queue->tx_ptr_lock); -+ spin_unlock_irqrestore(&queue->tx_ptr_lock, flags); - } - - static bool macb_tx_complete_pending(struct macb_queue *queue) - { - bool retval = false; -+ unsigned long flags; - -- spin_lock(&queue->tx_ptr_lock); -+ spin_lock_irqsave(&queue->tx_ptr_lock, flags); - if (queue->tx_head != queue->tx_tail) { - /* Make hw descriptor updates visible to CPU */ - rmb(); -@@ -1740,7 +1743,7 @@ static bool macb_tx_complete_pending(str - if (macb_tx_desc(queue, queue->tx_tail)->ctrl & MACB_BIT(TX_USED)) - retval = true; - } -- spin_unlock(&queue->tx_ptr_lock); -+ spin_unlock_irqrestore(&queue->tx_ptr_lock, flags); - return retval; - } - -@@ -2308,6 +2311,7 @@ static netdev_tx_t macb_start_xmit(struc - struct macb_queue *queue = &bp->queues[queue_index]; - unsigned int desc_cnt, nr_frags, frag_size, f; - unsigned int hdrlen; -+ unsigned long flags; - bool is_lso; - netdev_tx_t ret = NETDEV_TX_OK; - -@@ -2368,7 +2372,7 @@ static netdev_tx_t macb_start_xmit(struc - desc_cnt += DIV_ROUND_UP(frag_size, bp->max_tx_length); - } - -- spin_lock_bh(&queue->tx_ptr_lock); -+ spin_lock_irqsave(&queue->tx_ptr_lock, flags); - - /* This is a hard error, log it. */ - if (CIRC_SPACE(queue->tx_head, queue->tx_tail, -@@ -2392,15 +2396,15 @@ static netdev_tx_t macb_start_xmit(struc - netdev_tx_sent_queue(netdev_get_tx_queue(bp->dev, queue_index), - skb->len); - -- spin_lock_irq(&bp->lock); -+ spin_lock(&bp->lock); - macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART)); -- spin_unlock_irq(&bp->lock); -+ spin_unlock(&bp->lock); - - if (CIRC_SPACE(queue->tx_head, queue->tx_tail, bp->tx_ring_size) < 1) - netif_stop_subqueue(dev, queue_index); - - unlock: -- spin_unlock_bh(&queue->tx_ptr_lock); -+ spin_unlock_irqrestore(&queue->tx_ptr_lock, flags); - - return ret; - } -@@ -3090,7 +3094,7 @@ static void gem_update_stats(struct macb - /* Add GEM_OCTTXH, GEM_OCTRXH */ - val = bp->macb_reg_readl(bp, offset + 4); - bp->ethtool_stats[i] += ((u64)val) << 32; -- *(p++) += ((u64)val) << 32; -+ *p += ((u64)val) << 32; - } - } - -@@ -5391,19 +5395,16 @@ static void macb_remove(struct platform_ - - if (dev) { - bp = netdev_priv(dev); -+ unregister_netdev(dev); - phy_exit(bp->sgmii_phy); - mdiobus_unregister(bp->mii_bus); - mdiobus_free(bp->mii_bus); - -- unregister_netdev(dev); -+ device_set_wakeup_enable(&bp->pdev->dev, 0); - cancel_work_sync(&bp->hresp_err_bh_work); - pm_runtime_disable(&pdev->dev); - pm_runtime_dont_use_autosuspend(&pdev->dev); -- if (!pm_runtime_suspended(&pdev->dev)) { -- macb_clks_disable(bp->pclk, bp->hclk, bp->tx_clk, -- bp->rx_clk, bp->tsu_clk); -- pm_runtime_set_suspended(&pdev->dev); -- } -+ pm_runtime_set_suspended(&pdev->dev); - phylink_destroy(bp->phylink); - free_netdev(dev); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/cavium/liquidio/request_manager.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/cavium/liquidio/request_manager.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/cavium/liquidio/request_manager.c 2025-10-22 13:53:23.319328627 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/cavium/liquidio/request_manager.c 2025-10-22 13:53:56.551168968 -0400 -@@ -126,7 +126,7 @@ int octeon_init_instr_queue(struct octeo - oct->io_qmask.iq |= BIT_ULL(iq_no); - - /* Set the 32B/64B mode for each input queue */ -- oct->io_qmask.iq64B |= ((conf->instr_type == 64) << iq_no); -+ oct->io_qmask.iq64B |= ((u64)(conf->instr_type == 64) << iq_no); - iq->iqcmd_64B = (conf->instr_type == 64); - - oct->fn_list.setup_iq_regs(oct, iq_no); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/cavium/thunder/nicvf_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/cavium/thunder/nicvf_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/cavium/thunder/nicvf_main.c 2025-10-22 13:53:23.319328627 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/cavium/thunder/nicvf_main.c 2025-10-22 13:53:56.551168968 -0400 -@@ -1578,7 +1578,6 @@ napi_del: - static int nicvf_change_mtu(struct net_device *netdev, int new_mtu) - { - struct nicvf *nic = netdev_priv(netdev); -- int orig_mtu = netdev->mtu; - - /* For now just support only the usual MTU sized frames, - * plus some headroom for VLAN, QinQ. -@@ -1589,15 +1588,10 @@ static int nicvf_change_mtu(struct net_d - return -EINVAL; - } - -- WRITE_ONCE(netdev->mtu, new_mtu); -- -- if (!netif_running(netdev)) -- return 0; -- -- if (nicvf_update_hw_max_frs(nic, new_mtu)) { -- netdev->mtu = orig_mtu; -+ if (netif_running(netdev) && nicvf_update_hw_max_frs(nic, new_mtu)) - return -EINVAL; -- } -+ -+ WRITE_ONCE(netdev->mtu, new_mtu); - - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/cavium/thunder/thunder_bgx.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/cavium/thunder/thunder_bgx.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/cavium/thunder/thunder_bgx.c 2025-10-22 13:53:23.319328627 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/cavium/thunder/thunder_bgx.c 2025-10-22 13:53:56.551168968 -0400 -@@ -1429,9 +1429,9 @@ static acpi_status bgx_acpi_match_id(acp - { - struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; - struct bgx *bgx = context; -- char bgx_sel[5]; -+ char bgx_sel[7]; - -- snprintf(bgx_sel, 5, "BGX%d", bgx->bgx_id); -+ snprintf(bgx_sel, sizeof(bgx_sel), "BGX%d", bgx->bgx_id); - if (ACPI_FAILURE(acpi_get_name(handle, ACPI_SINGLE_NAME, &string))) { - pr_warn("Invalid link device\n"); - return AE_OK; -@@ -1493,13 +1493,17 @@ static int bgx_init_of_phy(struct bgx *b - * this cortina phy, for which there is no driver - * support, ignore it. - */ -- if (phy_np && -- !of_device_is_compatible(phy_np, "cortina,cs4223-slice")) { -- /* Wait until the phy drivers are available */ -- pd = of_phy_find_device(phy_np); -- if (!pd) -- goto defer; -- bgx->lmac[lmac].phydev = pd; -+ if (phy_np) { -+ if (!of_device_is_compatible(phy_np, "cortina,cs4223-slice")) { -+ /* Wait until the phy drivers are available */ -+ pd = of_phy_find_device(phy_np); -+ if (!pd) { -+ of_node_put(phy_np); -+ goto defer; -+ } -+ bgx->lmac[lmac].phydev = pd; -+ } -+ of_node_put(phy_np); - } - - lmac++; -@@ -1515,11 +1519,11 @@ defer: - * for phy devices we may have already found. - */ - while (lmac) { -+ lmac--; - if (bgx->lmac[lmac].phydev) { - put_device(&bgx->lmac[lmac].phydev->mdio.dev); - bgx->lmac[lmac].phydev = NULL; - } -- lmac--; - } - of_node_put(node); - return -EPROBE_DEFER; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/cisco/enic/enic_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/cisco/enic/enic_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/cisco/enic/enic_main.c 2025-10-22 13:53:23.323328608 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/cisco/enic/enic_main.c 2025-10-22 13:53:56.551168968 -0400 -@@ -1864,10 +1864,10 @@ static int enic_change_mtu(struct net_de - if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic)) - return -EOPNOTSUPP; - -- if (netdev->mtu > enic->port_mtu) -+ if (new_mtu > enic->port_mtu) - netdev_warn(netdev, - "interface MTU (%d) set higher than port MTU (%d)\n", -- netdev->mtu, enic->port_mtu); -+ new_mtu, enic->port_mtu); - - return _enic_change_mtu(netdev, new_mtu); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/dlink/dl2k.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/dlink/dl2k.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/dlink/dl2k.c 2025-10-22 13:53:23.323328608 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/dlink/dl2k.c 2025-10-22 13:53:56.551168968 -0400 -@@ -1091,7 +1091,7 @@ get_stats (struct net_device *dev) - dev->stats.rx_bytes += dr32(OctetRcvOk); - dev->stats.tx_bytes += dr32(OctetXmtOk); - -- dev->stats.multicast = dr32(McstFramesRcvdOk); -+ dev->stats.multicast += dr32(McstFramesRcvdOk); - dev->stats.collisions += dr32(SingleColFrames) - + dr32(MultiColFrames); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/emulex/benet/be_cmds.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/emulex/benet/be_cmds.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/emulex/benet/be_cmds.c 2025-10-22 13:53:23.323328608 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/emulex/benet/be_cmds.c 2025-10-22 13:53:56.551168968 -0400 -@@ -3856,8 +3856,8 @@ int be_cmd_set_mac_list(struct be_adapte - status = be_mcc_notify_wait(adapter); - - err: -- dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma); - spin_unlock_bh(&adapter->mcc_lock); -+ dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma); - return status; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/emulex/benet/be_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/emulex/benet/be_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/emulex/benet/be_main.c 2025-10-22 13:53:23.323328608 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/emulex/benet/be_main.c 2025-10-22 13:53:56.551168968 -0400 -@@ -1465,10 +1465,10 @@ static void be_tx_timeout(struct net_dev - ntohs(tcphdr->source)); - dev_info(dev, "TCP dest port %d\n", - ntohs(tcphdr->dest)); -- dev_info(dev, "TCP sequence num %d\n", -- ntohs(tcphdr->seq)); -- dev_info(dev, "TCP ack_seq %d\n", -- ntohs(tcphdr->ack_seq)); -+ dev_info(dev, "TCP sequence num %u\n", -+ ntohl(tcphdr->seq)); -+ dev_info(dev, "TCP ack_seq %u\n", -+ ntohl(tcphdr->ack_seq)); - } else if (ip_hdr(skb)->protocol == - IPPROTO_UDP) { - udphdr = udp_hdr(skb); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/faraday/ftgmac100.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/faraday/ftgmac100.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/faraday/ftgmac100.c 2025-10-22 13:53:23.323328608 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/faraday/ftgmac100.c 2025-10-22 13:53:56.551168968 -0400 -@@ -1730,16 +1730,17 @@ err_register_mdiobus: - static void ftgmac100_phy_disconnect(struct net_device *netdev) - { - struct ftgmac100 *priv = netdev_priv(netdev); -+ struct phy_device *phydev = netdev->phydev; - -- if (!netdev->phydev) -+ if (!phydev) - return; - -- phy_disconnect(netdev->phydev); -+ phy_disconnect(phydev); - if (of_phy_is_fixed_link(priv->dev->of_node)) - of_phy_deregister_fixed_link(priv->dev->of_node); - - if (priv->use_ncsi) -- fixed_phy_unregister(netdev->phydev); -+ fixed_phy_unregister(phydev); - } - - static void ftgmac100_destroy_mdio(struct net_device *netdev) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/faraday/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/faraday/Kconfig ---- BPI-Router-Linux-kernel/drivers/net/ethernet/faraday/Kconfig 2025-10-22 13:53:23.323328608 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/faraday/Kconfig 2025-10-22 13:53:56.551168968 -0400 -@@ -31,6 +31,7 @@ config FTGMAC100 - depends on ARM || COMPILE_TEST - depends on !64BIT || BROKEN - select PHYLIB -+ select FIXED_PHY - select MDIO_ASPEED if MACH_ASPEED_G6 - select CRC32 - help -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c 2025-10-22 13:53:23.323328608 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c 2025-10-22 13:53:56.551168968 -0400 -@@ -28,7 +28,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -3150,7 +3149,6 @@ static const struct net_device_ops dpaa_ - .ndo_stop = dpaa_eth_stop, - .ndo_tx_timeout = dpaa_tx_timeout, - .ndo_get_stats64 = dpaa_get_stats64, -- .ndo_change_carrier = fixed_phy_change_carrier, - .ndo_set_mac_address = dpaa_set_mac_address, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_rx_mode = dpaa_set_rx_mode, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c 2025-10-22 13:53:23.323328608 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c 2025-10-22 13:53:56.551168968 -0400 -@@ -401,8 +401,10 @@ static int dpaa_get_ts_info(struct net_d - of_node_put(ptp_node); - } - -- if (ptp_dev) -+ if (ptp_dev) { - ptp = platform_get_drvdata(ptp_dev); -+ put_device(&ptp_dev->dev); -+ } - - if (ptp) - info->phc_index = ptp->phc_index; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c 2025-10-22 13:53:23.323328608 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c 2025-10-22 13:53:56.551168968 -0400 -@@ -3939,6 +3939,7 @@ static int dpaa2_eth_setup_rx_flow(struc - MEM_TYPE_PAGE_ORDER0, NULL); - if (err) { - dev_err(dev, "xdp_rxq_info_reg_mem_model failed\n"); -+ xdp_rxq_info_unreg(&fq->channel->xdp_rxq); - return err; - } - -@@ -4432,17 +4433,25 @@ static int dpaa2_eth_bind_dpni(struct dp - return -EINVAL; - } - if (err) -- return err; -+ goto out; - } - - err = dpni_get_qdid(priv->mc_io, 0, priv->mc_token, - DPNI_QUEUE_TX, &priv->tx_qdid); - if (err) { - dev_err(dev, "dpni_get_qdid() failed\n"); -- return err; -+ goto out; - } - - return 0; -+ -+out: -+ while (i--) { -+ if (priv->fq[i].type == DPAA2_RX_FQ && -+ xdp_rxq_info_is_reg(&priv->fq[i].channel->xdp_rxq)) -+ xdp_rxq_info_unreg(&priv->fq[i].channel->xdp_rxq); -+ } -+ return err; - } - - /* Allocate rings for storing incoming frame descriptors */ -@@ -4657,12 +4666,19 @@ static int dpaa2_eth_connect_mac(struct - return PTR_ERR(dpmac_dev); - } - -- if (IS_ERR(dpmac_dev) || dpmac_dev->dev.type != &fsl_mc_bus_dpmac_type) -+ if (IS_ERR(dpmac_dev)) - return 0; - -+ if (dpmac_dev->dev.type != &fsl_mc_bus_dpmac_type) { -+ err = 0; -+ goto out_put_device; -+ } -+ - mac = kzalloc(sizeof(struct dpaa2_mac), GFP_KERNEL); -- if (!mac) -- return -ENOMEM; -+ if (!mac) { -+ err = -ENOMEM; -+ goto out_put_device; -+ } - - mac->mc_dev = dpmac_dev; - mac->mc_io = priv->mc_io; -@@ -4696,6 +4712,8 @@ err_close_mac: - dpaa2_mac_close(mac); - err_free_mac: - kfree(mac); -+out_put_device: -+ put_device(&dpmac_dev->dev); - return err; - } - -@@ -4825,6 +4843,17 @@ static void dpaa2_eth_del_ch_napi(struct - } - } - -+static void dpaa2_eth_free_rx_xdp_rxq(struct dpaa2_eth_priv *priv) -+{ -+ int i; -+ -+ for (i = 0; i < priv->num_fqs; i++) { -+ if (priv->fq[i].type == DPAA2_RX_FQ && -+ xdp_rxq_info_is_reg(&priv->fq[i].channel->xdp_rxq)) -+ xdp_rxq_info_unreg(&priv->fq[i].channel->xdp_rxq); -+ } -+} -+ - static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev) - { - struct device *dev; -@@ -5028,6 +5057,7 @@ err_alloc_percpu_extras: - free_percpu(priv->percpu_stats); - err_alloc_percpu_stats: - dpaa2_eth_del_ch_napi(priv); -+ dpaa2_eth_free_rx_xdp_rxq(priv); - err_bind: - dpaa2_eth_free_dpbps(priv); - err_dpbp_setup: -@@ -5080,6 +5110,7 @@ static void dpaa2_eth_remove(struct fsl_ - free_percpu(priv->percpu_extras); - - dpaa2_eth_del_ch_napi(priv); -+ dpaa2_eth_free_rx_xdp_rxq(priv); - dpaa2_eth_free_dpbps(priv); - dpaa2_eth_free_dpio(priv); - dpaa2_eth_free_dpni(priv); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c 2025-10-22 13:53:23.323328608 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c 2025-10-22 13:53:56.551168968 -0400 -@@ -1448,12 +1448,19 @@ static int dpaa2_switch_port_connect_mac - if (PTR_ERR(dpmac_dev) == -EPROBE_DEFER) - return PTR_ERR(dpmac_dev); - -- if (IS_ERR(dpmac_dev) || dpmac_dev->dev.type != &fsl_mc_bus_dpmac_type) -+ if (IS_ERR(dpmac_dev)) - return 0; - -+ if (dpmac_dev->dev.type != &fsl_mc_bus_dpmac_type) { -+ err = 0; -+ goto out_put_device; -+ } -+ - mac = kzalloc(sizeof(*mac), GFP_KERNEL); -- if (!mac) -- return -ENOMEM; -+ if (!mac) { -+ err = -ENOMEM; -+ goto out_put_device; -+ } - - mac->mc_dev = dpmac_dev; - mac->mc_io = port_priv->ethsw_data->mc_io; -@@ -1483,6 +1490,8 @@ err_close_mac: - dpaa2_mac_close(mac); - err_free_mac: - kfree(mac); -+out_put_device: -+ put_device(&dpmac_dev->dev); - return err; - } - -@@ -2727,7 +2736,7 @@ static int dpaa2_switch_setup_dpbp(struc - dev_err(dev, "dpsw_ctrl_if_set_pools() failed\n"); - goto err_get_attr; - } -- ethsw->bpid = dpbp_attrs.id; -+ ethsw->bpid = dpbp_attrs.bpid; - - return 0; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c 2025-10-22 13:53:23.323328608 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c 2025-10-22 13:53:56.555168949 -0400 -@@ -142,7 +142,7 @@ static const struct { - static const struct { - int reg; - char name[ETH_GSTRING_LEN] __nonstring; --} enetc_port_counters[] = { -+} enetc_pm_counters[] = { - { ENETC_PM_REOCT(0), "MAC rx ethernet octets" }, - { ENETC_PM_RALN(0), "MAC rx alignment errors" }, - { ENETC_PM_RXPF(0), "MAC rx valid pause frames" }, -@@ -194,6 +194,12 @@ static const struct { - { ENETC_PM_TSCOL(0), "MAC tx single collisions" }, - { ENETC_PM_TLCOL(0), "MAC tx late collisions" }, - { ENETC_PM_TECOL(0), "MAC tx excessive collisions" }, -+}; -+ -+static const struct { -+ int reg; -+ char name[ETH_GSTRING_LEN] __nonstring; -+} enetc_port_counters[] = { - { ENETC_UFDMF, "SI MAC nomatch u-cast discards" }, - { ENETC_MFDMF, "SI MAC nomatch m-cast discards" }, - { ENETC_PBFDSIR, "SI MAC nomatch b-cast discards" }, -@@ -240,6 +246,7 @@ static int enetc_get_sset_count(struct n - return len; - - len += ARRAY_SIZE(enetc_port_counters); -+ len += ARRAY_SIZE(enetc_pm_counters); - - return len; - } -@@ -266,6 +273,9 @@ static void enetc_get_strings(struct net - for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++) - ethtool_cpy(&data, enetc_port_counters[i].name); - -+ for (i = 0; i < ARRAY_SIZE(enetc_pm_counters); i++) -+ ethtool_cpy(&data, enetc_pm_counters[i].name); -+ - break; - } - } -@@ -302,6 +312,9 @@ static void enetc_get_ethtool_stats(stru - - for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++) - data[o++] = enetc_port_rd(hw, enetc_port_counters[i].reg); -+ -+ for (i = 0; i < ARRAY_SIZE(enetc_pm_counters); i++) -+ data[o++] = enetc_port_rd64(hw, enetc_pm_counters[i].reg); - } - - static void enetc_pause_stats(struct enetc_hw *hw, int mac, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/freescale/enetc/enetc_hw.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/freescale/enetc/enetc_hw.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/freescale/enetc/enetc_hw.h 2025-10-22 13:53:23.323328608 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/freescale/enetc/enetc_hw.h 2025-10-22 13:53:56.555168949 -0400 -@@ -507,7 +507,7 @@ static inline u64 _enetc_rd_reg64(void _ - tmp = ioread32(reg + 4); - } while (high != tmp); - -- return le64_to_cpu((__le64)high << 32 | low); -+ return (u64)high << 32 | low; - } - #endif - -@@ -533,6 +533,7 @@ static inline u64 _enetc_rd_reg64_wa(voi - /* port register accessors - PF only */ - #define enetc_port_rd(hw, off) enetc_rd_reg((hw)->port + (off)) - #define enetc_port_wr(hw, off, val) enetc_wr_reg((hw)->port + (off), val) -+#define enetc_port_rd64(hw, off) _enetc_rd_reg64_wa((hw)->port + (off)) - #define enetc_port_rd_mdio(hw, off) _enetc_rd_mdio_reg_wa((hw)->port + (off)) - #define enetc_port_wr_mdio(hw, off, val) _enetc_wr_mdio_reg_wa(\ - (hw)->port + (off), val) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/freescale/enetc/enetc_pf.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/freescale/enetc/enetc_pf.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/freescale/enetc/enetc_pf.c 2025-10-22 13:53:23.323328608 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/freescale/enetc/enetc_pf.c 2025-10-22 13:53:56.555168949 -0400 -@@ -829,19 +829,29 @@ static int enetc_pf_register_with_ierb(s - { - struct platform_device *ierb_pdev; - struct device_node *ierb_node; -+ int ret; - - ierb_node = of_find_compatible_node(NULL, NULL, - "fsl,ls1028a-enetc-ierb"); -- if (!ierb_node || !of_device_is_available(ierb_node)) -+ if (!ierb_node) - return -ENODEV; - -+ if (!of_device_is_available(ierb_node)) { -+ of_node_put(ierb_node); -+ return -ENODEV; -+ } -+ - ierb_pdev = of_find_device_by_node(ierb_node); - of_node_put(ierb_node); - - if (!ierb_pdev) - return -EPROBE_DEFER; - -- return enetc_ierb_register_pf(ierb_pdev, pdev); -+ ret = enetc_ierb_register_pf(ierb_pdev, pdev); -+ -+ put_device(&ierb_pdev->dev); -+ -+ return ret; - } - - static const struct enetc_si_ops enetc_psi_ops = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/freescale/enetc/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/freescale/enetc/Kconfig ---- BPI-Router-Linux-kernel/drivers/net/ethernet/freescale/enetc/Kconfig 2025-10-22 13:53:23.323328608 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/freescale/enetc/Kconfig 2025-10-22 13:53:56.551168968 -0400 -@@ -1,6 +1,7 @@ - # SPDX-License-Identifier: GPL-2.0 - config FSL_ENETC_CORE - tristate -+ select NXP_NETC_LIB if NXP_NTMP - help - This module supports common functionality between the PF and VF - drivers for the NXP ENETC controller. -@@ -22,6 +23,9 @@ config NXP_NETC_LIB - Switch, such as NETC Table Management Protocol (NTMP) 2.0, common tc - flower and debugfs interfaces and so on. - -+config NXP_NTMP -+ bool -+ - config FSL_ENETC - tristate "ENETC PF driver" - depends on PCI_MSI -@@ -45,7 +49,7 @@ config NXP_ENETC4 - select FSL_ENETC_CORE - select FSL_ENETC_MDIO - select NXP_ENETC_PF_COMMON -- select NXP_NETC_LIB -+ select NXP_NTMP - select PHYLINK - select DIMLIB - help -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/freescale/fec_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/freescale/fec_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/freescale/fec_main.c 2025-10-22 13:53:23.323328608 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/freescale/fec_main.c 2025-10-22 13:53:56.555168949 -0400 -@@ -131,7 +131,7 @@ static const struct fec_devinfo fec_mvf6 - FEC_QUIRK_HAS_MDIO_C45, - }; - --static const struct fec_devinfo fec_imx6x_info = { -+static const struct fec_devinfo fec_imx6sx_info = { - .quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | - FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | - FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB | -@@ -196,7 +196,7 @@ static const struct of_device_id fec_dt_ - { .compatible = "fsl,imx28-fec", .data = &fec_imx28_info, }, - { .compatible = "fsl,imx6q-fec", .data = &fec_imx6q_info, }, - { .compatible = "fsl,mvf600-fec", .data = &fec_mvf600_info, }, -- { .compatible = "fsl,imx6sx-fec", .data = &fec_imx6x_info, }, -+ { .compatible = "fsl,imx6sx-fec", .data = &fec_imx6sx_info, }, - { .compatible = "fsl,imx6ul-fec", .data = &fec_imx6ul_info, }, - { .compatible = "fsl,imx8mq-fec", .data = &fec_imx8mq_info, }, - { .compatible = "fsl,imx8qm-fec", .data = &fec_imx8qm_info, }, -@@ -2358,7 +2358,8 @@ static void fec_enet_phy_reset_after_clk - */ - phy_dev = of_phy_find_device(fep->phy_node); - phy_reset_after_clk_enable(phy_dev); -- put_device(&phy_dev->mdio.dev); -+ if (phy_dev) -+ put_device(&phy_dev->mdio.dev); - } - } - -@@ -3124,27 +3125,25 @@ static int fec_enet_us_to_itr_clock(stru - static void fec_enet_itr_coal_set(struct net_device *ndev) - { - struct fec_enet_private *fep = netdev_priv(ndev); -- int rx_itr, tx_itr; -+ u32 rx_itr = 0, tx_itr = 0; -+ int rx_ictt, tx_ictt; - -- /* Must be greater than zero to avoid unpredictable behavior */ -- if (!fep->rx_time_itr || !fep->rx_pkts_itr || -- !fep->tx_time_itr || !fep->tx_pkts_itr) -- return; -- -- /* Select enet system clock as Interrupt Coalescing -- * timer Clock Source -- */ -- rx_itr = FEC_ITR_CLK_SEL; -- tx_itr = FEC_ITR_CLK_SEL; -+ rx_ictt = fec_enet_us_to_itr_clock(ndev, fep->rx_time_itr); -+ tx_ictt = fec_enet_us_to_itr_clock(ndev, fep->tx_time_itr); - -- /* set ICFT and ICTT */ -- rx_itr |= FEC_ITR_ICFT(fep->rx_pkts_itr); -- rx_itr |= FEC_ITR_ICTT(fec_enet_us_to_itr_clock(ndev, fep->rx_time_itr)); -- tx_itr |= FEC_ITR_ICFT(fep->tx_pkts_itr); -- tx_itr |= FEC_ITR_ICTT(fec_enet_us_to_itr_clock(ndev, fep->tx_time_itr)); -- -- rx_itr |= FEC_ITR_EN; -- tx_itr |= FEC_ITR_EN; -+ if (rx_ictt > 0 && fep->rx_pkts_itr > 1) { -+ /* Enable with enet system clock as Interrupt Coalescing timer Clock Source */ -+ rx_itr = FEC_ITR_EN | FEC_ITR_CLK_SEL; -+ rx_itr |= FEC_ITR_ICFT(fep->rx_pkts_itr); -+ rx_itr |= FEC_ITR_ICTT(rx_ictt); -+ } -+ -+ if (tx_ictt > 0 && fep->tx_pkts_itr > 1) { -+ /* Enable with enet system clock as Interrupt Coalescing timer Clock Source */ -+ tx_itr = FEC_ITR_EN | FEC_ITR_CLK_SEL; -+ tx_itr |= FEC_ITR_ICFT(fep->tx_pkts_itr); -+ tx_itr |= FEC_ITR_ICTT(tx_ictt); -+ } - - writel(tx_itr, fep->hwp + FEC_TXIC0); - writel(rx_itr, fep->hwp + FEC_RXIC0); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/freescale/gianfar_ethtool.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/freescale/gianfar_ethtool.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/freescale/gianfar_ethtool.c 2025-10-22 13:53:23.323328608 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/freescale/gianfar_ethtool.c 2025-10-22 13:53:56.555168949 -0400 -@@ -1466,8 +1466,10 @@ static int gfar_get_ts_info(struct net_d - if (ptp_node) { - ptp_dev = of_find_device_by_node(ptp_node); - of_node_put(ptp_node); -- if (ptp_dev) -+ if (ptp_dev) { - ptp = platform_get_drvdata(ptp_dev); -+ put_device(&ptp_dev->dev); -+ } - } - - if (ptp) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/google/gve/gve_adminq.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/google/gve/gve_adminq.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/google/gve/gve_adminq.c 2025-10-22 13:53:23.327328588 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/google/gve/gve_adminq.c 2025-10-22 13:53:56.555168949 -0400 -@@ -564,6 +564,7 @@ static int gve_adminq_issue_cmd(struct g - break; - default: - dev_err(&priv->pdev->dev, "unknown AQ command opcode %d\n", opcode); -+ return -EINVAL; - } - - return 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/google/gve/gve_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/google/gve/gve_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/google/gve/gve_main.c 2025-10-22 13:53:23.327328588 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/google/gve/gve_main.c 2025-10-22 13:53:56.555168949 -0400 -@@ -1917,49 +1917,56 @@ static void gve_turnup_and_check_status( - gve_handle_link_status(priv, GVE_DEVICE_STATUS_LINK_STATUS_MASK & status); - } - --static void gve_tx_timeout(struct net_device *dev, unsigned int txqueue) -+static struct gve_notify_block *gve_get_tx_notify_block(struct gve_priv *priv, -+ unsigned int txqueue) - { -- struct gve_notify_block *block; -- struct gve_tx_ring *tx = NULL; -- struct gve_priv *priv; -- u32 last_nic_done; -- u32 current_time; - u32 ntfy_idx; - -- netdev_info(dev, "Timeout on tx queue, %d", txqueue); -- priv = netdev_priv(dev); - if (txqueue > priv->tx_cfg.num_queues) -- goto reset; -+ return NULL; - - ntfy_idx = gve_tx_idx_to_ntfy(priv, txqueue); - if (ntfy_idx >= priv->num_ntfy_blks) -- goto reset; -+ return NULL; -+ -+ return &priv->ntfy_blocks[ntfy_idx]; -+} -+ -+static bool gve_tx_timeout_try_q_kick(struct gve_priv *priv, -+ unsigned int txqueue) -+{ -+ struct gve_notify_block *block; -+ u32 current_time; -+ -+ block = gve_get_tx_notify_block(priv, txqueue); - -- block = &priv->ntfy_blocks[ntfy_idx]; -- tx = block->tx; -+ if (!block) -+ return false; - - current_time = jiffies_to_msecs(jiffies); -- if (tx->last_kick_msec + MIN_TX_TIMEOUT_GAP > current_time) -- goto reset; -+ if (block->tx->last_kick_msec + MIN_TX_TIMEOUT_GAP > current_time) -+ return false; - -- /* Check to see if there are missed completions, which will allow us to -- * kick the queue. -- */ -- last_nic_done = gve_tx_load_event_counter(priv, tx); -- if (last_nic_done - tx->done) { -- netdev_info(dev, "Kicking queue %d", txqueue); -- iowrite32be(GVE_IRQ_MASK, gve_irq_doorbell(priv, block)); -- napi_schedule(&block->napi); -- tx->last_kick_msec = current_time; -- goto out; -- } // Else reset. -- --reset: -- gve_schedule_reset(priv); -- --out: -- if (tx) -- tx->queue_timeout++; -+ netdev_info(priv->dev, "Kicking queue %d", txqueue); -+ napi_schedule(&block->napi); -+ block->tx->last_kick_msec = current_time; -+ return true; -+} -+ -+static void gve_tx_timeout(struct net_device *dev, unsigned int txqueue) -+{ -+ struct gve_notify_block *block; -+ struct gve_priv *priv; -+ -+ netdev_info(dev, "Timeout on tx queue, %d", txqueue); -+ priv = netdev_priv(dev); -+ -+ if (!gve_tx_timeout_try_q_kick(priv, txqueue)) -+ gve_schedule_reset(priv); -+ -+ block = gve_get_tx_notify_block(priv, txqueue); -+ if (block) -+ block->tx->queue_timeout++; - priv->tx_timeo_cnt++; - } - -@@ -2719,6 +2726,8 @@ static void gve_shutdown(struct pci_dev - struct gve_priv *priv = netdev_priv(netdev); - bool was_up = netif_running(priv->dev); - -+ netif_device_detach(netdev); -+ - rtnl_lock(); - netdev_lock(netdev); - if (was_up && gve_close(priv->dev)) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/hisilicon/hibmcge/hbg_err.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/hisilicon/hibmcge/hbg_err.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/hisilicon/hibmcge/hbg_err.c 2025-10-22 13:53:23.327328588 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/hisilicon/hibmcge/hbg_err.c 2025-10-22 13:53:56.555168949 -0400 -@@ -53,9 +53,11 @@ static int hbg_reset_prepare(struct hbg_ - { - int ret; - -- ASSERT_RTNL(); -+ if (test_and_set_bit(HBG_NIC_STATE_RESETTING, &priv->state)) -+ return -EBUSY; - - if (netif_running(priv->netdev)) { -+ clear_bit(HBG_NIC_STATE_RESETTING, &priv->state); - dev_warn(&priv->pdev->dev, - "failed to reset because port is up\n"); - return -EBUSY; -@@ -64,7 +66,6 @@ static int hbg_reset_prepare(struct hbg_ - netif_device_detach(priv->netdev); - - priv->reset_type = type; -- set_bit(HBG_NIC_STATE_RESETTING, &priv->state); - clear_bit(HBG_NIC_STATE_RESET_FAIL, &priv->state); - ret = hbg_hw_event_notify(priv, HBG_HW_EVENT_RESET); - if (ret) { -@@ -83,28 +84,25 @@ static int hbg_reset_done(struct hbg_pri - type != priv->reset_type) - return 0; - -- ASSERT_RTNL(); -- -- clear_bit(HBG_NIC_STATE_RESETTING, &priv->state); - ret = hbg_rebuild(priv); - if (ret) { - set_bit(HBG_NIC_STATE_RESET_FAIL, &priv->state); -+ clear_bit(HBG_NIC_STATE_RESETTING, &priv->state); - dev_err(&priv->pdev->dev, "failed to rebuild after reset\n"); - return ret; - } - - netif_device_attach(priv->netdev); -+ clear_bit(HBG_NIC_STATE_RESETTING, &priv->state); - - dev_info(&priv->pdev->dev, "reset done\n"); - return ret; - } - --/* must be protected by rtnl lock */ - int hbg_reset(struct hbg_priv *priv) - { - int ret; - -- ASSERT_RTNL(); - ret = hbg_reset_prepare(priv, HBG_RESET_TYPE_FUNCTION); - if (ret) - return ret; -@@ -169,7 +167,6 @@ static void hbg_pci_err_reset_prepare(st - struct net_device *netdev = pci_get_drvdata(pdev); - struct hbg_priv *priv = netdev_priv(netdev); - -- rtnl_lock(); - hbg_reset_prepare(priv, HBG_RESET_TYPE_FLR); - } - -@@ -179,7 +176,6 @@ static void hbg_pci_err_reset_done(struc - struct hbg_priv *priv = netdev_priv(netdev); - - hbg_reset_done(priv, HBG_RESET_TYPE_FLR); -- rtnl_unlock(); - } - - static const struct pci_error_handlers hbg_pci_err_handler = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c 2025-10-22 13:53:23.327328588 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c 2025-10-22 13:53:56.555168949 -0400 -@@ -12,6 +12,8 @@ - - #define HBG_HW_EVENT_WAIT_TIMEOUT_US (2 * 1000 * 1000) - #define HBG_HW_EVENT_WAIT_INTERVAL_US (10 * 1000) -+#define HBG_MAC_LINK_WAIT_TIMEOUT_US (500 * 1000) -+#define HBG_MAC_LINK_WAIT_INTERVAL_US (5 * 1000) - /* little endian or big endian. - * ctrl means packet description, data means skb packet data - */ -@@ -213,6 +215,9 @@ void hbg_hw_fill_buffer(struct hbg_priv - - void hbg_hw_adjust_link(struct hbg_priv *priv, u32 speed, u32 duplex) - { -+ u32 link_status; -+ int ret; -+ - hbg_hw_mac_enable(priv, HBG_STATUS_DISABLE); - - hbg_reg_write_field(priv, HBG_REG_PORT_MODE_ADDR, -@@ -224,8 +229,14 @@ void hbg_hw_adjust_link(struct hbg_priv - - hbg_hw_mac_enable(priv, HBG_STATUS_ENABLE); - -- if (!hbg_reg_read_field(priv, HBG_REG_AN_NEG_STATE_ADDR, -- HBG_REG_AN_NEG_STATE_NP_LINK_OK_B)) -+ /* wait MAC link up */ -+ ret = readl_poll_timeout(priv->io_base + HBG_REG_AN_NEG_STATE_ADDR, -+ link_status, -+ FIELD_GET(HBG_REG_AN_NEG_STATE_NP_LINK_OK_B, -+ link_status), -+ HBG_MAC_LINK_WAIT_INTERVAL_US, -+ HBG_MAC_LINK_WAIT_TIMEOUT_US); -+ if (ret) - hbg_np_link_fail_task_schedule(priv); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.h 2025-10-22 13:53:23.327328588 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.h 2025-10-22 13:53:56.555168949 -0400 -@@ -29,7 +29,12 @@ static inline bool hbg_fifo_is_full(stru - - static inline u32 hbg_get_queue_used_num(struct hbg_ring *ring) - { -- return (ring->ntu + ring->len - ring->ntc) % ring->len; -+ u32 len = READ_ONCE(ring->len); -+ -+ if (!len) -+ return 0; -+ -+ return (READ_ONCE(ring->ntu) + len - READ_ONCE(ring->ntc)) % len; - } - - netdev_tx_t hbg_net_start_xmit(struct sk_buff *skb, struct net_device *netdev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c 2025-10-22 13:53:23.327328588 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c 2025-10-22 13:53:56.555168949 -0400 -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1039,6 +1040,8 @@ static bool hns3_can_use_tx_sgl(struct h - static void hns3_init_tx_spare_buffer(struct hns3_enet_ring *ring) - { - u32 alloc_size = ring->tqp->handle->kinfo.tx_spare_buf_size; -+ struct net_device *netdev = ring_to_netdev(ring); -+ struct hns3_nic_priv *priv = netdev_priv(netdev); - struct hns3_tx_spare *tx_spare; - struct page *page; - dma_addr_t dma; -@@ -1080,6 +1083,7 @@ static void hns3_init_tx_spare_buffer(st - tx_spare->buf = page_address(page); - tx_spare->len = PAGE_SIZE << order; - ring->tx_spare = tx_spare; -+ ring->tx_copybreak = priv->tx_copybreak; - return; - - dma_mapping_error: -@@ -4874,6 +4878,30 @@ static void hns3_nic_dealloc_vector_data - devm_kfree(&pdev->dev, priv->tqp_vector); - } - -+static void hns3_update_tx_spare_buf_config(struct hns3_nic_priv *priv) -+{ -+#define HNS3_MIN_SPARE_BUF_SIZE (2 * 1024 * 1024) -+#define HNS3_MAX_PACKET_SIZE (64 * 1024) -+ -+ struct iommu_domain *domain = iommu_get_domain_for_dev(priv->dev); -+ struct hnae3_ae_dev *ae_dev = hns3_get_ae_dev(priv->ae_handle); -+ struct hnae3_handle *handle = priv->ae_handle; -+ -+ if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V3) -+ return; -+ -+ if (!(domain && iommu_is_dma_domain(domain))) -+ return; -+ -+ priv->min_tx_copybreak = HNS3_MAX_PACKET_SIZE; -+ priv->min_tx_spare_buf_size = HNS3_MIN_SPARE_BUF_SIZE; -+ -+ if (priv->tx_copybreak < priv->min_tx_copybreak) -+ priv->tx_copybreak = priv->min_tx_copybreak; -+ if (handle->kinfo.tx_spare_buf_size < priv->min_tx_spare_buf_size) -+ handle->kinfo.tx_spare_buf_size = priv->min_tx_spare_buf_size; -+} -+ - static void hns3_ring_get_cfg(struct hnae3_queue *q, struct hns3_nic_priv *priv, - unsigned int ring_type) - { -@@ -5107,6 +5135,7 @@ int hns3_init_all_ring(struct hns3_nic_p - int i, j; - int ret; - -+ hns3_update_tx_spare_buf_config(priv); - for (i = 0; i < ring_num; i++) { - ret = hns3_alloc_ring_memory(&priv->ring[i]); - if (ret) { -@@ -5311,6 +5340,8 @@ static int hns3_client_init(struct hnae3 - priv->ae_handle = handle; - priv->tx_timeout_count = 0; - priv->max_non_tso_bd_num = ae_dev->dev_specs.max_non_tso_bd_num; -+ priv->min_tx_copybreak = 0; -+ priv->min_tx_spare_buf_size = 0; - set_bit(HNS3_NIC_STATE_DOWN, &priv->state); - - handle->msg_enable = netif_msg_init(debug, DEFAULT_MSG_LEVEL); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h 2025-10-22 13:53:23.327328588 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h 2025-10-22 13:53:56.555168949 -0400 -@@ -596,6 +596,8 @@ struct hns3_nic_priv { - struct hns3_enet_coalesce rx_coal; - u32 tx_copybreak; - u32 rx_copybreak; -+ u32 min_tx_copybreak; -+ u32 min_tx_spare_buf_size; - }; - - union l3_hdr_info { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c 2025-10-22 13:53:23.327328588 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c 2025-10-22 13:53:56.555168949 -0400 -@@ -9576,33 +9576,36 @@ static bool hclge_need_enable_vport_vlan - return false; - } - --int hclge_enable_vport_vlan_filter(struct hclge_vport *vport, bool request_en) -+static int __hclge_enable_vport_vlan_filter(struct hclge_vport *vport, -+ bool request_en) - { -- struct hclge_dev *hdev = vport->back; - bool need_en; - int ret; - -- mutex_lock(&hdev->vport_lock); -- -- vport->req_vlan_fltr_en = request_en; -- - need_en = hclge_need_enable_vport_vlan_filter(vport); -- if (need_en == vport->cur_vlan_fltr_en) { -- mutex_unlock(&hdev->vport_lock); -+ if (need_en == vport->cur_vlan_fltr_en) - return 0; -- } - - ret = hclge_set_vport_vlan_filter(vport, need_en); -- if (ret) { -- mutex_unlock(&hdev->vport_lock); -+ if (ret) - return ret; -- } - - vport->cur_vlan_fltr_en = need_en; - -+ return 0; -+} -+ -+int hclge_enable_vport_vlan_filter(struct hclge_vport *vport, bool request_en) -+{ -+ struct hclge_dev *hdev = vport->back; -+ int ret; -+ -+ mutex_lock(&hdev->vport_lock); -+ vport->req_vlan_fltr_en = request_en; -+ ret = __hclge_enable_vport_vlan_filter(vport, request_en); - mutex_unlock(&hdev->vport_lock); - -- return 0; -+ return ret; - } - - static int hclge_enable_vlan_filter(struct hnae3_handle *handle, bool enable) -@@ -10623,16 +10626,19 @@ static void hclge_sync_vlan_fltr_state(s - &vport->state)) - continue; - -- ret = hclge_enable_vport_vlan_filter(vport, -- vport->req_vlan_fltr_en); -+ mutex_lock(&hdev->vport_lock); -+ ret = __hclge_enable_vport_vlan_filter(vport, -+ vport->req_vlan_fltr_en); - if (ret) { - dev_err(&hdev->pdev->dev, - "failed to sync vlan filter state for vport%u, ret = %d\n", - vport->vport_id, ret); - set_bit(HCLGE_VPORT_STATE_VLAN_FLTR_CHANGE, - &vport->state); -+ mutex_unlock(&hdev->vport_lock); - return; - } -+ mutex_unlock(&hdev->vport_lock); - } - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c 2025-10-22 13:53:23.327328588 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c 2025-10-22 13:53:56.555168949 -0400 -@@ -497,14 +497,14 @@ int hclge_ptp_init(struct hclge_dev *hde - if (ret) { - dev_err(&hdev->pdev->dev, - "failed to init freq, ret = %d\n", ret); -- goto out; -+ goto out_clear_int; - } - - ret = hclge_ptp_set_ts_mode(hdev, &hdev->ptp->ts_cfg); - if (ret) { - dev_err(&hdev->pdev->dev, - "failed to init ts mode, ret = %d\n", ret); -- goto out; -+ goto out_clear_int; - } - - ktime_get_real_ts64(&ts); -@@ -512,7 +512,7 @@ int hclge_ptp_init(struct hclge_dev *hde - if (ret) { - dev_err(&hdev->pdev->dev, - "failed to init ts time, ret = %d\n", ret); -- goto out; -+ goto out_clear_int; - } - - set_bit(HCLGE_STATE_PTP_EN, &hdev->state); -@@ -520,6 +520,9 @@ int hclge_ptp_init(struct hclge_dev *hde - - return 0; - -+out_clear_int: -+ clear_bit(HCLGE_PTP_FLAG_EN, &hdev->ptp->flags); -+ hclge_ptp_int_en(hdev, false); - out: - hclge_ptp_destroy_clock(hdev); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c 2025-10-22 13:53:23.327328588 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c 2025-10-22 13:53:56.555168949 -0400 -@@ -3094,11 +3094,7 @@ static void hclgevf_uninit_ae_dev(struct - - static u32 hclgevf_get_max_channels(struct hclgevf_dev *hdev) - { -- struct hnae3_handle *nic = &hdev->nic; -- struct hnae3_knic_private_info *kinfo = &nic->kinfo; -- -- return min_t(u32, hdev->rss_size_max, -- hdev->num_tqps / kinfo->tc_info.num_tc); -+ return min(hdev->rss_size_max, hdev->num_tqps); - } - - /** -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/ibm/ibmvnic.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/ibm/ibmvnic.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/ibm/ibmvnic.h 2025-10-22 13:53:23.327328588 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/ibm/ibmvnic.h 2025-10-22 13:53:56.555168949 -0400 -@@ -211,7 +211,6 @@ struct ibmvnic_statistics { - u8 reserved[72]; - } __packed __aligned(8); - --#define NUM_TX_STATS 3 - struct ibmvnic_tx_queue_stats { - u64 batched_packets; - u64 direct_packets; -@@ -219,13 +218,18 @@ struct ibmvnic_tx_queue_stats { - u64 dropped_packets; - }; - --#define NUM_RX_STATS 3 -+#define NUM_TX_STATS \ -+ (sizeof(struct ibmvnic_tx_queue_stats) / sizeof(u64)) -+ - struct ibmvnic_rx_queue_stats { - u64 packets; - u64 bytes; - u64 interrupts; - }; - -+#define NUM_RX_STATS \ -+ (sizeof(struct ibmvnic_rx_queue_stats) / sizeof(u64)) -+ - struct ibmvnic_acl_buffer { - __be32 len; - __be32 version; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/e1000/e1000_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/e1000/e1000_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/e1000/e1000_main.c 2025-10-22 13:53:23.327328588 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/e1000/e1000_main.c 2025-10-22 13:53:56.559168929 -0400 -@@ -477,10 +477,6 @@ static void e1000_down_and_stop(struct e - - cancel_delayed_work_sync(&adapter->phy_info_task); - cancel_delayed_work_sync(&adapter->fifo_stall_task); -- -- /* Only kill reset task if adapter is not resetting */ -- if (!test_bit(__E1000_RESETTING, &adapter->flags)) -- cancel_work_sync(&adapter->reset_task); - } - - void e1000_down(struct e1000_adapter *adapter) -@@ -1266,6 +1262,10 @@ static void e1000_remove(struct pci_dev - - unregister_netdev(netdev); - -+ /* Only kill reset task if adapter is not resetting */ -+ if (!test_bit(__E1000_RESETTING, &adapter->flags)) -+ cancel_work_sync(&adapter->reset_task); -+ - e1000_phy_hw_reset(hw); - - kfree(adapter->tx_ring); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/e1000e/defines.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/e1000e/defines.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/e1000e/defines.h 2025-10-22 13:53:23.327328588 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/e1000e/defines.h 2025-10-22 13:53:56.559168929 -0400 -@@ -638,6 +638,9 @@ - /* For checksumming, the sum of all words in the NVM should equal 0xBABA. */ - #define NVM_SUM 0xBABA - -+/* Uninitialized ("empty") checksum word value */ -+#define NVM_CHECKSUM_UNINITIALIZED 0xFFFF -+ - /* PBA (printed board assembly) number words */ - #define NVM_PBA_OFFSET_0 8 - #define NVM_PBA_OFFSET_1 9 -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/e1000e/ethtool.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/e1000e/ethtool.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/e1000e/ethtool.c 2025-10-22 13:53:23.331328570 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/e1000e/ethtool.c 2025-10-22 13:53:56.559168929 -0400 -@@ -549,12 +549,12 @@ static int e1000_set_eeprom(struct net_d - { - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; -+ size_t total_len, max_len; - u16 *eeprom_buff; -- void *ptr; -- int max_len; -+ int ret_val = 0; - int first_word; - int last_word; -- int ret_val = 0; -+ void *ptr; - u16 i; - - if (eeprom->len == 0) -@@ -569,6 +569,10 @@ static int e1000_set_eeprom(struct net_d - - max_len = hw->nvm.word_size * 2; - -+ if (check_add_overflow(eeprom->offset, eeprom->len, &total_len) || -+ total_len > max_len) -+ return -EFBIG; -+ - first_word = eeprom->offset >> 1; - last_word = (eeprom->offset + eeprom->len - 1) >> 1; - eeprom_buff = kmalloc(max_len, GFP_KERNEL); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/e1000e/ich8lan.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/e1000e/ich8lan.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/e1000e/ich8lan.c 2025-10-22 13:53:23.331328570 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/e1000e/ich8lan.c 2025-10-22 13:53:56.559168929 -0400 -@@ -4274,6 +4274,8 @@ static s32 e1000_validate_nvm_checksum_i - ret_val = e1000e_update_nvm_checksum(hw); - if (ret_val) - return ret_val; -+ } else if (hw->mac.type == e1000_pch_tgp) { -+ return 0; - } - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/e1000e/netdev.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/e1000e/netdev.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/e1000e/netdev.c 2025-10-22 13:53:23.331328570 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/e1000e/netdev.c 2025-10-22 13:53:56.559168929 -0400 -@@ -3534,9 +3534,6 @@ s32 e1000e_get_base_timinca(struct e1000 - case e1000_pch_cnp: - case e1000_pch_tgp: - case e1000_pch_adp: -- case e1000_pch_mtp: -- case e1000_pch_lnp: -- case e1000_pch_ptp: - case e1000_pch_nvp: - if (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI) { - /* Stable 24MHz frequency */ -@@ -3552,6 +3549,17 @@ s32 e1000e_get_base_timinca(struct e1000 - adapter->cc.shift = shift; - } - break; -+ case e1000_pch_mtp: -+ case e1000_pch_lnp: -+ case e1000_pch_ptp: -+ /* System firmware can misreport this value, so set it to a -+ * stable 38400KHz frequency. -+ */ -+ incperiod = INCPERIOD_38400KHZ; -+ incvalue = INCVALUE_38400KHZ; -+ shift = INCVALUE_SHIFT_38400KHZ; -+ adapter->cc.shift = shift; -+ break; - case e1000_82574: - case e1000_82583: - /* Stable 25MHz frequency */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/e1000e/nvm.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/e1000e/nvm.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/e1000e/nvm.c 2025-10-22 13:53:23.331328570 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/e1000e/nvm.c 2025-10-22 13:53:56.559168929 -0400 -@@ -558,6 +558,12 @@ s32 e1000e_validate_nvm_checksum_generic - checksum += nvm_data; - } - -+ if (hw->mac.type == e1000_pch_tgp && -+ nvm_data == NVM_CHECKSUM_UNINITIALIZED) { -+ e_dbg("Uninitialized NVM Checksum on TGP platform - ignoring\n"); -+ return 0; -+ } -+ - if (checksum != (u16)NVM_SUM) { - e_dbg("NVM Checksum Invalid\n"); - return -E1000_ERR_NVM; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/e1000e/ptp.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/e1000e/ptp.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/e1000e/ptp.c 2025-10-22 13:53:23.331328570 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/e1000e/ptp.c 2025-10-22 13:53:56.559168929 -0400 -@@ -295,15 +295,17 @@ void e1000e_ptp_init(struct e1000_adapte - case e1000_pch_cnp: - case e1000_pch_tgp: - case e1000_pch_adp: -- case e1000_pch_mtp: -- case e1000_pch_lnp: -- case e1000_pch_ptp: - case e1000_pch_nvp: - if (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI) - adapter->ptp_clock_info.max_adj = MAX_PPB_24MHZ; - else - adapter->ptp_clock_info.max_adj = MAX_PPB_38400KHZ; - break; -+ case e1000_pch_mtp: -+ case e1000_pch_lnp: -+ case e1000_pch_ptp: -+ adapter->ptp_clock_info.max_adj = MAX_PPB_38400KHZ; -+ break; - case e1000_82574: - case e1000_82583: - adapter->ptp_clock_info.max_adj = MAX_PPB_25MHZ; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/fm10k/fm10k.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/fm10k/fm10k.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/fm10k/fm10k.h 2025-10-22 13:53:23.331328570 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/fm10k/fm10k.h 2025-10-22 13:53:56.559168929 -0400 -@@ -189,13 +189,14 @@ struct fm10k_q_vector { - struct fm10k_ring_container rx, tx; - - struct napi_struct napi; -+ struct rcu_head rcu; /* to avoid race with update stats on free */ -+ - cpumask_t affinity_mask; - char name[IFNAMSIZ + 9]; - - #ifdef CONFIG_DEBUG_FS - struct dentry *dbg_q_vector; - #endif /* CONFIG_DEBUG_FS */ -- struct rcu_head rcu; /* to avoid race with update stats on free */ - - /* for dynamic allocation of rings associated with this q_vector */ - struct fm10k_ring ring[] ____cacheline_internodealigned_in_smp; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/i40e/i40e_client.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/i40e/i40e_client.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/i40e/i40e_client.c 2025-10-22 13:53:23.331328570 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/i40e/i40e_client.c 2025-10-22 13:53:56.559168929 -0400 -@@ -359,8 +359,8 @@ static void i40e_client_add_instance(str - if (i40e_client_get_params(vsi, &cdev->lan_info.params)) - goto free_cdev; - -- mac = list_first_entry(&cdev->lan_info.netdev->dev_addrs.list, -- struct netdev_hw_addr, list); -+ mac = list_first_entry_or_null(&cdev->lan_info.netdev->dev_addrs.list, -+ struct netdev_hw_addr, list); - if (mac) - ether_addr_copy(cdev->lan_info.lanmac, mac->addr); - else -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/i40e/i40e_debugfs.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/i40e/i40e_debugfs.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/i40e/i40e_debugfs.c 2025-10-22 13:53:23.331328570 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/i40e/i40e_debugfs.c 2025-10-22 13:53:56.559168929 -0400 -@@ -40,48 +40,6 @@ static struct i40e_vsi *i40e_dbg_find_vs - * setup, adding or removing filters, or other things. Many of - * these will be useful for some forms of unit testing. - **************************************************************/ --static char i40e_dbg_command_buf[256] = ""; -- --/** -- * i40e_dbg_command_read - read for command datum -- * @filp: the opened file -- * @buffer: where to write the data for the user to read -- * @count: the size of the user's buffer -- * @ppos: file position offset -- **/ --static ssize_t i40e_dbg_command_read(struct file *filp, char __user *buffer, -- size_t count, loff_t *ppos) --{ -- struct i40e_pf *pf = filp->private_data; -- struct i40e_vsi *main_vsi; -- int bytes_not_copied; -- int buf_size = 256; -- char *buf; -- int len; -- -- /* don't allow partial reads */ -- if (*ppos != 0) -- return 0; -- if (count < buf_size) -- return -ENOSPC; -- -- buf = kzalloc(buf_size, GFP_KERNEL); -- if (!buf) -- return -ENOSPC; -- -- main_vsi = i40e_pf_get_main_vsi(pf); -- len = snprintf(buf, buf_size, "%s: %s\n", main_vsi->netdev->name, -- i40e_dbg_command_buf); -- -- bytes_not_copied = copy_to_user(buffer, buf, len); -- kfree(buf); -- -- if (bytes_not_copied) -- return -EFAULT; -- -- *ppos = len; -- return len; --} - - static char *i40e_filter_state_string[] = { - "INVALID", -@@ -1621,7 +1579,6 @@ command_write_done: - static const struct file_operations i40e_dbg_command_fops = { - .owner = THIS_MODULE, - .open = simple_open, -- .read = i40e_dbg_command_read, - .write = i40e_dbg_command_write, - }; - -@@ -1630,48 +1587,6 @@ static const struct file_operations i40e - * The netdev_ops entry in debugfs is for giving the driver commands - * to be executed from the netdev operations. - **************************************************************/ --static char i40e_dbg_netdev_ops_buf[256] = ""; -- --/** -- * i40e_dbg_netdev_ops_read - read for netdev_ops datum -- * @filp: the opened file -- * @buffer: where to write the data for the user to read -- * @count: the size of the user's buffer -- * @ppos: file position offset -- **/ --static ssize_t i40e_dbg_netdev_ops_read(struct file *filp, char __user *buffer, -- size_t count, loff_t *ppos) --{ -- struct i40e_pf *pf = filp->private_data; -- struct i40e_vsi *main_vsi; -- int bytes_not_copied; -- int buf_size = 256; -- char *buf; -- int len; -- -- /* don't allow partal reads */ -- if (*ppos != 0) -- return 0; -- if (count < buf_size) -- return -ENOSPC; -- -- buf = kzalloc(buf_size, GFP_KERNEL); -- if (!buf) -- return -ENOSPC; -- -- main_vsi = i40e_pf_get_main_vsi(pf); -- len = snprintf(buf, buf_size, "%s: %s\n", main_vsi->netdev->name, -- i40e_dbg_netdev_ops_buf); -- -- bytes_not_copied = copy_to_user(buffer, buf, len); -- kfree(buf); -- -- if (bytes_not_copied) -- return -EFAULT; -- -- *ppos = len; -- return len; --} - - /** - * i40e_dbg_netdev_ops_write - write into netdev_ops datum -@@ -1685,35 +1600,36 @@ static ssize_t i40e_dbg_netdev_ops_write - size_t count, loff_t *ppos) - { - struct i40e_pf *pf = filp->private_data; -+ char *cmd_buf, *buf_tmp; - int bytes_not_copied; - struct i40e_vsi *vsi; -- char *buf_tmp; - int vsi_seid; - int i, cnt; - - /* don't allow partial writes */ - if (*ppos != 0) - return 0; -- if (count >= sizeof(i40e_dbg_netdev_ops_buf)) -- return -ENOSPC; - -- memset(i40e_dbg_netdev_ops_buf, 0, sizeof(i40e_dbg_netdev_ops_buf)); -- bytes_not_copied = copy_from_user(i40e_dbg_netdev_ops_buf, -- buffer, count); -- if (bytes_not_copied) -+ cmd_buf = kzalloc(count + 1, GFP_KERNEL); -+ if (!cmd_buf) -+ return count; -+ bytes_not_copied = copy_from_user(cmd_buf, buffer, count); -+ if (bytes_not_copied) { -+ kfree(cmd_buf); - return -EFAULT; -- i40e_dbg_netdev_ops_buf[count] = '\0'; -+ } -+ cmd_buf[count] = '\0'; - -- buf_tmp = strchr(i40e_dbg_netdev_ops_buf, '\n'); -+ buf_tmp = strchr(cmd_buf, '\n'); - if (buf_tmp) { - *buf_tmp = '\0'; -- count = buf_tmp - i40e_dbg_netdev_ops_buf + 1; -+ count = buf_tmp - cmd_buf + 1; - } - -- if (strncmp(i40e_dbg_netdev_ops_buf, "change_mtu", 10) == 0) { -+ if (strncmp(cmd_buf, "change_mtu", 10) == 0) { - int mtu; - -- cnt = sscanf(&i40e_dbg_netdev_ops_buf[11], "%i %i", -+ cnt = sscanf(&cmd_buf[11], "%i %i", - &vsi_seid, &mtu); - if (cnt != 2) { - dev_info(&pf->pdev->dev, "change_mtu \n"); -@@ -1735,8 +1651,8 @@ static ssize_t i40e_dbg_netdev_ops_write - dev_info(&pf->pdev->dev, "Could not acquire RTNL - please try again\n"); - } - -- } else if (strncmp(i40e_dbg_netdev_ops_buf, "set_rx_mode", 11) == 0) { -- cnt = sscanf(&i40e_dbg_netdev_ops_buf[11], "%i", &vsi_seid); -+ } else if (strncmp(cmd_buf, "set_rx_mode", 11) == 0) { -+ cnt = sscanf(&cmd_buf[11], "%i", &vsi_seid); - if (cnt != 1) { - dev_info(&pf->pdev->dev, "set_rx_mode \n"); - goto netdev_ops_write_done; -@@ -1756,8 +1672,8 @@ static ssize_t i40e_dbg_netdev_ops_write - dev_info(&pf->pdev->dev, "Could not acquire RTNL - please try again\n"); - } - -- } else if (strncmp(i40e_dbg_netdev_ops_buf, "napi", 4) == 0) { -- cnt = sscanf(&i40e_dbg_netdev_ops_buf[4], "%i", &vsi_seid); -+ } else if (strncmp(cmd_buf, "napi", 4) == 0) { -+ cnt = sscanf(&cmd_buf[4], "%i", &vsi_seid); - if (cnt != 1) { - dev_info(&pf->pdev->dev, "napi \n"); - goto netdev_ops_write_done; -@@ -1775,21 +1691,20 @@ static ssize_t i40e_dbg_netdev_ops_write - dev_info(&pf->pdev->dev, "napi called\n"); - } - } else { -- dev_info(&pf->pdev->dev, "unknown command '%s'\n", -- i40e_dbg_netdev_ops_buf); -+ dev_info(&pf->pdev->dev, "unknown command '%s'\n", cmd_buf); - dev_info(&pf->pdev->dev, "available commands\n"); - dev_info(&pf->pdev->dev, " change_mtu \n"); - dev_info(&pf->pdev->dev, " set_rx_mode \n"); - dev_info(&pf->pdev->dev, " napi \n"); - } - netdev_ops_write_done: -+ kfree(cmd_buf); - return count; - } - - static const struct file_operations i40e_dbg_netdev_ops_fops = { - .owner = THIS_MODULE, - .open = simple_open, -- .read = i40e_dbg_netdev_ops_read, - .write = i40e_dbg_netdev_ops_write, - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/i40e/i40e.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/i40e/i40e.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/i40e/i40e.h 2025-10-22 13:53:23.331328570 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/i40e/i40e.h 2025-10-22 13:53:56.559168929 -0400 -@@ -945,6 +945,7 @@ struct i40e_q_vector { - u16 reg_idx; /* register index of the interrupt */ - - struct napi_struct napi; -+ struct rcu_head rcu; /* to avoid race with update stats on free */ - - struct i40e_ring_container rx; - struct i40e_ring_container tx; -@@ -955,7 +956,6 @@ struct i40e_q_vector { - cpumask_t affinity_mask; - struct irq_affinity_notify affinity_notify; - -- struct rcu_head rcu; /* to avoid race with update stats on free */ - char name[I40E_INT_NAME_STR_LEN]; - bool arm_wb_state; - bool in_busy_poll; -@@ -1277,7 +1277,8 @@ struct i40e_mac_filter *i40e_add_mac_fil - const u8 *macaddr); - int i40e_del_mac_filter(struct i40e_vsi *vsi, const u8 *macaddr); - bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi); --int i40e_count_filters(struct i40e_vsi *vsi); -+int i40e_count_all_filters(struct i40e_vsi *vsi); -+int i40e_count_active_filters(struct i40e_vsi *vsi); - struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr); - void i40e_vlan_stripping_enable(struct i40e_vsi *vsi); - static inline bool i40e_is_sw_dcb(struct i40e_pf *pf) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/i40e/i40e_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/i40e/i40e_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/i40e/i40e_main.c 2025-10-22 13:53:23.331328570 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/i40e/i40e_main.c 2025-10-22 13:53:56.559168929 -0400 -@@ -1241,12 +1241,30 @@ void i40e_update_stats(struct i40e_vsi * - } - - /** -- * i40e_count_filters - counts VSI mac filters -+ * i40e_count_all_filters - counts VSI MAC filters - * @vsi: the VSI to be searched - * -- * Returns count of mac filters -- **/ --int i40e_count_filters(struct i40e_vsi *vsi) -+ * Return: count of MAC filters in any state. -+ */ -+int i40e_count_all_filters(struct i40e_vsi *vsi) -+{ -+ struct i40e_mac_filter *f; -+ struct hlist_node *h; -+ int bkt, cnt = 0; -+ -+ hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) -+ cnt++; -+ -+ return cnt; -+} -+ -+/** -+ * i40e_count_active_filters - counts VSI MAC filters -+ * @vsi: the VSI to be searched -+ * -+ * Return: count of active MAC filters. -+ */ -+int i40e_count_active_filters(struct i40e_vsi *vsi) - { - struct i40e_mac_filter *f; - struct hlist_node *h; -@@ -4182,7 +4200,7 @@ free_queue_irqs: - irq_num = pf->msix_entries[base + vector].vector; - irq_set_affinity_notifier(irq_num, NULL); - irq_update_affinity_hint(irq_num, NULL); -- free_irq(irq_num, &vsi->q_vectors[vector]); -+ free_irq(irq_num, vsi->q_vectors[vector]); - } - return err; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/i40e/i40e_txrx.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/i40e/i40e_txrx.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/i40e/i40e_txrx.c 2025-10-22 13:53:23.331328570 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/i40e/i40e_txrx.c 2025-10-22 13:53:56.559168929 -0400 -@@ -947,9 +947,6 @@ static bool i40e_clean_tx_irq(struct i40 - if (!eop_desc) - break; - -- /* prevent any other reads prior to eop_desc */ -- smp_rmb(); -- - i40e_trace(clean_tx_irq, tx_ring, tx_desc, tx_buf); - /* we have caught up to head, no work left to do */ - if (tx_head == tx_desc) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c 2025-10-22 13:53:56.559168929 -0400 -@@ -448,7 +448,7 @@ static void i40e_config_irq_link_list(st - (qtype << I40E_QINT_RQCTL_NEXTQ_TYPE_SHIFT) | - (pf_queue_id << I40E_QINT_RQCTL_NEXTQ_INDX_SHIFT) | - BIT(I40E_QINT_RQCTL_CAUSE_ENA_SHIFT) | -- (itr_idx << I40E_QINT_RQCTL_ITR_INDX_SHIFT); -+ FIELD_PREP(I40E_QINT_RQCTL_ITR_INDX_MASK, itr_idx); - wr32(hw, reg_idx, reg); - } - -@@ -653,6 +653,13 @@ static int i40e_config_vsi_tx_queue(stru - - /* only set the required fields */ - tx_ctx.base = info->dma_ring_addr / 128; -+ -+ /* ring_len has to be multiple of 8 */ -+ if (!IS_ALIGNED(info->ring_len, 8) || -+ info->ring_len > I40E_MAX_NUM_DESCRIPTORS_XL710) { -+ ret = -EINVAL; -+ goto error_context; -+ } - tx_ctx.qlen = info->ring_len; - tx_ctx.rdylist = le16_to_cpu(vsi->info.qs_handle[0]); - tx_ctx.rdylist_act = 0; -@@ -716,6 +723,13 @@ static int i40e_config_vsi_rx_queue(stru - - /* only set the required fields */ - rx_ctx.base = info->dma_ring_addr / 128; -+ -+ /* ring_len has to be multiple of 32 */ -+ if (!IS_ALIGNED(info->ring_len, 32) || -+ info->ring_len > I40E_MAX_NUM_DESCRIPTORS_XL710) { -+ ret = -EINVAL; -+ goto error_param; -+ } - rx_ctx.qlen = info->ring_len; - - if (info->splithdr_enabled) { -@@ -1453,6 +1467,7 @@ static void i40e_trigger_vf_reset(struct - * functions that may still be running at this point. - */ - clear_bit(I40E_VF_STATE_INIT, &vf->vf_states); -+ clear_bit(I40E_VF_STATE_RESOURCES_LOADED, &vf->vf_states); - - /* In the case of a VFLR, the HW has already reset the VF and we - * just need to clean up, so don't hit the VFRTRIG register. -@@ -1546,8 +1561,8 @@ static void i40e_cleanup_reset_vf(struct - * @vf: pointer to the VF structure - * @flr: VFLR was issued or not - * -- * Returns true if the VF is in reset, resets successfully, or resets -- * are disabled and false otherwise. -+ * Return: True if reset was performed successfully or if resets are disabled. -+ * False if reset is already in progress. - **/ - bool i40e_reset_vf(struct i40e_vf *vf, bool flr) - { -@@ -1566,7 +1581,7 @@ bool i40e_reset_vf(struct i40e_vf *vf, b - - /* If VF is being reset already we don't need to continue. */ - if (test_and_set_bit(I40E_VF_STATE_RESETTING, &vf->vf_states)) -- return true; -+ return false; - - i40e_trigger_vf_reset(vf, flr); - -@@ -2119,7 +2134,10 @@ static int i40e_vc_get_vf_resources_msg( - size_t len = 0; - int ret; - -- if (!i40e_sync_vf_state(vf, I40E_VF_STATE_INIT)) { -+ i40e_sync_vf_state(vf, I40E_VF_STATE_INIT); -+ -+ if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states) || -+ test_bit(I40E_VF_STATE_RESOURCES_LOADED, &vf->vf_states)) { - aq_ret = -EINVAL; - goto err; - } -@@ -2222,6 +2240,7 @@ static int i40e_vc_get_vf_resources_msg( - vf->default_lan_addr.addr); - } - set_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states); -+ set_bit(I40E_VF_STATE_RESOURCES_LOADED, &vf->vf_states); - - err: - /* send the response back to the VF */ -@@ -2384,7 +2403,7 @@ static int i40e_vc_config_queues_msg(str - } - - if (vf->adq_enabled) { -- if (idx >= ARRAY_SIZE(vf->ch)) { -+ if (idx >= vf->num_tc) { - aq_ret = -ENODEV; - goto error_param; - } -@@ -2405,7 +2424,7 @@ static int i40e_vc_config_queues_msg(str - * to its appropriate VSIs based on TC mapping - */ - if (vf->adq_enabled) { -- if (idx >= ARRAY_SIZE(vf->ch)) { -+ if (idx >= vf->num_tc) { - aq_ret = -ENODEV; - goto error_param; - } -@@ -2455,8 +2474,10 @@ static int i40e_validate_queue_map(struc - u16 vsi_queue_id, queue_id; - - for_each_set_bit(vsi_queue_id, &queuemap, I40E_MAX_VSI_QP) { -- if (vf->adq_enabled) { -- vsi_id = vf->ch[vsi_queue_id / I40E_MAX_VF_VSI].vsi_id; -+ u16 idx = vsi_queue_id / I40E_MAX_VF_VSI; -+ -+ if (vf->adq_enabled && idx < vf->num_tc) { -+ vsi_id = vf->ch[idx].vsi_id; - queue_id = (vsi_queue_id % I40E_DEFAULT_QUEUES_PER_VF); - } else { - queue_id = vsi_queue_id; -@@ -2844,24 +2865,6 @@ error_param: - (u8 *)&stats, sizeof(stats)); - } - --/** -- * i40e_can_vf_change_mac -- * @vf: pointer to the VF info -- * -- * Return true if the VF is allowed to change its MAC filters, false otherwise -- */ --static bool i40e_can_vf_change_mac(struct i40e_vf *vf) --{ -- /* If the VF MAC address has been set administratively (via the -- * ndo_set_vf_mac command), then deny permission to the VF to -- * add/delete unicast MAC addresses, unless the VF is trusted -- */ -- if (vf->pf_set_mac && !vf->trusted) -- return false; -- -- return true; --} -- - #define I40E_MAX_MACVLAN_PER_HW 3072 - #define I40E_MAX_MACVLAN_PER_PF(num_ports) (I40E_MAX_MACVLAN_PER_HW / \ - (num_ports)) -@@ -2900,8 +2903,10 @@ static inline int i40e_check_vf_permissi - struct i40e_pf *pf = vf->pf; - struct i40e_vsi *vsi = pf->vsi[vf->lan_vsi_idx]; - struct i40e_hw *hw = &pf->hw; -- int mac2add_cnt = 0; -- int i; -+ int i, mac_add_max, mac_add_cnt = 0; -+ bool vf_trusted; -+ -+ vf_trusted = test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps); - - for (i = 0; i < al->num_elements; i++) { - struct i40e_mac_filter *f; -@@ -2921,9 +2926,8 @@ static inline int i40e_check_vf_permissi - * The VF may request to set the MAC address filter already - * assigned to it so do not return an error in that case. - */ -- if (!i40e_can_vf_change_mac(vf) && -- !is_multicast_ether_addr(addr) && -- !ether_addr_equal(addr, vf->default_lan_addr.addr)) { -+ if (!vf_trusted && !is_multicast_ether_addr(addr) && -+ vf->pf_set_mac && !ether_addr_equal(addr, vf->default_lan_addr.addr)) { - dev_err(&pf->pdev->dev, - "VF attempting to override administratively set MAC address, bring down and up the VF interface to resume normal operation\n"); - return -EPERM; -@@ -2932,29 +2936,33 @@ static inline int i40e_check_vf_permissi - /*count filters that really will be added*/ - f = i40e_find_mac(vsi, addr); - if (!f) -- ++mac2add_cnt; -+ ++mac_add_cnt; - } - - /* If this VF is not privileged, then we can't add more than a limited -- * number of addresses. Check to make sure that the additions do not -- * push us over the limit. -- */ -- if (!test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps)) { -- if ((i40e_count_filters(vsi) + mac2add_cnt) > -- I40E_VC_MAX_MAC_ADDR_PER_VF) { -- dev_err(&pf->pdev->dev, -- "Cannot add more MAC addresses, VF is not trusted, switch the VF to trusted to add more functionality\n"); -- return -EPERM; -- } -- /* If this VF is trusted, it can use more resources than untrusted. -+ * number of addresses. -+ * -+ * If this VF is trusted, it can use more resources than untrusted. - * However to ensure that every trusted VF has appropriate number of - * resources, divide whole pool of resources per port and then across - * all VFs. - */ -- } else { -- if ((i40e_count_filters(vsi) + mac2add_cnt) > -- I40E_VC_MAX_MACVLAN_PER_TRUSTED_VF(pf->num_alloc_vfs, -- hw->num_ports)) { -+ if (!vf_trusted) -+ mac_add_max = I40E_VC_MAX_MAC_ADDR_PER_VF; -+ else -+ mac_add_max = I40E_VC_MAX_MACVLAN_PER_TRUSTED_VF(pf->num_alloc_vfs, hw->num_ports); -+ -+ /* VF can replace all its filters in one step, in this case mac_add_max -+ * will be added as active and another mac_add_max will be in -+ * a to-be-removed state. Account for that. -+ */ -+ if ((i40e_count_active_filters(vsi) + mac_add_cnt) > mac_add_max || -+ (i40e_count_all_filters(vsi) + mac_add_cnt) > 2 * mac_add_max) { -+ if (!vf_trusted) { -+ dev_err(&pf->pdev->dev, -+ "Cannot add more MAC addresses, VF is not trusted, switch the VF to trusted to add more functionality\n"); -+ return -EPERM; -+ } else { - dev_err(&pf->pdev->dev, - "Cannot add more MAC addresses, trusted VF exhausted it's resources\n"); - return -EPERM; -@@ -3137,10 +3145,10 @@ static int i40e_vc_del_mac_addr_msg(stru - const u8 *addr = al->list[i].addr; - - /* Allow to delete VF primary MAC only if it was not set -- * administratively by PF or if VF is trusted. -+ * administratively by PF. - */ - if (ether_addr_equal(addr, vf->default_lan_addr.addr)) { -- if (i40e_can_vf_change_mac(vf)) -+ if (!vf->pf_set_mac) - was_unimac_deleted = true; - else - continue; -@@ -3589,7 +3597,7 @@ static int i40e_validate_cloud_filter(st - - /* action_meta is TC number here to which the filter is applied */ - if (!tc_filter->action_meta || -- tc_filter->action_meta > vf->num_tc) { -+ tc_filter->action_meta >= vf->num_tc) { - dev_info(&pf->pdev->dev, "VF %d: Invalid TC number %u\n", - vf->vf_id, tc_filter->action_meta); - goto err; -@@ -3887,6 +3895,8 @@ err: - aq_ret); - } - -+#define I40E_MAX_VF_CLOUD_FILTER 0xFF00 -+ - /** - * i40e_vc_add_cloud_filter - * @vf: pointer to the VF info -@@ -3926,6 +3936,14 @@ static int i40e_vc_add_cloud_filter(stru - goto err_out; - } - -+ if (vf->num_cloud_filters >= I40E_MAX_VF_CLOUD_FILTER) { -+ dev_warn(&pf->pdev->dev, -+ "VF %d: Max number of filters reached, can't apply cloud filter\n", -+ vf->vf_id); -+ aq_ret = -ENOSPC; -+ goto err_out; -+ } -+ - cfilter = kzalloc(sizeof(*cfilter), GFP_KERNEL); - if (!cfilter) { - aq_ret = -ENOMEM; -@@ -4328,7 +4346,10 @@ int i40e_vc_process_vflr_event(struct i4 - reg = rd32(hw, I40E_GLGEN_VFLRSTAT(reg_idx)); - if (reg & BIT(bit_idx)) - /* i40e_reset_vf will clear the bit in GLGEN_VFLRSTAT */ -- i40e_reset_vf(vf, true); -+ if (!i40e_reset_vf(vf, true)) { -+ /* At least one VF did not finish resetting, retry next time */ -+ set_bit(__I40E_VFLR_EVENT_PENDING, pf->state); -+ } - } - - return 0; -@@ -5003,7 +5024,7 @@ int i40e_get_vf_stats(struct net_device - vf_stats->broadcast = stats->rx_broadcast; - vf_stats->multicast = stats->rx_multicast; - vf_stats->rx_dropped = stats->rx_discards + stats->rx_discards_other; -- vf_stats->tx_dropped = stats->tx_discards; -+ vf_stats->tx_dropped = stats->tx_errors; - - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h 2025-10-22 13:53:56.559168929 -0400 -@@ -41,7 +41,8 @@ enum i40e_vf_states { - I40E_VF_STATE_MC_PROMISC, - I40E_VF_STATE_UC_PROMISC, - I40E_VF_STATE_PRE_ENABLE, -- I40E_VF_STATE_RESETTING -+ I40E_VF_STATE_RESETTING, -+ I40E_VF_STATE_RESOURCES_LOADED, - }; - - /* VF capabilities */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/iavf/iavf_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/iavf/iavf_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/iavf/iavf_main.c 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/iavf/iavf_main.c 2025-10-22 13:53:56.563168910 -0400 -@@ -3209,6 +3209,17 @@ static void iavf_reset_task(struct work_ - } - - continue_reset: -+ /* If we are still early in the state machine, just restart. */ -+ if (adapter->state <= __IAVF_INIT_FAILED) { -+ iavf_shutdown_adminq(hw); -+ iavf_change_state(adapter, __IAVF_STARTUP); -+ iavf_startup(adapter); -+ queue_delayed_work(adapter->wq, &adapter->watchdog_task, -+ msecs_to_jiffies(30)); -+ netdev_unlock(netdev); -+ return; -+ } -+ - /* We don't use netif_running() because it may be true prior to - * ndo_open() returning, so we can't assume it means all our open - * tasks have finished, since we're not holding the rtnl_lock here. -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c 2025-10-22 13:53:56.563168910 -0400 -@@ -79,6 +79,23 @@ iavf_poll_virtchnl_msg(struct iavf_hw *h - return iavf_status_to_errno(status); - received_op = - (enum virtchnl_ops)le32_to_cpu(event->desc.cookie_high); -+ -+ if (received_op == VIRTCHNL_OP_EVENT) { -+ struct iavf_adapter *adapter = hw->back; -+ struct virtchnl_pf_event *vpe = -+ (struct virtchnl_pf_event *)event->msg_buf; -+ -+ if (vpe->event != VIRTCHNL_EVENT_RESET_IMPENDING) -+ continue; -+ -+ dev_info(&adapter->pdev->dev, "Reset indication received from the PF\n"); -+ if (!(adapter->flags & IAVF_FLAG_RESET_PENDING)) -+ iavf_schedule_reset(adapter, -+ IAVF_FLAG_RESET_PENDING); -+ -+ return -EIO; -+ } -+ - if (op_to_poll == received_op) - break; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_adapter.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_adapter.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_adapter.c 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_adapter.c 2025-10-22 13:53:56.563168910 -0400 -@@ -13,16 +13,45 @@ - static DEFINE_XARRAY(ice_adapters); - static DEFINE_MUTEX(ice_adapters_mutex); - --static unsigned long ice_adapter_index(u64 dsn) -+#define ICE_ADAPTER_FIXED_INDEX BIT_ULL(63) -+ -+#define ICE_ADAPTER_INDEX_E825C \ -+ (ICE_DEV_ID_E825C_BACKPLANE | ICE_ADAPTER_FIXED_INDEX) -+ -+static u64 ice_adapter_index(struct pci_dev *pdev) - { -+ switch (pdev->device) { -+ case ICE_DEV_ID_E825C_BACKPLANE: -+ case ICE_DEV_ID_E825C_QSFP: -+ case ICE_DEV_ID_E825C_SFP: -+ case ICE_DEV_ID_E825C_SGMII: -+ /* E825C devices have multiple NACs which are connected to the -+ * same clock source, and which must share the same -+ * ice_adapter structure. We can't use the serial number since -+ * each NAC has its own NVM generated with its own unique -+ * Device Serial Number. Instead, rely on the embedded nature -+ * of the E825C devices, and use a fixed index. This relies on -+ * the fact that all E825C physical functions in a given -+ * system are part of the same overall device. -+ */ -+ return ICE_ADAPTER_INDEX_E825C; -+ default: -+ return pci_get_dsn(pdev) & ~ICE_ADAPTER_FIXED_INDEX; -+ } -+} -+ -+static unsigned long ice_adapter_xa_index(struct pci_dev *pdev) -+{ -+ u64 index = ice_adapter_index(pdev); -+ - #if BITS_PER_LONG == 64 -- return dsn; -+ return index; - #else -- return (u32)dsn ^ (u32)(dsn >> 32); -+ return (u32)index ^ (u32)(index >> 32); - #endif - } - --static struct ice_adapter *ice_adapter_new(u64 dsn) -+static struct ice_adapter *ice_adapter_new(struct pci_dev *pdev) - { - struct ice_adapter *adapter; - -@@ -30,7 +59,7 @@ static struct ice_adapter *ice_adapter_n - if (!adapter) - return NULL; - -- adapter->device_serial_number = dsn; -+ adapter->index = ice_adapter_index(pdev); - spin_lock_init(&adapter->ptp_gltsyn_time_lock); - refcount_set(&adapter->refcount, 1); - -@@ -63,24 +92,23 @@ static void ice_adapter_free(struct ice_ - */ - struct ice_adapter *ice_adapter_get(struct pci_dev *pdev) - { -- u64 dsn = pci_get_dsn(pdev); - struct ice_adapter *adapter; - unsigned long index; - int err; - -- index = ice_adapter_index(dsn); -+ index = ice_adapter_xa_index(pdev); - scoped_guard(mutex, &ice_adapters_mutex) { - err = xa_insert(&ice_adapters, index, NULL, GFP_KERNEL); - if (err == -EBUSY) { - adapter = xa_load(&ice_adapters, index); - refcount_inc(&adapter->refcount); -- WARN_ON_ONCE(adapter->device_serial_number != dsn); -+ WARN_ON_ONCE(adapter->index != ice_adapter_index(pdev)); - return adapter; - } - if (err) - return ERR_PTR(err); - -- adapter = ice_adapter_new(dsn); -+ adapter = ice_adapter_new(pdev); - if (!adapter) - return ERR_PTR(-ENOMEM); - xa_store(&ice_adapters, index, adapter, GFP_KERNEL); -@@ -99,11 +127,10 @@ struct ice_adapter *ice_adapter_get(stru - */ - void ice_adapter_put(struct pci_dev *pdev) - { -- u64 dsn = pci_get_dsn(pdev); - struct ice_adapter *adapter; - unsigned long index; - -- index = ice_adapter_index(dsn); -+ index = ice_adapter_xa_index(pdev); - scoped_guard(mutex, &ice_adapters_mutex) { - adapter = xa_load(&ice_adapters, index); - if (WARN_ON(!adapter)) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_adapter.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_adapter.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_adapter.h 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_adapter.h 2025-10-22 13:53:56.563168910 -0400 -@@ -32,7 +32,7 @@ struct ice_port_list { - * @refcount: Reference count. struct ice_pf objects hold the references. - * @ctrl_pf: Control PF of the adapter - * @ports: Ports list -- * @device_serial_number: DSN cached for collision detection on 32bit systems -+ * @index: 64-bit index cached for collision detection on 32bit systems - */ - struct ice_adapter { - refcount_t refcount; -@@ -41,7 +41,7 @@ struct ice_adapter { - - struct ice_pf *ctrl_pf; - struct ice_port_list ports; -- u64 device_serial_number; -+ u64 index; - }; - - struct ice_adapter *ice_adapter_get(struct pci_dev *pdev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_arfs.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_arfs.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_arfs.c 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_arfs.c 2025-10-22 13:53:56.563168910 -0400 -@@ -378,6 +378,50 @@ ice_arfs_is_perfect_flow_set(struct ice_ - } - - /** -+ * ice_arfs_cmp - Check if aRFS filter matches this flow. -+ * @fltr_info: filter info of the saved ARFS entry. -+ * @fk: flow dissector keys. -+ * @n_proto: One of htons(ETH_P_IP) or htons(ETH_P_IPV6). -+ * @ip_proto: One of IPPROTO_TCP or IPPROTO_UDP. -+ * -+ * Since this function assumes limited values for n_proto and ip_proto, it -+ * is meant to be called only from ice_rx_flow_steer(). -+ * -+ * Return: -+ * * true - fltr_info refers to the same flow as fk. -+ * * false - fltr_info and fk refer to different flows. -+ */ -+static bool -+ice_arfs_cmp(const struct ice_fdir_fltr *fltr_info, const struct flow_keys *fk, -+ __be16 n_proto, u8 ip_proto) -+{ -+ /* Determine if the filter is for IPv4 or IPv6 based on flow_type, -+ * which is one of ICE_FLTR_PTYPE_NONF_IPV{4,6}_{TCP,UDP}. -+ */ -+ bool is_v4 = fltr_info->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP || -+ fltr_info->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP; -+ -+ /* Following checks are arranged in the quickest and most discriminative -+ * fields first for early failure. -+ */ -+ if (is_v4) -+ return n_proto == htons(ETH_P_IP) && -+ fltr_info->ip.v4.src_port == fk->ports.src && -+ fltr_info->ip.v4.dst_port == fk->ports.dst && -+ fltr_info->ip.v4.src_ip == fk->addrs.v4addrs.src && -+ fltr_info->ip.v4.dst_ip == fk->addrs.v4addrs.dst && -+ fltr_info->ip.v4.proto == ip_proto; -+ -+ return fltr_info->ip.v6.src_port == fk->ports.src && -+ fltr_info->ip.v6.dst_port == fk->ports.dst && -+ fltr_info->ip.v6.proto == ip_proto && -+ !memcmp(&fltr_info->ip.v6.src_ip, &fk->addrs.v6addrs.src, -+ sizeof(struct in6_addr)) && -+ !memcmp(&fltr_info->ip.v6.dst_ip, &fk->addrs.v6addrs.dst, -+ sizeof(struct in6_addr)); -+} -+ -+/** - * ice_rx_flow_steer - steer the Rx flow to where application is being run - * @netdev: ptr to the netdev being adjusted - * @skb: buffer with required header information -@@ -448,6 +492,10 @@ ice_rx_flow_steer(struct net_device *net - continue; - - fltr_info = &arfs_entry->fltr_info; -+ -+ if (!ice_arfs_cmp(fltr_info, &fk, n_proto, ip_proto)) -+ continue; -+ - ret = fltr_info->fltr_id; - - if (fltr_info->q_index == rxq_idx || -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_ddp.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_ddp.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_ddp.c 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_ddp.c 2025-10-22 13:53:56.563168910 -0400 -@@ -2301,6 +2301,8 @@ enum ice_ddp_state ice_copy_and_init_pkg - return ICE_DDP_PKG_ERR; - - buf_copy = devm_kmemdup(ice_hw_to_dev(hw), buf, len, GFP_KERNEL); -+ if (!buf_copy) -+ return ICE_DDP_PKG_ERR; - - state = ice_init_pkg(hw, buf_copy, len); - if (!ice_is_init_pkg_successful(state)) { -@@ -2374,7 +2376,13 @@ ice_get_set_tx_topo(struct ice_hw *hw, u - * The function will apply the new Tx topology from the package buffer - * if available. - * -- * Return: zero when update was successful, negative values otherwise. -+ * Return: -+ * * 0 - Successfully applied topology configuration. -+ * * -EBUSY - Failed to acquire global configuration lock. -+ * * -EEXIST - Topology configuration has already been applied. -+ * * -EIO - Unable to apply topology configuration. -+ * * -ENODEV - Failed to re-initialize device after applying configuration. -+ * * Other negative error codes indicate unexpected failures. - */ - int ice_cfg_tx_topo(struct ice_hw *hw, const void *buf, u32 len) - { -@@ -2407,7 +2415,7 @@ int ice_cfg_tx_topo(struct ice_hw *hw, c - - if (status) { - ice_debug(hw, ICE_DBG_INIT, "Get current topology is failed\n"); -- return status; -+ return -EIO; - } - - /* Is default topology already applied ? */ -@@ -2494,31 +2502,45 @@ update_topo: - ICE_GLOBAL_CFG_LOCK_TIMEOUT); - if (status) { - ice_debug(hw, ICE_DBG_INIT, "Failed to acquire global lock\n"); -- return status; -+ return -EBUSY; - } - - /* Check if reset was triggered already. */ - reg = rd32(hw, GLGEN_RSTAT); - if (reg & GLGEN_RSTAT_DEVSTATE_M) { -- /* Reset is in progress, re-init the HW again */ - ice_debug(hw, ICE_DBG_INIT, "Reset is in progress. Layer topology might be applied already\n"); - ice_check_reset(hw); -- return 0; -+ /* Reset is in progress, re-init the HW again */ -+ goto reinit_hw; - } - - /* Set new topology */ - status = ice_get_set_tx_topo(hw, new_topo, size, NULL, NULL, true); - if (status) { -- ice_debug(hw, ICE_DBG_INIT, "Failed setting Tx topology\n"); -- return status; -+ ice_debug(hw, ICE_DBG_INIT, "Failed to set Tx topology, status %pe\n", -+ ERR_PTR(status)); -+ /* only report -EIO here as the caller checks the error value -+ * and reports an informational error message informing that -+ * the driver failed to program Tx topology. -+ */ -+ status = -EIO; - } - -- /* New topology is updated, delay 1 second before issuing the CORER */ -+ /* Even if Tx topology config failed, we need to CORE reset here to -+ * clear the global configuration lock. Delay 1 second to allow -+ * hardware to settle then issue a CORER -+ */ - msleep(1000); - ice_reset(hw, ICE_RESET_CORER); -- /* CORER will clear the global lock, so no explicit call -- * required for release. -- */ -+ ice_check_reset(hw); - -- return 0; -+reinit_hw: -+ /* Since we triggered a CORER, re-initialize hardware */ -+ ice_deinit_hw(hw); -+ if (ice_init_hw(hw)) { -+ ice_debug(hw, ICE_DBG_INIT, "Failed to re-init hardware after setting Tx topology\n"); -+ return -ENODEV; -+ } -+ -+ return status; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_debugfs.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_debugfs.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_debugfs.c 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_debugfs.c 2025-10-22 13:53:56.563168910 -0400 -@@ -606,7 +606,7 @@ void ice_debugfs_fwlog_init(struct ice_p - - pf->ice_debugfs_pf_fwlog = debugfs_create_dir("fwlog", - pf->ice_debugfs_pf); -- if (IS_ERR(pf->ice_debugfs_pf)) -+ if (IS_ERR(pf->ice_debugfs_pf_fwlog)) - goto err_create_module_files; - - fw_modules_dir = debugfs_create_dir("modules", -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_eswitch.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_eswitch.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_eswitch.c 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_eswitch.c 2025-10-22 13:53:56.563168910 -0400 -@@ -508,10 +508,14 @@ err_create_repr: - */ - int ice_eswitch_attach_vf(struct ice_pf *pf, struct ice_vf *vf) - { -- struct ice_repr *repr = ice_repr_create_vf(vf); - struct devlink *devlink = priv_to_devlink(pf); -+ struct ice_repr *repr; - int err; - -+ if (!ice_is_eswitch_mode_switchdev(pf)) -+ return 0; -+ -+ repr = ice_repr_create_vf(vf); - if (IS_ERR(repr)) - return PTR_ERR(repr); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice.h 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice.h 2025-10-22 13:53:56.563168910 -0400 -@@ -509,6 +509,7 @@ enum ice_pf_flags { - ICE_FLAG_LINK_LENIENT_MODE_ENA, - ICE_FLAG_PLUG_AUX_DEV, - ICE_FLAG_UNPLUG_AUX_DEV, -+ ICE_FLAG_AUX_DEV_CREATED, - ICE_FLAG_MTU_CHANGED, - ICE_FLAG_GNSS, /* GNSS successfully initialized */ - ICE_FLAG_DPLL, /* SyncE/PTP dplls initialized */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_idc.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_idc.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_idc.c 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_idc.c 2025-10-22 13:53:56.563168910 -0400 -@@ -336,6 +336,7 @@ int ice_plug_aux_dev(struct ice_pf *pf) - mutex_lock(&pf->adev_mutex); - cdev->adev = adev; - mutex_unlock(&pf->adev_mutex); -+ set_bit(ICE_FLAG_AUX_DEV_CREATED, pf->flags); - - return 0; - } -@@ -347,15 +348,16 @@ void ice_unplug_aux_dev(struct ice_pf *p - { - struct auxiliary_device *adev; - -+ if (!test_and_clear_bit(ICE_FLAG_AUX_DEV_CREATED, pf->flags)) -+ return; -+ - mutex_lock(&pf->adev_mutex); - adev = pf->cdev_info->adev; - pf->cdev_info->adev = NULL; - mutex_unlock(&pf->adev_mutex); - -- if (adev) { -- auxiliary_device_delete(adev); -- auxiliary_device_uninit(adev); -- } -+ auxiliary_device_delete(adev); -+ auxiliary_device_uninit(adev); - } - - /** -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_lag.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_lag.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_lag.c 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_lag.c 2025-10-22 13:53:56.563168910 -0400 -@@ -2226,7 +2226,8 @@ bool ice_lag_is_switchdev_running(struct - struct ice_lag *lag = pf->lag; - struct net_device *tmp_nd; - -- if (!ice_is_feature_supported(pf, ICE_F_SRIOV_LAG) || !lag) -+ if (!ice_is_feature_supported(pf, ICE_F_SRIOV_LAG) || -+ !lag || !lag->upper_netdev) - return false; - - rcu_read_lock(); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_main.c 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_main.c 2025-10-22 13:53:56.563168910 -0400 -@@ -3172,12 +3172,14 @@ static irqreturn_t ice_ll_ts_intr(int __ - hw = &pf->hw; - tx = &pf->ptp.port.tx; - spin_lock_irqsave(&tx->lock, flags); -- ice_ptp_complete_tx_single_tstamp(tx); -+ if (tx->init) { -+ ice_ptp_complete_tx_single_tstamp(tx); - -- idx = find_next_bit_wrap(tx->in_use, tx->len, -- tx->last_ll_ts_idx_read + 1); -- if (idx != tx->len) -- ice_ptp_req_tx_single_tstamp(tx, idx); -+ idx = find_next_bit_wrap(tx->in_use, tx->len, -+ tx->last_ll_ts_idx_read + 1); -+ if (idx != tx->len) -+ ice_ptp_req_tx_single_tstamp(tx, idx); -+ } - spin_unlock_irqrestore(&tx->lock, flags); - - val = GLINT_DYN_CTL_INTENA_M | GLINT_DYN_CTL_CLEARPBA_M | -@@ -4532,17 +4534,23 @@ ice_init_tx_topology(struct ice_hw *hw, - dev_info(dev, "Tx scheduling layers switching feature disabled\n"); - else - dev_info(dev, "Tx scheduling layers switching feature enabled\n"); -- /* if there was a change in topology ice_cfg_tx_topo triggered -- * a CORER and we need to re-init hw -+ return 0; -+ } else if (err == -ENODEV) { -+ /* If we failed to re-initialize the device, we can no longer -+ * continue loading. - */ -- ice_deinit_hw(hw); -- err = ice_init_hw(hw); -- -+ dev_warn(dev, "Failed to initialize hardware after applying Tx scheduling configuration.\n"); - return err; - } else if (err == -EIO) { - dev_info(dev, "DDP package does not support Tx scheduling layers switching feature - please update to the latest DDP package and try again\n"); -+ return 0; -+ } else if (err == -EEXIST) { -+ return 0; - } - -+ /* Do not treat this as a fatal error. */ -+ dev_info(dev, "Failed to apply Tx scheduling configuration, err %pe\n", -+ ERR_PTR(err)); - return 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_ptp.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_ptp.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_ptp.c 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_ptp.c 2025-10-22 13:53:56.563168910 -0400 -@@ -2299,6 +2299,7 @@ static int ice_capture_crosststamp(ktime - ts = ((u64)ts_hi << 32) | ts_lo; - system->cycles = ts; - system->cs_id = CSID_X86_ART; -+ system->use_nsecs = true; - - /* Read Device source clock time */ - ts_lo = rd32(hw, cfg->dev_time_l[tmr_idx]); -@@ -2876,16 +2877,19 @@ irqreturn_t ice_ptp_ts_irq(struct ice_pf - */ - if (hw->dev_caps.ts_dev_info.ts_ll_int_read) { - struct ice_ptp_tx *tx = &pf->ptp.port.tx; -- u8 idx; -+ u8 idx, last; - - if (!ice_pf_state_is_nominal(pf)) - return IRQ_HANDLED; - - spin_lock(&tx->lock); -- idx = find_next_bit_wrap(tx->in_use, tx->len, -- tx->last_ll_ts_idx_read + 1); -- if (idx != tx->len) -- ice_ptp_req_tx_single_tstamp(tx, idx); -+ if (tx->init) { -+ last = tx->last_ll_ts_idx_read + 1; -+ idx = find_next_bit_wrap(tx->in_use, tx->len, -+ last); -+ if (idx != tx->len) -+ ice_ptp_req_tx_single_tstamp(tx, idx); -+ } - spin_unlock(&tx->lock); - - return IRQ_HANDLED; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_txrx.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_txrx.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_txrx.c 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_txrx.c 2025-10-22 13:53:56.563168910 -0400 -@@ -865,10 +865,6 @@ ice_add_xdp_frag(struct ice_rx_ring *rx_ - __skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++, rx_buf->page, - rx_buf->page_offset, size); - sinfo->xdp_frags_size += size; -- /* remember frag count before XDP prog execution; bpf_xdp_adjust_tail() -- * can pop off frags but driver has to handle it on its own -- */ -- rx_ring->nr_frags = sinfo->nr_frags; - - if (page_is_pfmemalloc(rx_buf->page)) - xdp_buff_set_frag_pfmemalloc(xdp); -@@ -939,20 +935,20 @@ ice_get_rx_buf(struct ice_rx_ring *rx_ri - /** - * ice_get_pgcnts - grab page_count() for gathered fragments - * @rx_ring: Rx descriptor ring to store the page counts on -+ * @ntc: the next to clean element (not included in this frame!) - * - * This function is intended to be called right before running XDP - * program so that the page recycling mechanism will be able to take - * a correct decision regarding underlying pages; this is done in such - * way as XDP program can change the refcount of page - */ --static void ice_get_pgcnts(struct ice_rx_ring *rx_ring) -+static void ice_get_pgcnts(struct ice_rx_ring *rx_ring, unsigned int ntc) - { -- u32 nr_frags = rx_ring->nr_frags + 1; - u32 idx = rx_ring->first_desc; - struct ice_rx_buf *rx_buf; - u32 cnt = rx_ring->count; - -- for (int i = 0; i < nr_frags; i++) { -+ while (idx != ntc) { - rx_buf = &rx_ring->rx_buf[idx]; - rx_buf->pgcnt = page_count(rx_buf->page); - -@@ -1125,62 +1121,51 @@ ice_put_rx_buf(struct ice_rx_ring *rx_ri - } - - /** -- * ice_put_rx_mbuf - ice_put_rx_buf() caller, for all frame frags -+ * ice_put_rx_mbuf - ice_put_rx_buf() caller, for all buffers in frame - * @rx_ring: Rx ring with all the auxiliary data - * @xdp: XDP buffer carrying linear + frags part -- * @xdp_xmit: XDP_TX/XDP_REDIRECT verdict storage -- * @ntc: a current next_to_clean value to be stored at rx_ring -+ * @ntc: the next to clean element (not included in this frame!) - * @verdict: return code from XDP program execution - * -- * Walk through gathered fragments and satisfy internal page -- * recycle mechanism; we take here an action related to verdict -- * returned by XDP program; -+ * Called after XDP program is completed, or on error with verdict set to -+ * ICE_XDP_CONSUMED. -+ * -+ * Walk through buffers from first_desc to the end of the frame, releasing -+ * buffers and satisfying internal page recycle mechanism. The action depends -+ * on verdict from XDP program. - */ - static void ice_put_rx_mbuf(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp, -- u32 *xdp_xmit, u32 ntc, u32 verdict) -+ u32 ntc, u32 verdict) - { -- u32 nr_frags = rx_ring->nr_frags + 1; - u32 idx = rx_ring->first_desc; - u32 cnt = rx_ring->count; -- u32 post_xdp_frags = 1; - struct ice_rx_buf *buf; -- int i; -+ u32 xdp_frags = 0; -+ int i = 0; - - if (unlikely(xdp_buff_has_frags(xdp))) -- post_xdp_frags += xdp_get_shared_info_from_buff(xdp)->nr_frags; -+ xdp_frags = xdp_get_shared_info_from_buff(xdp)->nr_frags; - -- for (i = 0; i < post_xdp_frags; i++) { -+ while (idx != ntc) { - buf = &rx_ring->rx_buf[idx]; -+ if (++idx == cnt) -+ idx = 0; - -- if (verdict & (ICE_XDP_TX | ICE_XDP_REDIR)) { -+ /* An XDP program could release fragments from the end of the -+ * buffer. For these, we need to keep the pagecnt_bias as-is. -+ * To do this, only adjust pagecnt_bias for fragments up to -+ * the total remaining after the XDP program has run. -+ */ -+ if (verdict != ICE_XDP_CONSUMED) - ice_rx_buf_adjust_pg_offset(buf, xdp->frame_sz); -- *xdp_xmit |= verdict; -- } else if (verdict & ICE_XDP_CONSUMED) { -+ else if (i++ <= xdp_frags) - buf->pagecnt_bias++; -- } else if (verdict == ICE_XDP_PASS) { -- ice_rx_buf_adjust_pg_offset(buf, xdp->frame_sz); -- } - - ice_put_rx_buf(rx_ring, buf); -- -- if (++idx == cnt) -- idx = 0; -- } -- /* handle buffers that represented frags released by XDP prog; -- * for these we keep pagecnt_bias as-is; refcount from struct page -- * has been decremented within XDP prog and we do not have to increase -- * the biased refcnt -- */ -- for (; i < nr_frags; i++) { -- buf = &rx_ring->rx_buf[idx]; -- ice_put_rx_buf(rx_ring, buf); -- if (++idx == cnt) -- idx = 0; - } - - xdp->data = NULL; - rx_ring->first_desc = ntc; -- rx_ring->nr_frags = 0; - } - - /** -@@ -1260,6 +1245,10 @@ int ice_clean_rx_irq(struct ice_rx_ring - /* retrieve a buffer from the ring */ - rx_buf = ice_get_rx_buf(rx_ring, size, ntc); - -+ /* Increment ntc before calls to ice_put_rx_mbuf() */ -+ if (++ntc == cnt) -+ ntc = 0; -+ - if (!xdp->data) { - void *hard_start; - -@@ -1268,24 +1257,23 @@ int ice_clean_rx_irq(struct ice_rx_ring - xdp_prepare_buff(xdp, hard_start, offset, size, !!offset); - xdp_buff_clear_frags_flag(xdp); - } else if (ice_add_xdp_frag(rx_ring, xdp, rx_buf, size)) { -- ice_put_rx_mbuf(rx_ring, xdp, NULL, ntc, ICE_XDP_CONSUMED); -+ ice_put_rx_mbuf(rx_ring, xdp, ntc, ICE_XDP_CONSUMED); - break; - } -- if (++ntc == cnt) -- ntc = 0; - - /* skip if it is NOP desc */ - if (ice_is_non_eop(rx_ring, rx_desc)) - continue; - -- ice_get_pgcnts(rx_ring); -+ ice_get_pgcnts(rx_ring, ntc); - xdp_verdict = ice_run_xdp(rx_ring, xdp, xdp_prog, xdp_ring, rx_desc); - if (xdp_verdict == ICE_XDP_PASS) - goto construct_skb; - total_rx_bytes += xdp_get_buff_len(xdp); - total_rx_pkts++; - -- ice_put_rx_mbuf(rx_ring, xdp, &xdp_xmit, ntc, xdp_verdict); -+ ice_put_rx_mbuf(rx_ring, xdp, ntc, xdp_verdict); -+ xdp_xmit |= xdp_verdict & (ICE_XDP_TX | ICE_XDP_REDIR); - - continue; - construct_skb: -@@ -1295,10 +1283,10 @@ construct_skb: - skb = ice_construct_skb(rx_ring, xdp); - /* exit if we failed to retrieve a buffer */ - if (!skb) { -- rx_ring->ring_stats->rx_stats.alloc_page_failed++; -+ rx_ring->ring_stats->rx_stats.alloc_buf_failed++; - xdp_verdict = ICE_XDP_CONSUMED; - } -- ice_put_rx_mbuf(rx_ring, xdp, &xdp_xmit, ntc, xdp_verdict); -+ ice_put_rx_mbuf(rx_ring, xdp, ntc, xdp_verdict); - - if (!skb) - break; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_txrx.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_txrx.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ice/ice_txrx.h 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ice/ice_txrx.h 2025-10-22 13:53:56.563168910 -0400 -@@ -358,7 +358,6 @@ struct ice_rx_ring { - struct ice_tx_ring *xdp_ring; - struct ice_rx_ring *next; /* pointer to next ring in q_vector */ - struct xsk_buff_pool *xsk_pool; -- u32 nr_frags; - u16 max_frame; - u16 rx_buf_len; - dma_addr_t dma; /* physical address of ring */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/idpf/idpf_controlq_api.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/idpf/idpf_controlq_api.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/idpf/idpf_controlq_api.h 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/idpf/idpf_controlq_api.h 2025-10-22 13:53:56.563168910 -0400 -@@ -99,7 +99,7 @@ struct idpf_ctlq_info { - - enum idpf_ctlq_type cq_type; - int q_id; -- struct mutex cq_lock; /* control queue lock */ -+ spinlock_t cq_lock; /* control queue lock */ - /* used for interrupt processing */ - u16 next_to_use; - u16 next_to_clean; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/idpf/idpf_controlq.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/idpf/idpf_controlq.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/idpf/idpf_controlq.c 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/idpf/idpf_controlq.c 2025-10-22 13:53:56.563168910 -0400 -@@ -96,7 +96,7 @@ static void idpf_ctlq_init_rxq_bufs(stru - */ - static void idpf_ctlq_shutdown(struct idpf_hw *hw, struct idpf_ctlq_info *cq) - { -- mutex_lock(&cq->cq_lock); -+ spin_lock(&cq->cq_lock); - - /* free ring buffers and the ring itself */ - idpf_ctlq_dealloc_ring_res(hw, cq); -@@ -104,8 +104,7 @@ static void idpf_ctlq_shutdown(struct id - /* Set ring_size to 0 to indicate uninitialized queue */ - cq->ring_size = 0; - -- mutex_unlock(&cq->cq_lock); -- mutex_destroy(&cq->cq_lock); -+ spin_unlock(&cq->cq_lock); - } - - /** -@@ -173,7 +172,7 @@ int idpf_ctlq_add(struct idpf_hw *hw, - - idpf_ctlq_init_regs(hw, cq, is_rxq); - -- mutex_init(&cq->cq_lock); -+ spin_lock_init(&cq->cq_lock); - - list_add(&cq->cq_list, &hw->cq_list_head); - -@@ -272,7 +271,7 @@ int idpf_ctlq_send(struct idpf_hw *hw, s - int err = 0; - int i; - -- mutex_lock(&cq->cq_lock); -+ spin_lock(&cq->cq_lock); - - /* Ensure there are enough descriptors to send all messages */ - num_desc_avail = IDPF_CTLQ_DESC_UNUSED(cq); -@@ -332,7 +331,7 @@ int idpf_ctlq_send(struct idpf_hw *hw, s - wr32(hw, cq->reg.tail, cq->next_to_use); - - err_unlock: -- mutex_unlock(&cq->cq_lock); -+ spin_unlock(&cq->cq_lock); - - return err; - } -@@ -364,7 +363,7 @@ int idpf_ctlq_clean_sq(struct idpf_ctlq_ - if (*clean_count > cq->ring_size) - return -EBADR; - -- mutex_lock(&cq->cq_lock); -+ spin_lock(&cq->cq_lock); - - ntc = cq->next_to_clean; - -@@ -397,7 +396,7 @@ int idpf_ctlq_clean_sq(struct idpf_ctlq_ - - cq->next_to_clean = ntc; - -- mutex_unlock(&cq->cq_lock); -+ spin_unlock(&cq->cq_lock); - - /* Return number of descriptors actually cleaned */ - *clean_count = i; -@@ -435,7 +434,7 @@ int idpf_ctlq_post_rx_buffs(struct idpf_ - if (*buff_count > 0) - buffs_avail = true; - -- mutex_lock(&cq->cq_lock); -+ spin_lock(&cq->cq_lock); - - if (tbp >= cq->ring_size) - tbp = 0; -@@ -524,7 +523,7 @@ post_buffs_out: - wr32(hw, cq->reg.tail, cq->next_to_post); - } - -- mutex_unlock(&cq->cq_lock); -+ spin_unlock(&cq->cq_lock); - - /* return the number of buffers that were not posted */ - *buff_count = *buff_count - i; -@@ -552,7 +551,7 @@ int idpf_ctlq_recv(struct idpf_ctlq_info - u16 i; - - /* take the lock before we start messing with the ring */ -- mutex_lock(&cq->cq_lock); -+ spin_lock(&cq->cq_lock); - - ntc = cq->next_to_clean; - -@@ -614,7 +613,7 @@ int idpf_ctlq_recv(struct idpf_ctlq_info - - cq->next_to_clean = ntc; - -- mutex_unlock(&cq->cq_lock); -+ spin_unlock(&cq->cq_lock); - - *num_q_msg = i; - if (*num_q_msg == 0) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/idpf/idpf_ethtool.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/idpf/idpf_ethtool.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/idpf/idpf_ethtool.c 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/idpf/idpf_ethtool.c 2025-10-22 13:53:56.563168910 -0400 -@@ -47,7 +47,7 @@ static u32 idpf_get_rxfh_key_size(struct - struct idpf_vport_user_config_data *user_config; - - if (!idpf_is_cap_ena_all(np->adapter, IDPF_RSS_CAPS, IDPF_CAP_RSS)) -- return -EOPNOTSUPP; -+ return 0; - - user_config = &np->adapter->vport_config[np->vport_idx]->user_config; - -@@ -66,7 +66,7 @@ static u32 idpf_get_rxfh_indir_size(stru - struct idpf_vport_user_config_data *user_config; - - if (!idpf_is_cap_ena_all(np->adapter, IDPF_RSS_CAPS, IDPF_CAP_RSS)) -- return -EOPNOTSUPP; -+ return 0; - - user_config = &np->adapter->vport_config[np->vport_idx]->user_config; - -@@ -1090,12 +1090,14 @@ static int idpf_get_per_q_coalesce(struc - /** - * __idpf_set_q_coalesce - set ITR values for specific queue - * @ec: ethtool structure from user to update ITR settings -+ * @q_coal: per queue coalesce settings - * @qv: queue vector for which itr values has to be set - * @is_rxq: is queue type rx - * - * Returns 0 on success, negative otherwise. - */ - static int __idpf_set_q_coalesce(const struct ethtool_coalesce *ec, -+ struct idpf_q_coalesce *q_coal, - struct idpf_q_vector *qv, bool is_rxq) - { - u32 use_adaptive_coalesce, coalesce_usecs; -@@ -1139,20 +1141,25 @@ static int __idpf_set_q_coalesce(const s - - if (is_rxq) { - qv->rx_itr_value = coalesce_usecs; -+ q_coal->rx_coalesce_usecs = coalesce_usecs; - if (use_adaptive_coalesce) { - qv->rx_intr_mode = IDPF_ITR_DYNAMIC; -+ q_coal->rx_intr_mode = IDPF_ITR_DYNAMIC; - } else { - qv->rx_intr_mode = !IDPF_ITR_DYNAMIC; -- idpf_vport_intr_write_itr(qv, qv->rx_itr_value, -- false); -+ q_coal->rx_intr_mode = !IDPF_ITR_DYNAMIC; -+ idpf_vport_intr_write_itr(qv, coalesce_usecs, false); - } - } else { - qv->tx_itr_value = coalesce_usecs; -+ q_coal->tx_coalesce_usecs = coalesce_usecs; - if (use_adaptive_coalesce) { - qv->tx_intr_mode = IDPF_ITR_DYNAMIC; -+ q_coal->tx_intr_mode = IDPF_ITR_DYNAMIC; - } else { - qv->tx_intr_mode = !IDPF_ITR_DYNAMIC; -- idpf_vport_intr_write_itr(qv, qv->tx_itr_value, true); -+ q_coal->tx_intr_mode = !IDPF_ITR_DYNAMIC; -+ idpf_vport_intr_write_itr(qv, coalesce_usecs, true); - } - } - -@@ -1165,6 +1172,7 @@ static int __idpf_set_q_coalesce(const s - /** - * idpf_set_q_coalesce - set ITR values for specific queue - * @vport: vport associated to the queue that need updating -+ * @q_coal: per queue coalesce settings - * @ec: coalesce settings to program the device with - * @q_num: update ITR/INTRL (coalesce) settings for this queue number/index - * @is_rxq: is queue type rx -@@ -1172,6 +1180,7 @@ static int __idpf_set_q_coalesce(const s - * Return 0 on success, and negative on failure - */ - static int idpf_set_q_coalesce(const struct idpf_vport *vport, -+ struct idpf_q_coalesce *q_coal, - const struct ethtool_coalesce *ec, - int q_num, bool is_rxq) - { -@@ -1180,7 +1189,7 @@ static int idpf_set_q_coalesce(const str - qv = is_rxq ? idpf_find_rxq_vec(vport, q_num) : - idpf_find_txq_vec(vport, q_num); - -- if (qv && __idpf_set_q_coalesce(ec, qv, is_rxq)) -+ if (qv && __idpf_set_q_coalesce(ec, q_coal, qv, is_rxq)) - return -EINVAL; - - return 0; -@@ -1201,9 +1210,13 @@ static int idpf_set_coalesce(struct net_ - struct netlink_ext_ack *extack) - { - struct idpf_netdev_priv *np = netdev_priv(netdev); -+ struct idpf_vport_user_config_data *user_config; -+ struct idpf_q_coalesce *q_coal; - struct idpf_vport *vport; - int i, err = 0; - -+ user_config = &np->adapter->vport_config[np->vport_idx]->user_config; -+ - idpf_vport_ctrl_lock(netdev); - vport = idpf_netdev_to_vport(netdev); - -@@ -1211,13 +1224,15 @@ static int idpf_set_coalesce(struct net_ - goto unlock_mutex; - - for (i = 0; i < vport->num_txq; i++) { -- err = idpf_set_q_coalesce(vport, ec, i, false); -+ q_coal = &user_config->q_coalesce[i]; -+ err = idpf_set_q_coalesce(vport, q_coal, ec, i, false); - if (err) - goto unlock_mutex; - } - - for (i = 0; i < vport->num_rxq; i++) { -- err = idpf_set_q_coalesce(vport, ec, i, true); -+ q_coal = &user_config->q_coalesce[i]; -+ err = idpf_set_q_coalesce(vport, q_coal, ec, i, true); - if (err) - goto unlock_mutex; - } -@@ -1239,20 +1254,25 @@ unlock_mutex: - static int idpf_set_per_q_coalesce(struct net_device *netdev, u32 q_num, - struct ethtool_coalesce *ec) - { -+ struct idpf_netdev_priv *np = netdev_priv(netdev); -+ struct idpf_vport_user_config_data *user_config; -+ struct idpf_q_coalesce *q_coal; - struct idpf_vport *vport; - int err; - - idpf_vport_ctrl_lock(netdev); - vport = idpf_netdev_to_vport(netdev); -+ user_config = &np->adapter->vport_config[np->vport_idx]->user_config; -+ q_coal = &user_config->q_coalesce[q_num]; - -- err = idpf_set_q_coalesce(vport, ec, q_num, false); -+ err = idpf_set_q_coalesce(vport, q_coal, ec, q_num, false); - if (err) { - idpf_vport_ctrl_unlock(netdev); - - return err; - } - -- err = idpf_set_q_coalesce(vport, ec, q_num, true); -+ err = idpf_set_q_coalesce(vport, q_coal, ec, q_num, true); - - idpf_vport_ctrl_unlock(netdev); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/idpf/idpf.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/idpf/idpf.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/idpf/idpf.h 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/idpf/idpf.h 2025-10-22 13:53:56.563168910 -0400 -@@ -379,9 +379,27 @@ struct idpf_rss_data { - }; - - /** -+ * struct idpf_q_coalesce - User defined coalescing configuration values for -+ * a single queue. -+ * @tx_intr_mode: Dynamic TX ITR or not -+ * @rx_intr_mode: Dynamic RX ITR or not -+ * @tx_coalesce_usecs: TX interrupt throttling rate -+ * @rx_coalesce_usecs: RX interrupt throttling rate -+ * -+ * Used to restore user coalescing configuration after a reset. -+ */ -+struct idpf_q_coalesce { -+ u32 tx_intr_mode; -+ u32 rx_intr_mode; -+ u32 tx_coalesce_usecs; -+ u32 rx_coalesce_usecs; -+}; -+ -+/** - * struct idpf_vport_user_config_data - User defined configuration values for - * each vport. - * @rss_data: See struct idpf_rss_data -+ * @q_coalesce: Array of per queue coalescing data - * @num_req_tx_qs: Number of user requested TX queues through ethtool - * @num_req_rx_qs: Number of user requested RX queues through ethtool - * @num_req_txq_desc: Number of user requested TX queue descriptors through -@@ -395,6 +413,7 @@ struct idpf_rss_data { - */ - struct idpf_vport_user_config_data { - struct idpf_rss_data rss_data; -+ struct idpf_q_coalesce *q_coalesce; - u16 num_req_tx_qs; - u16 num_req_rx_qs; - u32 num_req_txq_desc; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/idpf/idpf_lib.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/idpf/idpf_lib.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/idpf/idpf_lib.c 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/idpf/idpf_lib.c 2025-10-22 13:53:56.563168910 -0400 -@@ -1079,8 +1079,10 @@ static struct idpf_vport *idpf_vport_all - if (!vport) - return vport; - -+ num_max_q = max(max_q->max_txq, max_q->max_rxq); - if (!adapter->vport_config[idx]) { - struct idpf_vport_config *vport_config; -+ struct idpf_q_coalesce *q_coal; - - vport_config = kzalloc(sizeof(*vport_config), GFP_KERNEL); - if (!vport_config) { -@@ -1089,6 +1091,21 @@ static struct idpf_vport *idpf_vport_all - return NULL; - } - -+ q_coal = kcalloc(num_max_q, sizeof(*q_coal), GFP_KERNEL); -+ if (!q_coal) { -+ kfree(vport_config); -+ kfree(vport); -+ -+ return NULL; -+ } -+ for (int i = 0; i < num_max_q; i++) { -+ q_coal[i].tx_intr_mode = IDPF_ITR_DYNAMIC; -+ q_coal[i].tx_coalesce_usecs = IDPF_ITR_TX_DEF; -+ q_coal[i].rx_intr_mode = IDPF_ITR_DYNAMIC; -+ q_coal[i].rx_coalesce_usecs = IDPF_ITR_RX_DEF; -+ } -+ vport_config->user_config.q_coalesce = q_coal; -+ - adapter->vport_config[idx] = vport_config; - } - -@@ -1098,7 +1115,6 @@ static struct idpf_vport *idpf_vport_all - vport->default_vport = adapter->num_alloc_vports < - idpf_get_default_vports(adapter); - -- num_max_q = max(max_q->max_txq, max_q->max_rxq); - vport->q_vector_idxs = kcalloc(num_max_q, sizeof(u16), GFP_KERNEL); - if (!vport->q_vector_idxs) - goto free_vport; -@@ -2261,6 +2277,7 @@ static int idpf_set_mac(struct net_devic - struct idpf_netdev_priv *np = netdev_priv(netdev); - struct idpf_vport_config *vport_config; - struct sockaddr *addr = p; -+ u8 old_mac_addr[ETH_ALEN]; - struct idpf_vport *vport; - int err = 0; - -@@ -2284,17 +2301,19 @@ static int idpf_set_mac(struct net_devic - if (ether_addr_equal(netdev->dev_addr, addr->sa_data)) - goto unlock_mutex; - -+ ether_addr_copy(old_mac_addr, vport->default_mac_addr); -+ ether_addr_copy(vport->default_mac_addr, addr->sa_data); - vport_config = vport->adapter->vport_config[vport->idx]; - err = idpf_add_mac_filter(vport, np, addr->sa_data, false); - if (err) { - __idpf_del_mac_filter(vport_config, addr->sa_data); -+ ether_addr_copy(vport->default_mac_addr, netdev->dev_addr); - goto unlock_mutex; - } - -- if (is_valid_ether_addr(vport->default_mac_addr)) -- idpf_del_mac_filter(vport, np, vport->default_mac_addr, false); -+ if (is_valid_ether_addr(old_mac_addr)) -+ __idpf_del_mac_filter(vport_config, old_mac_addr); - -- ether_addr_copy(vport->default_mac_addr, addr->sa_data); - eth_hw_addr_set(netdev, addr->sa_data); - - unlock_mutex: -@@ -2314,8 +2333,12 @@ void *idpf_alloc_dma_mem(struct idpf_hw - struct idpf_adapter *adapter = hw->back; - size_t sz = ALIGN(size, 4096); - -- mem->va = dma_alloc_coherent(&adapter->pdev->dev, sz, -- &mem->pa, GFP_KERNEL); -+ /* The control queue resources are freed under a spinlock, contiguous -+ * pages will avoid IOMMU remapping and the use vmap (and vunmap in -+ * dma_free_*() path. -+ */ -+ mem->va = dma_alloc_attrs(&adapter->pdev->dev, sz, &mem->pa, -+ GFP_KERNEL, DMA_ATTR_FORCE_CONTIGUOUS); - mem->size = sz; - - return mem->va; -@@ -2330,8 +2353,8 @@ void idpf_free_dma_mem(struct idpf_hw *h - { - struct idpf_adapter *adapter = hw->back; - -- dma_free_coherent(&adapter->pdev->dev, mem->size, -- mem->va, mem->pa); -+ dma_free_attrs(&adapter->pdev->dev, mem->size, -+ mem->va, mem->pa, DMA_ATTR_FORCE_CONTIGUOUS); - mem->size = 0; - mem->va = NULL; - mem->pa = 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/idpf/idpf_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/idpf/idpf_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/idpf/idpf_main.c 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/idpf/idpf_main.c 2025-10-22 13:53:56.563168910 -0400 -@@ -62,6 +62,7 @@ destroy_wqs: - destroy_workqueue(adapter->vc_event_wq); - - for (i = 0; i < adapter->max_vports; i++) { -+ kfree(adapter->vport_config[i]->user_config.q_coalesce); - kfree(adapter->vport_config[i]); - adapter->vport_config[i] = NULL; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c 2025-10-22 13:53:23.335328551 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/idpf/idpf_singleq_txrx.c 2025-10-22 13:53:56.563168910 -0400 -@@ -180,6 +180,58 @@ static int idpf_tx_singleq_csum(struct s - } - - /** -+ * idpf_tx_singleq_dma_map_error - handle TX DMA map errors -+ * @txq: queue to send buffer on -+ * @skb: send buffer -+ * @first: original first buffer info buffer for packet -+ * @idx: starting point on ring to unwind -+ */ -+static void idpf_tx_singleq_dma_map_error(struct idpf_tx_queue *txq, -+ struct sk_buff *skb, -+ struct idpf_tx_buf *first, u16 idx) -+{ -+ struct libeth_sq_napi_stats ss = { }; -+ struct libeth_cq_pp cp = { -+ .dev = txq->dev, -+ .ss = &ss, -+ }; -+ -+ u64_stats_update_begin(&txq->stats_sync); -+ u64_stats_inc(&txq->q_stats.dma_map_errs); -+ u64_stats_update_end(&txq->stats_sync); -+ -+ /* clear dma mappings for failed tx_buf map */ -+ for (;;) { -+ struct idpf_tx_buf *tx_buf; -+ -+ tx_buf = &txq->tx_buf[idx]; -+ libeth_tx_complete(tx_buf, &cp); -+ if (tx_buf == first) -+ break; -+ if (idx == 0) -+ idx = txq->desc_count; -+ idx--; -+ } -+ -+ if (skb_is_gso(skb)) { -+ union idpf_tx_flex_desc *tx_desc; -+ -+ /* If we failed a DMA mapping for a TSO packet, we will have -+ * used one additional descriptor for a context -+ * descriptor. Reset that here. -+ */ -+ tx_desc = &txq->flex_tx[idx]; -+ memset(tx_desc, 0, sizeof(*tx_desc)); -+ if (idx == 0) -+ idx = txq->desc_count; -+ idx--; -+ } -+ -+ /* Update tail in case netdev_xmit_more was previously true */ -+ idpf_tx_buf_hw_update(txq, idx, false); -+} -+ -+/** - * idpf_tx_singleq_map - Build the Tx base descriptor - * @tx_q: queue to send buffer on - * @first: first buffer info buffer to use -@@ -219,8 +271,9 @@ static void idpf_tx_singleq_map(struct i - for (frag = &skb_shinfo(skb)->frags[0];; frag++) { - unsigned int max_data = IDPF_TX_MAX_DESC_DATA_ALIGNED; - -- if (dma_mapping_error(tx_q->dev, dma)) -- return idpf_tx_dma_map_error(tx_q, skb, first, i); -+ if (unlikely(dma_mapping_error(tx_q->dev, dma))) -+ return idpf_tx_singleq_dma_map_error(tx_q, skb, -+ first, i); - - /* record length, and DMA address */ - dma_unmap_len_set(tx_buf, len, size); -@@ -362,11 +415,11 @@ netdev_tx_t idpf_tx_singleq_frame(struct - { - struct idpf_tx_offload_params offload = { }; - struct idpf_tx_buf *first; -+ u32 count, buf_count = 1; - int csum, tso, needed; -- unsigned int count; - __be16 protocol; - -- count = idpf_tx_desc_count_required(tx_q, skb); -+ count = idpf_tx_res_count_required(tx_q, skb, &buf_count); - if (unlikely(!count)) - return idpf_tx_drop_skb(tx_q, skb); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/idpf/idpf_txrx.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/idpf/idpf_txrx.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/idpf/idpf_txrx.c 2025-10-22 13:53:23.339328532 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/idpf/idpf_txrx.c 2025-10-22 13:53:56.563168910 -0400 -@@ -13,6 +13,7 @@ struct idpf_tx_stash { - struct libeth_sqe buf; - }; - -+#define idpf_tx_buf_next(buf) (*(u32 *)&(buf)->priv) - #define idpf_tx_buf_compl_tag(buf) (*(u32 *)&(buf)->priv) - LIBETH_SQE_CHECK_PRIV(u32); - -@@ -91,7 +92,7 @@ static void idpf_tx_buf_rel_all(struct i - return; - - /* Free all the Tx buffer sk_buffs */ -- for (i = 0; i < txq->desc_count; i++) -+ for (i = 0; i < txq->buf_pool_size; i++) - libeth_tx_complete(&txq->tx_buf[i], &cp); - - kfree(txq->tx_buf); -@@ -139,6 +140,9 @@ static void idpf_tx_desc_rel(struct idpf - if (!txq->desc_ring) - return; - -+ if (txq->refillq) -+ kfree(txq->refillq->ring); -+ - dmam_free_coherent(txq->dev, txq->size, txq->desc_ring, txq->dma); - txq->desc_ring = NULL; - txq->next_to_use = 0; -@@ -196,14 +200,17 @@ static void idpf_tx_desc_rel_all(struct - static int idpf_tx_buf_alloc_all(struct idpf_tx_queue *tx_q) - { - struct idpf_buf_lifo *buf_stack; -- int buf_size; - int i; - - /* Allocate book keeping buffers only. Buffers to be supplied to HW - * are allocated by kernel network stack and received as part of skb - */ -- buf_size = sizeof(struct idpf_tx_buf) * tx_q->desc_count; -- tx_q->tx_buf = kzalloc(buf_size, GFP_KERNEL); -+ if (idpf_queue_has(FLOW_SCH_EN, tx_q)) -+ tx_q->buf_pool_size = U16_MAX; -+ else -+ tx_q->buf_pool_size = tx_q->desc_count; -+ tx_q->tx_buf = kcalloc(tx_q->buf_pool_size, sizeof(*tx_q->tx_buf), -+ GFP_KERNEL); - if (!tx_q->tx_buf) - return -ENOMEM; - -@@ -244,6 +251,7 @@ static int idpf_tx_desc_alloc(const stru - struct idpf_tx_queue *tx_q) - { - struct device *dev = tx_q->dev; -+ struct idpf_sw_queue *refillq; - int err; - - err = idpf_tx_buf_alloc_all(tx_q); -@@ -267,6 +275,29 @@ static int idpf_tx_desc_alloc(const stru - tx_q->next_to_clean = 0; - idpf_queue_set(GEN_CHK, tx_q); - -+ if (!idpf_queue_has(FLOW_SCH_EN, tx_q)) -+ return 0; -+ -+ refillq = tx_q->refillq; -+ refillq->desc_count = tx_q->buf_pool_size; -+ refillq->ring = kcalloc(refillq->desc_count, sizeof(u32), -+ GFP_KERNEL); -+ if (!refillq->ring) { -+ err = -ENOMEM; -+ goto err_alloc; -+ } -+ -+ for (unsigned int i = 0; i < refillq->desc_count; i++) -+ refillq->ring[i] = -+ FIELD_PREP(IDPF_RFL_BI_BUFID_M, i) | -+ FIELD_PREP(IDPF_RFL_BI_GEN_M, -+ idpf_queue_has(GEN_CHK, refillq)); -+ -+ /* Go ahead and flip the GEN bit since this counts as filling -+ * up the ring, i.e. we already ring wrapped. -+ */ -+ idpf_queue_change(GEN_CHK, refillq); -+ - return 0; - - err_alloc: -@@ -603,18 +634,18 @@ static int idpf_rx_hdr_buf_alloc_all(str - } - - /** -- * idpf_rx_post_buf_refill - Post buffer id to refill queue -+ * idpf_post_buf_refill - Post buffer id to refill queue - * @refillq: refill queue to post to - * @buf_id: buffer id to post - */ --static void idpf_rx_post_buf_refill(struct idpf_sw_queue *refillq, u16 buf_id) -+static void idpf_post_buf_refill(struct idpf_sw_queue *refillq, u16 buf_id) - { - u32 nta = refillq->next_to_use; - - /* store the buffer ID and the SW maintained GEN bit to the refillq */ - refillq->ring[nta] = -- FIELD_PREP(IDPF_RX_BI_BUFID_M, buf_id) | -- FIELD_PREP(IDPF_RX_BI_GEN_M, -+ FIELD_PREP(IDPF_RFL_BI_BUFID_M, buf_id) | -+ FIELD_PREP(IDPF_RFL_BI_GEN_M, - idpf_queue_has(GEN_CHK, refillq)); - - if (unlikely(++nta == refillq->desc_count)) { -@@ -995,6 +1026,11 @@ static void idpf_txq_group_rel(struct id - struct idpf_txq_group *txq_grp = &vport->txq_grps[i]; - - for (j = 0; j < txq_grp->num_txq; j++) { -+ if (flow_sch_en) { -+ kfree(txq_grp->txqs[j]->refillq); -+ txq_grp->txqs[j]->refillq = NULL; -+ } -+ - kfree(txq_grp->txqs[j]); - txq_grp->txqs[j] = NULL; - } -@@ -1414,6 +1450,13 @@ static int idpf_txq_group_alloc(struct i - } - - idpf_queue_set(FLOW_SCH_EN, q); -+ -+ q->refillq = kzalloc(sizeof(*q->refillq), GFP_KERNEL); -+ if (!q->refillq) -+ goto err_alloc; -+ -+ idpf_queue_set(GEN_CHK, q->refillq); -+ idpf_queue_set(RFL_GEN_CHK, q->refillq); - } - - if (!split) -@@ -1828,6 +1871,12 @@ static bool idpf_tx_splitq_clean(struct - struct idpf_tx_buf *tx_buf; - bool clean_complete = true; - -+ if (descs_only) { -+ /* Bump ring index to mark as cleaned. */ -+ tx_q->next_to_clean = end; -+ return true; -+ } -+ - tx_desc = &tx_q->flex_tx[ntc]; - next_pending_desc = &tx_q->flex_tx[end]; - tx_buf = &tx_q->tx_buf[ntc]; -@@ -1894,87 +1943,43 @@ do { \ - } while (0) - - /** -- * idpf_tx_clean_buf_ring - clean flow scheduling TX queue buffers -+ * idpf_tx_clean_bufs - clean flow scheduling TX queue buffers - * @txq: queue to clean -- * @compl_tag: completion tag of packet to clean (from completion descriptor) -+ * @buf_id: packet's starting buffer ID, from completion descriptor - * @cleaned: pointer to stats struct to track cleaned packets/bytes - * @budget: Used to determine if we are in netpoll - * -- * Cleans all buffers associated with the input completion tag either from the -- * TX buffer ring or from the hash table if the buffers were previously -- * stashed. Returns the byte/segment count for the cleaned packet associated -- * this completion tag. -- */ --static bool idpf_tx_clean_buf_ring(struct idpf_tx_queue *txq, u16 compl_tag, -- struct libeth_sq_napi_stats *cleaned, -- int budget) -+ * Clean all buffers associated with the packet starting at buf_id. Returns the -+ * byte/segment count for the cleaned packet. -+ */ -+static bool idpf_tx_clean_bufs(struct idpf_tx_queue *txq, u32 buf_id, -+ struct libeth_sq_napi_stats *cleaned, -+ int budget) - { -- u16 idx = compl_tag & txq->compl_tag_bufid_m; - struct idpf_tx_buf *tx_buf = NULL; - struct libeth_cq_pp cp = { - .dev = txq->dev, - .ss = cleaned, - .napi = budget, - }; -- u16 ntc, orig_idx = idx; -- -- tx_buf = &txq->tx_buf[idx]; -- -- if (unlikely(tx_buf->type <= LIBETH_SQE_CTX || -- idpf_tx_buf_compl_tag(tx_buf) != compl_tag)) -- return false; - -+ tx_buf = &txq->tx_buf[buf_id]; - if (tx_buf->type == LIBETH_SQE_SKB) { - if (skb_shinfo(tx_buf->skb)->tx_flags & SKBTX_IN_PROGRESS) - idpf_tx_read_tstamp(txq, tx_buf->skb); - - libeth_tx_complete(tx_buf, &cp); -+ idpf_post_buf_refill(txq->refillq, buf_id); - } - -- idpf_tx_clean_buf_ring_bump_ntc(txq, idx, tx_buf); -+ while (idpf_tx_buf_next(tx_buf) != IDPF_TXBUF_NULL) { -+ buf_id = idpf_tx_buf_next(tx_buf); - -- while (idpf_tx_buf_compl_tag(tx_buf) == compl_tag) { -+ tx_buf = &txq->tx_buf[buf_id]; - libeth_tx_complete(tx_buf, &cp); -- idpf_tx_clean_buf_ring_bump_ntc(txq, idx, tx_buf); -+ idpf_post_buf_refill(txq->refillq, buf_id); - } - -- /* -- * It's possible the packet we just cleaned was an out of order -- * completion, which means we can stash the buffers starting from -- * the original next_to_clean and reuse the descriptors. We need -- * to compare the descriptor ring next_to_clean packet's "first" buffer -- * to the "first" buffer of the packet we just cleaned to determine if -- * this is the case. Howevever, next_to_clean can point to either a -- * reserved buffer that corresponds to a context descriptor used for the -- * next_to_clean packet (TSO packet) or the "first" buffer (single -- * packet). The orig_idx from the packet we just cleaned will always -- * point to the "first" buffer. If next_to_clean points to a reserved -- * buffer, let's bump ntc once and start the comparison from there. -- */ -- ntc = txq->next_to_clean; -- tx_buf = &txq->tx_buf[ntc]; -- -- if (tx_buf->type == LIBETH_SQE_CTX) -- idpf_tx_clean_buf_ring_bump_ntc(txq, ntc, tx_buf); -- -- /* -- * If ntc still points to a different "first" buffer, clean the -- * descriptor ring and stash all of the buffers for later cleaning. If -- * we cannot stash all of the buffers, next_to_clean will point to the -- * "first" buffer of the packet that could not be stashed and cleaning -- * will start there next time. -- */ -- if (unlikely(tx_buf != &txq->tx_buf[orig_idx] && -- !idpf_tx_splitq_clean(txq, orig_idx, budget, cleaned, -- true))) -- return true; -- -- /* -- * Otherwise, update next_to_clean to reflect the cleaning that was -- * done above. -- */ -- txq->next_to_clean = idx; -- - return true; - } - -@@ -2008,7 +2013,7 @@ static void idpf_tx_handle_rs_completion - /* If we didn't clean anything on the ring, this packet must be - * in the hash table. Go clean it there. - */ -- if (!idpf_tx_clean_buf_ring(txq, compl_tag, cleaned, budget)) -+ if (!idpf_tx_clean_bufs(txq, compl_tag, cleaned, budget)) - idpf_tx_clean_stashed_bufs(txq, compl_tag, cleaned, budget); - } - -@@ -2184,15 +2189,22 @@ void idpf_tx_splitq_build_flow_desc(unio - desc->flow.qw1.compl_tag = cpu_to_le16(params->compl_tag); - } - --/* Global conditions to tell whether the txq (and related resources) -- * has room to allow the use of "size" descriptors. -+/** -+ * idpf_tx_splitq_has_room - check if enough Tx splitq resources are available -+ * @tx_q: the queue to be checked -+ * @descs_needed: number of descriptors required for this packet -+ * @bufs_needed: number of Tx buffers required for this packet -+ * -+ * Return: 0 if no room available, 1 otherwise - */ --static int idpf_txq_has_room(struct idpf_tx_queue *tx_q, u32 size) -+static int idpf_txq_has_room(struct idpf_tx_queue *tx_q, u32 descs_needed, -+ u32 bufs_needed) - { -- if (IDPF_DESC_UNUSED(tx_q) < size || -+ if (IDPF_DESC_UNUSED(tx_q) < descs_needed || - IDPF_TX_COMPLQ_PENDING(tx_q->txq_grp) > - IDPF_TX_COMPLQ_OVERFLOW_THRESH(tx_q->txq_grp->complq) || -- IDPF_TX_BUF_RSV_LOW(tx_q)) -+ IDPF_TX_BUF_RSV_LOW(tx_q) || -+ idpf_tx_splitq_get_free_bufs(tx_q->refillq) < bufs_needed) - return 0; - return 1; - } -@@ -2201,14 +2213,21 @@ static int idpf_txq_has_room(struct idpf - * idpf_tx_maybe_stop_splitq - 1st level check for Tx splitq stop conditions - * @tx_q: the queue to be checked - * @descs_needed: number of descriptors required for this packet -+ * @bufs_needed: number of buffers needed for this packet - * -- * Returns 0 if stop is not needed -+ * Return: 0 if stop is not needed - */ - static int idpf_tx_maybe_stop_splitq(struct idpf_tx_queue *tx_q, -- unsigned int descs_needed) -+ u32 descs_needed, -+ u32 bufs_needed) - { -+ /* Since we have multiple resources to check for splitq, our -+ * start,stop_thrs becomes a boolean check instead of a count -+ * threshold. -+ */ - if (netif_subqueue_maybe_stop(tx_q->netdev, tx_q->idx, -- idpf_txq_has_room(tx_q, descs_needed), -+ idpf_txq_has_room(tx_q, descs_needed, -+ bufs_needed), - 1, 1)) - return 0; - -@@ -2250,14 +2269,16 @@ void idpf_tx_buf_hw_update(struct idpf_t - } - - /** -- * idpf_tx_desc_count_required - calculate number of Tx descriptors needed -+ * idpf_tx_res_count_required - get number of Tx resources needed for this pkt - * @txq: queue to send buffer on - * @skb: send buffer -+ * @bufs_needed: (output) number of buffers needed for this skb. - * -- * Returns number of data descriptors needed for this skb. -+ * Return: number of data descriptors and buffers needed for this skb. - */ --unsigned int idpf_tx_desc_count_required(struct idpf_tx_queue *txq, -- struct sk_buff *skb) -+unsigned int idpf_tx_res_count_required(struct idpf_tx_queue *txq, -+ struct sk_buff *skb, -+ u32 *bufs_needed) - { - const struct skb_shared_info *shinfo; - unsigned int count = 0, i; -@@ -2268,6 +2289,7 @@ unsigned int idpf_tx_desc_count_required - return count; - - shinfo = skb_shinfo(skb); -+ *bufs_needed += shinfo->nr_frags; - for (i = 0; i < shinfo->nr_frags; i++) { - unsigned int size; - -@@ -2297,71 +2319,91 @@ unsigned int idpf_tx_desc_count_required - } - - /** -- * idpf_tx_dma_map_error - handle TX DMA map errors -- * @txq: queue to send buffer on -- * @skb: send buffer -- * @first: original first buffer info buffer for packet -- * @idx: starting point on ring to unwind -+ * idpf_tx_splitq_bump_ntu - adjust NTU and generation -+ * @txq: the tx ring to wrap -+ * @ntu: ring index to bump - */ --void idpf_tx_dma_map_error(struct idpf_tx_queue *txq, struct sk_buff *skb, -- struct idpf_tx_buf *first, u16 idx) -+static unsigned int idpf_tx_splitq_bump_ntu(struct idpf_tx_queue *txq, u16 ntu) - { -- struct libeth_sq_napi_stats ss = { }; -- struct libeth_cq_pp cp = { -- .dev = txq->dev, -- .ss = &ss, -- }; -+ ntu++; - -- u64_stats_update_begin(&txq->stats_sync); -- u64_stats_inc(&txq->q_stats.dma_map_errs); -- u64_stats_update_end(&txq->stats_sync); -+ if (ntu == txq->desc_count) { -+ ntu = 0; -+ txq->compl_tag_cur_gen = IDPF_TX_ADJ_COMPL_TAG_GEN(txq); -+ } - -- /* clear dma mappings for failed tx_buf map */ -- for (;;) { -- struct idpf_tx_buf *tx_buf; -+ return ntu; -+} - -- tx_buf = &txq->tx_buf[idx]; -- libeth_tx_complete(tx_buf, &cp); -- if (tx_buf == first) -- break; -- if (idx == 0) -- idx = txq->desc_count; -- idx--; -- } -+/** -+ * idpf_tx_get_free_buf_id - get a free buffer ID from the refill queue -+ * @refillq: refill queue to get buffer ID from -+ * @buf_id: return buffer ID -+ * -+ * Return: true if a buffer ID was found, false if not -+ */ -+static bool idpf_tx_get_free_buf_id(struct idpf_sw_queue *refillq, -+ u32 *buf_id) -+{ -+ u32 ntc = refillq->next_to_clean; -+ u32 refill_desc; - -- if (skb_is_gso(skb)) { -- union idpf_tx_flex_desc *tx_desc; -+ refill_desc = refillq->ring[ntc]; - -- /* If we failed a DMA mapping for a TSO packet, we will have -- * used one additional descriptor for a context -- * descriptor. Reset that here. -- */ -- tx_desc = &txq->flex_tx[idx]; -- memset(tx_desc, 0, sizeof(*tx_desc)); -- if (idx == 0) -- idx = txq->desc_count; -- idx--; -+ if (unlikely(idpf_queue_has(RFL_GEN_CHK, refillq) != -+ !!(refill_desc & IDPF_RFL_BI_GEN_M))) -+ return false; -+ -+ *buf_id = FIELD_GET(IDPF_RFL_BI_BUFID_M, refill_desc); -+ -+ if (unlikely(++ntc == refillq->desc_count)) { -+ idpf_queue_change(RFL_GEN_CHK, refillq); -+ ntc = 0; - } - -- /* Update tail in case netdev_xmit_more was previously true */ -- idpf_tx_buf_hw_update(txq, idx, false); -+ refillq->next_to_clean = ntc; -+ -+ return true; - } - - /** -- * idpf_tx_splitq_bump_ntu - adjust NTU and generation -- * @txq: the tx ring to wrap -- * @ntu: ring index to bump -+ * idpf_tx_splitq_pkt_err_unmap - Unmap buffers and bump tail in case of error -+ * @txq: Tx queue to unwind -+ * @params: pointer to splitq params struct -+ * @first: starting buffer for packet to unmap - */ --static unsigned int idpf_tx_splitq_bump_ntu(struct idpf_tx_queue *txq, u16 ntu) -+static void idpf_tx_splitq_pkt_err_unmap(struct idpf_tx_queue *txq, -+ struct idpf_tx_splitq_params *params, -+ struct idpf_tx_buf *first) - { -- ntu++; -+ struct idpf_sw_queue *refillq = txq->refillq; -+ struct libeth_sq_napi_stats ss = { }; -+ struct idpf_tx_buf *tx_buf = first; -+ struct libeth_cq_pp cp = { -+ .dev = txq->dev, -+ .ss = &ss, -+ }; - -- if (ntu == txq->desc_count) { -- ntu = 0; -- txq->compl_tag_cur_gen = IDPF_TX_ADJ_COMPL_TAG_GEN(txq); -+ u64_stats_update_begin(&txq->stats_sync); -+ u64_stats_inc(&txq->q_stats.dma_map_errs); -+ u64_stats_update_end(&txq->stats_sync); -+ -+ libeth_tx_complete(tx_buf, &cp); -+ while (idpf_tx_buf_next(tx_buf) != IDPF_TXBUF_NULL) { -+ tx_buf = &txq->tx_buf[idpf_tx_buf_next(tx_buf)]; -+ libeth_tx_complete(tx_buf, &cp); - } - -- return ntu; -+ /* Update tail in case netdev_xmit_more was previously true. */ -+ idpf_tx_buf_hw_update(txq, params->prev_ntu, false); -+ -+ if (!refillq) -+ return; -+ -+ /* Restore refillq state to avoid leaking tags. */ -+ if (params->prev_refill_gen != idpf_queue_has(RFL_GEN_CHK, refillq)) -+ idpf_queue_change(RFL_GEN_CHK, refillq); -+ refillq->next_to_clean = params->prev_refill_ntc; - } - - /** -@@ -2385,6 +2427,7 @@ static void idpf_tx_splitq_map(struct id - struct netdev_queue *nq; - struct sk_buff *skb; - skb_frag_t *frag; -+ u32 next_buf_id; - u16 td_cmd = 0; - dma_addr_t dma; - -@@ -2402,17 +2445,16 @@ static void idpf_tx_splitq_map(struct id - tx_buf = first; - first->nr_frags = 0; - -- params->compl_tag = -- (tx_q->compl_tag_cur_gen << tx_q->compl_tag_gen_s) | i; -- - for (frag = &skb_shinfo(skb)->frags[0];; frag++) { - unsigned int max_data = IDPF_TX_MAX_DESC_DATA_ALIGNED; - -- if (dma_mapping_error(tx_q->dev, dma)) -- return idpf_tx_dma_map_error(tx_q, skb, first, i); -+ if (unlikely(dma_mapping_error(tx_q->dev, dma))) { -+ idpf_tx_buf_next(tx_buf) = IDPF_TXBUF_NULL; -+ return idpf_tx_splitq_pkt_err_unmap(tx_q, params, -+ first); -+ } - - first->nr_frags++; -- idpf_tx_buf_compl_tag(tx_buf) = params->compl_tag; - tx_buf->type = LIBETH_SQE_FRAG; - - /* record length, and DMA address */ -@@ -2468,29 +2510,14 @@ static void idpf_tx_splitq_map(struct id - max_data); - - if (unlikely(++i == tx_q->desc_count)) { -- tx_buf = tx_q->tx_buf; - tx_desc = &tx_q->flex_tx[0]; - i = 0; - tx_q->compl_tag_cur_gen = - IDPF_TX_ADJ_COMPL_TAG_GEN(tx_q); - } else { -- tx_buf++; - tx_desc++; - } - -- /* Since this packet has a buffer that is going to span -- * multiple descriptors, it's going to leave holes in -- * to the TX buffer ring. To ensure these holes do not -- * cause issues in the cleaning routines, we will clear -- * them of any stale data and assign them the same -- * completion tag as the current packet. Then when the -- * packet is being cleaned, the cleaning routines will -- * simply pass over these holes and finish cleaning the -- * rest of the packet. -- */ -- tx_buf->type = LIBETH_SQE_EMPTY; -- idpf_tx_buf_compl_tag(tx_buf) = params->compl_tag; -- - /* Adjust the DMA offset and the remaining size of the - * fragment. On the first iteration of this loop, - * max_data will be >= 12K and <= 16K-1. On any -@@ -2515,15 +2542,26 @@ static void idpf_tx_splitq_map(struct id - idpf_tx_splitq_build_desc(tx_desc, params, td_cmd, size); - - if (unlikely(++i == tx_q->desc_count)) { -- tx_buf = tx_q->tx_buf; - tx_desc = &tx_q->flex_tx[0]; - i = 0; - tx_q->compl_tag_cur_gen = IDPF_TX_ADJ_COMPL_TAG_GEN(tx_q); - } else { -- tx_buf++; - tx_desc++; - } - -+ if (idpf_queue_has(FLOW_SCH_EN, tx_q)) { -+ if (unlikely(!idpf_tx_get_free_buf_id(tx_q->refillq, -+ &next_buf_id))) { -+ idpf_tx_buf_next(tx_buf) = IDPF_TXBUF_NULL; -+ return idpf_tx_splitq_pkt_err_unmap(tx_q, params, -+ first); -+ } -+ } else { -+ next_buf_id = i; -+ } -+ idpf_tx_buf_next(tx_buf) = next_buf_id; -+ tx_buf = &tx_q->tx_buf[next_buf_id]; -+ - size = skb_frag_size(frag); - data_len -= size; - -@@ -2538,6 +2576,7 @@ static void idpf_tx_splitq_map(struct id - - /* write last descriptor with RS and EOP bits */ - first->rs_idx = i; -+ idpf_tx_buf_next(tx_buf) = IDPF_TXBUF_NULL; - td_cmd |= params->eop_cmd; - idpf_tx_splitq_build_desc(tx_desc, params, td_cmd, size); - i = idpf_tx_splitq_bump_ntu(tx_q, i); -@@ -2746,8 +2785,6 @@ idpf_tx_splitq_get_ctx_desc(struct idpf_ - union idpf_flex_tx_ctx_desc *desc; - int i = txq->next_to_use; - -- txq->tx_buf[i].type = LIBETH_SQE_CTX; -- - /* grab the next descriptor */ - desc = &txq->flex_ctx[i]; - txq->next_to_use = idpf_tx_splitq_bump_ntu(txq, i); -@@ -2850,13 +2887,16 @@ static void idpf_tx_set_tstamp_desc(unio - static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb, - struct idpf_tx_queue *tx_q) - { -- struct idpf_tx_splitq_params tx_params = { }; -+ struct idpf_tx_splitq_params tx_params = { -+ .prev_ntu = tx_q->next_to_use, -+ }; - union idpf_flex_tx_ctx_desc *ctx_desc; - struct idpf_tx_buf *first; -- unsigned int count; -+ u32 count, buf_count = 1; - int tso, idx; -+ u32 buf_id; - -- count = idpf_tx_desc_count_required(tx_q, skb); -+ count = idpf_tx_res_count_required(tx_q, skb, &buf_count); - if (unlikely(!count)) - return idpf_tx_drop_skb(tx_q, skb); - -@@ -2866,7 +2906,7 @@ static netdev_tx_t idpf_tx_splitq_frame( - - /* Check for splitq specific TX resources */ - count += (IDPF_TX_DESCS_PER_CACHE_LINE + tso); -- if (idpf_tx_maybe_stop_splitq(tx_q, count)) { -+ if (idpf_tx_maybe_stop_splitq(tx_q, count, buf_count)) { - idpf_tx_buf_hw_update(tx_q, tx_q->next_to_use, false); - - return NETDEV_TX_BUSY; -@@ -2898,20 +2938,29 @@ static netdev_tx_t idpf_tx_splitq_frame( - idpf_tx_set_tstamp_desc(ctx_desc, idx); - } - -- /* record the location of the first descriptor for this packet */ -- first = &tx_q->tx_buf[tx_q->next_to_use]; -- first->skb = skb; -+ if (idpf_queue_has(FLOW_SCH_EN, tx_q)) { -+ struct idpf_sw_queue *refillq = tx_q->refillq; - -- if (tso) { -- first->packets = tx_params.offload.tso_segs; -- first->bytes = skb->len + -- ((first->packets - 1) * tx_params.offload.tso_hdr_len); -- } else { -- first->packets = 1; -- first->bytes = max_t(unsigned int, skb->len, ETH_ZLEN); -- } -+ /* Save refillq state in case of a packet rollback. Otherwise, -+ * the tags will be leaked since they will be popped from the -+ * refillq but never reposted during cleaning. -+ */ -+ tx_params.prev_refill_gen = -+ idpf_queue_has(RFL_GEN_CHK, refillq); -+ tx_params.prev_refill_ntc = refillq->next_to_clean; -+ -+ if (unlikely(!idpf_tx_get_free_buf_id(tx_q->refillq, -+ &buf_id))) { -+ if (tx_params.prev_refill_gen != -+ idpf_queue_has(RFL_GEN_CHK, refillq)) -+ idpf_queue_change(RFL_GEN_CHK, refillq); -+ refillq->next_to_clean = tx_params.prev_refill_ntc; -+ -+ tx_q->next_to_use = tx_params.prev_ntu; -+ return idpf_tx_drop_skb(tx_q, skb); -+ } -+ tx_params.compl_tag = buf_id; - -- if (idpf_queue_has(FLOW_SCH_EN, tx_q)) { - tx_params.dtype = IDPF_TX_DESC_DTYPE_FLEX_FLOW_SCHE; - tx_params.eop_cmd = IDPF_TXD_FLEX_FLOW_CMD_EOP; - /* Set the RE bit to catch any packets that may have not been -@@ -2928,6 +2977,8 @@ static netdev_tx_t idpf_tx_splitq_frame( - tx_params.offload.td_cmd |= IDPF_TXD_FLEX_FLOW_CMD_CS_EN; - - } else { -+ buf_id = tx_q->next_to_use; -+ - tx_params.dtype = IDPF_TX_DESC_DTYPE_FLEX_L2TAG1_L2TAG2; - tx_params.eop_cmd = IDPF_TXD_LAST_DESC_CMD; - -@@ -2935,6 +2986,18 @@ static netdev_tx_t idpf_tx_splitq_frame( - tx_params.offload.td_cmd |= IDPF_TX_FLEX_DESC_CMD_CS_EN; - } - -+ first = &tx_q->tx_buf[buf_id]; -+ first->skb = skb; -+ -+ if (tso) { -+ first->packets = tx_params.offload.tso_segs; -+ first->bytes = skb->len + -+ ((first->packets - 1) * tx_params.offload.tso_hdr_len); -+ } else { -+ first->packets = 1; -+ first->bytes = max_t(unsigned int, skb->len, ETH_ZLEN); -+ } -+ - idpf_tx_splitq_map(tx_q, &tx_params, first); - - return NETDEV_TX_OK; -@@ -3464,7 +3527,7 @@ payload: - skip_data: - rx_buf->page = NULL; - -- idpf_rx_post_buf_refill(refillq, buf_id); -+ idpf_post_buf_refill(refillq, buf_id); - IDPF_RX_BUMP_NTC(rxq, ntc); - - /* skip if it is non EOP desc */ -@@ -3572,10 +3635,10 @@ static void idpf_rx_clean_refillq(struct - bool failure; - - if (idpf_queue_has(RFL_GEN_CHK, refillq) != -- !!(refill_desc & IDPF_RX_BI_GEN_M)) -+ !!(refill_desc & IDPF_RFL_BI_GEN_M)) - break; - -- buf_id = FIELD_GET(IDPF_RX_BI_BUFID_M, refill_desc); -+ buf_id = FIELD_GET(IDPF_RFL_BI_BUFID_M, refill_desc); - failure = idpf_rx_update_bufq_desc(bufq, buf_id, buf_desc); - if (failure) - break; -@@ -4349,9 +4412,13 @@ static void idpf_vport_intr_napi_add_all - int idpf_vport_intr_alloc(struct idpf_vport *vport) - { - u16 txqs_per_vector, rxqs_per_vector, bufqs_per_vector; -+ struct idpf_vport_user_config_data *user_config; - struct idpf_q_vector *q_vector; -+ struct idpf_q_coalesce *q_coal; - u32 complqs_per_vector, v_idx; -+ u16 idx = vport->idx; - -+ user_config = &vport->adapter->vport_config[idx]->user_config; - vport->q_vectors = kcalloc(vport->num_q_vectors, - sizeof(struct idpf_q_vector), GFP_KERNEL); - if (!vport->q_vectors) -@@ -4369,14 +4436,15 @@ int idpf_vport_intr_alloc(struct idpf_vp - - for (v_idx = 0; v_idx < vport->num_q_vectors; v_idx++) { - q_vector = &vport->q_vectors[v_idx]; -+ q_coal = &user_config->q_coalesce[v_idx]; - q_vector->vport = vport; - -- q_vector->tx_itr_value = IDPF_ITR_TX_DEF; -- q_vector->tx_intr_mode = IDPF_ITR_DYNAMIC; -+ q_vector->tx_itr_value = q_coal->tx_coalesce_usecs; -+ q_vector->tx_intr_mode = q_coal->tx_intr_mode; - q_vector->tx_itr_idx = VIRTCHNL2_ITR_IDX_1; - -- q_vector->rx_itr_value = IDPF_ITR_RX_DEF; -- q_vector->rx_intr_mode = IDPF_ITR_DYNAMIC; -+ q_vector->rx_itr_value = q_coal->rx_coalesce_usecs; -+ q_vector->rx_intr_mode = q_coal->rx_intr_mode; - q_vector->rx_itr_idx = VIRTCHNL2_ITR_IDX_0; - - q_vector->tx = kcalloc(txqs_per_vector, sizeof(*q_vector->tx), -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/idpf/idpf_txrx.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/idpf/idpf_txrx.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/idpf/idpf_txrx.h 2025-10-22 13:53:23.339328532 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/idpf/idpf_txrx.h 2025-10-22 13:53:56.563168910 -0400 -@@ -107,8 +107,8 @@ do { \ - */ - #define IDPF_TX_SPLITQ_RE_MIN_GAP 64 - --#define IDPF_RX_BI_GEN_M BIT(16) --#define IDPF_RX_BI_BUFID_M GENMASK(15, 0) -+#define IDPF_RFL_BI_GEN_M BIT(16) -+#define IDPF_RFL_BI_BUFID_M GENMASK(15, 0) - - #define IDPF_RXD_EOF_SPLITQ VIRTCHNL2_RX_FLEX_DESC_ADV_STATUS0_EOF_M - #define IDPF_RXD_EOF_SINGLEQ VIRTCHNL2_RX_BASE_DESC_STATUS_EOF_M -@@ -136,6 +136,8 @@ do { \ - ((++(txq)->compl_tag_cur_gen) >= (txq)->compl_tag_gen_max ? \ - 0 : (txq)->compl_tag_cur_gen) - -+#define IDPF_TXBUF_NULL U32_MAX -+ - #define IDPF_TXD_LAST_DESC_CMD (IDPF_TX_DESC_CMD_EOP | IDPF_TX_DESC_CMD_RS) - - #define IDPF_TX_FLAGS_TSO BIT(0) -@@ -195,6 +197,9 @@ struct idpf_tx_offload_params { - * @compl_tag: Associated tag for completion - * @td_tag: Descriptor tunneling tag - * @offload: Offload parameters -+ * @prev_ntu: stored TxQ next_to_use in case of rollback -+ * @prev_refill_ntc: stored refillq next_to_clean in case of packet rollback -+ * @prev_refill_gen: stored refillq generation bit in case of packet rollback - */ - struct idpf_tx_splitq_params { - enum idpf_tx_desc_dtype_value dtype; -@@ -205,6 +210,10 @@ struct idpf_tx_splitq_params { - }; - - struct idpf_tx_offload_params offload; -+ -+ u16 prev_ntu; -+ u16 prev_refill_ntc; -+ bool prev_refill_gen; - }; - - enum idpf_tx_ctx_desc_eipt_offload { -@@ -621,6 +630,7 @@ libeth_cacheline_set_assert(struct idpf_ - * @cleaned_pkts: Number of packets cleaned for the above said case - * @tx_max_bufs: Max buffers that can be transmitted with scatter-gather - * @stash: Tx buffer stash for Flow-based scheduling mode -+ * @refillq: Pointer to refill queue - * @compl_tag_bufid_m: Completion tag buffer id mask - * @compl_tag_cur_gen: Used to keep track of current completion tag generation - * @compl_tag_gen_max: To determine when compl_tag_cur_gen should be reset -@@ -632,6 +642,7 @@ libeth_cacheline_set_assert(struct idpf_ - * @size: Length of descriptor ring in bytes - * @dma: Physical address of ring - * @q_vector: Backreference to associated vector -+ * @buf_pool_size: Total number of idpf_tx_buf - */ - struct idpf_tx_queue { - __cacheline_group_begin_aligned(read_mostly); -@@ -670,6 +681,7 @@ struct idpf_tx_queue { - - u16 tx_max_bufs; - struct idpf_txq_stash *stash; -+ struct idpf_sw_queue *refillq; - - u16 compl_tag_bufid_m; - u16 compl_tag_cur_gen; -@@ -688,11 +700,12 @@ struct idpf_tx_queue { - dma_addr_t dma; - - struct idpf_q_vector *q_vector; -+ u32 buf_pool_size; - __cacheline_group_end_aligned(cold); - }; - libeth_cacheline_set_assert(struct idpf_tx_queue, 64, -- 112 + sizeof(struct u64_stats_sync), -- 24); -+ 120 + sizeof(struct u64_stats_sync), -+ 32); - - /** - * struct idpf_buf_queue - software structure representing a buffer queue -@@ -1010,6 +1023,17 @@ static inline void idpf_vport_intr_set_w - reg->dyn_ctl); - } - -+/** -+ * idpf_tx_splitq_get_free_bufs - get number of free buf_ids in refillq -+ * @refillq: pointer to refillq containing buf_ids -+ */ -+static inline u32 idpf_tx_splitq_get_free_bufs(struct idpf_sw_queue *refillq) -+{ -+ return (refillq->next_to_use > refillq->next_to_clean ? -+ 0 : refillq->desc_count) + -+ refillq->next_to_use - refillq->next_to_clean - 1; -+} -+ - int idpf_vport_singleq_napi_poll(struct napi_struct *napi, int budget); - void idpf_vport_init_num_qs(struct idpf_vport *vport, - struct virtchnl2_create_vport *vport_msg); -@@ -1037,10 +1061,8 @@ void idpf_tx_buf_hw_update(struct idpf_t - bool xmit_more); - unsigned int idpf_size_to_txd_count(unsigned int size); - netdev_tx_t idpf_tx_drop_skb(struct idpf_tx_queue *tx_q, struct sk_buff *skb); --void idpf_tx_dma_map_error(struct idpf_tx_queue *txq, struct sk_buff *skb, -- struct idpf_tx_buf *first, u16 ring_idx); --unsigned int idpf_tx_desc_count_required(struct idpf_tx_queue *txq, -- struct sk_buff *skb); -+unsigned int idpf_tx_res_count_required(struct idpf_tx_queue *txq, -+ struct sk_buff *skb, u32 *buf_count); - void idpf_tx_timeout(struct net_device *netdev, unsigned int txqueue); - netdev_tx_t idpf_tx_singleq_frame(struct sk_buff *skb, - struct idpf_tx_queue *tx_q); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c 2025-10-22 13:53:23.339328532 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c 2025-10-22 13:53:56.567168891 -0400 -@@ -3507,6 +3507,16 @@ u32 idpf_get_vport_id(struct idpf_vport - return le32_to_cpu(vport_msg->vport_id); - } - -+static void idpf_set_mac_type(struct idpf_vport *vport, -+ struct virtchnl2_mac_addr *mac_addr) -+{ -+ bool is_primary; -+ -+ is_primary = ether_addr_equal(vport->default_mac_addr, mac_addr->addr); -+ mac_addr->type = is_primary ? VIRTCHNL2_MAC_ADDR_PRIMARY : -+ VIRTCHNL2_MAC_ADDR_EXTRA; -+} -+ - /** - * idpf_mac_filter_async_handler - Async callback for mac filters - * @adapter: private data struct -@@ -3636,6 +3646,7 @@ int idpf_add_del_mac_filters(struct idpf - list) { - if (add && f->add) { - ether_addr_copy(mac_addr[i].addr, f->macaddr); -+ idpf_set_mac_type(vport, &mac_addr[i]); - i++; - f->add = false; - if (i == total_filters) -@@ -3643,6 +3654,7 @@ int idpf_add_del_mac_filters(struct idpf - } - if (!add && f->remove) { - ether_addr_copy(mac_addr[i].addr, f->macaddr); -+ idpf_set_mac_type(vport, &mac_addr[i]); - i++; - f->remove = false; - if (i == total_filters) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/igb/igb_ethtool.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/igb/igb_ethtool.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/igb/igb_ethtool.c 2025-10-22 13:53:23.339328532 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/igb/igb_ethtool.c 2025-10-22 13:53:56.567168891 -0400 -@@ -2081,11 +2081,8 @@ static void igb_diag_test(struct net_dev - } else { - dev_info(&adapter->pdev->dev, "online testing starting\n"); - -- /* PHY is powered down when interface is down */ -- if (if_running && igb_link_test(adapter, &data[TEST_LINK])) -+ if (igb_link_test(adapter, &data[TEST_LINK])) - eth_test->flags |= ETH_TEST_FL_FAILED; -- else -- data[TEST_LINK] = 0; - - /* Online tests aren't run; pass by default */ - data[TEST_REG] = 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/igb/igb_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/igb/igb_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/igb/igb_main.c 2025-10-22 13:53:23.339328532 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/igb/igb_main.c 2025-10-22 13:53:56.567168891 -0400 -@@ -4451,8 +4451,7 @@ int igb_setup_rx_resources(struct igb_ri - if (xdp_rxq_info_is_reg(&rx_ring->xdp_rxq)) - xdp_rxq_info_unreg(&rx_ring->xdp_rxq); - res = xdp_rxq_info_reg(&rx_ring->xdp_rxq, rx_ring->netdev, -- rx_ring->queue_index, -- rx_ring->q_vector->napi.napi_id); -+ rx_ring->queue_index, 0); - if (res < 0) { - dev_err(dev, "Failed to register xdp_rxq index %u\n", - rx_ring->queue_index); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/igb/igb_xsk.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/igb/igb_xsk.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/igb/igb_xsk.c 2025-10-22 13:53:23.339328532 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/igb/igb_xsk.c 2025-10-22 13:53:56.567168891 -0400 -@@ -482,7 +482,7 @@ bool igb_xmit_zc(struct igb_ring *tx_rin - if (!nb_pkts) - return true; - -- while (nb_pkts-- > 0) { -+ for (; i < nb_pkts; i++) { - dma = xsk_buff_raw_get_dma(xsk_pool, descs[i].addr); - xsk_buff_raw_dma_sync_for_device(xsk_pool, dma, descs[i].len); - -@@ -512,7 +512,6 @@ bool igb_xmit_zc(struct igb_ring *tx_rin - - total_bytes += descs[i].len; - -- i++; - tx_ring->next_to_use++; - tx_buffer_info->next_to_watch = tx_desc; - if (tx_ring->next_to_use == tx_ring->count) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/igc/igc.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/igc/igc.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/igc/igc.h 2025-10-22 13:53:23.339328532 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/igc/igc.h 2025-10-22 13:53:56.567168891 -0400 -@@ -343,6 +343,7 @@ struct igc_adapter { - /* LEDs */ - struct mutex led_mutex; - struct igc_led_classdev *leds; -+ bool leds_available; - }; - - void igc_up(struct igc_adapter *adapter); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/igc/igc_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/igc/igc_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/igc/igc_main.c 2025-10-22 13:53:23.339328532 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/igc/igc_main.c 2025-10-22 13:53:56.567168891 -0400 -@@ -7115,6 +7115,17 @@ static int igc_probe(struct pci_dev *pde - adapter->port_num = hw->bus.func; - adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); - -+ /* PCI config space info */ -+ hw->vendor_id = pdev->vendor; -+ hw->device_id = pdev->device; -+ hw->revision_id = pdev->revision; -+ hw->subsystem_vendor_id = pdev->subsystem_vendor; -+ hw->subsystem_device_id = pdev->subsystem_device; -+ -+ /* Disable ASPM L1.2 on I226 devices to avoid packet loss */ -+ if (igc_is_device_id_i226(hw)) -+ pci_disable_link_state(pdev, PCIE_LINK_STATE_L1_2); -+ - err = pci_save_state(pdev); - if (err) - goto err_ioremap; -@@ -7137,13 +7148,6 @@ static int igc_probe(struct pci_dev *pde - netdev->mem_start = pci_resource_start(pdev, 0); - netdev->mem_end = pci_resource_end(pdev, 0); - -- /* PCI config space info */ -- hw->vendor_id = pdev->vendor; -- hw->device_id = pdev->device; -- hw->revision_id = pdev->revision; -- hw->subsystem_vendor_id = pdev->subsystem_vendor; -- hw->subsystem_device_id = pdev->subsystem_device; -- - /* Copy the default MAC and PHY function pointers */ - memcpy(&hw->mac.ops, ei->mac_ops, sizeof(hw->mac.ops)); - memcpy(&hw->phy.ops, ei->phy_ops, sizeof(hw->phy.ops)); -@@ -7297,8 +7301,14 @@ static int igc_probe(struct pci_dev *pde - - if (IS_ENABLED(CONFIG_IGC_LEDS)) { - err = igc_led_setup(adapter); -- if (err) -- goto err_register; -+ if (err) { -+ netdev_warn_once(netdev, -+ "LED init failed (%d); continuing without LED support\n", -+ err); -+ adapter->leds_available = false; -+ } else { -+ adapter->leds_available = true; -+ } - } - - return 0; -@@ -7354,7 +7364,7 @@ static void igc_remove(struct pci_dev *p - cancel_work_sync(&adapter->watchdog_task); - hrtimer_cancel(&adapter->hrtimer); - -- if (IS_ENABLED(CONFIG_IGC_LEDS)) -+ if (IS_ENABLED(CONFIG_IGC_LEDS) && adapter->leds_available) - igc_led_free(adapter); - - /* Release control of h/w to f/w. If f/w is AMT enabled, this -@@ -7500,6 +7510,9 @@ static int __igc_resume(struct device *d - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - -+ if (igc_is_device_id_i226(hw)) -+ pci_disable_link_state(pdev, PCIE_LINK_STATE_L1_2); -+ - if (igc_init_interrupt_scheme(adapter, true)) { - netdev_err(netdev, "Unable to allocate memory for queues\n"); - return -ENOMEM; -@@ -7625,6 +7638,9 @@ static pci_ers_result_t igc_io_slot_rese - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - -+ if (igc_is_device_id_i226(hw)) -+ pci_disable_link_state_locked(pdev, PCIE_LINK_STATE_L1_2); -+ - /* In case of PCI error, adapter loses its HW address - * so we should re-assign it here. - */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ixgbe/devlink/devlink.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ixgbe/devlink/devlink.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ixgbe/devlink/devlink.c 2025-10-22 13:53:23.339328532 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ixgbe/devlink/devlink.c 2025-10-22 13:53:56.567168891 -0400 -@@ -543,6 +543,7 @@ int ixgbe_devlink_register_port(struct i - - attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; - attrs.phys.port_number = adapter->hw.bus.func; -+ attrs.no_phys_port_name = 1; - ixgbe_devlink_set_switch_id(adapter, &attrs.switch_id); - - devlink_port_attrs_set(devlink_port, &attrs); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c 2025-10-22 13:53:23.339328532 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c 2025-10-22 13:53:56.567168891 -0400 -@@ -3123,7 +3123,7 @@ static int ixgbe_get_orom_ver_info(struc - if (err) - return err; - -- combo_ver = le32_to_cpu(civd.combo_ver); -+ combo_ver = get_unaligned_le32(&civd.combo_ver); - - orom->major = (u8)FIELD_GET(IXGBE_OROM_VER_MASK, combo_ver); - orom->patch = (u8)FIELD_GET(IXGBE_OROM_VER_PATCH_MASK, combo_ver); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c 2025-10-22 13:53:23.339328532 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c 2025-10-22 13:53:56.567168891 -0400 -@@ -3565,13 +3565,13 @@ ixgbe_get_eee_fw(struct ixgbe_adapter *a - - for (i = 0; i < ARRAY_SIZE(ixgbe_ls_map); ++i) { - if (hw->phy.eee_speeds_supported & ixgbe_ls_map[i].mac_speed) -- linkmode_set_bit(ixgbe_lp_map[i].link_mode, -+ linkmode_set_bit(ixgbe_ls_map[i].link_mode, - edata->supported); - } - - for (i = 0; i < ARRAY_SIZE(ixgbe_ls_map); ++i) { - if (hw->phy.eee_speeds_advertised & ixgbe_ls_map[i].mac_speed) -- linkmode_set_bit(ixgbe_lp_map[i].link_mode, -+ linkmode_set_bit(ixgbe_ls_map[i].link_mode, - edata->advertised); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ixgbe/ixgbe.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ixgbe/ixgbe.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ixgbe/ixgbe.h 2025-10-22 13:53:23.339328532 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ixgbe/ixgbe.h 2025-10-22 13:53:56.567168891 -0400 -@@ -507,9 +507,10 @@ struct ixgbe_q_vector { - struct ixgbe_ring_container rx, tx; - - struct napi_struct napi; -+ struct rcu_head rcu; /* to avoid race with update stats on free */ -+ - cpumask_t affinity_mask; - int numa_node; -- struct rcu_head rcu; /* to avoid race with update stats on free */ - char name[IFNAMSIZ + 9]; - - /* for dynamic allocation of rings associated with this q_vector */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c 2025-10-22 13:53:23.339328532 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c 2025-10-22 13:53:56.567168891 -0400 -@@ -6801,6 +6801,13 @@ static int ixgbe_sw_init(struct ixgbe_ad - break; - } - -+ /* Make sure the SWFW semaphore is in a valid state */ -+ if (hw->mac.ops.init_swfw_sync) -+ hw->mac.ops.init_swfw_sync(hw); -+ -+ if (hw->mac.type == ixgbe_mac_e610) -+ mutex_init(&hw->aci.lock); -+ - #ifdef IXGBE_FCOE - /* FCoE support exists, always init the FCoE lock */ - spin_lock_init(&adapter->fcoe.lock); -@@ -11474,10 +11481,6 @@ static int ixgbe_probe(struct pci_dev *p - if (err) - goto err_sw_init; - -- /* Make sure the SWFW semaphore is in a valid state */ -- if (hw->mac.ops.init_swfw_sync) -- hw->mac.ops.init_swfw_sync(hw); -- - if (ixgbe_check_fw_error(adapter)) - return ixgbe_recovery_probe(adapter); - -@@ -11681,8 +11684,6 @@ skip_sriov: - ether_addr_copy(hw->mac.addr, hw->mac.perm_addr); - ixgbe_mac_set_default_filter(adapter); - -- if (hw->mac.type == ixgbe_mac_e610) -- mutex_init(&hw->aci.lock); - timer_setup(&adapter->service_timer, ixgbe_service_timer, 0); - - if (ixgbe_removed(hw->hw_addr)) { -@@ -11838,9 +11839,9 @@ err_register: - devl_unlock(adapter->devlink); - ixgbe_release_hw_control(adapter); - ixgbe_clear_interrupt_scheme(adapter); -+err_sw_init: - if (hw->mac.type == ixgbe_mac_e610) - mutex_destroy(&adapter->hw.aci.lock); --err_sw_init: - ixgbe_disable_sriov(adapter); - adapter->flags2 &= ~IXGBE_FLAG2_SEARCH_FOR_SFP; - iounmap(adapter->io_addr); -@@ -11891,10 +11892,8 @@ static void ixgbe_remove(struct pci_dev - set_bit(__IXGBE_REMOVING, &adapter->state); - cancel_work_sync(&adapter->service_task); - -- if (adapter->hw.mac.type == ixgbe_mac_e610) { -+ if (adapter->hw.mac.type == ixgbe_mac_e610) - ixgbe_disable_link_status_events(adapter); -- mutex_destroy(&adapter->hw.aci.lock); -- } - - if (adapter->mii_bus) - mdiobus_unregister(adapter->mii_bus); -@@ -11954,6 +11953,9 @@ static void ixgbe_remove(struct pci_dev - disable_dev = !test_and_set_bit(__IXGBE_DISABLED, &adapter->state); - free_netdev(netdev); - -+ if (adapter->hw.mac.type == ixgbe_mac_e610) -+ mutex_destroy(&adapter->hw.aci.lock); -+ - if (disable_dev) - pci_disable_device(pdev); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h 2025-10-22 13:53:56.567168891 -0400 -@@ -1150,7 +1150,7 @@ struct ixgbe_orom_civd_info { - __le32 combo_ver; /* Combo Image Version number */ - u8 combo_name_len; /* Length of the unicode combo image version string, max of 32 */ - __le16 combo_name[32]; /* Unicode string representing the Combo Image version */ --}; -+} __packed; - - /* Function specific capabilities */ - struct ixgbe_hw_func_caps { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c 2025-10-22 13:53:56.567168891 -0400 -@@ -398,7 +398,7 @@ static bool ixgbe_xmit_zc(struct ixgbe_r - dma_addr_t dma; - u32 cmd_type; - -- while (budget-- > 0) { -+ while (likely(budget)) { - if (unlikely(!ixgbe_desc_unused(xdp_ring))) { - work_done = false; - break; -@@ -433,6 +433,8 @@ static bool ixgbe_xmit_zc(struct ixgbe_r - xdp_ring->next_to_use++; - if (xdp_ring->next_to_use == xdp_ring->count) - xdp_ring->next_to_use = 0; -+ -+ budget--; - } - - if (tx_desc) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeon_ep/octep_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeon_ep/octep_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeon_ep/octep_main.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeon_ep/octep_main.c 2025-10-22 13:53:56.567168891 -0400 -@@ -1124,11 +1124,24 @@ static int octep_set_features(struct net - return err; - } - -+static bool octep_is_vf_valid(struct octep_device *oct, int vf) -+{ -+ if (vf >= CFG_GET_ACTIVE_VFS(oct->conf)) { -+ netdev_err(oct->netdev, "Invalid VF ID %d\n", vf); -+ return false; -+ } -+ -+ return true; -+} -+ - static int octep_get_vf_config(struct net_device *dev, int vf, - struct ifla_vf_info *ivi) - { - struct octep_device *oct = netdev_priv(dev); - -+ if (!octep_is_vf_valid(oct, vf)) -+ return -EINVAL; -+ - ivi->vf = vf; - ether_addr_copy(ivi->mac, oct->vf_info[vf].mac_addr); - ivi->spoofchk = true; -@@ -1143,6 +1156,9 @@ static int octep_set_vf_mac(struct net_d - struct octep_device *oct = netdev_priv(dev); - int err; - -+ if (!octep_is_vf_valid(oct, vf)) -+ return -EINVAL; -+ - if (!is_valid_ether_addr(mac)) { - dev_err(&oct->pdev->dev, "Invalid MAC Address %pM\n", mac); - return -EADDRNOTAVAIL; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c 2025-10-22 13:53:56.567168891 -0400 -@@ -196,6 +196,7 @@ static void octep_pfvf_get_mac_addr(stru - vf_id); - return; - } -+ ether_addr_copy(oct->vf_info[vf_id].mac_addr, rsp->s_set_mac.mac_addr); - rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; - } - -@@ -205,6 +206,8 @@ static void octep_pfvf_dev_remove(struct - { - int err; - -+ /* Reset VF-specific information maintained by the PF */ -+ memset(&oct->vf_info[vf_id], 0, sizeof(struct octep_pfvf_info)); - err = octep_ctrl_net_dev_remove(oct, vf_id); - if (err) { - rsp->s.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/cgx.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/cgx.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/cgx.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/cgx.c 2025-10-22 13:53:56.571168871 -0400 -@@ -21,8 +21,7 @@ - #include "rvu.h" - #include "lmac_common.h" - --#define DRV_NAME "Marvell-CGX/RPM" --#define DRV_STRING "Marvell CGX/RPM Driver" -+#define DRV_NAME "Marvell-CGX-RPM" - - #define CGX_RX_STAT_GLOBAL_INDEX 9 - -@@ -1940,6 +1939,13 @@ static int cgx_probe(struct pci_dev *pde - goto err_release_regions; - } - -+ if (!is_cn20k(pdev) && -+ !is_cgx_mapped_to_nix(pdev->subsystem_device, cgx->cgx_id)) { -+ dev_notice(dev, "CGX %d not mapped to NIX, skipping probe\n", -+ cgx->cgx_id); -+ goto err_release_regions; -+ } -+ - cgx->lmac_count = cgx->mac_ops->get_nr_lmacs(cgx); - if (!cgx->lmac_count) { - dev_notice(dev, "CGX %d LMAC count is zero, skipping probe\n", cgx->cgx_id); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/mcs_rvu_if.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/mcs_rvu_if.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/mcs_rvu_if.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/mcs_rvu_if.c 2025-10-22 13:53:56.571168871 -0400 -@@ -97,7 +97,7 @@ int mcs_add_intr_wq_entry(struct mcs *mc - if (pcifunc & RVU_PFVF_FUNC_MASK) - pfvf = &mcs->vf[rvu_get_hwvf(rvu, pcifunc)]; - else -- pfvf = &mcs->pf[rvu_get_pf(pcifunc)]; -+ pfvf = &mcs->pf[rvu_get_pf(rvu->pdev, pcifunc)]; - - event->intr_mask &= pfvf->intr_mask; - -@@ -123,7 +123,7 @@ static int mcs_notify_pfvf(struct mcs_in - struct mcs_intr_info *req; - int pf; - -- pf = rvu_get_pf(event->pcifunc); -+ pf = rvu_get_pf(rvu->pdev, event->pcifunc); - - mutex_lock(&rvu->mbox_lock); - -@@ -193,7 +193,7 @@ int rvu_mbox_handler_mcs_intr_cfg(struct - if (pcifunc & RVU_PFVF_FUNC_MASK) - pfvf = &mcs->vf[rvu_get_hwvf(rvu, pcifunc)]; - else -- pfvf = &mcs->pf[rvu_get_pf(pcifunc)]; -+ pfvf = &mcs->pf[rvu_get_pf(rvu->pdev, pcifunc)]; - - mcs->pf_map[0] = pcifunc; - pfvf->intr_mask = req->intr_mask; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu.c 2025-10-22 13:53:56.571168871 -0400 -@@ -294,7 +294,7 @@ int rvu_get_blkaddr(struct rvu *rvu, int - devnum = rvu_get_hwvf(rvu, pcifunc); - } else { - is_pf = true; -- devnum = rvu_get_pf(pcifunc); -+ devnum = rvu_get_pf(rvu->pdev, pcifunc); - } - - /* Check if the 'pcifunc' has a NIX LF from 'BLKADDR_NIX0' or -@@ -359,7 +359,7 @@ static void rvu_update_rsrc_map(struct r - devnum = rvu_get_hwvf(rvu, pcifunc); - } else { - is_pf = true; -- devnum = rvu_get_pf(pcifunc); -+ devnum = rvu_get_pf(rvu->pdev, pcifunc); - } - - block->fn_map[lf] = attach ? pcifunc : 0; -@@ -400,11 +400,6 @@ static void rvu_update_rsrc_map(struct r - rvu_write64(rvu, BLKADDR_RVUM, reg | (devnum << 16), num_lfs); - } - --inline int rvu_get_pf(u16 pcifunc) --{ -- return (pcifunc >> RVU_PFVF_PF_SHIFT) & RVU_PFVF_PF_MASK; --} -- - void rvu_get_pf_numvfs(struct rvu *rvu, int pf, int *numvfs, int *hwvf) - { - u64 cfg; -@@ -422,7 +417,7 @@ int rvu_get_hwvf(struct rvu *rvu, int pc - int pf, func; - u64 cfg; - -- pf = rvu_get_pf(pcifunc); -+ pf = rvu_get_pf(rvu->pdev, pcifunc); - func = pcifunc & RVU_PFVF_FUNC_MASK; - - /* Get first HWVF attached to this PF */ -@@ -437,7 +432,7 @@ struct rvu_pfvf *rvu_get_pfvf(struct rvu - if (pcifunc & RVU_PFVF_FUNC_MASK) - return &rvu->hwvf[rvu_get_hwvf(rvu, pcifunc)]; - else -- return &rvu->pf[rvu_get_pf(pcifunc)]; -+ return &rvu->pf[rvu_get_pf(rvu->pdev, pcifunc)]; - } - - static bool is_pf_func_valid(struct rvu *rvu, u16 pcifunc) -@@ -445,7 +440,7 @@ static bool is_pf_func_valid(struct rvu - int pf, vf, nvfs; - u64 cfg; - -- pf = rvu_get_pf(pcifunc); -+ pf = rvu_get_pf(rvu->pdev, pcifunc); - if (pf >= rvu->hw->total_pfs) - return false; - -@@ -1487,7 +1482,7 @@ int rvu_get_nix_blkaddr(struct rvu *rvu, - pf = rvu_get_pfvf(rvu, pcifunc & ~RVU_PFVF_FUNC_MASK); - - /* All CGX mapped PFs are set with assigned NIX block during init */ -- if (is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc))) { -+ if (is_pf_cgxmapped(rvu, rvu_get_pf(rvu->pdev, pcifunc))) { - blkaddr = pf->nix_blkaddr; - } else if (is_lbk_vf(rvu, pcifunc)) { - vf = pcifunc - 1; -@@ -1501,7 +1496,7 @@ int rvu_get_nix_blkaddr(struct rvu *rvu, - } - - /* if SDP1 then the blkaddr is NIX1 */ -- if (is_sdp_pfvf(pcifunc) && pf->sdp_info->node_id == 1) -+ if (is_sdp_pfvf(rvu, pcifunc) && pf->sdp_info->node_id == 1) - blkaddr = BLKADDR_NIX1; - - switch (blkaddr) { -@@ -2006,7 +2001,7 @@ int rvu_mbox_handler_vf_flr(struct rvu * - - vf = pcifunc & RVU_PFVF_FUNC_MASK; - cfg = rvu_read64(rvu, BLKADDR_RVUM, -- RVU_PRIV_PFX_CFG(rvu_get_pf(pcifunc))); -+ RVU_PRIV_PFX_CFG(rvu_get_pf(rvu->pdev, pcifunc))); - numvfs = (cfg >> 12) & 0xFF; - - if (vf && vf <= numvfs) -@@ -2229,9 +2224,8 @@ static void __rvu_mbox_handler(struct rv - /* Set which PF/VF sent this message based on mbox IRQ */ - switch (type) { - case TYPE_AFPF: -- msg->pcifunc &= -- ~(RVU_PFVF_PF_MASK << RVU_PFVF_PF_SHIFT); -- msg->pcifunc |= (devid << RVU_PFVF_PF_SHIFT); -+ msg->pcifunc &= rvu_pcifunc_pf_mask(rvu->pdev); -+ msg->pcifunc |= rvu_make_pcifunc(rvu->pdev, devid, 0); - break; - case TYPE_AFVF: - msg->pcifunc &= -@@ -2249,7 +2243,7 @@ static void __rvu_mbox_handler(struct rv - if (msg->pcifunc & RVU_PFVF_FUNC_MASK) - dev_warn(rvu->dev, "Error %d when processing message %s (0x%x) from PF%d:VF%d\n", - err, otx2_mbox_id2name(msg->id), -- msg->id, rvu_get_pf(msg->pcifunc), -+ msg->id, rvu_get_pf(rvu->pdev, msg->pcifunc), - (msg->pcifunc & RVU_PFVF_FUNC_MASK) - 1); - else - dev_warn(rvu->dev, "Error %d when processing message %s (0x%x) from PF%d\n", -@@ -2773,7 +2767,7 @@ static void rvu_flr_handler(struct work_ - - cfg = rvu_read64(rvu, BLKADDR_RVUM, RVU_PRIV_PFX_CFG(pf)); - numvfs = (cfg >> 12) & 0xFF; -- pcifunc = pf << RVU_PFVF_PF_SHIFT; -+ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, 0); - - for (vf = 0; vf < numvfs; vf++) - __rvu_flr_handler(rvu, (pcifunc | (vf + 1))); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c 2025-10-22 13:53:56.571168871 -0400 -@@ -457,7 +457,7 @@ int rvu_cgx_exit(struct rvu *rvu) - inline bool is_cgx_config_permitted(struct rvu *rvu, u16 pcifunc) - { - if ((pcifunc & RVU_PFVF_FUNC_MASK) || -- !is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc))) -+ !is_pf_cgxmapped(rvu, rvu_get_pf(rvu->pdev, pcifunc))) - return false; - return true; - } -@@ -484,7 +484,7 @@ void rvu_cgx_enadis_rx_bp(struct rvu *rv - - int rvu_cgx_config_rxtx(struct rvu *rvu, u16 pcifunc, bool start) - { -- int pf = rvu_get_pf(pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, pcifunc); - struct mac_ops *mac_ops; - u8 cgx_id, lmac_id; - void *cgxd; -@@ -501,7 +501,7 @@ int rvu_cgx_config_rxtx(struct rvu *rvu, - - int rvu_cgx_tx_enable(struct rvu *rvu, u16 pcifunc, bool enable) - { -- int pf = rvu_get_pf(pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, pcifunc); - struct mac_ops *mac_ops; - u8 cgx_id, lmac_id; - void *cgxd; -@@ -526,7 +526,7 @@ int rvu_cgx_config_tx(void *cgxd, int lm - - void rvu_cgx_disable_dmac_entries(struct rvu *rvu, u16 pcifunc) - { -- int pf = rvu_get_pf(pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, pcifunc); - int i = 0, lmac_count = 0; - struct mac_ops *mac_ops; - u8 max_dmac_filters; -@@ -577,7 +577,7 @@ int rvu_mbox_handler_cgx_stop_rxtx(struc - static int rvu_lmac_get_stats(struct rvu *rvu, struct msg_req *req, - void *rsp) - { -- int pf = rvu_get_pf(req->hdr.pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - struct mac_ops *mac_ops; - int stat = 0, err = 0; - u64 tx_stat, rx_stat; -@@ -633,7 +633,7 @@ int rvu_mbox_handler_rpm_stats(struct rv - int rvu_mbox_handler_cgx_stats_rst(struct rvu *rvu, struct msg_req *req, - struct msg_rsp *rsp) - { -- int pf = rvu_get_pf(req->hdr.pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - struct rvu_pfvf *parent_pf; - struct mac_ops *mac_ops; - u8 cgx_idx, lmac; -@@ -663,7 +663,7 @@ int rvu_mbox_handler_cgx_fec_stats(struc - struct msg_req *req, - struct cgx_fec_stats_rsp *rsp) - { -- int pf = rvu_get_pf(req->hdr.pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - struct mac_ops *mac_ops; - u8 cgx_idx, lmac; - void *cgxd; -@@ -681,7 +681,7 @@ int rvu_mbox_handler_cgx_mac_addr_set(st - struct cgx_mac_addr_set_or_get *req, - struct cgx_mac_addr_set_or_get *rsp) - { -- int pf = rvu_get_pf(req->hdr.pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - u8 cgx_id, lmac_id; - - if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc)) -@@ -701,7 +701,7 @@ int rvu_mbox_handler_cgx_mac_addr_add(st - struct cgx_mac_addr_add_req *req, - struct cgx_mac_addr_add_rsp *rsp) - { -- int pf = rvu_get_pf(req->hdr.pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - u8 cgx_id, lmac_id; - int rc = 0; - -@@ -725,7 +725,7 @@ int rvu_mbox_handler_cgx_mac_addr_del(st - struct cgx_mac_addr_del_req *req, - struct msg_rsp *rsp) - { -- int pf = rvu_get_pf(req->hdr.pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - u8 cgx_id, lmac_id; - - if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc)) -@@ -743,7 +743,7 @@ int rvu_mbox_handler_cgx_mac_max_entries - struct cgx_max_dmac_entries_get_rsp - *rsp) - { -- int pf = rvu_get_pf(req->hdr.pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - u8 cgx_id, lmac_id; - - /* If msg is received from PFs(which are not mapped to CGX LMACs) -@@ -769,7 +769,7 @@ int rvu_mbox_handler_cgx_mac_addr_get(st - struct cgx_mac_addr_set_or_get *req, - struct cgx_mac_addr_set_or_get *rsp) - { -- int pf = rvu_get_pf(req->hdr.pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - u8 cgx_id, lmac_id; - int rc = 0; - u64 cfg; -@@ -790,7 +790,7 @@ int rvu_mbox_handler_cgx_promisc_enable( - struct msg_rsp *rsp) - { - u16 pcifunc = req->hdr.pcifunc; -- int pf = rvu_get_pf(pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, pcifunc); - u8 cgx_id, lmac_id; - - if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc)) -@@ -809,7 +809,7 @@ int rvu_mbox_handler_cgx_promisc_enable( - int rvu_mbox_handler_cgx_promisc_disable(struct rvu *rvu, struct msg_req *req, - struct msg_rsp *rsp) - { -- int pf = rvu_get_pf(req->hdr.pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - u8 cgx_id, lmac_id; - - if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc)) -@@ -828,7 +828,7 @@ int rvu_mbox_handler_cgx_promisc_disable - static int rvu_cgx_ptp_rx_cfg(struct rvu *rvu, u16 pcifunc, bool enable) - { - struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc); -- int pf = rvu_get_pf(pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, pcifunc); - struct mac_ops *mac_ops; - u8 cgx_id, lmac_id; - void *cgxd; -@@ -864,7 +864,7 @@ static int rvu_cgx_ptp_rx_cfg(struct rvu - int rvu_mbox_handler_cgx_ptp_rx_enable(struct rvu *rvu, struct msg_req *req, - struct msg_rsp *rsp) - { -- if (!is_pf_cgxmapped(rvu, rvu_get_pf(req->hdr.pcifunc))) -+ if (!is_pf_cgxmapped(rvu, rvu_get_pf(rvu->pdev, req->hdr.pcifunc))) - return -EPERM; - - return rvu_cgx_ptp_rx_cfg(rvu, req->hdr.pcifunc, true); -@@ -878,7 +878,7 @@ int rvu_mbox_handler_cgx_ptp_rx_disable( - - static int rvu_cgx_config_linkevents(struct rvu *rvu, u16 pcifunc, bool en) - { -- int pf = rvu_get_pf(pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, pcifunc); - u8 cgx_id, lmac_id; - - if (!is_cgx_config_permitted(rvu, pcifunc)) -@@ -917,7 +917,7 @@ int rvu_mbox_handler_cgx_get_linkinfo(st - u8 cgx_id, lmac_id; - int pf, err; - -- pf = rvu_get_pf(req->hdr.pcifunc); -+ pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - - if (!is_pf_cgxmapped(rvu, pf)) - return -ENODEV; -@@ -933,7 +933,7 @@ int rvu_mbox_handler_cgx_features_get(st - struct msg_req *req, - struct cgx_features_info_msg *rsp) - { -- int pf = rvu_get_pf(req->hdr.pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - u8 cgx_idx, lmac; - void *cgxd; - -@@ -975,7 +975,7 @@ u32 rvu_cgx_get_lmac_fifolen(struct rvu - - static int rvu_cgx_config_intlbk(struct rvu *rvu, u16 pcifunc, bool en) - { -- int pf = rvu_get_pf(pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, pcifunc); - struct mac_ops *mac_ops; - u8 cgx_id, lmac_id; - -@@ -1005,7 +1005,7 @@ int rvu_mbox_handler_cgx_intlbk_disable( - - int rvu_cgx_cfg_pause_frm(struct rvu *rvu, u16 pcifunc, u8 tx_pause, u8 rx_pause) - { -- int pf = rvu_get_pf(pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, pcifunc); - u8 rx_pfc = 0, tx_pfc = 0; - struct mac_ops *mac_ops; - u8 cgx_id, lmac_id; -@@ -1046,7 +1046,7 @@ int rvu_mbox_handler_cgx_cfg_pause_frm(s - struct cgx_pause_frm_cfg *req, - struct cgx_pause_frm_cfg *rsp) - { -- int pf = rvu_get_pf(req->hdr.pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - struct mac_ops *mac_ops; - u8 cgx_id, lmac_id; - int err = 0; -@@ -1073,7 +1073,7 @@ int rvu_mbox_handler_cgx_cfg_pause_frm(s - int rvu_mbox_handler_cgx_get_phy_fec_stats(struct rvu *rvu, struct msg_req *req, - struct msg_rsp *rsp) - { -- int pf = rvu_get_pf(req->hdr.pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - u8 cgx_id, lmac_id; - - if (!is_pf_cgxmapped(rvu, pf)) -@@ -1106,7 +1106,7 @@ int rvu_cgx_nix_cuml_stats(struct rvu *r - /* Assumes LF of a PF and all of its VF belongs to the same - * NIX block - */ -- pcifunc = pf << RVU_PFVF_PF_SHIFT; -+ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, 0); - blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc); - if (blkaddr < 0) - return 0; -@@ -1133,10 +1133,10 @@ int rvu_cgx_start_stop_io(struct rvu *rv - struct rvu_pfvf *parent_pf, *pfvf; - int cgx_users, err = 0; - -- if (!is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc))) -+ if (!is_pf_cgxmapped(rvu, rvu_get_pf(rvu->pdev, pcifunc))) - return 0; - -- parent_pf = &rvu->pf[rvu_get_pf(pcifunc)]; -+ parent_pf = &rvu->pf[rvu_get_pf(rvu->pdev, pcifunc)]; - pfvf = rvu_get_pfvf(rvu, pcifunc); - - mutex_lock(&rvu->cgx_cfg_lock); -@@ -1179,7 +1179,7 @@ int rvu_mbox_handler_cgx_set_fec_param(s - struct fec_mode *req, - struct fec_mode *rsp) - { -- int pf = rvu_get_pf(req->hdr.pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - u8 cgx_id, lmac_id; - - if (!is_pf_cgxmapped(rvu, pf)) -@@ -1195,7 +1195,7 @@ int rvu_mbox_handler_cgx_set_fec_param(s - int rvu_mbox_handler_cgx_get_aux_link_info(struct rvu *rvu, struct msg_req *req, - struct cgx_fw_data *rsp) - { -- int pf = rvu_get_pf(req->hdr.pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - u8 cgx_id, lmac_id; - - if (!rvu->fwdata) -@@ -1222,7 +1222,7 @@ int rvu_mbox_handler_cgx_set_link_mode(s - struct cgx_set_link_mode_req *req, - struct cgx_set_link_mode_rsp *rsp) - { -- int pf = rvu_get_pf(req->hdr.pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - u8 cgx_idx, lmac; - void *cgxd; - -@@ -1238,7 +1238,7 @@ int rvu_mbox_handler_cgx_set_link_mode(s - int rvu_mbox_handler_cgx_mac_addr_reset(struct rvu *rvu, struct cgx_mac_addr_reset_req *req, - struct msg_rsp *rsp) - { -- int pf = rvu_get_pf(req->hdr.pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - u8 cgx_id, lmac_id; - - if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc)) -@@ -1256,7 +1256,7 @@ int rvu_mbox_handler_cgx_mac_addr_update - struct cgx_mac_addr_update_req *req, - struct cgx_mac_addr_update_rsp *rsp) - { -- int pf = rvu_get_pf(req->hdr.pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - u8 cgx_id, lmac_id; - - if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc)) -@@ -1272,7 +1272,7 @@ int rvu_mbox_handler_cgx_mac_addr_update - int rvu_cgx_prio_flow_ctrl_cfg(struct rvu *rvu, u16 pcifunc, u8 tx_pause, - u8 rx_pause, u16 pfc_en) - { -- int pf = rvu_get_pf(pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, pcifunc); - u8 rx_8023 = 0, tx_8023 = 0; - struct mac_ops *mac_ops; - u8 cgx_id, lmac_id; -@@ -1310,7 +1310,7 @@ int rvu_mbox_handler_cgx_prio_flow_ctrl_ - struct cgx_pfc_cfg *req, - struct cgx_pfc_rsp *rsp) - { -- int pf = rvu_get_pf(req->hdr.pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - struct mac_ops *mac_ops; - u8 cgx_id, lmac_id; - void *cgxd; -@@ -1335,7 +1335,7 @@ int rvu_mbox_handler_cgx_prio_flow_ctrl_ - - void rvu_mac_reset(struct rvu *rvu, u16 pcifunc) - { -- int pf = rvu_get_pf(pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, pcifunc); - struct mac_ops *mac_ops; - struct cgx *cgxd; - u8 cgx, lmac; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_cn10k.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_cn10k.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_cn10k.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_cn10k.c 2025-10-22 13:53:56.571168871 -0400 -@@ -66,7 +66,7 @@ static int lmtst_map_table_ops(struct rv - #define LMT_MAP_TBL_W1_OFF 8 - static u32 rvu_get_lmtst_tbl_index(struct rvu *rvu, u16 pcifunc) - { -- return ((rvu_get_pf(pcifunc) * LMT_MAX_VFS) + -+ return ((rvu_get_pf(rvu->pdev, pcifunc) * LMT_MAX_VFS) + - (pcifunc & RVU_PFVF_FUNC_MASK)) * LMT_MAPTBL_ENTRY_SIZE; - } - -@@ -83,7 +83,7 @@ static int rvu_get_lmtaddr(struct rvu *r - - mutex_lock(&rvu->rsrc_lock); - rvu_write64(rvu, BLKADDR_RVUM, RVU_AF_SMMU_ADDR_REQ, iova); -- pf = rvu_get_pf(pcifunc) & RVU_PFVF_PF_MASK; -+ pf = rvu_get_pf(rvu->pdev, pcifunc) & RVU_OTX2_PFVF_PF_MASK; - val = BIT_ULL(63) | BIT_ULL(14) | BIT_ULL(13) | pf << 8 | - ((pcifunc & RVU_PFVF_FUNC_MASK) & 0xFF); - rvu_write64(rvu, BLKADDR_RVUM, RVU_AF_SMMU_TXN_REQ, val); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_cpt.c 2025-10-22 13:53:56.571168871 -0400 -@@ -410,7 +410,7 @@ static bool is_cpt_pf(struct rvu *rvu, u - { - int cpt_pf_num = rvu->cpt_pf_num; - -- if (rvu_get_pf(pcifunc) != cpt_pf_num) -+ if (rvu_get_pf(rvu->pdev, pcifunc) != cpt_pf_num) - return false; - if (pcifunc & RVU_PFVF_FUNC_MASK) - return false; -@@ -422,7 +422,7 @@ static bool is_cpt_vf(struct rvu *rvu, u - { - int cpt_pf_num = rvu->cpt_pf_num; - -- if (rvu_get_pf(pcifunc) != cpt_pf_num) -+ if (rvu_get_pf(rvu->pdev, pcifunc) != cpt_pf_num) - return false; - if (!(pcifunc & RVU_PFVF_FUNC_MASK)) - return false; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c 2025-10-22 13:53:56.571168871 -0400 -@@ -688,7 +688,7 @@ static int get_max_column_width(struct r - - for (pf = 0; pf < rvu->hw->total_pfs; pf++) { - for (vf = 0; vf <= rvu->hw->total_vfs; vf++) { -- pcifunc = pf << 10 | vf; -+ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, vf); - if (!pcifunc) - continue; - -@@ -759,7 +759,7 @@ static ssize_t rvu_dbg_rsrc_attach_statu - for (vf = 0; vf <= rvu->hw->total_vfs; vf++) { - off = 0; - flag = 0; -- pcifunc = pf << 10 | vf; -+ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, vf); - if (!pcifunc) - continue; - -@@ -842,7 +842,7 @@ static int rvu_dbg_rvu_pf_cgx_map_displa - - cgx[0] = 0; - lmac[0] = 0; -- pcifunc = pf << 10; -+ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, 0); - pfvf = rvu_get_pfvf(rvu, pcifunc); - - if (pfvf->nix_blkaddr == BLKADDR_NIX0) -@@ -2623,10 +2623,10 @@ static int rvu_dbg_nix_band_prof_ctx_dis - pcifunc = ipolicer->pfvf_map[idx]; - if (!(pcifunc & RVU_PFVF_FUNC_MASK)) - seq_printf(m, "Allocated to :: PF %d\n", -- rvu_get_pf(pcifunc)); -+ rvu_get_pf(rvu->pdev, pcifunc)); - else - seq_printf(m, "Allocated to :: PF %d VF %d\n", -- rvu_get_pf(pcifunc), -+ rvu_get_pf(rvu->pdev, pcifunc), - (pcifunc & RVU_PFVF_FUNC_MASK) - 1); - print_band_prof_ctx(m, &aq_rsp.prof); - } -@@ -2983,10 +2983,10 @@ static void rvu_print_npc_mcam_info(stru - - if (!(pcifunc & RVU_PFVF_FUNC_MASK)) - seq_printf(s, "\n\t\t Device \t\t: PF%d\n", -- rvu_get_pf(pcifunc)); -+ rvu_get_pf(rvu->pdev, pcifunc)); - else - seq_printf(s, "\n\t\t Device \t\t: PF%d VF%d\n", -- rvu_get_pf(pcifunc), -+ rvu_get_pf(rvu->pdev, pcifunc), - (pcifunc & RVU_PFVF_FUNC_MASK) - 1); - - if (entry_acnt) { -@@ -3049,13 +3049,13 @@ static int rvu_dbg_npc_mcam_info_display - seq_puts(filp, "\n\t\t Current allocation\n"); - seq_puts(filp, "\t\t====================\n"); - for (pf = 0; pf < rvu->hw->total_pfs; pf++) { -- pcifunc = (pf << RVU_PFVF_PF_SHIFT); -+ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, 0); - rvu_print_npc_mcam_info(filp, pcifunc, blkaddr); - - cfg = rvu_read64(rvu, BLKADDR_RVUM, RVU_PRIV_PFX_CFG(pf)); - numvfs = (cfg >> 12) & 0xFF; - for (vf = 0; vf < numvfs; vf++) { -- pcifunc = (pf << RVU_PFVF_PF_SHIFT) | (vf + 1); -+ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, (vf + 1)); - rvu_print_npc_mcam_info(filp, pcifunc, blkaddr); - } - } -@@ -3326,7 +3326,7 @@ static int rvu_dbg_npc_mcam_show_rules(s - - mutex_lock(&mcam->lock); - list_for_each_entry(iter, &mcam->mcam_rules, list) { -- pf = (iter->owner >> RVU_PFVF_PF_SHIFT) & RVU_PFVF_PF_MASK; -+ pf = rvu_get_pf(rvu->pdev, iter->owner); - seq_printf(s, "\n\tInstalled by: PF%d ", pf); - - if (iter->owner & RVU_PFVF_FUNC_MASK) { -@@ -3344,7 +3344,7 @@ static int rvu_dbg_npc_mcam_show_rules(s - rvu_dbg_npc_mcam_show_flows(s, iter); - if (is_npc_intf_rx(iter->intf)) { - target = iter->rx_action.pf_func; -- pf = (target >> RVU_PFVF_PF_SHIFT) & RVU_PFVF_PF_MASK; -+ pf = rvu_get_pf(rvu->pdev, target); - seq_printf(s, "\tForward to: PF%d ", pf); - - if (target & RVU_PFVF_FUNC_MASK) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu.h 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu.h 2025-10-22 13:53:56.571168871 -0400 -@@ -10,6 +10,7 @@ - - #include - #include -+#include - - #include "rvu_struct.h" - #include "rvu_devlink.h" -@@ -43,10 +44,34 @@ - #define MAX_CPT_BLKS 2 - - /* PF_FUNC */ --#define RVU_PFVF_PF_SHIFT 10 --#define RVU_PFVF_PF_MASK 0x3F --#define RVU_PFVF_FUNC_SHIFT 0 --#define RVU_PFVF_FUNC_MASK 0x3FF -+#define RVU_OTX2_PFVF_PF_SHIFT 10 -+#define RVU_OTX2_PFVF_PF_MASK 0x3F -+#define RVU_PFVF_FUNC_SHIFT 0 -+#define RVU_PFVF_FUNC_MASK 0x3FF -+#define RVU_CN20K_PFVF_PF_SHIFT 9 -+#define RVU_CN20K_PFVF_PF_MASK 0x7F -+ -+static inline u16 rvu_make_pcifunc(struct pci_dev *pdev, int pf, int func) -+{ -+ if (is_cn20k(pdev)) -+ return ((pf & RVU_CN20K_PFVF_PF_MASK) << -+ RVU_CN20K_PFVF_PF_SHIFT) | -+ ((func & RVU_PFVF_FUNC_MASK) << -+ RVU_PFVF_FUNC_SHIFT); -+ else -+ return ((pf & RVU_OTX2_PFVF_PF_MASK) << -+ RVU_OTX2_PFVF_PF_SHIFT) | -+ ((func & RVU_PFVF_FUNC_MASK) << -+ RVU_PFVF_FUNC_SHIFT); -+} -+ -+static inline int rvu_pcifunc_pf_mask(struct pci_dev *pdev) -+{ -+ if (is_cn20k(pdev)) -+ return ~(RVU_CN20K_PFVF_PF_MASK << RVU_CN20K_PFVF_PF_SHIFT); -+ else -+ return ~(RVU_OTX2_PFVF_PF_MASK << RVU_OTX2_PFVF_PF_SHIFT); -+} - - #ifdef CONFIG_DEBUG_FS - struct dump_ctx { -@@ -736,6 +761,20 @@ static inline bool is_cn10kb(struct rvu - return false; - } - -+static inline bool is_cgx_mapped_to_nix(unsigned short id, u8 cgx_id) -+{ -+ /* On CNF10KA and CNF10KB silicons only two CGX blocks are connected -+ * to NIX. -+ */ -+ if (id == PCI_SUBSYS_DEVID_CNF10K_A || id == PCI_SUBSYS_DEVID_CNF10K_B) -+ return cgx_id <= 1; -+ -+ return !(cgx_id && !(id == PCI_SUBSYS_DEVID_96XX || -+ id == PCI_SUBSYS_DEVID_98XX || -+ id == PCI_SUBSYS_DEVID_CN10K_A || -+ id == PCI_SUBSYS_DEVID_CN10K_B)); -+} -+ - static inline bool is_rvu_npc_hash_extract_en(struct rvu *rvu) - { - u64 npc_const3; -@@ -836,7 +875,6 @@ int rvu_alloc_rsrc_contig(struct rsrc_bm - void rvu_free_rsrc_contig(struct rsrc_bmap *rsrc, int nrsrc, int start); - bool rvu_rsrc_check_contig(struct rsrc_bmap *rsrc, int nrsrc); - u16 rvu_get_rsrc_mapcount(struct rvu_pfvf *pfvf, int blkaddr); --int rvu_get_pf(u16 pcifunc); - struct rvu_pfvf *rvu_get_pfvf(struct rvu *rvu, int pcifunc); - void rvu_get_pf_numvfs(struct rvu *rvu, int pf, int *numvfs, int *hwvf); - bool is_block_implemented(struct rvu_hwinfo *hw, int blkaddr); -@@ -865,8 +903,8 @@ void rvu_aq_free(struct rvu *rvu, struct - - /* SDP APIs */ - int rvu_sdp_init(struct rvu *rvu); --bool is_sdp_pfvf(u16 pcifunc); --bool is_sdp_pf(u16 pcifunc); -+bool is_sdp_pfvf(struct rvu *rvu, u16 pcifunc); -+bool is_sdp_pf(struct rvu *rvu, u16 pcifunc); - bool is_sdp_vf(struct rvu *rvu, u16 pcifunc); - - static inline bool is_rep_dev(struct rvu *rvu, u16 pcifunc) -@@ -877,11 +915,21 @@ static inline bool is_rep_dev(struct rvu - return false; - } - -+static inline int rvu_get_pf(struct pci_dev *pdev, u16 pcifunc) -+{ -+ if (is_cn20k(pdev)) -+ return (pcifunc >> RVU_CN20K_PFVF_PF_SHIFT) & -+ RVU_CN20K_PFVF_PF_MASK; -+ else -+ return (pcifunc >> RVU_OTX2_PFVF_PF_SHIFT) & -+ RVU_OTX2_PFVF_PF_MASK; -+} -+ - /* CGX APIs */ - static inline bool is_pf_cgxmapped(struct rvu *rvu, u8 pf) - { - return (pf >= PF_CGXMAP_BASE && pf <= rvu->cgx_mapped_pfs) && -- !is_sdp_pf(pf << RVU_PFVF_PF_SHIFT); -+ !is_sdp_pf(rvu, rvu_make_pcifunc(rvu->pdev, pf, 0)); - } - - static inline void rvu_get_cgx_lmac_id(u8 map, u8 *cgx_id, u8 *lmac_id) -@@ -893,7 +941,7 @@ static inline void rvu_get_cgx_lmac_id(u - static inline bool is_cgx_vf(struct rvu *rvu, u16 pcifunc) - { - return ((pcifunc & RVU_PFVF_FUNC_MASK) && -- is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc))); -+ is_pf_cgxmapped(rvu, rvu_get_pf(rvu->pdev, pcifunc))); - } - - #define M(_name, _id, fn_name, req, rsp) \ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c 2025-10-22 13:53:56.571168871 -0400 -@@ -315,7 +315,8 @@ static bool is_valid_txschq(struct rvu * - if (lvl >= hw->cap.nix_tx_aggr_lvl) { - if ((nix_get_tx_link(rvu, map_func) != - nix_get_tx_link(rvu, pcifunc)) && -- (rvu_get_pf(map_func) != rvu_get_pf(pcifunc))) -+ (rvu_get_pf(rvu->pdev, map_func) != -+ rvu_get_pf(rvu->pdev, pcifunc))) - return false; - else - return true; -@@ -339,7 +340,7 @@ static int nix_interface_init(struct rvu - bool from_vf; - int err; - -- pf = rvu_get_pf(pcifunc); -+ pf = rvu_get_pf(rvu->pdev, pcifunc); - if (!is_pf_cgxmapped(rvu, pf) && type != NIX_INTF_TYPE_LBK && - type != NIX_INTF_TYPE_SDP) - return 0; -@@ -416,7 +417,7 @@ static int nix_interface_init(struct rvu - break; - case NIX_INTF_TYPE_SDP: - from_vf = !!(pcifunc & RVU_PFVF_FUNC_MASK); -- parent_pf = &rvu->pf[rvu_get_pf(pcifunc)]; -+ parent_pf = &rvu->pf[rvu_get_pf(rvu->pdev, pcifunc)]; - sdp_info = parent_pf->sdp_info; - if (!sdp_info) { - dev_err(rvu->dev, "Invalid sdp_info pointer\n"); -@@ -590,12 +591,12 @@ static int nix_bp_disable(struct rvu *rv - u16 chan_v; - u64 cfg; - -- pf = rvu_get_pf(pcifunc); -+ pf = rvu_get_pf(rvu->pdev, pcifunc); - type = is_lbk_vf(rvu, pcifunc) ? NIX_INTF_TYPE_LBK : NIX_INTF_TYPE_CGX; - if (!is_pf_cgxmapped(rvu, pf) && type != NIX_INTF_TYPE_LBK) - return 0; - -- if (is_sdp_pfvf(pcifunc)) -+ if (is_sdp_pfvf(rvu, pcifunc)) - type = NIX_INTF_TYPE_SDP; - - if (cpt_link && !rvu->hw->cpt_links) -@@ -736,9 +737,9 @@ static int nix_bp_enable(struct rvu *rvu - u16 chan_v; - u64 cfg; - -- pf = rvu_get_pf(pcifunc); -+ pf = rvu_get_pf(rvu->pdev, pcifunc); - type = is_lbk_vf(rvu, pcifunc) ? NIX_INTF_TYPE_LBK : NIX_INTF_TYPE_CGX; -- if (is_sdp_pfvf(pcifunc)) -+ if (is_sdp_pfvf(rvu, pcifunc)) - type = NIX_INTF_TYPE_SDP; - - /* Enable backpressure only for CGX mapped PFs and LBK/SDP interface */ -@@ -1674,7 +1675,7 @@ int rvu_mbox_handler_nix_lf_alloc(struct - } - - intf = is_lbk_vf(rvu, pcifunc) ? NIX_INTF_TYPE_LBK : NIX_INTF_TYPE_CGX; -- if (is_sdp_pfvf(pcifunc)) -+ if (is_sdp_pfvf(rvu, pcifunc)) - intf = NIX_INTF_TYPE_SDP; - - err = nix_interface_init(rvu, pcifunc, intf, nixlf, rsp, -@@ -1798,7 +1799,8 @@ int rvu_mbox_handler_nix_mark_format_cfg - rc = rvu_nix_reserve_mark_format(rvu, nix_hw, blkaddr, cfg); - if (rc < 0) { - dev_err(rvu->dev, "No mark_format_ctl for (pf:%d, vf:%d)", -- rvu_get_pf(pcifunc), pcifunc & RVU_PFVF_FUNC_MASK); -+ rvu_get_pf(rvu->pdev, pcifunc), -+ pcifunc & RVU_PFVF_FUNC_MASK); - return NIX_AF_ERR_MARK_CFG_FAIL; - } - -@@ -2050,7 +2052,7 @@ static void nix_clear_tx_xoff(struct rvu - static int nix_get_tx_link(struct rvu *rvu, u16 pcifunc) - { - struct rvu_hwinfo *hw = rvu->hw; -- int pf = rvu_get_pf(pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, pcifunc); - u8 cgx_id = 0, lmac_id = 0; - - if (is_lbk_vf(rvu, pcifunc)) {/* LBK links */ -@@ -2068,7 +2070,7 @@ static void nix_get_txschq_range(struct - int link, int *start, int *end) - { - struct rvu_hwinfo *hw = rvu->hw; -- int pf = rvu_get_pf(pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, pcifunc); - - /* LBK links */ - if (is_lbk_vf(rvu, pcifunc) || is_rep_dev(rvu, pcifunc)) { -@@ -2426,7 +2428,7 @@ static int nix_smq_flush(struct rvu *rvu - { - struct nix_smq_flush_ctx *smq_flush_ctx; - int err, restore_tx_en = 0, i; -- int pf = rvu_get_pf(pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, pcifunc); - u8 cgx_id = 0, lmac_id = 0; - u16 tl2_tl3_link_schq; - u8 link, link_level; -@@ -2820,7 +2822,7 @@ void rvu_nix_tx_tl2_cfg(struct rvu *rvu, - { - struct rvu_hwinfo *hw = rvu->hw; - int lbk_link_start, lbk_links; -- u8 pf = rvu_get_pf(pcifunc); -+ u8 pf = rvu_get_pf(rvu->pdev, pcifunc); - int schq; - u64 cfg; - -@@ -3190,7 +3192,8 @@ static int nix_blk_setup_mce(struct rvu - err = rvu_nix_blk_aq_enq_inst(rvu, nix_hw, &aq_req, NULL); - if (err) { - dev_err(rvu->dev, "Failed to setup Bcast MCE for PF%d:VF%d\n", -- rvu_get_pf(pcifunc), pcifunc & RVU_PFVF_FUNC_MASK); -+ rvu_get_pf(rvu->pdev, pcifunc), -+ pcifunc & RVU_PFVF_FUNC_MASK); - return err; - } - return 0; -@@ -3458,7 +3461,7 @@ int nix_update_mce_list(struct rvu *rvu, - dev_err(rvu->dev, - "%s: Idx %d > max MCE idx %d, for PF%d bcast list\n", - __func__, idx, mce_list->max, -- pcifunc >> RVU_PFVF_PF_SHIFT); -+ rvu_get_pf(rvu->pdev, pcifunc)); - return -EINVAL; - } - -@@ -3510,7 +3513,8 @@ void nix_get_mce_list(struct rvu *rvu, u - struct rvu_pfvf *pfvf; - - if (!hw->cap.nix_rx_multicast || -- !is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc & ~RVU_PFVF_FUNC_MASK))) { -+ !is_pf_cgxmapped(rvu, rvu_get_pf(rvu->pdev, -+ pcifunc & ~RVU_PFVF_FUNC_MASK))) { - *mce_list = NULL; - *mce_idx = 0; - return; -@@ -3544,13 +3548,13 @@ static int nix_update_mce_rule(struct rv - int pf; - - /* skip multicast pkt replication for AF's VFs & SDP links */ -- if (is_lbk_vf(rvu, pcifunc) || is_sdp_pfvf(pcifunc)) -+ if (is_lbk_vf(rvu, pcifunc) || is_sdp_pfvf(rvu, pcifunc)) - return 0; - - if (!hw->cap.nix_rx_multicast) - return 0; - -- pf = rvu_get_pf(pcifunc); -+ pf = rvu_get_pf(rvu->pdev, pcifunc); - if (!is_pf_cgxmapped(rvu, pf)) - return 0; - -@@ -3619,7 +3623,7 @@ static int nix_setup_mce_tables(struct r - - for (idx = 0; idx < (numvfs + 1); idx++) { - /* idx-0 is for PF, followed by VFs */ -- pcifunc = (pf << RVU_PFVF_PF_SHIFT); -+ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, 0); - pcifunc |= idx; - /* Add dummy entries now, so that we don't have to check - * for whether AQ_OP should be INIT/WRITE later on. -@@ -4554,7 +4558,7 @@ int rvu_mbox_handler_nix_set_rx_mode(str - static void nix_find_link_frs(struct rvu *rvu, - struct nix_frs_cfg *req, u16 pcifunc) - { -- int pf = rvu_get_pf(pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, pcifunc); - struct rvu_pfvf *pfvf; - int maxlen, minlen; - int numvfs, hwvf; -@@ -4601,7 +4605,7 @@ int rvu_mbox_handler_nix_set_hw_frs(stru - { - struct rvu_hwinfo *hw = rvu->hw; - u16 pcifunc = req->hdr.pcifunc; -- int pf = rvu_get_pf(pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, pcifunc); - int blkaddr, link = -1; - struct nix_hw *nix_hw; - struct rvu_pfvf *pfvf; -@@ -5251,7 +5255,7 @@ int rvu_mbox_handler_nix_lf_start_rx(str - - rvu_switch_update_rules(rvu, pcifunc, true); - -- pf = rvu_get_pf(pcifunc); -+ pf = rvu_get_pf(rvu->pdev, pcifunc); - if (is_pf_cgxmapped(rvu, pf) && rvu->rep_mode) - rvu_rep_notify_pfvf_state(rvu, pcifunc, true); - -@@ -5284,7 +5288,7 @@ int rvu_mbox_handler_nix_lf_stop_rx(stru - rvu_switch_update_rules(rvu, pcifunc, false); - rvu_cgx_tx_enable(rvu, pcifunc, true); - -- pf = rvu_get_pf(pcifunc); -+ pf = rvu_get_pf(rvu->pdev, pcifunc); - if (is_pf_cgxmapped(rvu, pf) && rvu->rep_mode) - rvu_rep_notify_pfvf_state(rvu, pcifunc, false); - return 0; -@@ -5296,7 +5300,7 @@ void rvu_nix_lf_teardown(struct rvu *rvu - { - struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc); - struct hwctx_disable_req ctx_req; -- int pf = rvu_get_pf(pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, pcifunc); - struct mac_ops *mac_ops; - u8 cgx_id, lmac_id; - u64 sa_base; -@@ -5385,7 +5389,7 @@ static int rvu_nix_lf_ptp_tx_cfg(struct - int nixlf; - u64 cfg; - -- pf = rvu_get_pf(pcifunc); -+ pf = rvu_get_pf(rvu->pdev, pcifunc); - if (!is_mac_feature_supported(rvu, pf, RVU_LMAC_FEAT_PTP)) - return 0; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c 2025-10-22 13:53:56.571168871 -0400 -@@ -147,7 +147,9 @@ static int npc_get_ucast_mcam_index(stru - int npc_get_nixlf_mcam_index(struct npc_mcam *mcam, - u16 pcifunc, int nixlf, int type) - { -- int pf = rvu_get_pf(pcifunc); -+ struct rvu_hwinfo *hw = container_of(mcam, struct rvu_hwinfo, mcam); -+ struct rvu *rvu = hw->rvu; -+ int pf = rvu_get_pf(rvu->pdev, pcifunc); - int index; - - /* Check if this is for a PF */ -@@ -698,7 +700,7 @@ void rvu_npc_install_promisc_entry(struc - - /* RX_ACTION set to MCAST for CGX PF's */ - if (hw->cap.nix_rx_multicast && pfvf->use_mce_list && -- is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc))) { -+ is_pf_cgxmapped(rvu, rvu_get_pf(rvu->pdev, pcifunc))) { - *(u64 *)&action = 0; - action.op = NIX_RX_ACTIONOP_MCAST; - pfvf = rvu_get_pfvf(rvu, pcifunc & ~RVU_PFVF_FUNC_MASK); -@@ -3434,7 +3436,7 @@ int rvu_npc_set_parse_mode(struct rvu *r - { - struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc); - int blkaddr, nixlf, rc, intf_mode; -- int pf = rvu_get_pf(pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, pcifunc); - u64 rxpkind, txpkind; - u8 cgx_id, lmac_id; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c 2025-10-22 13:53:56.571168871 -0400 -@@ -606,8 +606,8 @@ static void npc_set_features(struct rvu - if (!npc_check_field(rvu, blkaddr, NPC_LB, intf)) - *features &= ~BIT_ULL(NPC_OUTER_VID); - -- /* Set SPI flag only if AH/ESP and IPSEC_SPI are in the key */ -- if (npc_check_field(rvu, blkaddr, NPC_IPSEC_SPI, intf) && -+ /* Allow extracting SPI field from AH and ESP headers at same offset */ -+ if (npc_is_field_present(rvu, NPC_IPSEC_SPI, intf) && - (*features & (BIT_ULL(NPC_IPPROTO_ESP) | BIT_ULL(NPC_IPPROTO_AH)))) - *features |= BIT_ULL(NPC_IPSEC_SPI); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c 2025-10-22 13:53:56.571168871 -0400 -@@ -1465,7 +1465,7 @@ static int rvu_npc_exact_update_table_en - int rvu_npc_exact_promisc_disable(struct rvu *rvu, u16 pcifunc) - { - struct npc_exact_table *table; -- int pf = rvu_get_pf(pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, pcifunc); - u8 cgx_id, lmac_id; - u32 drop_mcam_idx; - bool *promisc; -@@ -1512,7 +1512,7 @@ int rvu_npc_exact_promisc_disable(struct - int rvu_npc_exact_promisc_enable(struct rvu *rvu, u16 pcifunc) - { - struct npc_exact_table *table; -- int pf = rvu_get_pf(pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, pcifunc); - u8 cgx_id, lmac_id; - u32 drop_mcam_idx; - bool *promisc; -@@ -1560,7 +1560,7 @@ int rvu_npc_exact_promisc_enable(struct - int rvu_npc_exact_mac_addr_reset(struct rvu *rvu, struct cgx_mac_addr_reset_req *req, - struct msg_rsp *rsp) - { -- int pf = rvu_get_pf(req->hdr.pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - u32 seq_id = req->index; - struct rvu_pfvf *pfvf; - u8 cgx_id, lmac_id; -@@ -1593,7 +1593,7 @@ int rvu_npc_exact_mac_addr_update(struct - struct cgx_mac_addr_update_req *req, - struct cgx_mac_addr_update_rsp *rsp) - { -- int pf = rvu_get_pf(req->hdr.pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - struct npc_exact_table_entry *entry; - struct npc_exact_table *table; - struct rvu_pfvf *pfvf; -@@ -1675,7 +1675,7 @@ int rvu_npc_exact_mac_addr_add(struct rv - struct cgx_mac_addr_add_req *req, - struct cgx_mac_addr_add_rsp *rsp) - { -- int pf = rvu_get_pf(req->hdr.pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - struct rvu_pfvf *pfvf; - u8 cgx_id, lmac_id; - int rc = 0; -@@ -1711,7 +1711,7 @@ int rvu_npc_exact_mac_addr_del(struct rv - struct cgx_mac_addr_del_req *req, - struct msg_rsp *rsp) - { -- int pf = rvu_get_pf(req->hdr.pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - int rc; - - rc = rvu_npc_exact_del_table_entry_by_id(rvu, req->index); -@@ -1736,7 +1736,7 @@ int rvu_npc_exact_mac_addr_del(struct rv - int rvu_npc_exact_mac_addr_set(struct rvu *rvu, struct cgx_mac_addr_set_or_get *req, - struct cgx_mac_addr_set_or_get *rsp) - { -- int pf = rvu_get_pf(req->hdr.pcifunc); -+ int pf = rvu_get_pf(rvu->pdev, req->hdr.pcifunc); - u32 seq_id = req->index; - struct rvu_pfvf *pfvf; - u8 cgx_id, lmac_id; -@@ -2001,7 +2001,7 @@ int rvu_npc_exact_init(struct rvu *rvu) - } - - /* Filter rules are only for PF */ -- pcifunc = RVU_PFFUNC(i, 0); -+ pcifunc = RVU_PFFUNC(rvu->pdev, i, 0); - - dev_dbg(rvu->dev, - "%s:Drop rule cgx=%d lmac=%d chan(val=0x%llx, mask=0x%llx\n", -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h 2025-10-22 13:53:56.571168871 -0400 -@@ -139,9 +139,7 @@ static struct npc_mcam_kex_hash npc_mkex - #define NPC_MCAM_DROP_RULE_MAX 30 - #define NPC_MCAM_SDP_DROP_RULE_IDX 0 - --#define RVU_PFFUNC(pf, func) \ -- ((((pf) & RVU_PFVF_PF_MASK) << RVU_PFVF_PF_SHIFT) | \ -- (((func) & RVU_PFVF_FUNC_MASK) << RVU_PFVF_FUNC_SHIFT)) -+#define RVU_PFFUNC(pdev, pf, func) rvu_make_pcifunc(pdev, pf, func) - - enum npc_exact_opc_type { - NPC_EXACT_OPC_MEM, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_rep.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_rep.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_rep.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_rep.c 2025-10-22 13:53:56.571168871 -0400 -@@ -39,7 +39,7 @@ static int rvu_rep_up_notify(struct rvu - struct rep_event *msg; - int pf; - -- pf = rvu_get_pf(event->pcifunc); -+ pf = rvu_get_pf(rvu->pdev, event->pcifunc); - - if (event->event & RVU_EVENT_MAC_ADDR_CHANGE) - ether_addr_copy(pfvf->mac_addr, event->evt_data.mac); -@@ -114,10 +114,10 @@ int rvu_rep_notify_pfvf_state(struct rvu - struct rep_event *req; - int pf; - -- if (!is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc))) -+ if (!is_pf_cgxmapped(rvu, rvu_get_pf(rvu->pdev, pcifunc))) - return 0; - -- pf = rvu_get_pf(rvu->rep_pcifunc); -+ pf = rvu_get_pf(rvu->pdev, rvu->rep_pcifunc); - - mutex_lock(&rvu->mbox_lock); - req = otx2_mbox_alloc_msg_rep_event_up_notify(rvu, pf); -@@ -325,7 +325,7 @@ int rvu_rep_install_mcam_rules(struct rv - if (!is_pf_cgxmapped(rvu, pf)) - continue; - -- pcifunc = pf << RVU_PFVF_PF_SHIFT; -+ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, 0); - rvu_get_nix_blkaddr(rvu, pcifunc); - rep = true; - for (i = 0; i < 2; i++) { -@@ -345,8 +345,7 @@ int rvu_rep_install_mcam_rules(struct rv - - rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL); - for (vf = 0; vf < numvfs; vf++) { -- pcifunc = pf << RVU_PFVF_PF_SHIFT | -- ((vf + 1) & RVU_PFVF_FUNC_MASK); -+ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, vf + 1); - rvu_get_nix_blkaddr(rvu, pcifunc); - - /* Skip installimg rules if nixlf is not attached */ -@@ -454,7 +453,7 @@ int rvu_mbox_handler_get_rep_cnt(struct - for (pf = 0; pf < rvu->hw->total_pfs; pf++) { - if (!is_pf_cgxmapped(rvu, pf)) - continue; -- pcifunc = pf << RVU_PFVF_PF_SHIFT; -+ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, 0); - rvu->rep2pfvf_map[rep] = pcifunc; - rsp->rep_pf_map[rep] = pcifunc; - rep++; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_sdp.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_sdp.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_sdp.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_sdp.c 2025-10-22 13:53:56.571168871 -0400 -@@ -17,9 +17,9 @@ - /* SDP PF number */ - static int sdp_pf_num[MAX_SDP] = {-1, -1}; - --bool is_sdp_pfvf(u16 pcifunc) -+bool is_sdp_pfvf(struct rvu *rvu, u16 pcifunc) - { -- u16 pf = rvu_get_pf(pcifunc); -+ u16 pf = rvu_get_pf(rvu->pdev, pcifunc); - u32 found = 0, i = 0; - - while (i < MAX_SDP) { -@@ -34,9 +34,9 @@ bool is_sdp_pfvf(u16 pcifunc) - return true; - } - --bool is_sdp_pf(u16 pcifunc) -+bool is_sdp_pf(struct rvu *rvu, u16 pcifunc) - { -- return (is_sdp_pfvf(pcifunc) && -+ return (is_sdp_pfvf(rvu, pcifunc) && - !(pcifunc & RVU_PFVF_FUNC_MASK)); - } - -@@ -46,7 +46,7 @@ bool is_sdp_vf(struct rvu *rvu, u16 pcif - if (!(pcifunc & ~RVU_PFVF_FUNC_MASK)) - return (rvu->vf_devid == RVU_SDP_VF_DEVID); - -- return (is_sdp_pfvf(pcifunc) && -+ return (is_sdp_pfvf(rvu, pcifunc) && - !!(pcifunc & RVU_PFVF_FUNC_MASK)); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c 2025-10-22 13:53:56.571168871 -0400 -@@ -93,7 +93,7 @@ static int rvu_switch_install_rules(stru - if (!is_pf_cgxmapped(rvu, pf)) - continue; - -- pcifunc = pf << 10; -+ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, 0); - /* rvu_get_nix_blkaddr sets up the corresponding NIX block - * address and NIX RX and TX interfaces for a pcifunc. - * Generally it is called during attach call of a pcifunc but it -@@ -126,7 +126,7 @@ static int rvu_switch_install_rules(stru - - rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL); - for (vf = 0; vf < numvfs; vf++) { -- pcifunc = pf << 10 | ((vf + 1) & 0x3FF); -+ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, (vf + 1)); - rvu_get_nix_blkaddr(rvu, pcifunc); - - err = rvu_switch_install_rx_rule(rvu, pcifunc, 0x0); -@@ -236,7 +236,7 @@ void rvu_switch_disable(struct rvu *rvu) - if (!is_pf_cgxmapped(rvu, pf)) - continue; - -- pcifunc = pf << 10; -+ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, 0); - err = rvu_switch_install_rx_rule(rvu, pcifunc, 0xFFF); - if (err) - dev_err(rvu->dev, -@@ -248,7 +248,7 @@ void rvu_switch_disable(struct rvu *rvu) - - rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL); - for (vf = 0; vf < numvfs; vf++) { -- pcifunc = pf << 10 | ((vf + 1) & 0x3FF); -+ pcifunc = rvu_make_pcifunc(rvu->pdev, pf, (vf + 1)); - err = rvu_switch_install_rx_rule(rvu, pcifunc, 0xFFF); - if (err) - dev_err(rvu->dev, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.c 2025-10-22 13:53:56.571168871 -0400 -@@ -481,7 +481,7 @@ static int cn10k_outb_write_sa(struct ot - goto set_available; - - /* Trigger CTX flush to write dirty data back to DRAM */ -- reg_val = FIELD_PREP(CPT_LF_CTX_FLUSH, sa_iova >> 7); -+ reg_val = FIELD_PREP(CPT_LF_CTX_FLUSH_CPTR, sa_iova >> 7); - otx2_write64(pf, CN10K_CPT_LF_CTX_FLUSH, reg_val); - - set_available: -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.h 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.h 2025-10-22 13:53:56.571168871 -0400 -@@ -220,7 +220,7 @@ struct cpt_sg_s { - #define CPT_LF_Q_SIZE_DIV40 GENMASK_ULL(14, 0) - - /* CPT LF CTX Flush Register */ --#define CPT_LF_CTX_FLUSH GENMASK_ULL(45, 0) -+#define CPT_LF_CTX_FLUSH_CPTR GENMASK_ULL(45, 0) - - #ifdef CONFIG_XFRM_OFFLOAD - int cn10k_ipsec_init(struct net_device *netdev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c 2025-10-22 13:53:56.571168871 -0400 -@@ -124,7 +124,9 @@ void otx2_get_dev_stats(struct otx2_nic - dev_stats->rx_ucast_frames; - - dev_stats->tx_bytes = OTX2_GET_TX_STATS(TX_OCTS); -- dev_stats->tx_drops = OTX2_GET_TX_STATS(TX_DROP); -+ dev_stats->tx_drops = OTX2_GET_TX_STATS(TX_DROP) + -+ (unsigned long)atomic_long_read(&dev_stats->tx_discards); -+ - dev_stats->tx_bcast_frames = OTX2_GET_TX_STATS(TX_BCAST); - dev_stats->tx_mcast_frames = OTX2_GET_TX_STATS(TX_MCAST); - dev_stats->tx_ucast_frames = OTX2_GET_TX_STATS(TX_UCAST); -@@ -1822,7 +1824,7 @@ int otx2_nix_config_bp(struct otx2_nic * - req->chan_cnt = IEEE_8021QAZ_MAX_TCS; - req->bpid_per_chan = 1; - } else { -- req->chan_cnt = 1; -+ req->chan_cnt = pfvf->hw.rx_chan_cnt; - req->bpid_per_chan = 0; - } - -@@ -1847,7 +1849,7 @@ int otx2_nix_cpt_config_bp(struct otx2_n - req->chan_cnt = IEEE_8021QAZ_MAX_TCS; - req->bpid_per_chan = 1; - } else { -- req->chan_cnt = 1; -+ req->chan_cnt = pfvf->hw.rx_chan_cnt; - req->bpid_per_chan = 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h 2025-10-22 13:53:56.571168871 -0400 -@@ -28,6 +28,7 @@ - #include "otx2_reg.h" - #include "otx2_txrx.h" - #include "otx2_devlink.h" -+#include - #include - #include "qos.h" - #include "rep.h" -@@ -149,6 +150,7 @@ struct otx2_dev_stats { - u64 tx_bcast_frames; - u64 tx_mcast_frames; - u64 tx_drops; -+ atomic_long_t tx_discards; - }; - - /* Driver counted stats */ -@@ -899,21 +901,11 @@ MBOX_UP_MCS_MESSAGES - /* Time to wait before watchdog kicks off */ - #define OTX2_TX_TIMEOUT (100 * HZ) - --#define RVU_PFVF_PF_SHIFT 10 --#define RVU_PFVF_PF_MASK 0x3F --#define RVU_PFVF_FUNC_SHIFT 0 --#define RVU_PFVF_FUNC_MASK 0x3FF -- - static inline bool is_otx2_vf(u16 pcifunc) - { - return !!(pcifunc & RVU_PFVF_FUNC_MASK); - } - --static inline int rvu_get_pf(u16 pcifunc) --{ -- return (pcifunc >> RVU_PFVF_PF_SHIFT) & RVU_PFVF_PF_MASK; --} -- - static inline dma_addr_t otx2_dma_map_page(struct otx2_nic *pfvf, - struct page *page, - size_t offset, size_t size, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c 2025-10-22 13:53:56.571168871 -0400 -@@ -206,7 +206,8 @@ static int otx2_register_flr_me_intr(str - - /* Register ME interrupt handler*/ - irq_name = &hw->irq_name[RVU_PF_INT_VEC_VFME0 * NAME_SIZE]; -- snprintf(irq_name, NAME_SIZE, "RVUPF%d_ME0", rvu_get_pf(pf->pcifunc)); -+ snprintf(irq_name, NAME_SIZE, "RVUPF%d_ME0", -+ rvu_get_pf(pf->pdev, pf->pcifunc)); - ret = request_irq(pci_irq_vector(pf->pdev, RVU_PF_INT_VEC_VFME0), - otx2_pf_me_intr_handler, 0, irq_name, pf); - if (ret) { -@@ -216,7 +217,8 @@ static int otx2_register_flr_me_intr(str - - /* Register FLR interrupt handler */ - irq_name = &hw->irq_name[RVU_PF_INT_VEC_VFFLR0 * NAME_SIZE]; -- snprintf(irq_name, NAME_SIZE, "RVUPF%d_FLR0", rvu_get_pf(pf->pcifunc)); -+ snprintf(irq_name, NAME_SIZE, "RVUPF%d_FLR0", -+ rvu_get_pf(pf->pdev, pf->pcifunc)); - ret = request_irq(pci_irq_vector(pf->pdev, RVU_PF_INT_VEC_VFFLR0), - otx2_pf_flr_intr_handler, 0, irq_name, pf); - if (ret) { -@@ -228,7 +230,7 @@ static int otx2_register_flr_me_intr(str - if (numvfs > 64) { - irq_name = &hw->irq_name[RVU_PF_INT_VEC_VFME1 * NAME_SIZE]; - snprintf(irq_name, NAME_SIZE, "RVUPF%d_ME1", -- rvu_get_pf(pf->pcifunc)); -+ rvu_get_pf(pf->pdev, pf->pcifunc)); - ret = request_irq(pci_irq_vector - (pf->pdev, RVU_PF_INT_VEC_VFME1), - otx2_pf_me_intr_handler, 0, irq_name, pf); -@@ -238,7 +240,7 @@ static int otx2_register_flr_me_intr(str - } - irq_name = &hw->irq_name[RVU_PF_INT_VEC_VFFLR1 * NAME_SIZE]; - snprintf(irq_name, NAME_SIZE, "RVUPF%d_FLR1", -- rvu_get_pf(pf->pcifunc)); -+ rvu_get_pf(pf->pdev, pf->pcifunc)); - ret = request_irq(pci_irq_vector - (pf->pdev, RVU_PF_INT_VEC_VFFLR1), - otx2_pf_flr_intr_handler, 0, irq_name, pf); -@@ -701,7 +703,7 @@ static int otx2_register_pfvf_mbox_intr( - irq_name = &hw->irq_name[RVU_PF_INT_VEC_VFPF_MBOX0 * NAME_SIZE]; - if (pf->pcifunc) - snprintf(irq_name, NAME_SIZE, -- "RVUPF%d_VF Mbox0", rvu_get_pf(pf->pcifunc)); -+ "RVUPF%d_VF Mbox0", rvu_get_pf(pf->pdev, pf->pcifunc)); - else - snprintf(irq_name, NAME_SIZE, "RVUPF_VF Mbox0"); - err = request_irq(pci_irq_vector(pf->pdev, RVU_PF_INT_VEC_VFPF_MBOX0), -@@ -717,7 +719,8 @@ static int otx2_register_pfvf_mbox_intr( - irq_name = &hw->irq_name[RVU_PF_INT_VEC_VFPF_MBOX1 * NAME_SIZE]; - if (pf->pcifunc) - snprintf(irq_name, NAME_SIZE, -- "RVUPF%d_VF Mbox1", rvu_get_pf(pf->pcifunc)); -+ "RVUPF%d_VF Mbox1", -+ rvu_get_pf(pf->pdev, pf->pcifunc)); - else - snprintf(irq_name, NAME_SIZE, "RVUPF_VF Mbox1"); - err = request_irq(pci_irq_vector(pf->pdev, -@@ -1972,7 +1975,7 @@ int otx2_open(struct net_device *netdev) - if (err) { - dev_err(pf->dev, - "RVUPF%d: IRQ registration failed for QERR\n", -- rvu_get_pf(pf->pcifunc)); -+ rvu_get_pf(pf->pdev, pf->pcifunc)); - goto err_disable_napi; - } - -@@ -1990,7 +1993,7 @@ int otx2_open(struct net_device *netdev) - if (name_len >= NAME_SIZE) { - dev_err(pf->dev, - "RVUPF%d: IRQ registration failed for CQ%d, irq name is too long\n", -- rvu_get_pf(pf->pcifunc), qidx); -+ rvu_get_pf(pf->pdev, pf->pcifunc), qidx); - err = -EINVAL; - goto err_free_cints; - } -@@ -2001,7 +2004,7 @@ int otx2_open(struct net_device *netdev) - if (err) { - dev_err(pf->dev, - "RVUPF%d: IRQ registration failed for CQ%d\n", -- rvu_get_pf(pf->pcifunc), qidx); -+ rvu_get_pf(pf->pdev, pf->pcifunc), qidx); - goto err_free_cints; - } - vec++; -@@ -2153,6 +2156,7 @@ static netdev_tx_t otx2_xmit(struct sk_b - { - struct otx2_nic *pf = netdev_priv(netdev); - int qidx = skb_get_queue_mapping(skb); -+ struct otx2_dev_stats *dev_stats; - struct otx2_snd_queue *sq; - struct netdev_queue *txq; - int sq_idx; -@@ -2165,6 +2169,8 @@ static netdev_tx_t otx2_xmit(struct sk_b - /* Check for minimum and maximum packet length */ - if (skb->len <= ETH_HLEN || - (!skb_shinfo(skb)->gso_size && skb->len > pf->tx_max_pktlen)) { -+ dev_stats = &pf->hw.dev_stats; -+ atomic_long_inc(&dev_stats->tx_discards); - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c 2025-10-22 13:53:56.571168871 -0400 -@@ -491,7 +491,7 @@ void otx2_ptp_destroy(struct otx2_nic *p - if (!ptp) - return; - -- cancel_delayed_work(&pfvf->ptp->synctstamp_work); -+ cancel_delayed_work_sync(&pfvf->ptp->synctstamp_work); - - ptp_clock_unregister(ptp->ptp_clock); - kfree(ptp); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h 2025-10-22 13:53:56.571168871 -0400 -@@ -138,36 +138,6 @@ - #define NIX_LF_CINTX_ENA_W1S(a) (NIX_LFBASE | 0xD40 | (a) << 12) - #define NIX_LF_CINTX_ENA_W1C(a) (NIX_LFBASE | 0xD50 | (a) << 12) - --/* NIX AF transmit scheduler registers */ --#define NIX_AF_SMQX_CFG(a) (0x700 | (u64)(a) << 16) --#define NIX_AF_TL4X_SDP_LINK_CFG(a) (0xB10 | (u64)(a) << 16) --#define NIX_AF_TL1X_SCHEDULE(a) (0xC00 | (u64)(a) << 16) --#define NIX_AF_TL1X_CIR(a) (0xC20 | (u64)(a) << 16) --#define NIX_AF_TL1X_TOPOLOGY(a) (0xC80 | (u64)(a) << 16) --#define NIX_AF_TL2X_PARENT(a) (0xE88 | (u64)(a) << 16) --#define NIX_AF_TL2X_SCHEDULE(a) (0xE00 | (u64)(a) << 16) --#define NIX_AF_TL2X_TOPOLOGY(a) (0xE80 | (u64)(a) << 16) --#define NIX_AF_TL2X_CIR(a) (0xE20 | (u64)(a) << 16) --#define NIX_AF_TL2X_PIR(a) (0xE30 | (u64)(a) << 16) --#define NIX_AF_TL3X_PARENT(a) (0x1088 | (u64)(a) << 16) --#define NIX_AF_TL3X_SCHEDULE(a) (0x1000 | (u64)(a) << 16) --#define NIX_AF_TL3X_SHAPE(a) (0x1010 | (u64)(a) << 16) --#define NIX_AF_TL3X_CIR(a) (0x1020 | (u64)(a) << 16) --#define NIX_AF_TL3X_PIR(a) (0x1030 | (u64)(a) << 16) --#define NIX_AF_TL3X_TOPOLOGY(a) (0x1080 | (u64)(a) << 16) --#define NIX_AF_TL4X_PARENT(a) (0x1288 | (u64)(a) << 16) --#define NIX_AF_TL4X_SCHEDULE(a) (0x1200 | (u64)(a) << 16) --#define NIX_AF_TL4X_SHAPE(a) (0x1210 | (u64)(a) << 16) --#define NIX_AF_TL4X_CIR(a) (0x1220 | (u64)(a) << 16) --#define NIX_AF_TL4X_PIR(a) (0x1230 | (u64)(a) << 16) --#define NIX_AF_TL4X_TOPOLOGY(a) (0x1280 | (u64)(a) << 16) --#define NIX_AF_MDQX_SCHEDULE(a) (0x1400 | (u64)(a) << 16) --#define NIX_AF_MDQX_SHAPE(a) (0x1410 | (u64)(a) << 16) --#define NIX_AF_MDQX_CIR(a) (0x1420 | (u64)(a) << 16) --#define NIX_AF_MDQX_PIR(a) (0x1430 | (u64)(a) << 16) --#define NIX_AF_MDQX_PARENT(a) (0x1480 | (u64)(a) << 16) --#define NIX_AF_TL3_TL2X_LINKX_CFG(a, b) (0x1700 | (u64)(a) << 16 | (b) << 3) -- - /* LMT LF registers */ - #define LMT_LFBASE BIT_ULL(RVU_FUNC_BLKADDR_SHIFT) - #define LMT_LF_LMTLINEX(a) (LMT_LFBASE | 0x000 | (a) << 12) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c 2025-10-22 13:53:56.571168871 -0400 -@@ -467,7 +467,8 @@ static int otx2_tc_parse_actions(struct - target = act->dev; - if (target->dev.parent) { - priv = netdev_priv(target); -- if (rvu_get_pf(nic->pcifunc) != rvu_get_pf(priv->pcifunc)) { -+ if (rvu_get_pf(nic->pdev, nic->pcifunc) != -+ rvu_get_pf(nic->pdev, priv->pcifunc)) { - NL_SET_ERR_MSG_MOD(extack, - "can't redirect to other pf/vf"); - return -EOPNOTSUPP; -@@ -1325,7 +1326,6 @@ static int otx2_tc_add_flow(struct otx2_ - - free_leaf: - otx2_tc_del_from_flow_list(flow_cfg, new_node); -- kfree_rcu(new_node, rcu); - if (new_node->is_act_police) { - mutex_lock(&nic->mbox.lock); - -@@ -1345,6 +1345,7 @@ free_leaf: - - mutex_unlock(&nic->mbox.lock); - } -+ kfree_rcu(new_node, rcu); - - return rc; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c 2025-10-22 13:53:56.571168871 -0400 -@@ -391,9 +391,19 @@ static netdev_tx_t otx2vf_xmit(struct sk - { - struct otx2_nic *vf = netdev_priv(netdev); - int qidx = skb_get_queue_mapping(skb); -+ struct otx2_dev_stats *dev_stats; - struct otx2_snd_queue *sq; - struct netdev_queue *txq; - -+ /* Check for minimum and maximum packet length */ -+ if (skb->len <= ETH_HLEN || -+ (!skb_shinfo(skb)->gso_size && skb->len > vf->tx_max_pktlen)) { -+ dev_stats = &vf->hw.dev_stats; -+ atomic_long_inc(&dev_stats->tx_discards); -+ dev_kfree_skb(skb); -+ return NETDEV_TX_OK; -+ } -+ - sq = &vf->qset.sq[qidx]; - txq = netdev_get_tx_queue(netdev, qidx); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/nic/rep.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/nic/rep.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/nic/rep.c 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/nic/rep.c 2025-10-22 13:53:56.571168871 -0400 -@@ -244,10 +244,10 @@ static int rvu_rep_devlink_port_register - - if (!(rep->pcifunc & RVU_PFVF_FUNC_MASK)) { - attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; -- attrs.phys.port_number = rvu_get_pf(rep->pcifunc); -+ attrs.phys.port_number = rvu_get_pf(priv->pdev, rep->pcifunc); - } else { - attrs.flavour = DEVLINK_PORT_FLAVOUR_PCI_VF; -- attrs.pci_vf.pf = rvu_get_pf(rep->pcifunc); -+ attrs.pci_vf.pf = rvu_get_pf(priv->pdev, rep->pcifunc); - attrs.pci_vf.vf = rep->pcifunc & RVU_PFVF_FUNC_MASK; - } - -@@ -371,7 +371,8 @@ static void rvu_rep_get_stats(struct wor - stats->rx_mcast_frames = rsp->rx.mcast; - stats->tx_bytes = rsp->tx.octs; - stats->tx_frames = rsp->tx.ucast + rsp->tx.bcast + rsp->tx.mcast; -- stats->tx_drops = rsp->tx.drop; -+ stats->tx_drops = rsp->tx.drop + -+ (unsigned long)atomic_long_read(&stats->tx_discards); - exit: - mutex_unlock(&priv->mbox.lock); - } -@@ -418,6 +419,16 @@ static netdev_tx_t rvu_rep_xmit(struct s - struct otx2_nic *pf = rep->mdev; - struct otx2_snd_queue *sq; - struct netdev_queue *txq; -+ struct rep_stats *stats; -+ -+ /* Check for minimum and maximum packet length */ -+ if (skb->len <= ETH_HLEN || -+ (!skb_shinfo(skb)->gso_size && skb->len > pf->tx_max_pktlen)) { -+ stats = &rep->stats; -+ atomic_long_inc(&stats->tx_discards); -+ dev_kfree_skb(skb); -+ return NETDEV_TX_OK; -+ } - - sq = &pf->qset.sq[rep->rep_id]; - txq = netdev_get_tx_queue(dev, 0); -@@ -672,7 +683,8 @@ int rvu_rep_create(struct otx2_nic *priv - rep->pcifunc = pcifunc; - - snprintf(ndev->name, sizeof(ndev->name), "Rpf%dvf%d", -- rvu_get_pf(pcifunc), (pcifunc & RVU_PFVF_FUNC_MASK)); -+ rvu_get_pf(priv->pdev, pcifunc), -+ (pcifunc & RVU_PFVF_FUNC_MASK)); - - ndev->hw_features = (NETIF_F_RXCSUM | NETIF_F_IP_CSUM | - NETIF_F_IPV6_CSUM | NETIF_F_RXHASH | -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/nic/rep.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/nic/rep.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/marvell/octeontx2/nic/rep.h 2025-10-22 13:53:23.343328512 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/marvell/octeontx2/nic/rep.h 2025-10-22 13:53:56.571168871 -0400 -@@ -27,6 +27,7 @@ struct rep_stats { - u64 tx_bytes; - u64 tx_frames; - u64 tx_drops; -+ atomic_long_t tx_discards; - }; - - struct rep_dev { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mediatek/mtk_eth_soc.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mediatek/mtk_eth_soc.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mediatek/mtk_eth_soc.c 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mediatek/mtk_eth_soc.c 2025-10-22 13:53:56.571168871 -0400 -@@ -1831,6 +1831,13 @@ static netdev_tx_t mtk_start_xmit(struct - bool gso = false; - int tx_num; - -+ if (skb_vlan_tag_present(skb) && -+ !eth_proto_is_802_3(eth_hdr(skb)->h_proto)) { -+ skb = __vlan_hwaccel_push_inside(skb); -+ if (!skb) -+ goto dropped; -+ } -+ - /* normally we can rely on the stack not calling this more than once, - * however we have 2 queues running on the same ring so we need to lock - * the ring access -@@ -1876,8 +1883,9 @@ static netdev_tx_t mtk_start_xmit(struct - - drop: - spin_unlock(ð->page_lock); -- stats->tx_dropped++; - dev_kfree_skb_any(skb); -+dropped: -+ stats->tx_dropped++; - return NETDEV_TX_OK; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mediatek/mtk_ppe_offload.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mediatek/mtk_ppe_offload.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mediatek/mtk_ppe_offload.c 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mediatek/mtk_ppe_offload.c 2025-10-22 13:53:56.571168871 -0400 -@@ -101,7 +101,9 @@ mtk_flow_get_wdma_info(struct net_device - if (!IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED)) - return -1; - -+ rcu_read_lock(); - err = dev_fill_forward_path(dev, addr, &stack); -+ rcu_read_unlock(); - if (err) - return err; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mediatek/mtk_wed.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mediatek/mtk_wed.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mediatek/mtk_wed.c 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mediatek/mtk_wed.c 2025-10-22 13:53:56.571168871 -0400 -@@ -2794,7 +2794,6 @@ void mtk_wed_add_hw(struct device_node * - if (!pdev) - goto err_of_node_put; - -- get_device(&pdev->dev); - irq = platform_get_irq(pdev, 0); - if (irq < 0) - goto err_put_device; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx4/en_rx.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx4/en_rx.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx4/en_rx.c 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx4/en_rx.c 2025-10-22 13:53:56.571168871 -0400 -@@ -267,8 +267,10 @@ int mlx4_en_create_rx_ring(struct mlx4_e - pp.dma_dir = priv->dma_dir; - - ring->pp = page_pool_create(&pp); -- if (!ring->pp) -+ if (IS_ERR(ring->pp)) { -+ err = PTR_ERR(ring->pp); - goto err_ring; -+ } - - if (xdp_rxq_info_reg(&ring->xdp_rxq, priv->dev, queue_index, 0) < 0) - goto err_pp; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/cmd.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/cmd.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/cmd.c 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/cmd.c 2025-10-22 13:53:56.575168852 -0400 -@@ -1947,8 +1947,8 @@ static int cmd_exec(struct mlx5_core_dev - - err = mlx5_cmd_invoke(dev, inb, outb, out, out_size, callback, context, - pages_queue, token, force_polling); -- if (callback) -- return err; -+ if (callback && !err) -+ return 0; - - if (err > 0) /* Failed in FW, command didn't execute */ - err = deliv_status_to_err(err); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/devlink.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/devlink.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/devlink.c 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/devlink.c 2025-10-22 13:53:56.575168852 -0400 -@@ -107,7 +107,7 @@ static int mlx5_devlink_reload_fw_activa - if (err) - return err; - -- mlx5_unload_one_devl_locked(dev, true); -+ mlx5_sync_reset_unload_flow(dev, true); - err = mlx5_health_wait_pci_up(dev); - if (err) - NL_SET_ERR_MSG_MOD(extack, "FW activate aborted, PCI reads fail after reset"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en/dcbnl.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en/dcbnl.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en/dcbnl.h 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en/dcbnl.h 2025-10-22 13:53:56.575168852 -0400 -@@ -26,7 +26,6 @@ struct mlx5e_dcbx { - u8 cap; - - /* Buffer configuration */ -- bool manual_buffer; - u32 cable_len; - u32 xoff; - u16 port_buff_cell_sz; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h 2025-10-22 13:53:56.575168852 -0400 -@@ -18,7 +18,8 @@ enum { - - enum { - MLX5E_TC_PRIO = 0, -- MLX5E_NIC_PRIO -+ MLX5E_PROMISC_PRIO, -+ MLX5E_NIC_PRIO, - }; - - struct mlx5e_flow_table { -@@ -68,9 +69,13 @@ struct mlx5e_l2_table { - MLX5_HASH_FIELD_SEL_DST_IP |\ - MLX5_HASH_FIELD_SEL_IPSEC_SPI) - --/* NIC prio FTS */ -+/* NIC promisc FT level */ - enum { - MLX5E_PROMISC_FT_LEVEL, -+}; -+ -+/* NIC prio FTS */ -+enum { - MLX5E_VLAN_FT_LEVEL, - MLX5E_L2_FT_LEVEL, - MLX5E_TTC_FT_LEVEL, -@@ -87,6 +92,7 @@ enum { - MLX5E_ACCEL_FS_ESP_FT_LEVEL = MLX5E_INNER_TTC_FT_LEVEL + 1, - MLX5E_ACCEL_FS_ESP_FT_ERR_LEVEL, - MLX5E_ACCEL_FS_POL_FT_LEVEL, -+ MLX5E_ACCEL_FS_POL_MISS_FT_LEVEL, - MLX5E_ACCEL_FS_ESP_FT_ROCE_LEVEL, - #endif - }; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c 2025-10-22 13:53:56.575168852 -0400 -@@ -272,8 +272,8 @@ static int port_update_shared_buffer(str - /* Total shared buffer size is split in a ratio of 3:1 between - * lossy and lossless pools respectively. - */ -- lossy_epool_size = (shared_buffer_size / 4) * 3; - lossless_ipool_size = shared_buffer_size / 4; -+ lossy_epool_size = shared_buffer_size - lossless_ipool_size; - - mlx5e_port_set_sbpr(mdev, 0, MLX5_EGRESS_DIR, MLX5_LOSSY_POOL, 0, - lossy_epool_size); -@@ -288,14 +288,12 @@ static int port_set_buffer(struct mlx5e_ - u16 port_buff_cell_sz = priv->dcbx.port_buff_cell_sz; - struct mlx5_core_dev *mdev = priv->mdev; - int sz = MLX5_ST_SZ_BYTES(pbmc_reg); -- u32 new_headroom_size = 0; -- u32 current_headroom_size; -+ u32 current_headroom_cells = 0; -+ u32 new_headroom_cells = 0; - void *in; - int err; - int i; - -- current_headroom_size = port_buffer->headroom_size; -- - in = kzalloc(sz, GFP_KERNEL); - if (!in) - return -ENOMEM; -@@ -306,12 +304,14 @@ static int port_set_buffer(struct mlx5e_ - - for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) { - void *buffer = MLX5_ADDR_OF(pbmc_reg, in, buffer[i]); -+ current_headroom_cells += MLX5_GET(bufferx_reg, buffer, size); -+ - u64 size = port_buffer->buffer[i].size; - u64 xoff = port_buffer->buffer[i].xoff; - u64 xon = port_buffer->buffer[i].xon; - -- new_headroom_size += size; - do_div(size, port_buff_cell_sz); -+ new_headroom_cells += size; - do_div(xoff, port_buff_cell_sz); - do_div(xon, port_buff_cell_sz); - MLX5_SET(bufferx_reg, buffer, size, size); -@@ -320,10 +320,8 @@ static int port_set_buffer(struct mlx5e_ - MLX5_SET(bufferx_reg, buffer, xon_threshold, xon); - } - -- new_headroom_size /= port_buff_cell_sz; -- current_headroom_size /= port_buff_cell_sz; -- err = port_update_shared_buffer(priv->mdev, current_headroom_size, -- new_headroom_size); -+ err = port_update_shared_buffer(priv->mdev, current_headroom_cells, -+ new_headroom_cells); - if (err) - goto out; - -@@ -331,6 +329,9 @@ static int port_set_buffer(struct mlx5e_ - if (err) - goto out; - -+ /* RO bits should be set to 0 on write */ -+ MLX5_SET(pbmc_reg, in, port_buffer_size, 0); -+ - err = mlx5e_port_set_pbmc(mdev, in); - out: - kfree(in); -@@ -574,7 +575,6 @@ int mlx5e_port_manual_buffer_config(stru - if (err) - return err; - } -- priv->dcbx.xoff = xoff; - - /* Apply the settings */ - if (update_buffer) { -@@ -583,6 +583,8 @@ int mlx5e_port_manual_buffer_config(stru - return err; - } - -+ priv->dcbx.xoff = xoff; -+ - if (update_prio2buffer) - err = mlx5e_port_set_priority2buffer(priv->mdev, prio2buffer); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h 2025-10-22 13:53:56.575168852 -0400 -@@ -66,11 +66,23 @@ struct mlx5e_port_buffer { - struct mlx5e_bufferx_reg buffer[MLX5E_MAX_NETWORK_BUFFER]; - }; - -+#ifdef CONFIG_MLX5_CORE_EN_DCB - int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, - u32 change, unsigned int mtu, - struct ieee_pfc *pfc, - u32 *buffer_size, - u8 *prio2buffer); -+#else -+static inline int -+mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, -+ u32 change, unsigned int mtu, -+ void *pfc, -+ u32 *buffer_size, -+ u8 *prio2buffer) -+{ -+ return 0; -+} -+#endif - - int mlx5e_port_query_buffer(struct mlx5e_priv *priv, - struct mlx5e_port_buffer *port_buffer); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c 2025-10-22 13:53:56.575168852 -0400 -@@ -374,7 +374,7 @@ void mlx5e_reactivate_qos_sq(struct mlx5 - void mlx5e_reset_qdisc(struct net_device *dev, u16 qid) - { - struct netdev_queue *dev_queue = netdev_get_tx_queue(dev, qid); -- struct Qdisc *qdisc = dev_queue->qdisc_sleeping; -+ struct Qdisc *qdisc = rtnl_dereference(dev_queue->qdisc_sleeping); - - if (!qdisc) - return; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c 2025-10-22 13:53:56.575168852 -0400 -@@ -170,16 +170,23 @@ static int mlx5e_rx_reporter_err_rq_cqe_ - static int mlx5e_rx_reporter_timeout_recover(void *ctx) - { - struct mlx5_eq_comp *eq; -+ struct mlx5e_priv *priv; - struct mlx5e_rq *rq; - int err; - - rq = ctx; -+ priv = rq->priv; -+ -+ mutex_lock(&priv->state_lock); -+ - eq = rq->cq.mcq.eq; - - err = mlx5e_health_channel_eq_recover(rq->netdev, eq, rq->cq.ch_stats); - if (err && rq->icosq) - clear_bit(MLX5E_SQ_STATE_ENABLED, &rq->icosq->state); - -+ mutex_unlock(&priv->state_lock); -+ - return err; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_hmfs.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_hmfs.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_hmfs.c 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_hmfs.c 2025-10-22 13:53:56.575168852 -0400 -@@ -173,6 +173,8 @@ static void mlx5_ct_fs_hmfs_fill_rule_ac - - memset(rule_actions, 0, NUM_CT_HMFS_RULES * sizeof(*rule_actions)); - rule_actions[0].action = mlx5_fc_get_hws_action(fs_hmfs->ctx, attr->counter); -+ rule_actions[0].counter.offset = -+ attr->counter->id - attr->counter->bulk->base_id; - /* Modify header is special, it may require extra arguments outside the action itself. */ - if (mh_action->mh_data) { - rule_actions[1].modify_header.offset = mh_action->mh_data->offset; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c 2025-10-22 13:53:56.575168852 -0400 -@@ -747,6 +747,7 @@ static void ipsec_rx_create_attr_set(str - attr->family = family; - attr->prio = MLX5E_NIC_PRIO; - attr->pol_level = MLX5E_ACCEL_FS_POL_FT_LEVEL; -+ attr->pol_miss_level = MLX5E_ACCEL_FS_POL_MISS_FT_LEVEL; - attr->sa_level = MLX5E_ACCEL_FS_ESP_FT_LEVEL; - attr->status_level = MLX5E_ACCEL_FS_ESP_FT_ERR_LEVEL; - attr->chains_ns = MLX5_FLOW_NAMESPACE_KERNEL; -@@ -833,7 +834,7 @@ static int ipsec_rx_chains_create_miss(s - - ft_attr.max_fte = 1; - ft_attr.autogroup.max_num_groups = 1; -- ft_attr.level = attr->pol_level; -+ ft_attr.level = attr->pol_miss_level; - ft_attr.prio = attr->prio; - - ft = mlx5_create_auto_grouped_flow_table(attr->ns, &ft_attr); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h 2025-10-22 13:53:56.575168852 -0400 -@@ -185,6 +185,7 @@ struct mlx5e_ipsec_rx_create_attr { - u32 family; - int prio; - int pol_level; -+ int pol_miss_level; - int sa_level; - int status_level; - enum mlx5_flow_namespace_type chains_ns; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c 2025-10-22 13:53:56.575168852 -0400 -@@ -327,6 +327,10 @@ void mlx5e_ipsec_offload_handle_rx_skb(s - if (unlikely(!sa_entry)) { - rcu_read_unlock(); - atomic64_inc(&ipsec->sw_stats.ipsec_rx_drop_sadb_miss); -+ /* Clear secpath to prevent invalid dereference -+ * in downstream XFRM policy checks. -+ */ -+ secpath_reset(skb); - return; - } - xfrm_state_hold(sa_entry->x); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c 2025-10-22 13:53:56.575168852 -0400 -@@ -362,6 +362,7 @@ static int mlx5e_dcbnl_ieee_getpfc(struc - static int mlx5e_dcbnl_ieee_setpfc(struct net_device *dev, - struct ieee_pfc *pfc) - { -+ u8 buffer_ownership = MLX5_BUF_OWNERSHIP_UNKNOWN; - struct mlx5e_priv *priv = netdev_priv(dev); - struct mlx5_core_dev *mdev = priv->mdev; - u32 old_cable_len = priv->dcbx.cable_len; -@@ -389,7 +390,14 @@ static int mlx5e_dcbnl_ieee_setpfc(struc - - if (MLX5_BUFFER_SUPPORTED(mdev)) { - pfc_new.pfc_en = (changed & MLX5E_PORT_BUFFER_PFC) ? pfc->pfc_en : curr_pfc_en; -- if (priv->dcbx.manual_buffer) -+ ret = mlx5_query_port_buffer_ownership(mdev, -+ &buffer_ownership); -+ if (ret) -+ netdev_err(dev, -+ "%s, Failed to get buffer ownership: %d\n", -+ __func__, ret); -+ -+ if (buffer_ownership == MLX5_BUF_OWNERSHIP_SW_OWNED) - ret = mlx5e_port_manual_buffer_config(priv, changed, - dev->mtu, &pfc_new, - NULL, NULL); -@@ -982,7 +990,6 @@ static int mlx5e_dcbnl_setbuffer(struct - if (!changed) - return 0; - -- priv->dcbx.manual_buffer = true; - err = mlx5e_port_manual_buffer_config(priv, changed, dev->mtu, NULL, - buffer_size, prio2buffer); - return err; -@@ -1252,7 +1259,6 @@ void mlx5e_dcbnl_initialize(struct mlx5e - priv->dcbx.cap |= DCB_CAP_DCBX_HOST; - - priv->dcbx.port_buff_cell_sz = mlx5e_query_port_buffers_cell_size(priv); -- priv->dcbx.manual_buffer = false; - priv->dcbx.cable_len = MLX5E_DEFAULT_CABLE_LEN; - - mlx5e_ets_init(priv); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_dim.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_dim.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_dim.c 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_dim.c 2025-10-22 13:53:56.575168852 -0400 -@@ -113,7 +113,7 @@ int mlx5e_dim_rx_change(struct mlx5e_rq - __set_bit(MLX5E_RQ_STATE_DIM, &rq->state); - } else { - __clear_bit(MLX5E_RQ_STATE_DIM, &rq->state); -- -+ synchronize_net(); - mlx5e_dim_disable(rq->dim); - rq->dim = NULL; - } -@@ -140,7 +140,7 @@ int mlx5e_dim_tx_change(struct mlx5e_txq - __set_bit(MLX5E_SQ_STATE_DIM, &sq->state); - } else { - __clear_bit(MLX5E_SQ_STATE_DIM, &sq->state); -- -+ synchronize_net(); - mlx5e_dim_disable(sq->dim); - sq->dim = NULL; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c 2025-10-22 13:53:56.575168852 -0400 -@@ -43,7 +43,6 @@ - #include "en/fs_ethtool.h" - - #define LANES_UNKNOWN 0 --#define MAX_LANES 8 - - void mlx5e_ethtool_get_drvinfo(struct mlx5e_priv *priv, - struct ethtool_drvinfo *drvinfo) -@@ -1098,10 +1097,8 @@ static void get_link_properties(struct n - speed = info->speed; - lanes = info->lanes; - duplex = DUPLEX_FULL; -- } else if (data_rate_oper) { -+ } else if (data_rate_oper) - speed = 100 * data_rate_oper; -- lanes = MAX_LANES; -- } - - out: - link_ksettings->base.duplex = duplex; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c 2025-10-22 13:53:56.575168852 -0400 -@@ -780,7 +780,7 @@ static int mlx5e_create_promisc_table(st - ft_attr.max_fte = MLX5E_PROMISC_TABLE_SIZE; - ft_attr.autogroup.max_num_groups = 1; - ft_attr.level = MLX5E_PROMISC_FT_LEVEL; -- ft_attr.prio = MLX5E_NIC_PRIO; -+ ft_attr.prio = MLX5E_PROMISC_PRIO; - - ft->t = mlx5_create_auto_grouped_flow_table(fs->ns, &ft_attr); - if (IS_ERR(ft->t)) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en.h 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en.h 2025-10-22 13:53:56.575168852 -0400 -@@ -728,6 +728,7 @@ struct mlx5e_rq { - struct xsk_buff_pool *xsk_pool; - - struct work_struct recover_work; -+ struct work_struct rx_timeout_work; - - /* control */ - struct mlx5_wq_ctrl wq_ctrl; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_main.c 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_main.c 2025-10-22 13:53:56.575168852 -0400 -@@ -48,6 +48,7 @@ - #include "en.h" - #include "en/dim.h" - #include "en/txrx.h" -+#include "en/port_buffer.h" - #include "en_tc.h" - #include "en_rep.h" - #include "en_accel/ipsec.h" -@@ -707,6 +708,27 @@ static void mlx5e_rq_err_cqe_work(struct - mlx5e_reporter_rq_cqe_err(rq); - } - -+static void mlx5e_rq_timeout_work(struct work_struct *timeout_work) -+{ -+ struct mlx5e_rq *rq = container_of(timeout_work, -+ struct mlx5e_rq, -+ rx_timeout_work); -+ -+ /* Acquire netdev instance lock to synchronize with channel close and -+ * reopen flows. Either successfully obtain the lock, or detect that -+ * channels are closing for another reason, making this work no longer -+ * necessary. -+ */ -+ while (!netdev_trylock(rq->netdev)) { -+ if (!test_bit(MLX5E_STATE_CHANNELS_ACTIVE, &rq->priv->state)) -+ return; -+ msleep(20); -+ } -+ -+ mlx5e_reporter_rx_timeout(rq); -+ netdev_unlock(rq->netdev); -+} -+ - static int mlx5e_alloc_mpwqe_rq_drop_page(struct mlx5e_rq *rq) - { - rq->wqe_overflow.page = alloc_page(GFP_KERNEL); -@@ -830,6 +852,7 @@ static int mlx5e_alloc_rq(struct mlx5e_p - - rqp->wq.db_numa_node = node; - INIT_WORK(&rq->recover_work, mlx5e_rq_err_cqe_work); -+ INIT_WORK(&rq->rx_timeout_work, mlx5e_rq_timeout_work); - - if (params->xdp_prog) - bpf_prog_inc(params->xdp_prog); -@@ -1204,7 +1227,8 @@ int mlx5e_wait_for_min_rx_wqes(struct ml - netdev_warn(rq->netdev, "Failed to get min RX wqes on Channel[%d] RQN[0x%x] wq cur_sz(%d) min_rx_wqes(%d)\n", - rq->ix, rq->rqn, mlx5e_rqwq_get_cur_sz(rq), min_wqes); - -- mlx5e_reporter_rx_timeout(rq); -+ queue_work(rq->priv->wq, &rq->rx_timeout_work); -+ - return -ETIMEDOUT; - } - -@@ -1375,6 +1399,7 @@ void mlx5e_close_rq(struct mlx5e_rq *rq) - if (rq->dim) - cancel_work_sync(&rq->dim->work); - cancel_work_sync(&rq->recover_work); -+ cancel_work_sync(&rq->rx_timeout_work); - mlx5e_destroy_rq(rq); - mlx5e_free_rx_descs(rq); - mlx5e_free_rq(rq); -@@ -2961,9 +2986,11 @@ int mlx5e_set_dev_port_mtu(struct mlx5e_ - struct mlx5e_params *params = &priv->channels.params; - struct net_device *netdev = priv->netdev; - struct mlx5_core_dev *mdev = priv->mdev; -- u16 mtu; -+ u16 mtu, prev_mtu; - int err; - -+ mlx5e_query_mtu(mdev, params, &prev_mtu); -+ - err = mlx5e_set_mtu(mdev, params, params->sw_mtu); - if (err) - return err; -@@ -2973,6 +3000,18 @@ int mlx5e_set_dev_port_mtu(struct mlx5e_ - netdev_warn(netdev, "%s: VPort MTU %d is different than netdev mtu %d\n", - __func__, mtu, params->sw_mtu); - -+ if (mtu != prev_mtu && MLX5_BUFFER_SUPPORTED(mdev)) { -+ err = mlx5e_port_manual_buffer_config(priv, 0, mtu, -+ NULL, NULL, NULL); -+ if (err) { -+ netdev_warn(netdev, "%s: Failed to set Xon/Xoff values with MTU %d (err %d), setting back to previous MTU %d\n", -+ __func__, mtu, err, prev_mtu); -+ -+ mlx5e_set_mtu(mdev, params, prev_mtu); -+ return err; -+ } -+ } -+ - params->sw_mtu = mtu; - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c 2025-10-22 13:53:56.575168852 -0400 -@@ -1506,12 +1506,21 @@ static const struct mlx5e_profile mlx5e_ - static int - mlx5e_vport_uplink_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) - { -- struct mlx5e_priv *priv = netdev_priv(mlx5_uplink_netdev_get(dev)); - struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep); -+ struct net_device *netdev; -+ struct mlx5e_priv *priv; -+ int err; - -+ netdev = mlx5_uplink_netdev_get(dev); -+ if (!netdev) -+ return 0; -+ -+ priv = netdev_priv(netdev); - rpriv->netdev = priv->netdev; -- return mlx5e_netdev_change_profile(priv, &mlx5e_uplink_rep_profile, -- rpriv); -+ err = mlx5e_netdev_change_profile(priv, &mlx5e_uplink_rep_profile, -+ rpriv); -+ mlx5_uplink_netdev_put(dev, netdev); -+ return err; - } - - static void -@@ -1638,8 +1647,16 @@ mlx5e_vport_rep_unload(struct mlx5_eswit - { - struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep); - struct net_device *netdev = rpriv->netdev; -- struct mlx5e_priv *priv = netdev_priv(netdev); -- void *ppriv = priv->ppriv; -+ struct mlx5e_priv *priv; -+ void *ppriv; -+ -+ if (!netdev) { -+ ppriv = rpriv; -+ goto free_ppriv; -+ } -+ -+ priv = netdev_priv(netdev); -+ ppriv = priv->ppriv; - - if (rep->vport == MLX5_VPORT_UPLINK) { - mlx5e_vport_uplink_rep_unload(rpriv); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c 2025-10-22 13:53:56.575168852 -0400 -@@ -1154,8 +1154,9 @@ static void mlx5e_lro_update_tcp_hdr(str - } - } - --static void mlx5e_lro_update_hdr(struct sk_buff *skb, struct mlx5_cqe64 *cqe, -- u32 cqe_bcnt) -+static unsigned int mlx5e_lro_update_hdr(struct sk_buff *skb, -+ struct mlx5_cqe64 *cqe, -+ u32 cqe_bcnt) - { - struct ethhdr *eth = (struct ethhdr *)(skb->data); - struct tcphdr *tcp; -@@ -1205,6 +1206,8 @@ static void mlx5e_lro_update_hdr(struct - tcp->check = tcp_v6_check(payload_len, &ipv6->saddr, - &ipv6->daddr, check); - } -+ -+ return (unsigned int)((unsigned char *)tcp + tcp->doff * 4 - skb->data); - } - - static void *mlx5e_shampo_get_packet_hd(struct mlx5e_rq *rq, u16 header_index) -@@ -1561,8 +1564,10 @@ static inline void mlx5e_build_rx_skb(st - mlx5e_macsec_offload_handle_rx_skb(netdev, skb, cqe); - - if (lro_num_seg > 1) { -- mlx5e_lro_update_hdr(skb, cqe, cqe_bcnt); -- skb_shinfo(skb)->gso_size = DIV_ROUND_UP(cqe_bcnt, lro_num_seg); -+ unsigned int hdrlen = mlx5e_lro_update_hdr(skb, cqe, cqe_bcnt); -+ -+ skb_shinfo(skb)->gso_size = DIV_ROUND_UP(cqe_bcnt - hdrlen, lro_num_seg); -+ skb_shinfo(skb)->gso_segs = lro_num_seg; - /* Subtract one since we already counted this as one - * "regular" packet in mlx5e_complete_rx_cqe() - */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c 2025-10-22 13:53:23.347328493 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c 2025-10-22 13:53:56.575168852 -0400 -@@ -1466,6 +1466,7 @@ static void fec_set_block_stats(struct m - case MLX5E_FEC_RS_528_514: - case MLX5E_FEC_RS_544_514: - case MLX5E_FEC_LLRS_272_257_1: -+ case MLX5E_FEC_RS_544_514_INTERLEAVED_QUAD: - fec_set_rs_stats(fec_stats, out); - return; - case MLX5E_FEC_FIRECODE: -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c 2025-10-22 13:53:56.575168852 -0400 -@@ -2028,9 +2028,8 @@ err_out: - return err; - } - --static bool mlx5_flow_has_geneve_opt(struct mlx5e_tc_flow *flow) -+static bool mlx5_flow_has_geneve_opt(struct mlx5_flow_spec *spec) - { -- struct mlx5_flow_spec *spec = &flow->attr->parse_attr->spec; - void *headers_v = MLX5_ADDR_OF(fte_match_param, - spec->match_value, - misc_parameters_3); -@@ -2069,7 +2068,7 @@ static void mlx5e_tc_del_fdb_flow(struct - } - complete_all(&flow->del_hw_done); - -- if (mlx5_flow_has_geneve_opt(flow)) -+ if (mlx5_flow_has_geneve_opt(&attr->parse_attr->spec)) - mlx5_geneve_tlv_option_del(priv->mdev->geneve); - - if (flow->decap_route) -@@ -2574,12 +2573,13 @@ static int parse_tunnel_attr(struct mlx5 - - err = mlx5e_tc_tun_parse(filter_dev, priv, tmp_spec, f, match_level); - if (err) { -- kvfree(tmp_spec); - NL_SET_ERR_MSG_MOD(extack, "Failed to parse tunnel attributes"); - netdev_warn(priv->netdev, "Failed to parse tunnel attributes"); -- return err; -+ } else { -+ err = mlx5e_tc_set_attr_rx_tun(flow, tmp_spec); - } -- err = mlx5e_tc_set_attr_rx_tun(flow, tmp_spec); -+ if (mlx5_flow_has_geneve_opt(tmp_spec)) -+ mlx5_geneve_tlv_option_del(priv->mdev->geneve); - kvfree(tmp_spec); - if (err) - return err; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c 2025-10-22 13:53:56.575168852 -0400 -@@ -47,10 +47,12 @@ static void mlx5_esw_offloads_pf_vf_devl - devlink_port_attrs_pci_vf_set(dl_port, controller_num, pfnum, - vport_num - 1, external); - } else if (mlx5_core_is_ec_vf_vport(esw->dev, vport_num)) { -+ u16 base_vport = mlx5_core_ec_vf_vport_base(dev); -+ - memcpy(dl_port->attrs.switch_id.id, ppid.id, ppid.id_len); - dl_port->attrs.switch_id.id_len = ppid.id_len; - devlink_port_attrs_pci_vf_set(dl_port, 0, pfnum, -- vport_num - 1, false); -+ vport_num - base_vport, false); - } - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c 2025-10-22 13:53:56.575168852 -0400 -@@ -743,6 +743,7 @@ static u32 mlx5_esw_qos_lag_link_speed_g - speed = lksettings.base.speed; - - out: -+ mlx5_uplink_netdev_put(mdev, slave); - return speed; - } - -@@ -1076,6 +1077,7 @@ static int esw_qos_vports_node_update_pa - return err; - } - esw_qos_node_set_parent(node, parent); -+ node->bw_share = 0; - - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c 2025-10-22 13:53:56.575168852 -0400 -@@ -1295,12 +1295,15 @@ mlx5_eswitch_enable_pf_vf_vports(struct - ret = mlx5_eswitch_load_pf_vf_vport(esw, MLX5_VPORT_ECPF, enabled_events); - if (ret) - goto ecpf_err; -- if (mlx5_core_ec_sriov_enabled(esw->dev)) { -- ret = mlx5_eswitch_load_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs, -- enabled_events); -- if (ret) -- goto ec_vf_err; -- } -+ } -+ -+ /* Enable ECVF vports */ -+ if (mlx5_core_ec_sriov_enabled(esw->dev)) { -+ ret = mlx5_eswitch_load_ec_vf_vports(esw, -+ esw->esw_funcs.num_ec_vfs, -+ enabled_events); -+ if (ret) -+ goto ec_vf_err; - } - - /* Enable VF vports */ -@@ -1331,9 +1334,11 @@ void mlx5_eswitch_disable_pf_vf_vports(s - { - mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs); - -+ if (mlx5_core_ec_sriov_enabled(esw->dev)) -+ mlx5_eswitch_unload_ec_vf_vports(esw, -+ esw->esw_funcs.num_ec_vfs); -+ - if (mlx5_ecpf_vport_exists(esw->dev)) { -- if (mlx5_core_ec_sriov_enabled(esw->dev)) -- mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_vfs); - mlx5_eswitch_unload_pf_vf_vport(esw, MLX5_VPORT_ECPF); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c 2025-10-22 13:53:56.575168852 -0400 -@@ -1182,19 +1182,19 @@ static void esw_set_peer_miss_rule_sourc - static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw, - struct mlx5_core_dev *peer_dev) - { -+ struct mlx5_eswitch *peer_esw = peer_dev->priv.eswitch; - struct mlx5_flow_destination dest = {}; - struct mlx5_flow_act flow_act = {0}; - struct mlx5_flow_handle **flows; -- /* total vports is the same for both e-switches */ -- int nvports = esw->total_vports; - struct mlx5_flow_handle *flow; -+ struct mlx5_vport *peer_vport; - struct mlx5_flow_spec *spec; -- struct mlx5_vport *vport; - int err, pfindex; - unsigned long i; - void *misc; - -- if (!MLX5_VPORT_MANAGER(esw->dev) && !mlx5_core_is_ecpf_esw_manager(esw->dev)) -+ if (!MLX5_VPORT_MANAGER(peer_dev) && -+ !mlx5_core_is_ecpf_esw_manager(peer_dev)) - return 0; - - spec = kvzalloc(sizeof(*spec), GFP_KERNEL); -@@ -1203,7 +1203,7 @@ static int esw_add_fdb_peer_miss_rules(s - - peer_miss_rules_setup(esw, peer_dev, spec, &dest); - -- flows = kvcalloc(nvports, sizeof(*flows), GFP_KERNEL); -+ flows = kvcalloc(peer_esw->total_vports, sizeof(*flows), GFP_KERNEL); - if (!flows) { - err = -ENOMEM; - goto alloc_flows_err; -@@ -1213,10 +1213,10 @@ static int esw_add_fdb_peer_miss_rules(s - misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, - misc_parameters); - -- if (mlx5_core_is_ecpf_esw_manager(esw->dev)) { -- vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF); -- esw_set_peer_miss_rule_source_port(esw, peer_dev->priv.eswitch, -- spec, MLX5_VPORT_PF); -+ if (mlx5_core_is_ecpf_esw_manager(peer_dev)) { -+ peer_vport = mlx5_eswitch_get_vport(peer_esw, MLX5_VPORT_PF); -+ esw_set_peer_miss_rule_source_port(esw, peer_esw, spec, -+ MLX5_VPORT_PF); - - flow = mlx5_add_flow_rules(mlx5_eswitch_get_slow_fdb(esw), - spec, &flow_act, &dest, 1); -@@ -1224,11 +1224,11 @@ static int esw_add_fdb_peer_miss_rules(s - err = PTR_ERR(flow); - goto add_pf_flow_err; - } -- flows[vport->index] = flow; -+ flows[peer_vport->index] = flow; - } - -- if (mlx5_ecpf_vport_exists(esw->dev)) { -- vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_ECPF); -+ if (mlx5_ecpf_vport_exists(peer_dev)) { -+ peer_vport = mlx5_eswitch_get_vport(peer_esw, MLX5_VPORT_ECPF); - MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_ECPF); - flow = mlx5_add_flow_rules(mlx5_eswitch_get_slow_fdb(esw), - spec, &flow_act, &dest, 1); -@@ -1236,13 +1236,14 @@ static int esw_add_fdb_peer_miss_rules(s - err = PTR_ERR(flow); - goto add_ecpf_flow_err; - } -- flows[vport->index] = flow; -+ flows[peer_vport->index] = flow; - } - -- mlx5_esw_for_each_vf_vport(esw, i, vport, mlx5_core_max_vfs(esw->dev)) { -+ mlx5_esw_for_each_vf_vport(peer_esw, i, peer_vport, -+ mlx5_core_max_vfs(peer_dev)) { - esw_set_peer_miss_rule_source_port(esw, -- peer_dev->priv.eswitch, -- spec, vport->vport); -+ peer_esw, -+ spec, peer_vport->vport); - - flow = mlx5_add_flow_rules(mlx5_eswitch_get_slow_fdb(esw), - spec, &flow_act, &dest, 1); -@@ -1250,22 +1251,22 @@ static int esw_add_fdb_peer_miss_rules(s - err = PTR_ERR(flow); - goto add_vf_flow_err; - } -- flows[vport->index] = flow; -+ flows[peer_vport->index] = flow; - } - -- if (mlx5_core_ec_sriov_enabled(esw->dev)) { -- mlx5_esw_for_each_ec_vf_vport(esw, i, vport, mlx5_core_max_ec_vfs(esw->dev)) { -- if (i >= mlx5_core_max_ec_vfs(peer_dev)) -- break; -- esw_set_peer_miss_rule_source_port(esw, peer_dev->priv.eswitch, -- spec, vport->vport); -+ if (mlx5_core_ec_sriov_enabled(peer_dev)) { -+ mlx5_esw_for_each_ec_vf_vport(peer_esw, i, peer_vport, -+ mlx5_core_max_ec_vfs(peer_dev)) { -+ esw_set_peer_miss_rule_source_port(esw, peer_esw, -+ spec, -+ peer_vport->vport); - flow = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb, - spec, &flow_act, &dest, 1); - if (IS_ERR(flow)) { - err = PTR_ERR(flow); - goto add_ec_vf_flow_err; - } -- flows[vport->index] = flow; -+ flows[peer_vport->index] = flow; - } - } - -@@ -1282,25 +1283,27 @@ static int esw_add_fdb_peer_miss_rules(s - return 0; - - add_ec_vf_flow_err: -- mlx5_esw_for_each_ec_vf_vport(esw, i, vport, mlx5_core_max_ec_vfs(esw->dev)) { -- if (!flows[vport->index]) -+ mlx5_esw_for_each_ec_vf_vport(peer_esw, i, peer_vport, -+ mlx5_core_max_ec_vfs(peer_dev)) { -+ if (!flows[peer_vport->index]) - continue; -- mlx5_del_flow_rules(flows[vport->index]); -+ mlx5_del_flow_rules(flows[peer_vport->index]); - } - add_vf_flow_err: -- mlx5_esw_for_each_vf_vport(esw, i, vport, mlx5_core_max_vfs(esw->dev)) { -- if (!flows[vport->index]) -+ mlx5_esw_for_each_vf_vport(peer_esw, i, peer_vport, -+ mlx5_core_max_vfs(peer_dev)) { -+ if (!flows[peer_vport->index]) - continue; -- mlx5_del_flow_rules(flows[vport->index]); -+ mlx5_del_flow_rules(flows[peer_vport->index]); - } -- if (mlx5_ecpf_vport_exists(esw->dev)) { -- vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_ECPF); -- mlx5_del_flow_rules(flows[vport->index]); -+ if (mlx5_ecpf_vport_exists(peer_dev)) { -+ peer_vport = mlx5_eswitch_get_vport(peer_esw, MLX5_VPORT_ECPF); -+ mlx5_del_flow_rules(flows[peer_vport->index]); - } - add_ecpf_flow_err: -- if (mlx5_core_is_ecpf_esw_manager(esw->dev)) { -- vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF); -- mlx5_del_flow_rules(flows[vport->index]); -+ if (mlx5_core_is_ecpf_esw_manager(peer_dev)) { -+ peer_vport = mlx5_eswitch_get_vport(peer_esw, MLX5_VPORT_PF); -+ mlx5_del_flow_rules(flows[peer_vport->index]); - } - add_pf_flow_err: - esw_warn(esw->dev, "FDB: Failed to add peer miss flow rule err %d\n", err); -@@ -1313,37 +1316,34 @@ alloc_flows_err: - static void esw_del_fdb_peer_miss_rules(struct mlx5_eswitch *esw, - struct mlx5_core_dev *peer_dev) - { -+ struct mlx5_eswitch *peer_esw = peer_dev->priv.eswitch; - u16 peer_index = mlx5_get_dev_index(peer_dev); - struct mlx5_flow_handle **flows; -- struct mlx5_vport *vport; -+ struct mlx5_vport *peer_vport; - unsigned long i; - - flows = esw->fdb_table.offloads.peer_miss_rules[peer_index]; - if (!flows) - return; - -- if (mlx5_core_ec_sriov_enabled(esw->dev)) { -- mlx5_esw_for_each_ec_vf_vport(esw, i, vport, mlx5_core_max_ec_vfs(esw->dev)) { -- /* The flow for a particular vport could be NULL if the other ECPF -- * has fewer or no VFs enabled -- */ -- if (!flows[vport->index]) -- continue; -- mlx5_del_flow_rules(flows[vport->index]); -- } -+ if (mlx5_core_ec_sriov_enabled(peer_dev)) { -+ mlx5_esw_for_each_ec_vf_vport(peer_esw, i, peer_vport, -+ mlx5_core_max_ec_vfs(peer_dev)) -+ mlx5_del_flow_rules(flows[peer_vport->index]); - } - -- mlx5_esw_for_each_vf_vport(esw, i, vport, mlx5_core_max_vfs(esw->dev)) -- mlx5_del_flow_rules(flows[vport->index]); -+ mlx5_esw_for_each_vf_vport(peer_esw, i, peer_vport, -+ mlx5_core_max_vfs(peer_dev)) -+ mlx5_del_flow_rules(flows[peer_vport->index]); - -- if (mlx5_ecpf_vport_exists(esw->dev)) { -- vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_ECPF); -- mlx5_del_flow_rules(flows[vport->index]); -+ if (mlx5_ecpf_vport_exists(peer_dev)) { -+ peer_vport = mlx5_eswitch_get_vport(peer_esw, MLX5_VPORT_ECPF); -+ mlx5_del_flow_rules(flows[peer_vport->index]); - } - -- if (mlx5_core_is_ecpf_esw_manager(esw->dev)) { -- vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF); -- mlx5_del_flow_rules(flows[vport->index]); -+ if (mlx5_core_is_ecpf_esw_manager(peer_dev)) { -+ peer_vport = mlx5_eswitch_get_vport(peer_esw, MLX5_VPORT_PF); -+ mlx5_del_flow_rules(flows[peer_vport->index]); - } - - kvfree(flows); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c 2025-10-22 13:53:56.575168852 -0400 -@@ -113,13 +113,16 @@ - #define ETHTOOL_PRIO_NUM_LEVELS 1 - #define ETHTOOL_NUM_PRIOS 11 - #define ETHTOOL_MIN_LEVEL (KERNEL_MIN_LEVEL + ETHTOOL_NUM_PRIOS) --/* Promiscuous, Vlan, mac, ttc, inner ttc, {UDP/ANY/aRFS/accel/{esp, esp_err}}, IPsec policy, -- * {IPsec RoCE MPV,Alias table},IPsec RoCE policy -+/* Vlan, mac, ttc, inner ttc, {UDP/ANY/aRFS/accel/{esp, esp_err}}, IPsec policy, -+ * IPsec policy miss, {IPsec RoCE MPV,Alias table},IPsec RoCE policy - */ - #define KERNEL_NIC_PRIO_NUM_LEVELS 11 - #define KERNEL_NIC_NUM_PRIOS 1 --/* One more level for tc */ --#define KERNEL_MIN_LEVEL (KERNEL_NIC_PRIO_NUM_LEVELS + 1) -+/* One more level for tc, and one more for promisc */ -+#define KERNEL_MIN_LEVEL (KERNEL_NIC_PRIO_NUM_LEVELS + 2) -+ -+#define KERNEL_NIC_PROMISC_NUM_PRIOS 1 -+#define KERNEL_NIC_PROMISC_NUM_LEVELS 1 - - #define KERNEL_NIC_TC_NUM_PRIOS 1 - #define KERNEL_NIC_TC_NUM_LEVELS 3 -@@ -187,6 +190,8 @@ static struct init_tree_node { - ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_DEF, - ADD_MULTIPLE_PRIO(KERNEL_NIC_TC_NUM_PRIOS, - KERNEL_NIC_TC_NUM_LEVELS), -+ ADD_MULTIPLE_PRIO(KERNEL_NIC_PROMISC_NUM_PRIOS, -+ KERNEL_NIC_PROMISC_NUM_LEVELS), - ADD_MULTIPLE_PRIO(KERNEL_NIC_NUM_PRIOS, - KERNEL_NIC_PRIO_NUM_LEVELS))), - ADD_PRIO(0, BY_PASS_MIN_LEVEL, 0, FS_CHAINING_CAPS, -@@ -658,7 +663,7 @@ static void del_sw_hw_rule(struct fs_nod - BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_ACTION) | - BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_FLOW_COUNTERS); - fte->act_dests.action.action &= ~MLX5_FLOW_CONTEXT_ACTION_COUNT; -- mlx5_fc_local_destroy(rule->dest_attr.counter); -+ mlx5_fc_local_put(rule->dest_attr.counter); - goto out; - } - -@@ -2228,6 +2233,7 @@ try_add_to_existing_fg(struct mlx5_flow_ - struct mlx5_flow_handle *rule; - struct match_list *iter; - bool take_write = false; -+ bool try_again = false; - struct fs_fte *fte; - u64 version = 0; - int err; -@@ -2292,6 +2298,7 @@ skip_search: - nested_down_write_ref_node(&g->node, FS_LOCK_PARENT); - - if (!g->node.active) { -+ try_again = true; - up_write_ref_node(&g->node, false); - continue; - } -@@ -2313,7 +2320,8 @@ skip_search: - tree_put_node(&fte->node, false); - return rule; - } -- rule = ERR_PTR(-ENOENT); -+ err = try_again ? -EAGAIN : -ENOENT; -+ rule = ERR_PTR(err); - out: - kmem_cache_free(steering->ftes_cache, fte); - return rule; -@@ -3698,6 +3706,13 @@ static int mlx5_fs_mode_validate(struct - char *value = val.vstr; - u8 eswitch_mode; - -+ eswitch_mode = mlx5_eswitch_mode(dev); -+ if (eswitch_mode == MLX5_ESWITCH_OFFLOADS) { -+ NL_SET_ERR_MSG_FMT_MOD(extack, -+ "Changing fs mode is not supported when eswitch offloads enabled."); -+ return -EOPNOTSUPP; -+ } -+ - if (!strcmp(value, "dmfs")) - return 0; - -@@ -3723,14 +3738,6 @@ static int mlx5_fs_mode_validate(struct - return -EINVAL; - } - -- eswitch_mode = mlx5_eswitch_mode(dev); -- if (eswitch_mode == MLX5_ESWITCH_OFFLOADS) { -- NL_SET_ERR_MSG_FMT_MOD(extack, -- "Moving to %s is not supported when eswitch offloads enabled.", -- value); -- return -EOPNOTSUPP; -- } -- - return 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h 2025-10-22 13:53:56.575168852 -0400 -@@ -343,6 +343,7 @@ struct mlx5_fc { - enum mlx5_fc_type type; - struct mlx5_fc_bulk *bulk; - struct mlx5_fc_cache cache; -+ refcount_t fc_local_refcount; - /* last{packets,bytes} are used for calculating deltas since last reading. */ - u64 lastpackets; - u64 lastbytes; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c 2025-10-22 13:53:56.575168852 -0400 -@@ -562,17 +562,36 @@ mlx5_fc_local_create(u32 counter_id, u32 - counter->id = counter_id; - fc_bulk->base_id = counter_id - offset; - fc_bulk->fs_bulk.bulk_len = bulk_size; -+ refcount_set(&fc_bulk->hws_data.hws_action_refcount, 0); -+ mutex_init(&fc_bulk->hws_data.lock); - counter->bulk = fc_bulk; -+ refcount_set(&counter->fc_local_refcount, 1); - return counter; - } - EXPORT_SYMBOL(mlx5_fc_local_create); - - void mlx5_fc_local_destroy(struct mlx5_fc *counter) - { -- if (!counter || counter->type != MLX5_FC_TYPE_LOCAL) -- return; -- - kfree(counter->bulk); - kfree(counter); - } - EXPORT_SYMBOL(mlx5_fc_local_destroy); -+ -+void mlx5_fc_local_get(struct mlx5_fc *counter) -+{ -+ if (!counter || counter->type != MLX5_FC_TYPE_LOCAL) -+ return; -+ -+ refcount_inc(&counter->fc_local_refcount); -+} -+ -+void mlx5_fc_local_put(struct mlx5_fc *counter) -+{ -+ if (!counter || counter->type != MLX5_FC_TYPE_LOCAL) -+ return; -+ -+ if (!refcount_dec_and_test(&counter->fc_local_refcount)) -+ return; -+ -+ mlx5_fc_local_destroy(counter); -+} -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c 2025-10-22 13:53:56.579168833 -0400 -@@ -6,13 +6,15 @@ - #include "fw_reset.h" - #include "diag/fw_tracer.h" - #include "lib/tout.h" -+#include "sf/sf.h" - - enum { - MLX5_FW_RESET_FLAGS_RESET_REQUESTED, - MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST, - MLX5_FW_RESET_FLAGS_PENDING_COMP, - MLX5_FW_RESET_FLAGS_DROP_NEW_REQUESTS, -- MLX5_FW_RESET_FLAGS_RELOAD_REQUIRED -+ MLX5_FW_RESET_FLAGS_RELOAD_REQUIRED, -+ MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, - }; - - struct mlx5_fw_reset { -@@ -219,7 +221,7 @@ int mlx5_fw_reset_set_live_patch(struct - return mlx5_reg_mfrl_set(dev, MLX5_MFRL_REG_RESET_LEVEL0, 0, 0, false); - } - --static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev, bool unloaded) -+static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev) - { - struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; - struct devlink *devlink = priv_to_devlink(dev); -@@ -228,8 +230,7 @@ static void mlx5_fw_reset_complete_reloa - if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) { - complete(&fw_reset->done); - } else { -- if (!unloaded) -- mlx5_unload_one(dev, false); -+ mlx5_sync_reset_unload_flow(dev, false); - if (mlx5_health_wait_pci_up(dev)) - mlx5_core_err(dev, "reset reload flow aborted, PCI reads still not working\n"); - else -@@ -272,7 +273,7 @@ static void mlx5_sync_reset_reload_work( - - mlx5_sync_reset_clear_reset_requested(dev, false); - mlx5_enter_error_state(dev, true); -- mlx5_fw_reset_complete_reload(dev, false); -+ mlx5_fw_reset_complete_reload(dev); - } - - #define MLX5_RESET_POLL_INTERVAL (HZ / 10) -@@ -428,6 +429,11 @@ static bool mlx5_is_reset_now_capable(st - return false; - } - -+ if (!mlx5_core_is_ecpf(dev) && !mlx5_sf_table_empty(dev)) { -+ mlx5_core_warn(dev, "SFs should be removed before reset\n"); -+ return false; -+ } -+ - #if IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE) - if (reset_method != MLX5_MFRL_REG_PCI_RESET_METHOD_HOT_RESET) { - err = mlx5_check_hotplug_interrupt(dev, bridge); -@@ -586,6 +592,65 @@ static int mlx5_sync_pci_reset(struct ml - return err; - } - -+void mlx5_sync_reset_unload_flow(struct mlx5_core_dev *dev, bool locked) -+{ -+ struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; -+ unsigned long timeout; -+ int poll_freq = 20; -+ bool reset_action; -+ u8 rst_state; -+ int err; -+ -+ if (locked) -+ mlx5_unload_one_devl_locked(dev, false); -+ else -+ mlx5_unload_one(dev, false); -+ -+ if (!test_bit(MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, &fw_reset->reset_flags)) -+ return; -+ -+ mlx5_set_fw_rst_ack(dev); -+ mlx5_core_warn(dev, "Sync Reset Unload done, device reset expected\n"); -+ -+ reset_action = false; -+ timeout = jiffies + msecs_to_jiffies(mlx5_tout_ms(dev, RESET_UNLOAD)); -+ do { -+ rst_state = mlx5_get_fw_rst_state(dev); -+ if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ || -+ rst_state == MLX5_FW_RST_STATE_IDLE) { -+ reset_action = true; -+ break; -+ } -+ if (rst_state == MLX5_FW_RST_STATE_DROP_MODE) { -+ mlx5_core_info(dev, "Sync Reset Drop mode ack\n"); -+ mlx5_set_fw_rst_ack(dev); -+ poll_freq = 1000; -+ } -+ msleep(poll_freq); -+ } while (!time_after(jiffies, timeout)); -+ -+ if (!reset_action) { -+ mlx5_core_err(dev, "Got timeout waiting for sync reset action, state = %u\n", -+ rst_state); -+ fw_reset->ret = -ETIMEDOUT; -+ goto done; -+ } -+ -+ mlx5_core_warn(dev, "Sync Reset, got reset action. rst_state = %u\n", -+ rst_state); -+ if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ) { -+ err = mlx5_sync_pci_reset(dev, fw_reset->reset_method); -+ if (err) { -+ mlx5_core_warn(dev, "mlx5_sync_pci_reset failed, err %d\n", -+ err); -+ fw_reset->ret = err; -+ } -+ } -+ -+done: -+ clear_bit(MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, &fw_reset->reset_flags); -+} -+ - static void mlx5_sync_reset_now_event(struct work_struct *work) - { - struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset, -@@ -613,17 +678,13 @@ static void mlx5_sync_reset_now_event(st - mlx5_enter_error_state(dev, true); - done: - fw_reset->ret = err; -- mlx5_fw_reset_complete_reload(dev, false); -+ mlx5_fw_reset_complete_reload(dev); - } - - static void mlx5_sync_reset_unload_event(struct work_struct *work) - { - struct mlx5_fw_reset *fw_reset; - struct mlx5_core_dev *dev; -- unsigned long timeout; -- int poll_freq = 20; -- bool reset_action; -- u8 rst_state; - int err; - - fw_reset = container_of(work, struct mlx5_fw_reset, reset_unload_work); -@@ -632,6 +693,7 @@ static void mlx5_sync_reset_unload_event - if (mlx5_sync_reset_clear_reset_requested(dev, false)) - return; - -+ set_bit(MLX5_FW_RESET_FLAGS_UNLOAD_EVENT, &fw_reset->reset_flags); - mlx5_core_warn(dev, "Sync Reset Unload. Function is forced down.\n"); - - err = mlx5_cmd_fast_teardown_hca(dev); -@@ -640,49 +702,7 @@ static void mlx5_sync_reset_unload_event - else - mlx5_enter_error_state(dev, true); - -- if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) -- mlx5_unload_one_devl_locked(dev, false); -- else -- mlx5_unload_one(dev, false); -- -- mlx5_set_fw_rst_ack(dev); -- mlx5_core_warn(dev, "Sync Reset Unload done, device reset expected\n"); -- -- reset_action = false; -- timeout = jiffies + msecs_to_jiffies(mlx5_tout_ms(dev, RESET_UNLOAD)); -- do { -- rst_state = mlx5_get_fw_rst_state(dev); -- if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ || -- rst_state == MLX5_FW_RST_STATE_IDLE) { -- reset_action = true; -- break; -- } -- if (rst_state == MLX5_FW_RST_STATE_DROP_MODE) { -- mlx5_core_info(dev, "Sync Reset Drop mode ack\n"); -- mlx5_set_fw_rst_ack(dev); -- poll_freq = 1000; -- } -- msleep(poll_freq); -- } while (!time_after(jiffies, timeout)); -- -- if (!reset_action) { -- mlx5_core_err(dev, "Got timeout waiting for sync reset action, state = %u\n", -- rst_state); -- fw_reset->ret = -ETIMEDOUT; -- goto done; -- } -- -- mlx5_core_warn(dev, "Sync Reset, got reset action. rst_state = %u\n", rst_state); -- if (rst_state == MLX5_FW_RST_STATE_TOGGLE_REQ) { -- err = mlx5_sync_pci_reset(dev, fw_reset->reset_method); -- if (err) { -- mlx5_core_warn(dev, "mlx5_sync_pci_reset failed, err %d\n", err); -- fw_reset->ret = err; -- } -- } -- --done: -- mlx5_fw_reset_complete_reload(dev, true); -+ mlx5_fw_reset_complete_reload(dev); - } - - static void mlx5_sync_reset_abort_event(struct work_struct *work) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.h 2025-10-22 13:53:56.579168833 -0400 -@@ -12,6 +12,7 @@ int mlx5_fw_reset_set_reset_sync(struct - int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev); - - int mlx5_fw_reset_wait_reset_done(struct mlx5_core_dev *dev); -+void mlx5_sync_reset_unload_flow(struct mlx5_core_dev *dev, bool locked); - int mlx5_fw_reset_verify_fw_complete(struct mlx5_core_dev *dev, - struct netlink_ext_ack *extack); - void mlx5_fw_reset_events_start(struct mlx5_core_dev *dev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/lib/dm.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/lib/dm.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/lib/dm.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/lib/dm.c 2025-10-22 13:53:56.579168833 -0400 -@@ -30,7 +30,7 @@ struct mlx5_dm *mlx5_dm_create(struct ml - - dm = kzalloc(sizeof(*dm), GFP_KERNEL); - if (!dm) -- return ERR_PTR(-ENOMEM); -+ return NULL; - - spin_lock_init(&dm->lock); - -@@ -96,7 +96,7 @@ err_modify_hdr: - err_steering: - kfree(dm); - -- return ERR_PTR(-ENOMEM); -+ return NULL; - } - - void mlx5_dm_cleanup(struct mlx5_core_dev *dev) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h 2025-10-22 13:53:56.579168833 -0400 -@@ -52,7 +52,20 @@ static inline struct net *mlx5_core_net( - - static inline struct net_device *mlx5_uplink_netdev_get(struct mlx5_core_dev *mdev) - { -- return mdev->mlx5e_res.uplink_netdev; -+ struct mlx5e_resources *mlx5e_res = &mdev->mlx5e_res; -+ struct net_device *netdev; -+ -+ mutex_lock(&mlx5e_res->uplink_netdev_lock); -+ netdev = mlx5e_res->uplink_netdev; -+ netdev_hold(netdev, &mlx5e_res->tracker, GFP_KERNEL); -+ mutex_unlock(&mlx5e_res->uplink_netdev_lock); -+ return netdev; -+} -+ -+static inline void mlx5_uplink_netdev_put(struct mlx5_core_dev *mdev, -+ struct net_device *netdev) -+{ -+ netdev_put(netdev, &mdev->mlx5e_res.tracker); - } - - struct mlx5_sd; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/main.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/main.c 2025-10-22 13:53:56.579168833 -0400 -@@ -1102,9 +1102,6 @@ static int mlx5_init_once(struct mlx5_co - } - - dev->dm = mlx5_dm_create(dev); -- if (IS_ERR(dev->dm)) -- mlx5_core_warn(dev, "Failed to init device memory %ld\n", PTR_ERR(dev->dm)); -- - dev->tracer = mlx5_fw_tracer_create(dev); - dev->hv_vhca = mlx5_hv_vhca_create(dev); - dev->rsc_dump = mlx5_rsc_dump_create(dev); -@@ -2257,6 +2254,7 @@ static const struct pci_device_id mlx5_c - { PCI_VDEVICE(MELLANOX, 0x1021) }, /* ConnectX-7 */ - { PCI_VDEVICE(MELLANOX, 0x1023) }, /* ConnectX-8 */ - { PCI_VDEVICE(MELLANOX, 0x1025) }, /* ConnectX-9 */ -+ { PCI_VDEVICE(MELLANOX, 0x1027) }, /* ConnectX-10 */ - { PCI_VDEVICE(MELLANOX, 0xa2d2) }, /* BlueField integrated ConnectX-5 network controller */ - { PCI_VDEVICE(MELLANOX, 0xa2d3), MLX5_PCI_DEV_IS_VF}, /* BlueField integrated ConnectX-5 network controller VF */ - { PCI_VDEVICE(MELLANOX, 0xa2d6) }, /* BlueField-2 integrated ConnectX-6 Dx network controller */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h 2025-10-22 13:53:56.579168833 -0400 -@@ -358,6 +358,8 @@ int mlx5_query_port_dcbx_param(struct ml - int mlx5_set_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *in); - int mlx5_set_trust_state(struct mlx5_core_dev *mdev, u8 trust_state); - int mlx5_query_trust_state(struct mlx5_core_dev *mdev, u8 *trust_state); -+int mlx5_query_port_buffer_ownership(struct mlx5_core_dev *mdev, -+ u8 *buffer_ownership); - int mlx5_set_dscp2prio(struct mlx5_core_dev *mdev, u8 dscp, u8 prio); - int mlx5_query_dscp2prio(struct mlx5_core_dev *mdev, u8 *dscp2prio); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c 2025-10-22 13:53:56.579168833 -0400 -@@ -291,7 +291,7 @@ static void free_4k(struct mlx5_core_dev - static int alloc_system_page(struct mlx5_core_dev *dev, u32 function) - { - struct device *device = mlx5_core_dma_dev(dev); -- int nid = dev_to_node(device); -+ int nid = dev->priv.numa_node; - struct page *page; - u64 zero_addr = 1; - u64 addr; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/port.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/port.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/port.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/port.c 2025-10-22 13:53:56.579168833 -0400 -@@ -968,6 +968,26 @@ int mlx5_query_trust_state(struct mlx5_c - return err; - } - -+int mlx5_query_port_buffer_ownership(struct mlx5_core_dev *mdev, -+ u8 *buffer_ownership) -+{ -+ u32 out[MLX5_ST_SZ_DW(pfcc_reg)] = {}; -+ int err; -+ -+ if (!MLX5_CAP_PCAM_FEATURE(mdev, buffer_ownership)) { -+ *buffer_ownership = MLX5_BUF_OWNERSHIP_UNKNOWN; -+ return 0; -+ } -+ -+ err = mlx5_query_pfcc_reg(mdev, out, sizeof(out)); -+ if (err) -+ return err; -+ -+ *buffer_ownership = MLX5_GET(pfcc_reg, out, buf_ownership); -+ -+ return 0; -+} -+ - int mlx5_set_dscp2prio(struct mlx5_core_dev *mdev, u8 dscp, u8 prio) - { - int sz = MLX5_ST_SZ_BYTES(qpdpm_reg); -@@ -1150,7 +1170,11 @@ const struct mlx5_link_info *mlx5_port_p - mlx5e_port_get_link_mode_info_arr(mdev, &table, &max_size, - force_legacy); - i = find_first_bit(&temp, max_size); -- if (i < max_size) -+ -+ /* mlx5e_link_info has holes. Check speed -+ * is not zero as indication of one. -+ */ -+ if (i < max_size && table[i].speed) - return &table[i]; - - return NULL; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c 2025-10-22 13:53:56.579168833 -0400 -@@ -518,3 +518,13 @@ void mlx5_sf_table_cleanup(struct mlx5_c - WARN_ON(!xa_empty(&table->function_ids)); - kfree(table); - } -+ -+bool mlx5_sf_table_empty(const struct mlx5_core_dev *dev) -+{ -+ struct mlx5_sf_table *table = dev->priv.sf_table; -+ -+ if (!table) -+ return true; -+ -+ return xa_empty(&table->function_ids); -+} -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h 2025-10-22 13:53:56.579168833 -0400 -@@ -17,6 +17,7 @@ void mlx5_sf_hw_table_destroy(struct mlx - - int mlx5_sf_table_init(struct mlx5_core_dev *dev); - void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev); -+bool mlx5_sf_table_empty(const struct mlx5_core_dev *dev); - - int mlx5_devlink_sf_port_new(struct devlink *devlink, - const struct devlink_port_new_attrs *add_attr, -@@ -61,6 +62,11 @@ static inline void mlx5_sf_table_cleanup - { - } - -+static inline bool mlx5_sf_table_empty(const struct mlx5_core_dev *dev) -+{ -+ return true; -+} -+ - #endif - - #endif -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c 2025-10-22 13:53:56.579168833 -0400 -@@ -117,7 +117,7 @@ static int hws_action_get_shared_stc_nic - mlx5hws_err(ctx, "No such stc_type: %d\n", stc_type); - pr_warn("HWS: Invalid stc_type: %d\n", stc_type); - ret = -EINVAL; -- goto unlock_and_out; -+ goto free_shared_stc; - } - - ret = mlx5hws_action_alloc_single_stc(ctx, &stc_attr, tbl_type, -@@ -1358,11 +1358,8 @@ free_action: - } - - struct mlx5hws_action * --mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx, -- size_t num_dest, -+mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx, size_t num_dest, - struct mlx5hws_action_dest_attr *dests, -- bool ignore_flow_level, -- u32 flow_source, - u32 flags) - { - struct mlx5hws_cmd_set_fte_dest *dest_list = NULL; -@@ -1370,8 +1367,8 @@ mlx5hws_action_create_dest_array(struct - struct mlx5hws_cmd_set_fte_attr fte_attr = {0}; - struct mlx5hws_cmd_forward_tbl *fw_island; - struct mlx5hws_action *action; -- u32 i /*, packet_reformat_id*/; -- int ret; -+ int ret, last_dest_idx = -1; -+ u32 i; - - if (num_dest <= 1) { - mlx5hws_err(ctx, "Action must have multiple dests\n"); -@@ -1400,12 +1397,9 @@ mlx5hws_action_create_dest_array(struct - MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; - dest_list[i].destination_id = dests[i].dest->dest_obj.obj_id; - fte_attr.action_flags |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; -- fte_attr.ignore_flow_level = ignore_flow_level; -- /* ToDo: In SW steering we have a handling of 'go to WIRE' -- * destination here by upper layer setting 'is_wire_ft' flag -- * if the destination is wire. -- * This is because uplink should be last dest in the list. -- */ -+ fte_attr.ignore_flow_level = 1; -+ if (dests[i].is_wire_ft) -+ last_dest_idx = i; - break; - case MLX5HWS_ACTION_TYP_VPORT: - dest_list[i].destination_type = MLX5_FLOW_DESTINATION_TYPE_VPORT; -@@ -1429,6 +1423,9 @@ mlx5hws_action_create_dest_array(struct - } - } - -+ if (last_dest_idx != -1) -+ swap(dest_list[last_dest_idx], dest_list[num_dest - 1]); -+ - fte_attr.dests_num = num_dest; - fte_attr.dests = dest_list; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc_complex.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc_complex.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc_complex.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc_complex.c 2025-10-22 13:53:56.579168833 -0400 -@@ -1070,7 +1070,7 @@ hws_bwc_rule_complex_hash_node_get(struc - struct mlx5hws_bwc_matcher *bwc_matcher = bwc_rule->bwc_matcher; - struct mlx5hws_bwc_complex_rule_hash_node *node, *old_node; - struct rhashtable *refcount_hash; -- int i; -+ int ret, i; - - bwc_rule->complex_hash_node = NULL; - -@@ -1078,7 +1078,11 @@ hws_bwc_rule_complex_hash_node_get(struc - if (unlikely(!node)) - return -ENOMEM; - -- node->tag = ida_alloc(&bwc_matcher->complex->metadata_ida, GFP_KERNEL); -+ ret = ida_alloc(&bwc_matcher->complex->metadata_ida, GFP_KERNEL); -+ if (ret < 0) -+ goto err_free_node; -+ node->tag = ret; -+ - refcount_set(&node->refcount, 1); - - /* Clear match buffer - turn off all the unrelated fields -@@ -1094,6 +1098,11 @@ hws_bwc_rule_complex_hash_node_get(struc - old_node = rhashtable_lookup_get_insert_fast(refcount_hash, - &node->hash_node, - hws_refcount_hash); -+ if (IS_ERR(old_node)) { -+ ret = PTR_ERR(old_node); -+ goto err_free_ida; -+ } -+ - if (old_node) { - /* Rule with the same tag already exists - update refcount */ - refcount_inc(&old_node->refcount); -@@ -1112,6 +1121,12 @@ hws_bwc_rule_complex_hash_node_get(struc - - bwc_rule->complex_hash_node = node; - return 0; -+ -+err_free_ida: -+ ida_free(&bwc_matcher->complex->metadata_ida, node->tag); -+err_free_node: -+ kfree(node); -+ return ret; - } - - static void -@@ -1313,11 +1328,11 @@ mlx5hws_bwc_matcher_move_all_complex(str - { - struct mlx5hws_context *ctx = bwc_matcher->matcher->tbl->ctx; - struct mlx5hws_matcher *matcher = bwc_matcher->matcher; -- bool move_error = false, poll_error = false; - u16 bwc_queues = mlx5hws_bwc_queues(ctx); - struct mlx5hws_bwc_rule *tmp_bwc_rule; - struct mlx5hws_rule_attr rule_attr; - struct mlx5hws_table *isolated_tbl; -+ int move_error = 0, poll_error = 0; - struct mlx5hws_rule *tmp_rule; - struct list_head *rules_list; - u32 expected_completions = 1; -@@ -1376,11 +1391,15 @@ mlx5hws_bwc_matcher_move_all_complex(str - ret = mlx5hws_matcher_resize_rule_move(matcher, - tmp_rule, - &rule_attr); -- if (unlikely(ret && !move_error)) { -- mlx5hws_err(ctx, -- "Moving complex BWC rule failed (%d), attempting to move rest of the rules\n", -- ret); -- move_error = true; -+ if (unlikely(ret)) { -+ if (!move_error) { -+ mlx5hws_err(ctx, -+ "Moving complex BWC rule: move failed (%d), attempting to move rest of the rules\n", -+ ret); -+ move_error = ret; -+ } -+ /* Rule wasn't queued, no need to poll */ -+ continue; - } - - expected_completions = 1; -@@ -1388,11 +1407,19 @@ mlx5hws_bwc_matcher_move_all_complex(str - rule_attr.queue_id, - &expected_completions, - true); -- if (unlikely(ret && !poll_error)) { -- mlx5hws_err(ctx, -- "Moving complex BWC rule: poll failed (%d), attempting to move rest of the rules\n", -- ret); -- poll_error = true; -+ if (unlikely(ret)) { -+ if (ret == -ETIMEDOUT) { -+ mlx5hws_err(ctx, -+ "Moving complex BWC rule: timeout polling for completions (%d), aborting rehash\n", -+ ret); -+ return ret; -+ } -+ if (!poll_error) { -+ mlx5hws_err(ctx, -+ "Moving complex BWC rule: polling for completions failed (%d), attempting to move rest of the rules\n", -+ ret); -+ poll_error = ret; -+ } - } - - /* Done moving the rule to the new matcher, -@@ -1407,8 +1434,11 @@ mlx5hws_bwc_matcher_move_all_complex(str - } - } - -- if (move_error || poll_error) -- ret = -EINVAL; -+ /* Return the first error that happened */ -+ if (unlikely(move_error)) -+ return move_error; -+ if (unlikely(poll_error)) -+ return poll_error; - - return ret; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.c 2025-10-22 13:53:56.579168833 -0400 -@@ -55,6 +55,7 @@ int mlx5hws_cmd_flow_table_create(struct - - MLX5_SET(create_flow_table_in, in, opcode, MLX5_CMD_OP_CREATE_FLOW_TABLE); - MLX5_SET(create_flow_table_in, in, table_type, ft_attr->type); -+ MLX5_SET(create_flow_table_in, in, uid, ft_attr->uid); - - ft_ctx = MLX5_ADDR_OF(create_flow_table_in, in, flow_table_context); - MLX5_SET(flow_table_context, ft_ctx, level, ft_attr->level); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.h 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.h 2025-10-22 13:53:56.579168833 -0400 -@@ -36,6 +36,7 @@ struct mlx5hws_cmd_set_fte_attr { - struct mlx5hws_cmd_ft_create_attr { - u8 type; - u8 level; -+ u16 uid; - bool rtc_valid; - bool decap_en; - bool reformat_en; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c 2025-10-22 13:53:56.579168833 -0400 -@@ -785,6 +785,9 @@ hws_definer_conv_outer(struct mlx5hws_de - HWS_SET_HDR(fc, match_param, IP_PROTOCOL_O, - outer_headers.ip_protocol, - eth_l3_outer.protocol_next_header); -+ HWS_SET_HDR(fc, match_param, IP_VERSION_O, -+ outer_headers.ip_version, -+ eth_l3_outer.ip_version); - HWS_SET_HDR(fc, match_param, IP_TTL_O, - outer_headers.ttl_hoplimit, - eth_l3_outer.time_to_live_hop_limit); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c 2025-10-22 13:53:56.579168833 -0400 -@@ -267,6 +267,7 @@ static int mlx5_cmd_hws_create_flow_tabl - - tbl_attr.type = MLX5HWS_TABLE_TYPE_FDB; - tbl_attr.level = ft_attr->level; -+ tbl_attr.uid = ft_attr->uid; - tbl = mlx5hws_table_create(ctx, &tbl_attr); - if (!tbl) { - mlx5_core_err(ns->dev, "Failed creating hws flow_table\n"); -@@ -571,14 +572,12 @@ static void mlx5_fs_put_dest_action_samp - static struct mlx5hws_action * - mlx5_fs_create_action_dest_array(struct mlx5hws_context *ctx, - struct mlx5hws_action_dest_attr *dests, -- u32 num_of_dests, bool ignore_flow_level, -- u32 flow_source) -+ u32 num_of_dests) - { - u32 flags = MLX5HWS_ACTION_FLAG_HWS_FDB | MLX5HWS_ACTION_FLAG_SHARED; - - return mlx5hws_action_create_dest_array(ctx, num_of_dests, dests, -- ignore_flow_level, -- flow_source, flags); -+ flags); - } - - static struct mlx5hws_action * -@@ -966,6 +965,9 @@ static int mlx5_fs_fte_get_hws_actions(s - switch (attr->type) { - case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE: - dest_action = mlx5_fs_get_dest_action_ft(fs_ctx, dst); -+ if (dst->dest_attr.ft->flags & -+ MLX5_FLOW_TABLE_UPLINK_VPORT) -+ dest_actions[num_dest_actions].is_wire_ft = true; - break; - case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM: - dest_action = mlx5_fs_get_dest_action_table_num(fs_ctx, -@@ -1012,20 +1014,14 @@ static int mlx5_fs_fte_get_hws_actions(s - } - (*ractions)[num_actions++].action = dest_actions->dest; - } else if (num_dest_actions > 1) { -- u32 flow_source = fte->act_dests.flow_context.flow_source; -- bool ignore_flow_level; -- - if (num_actions == MLX5_FLOW_CONTEXT_ACTION_MAX || - num_fs_actions == MLX5_FLOW_CONTEXT_ACTION_MAX) { - err = -EOPNOTSUPP; - goto free_actions; - } -- ignore_flow_level = -- !!(fte_action->flags & FLOW_ACT_IGNORE_FLOW_LEVEL); -- tmp_action = mlx5_fs_create_action_dest_array(ctx, dest_actions, -- num_dest_actions, -- ignore_flow_level, -- flow_source); -+ tmp_action = -+ mlx5_fs_create_action_dest_array(ctx, dest_actions, -+ num_dest_actions); - if (!tmp_action) { - err = -EOPNOTSUPP; - goto free_actions; -@@ -1357,6 +1353,7 @@ mlx5_cmd_hws_packet_reformat_alloc(struc - pkt_reformat->fs_hws_action.pr_data = pr_data; - } - -+ mutex_init(&pkt_reformat->fs_hws_action.lock); - pkt_reformat->owner = MLX5_FLOW_RESOURCE_OWNER_HWS; - pkt_reformat->fs_hws_action.hws_action = hws_action; - return 0; -@@ -1503,7 +1500,6 @@ static int mlx5_cmd_hws_modify_header_al - err = -ENOMEM; - goto release_mh; - } -- mutex_init(&modify_hdr->fs_hws_action.lock); - modify_hdr->fs_hws_action.mh_data = mh_data; - modify_hdr->fs_hws_action.fs_pool = pool; - modify_hdr->owner = MLX5_FLOW_RESOURCE_OWNER_SW; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws_pools.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws_pools.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws_pools.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws_pools.c 2025-10-22 13:53:56.579168833 -0400 -@@ -407,15 +407,21 @@ struct mlx5hws_action *mlx5_fc_get_hws_a - { - struct mlx5_fs_hws_create_action_ctx create_ctx; - struct mlx5_fc_bulk *fc_bulk = counter->bulk; -+ struct mlx5hws_action *hws_action; - - create_ctx.hws_ctx = ctx; - create_ctx.id = fc_bulk->base_id; - create_ctx.actions_type = MLX5HWS_ACTION_TYP_CTR; - -- return mlx5_fs_get_hws_action(&fc_bulk->hws_data, &create_ctx); -+ mlx5_fc_local_get(counter); -+ hws_action = mlx5_fs_get_hws_action(&fc_bulk->hws_data, &create_ctx); -+ if (!hws_action) -+ mlx5_fc_local_put(counter); -+ return hws_action; - } - - void mlx5_fc_put_hws_action(struct mlx5_fc *counter) - { - mlx5_fs_put_hws_action(&counter->bulk->hws_data); -+ mlx5_fc_local_put(counter); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.c 2025-10-22 13:53:56.579168833 -0400 -@@ -85,6 +85,7 @@ static int hws_matcher_create_end_ft_iso - - ret = mlx5hws_table_create_default_ft(tbl->ctx->mdev, - tbl, -+ 0, - &matcher->end_ft_id); - if (ret) { - mlx5hws_err(tbl->ctx, "Isolated matcher: failed to create end flow table\n"); -@@ -112,7 +113,9 @@ static int hws_matcher_create_end_ft(str - if (mlx5hws_matcher_is_isolated(matcher)) - ret = hws_matcher_create_end_ft_isolated(matcher); - else -- ret = mlx5hws_table_create_default_ft(tbl->ctx->mdev, tbl, -+ ret = mlx5hws_table_create_default_ft(tbl->ctx->mdev, -+ tbl, -+ 0, - &matcher->end_ft_id); - - if (ret) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws.h 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws.h 2025-10-22 13:53:56.579168833 -0400 -@@ -75,6 +75,7 @@ struct mlx5hws_context_attr { - struct mlx5hws_table_attr { - enum mlx5hws_table_type type; - u32 level; -+ u16 uid; - }; - - enum mlx5hws_matcher_flow_src { -@@ -213,6 +214,7 @@ struct mlx5hws_action_dest_attr { - struct mlx5hws_action *dest; - /* Optional reformat action */ - struct mlx5hws_action *reformat; -+ bool is_wire_ft; - }; - - /** -@@ -725,18 +727,13 @@ mlx5hws_action_create_push_vlan(struct m - * @num_dest: The number of dests attributes. - * @dests: The destination array. Each contains a destination action and can - * have additional actions. -- * @ignore_flow_level: Whether to turn on 'ignore_flow_level' for this dest. -- * @flow_source: Source port of the traffic for this actions. - * @flags: Action creation flags (enum mlx5hws_action_flags). - * - * Return: pointer to mlx5hws_action on success NULL otherwise. - */ - struct mlx5hws_action * --mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx, -- size_t num_dest, -+mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx, size_t num_dest, - struct mlx5hws_action_dest_attr *dests, -- bool ignore_flow_level, -- u32 flow_source, - u32 flags); - - /** -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.c 2025-10-22 13:53:56.579168833 -0400 -@@ -279,7 +279,7 @@ int mlx5hws_pat_get_pattern(struct mlx5h - return ret; - - clean_pattern: -- mlx5hws_cmd_header_modify_pattern_destroy(ctx->mdev, *pattern_id); -+ mlx5hws_cmd_header_modify_pattern_destroy(ctx->mdev, ptrn_id); - out_unlock: - mutex_unlock(&ctx->pattern_cache->lock); - return ret; -@@ -527,7 +527,6 @@ int mlx5hws_pat_calc_nop(__be64 *pattern - u32 *nop_locations, __be64 *new_pat) - { - u16 prev_src_field = INVALID_FIELD, prev_dst_field = INVALID_FIELD; -- u16 src_field, dst_field; - u8 action_type; - bool dependent; - size_t i, j; -@@ -539,6 +538,9 @@ int mlx5hws_pat_calc_nop(__be64 *pattern - return 0; - - for (i = 0, j = 0; i < num_actions; i++, j++) { -+ u16 src_field = INVALID_FIELD; -+ u16 dst_field = INVALID_FIELD; -+ - if (j >= max_actions) - return -EINVAL; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pool.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pool.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pool.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pool.c 2025-10-22 13:53:56.579168833 -0400 -@@ -124,6 +124,7 @@ static int hws_pool_buddy_init(struct ml - mlx5hws_err(pool->ctx, "Failed to create resource type: %d size %zu\n", - pool->type, pool->alloc_log_sz); - mlx5hws_buddy_cleanup(buddy); -+ kfree(buddy); - return -ENOMEM; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c 2025-10-22 13:53:56.579168833 -0400 -@@ -964,7 +964,6 @@ static int hws_send_ring_open_cq(struct - return -ENOMEM; - - MLX5_SET(cqc, cqc_data, uar_page, mdev->priv.uar->index); -- MLX5_SET(cqc, cqc_data, cqe_sz, queue->num_entries); - MLX5_SET(cqc, cqc_data, log_cq_size, ilog2(queue->num_entries)); - - err = hws_send_ring_alloc_cq(mdev, numa_node, queue, cqc_data, cq); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.c 2025-10-22 13:53:56.579168833 -0400 -@@ -9,6 +9,7 @@ u32 mlx5hws_table_get_id(struct mlx5hws_ - } - - static void hws_table_init_next_ft_attr(struct mlx5hws_table *tbl, -+ u16 uid, - struct mlx5hws_cmd_ft_create_attr *ft_attr) - { - ft_attr->type = tbl->fw_ft_type; -@@ -16,7 +17,9 @@ static void hws_table_init_next_ft_attr( - ft_attr->level = tbl->ctx->caps->fdb_ft.max_level - 1; - else - ft_attr->level = tbl->ctx->caps->nic_ft.max_level - 1; -+ - ft_attr->rtc_valid = true; -+ ft_attr->uid = uid; - } - - static void hws_table_set_cap_attr(struct mlx5hws_table *tbl, -@@ -119,12 +122,12 @@ static int hws_table_connect_to_default_ - - int mlx5hws_table_create_default_ft(struct mlx5_core_dev *mdev, - struct mlx5hws_table *tbl, -- u32 *ft_id) -+ u16 uid, u32 *ft_id) - { - struct mlx5hws_cmd_ft_create_attr ft_attr = {0}; - int ret; - -- hws_table_init_next_ft_attr(tbl, &ft_attr); -+ hws_table_init_next_ft_attr(tbl, uid, &ft_attr); - hws_table_set_cap_attr(tbl, &ft_attr); - - ret = mlx5hws_cmd_flow_table_create(mdev, &ft_attr, ft_id); -@@ -189,7 +192,10 @@ static int hws_table_init(struct mlx5hws - } - - mutex_lock(&ctx->ctrl_lock); -- ret = mlx5hws_table_create_default_ft(tbl->ctx->mdev, tbl, &tbl->ft_id); -+ ret = mlx5hws_table_create_default_ft(tbl->ctx->mdev, -+ tbl, -+ tbl->uid, -+ &tbl->ft_id); - if (ret) { - mlx5hws_err(tbl->ctx, "Failed to create flow table object\n"); - mutex_unlock(&ctx->ctrl_lock); -@@ -239,6 +245,7 @@ struct mlx5hws_table *mlx5hws_table_crea - tbl->ctx = ctx; - tbl->type = attr->type; - tbl->level = attr->level; -+ tbl->uid = attr->uid; - - ret = hws_table_init(tbl); - if (ret) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.h 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.h 2025-10-22 13:53:56.579168833 -0400 -@@ -18,6 +18,7 @@ struct mlx5hws_table { - enum mlx5hws_table_type type; - u32 fw_ft_type; - u32 level; -+ u16 uid; - struct list_head matchers_list; - struct list_head tbl_list_node; - struct mlx5hws_default_miss default_miss; -@@ -47,7 +48,7 @@ u32 mlx5hws_table_get_res_fw_ft_type(enu - - int mlx5hws_table_create_default_ft(struct mlx5_core_dev *mdev, - struct mlx5hws_table *tbl, -- u32 *ft_id); -+ u16 uid, u32 *ft_id); - - void mlx5hws_table_destroy_default_ft(struct mlx5hws_table *tbl, - u32 ft_id); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c 2025-10-22 13:53:23.351328474 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c 2025-10-22 13:53:56.579168833 -0400 -@@ -447,8 +447,10 @@ static int mlxbf_gige_probe(struct platf - priv->llu_plu_irq = platform_get_irq(pdev, MLXBF_GIGE_LLU_PLU_INTR_IDX); - - phy_irq = acpi_dev_gpio_irq_get_by(ACPI_COMPANION(&pdev->dev), "phy", 0); -- if (phy_irq < 0) { -- dev_err(&pdev->dev, "Error getting PHY irq. Use polling instead"); -+ if (phy_irq == -EPROBE_DEFER) { -+ err = -EPROBE_DEFER; -+ goto out; -+ } else if (phy_irq < 0) { - phy_irq = PHY_POLL; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlxsw/spectrum.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlxsw/spectrum.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 2025-10-22 13:53:23.355328455 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlxsw/spectrum.c 2025-10-22 13:53:56.579168833 -0400 -@@ -2375,6 +2375,8 @@ static const struct mlxsw_listener mlxsw - ROUTER_EXP, false), - MLXSW_SP_RXL_NO_MARK(DISCARD_ING_ROUTER_DIP_LINK_LOCAL, FORWARD, - ROUTER_EXP, false), -+ MLXSW_SP_RXL_NO_MARK(DISCARD_ING_ROUTER_SIP_LINK_LOCAL, FORWARD, -+ ROUTER_EXP, false), - /* Multicast Router Traps */ - MLXSW_SP_RXL_MARK(ACL1, TRAP_TO_CPU, MULTICAST, false), - MLXSW_SP_RXL_L3_MARK(ACL2, TRAP_TO_CPU, MULTICAST, false), -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlxsw/trap.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlxsw/trap.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/mellanox/mlxsw/trap.h 2025-10-22 13:53:23.355328455 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/mellanox/mlxsw/trap.h 2025-10-22 13:53:56.579168833 -0400 -@@ -94,6 +94,7 @@ enum { - MLXSW_TRAP_ID_DISCARD_ING_ROUTER_IPV4_SIP_BC = 0x16A, - MLXSW_TRAP_ID_DISCARD_ING_ROUTER_IPV4_DIP_LOCAL_NET = 0x16B, - MLXSW_TRAP_ID_DISCARD_ING_ROUTER_DIP_LINK_LOCAL = 0x16C, -+ MLXSW_TRAP_ID_DISCARD_ING_ROUTER_SIP_LINK_LOCAL = 0x16D, - MLXSW_TRAP_ID_DISCARD_ROUTER_IRIF_EN = 0x178, - MLXSW_TRAP_ID_DISCARD_ROUTER_ERIF_EN = 0x179, - MLXSW_TRAP_ID_DISCARD_ROUTER_LPM4 = 0x17B, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/meta/fbnic/fbnic_fw.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/meta/fbnic/fbnic_fw.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/meta/fbnic/fbnic_fw.c 2025-10-22 13:53:23.355328455 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/meta/fbnic/fbnic_fw.c 2025-10-22 13:53:56.579168833 -0400 -@@ -127,11 +127,8 @@ static int fbnic_mbx_map_msg(struct fbni - return -EBUSY; - - addr = dma_map_single(fbd->dev, msg, PAGE_SIZE, direction); -- if (dma_mapping_error(fbd->dev, addr)) { -- free_page((unsigned long)msg); -- -+ if (dma_mapping_error(fbd->dev, addr)) - return -ENOSPC; -- } - - mbx->buf_info[tail].msg = msg; - mbx->buf_info[tail].addr = addr; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c 2025-10-22 13:53:23.355328455 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c 2025-10-22 13:53:56.579168833 -0400 -@@ -33,7 +33,7 @@ int __fbnic_open(struct fbnic_net *fbn) - dev_warn(fbd->dev, - "Error %d sending host ownership message to the firmware\n", - err); -- goto free_resources; -+ goto err_reset_queues; - } - - err = fbnic_time_start(fbn); -@@ -52,11 +52,15 @@ int __fbnic_open(struct fbnic_net *fbn) - fbnic_bmc_rpc_init(fbd); - fbnic_rss_reinit(fbd, fbn); - -+ phylink_resume(fbn->phylink); -+ - return 0; - time_stop: - fbnic_time_stop(fbn); - release_ownership: - fbnic_fw_xmit_ownership_msg(fbn->fbd, false); -+err_reset_queues: -+ fbnic_reset_netif_queues(fbn); - free_resources: - fbnic_free_resources(fbn); - free_napi_vectors: -@@ -82,6 +86,8 @@ static int fbnic_stop(struct net_device - { - struct fbnic_net *fbn = netdev_priv(netdev); - -+ phylink_suspend(fbn->phylink, fbnic_bmc_present(fbn->fbd)); -+ - fbnic_down(fbn); - fbnic_pcs_free_irq(fbn->fbd); - -@@ -420,15 +426,17 @@ static void fbnic_get_stats64(struct net - tx_packets = stats->packets; - tx_dropped = stats->dropped; - -- stats64->tx_bytes = tx_bytes; -- stats64->tx_packets = tx_packets; -- stats64->tx_dropped = tx_dropped; -- - /* Record drops from Tx HW Datapath */ -+ spin_lock(&fbd->hw_stats_lock); - tx_dropped += fbd->hw_stats.tmi.drop.frames.value + - fbd->hw_stats.tti.cm_drop.frames.value + - fbd->hw_stats.tti.frame_drop.frames.value + - fbd->hw_stats.tti.tbi_drop.frames.value; -+ spin_unlock(&fbd->hw_stats_lock); -+ -+ stats64->tx_bytes = tx_bytes; -+ stats64->tx_packets = tx_packets; -+ stats64->tx_dropped = tx_dropped; - - for (i = 0; i < fbn->num_tx_queues; i++) { - struct fbnic_ring *txr = fbn->tx[i]; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/meta/fbnic/fbnic_pci.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/meta/fbnic/fbnic_pci.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/meta/fbnic/fbnic_pci.c 2025-10-22 13:53:23.355328455 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/meta/fbnic/fbnic_pci.c 2025-10-22 13:53:56.579168833 -0400 -@@ -118,14 +118,12 @@ static void fbnic_service_task_start(str - struct fbnic_dev *fbd = fbn->fbd; - - schedule_delayed_work(&fbd->service_task, HZ); -- phylink_resume(fbn->phylink); - } - - static void fbnic_service_task_stop(struct fbnic_net *fbn) - { - struct fbnic_dev *fbd = fbn->fbd; - -- phylink_suspend(fbn->phylink, fbnic_bmc_present(fbd)); - cancel_delayed_work(&fbd->service_task); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c 2025-10-22 13:53:23.355328455 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c 2025-10-22 13:53:56.579168833 -0400 -@@ -661,8 +661,8 @@ static void fbnic_page_pool_init(struct - { - struct fbnic_rx_buf *rx_buf = &ring->rx_buf[idx]; - -- page_pool_fragment_page(page, PAGECNT_BIAS_MAX); -- rx_buf->pagecnt_bias = PAGECNT_BIAS_MAX; -+ page_pool_fragment_page(page, FBNIC_PAGECNT_BIAS_MAX); -+ rx_buf->pagecnt_bias = FBNIC_PAGECNT_BIAS_MAX; - rx_buf->page = page; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h 2025-10-22 13:53:23.355328455 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h 2025-10-22 13:53:56.579168833 -0400 -@@ -91,10 +91,8 @@ struct fbnic_queue_stats { - struct u64_stats_sync syncp; - }; - --/* Pagecnt bias is long max to reserve the last bit to catch overflow -- * cases where if we overcharge the bias it will flip over to be negative. -- */ --#define PAGECNT_BIAS_MAX LONG_MAX -+#define FBNIC_PAGECNT_BIAS_MAX PAGE_SIZE -+ - struct fbnic_rx_buf { - struct page *page; - long pagecnt_bias; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/microchip/lan743x_ptp.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/microchip/lan743x_ptp.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/microchip/lan743x_ptp.h 2025-10-22 13:53:23.355328455 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/microchip/lan743x_ptp.h 2025-10-22 13:53:56.579168833 -0400 -@@ -18,9 +18,9 @@ - */ - #define LAN743X_PTP_N_EVENT_CHAN 2 - #define LAN743X_PTP_N_PEROUT LAN743X_PTP_N_EVENT_CHAN --#define LAN743X_PTP_N_EXTTS 4 --#define LAN743X_PTP_N_PPS 0 - #define PCI11X1X_PTP_IO_MAX_CHANNELS 8 -+#define LAN743X_PTP_N_EXTTS PCI11X1X_PTP_IO_MAX_CHANNELS -+#define LAN743X_PTP_N_PPS 0 - #define PTP_CMD_CTL_TIMEOUT_CNT 50 - - struct lan743x_adapter; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/microchip/lan865x/lan865x.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/microchip/lan865x/lan865x.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/microchip/lan865x/lan865x.c 2025-10-22 13:53:23.355328455 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/microchip/lan865x/lan865x.c 2025-10-22 13:53:56.579168833 -0400 -@@ -32,6 +32,10 @@ - /* MAC Specific Addr 1 Top Reg */ - #define LAN865X_REG_MAC_H_SADDR1 0x00010023 - -+/* MAC TSU Timer Increment Register */ -+#define LAN865X_REG_MAC_TSU_TIMER_INCR 0x00010077 -+#define MAC_TSU_TIMER_INCR_COUNT_NANOSECONDS 0x0028 -+ - struct lan865x_priv { - struct work_struct multicast_work; - struct net_device *netdev; -@@ -311,6 +315,8 @@ static int lan865x_net_open(struct net_d - - phy_start(netdev->phydev); - -+ netif_start_queue(netdev); -+ - return 0; - } - -@@ -344,6 +350,21 @@ static int lan865x_probe(struct spi_devi - goto free_netdev; - } - -+ /* LAN865x Rev.B0/B1 configuration parameters from AN1760 -+ * As per the Configuration Application Note AN1760 published in the -+ * link, https://www.microchip.com/en-us/application-notes/an1760 -+ * Revision F (DS60001760G - June 2024), configure the MAC to set time -+ * stamping at the end of the Start of Frame Delimiter (SFD) and set the -+ * Timer Increment reg to 40 ns to be used as a 25 MHz internal clock. -+ */ -+ ret = oa_tc6_write_register(priv->tc6, LAN865X_REG_MAC_TSU_TIMER_INCR, -+ MAC_TSU_TIMER_INCR_COUNT_NANOSECONDS); -+ if (ret) { -+ dev_err(&spi->dev, "Failed to config TSU Timer Incr reg: %d\n", -+ ret); -+ goto oa_tc6_exit; -+ } -+ - /* As per the point s3 in the below errata, SPI receive Ethernet frame - * transfer may halt when starting the next frame in the same data block - * (chunk) as the end of a previous frame. The RFA field should be -@@ -402,13 +423,16 @@ static void lan865x_remove(struct spi_de - free_netdev(priv->netdev); - } - --static const struct spi_device_id spidev_spi_ids[] = { -+static const struct spi_device_id lan865x_ids[] = { - { .name = "lan8650" }, -+ { .name = "lan8651" }, - {}, - }; -+MODULE_DEVICE_TABLE(spi, lan865x_ids); - - static const struct of_device_id lan865x_dt_ids[] = { - { .compatible = "microchip,lan8650" }, -+ { .compatible = "microchip,lan8651" }, - { /* Sentinel */ } - }; - MODULE_DEVICE_TABLE(of, lan865x_dt_ids); -@@ -420,7 +444,7 @@ static struct spi_driver lan865x_driver - }, - .probe = lan865x_probe, - .remove = lan865x_remove, -- .id_table = spidev_spi_ids, -+ .id_table = lan865x_ids, - }; - module_spi_driver(lan865x_driver); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/microsoft/mana/gdma_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/microsoft/mana/gdma_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/microsoft/mana/gdma_main.c 2025-10-22 13:53:23.355328455 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/microsoft/mana/gdma_main.c 2025-10-22 13:53:56.579168833 -0400 -@@ -6,6 +6,7 @@ - #include - #include - #include -+#include - - #include - -@@ -31,6 +32,9 @@ static void mana_gd_init_pf_regs(struct - gc->db_page_base = gc->bar0_va + - mana_gd_r64(gc, GDMA_PF_REG_DB_PAGE_OFF); - -+ gc->phys_db_page_base = gc->bar0_pa + -+ mana_gd_r64(gc, GDMA_PF_REG_DB_PAGE_OFF); -+ - sriov_base_off = mana_gd_r64(gc, GDMA_SRIOV_REG_CFG_BASE_OFF); - - sriov_base_va = gc->bar0_va + sriov_base_off; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/microsoft/mana/mana_en.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/microsoft/mana/mana_en.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/microsoft/mana/mana_en.c 2025-10-22 13:53:23.355328455 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/microsoft/mana/mana_en.c 2025-10-22 13:53:56.583168814 -0400 -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -1911,8 +1912,10 @@ static void mana_destroy_txq(struct mana - napi = &apc->tx_qp[i].tx_cq.napi; - if (apc->tx_qp[i].txq.napi_initialized) { - napi_synchronize(napi); -- napi_disable(napi); -- netif_napi_del(napi); -+ netdev_lock_ops_to_full(napi->dev); -+ napi_disable_locked(napi); -+ netif_napi_del_locked(napi); -+ netdev_unlock_full_to_ops(napi->dev); - apc->tx_qp[i].txq.napi_initialized = false; - } - mana_destroy_wq_obj(apc, GDMA_SQ, apc->tx_qp[i].tx_object); -@@ -2064,8 +2067,11 @@ static int mana_create_txq(struct mana_p - - mana_create_txq_debugfs(apc, i); - -- netif_napi_add_tx(net, &cq->napi, mana_poll); -- napi_enable(&cq->napi); -+ set_bit(NAPI_STATE_NO_BUSY_POLL, &cq->napi.state); -+ netdev_lock_ops_to_full(net); -+ netif_napi_add_locked(net, &cq->napi, mana_poll); -+ napi_enable_locked(&cq->napi); -+ netdev_unlock_full_to_ops(net); - txq->napi_initialized = true; - - mana_gd_ring_cq(cq->gdma_cq, SET_ARM_BIT); -@@ -2101,9 +2107,10 @@ static void mana_destroy_rxq(struct mana - if (napi_initialized) { - napi_synchronize(napi); - -- napi_disable(napi); -- -- netif_napi_del(napi); -+ netdev_lock_ops_to_full(napi->dev); -+ napi_disable_locked(napi); -+ netif_napi_del_locked(napi); -+ netdev_unlock_full_to_ops(napi->dev); - } - xdp_rxq_info_unreg(&rxq->xdp_rxq); - -@@ -2354,14 +2361,18 @@ static struct mana_rxq *mana_create_rxq( - - gc->cq_table[cq->gdma_id] = cq->gdma_cq; - -- netif_napi_add_weight(ndev, &cq->napi, mana_poll, 1); -+ netdev_lock_ops_to_full(ndev); -+ netif_napi_add_weight_locked(ndev, &cq->napi, mana_poll, 1); -+ netdev_unlock_full_to_ops(ndev); - - WARN_ON(xdp_rxq_info_reg(&rxq->xdp_rxq, ndev, rxq_idx, - cq->napi.napi_id)); - WARN_ON(xdp_rxq_info_reg_mem_model(&rxq->xdp_rxq, MEM_TYPE_PAGE_POOL, - rxq->page_pool)); - -- napi_enable(&cq->napi); -+ netdev_lock_ops_to_full(ndev); -+ napi_enable_locked(&cq->napi); -+ netdev_unlock_full_to_ops(ndev); - - mana_gd_ring_cq(cq->gdma_cq, SET_ARM_BIT); - out: -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/natsemi/ns83820.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/natsemi/ns83820.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/natsemi/ns83820.c 2025-10-22 13:53:23.355328455 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/natsemi/ns83820.c 2025-10-22 13:53:56.583168814 -0400 -@@ -820,7 +820,7 @@ static void rx_irq(struct net_device *nd - struct ns83820 *dev = PRIV(ndev); - struct rx_info *info = &dev->rx_info; - unsigned next_rx; -- int rx_rc, len; -+ int len; - u32 cmdsts; - __le32 *desc; - unsigned long flags; -@@ -881,8 +881,10 @@ static void rx_irq(struct net_device *nd - if (likely(CMDSTS_OK & cmdsts)) { - #endif - skb_put(skb, len); -- if (unlikely(!skb)) -+ if (unlikely(!skb)) { -+ ndev->stats.rx_dropped++; - goto netdev_mangle_me_harder_failed; -+ } - if (cmdsts & CMDSTS_DEST_MULTI) - ndev->stats.multicast++; - ndev->stats.rx_packets++; -@@ -901,15 +903,12 @@ static void rx_irq(struct net_device *nd - __vlan_hwaccel_put_tag(skb, htons(ETH_P_IPV6), tag); - } - #endif -- rx_rc = netif_rx(skb); -- if (NET_RX_DROP == rx_rc) { --netdev_mangle_me_harder_failed: -- ndev->stats.rx_dropped++; -- } -+ netif_rx(skb); - } else { - dev_kfree_skb_irq(skb); - } - -+netdev_mangle_me_harder_failed: - nr++; - next_rx = info->next_rx; - desc = info->descs + (DESC_SIZE * next_rx); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/oa_tc6.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/oa_tc6.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/oa_tc6.c 2025-10-22 13:53:23.355328455 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/oa_tc6.c 2025-10-22 13:53:56.583168814 -0400 -@@ -1249,7 +1249,8 @@ struct oa_tc6 *oa_tc6_init(struct spi_de - - /* Set the SPI controller to pump at realtime priority */ - tc6->spi->rt = true; -- spi_setup(tc6->spi); -+ if (spi_setup(tc6->spi) < 0) -+ return NULL; - - tc6->spi_ctrl_tx_buf = devm_kzalloc(&tc6->spi->dev, - OA_TC6_CTRL_SPI_BUF_SIZE, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/pensando/ionic/ionic_lif.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/pensando/ionic/ionic_lif.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/pensando/ionic/ionic_lif.c 2025-10-22 13:53:23.355328455 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/pensando/ionic/ionic_lif.c 2025-10-22 13:53:56.583168814 -0400 -@@ -3526,10 +3526,6 @@ void ionic_lif_free(struct ionic_lif *li - lif->info = NULL; - lif->info_pa = 0; - -- /* unmap doorbell page */ -- ionic_bus_unmap_dbpage(lif->ionic, lif->kern_dbpage); -- lif->kern_dbpage = NULL; -- - mutex_destroy(&lif->config_lock); - mutex_destroy(&lif->queue_lock); - -@@ -3555,6 +3551,9 @@ void ionic_lif_deinit(struct ionic_lif * - ionic_lif_qcq_deinit(lif, lif->notifyqcq); - ionic_lif_qcq_deinit(lif, lif->adminqcq); - -+ ionic_bus_unmap_dbpage(lif->ionic, lif->kern_dbpage); -+ lif->kern_dbpage = NULL; -+ - ionic_lif_reset(lif); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/pensando/ionic/ionic_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/pensando/ionic/ionic_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/pensando/ionic/ionic_main.c 2025-10-22 13:53:23.355328455 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/pensando/ionic/ionic_main.c 2025-10-22 13:53:56.583168814 -0400 -@@ -516,9 +516,9 @@ static int __ionic_dev_cmd_wait(struct i - unsigned long start_time; - unsigned long max_wait; - unsigned long duration; -- int done = 0; - bool fw_up; - int opcode; -+ bool done; - int err; - - /* Wait for dev cmd to complete, retrying if we get EAGAIN, -@@ -526,6 +526,7 @@ static int __ionic_dev_cmd_wait(struct i - */ - max_wait = jiffies + (max_seconds * HZ); - try_again: -+ done = false; - opcode = idev->opcode; - start_time = jiffies; - for (fw_up = ionic_is_fw_running(idev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/pensando/ionic/ionic_txrx.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/pensando/ionic/ionic_txrx.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/pensando/ionic/ionic_txrx.c 2025-10-22 13:53:23.355328455 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/pensando/ionic/ionic_txrx.c 2025-10-22 13:53:56.583168814 -0400 -@@ -321,7 +321,7 @@ static int ionic_xdp_post_frame(struct i - len, DMA_TO_DEVICE); - } else /* XDP_REDIRECT */ { - dma_addr = ionic_tx_map_single(q, frame->data, len); -- if (!dma_addr) -+ if (dma_addr == DMA_MAPPING_ERROR) - return -EIO; - } - -@@ -357,7 +357,7 @@ static int ionic_xdp_post_frame(struct i - } else { - dma_addr = ionic_tx_map_frag(q, frag, 0, - skb_frag_size(frag)); -- if (dma_mapping_error(q->dev, dma_addr)) { -+ if (dma_addr == DMA_MAPPING_ERROR) { - ionic_tx_desc_unmap_bufs(q, desc_info); - return -EIO; - } -@@ -1083,7 +1083,7 @@ static dma_addr_t ionic_tx_map_single(st - net_warn_ratelimited("%s: DMA single map failed on %s!\n", - dev_name(dev), q->name); - q_to_tx_stats(q)->dma_map_err++; -- return 0; -+ return DMA_MAPPING_ERROR; - } - return dma_addr; - } -@@ -1100,7 +1100,7 @@ static dma_addr_t ionic_tx_map_frag(stru - net_warn_ratelimited("%s: DMA frag map failed on %s!\n", - dev_name(dev), q->name); - q_to_tx_stats(q)->dma_map_err++; -- return 0; -+ return DMA_MAPPING_ERROR; - } - return dma_addr; - } -@@ -1116,7 +1116,7 @@ static int ionic_tx_map_skb(struct ionic - int frag_idx; - - dma_addr = ionic_tx_map_single(q, skb->data, skb_headlen(skb)); -- if (!dma_addr) -+ if (dma_addr == DMA_MAPPING_ERROR) - return -EIO; - buf_info->dma_addr = dma_addr; - buf_info->len = skb_headlen(skb); -@@ -1126,7 +1126,7 @@ static int ionic_tx_map_skb(struct ionic - nfrags = skb_shinfo(skb)->nr_frags; - for (frag_idx = 0; frag_idx < nfrags; frag_idx++, frag++) { - dma_addr = ionic_tx_map_frag(q, frag, 0, skb_frag_size(frag)); -- if (!dma_addr) -+ if (dma_addr == DMA_MAPPING_ERROR) - goto dma_fail; - buf_info->dma_addr = dma_addr; - buf_info->len = skb_frag_size(frag); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/qlogic/qed/qed_debug.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/qlogic/qed/qed_debug.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/qlogic/qed/qed_debug.c 2025-10-22 13:53:23.359328436 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/qlogic/qed/qed_debug.c 2025-10-22 13:53:56.583168814 -0400 -@@ -4462,10 +4462,11 @@ static enum dbg_status qed_protection_ov - goto out; - } - -- /* Add override window info to buffer */ -+ /* Add override window info to buffer, preventing buffer overflow */ - override_window_dwords = -- qed_rd(p_hwfn, p_ptt, GRC_REG_NUMBER_VALID_OVERRIDE_WINDOW) * -- PROTECTION_OVERRIDE_ELEMENT_DWORDS; -+ min(qed_rd(p_hwfn, p_ptt, GRC_REG_NUMBER_VALID_OVERRIDE_WINDOW) * -+ PROTECTION_OVERRIDE_ELEMENT_DWORDS, -+ PROTECTION_OVERRIDE_DEPTH_DWORDS); - if (override_window_dwords) { - addr = BYTES_TO_DWORDS(GRC_REG_PROTECTION_OVERRIDE_WINDOW); - offset += qed_grc_dump_addr_range(p_hwfn, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/qlogic/qed/qed_mng_tlv.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/qlogic/qed/qed_mng_tlv.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/qlogic/qed/qed_mng_tlv.c 2025-10-22 13:53:23.359328436 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/qlogic/qed/qed_mng_tlv.c 2025-10-22 13:53:56.583168814 -0400 -@@ -242,7 +242,7 @@ static int qed_mfw_get_tlv_group(u8 tlv_ - } - - /* Returns size of the data buffer or, -1 in case TLV data is not available. */ --static int -+static noinline_for_stack int - qed_mfw_get_gen_tlv_value(struct qed_drv_tlv_hdr *p_tlv, - struct qed_mfw_tlv_generic *p_drv_buf, - struct qed_tlv_parsed_buf *p_buf) -@@ -304,7 +304,7 @@ qed_mfw_get_gen_tlv_value(struct qed_drv - return -1; - } - --static int -+static noinline_for_stack int - qed_mfw_get_eth_tlv_value(struct qed_drv_tlv_hdr *p_tlv, - struct qed_mfw_tlv_eth *p_drv_buf, - struct qed_tlv_parsed_buf *p_buf) -@@ -438,7 +438,7 @@ qed_mfw_get_tlv_time_value(struct qed_mf - return QED_MFW_TLV_TIME_SIZE; - } - --static int -+static noinline_for_stack int - qed_mfw_get_fcoe_tlv_value(struct qed_drv_tlv_hdr *p_tlv, - struct qed_mfw_tlv_fcoe *p_drv_buf, - struct qed_tlv_parsed_buf *p_buf) -@@ -1073,7 +1073,7 @@ qed_mfw_get_fcoe_tlv_value(struct qed_dr - return -1; - } - --static int -+static noinline_for_stack int - qed_mfw_get_iscsi_tlv_value(struct qed_drv_tlv_hdr *p_tlv, - struct qed_mfw_tlv_iscsi *p_drv_buf, - struct qed_tlv_parsed_buf *p_buf) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/realtek/rtase/rtase.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/realtek/rtase/rtase.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/realtek/rtase/rtase.h 2025-10-22 13:53:23.359328436 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/realtek/rtase/rtase.h 2025-10-22 13:53:56.583168814 -0400 -@@ -241,7 +241,7 @@ union rtase_rx_desc { - #define RTASE_RX_RES BIT(20) - #define RTASE_RX_RUNT BIT(19) - #define RTASE_RX_RWT BIT(18) --#define RTASE_RX_CRC BIT(16) -+#define RTASE_RX_CRC BIT(17) - #define RTASE_RX_V6F BIT(31) - #define RTASE_RX_V4F BIT(30) - #define RTASE_RX_UDPT BIT(29) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/renesas/rtsn.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/renesas/rtsn.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/renesas/rtsn.c 2025-10-22 13:53:23.359328436 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/renesas/rtsn.c 2025-10-22 13:53:56.583168814 -0400 -@@ -1259,7 +1259,12 @@ static int rtsn_probe(struct platform_de - priv = netdev_priv(ndev); - priv->pdev = pdev; - priv->ndev = ndev; -+ - priv->ptp_priv = rcar_gen4_ptp_alloc(pdev); -+ if (!priv->ptp_priv) { -+ ret = -ENOMEM; -+ goto error_free; -+ } - - spin_lock_init(&priv->lock); - platform_set_drvdata(pdev, priv); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c 2025-10-22 13:53:23.359328436 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c 2025-10-22 13:53:56.583168814 -0400 -@@ -433,6 +433,12 @@ static int intel_crosststamp(ktime_t *de - return -ETIMEDOUT; - } - -+ *system = (struct system_counterval_t) { -+ .cycles = 0, -+ .cs_id = CSID_X86_ART, -+ .use_nsecs = false, -+ }; -+ - num_snapshot = (readl(ioaddr + GMAC_TIMESTAMP_STATUS) & - GMAC_TIMESTAMP_ATSNS_MASK) >> - GMAC_TIMESTAMP_ATSNS_SHIFT; -@@ -448,7 +454,7 @@ static int intel_crosststamp(ktime_t *de - } - - system->cycles *= intel_priv->crossts_adj; -- system->cs_id = CSID_X86_ART; -+ - priv->plat->flags &= ~STMMAC_FLAG_INT_SNAPSHOT_EN; - - return 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c 2025-10-22 13:53:23.359328436 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/stmicro/stmmac/dwmac-thead.c 2025-10-22 13:53:56.583168814 -0400 -@@ -152,7 +152,7 @@ static int thead_set_clk_tx_rate(void *b - static int thead_dwmac_enable_clk(struct plat_stmmacenet_data *plat) - { - struct thead_dwmac *dwmac = plat->bsp_priv; -- u32 reg; -+ u32 reg, div; - - switch (plat->mac_interface) { - case PHY_INTERFACE_MODE_MII: -@@ -164,6 +164,13 @@ static int thead_dwmac_enable_clk(struct - case PHY_INTERFACE_MODE_RGMII_RXID: - case PHY_INTERFACE_MODE_RGMII_TXID: - /* use pll */ -+ div = clk_get_rate(plat->stmmac_clk) / rgmii_clock(SPEED_1000); -+ reg = FIELD_PREP(GMAC_PLLCLK_DIV_EN, 1) | -+ FIELD_PREP(GMAC_PLLCLK_DIV_NUM, div); -+ -+ writel(0, dwmac->apb_base + GMAC_PLLCLK_DIV); -+ writel(reg, dwmac->apb_base + GMAC_PLLCLK_DIV); -+ - writel(GMAC_GTXCLK_SEL_PLL, dwmac->apb_base + GMAC_GTXCLK_SEL); - reg = GMAC_TX_CLK_EN | GMAC_TX_CLK_N_EN | GMAC_TX_CLK_OUT_EN | - GMAC_RX_CLK_EN | GMAC_RX_CLK_N_EN; -@@ -211,6 +218,7 @@ static int thead_dwmac_probe(struct plat - struct stmmac_resources stmmac_res; - struct plat_stmmacenet_data *plat; - struct thead_dwmac *dwmac; -+ struct clk *apb_clk; - void __iomem *apb; - int ret; - -@@ -224,6 +232,19 @@ static int thead_dwmac_probe(struct plat - return dev_err_probe(&pdev->dev, PTR_ERR(plat), - "dt configuration failed\n"); - -+ /* -+ * The APB clock is essential for accessing glue registers. However, -+ * old devicetrees don't describe it correctly. We continue to probe -+ * and emit a warning if it isn't present. -+ */ -+ apb_clk = devm_clk_get_enabled(&pdev->dev, "apb"); -+ if (PTR_ERR(apb_clk) == -ENOENT) -+ dev_warn(&pdev->dev, -+ "cannot get apb clock, link may break after speed changes\n"); -+ else if (IS_ERR(apb_clk)) -+ return dev_err_probe(&pdev->dev, PTR_ERR(apb_clk), -+ "failed to get apb clock\n"); -+ - dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL); - if (!dwmac) - return -ENOMEM; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c 2025-10-22 13:53:23.359328436 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c 2025-10-22 13:53:56.583168814 -0400 -@@ -49,6 +49,14 @@ static void dwxgmac2_core_init(struct ma - writel(XGMAC_INT_DEFAULT_EN, ioaddr + XGMAC_INT_EN); - } - -+static void dwxgmac2_update_caps(struct stmmac_priv *priv) -+{ -+ if (!priv->dma_cap.mbps_10_100) -+ priv->hw->link.caps &= ~(MAC_10 | MAC_100); -+ else if (!priv->dma_cap.half_duplex) -+ priv->hw->link.caps &= ~(MAC_10HD | MAC_100HD); -+} -+ - static void dwxgmac2_set_mac(void __iomem *ioaddr, bool enable) - { - u32 tx = readl(ioaddr + XGMAC_TX_CONFIG); -@@ -1424,6 +1432,7 @@ static void dwxgmac2_set_arp_offload(str - - const struct stmmac_ops dwxgmac210_ops = { - .core_init = dwxgmac2_core_init, -+ .update_caps = dwxgmac2_update_caps, - .set_mac = dwxgmac2_set_mac, - .rx_ipc = dwxgmac2_rx_ipc, - .rx_queue_enable = dwxgmac2_rx_queue_enable, -@@ -1532,8 +1541,8 @@ int dwxgmac2_setup(struct stmmac_priv *p - mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins); - - mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | -- MAC_1000FD | MAC_2500FD | MAC_5000FD | -- MAC_10000FD; -+ MAC_10 | MAC_100 | MAC_1000FD | -+ MAC_2500FD | MAC_5000FD | MAC_10000FD; - mac->link.duplex = 0; - mac->link.speed10 = XGMAC_CONFIG_SS_10_MII; - mac->link.speed100 = XGMAC_CONFIG_SS_100_MII; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c 2025-10-22 13:53:23.359328436 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c 2025-10-22 13:53:56.583168814 -0400 -@@ -203,10 +203,6 @@ static void dwxgmac2_dma_rx_mode(struct - } - - writel(value, ioaddr + XGMAC_MTL_RXQ_OPMODE(channel)); -- -- /* Enable MTL RX overflow */ -- value = readl(ioaddr + XGMAC_MTL_QINTEN(channel)); -- writel(value | XGMAC_RXOIE, ioaddr + XGMAC_MTL_QINTEN(channel)); - } - - static void dwxgmac2_dma_tx_mode(struct stmmac_priv *priv, void __iomem *ioaddr, -@@ -364,19 +360,17 @@ static int dwxgmac2_dma_interrupt(struct - } - - /* TX/RX NORMAL interrupts */ -- if (likely(intr_status & XGMAC_NIS)) { -- if (likely(intr_status & XGMAC_RI)) { -- u64_stats_update_begin(&stats->syncp); -- u64_stats_inc(&stats->rx_normal_irq_n[chan]); -- u64_stats_update_end(&stats->syncp); -- ret |= handle_rx; -- } -- if (likely(intr_status & (XGMAC_TI | XGMAC_TBU))) { -- u64_stats_update_begin(&stats->syncp); -- u64_stats_inc(&stats->tx_normal_irq_n[chan]); -- u64_stats_update_end(&stats->syncp); -- ret |= handle_tx; -- } -+ if (likely(intr_status & XGMAC_RI)) { -+ u64_stats_update_begin(&stats->syncp); -+ u64_stats_inc(&stats->rx_normal_irq_n[chan]); -+ u64_stats_update_end(&stats->syncp); -+ ret |= handle_rx; -+ } -+ if (likely(intr_status & (XGMAC_TI | XGMAC_TBU))) { -+ u64_stats_update_begin(&stats->syncp); -+ u64_stats_inc(&stats->tx_normal_irq_n[chan]); -+ u64_stats_update_end(&stats->syncp); -+ ret |= handle_tx; - } - - /* Clear interrupts */ -@@ -388,8 +382,11 @@ static int dwxgmac2_dma_interrupt(struct - static int dwxgmac2_get_hw_feature(void __iomem *ioaddr, - struct dma_features *dma_cap) - { -+ struct stmmac_priv *priv; - u32 hw_cap; - -+ priv = container_of(dma_cap, struct stmmac_priv, dma_cap); -+ - /* MAC HW feature 0 */ - hw_cap = readl(ioaddr + XGMAC_HW_FEATURE0); - dma_cap->edma = (hw_cap & XGMAC_HWFEAT_EDMA) >> 31; -@@ -412,6 +409,8 @@ static int dwxgmac2_get_hw_feature(void - dma_cap->vlhash = (hw_cap & XGMAC_HWFEAT_VLHASH) >> 4; - dma_cap->half_duplex = (hw_cap & XGMAC_HWFEAT_HDSEL) >> 3; - dma_cap->mbps_1000 = (hw_cap & XGMAC_HWFEAT_GMIISEL) >> 1; -+ if (dma_cap->mbps_1000 && priv->synopsys_id >= DWXGMAC_CORE_2_20) -+ dma_cap->mbps_10_100 = 1; - - /* MAC HW feature 1 */ - hw_cap = readl(ioaddr + XGMAC_HW_FEATURE1); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c 2025-10-22 13:53:23.359328436 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c 2025-10-22 13:53:56.583168814 -0400 -@@ -2584,6 +2584,7 @@ static bool stmmac_xdp_xmit_zc(struct st - struct netdev_queue *nq = netdev_get_tx_queue(priv->dev, queue); - struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue]; - struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[queue]; -+ bool csum = !priv->plat->tx_queues_cfg[queue].coe_unsupported; - struct xsk_buff_pool *pool = tx_q->xsk_pool; - unsigned int entry = tx_q->cur_tx; - struct dma_desc *tx_desc = NULL; -@@ -2596,7 +2597,7 @@ static bool stmmac_xdp_xmit_zc(struct st - - budget = min(budget, stmmac_tx_avail(priv, queue)); - -- while (budget-- > 0) { -+ for (; budget > 0; budget--) { - struct stmmac_metadata_request meta_req; - struct xsk_tx_metadata *meta = NULL; - dma_addr_t dma_addr; -@@ -2671,7 +2672,7 @@ static bool stmmac_xdp_xmit_zc(struct st - } - - stmmac_prepare_tx_desc(priv, tx_desc, 1, xdp_desc.len, -- true, priv->mode, true, true, -+ csum, priv->mode, true, true, - xdp_desc.len); - - stmmac_enable_dma_transmission(priv, priv->ioaddr, queue); -@@ -4983,6 +4984,7 @@ static int stmmac_xdp_xmit_xdpf(struct s - { - struct stmmac_txq_stats *txq_stats = &priv->xstats.txq_stats[queue]; - struct stmmac_tx_queue *tx_q = &priv->dma_conf.tx_queue[queue]; -+ bool csum = !priv->plat->tx_queues_cfg[queue].coe_unsupported; - unsigned int entry = tx_q->cur_tx; - struct dma_desc *tx_desc; - dma_addr_t dma_addr; -@@ -5034,7 +5036,7 @@ static int stmmac_xdp_xmit_xdpf(struct s - stmmac_set_desc_addr(priv, tx_desc, dma_addr); - - stmmac_prepare_tx_desc(priv, tx_desc, 1, xdpf->len, -- true, priv->mode, true, true, -+ csum, priv->mode, true, true, - xdpf->len); - - tx_q->tx_count_frames++; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/sun/niu.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/sun/niu.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/sun/niu.c 2025-10-22 13:53:23.359328436 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/sun/niu.c 2025-10-22 13:53:56.583168814 -0400 -@@ -3336,7 +3336,7 @@ static int niu_rbr_add_page(struct niu * - - addr = np->ops->map_page(np->device, page, 0, - PAGE_SIZE, DMA_FROM_DEVICE); -- if (!addr) { -+ if (np->ops->mapping_error(np->device, addr)) { - __free_page(page); - return -ENOMEM; - } -@@ -6676,6 +6676,8 @@ static netdev_tx_t niu_start_xmit(struct - len = skb_headlen(skb); - mapping = np->ops->map_single(np->device, skb->data, - len, DMA_TO_DEVICE); -+ if (np->ops->mapping_error(np->device, mapping)) -+ goto out_drop; - - prod = rp->prod; - -@@ -6717,6 +6719,8 @@ static netdev_tx_t niu_start_xmit(struct - mapping = np->ops->map_page(np->device, skb_frag_page(frag), - skb_frag_off(frag), len, - DMA_TO_DEVICE); -+ if (np->ops->mapping_error(np->device, mapping)) -+ goto out_unmap; - - rp->tx_buffs[prod].skb = NULL; - rp->tx_buffs[prod].mapping = mapping; -@@ -6741,6 +6745,19 @@ static netdev_tx_t niu_start_xmit(struct - out: - return NETDEV_TX_OK; - -+out_unmap: -+ while (i--) { -+ const skb_frag_t *frag; -+ -+ prod = PREVIOUS_TX(rp, prod); -+ frag = &skb_shinfo(skb)->frags[i]; -+ np->ops->unmap_page(np->device, rp->tx_buffs[prod].mapping, -+ skb_frag_size(frag), DMA_TO_DEVICE); -+ } -+ -+ np->ops->unmap_single(np->device, rp->tx_buffs[rp->prod].mapping, -+ skb_headlen(skb), DMA_TO_DEVICE); -+ - out_drop: - rp->tx_errors++; - kfree_skb(skb); -@@ -9644,6 +9661,11 @@ static void niu_pci_unmap_single(struct - dma_unmap_single(dev, dma_address, size, direction); - } - -+static int niu_pci_mapping_error(struct device *dev, u64 addr) -+{ -+ return dma_mapping_error(dev, addr); -+} -+ - static const struct niu_ops niu_pci_ops = { - .alloc_coherent = niu_pci_alloc_coherent, - .free_coherent = niu_pci_free_coherent, -@@ -9651,6 +9673,7 @@ static const struct niu_ops niu_pci_ops - .unmap_page = niu_pci_unmap_page, - .map_single = niu_pci_map_single, - .unmap_single = niu_pci_unmap_single, -+ .mapping_error = niu_pci_mapping_error, - }; - - static void niu_driver_version(void) -@@ -10019,6 +10042,11 @@ static void niu_phys_unmap_single(struct - /* Nothing to do. */ - } - -+static int niu_phys_mapping_error(struct device *dev, u64 dma_address) -+{ -+ return false; -+} -+ - static const struct niu_ops niu_phys_ops = { - .alloc_coherent = niu_phys_alloc_coherent, - .free_coherent = niu_phys_free_coherent, -@@ -10026,6 +10054,7 @@ static const struct niu_ops niu_phys_ops - .unmap_page = niu_phys_unmap_page, - .map_single = niu_phys_map_single, - .unmap_single = niu_phys_unmap_single, -+ .mapping_error = niu_phys_mapping_error, - }; - - static int niu_of_probe(struct platform_device *op) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/sun/niu.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/sun/niu.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/sun/niu.h 2025-10-22 13:53:23.359328436 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/sun/niu.h 2025-10-22 13:53:56.583168814 -0400 -@@ -2879,6 +2879,9 @@ struct tx_ring_info { - #define NEXT_TX(tp, index) \ - (((index) + 1) < (tp)->pending ? ((index) + 1) : 0) - -+#define PREVIOUS_TX(tp, index) \ -+ (((index) - 1) >= 0 ? ((index) - 1) : (((tp)->pending) - 1)) -+ - static inline u32 niu_tx_avail(struct tx_ring_info *tp) - { - return (tp->pending - -@@ -3140,6 +3143,7 @@ struct niu_ops { - enum dma_data_direction direction); - void (*unmap_single)(struct device *dev, u64 dma_address, - size_t size, enum dma_data_direction direction); -+ int (*mapping_error)(struct device *dev, u64 dma_address); - }; - - struct niu_link_config { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/ti/am65-cpsw-nuss.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/ti/am65-cpsw-nuss.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/ti/am65-cpsw-nuss.c 2025-10-22 13:53:23.359328436 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/ti/am65-cpsw-nuss.c 2025-10-22 13:53:56.587168794 -0400 -@@ -856,8 +856,6 @@ static struct sk_buff *am65_cpsw_build_s - { - struct sk_buff *skb; - -- len += AM65_CPSW_HEADROOM; -- - skb = build_skb(page_addr, len); - if (unlikely(!skb)) - return NULL; -@@ -1344,7 +1342,7 @@ static int am65_cpsw_nuss_rx_packets(str - } - - skb = am65_cpsw_build_skb(page_addr, ndev, -- AM65_CPSW_MAX_PACKET_SIZE, headroom); -+ PAGE_SIZE, headroom); - if (unlikely(!skb)) { - new_page = page; - goto requeue; -@@ -1524,7 +1522,7 @@ static int am65_cpsw_nuss_tx_compl_packe - } - } - -- if (single_port) { -+ if (single_port && num_tx) { - netif_txq = netdev_get_tx_queue(ndev, chn); - netdev_tx_completed_queue(netif_txq, num_tx, total_bytes); - am65_cpsw_nuss_tx_wake(tx_chn, ndev, netif_txq); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/ti/icssg/icssg_common.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/ti/icssg/icssg_common.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/ti/icssg/icssg_common.c 2025-10-22 13:53:23.359328436 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/ti/icssg/icssg_common.c 2025-10-22 13:53:56.587168794 -0400 -@@ -98,20 +98,11 @@ void prueth_xmit_free(struct prueth_tx_c - { - struct cppi5_host_desc_t *first_desc, *next_desc; - dma_addr_t buf_dma, next_desc_dma; -- struct prueth_swdata *swdata; -- struct page *page; - u32 buf_dma_len; - - first_desc = desc; - next_desc = first_desc; - -- swdata = cppi5_hdesc_get_swdata(desc); -- if (swdata->type == PRUETH_SWDATA_PAGE) { -- page = swdata->data.page; -- page_pool_recycle_direct(page->pp, swdata->data.page); -- goto free_desc; -- } -- - cppi5_hdesc_get_obuf(first_desc, &buf_dma, &buf_dma_len); - k3_udma_glue_tx_cppi5_to_dma_addr(tx_chn->tx_chn, &buf_dma); - -@@ -135,7 +126,6 @@ void prueth_xmit_free(struct prueth_tx_c - k3_cppi_desc_pool_free(tx_chn->desc_pool, next_desc); - } - --free_desc: - k3_cppi_desc_pool_free(tx_chn->desc_pool, first_desc); - } - EXPORT_SYMBOL_GPL(prueth_xmit_free); -@@ -612,13 +602,8 @@ u32 emac_xmit_xdp_frame(struct prueth_em - k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &buf_dma); - cppi5_hdesc_attach_buf(first_desc, buf_dma, xdpf->len, buf_dma, xdpf->len); - swdata = cppi5_hdesc_get_swdata(first_desc); -- if (page) { -- swdata->type = PRUETH_SWDATA_PAGE; -- swdata->data.page = page; -- } else { -- swdata->type = PRUETH_SWDATA_XDPF; -- swdata->data.xdpf = xdpf; -- } -+ swdata->type = PRUETH_SWDATA_XDPF; -+ swdata->data.xdpf = xdpf; - - /* Report BQL before sending the packet */ - netif_txq = netdev_get_tx_queue(ndev, tx_chn->id); -@@ -721,9 +706,9 @@ static int emac_rx_packet(struct prueth_ - struct page_pool *pool; - struct sk_buff *skb; - struct xdp_buff xdp; -+ int headroom, ret; - u32 *psdata; - void *pa; -- int ret; - - *xdp_state = 0; - pool = rx_chn->pg_pool; -@@ -772,22 +757,23 @@ static int emac_rx_packet(struct prueth_ - xdp_prepare_buff(&xdp, pa, PRUETH_HEADROOM, pkt_len, false); - - *xdp_state = emac_run_xdp(emac, &xdp, page, &pkt_len); -- if (*xdp_state == ICSSG_XDP_PASS) -- skb = xdp_build_skb_from_buff(&xdp); -- else -+ if (*xdp_state != ICSSG_XDP_PASS) - goto requeue; -+ headroom = xdp.data - xdp.data_hard_start; -+ pkt_len = xdp.data_end - xdp.data; - } else { -- /* prepare skb and send to n/w stack */ -- skb = napi_build_skb(pa, PAGE_SIZE); -+ headroom = PRUETH_HEADROOM; - } - -+ /* prepare skb and send to n/w stack */ -+ skb = napi_build_skb(pa, PAGE_SIZE); - if (!skb) { - ndev->stats.rx_dropped++; - page_pool_recycle_direct(pool, page); - goto requeue; - } - -- skb_reserve(skb, PRUETH_HEADROOM); -+ skb_reserve(skb, headroom); - skb_put(skb, pkt_len); - skb->dev = ndev; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/ti/icssg/icssg_config.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/ti/icssg/icssg_config.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/ti/icssg/icssg_config.c 2025-10-22 13:53:23.359328436 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/ti/icssg/icssg_config.c 2025-10-22 13:53:56.587168794 -0400 -@@ -288,8 +288,12 @@ static int prueth_fw_offload_buffer_setu - int i; - - addr = lower_32_bits(prueth->msmcram.pa); -- if (slice) -- addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE; -+ if (slice) { -+ if (prueth->pdata.banked_ms_ram) -+ addr += MSMC_RAM_BANK_SIZE; -+ else -+ addr += PRUETH_SW_TOTAL_BUF_SIZE_PER_SLICE; -+ } - - if (addr % SZ_64K) { - dev_warn(prueth->dev, "buffer pool needs to be 64KB aligned\n"); -@@ -297,43 +301,66 @@ static int prueth_fw_offload_buffer_setu - } - - bpool_cfg = emac->dram.va + BUFFER_POOL_0_ADDR_OFFSET; -- /* workaround for f/w bug. bpool 0 needs to be initialized */ -- for (i = 0; i < PRUETH_NUM_BUF_POOLS; i++) { -+ -+ /* Configure buffer pools for forwarding buffers -+ * - used by firmware to store packets to be forwarded to other port -+ * - 8 total pools per slice -+ */ -+ for (i = 0; i < PRUETH_NUM_FWD_BUF_POOLS_PER_SLICE; i++) { - writel(addr, &bpool_cfg[i].addr); -- writel(PRUETH_EMAC_BUF_POOL_SIZE, &bpool_cfg[i].len); -- addr += PRUETH_EMAC_BUF_POOL_SIZE; -+ writel(PRUETH_SW_FWD_BUF_POOL_SIZE, &bpool_cfg[i].len); -+ addr += PRUETH_SW_FWD_BUF_POOL_SIZE; - } - -- if (!slice) -- addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE; -- else -- addr += PRUETH_SW_NUM_BUF_POOLS_HOST * PRUETH_SW_BUF_POOL_SIZE_HOST; -- -- for (i = PRUETH_NUM_BUF_POOLS; -- i < 2 * PRUETH_SW_NUM_BUF_POOLS_HOST + PRUETH_NUM_BUF_POOLS; -- i++) { -- /* The driver only uses first 4 queues per PRU so only initialize them */ -- if (i % PRUETH_SW_NUM_BUF_POOLS_HOST < PRUETH_SW_NUM_BUF_POOLS_PER_PRU) { -- writel(addr, &bpool_cfg[i].addr); -- writel(PRUETH_SW_BUF_POOL_SIZE_HOST, &bpool_cfg[i].len); -- addr += PRUETH_SW_BUF_POOL_SIZE_HOST; -+ /* Configure buffer pools for Local Injection buffers -+ * - used by firmware to store packets received from host core -+ * - 16 total pools per slice -+ */ -+ for (i = 0; i < PRUETH_NUM_LI_BUF_POOLS_PER_SLICE; i++) { -+ int cfg_idx = i + PRUETH_NUM_FWD_BUF_POOLS_PER_SLICE; -+ -+ /* The driver only uses first 4 queues per PRU, -+ * so only initialize buffer for them -+ */ -+ if ((i % PRUETH_NUM_LI_BUF_POOLS_PER_PORT_PER_SLICE) -+ < PRUETH_SW_USED_LI_BUF_POOLS_PER_PORT_PER_SLICE) { -+ writel(addr, &bpool_cfg[cfg_idx].addr); -+ writel(PRUETH_SW_LI_BUF_POOL_SIZE, -+ &bpool_cfg[cfg_idx].len); -+ addr += PRUETH_SW_LI_BUF_POOL_SIZE; - } else { -- writel(0, &bpool_cfg[i].addr); -- writel(0, &bpool_cfg[i].len); -+ writel(0, &bpool_cfg[cfg_idx].addr); -+ writel(0, &bpool_cfg[cfg_idx].len); - } - } - -- if (!slice) -- addr += PRUETH_SW_NUM_BUF_POOLS_HOST * PRUETH_SW_BUF_POOL_SIZE_HOST; -- else -- addr += PRUETH_EMAC_RX_CTX_BUF_SIZE; -+ /* Express RX buffer queue -+ * - used by firmware to store express packets to be transmitted -+ * to the host core -+ */ -+ rxq_ctx = emac->dram.va + HOST_RX_Q_EXP_CONTEXT_OFFSET; -+ for (i = 0; i < 3; i++) -+ writel(addr, &rxq_ctx->start[i]); -+ -+ addr += PRUETH_SW_HOST_EXP_BUF_POOL_SIZE; -+ writel(addr, &rxq_ctx->end); - -+ /* Pre-emptible RX buffer queue -+ * - used by firmware to store preemptible packets to be transmitted -+ * to the host core -+ */ - rxq_ctx = emac->dram.va + HOST_RX_Q_PRE_CONTEXT_OFFSET; - for (i = 0; i < 3; i++) - writel(addr, &rxq_ctx->start[i]); - -- addr += PRUETH_EMAC_RX_CTX_BUF_SIZE; -- writel(addr - SZ_2K, &rxq_ctx->end); -+ addr += PRUETH_SW_HOST_PRE_BUF_POOL_SIZE; -+ writel(addr, &rxq_ctx->end); -+ -+ /* Set pointer for default dropped packet write -+ * - used by firmware to temporarily store packet to be dropped -+ */ -+ rxq_ctx = emac->dram.va + DEFAULT_MSMC_Q_OFFSET; -+ writel(addr, &rxq_ctx->start[0]); - - return 0; - } -@@ -347,13 +374,13 @@ static int prueth_emac_buffer_setup(stru - u32 addr; - int i; - -- /* Layout to have 64KB aligned buffer pool -- * |BPOOL0|BPOOL1|RX_CTX0|RX_CTX1| -- */ -- - addr = lower_32_bits(prueth->msmcram.pa); -- if (slice) -- addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE; -+ if (slice) { -+ if (prueth->pdata.banked_ms_ram) -+ addr += MSMC_RAM_BANK_SIZE; -+ else -+ addr += PRUETH_EMAC_TOTAL_BUF_SIZE_PER_SLICE; -+ } - - if (addr % SZ_64K) { - dev_warn(prueth->dev, "buffer pool needs to be 64KB aligned\n"); -@@ -361,39 +388,66 @@ static int prueth_emac_buffer_setup(stru - } - - bpool_cfg = emac->dram.va + BUFFER_POOL_0_ADDR_OFFSET; -- /* workaround for f/w bug. bpool 0 needs to be initilalized */ -- writel(addr, &bpool_cfg[0].addr); -- writel(0, &bpool_cfg[0].len); -- -- for (i = PRUETH_EMAC_BUF_POOL_START; -- i < PRUETH_EMAC_BUF_POOL_START + PRUETH_NUM_BUF_POOLS; -- i++) { -- writel(addr, &bpool_cfg[i].addr); -- writel(PRUETH_EMAC_BUF_POOL_SIZE, &bpool_cfg[i].len); -- addr += PRUETH_EMAC_BUF_POOL_SIZE; -+ -+ /* Configure buffer pools for forwarding buffers -+ * - in mac mode - no forwarding so initialize all pools to 0 -+ * - 8 total pools per slice -+ */ -+ for (i = 0; i < PRUETH_NUM_FWD_BUF_POOLS_PER_SLICE; i++) { -+ writel(0, &bpool_cfg[i].addr); -+ writel(0, &bpool_cfg[i].len); - } - -- if (!slice) -- addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE; -- else -- addr += PRUETH_EMAC_RX_CTX_BUF_SIZE * 2; -+ /* Configure buffer pools for Local Injection buffers -+ * - used by firmware to store packets received from host core -+ * - 16 total pools per slice -+ */ -+ bpool_cfg = emac->dram.va + BUFFER_POOL_0_ADDR_OFFSET; -+ for (i = 0; i < PRUETH_NUM_LI_BUF_POOLS_PER_SLICE; i++) { -+ int cfg_idx = i + PRUETH_NUM_FWD_BUF_POOLS_PER_SLICE; - -- /* Pre-emptible RX buffer queue */ -- rxq_ctx = emac->dram.va + HOST_RX_Q_PRE_CONTEXT_OFFSET; -+ /* In EMAC mode, only first 4 buffers are used, -+ * as 1 slice needs to handle only 1 port -+ */ -+ if (i < PRUETH_EMAC_USED_LI_BUF_POOLS_PER_PORT_PER_SLICE) { -+ writel(addr, &bpool_cfg[cfg_idx].addr); -+ writel(PRUETH_EMAC_LI_BUF_POOL_SIZE, -+ &bpool_cfg[cfg_idx].len); -+ addr += PRUETH_EMAC_LI_BUF_POOL_SIZE; -+ } else { -+ writel(0, &bpool_cfg[cfg_idx].addr); -+ writel(0, &bpool_cfg[cfg_idx].len); -+ } -+ } -+ -+ /* Express RX buffer queue -+ * - used by firmware to store express packets to be transmitted -+ * to host core -+ */ -+ rxq_ctx = emac->dram.va + HOST_RX_Q_EXP_CONTEXT_OFFSET; - for (i = 0; i < 3; i++) - writel(addr, &rxq_ctx->start[i]); - -- addr += PRUETH_EMAC_RX_CTX_BUF_SIZE; -+ addr += PRUETH_EMAC_HOST_EXP_BUF_POOL_SIZE; - writel(addr, &rxq_ctx->end); - -- /* Express RX buffer queue */ -- rxq_ctx = emac->dram.va + HOST_RX_Q_EXP_CONTEXT_OFFSET; -+ /* Pre-emptible RX buffer queue -+ * - used by firmware to store preemptible packets to be transmitted -+ * to host core -+ */ -+ rxq_ctx = emac->dram.va + HOST_RX_Q_PRE_CONTEXT_OFFSET; - for (i = 0; i < 3; i++) - writel(addr, &rxq_ctx->start[i]); - -- addr += PRUETH_EMAC_RX_CTX_BUF_SIZE; -+ addr += PRUETH_EMAC_HOST_PRE_BUF_POOL_SIZE; - writel(addr, &rxq_ctx->end); - -+ /* Set pointer for default dropped packet write -+ * - used by firmware to temporarily store packet to be dropped -+ */ -+ rxq_ctx = emac->dram.va + DEFAULT_MSMC_Q_OFFSET; -+ writel(addr, &rxq_ctx->start[0]); -+ - return 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/ti/icssg/icssg_config.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/ti/icssg/icssg_config.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/ti/icssg/icssg_config.h 2025-10-22 13:53:23.359328436 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/ti/icssg/icssg_config.h 2025-10-22 13:53:56.587168794 -0400 -@@ -26,21 +26,71 @@ struct icssg_flow_cfg { - #define PRUETH_MAX_RX_FLOWS 1 /* excluding default flow */ - #define PRUETH_RX_FLOW_DATA 0 - --#define PRUETH_EMAC_BUF_POOL_SIZE SZ_8K --#define PRUETH_EMAC_POOLS_PER_SLICE 24 --#define PRUETH_EMAC_BUF_POOL_START 8 --#define PRUETH_NUM_BUF_POOLS 8 --#define PRUETH_EMAC_RX_CTX_BUF_SIZE SZ_16K /* per slice */ --#define MSMC_RAM_SIZE \ -- (2 * (PRUETH_EMAC_BUF_POOL_SIZE * PRUETH_NUM_BUF_POOLS + \ -- PRUETH_EMAC_RX_CTX_BUF_SIZE * 2)) -- --#define PRUETH_SW_BUF_POOL_SIZE_HOST SZ_4K --#define PRUETH_SW_NUM_BUF_POOLS_HOST 8 --#define PRUETH_SW_NUM_BUF_POOLS_PER_PRU 4 --#define MSMC_RAM_SIZE_SWITCH_MODE \ -- (MSMC_RAM_SIZE + \ -- (2 * PRUETH_SW_BUF_POOL_SIZE_HOST * PRUETH_SW_NUM_BUF_POOLS_HOST)) -+/* Defines for forwarding path buffer pools: -+ * - used by firmware to store packets to be forwarded to other port -+ * - 8 total pools per slice -+ * - only used in switch mode (as no forwarding in mac mode) -+ */ -+#define PRUETH_NUM_FWD_BUF_POOLS_PER_SLICE 8 -+#define PRUETH_SW_FWD_BUF_POOL_SIZE (SZ_8K) -+ -+/* Defines for local injection path buffer pools: -+ * - used by firmware to store packets received from host core -+ * - 16 total pools per slice -+ * - 8 pools per port per slice and each slice handles both ports -+ * - only 4 out of 8 pools used per port (as only 4 real QoS levels in ICSSG) -+ * - switch mode: 8 total pools used -+ * - mac mode: 4 total pools used -+ */ -+#define PRUETH_NUM_LI_BUF_POOLS_PER_SLICE 16 -+#define PRUETH_NUM_LI_BUF_POOLS_PER_PORT_PER_SLICE 8 -+#define PRUETH_SW_LI_BUF_POOL_SIZE SZ_4K -+#define PRUETH_SW_USED_LI_BUF_POOLS_PER_SLICE 8 -+#define PRUETH_SW_USED_LI_BUF_POOLS_PER_PORT_PER_SLICE 4 -+#define PRUETH_EMAC_LI_BUF_POOL_SIZE SZ_8K -+#define PRUETH_EMAC_USED_LI_BUF_POOLS_PER_SLICE 4 -+#define PRUETH_EMAC_USED_LI_BUF_POOLS_PER_PORT_PER_SLICE 4 -+ -+/* Defines for host egress path - express and preemptible buffers -+ * - used by firmware to store express and preemptible packets -+ * to be transmitted to host core -+ * - used by both mac/switch modes -+ */ -+#define PRUETH_SW_HOST_EXP_BUF_POOL_SIZE SZ_16K -+#define PRUETH_SW_HOST_PRE_BUF_POOL_SIZE (SZ_16K - SZ_2K) -+#define PRUETH_EMAC_HOST_EXP_BUF_POOL_SIZE PRUETH_SW_HOST_EXP_BUF_POOL_SIZE -+#define PRUETH_EMAC_HOST_PRE_BUF_POOL_SIZE PRUETH_SW_HOST_PRE_BUF_POOL_SIZE -+ -+/* Buffer used by firmware to temporarily store packet to be dropped */ -+#define PRUETH_SW_DROP_PKT_BUF_SIZE SZ_2K -+#define PRUETH_EMAC_DROP_PKT_BUF_SIZE PRUETH_SW_DROP_PKT_BUF_SIZE -+ -+/* Total switch mode memory usage for buffers per slice */ -+#define PRUETH_SW_TOTAL_BUF_SIZE_PER_SLICE \ -+ (PRUETH_SW_FWD_BUF_POOL_SIZE * PRUETH_NUM_FWD_BUF_POOLS_PER_SLICE + \ -+ PRUETH_SW_LI_BUF_POOL_SIZE * PRUETH_SW_USED_LI_BUF_POOLS_PER_SLICE + \ -+ PRUETH_SW_HOST_EXP_BUF_POOL_SIZE + \ -+ PRUETH_SW_HOST_PRE_BUF_POOL_SIZE + \ -+ PRUETH_SW_DROP_PKT_BUF_SIZE) -+ -+/* Total switch mode memory usage for all buffers */ -+#define PRUETH_SW_TOTAL_BUF_SIZE \ -+ (2 * PRUETH_SW_TOTAL_BUF_SIZE_PER_SLICE) -+ -+/* Total mac mode memory usage for buffers per slice */ -+#define PRUETH_EMAC_TOTAL_BUF_SIZE_PER_SLICE \ -+ (PRUETH_EMAC_LI_BUF_POOL_SIZE * \ -+ PRUETH_EMAC_USED_LI_BUF_POOLS_PER_SLICE + \ -+ PRUETH_EMAC_HOST_EXP_BUF_POOL_SIZE + \ -+ PRUETH_EMAC_HOST_PRE_BUF_POOL_SIZE + \ -+ PRUETH_EMAC_DROP_PKT_BUF_SIZE) -+ -+/* Total mac mode memory usage for all buffers */ -+#define PRUETH_EMAC_TOTAL_BUF_SIZE \ -+ (2 * PRUETH_EMAC_TOTAL_BUF_SIZE_PER_SLICE) -+ -+/* Size of 1 bank of MSMC/OC_SRAM memory */ -+#define MSMC_RAM_BANK_SIZE SZ_256K - - #define PRUETH_SWITCH_FDB_MASK ((SIZE_OF_FDB / NUMBER_OF_FDB_BUCKET_ENTRIES) - 1) - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/ti/icssg/icssg_prueth.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/ti/icssg/icssg_prueth.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/ti/icssg/icssg_prueth.c 2025-10-22 13:53:23.359328436 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/ti/icssg/icssg_prueth.c 2025-10-22 13:53:56.587168794 -0400 -@@ -50,6 +50,8 @@ - /* CTRLMMR_ICSSG_RGMII_CTRL register bits */ - #define ICSSG_CTRL_RGMII_ID_MODE BIT(24) - -+static void emac_adjust_link(struct net_device *ndev); -+ - static int emac_get_tx_ts(struct prueth_emac *emac, - struct emac_tx_ts_response *rsp) - { -@@ -238,6 +240,44 @@ static void prueth_emac_stop(struct prue - } - } - -+static void icssg_enable_fw_offload(struct prueth *prueth) -+{ -+ struct prueth_emac *emac; -+ int mac; -+ -+ for (mac = PRUETH_MAC0; mac < PRUETH_NUM_MACS; mac++) { -+ emac = prueth->emac[mac]; -+ if (prueth->is_hsr_offload_mode) { -+ if (emac->ndev->features & NETIF_F_HW_HSR_TAG_RM) -+ icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE); -+ else -+ icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_DISABLE); -+ } -+ -+ if (prueth->is_switch_mode || prueth->is_hsr_offload_mode) { -+ if (netif_running(emac->ndev)) { -+ icssg_fdb_add_del(emac, eth_stp_addr, prueth->default_vlan, -+ ICSSG_FDB_ENTRY_P0_MEMBERSHIP | -+ ICSSG_FDB_ENTRY_P1_MEMBERSHIP | -+ ICSSG_FDB_ENTRY_P2_MEMBERSHIP | -+ ICSSG_FDB_ENTRY_BLOCK, -+ true); -+ icssg_vtbl_modify(emac, emac->port_vlan | DEFAULT_VID, -+ BIT(emac->port_id) | DEFAULT_PORT_MASK, -+ BIT(emac->port_id) | DEFAULT_UNTAG_MASK, -+ true); -+ if (prueth->is_hsr_offload_mode) -+ icssg_vtbl_modify(emac, DEFAULT_VID, -+ DEFAULT_PORT_MASK, -+ DEFAULT_UNTAG_MASK, true); -+ icssg_set_pvid(prueth, emac->port_vlan, emac->port_id); -+ if (prueth->is_switch_mode) -+ icssg_set_port_state(emac, ICSSG_EMAC_PORT_VLAN_AWARE_ENABLE); -+ } -+ } -+ } -+} -+ - static int prueth_emac_common_start(struct prueth *prueth) - { - struct prueth_emac *emac; -@@ -266,6 +306,10 @@ static int prueth_emac_common_start(stru - ret = icssg_config(prueth, emac, slice); - if (ret) - goto disable_class; -+ -+ mutex_lock(&emac->ndev->phydev->lock); -+ emac_adjust_link(emac->ndev); -+ mutex_unlock(&emac->ndev->phydev->lock); - } - - ret = prueth_emac_start(prueth); -@@ -647,7 +691,7 @@ static void icssg_prueth_hsr_fdb_add_del - - static int icssg_prueth_hsr_add_mcast(struct net_device *ndev, const u8 *addr) - { -- struct net_device *real_dev; -+ struct net_device *real_dev, *port_dev; - struct prueth_emac *emac; - u8 vlan_id, i; - -@@ -656,11 +700,15 @@ static int icssg_prueth_hsr_add_mcast(st - - if (is_hsr_master(real_dev)) { - for (i = HSR_PT_SLAVE_A; i < HSR_PT_INTERLINK; i++) { -- emac = netdev_priv(hsr_get_port_ndev(real_dev, i)); -- if (!emac) -+ port_dev = hsr_get_port_ndev(real_dev, i); -+ emac = netdev_priv(port_dev); -+ if (!emac) { -+ dev_put(port_dev); - return -EINVAL; -+ } - icssg_prueth_hsr_fdb_add_del(emac, addr, vlan_id, - true); -+ dev_put(port_dev); - } - } else { - emac = netdev_priv(real_dev); -@@ -672,7 +720,7 @@ static int icssg_prueth_hsr_add_mcast(st - - static int icssg_prueth_hsr_del_mcast(struct net_device *ndev, const u8 *addr) - { -- struct net_device *real_dev; -+ struct net_device *real_dev, *port_dev; - struct prueth_emac *emac; - u8 vlan_id, i; - -@@ -681,11 +729,15 @@ static int icssg_prueth_hsr_del_mcast(st - - if (is_hsr_master(real_dev)) { - for (i = HSR_PT_SLAVE_A; i < HSR_PT_INTERLINK; i++) { -- emac = netdev_priv(hsr_get_port_ndev(real_dev, i)); -- if (!emac) -+ port_dev = hsr_get_port_ndev(real_dev, i); -+ emac = netdev_priv(port_dev); -+ if (!emac) { -+ dev_put(port_dev); - return -EINVAL; -+ } - icssg_prueth_hsr_fdb_add_del(emac, addr, vlan_id, - false); -+ dev_put(port_dev); - } - } else { - emac = netdev_priv(real_dev); -@@ -784,6 +836,7 @@ static int emac_ndo_open(struct net_devi - ret = prueth_emac_common_start(prueth); - if (ret) - goto free_rx_irq; -+ icssg_enable_fw_offload(prueth); - } - - flow_cfg = emac->dram.va + ICSSG_CONFIG_OFFSET + PSI_L_REGULAR_FLOW_ID_BASE_OFFSET; -@@ -1391,8 +1444,7 @@ static int prueth_emac_restart(struct pr - - static void icssg_change_mode(struct prueth *prueth) - { -- struct prueth_emac *emac; -- int mac, ret; -+ int ret; - - ret = prueth_emac_restart(prueth); - if (ret) { -@@ -1400,35 +1452,7 @@ static void icssg_change_mode(struct pru - return; - } - -- for (mac = PRUETH_MAC0; mac < PRUETH_NUM_MACS; mac++) { -- emac = prueth->emac[mac]; -- if (prueth->is_hsr_offload_mode) { -- if (emac->ndev->features & NETIF_F_HW_HSR_TAG_RM) -- icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_ENABLE); -- else -- icssg_set_port_state(emac, ICSSG_EMAC_HSR_RX_OFFLOAD_DISABLE); -- } -- -- if (netif_running(emac->ndev)) { -- icssg_fdb_add_del(emac, eth_stp_addr, prueth->default_vlan, -- ICSSG_FDB_ENTRY_P0_MEMBERSHIP | -- ICSSG_FDB_ENTRY_P1_MEMBERSHIP | -- ICSSG_FDB_ENTRY_P2_MEMBERSHIP | -- ICSSG_FDB_ENTRY_BLOCK, -- true); -- icssg_vtbl_modify(emac, emac->port_vlan | DEFAULT_VID, -- BIT(emac->port_id) | DEFAULT_PORT_MASK, -- BIT(emac->port_id) | DEFAULT_UNTAG_MASK, -- true); -- if (prueth->is_hsr_offload_mode) -- icssg_vtbl_modify(emac, DEFAULT_VID, -- DEFAULT_PORT_MASK, -- DEFAULT_UNTAG_MASK, true); -- icssg_set_pvid(prueth, emac->port_vlan, emac->port_id); -- if (prueth->is_switch_mode) -- icssg_set_port_state(emac, ICSSG_EMAC_PORT_VLAN_AWARE_ENABLE); -- } -- } -+ icssg_enable_fw_offload(prueth); - } - - static int prueth_netdevice_port_link(struct net_device *ndev, -@@ -1764,10 +1788,15 @@ static int prueth_probe(struct platform_ - goto put_mem; - } - -- msmc_ram_size = MSMC_RAM_SIZE; - prueth->is_switchmode_supported = prueth->pdata.switch_mode; -- if (prueth->is_switchmode_supported) -- msmc_ram_size = MSMC_RAM_SIZE_SWITCH_MODE; -+ if (prueth->pdata.banked_ms_ram) { -+ /* Reserve 2 MSMC RAM banks for buffers to avoid arbitration */ -+ msmc_ram_size = (2 * MSMC_RAM_BANK_SIZE); -+ } else { -+ msmc_ram_size = PRUETH_EMAC_TOTAL_BUF_SIZE; -+ if (prueth->is_switchmode_supported) -+ msmc_ram_size = PRUETH_SW_TOTAL_BUF_SIZE; -+ } - - /* NOTE: FW bug needs buffer base to be 64KB aligned */ - prueth->msmcram.va = -@@ -1924,7 +1953,8 @@ put_iep0: - - free_pool: - gen_pool_free(prueth->sram_pool, -- (unsigned long)prueth->msmcram.va, msmc_ram_size); -+ (unsigned long)prueth->msmcram.va, -+ prueth->msmcram.size); - - put_mem: - pruss_release_mem_region(prueth->pruss, &prueth->shram); -@@ -1976,8 +2006,8 @@ static void prueth_remove(struct platfor - icss_iep_put(prueth->iep0); - - gen_pool_free(prueth->sram_pool, -- (unsigned long)prueth->msmcram.va, -- MSMC_RAM_SIZE); -+ (unsigned long)prueth->msmcram.va, -+ prueth->msmcram.size); - - pruss_release_mem_region(prueth->pruss, &prueth->shram); - -@@ -1994,12 +2024,14 @@ static const struct prueth_pdata am654_i - .fdqring_mode = K3_RINGACC_RING_MODE_MESSAGE, - .quirk_10m_link_issue = 1, - .switch_mode = 1, -+ .banked_ms_ram = 0, - }; - - static const struct prueth_pdata am64x_icssg_pdata = { - .fdqring_mode = K3_RINGACC_RING_MODE_RING, - .quirk_10m_link_issue = 1, - .switch_mode = 1, -+ .banked_ms_ram = 1, - }; - - static const struct of_device_id prueth_dt_match[] = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/ti/icssg/icssg_prueth.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/ti/icssg/icssg_prueth.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/ti/icssg/icssg_prueth.h 2025-10-22 13:53:23.359328436 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/ti/icssg/icssg_prueth.h 2025-10-22 13:53:56.587168794 -0400 -@@ -251,11 +251,13 @@ struct prueth_emac { - * @fdqring_mode: Free desc queue mode - * @quirk_10m_link_issue: 10M link detect errata - * @switch_mode: switch firmware support -+ * @banked_ms_ram: banked memory support - */ - struct prueth_pdata { - enum k3_ring_mode fdqring_mode; - u32 quirk_10m_link_issue:1; - u32 switch_mode:1; -+ u32 banked_ms_ram:1; - }; - - struct icssg_firmwares { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/ti/icssg/icssg_switch_map.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/ti/icssg/icssg_switch_map.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/ti/icssg/icssg_switch_map.h 2025-10-22 13:53:23.359328436 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/ti/icssg/icssg_switch_map.h 2025-10-22 13:53:56.587168794 -0400 -@@ -180,6 +180,9 @@ - /* Used to notify the FW of the current link speed */ - #define PORT_LINK_SPEED_OFFSET 0x00A8 - -+/* 2k memory pointer reserved for default writes by PRU0*/ -+#define DEFAULT_MSMC_Q_OFFSET 0x00AC -+ - /* TAS gate mask for windows list0 */ - #define TAS_GATE_MASK_LIST0 0x0100 - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/ti/icssg/icss_iep.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/ti/icssg/icss_iep.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/ti/icssg/icss_iep.c 2025-10-22 13:53:23.359328436 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/ti/icssg/icss_iep.c 2025-10-22 13:53:56.587168794 -0400 -@@ -621,7 +621,8 @@ exit: - - static int icss_iep_extts_enable(struct icss_iep *iep, u32 index, int on) - { -- u32 val, cap, ret = 0; -+ u32 val, cap; -+ int ret = 0; - - mutex_lock(&iep->ptp_clk_mutex); - -@@ -685,11 +686,17 @@ struct icss_iep *icss_iep_get_idx(struct - struct platform_device *pdev; - struct device_node *iep_np; - struct icss_iep *iep; -+ int ret; - - iep_np = of_parse_phandle(np, "ti,iep", idx); -- if (!iep_np || !of_device_is_available(iep_np)) -+ if (!iep_np) - return ERR_PTR(-ENODEV); - -+ if (!of_device_is_available(iep_np)) { -+ of_node_put(iep_np); -+ return ERR_PTR(-ENODEV); -+ } -+ - pdev = of_find_device_by_node(iep_np); - of_node_put(iep_np); - -@@ -698,21 +705,28 @@ struct icss_iep *icss_iep_get_idx(struct - return ERR_PTR(-EPROBE_DEFER); - - iep = platform_get_drvdata(pdev); -- if (!iep) -- return ERR_PTR(-EPROBE_DEFER); -+ if (!iep) { -+ ret = -EPROBE_DEFER; -+ goto err_put_pdev; -+ } - - device_lock(iep->dev); - if (iep->client_np) { - device_unlock(iep->dev); - dev_err(iep->dev, "IEP is already acquired by %s", - iep->client_np->name); -- return ERR_PTR(-EBUSY); -+ ret = -EBUSY; -+ goto err_put_pdev; - } - iep->client_np = np; - device_unlock(iep->dev); -- get_device(iep->dev); - - return iep; -+ -+err_put_pdev: -+ put_device(&pdev->dev); -+ -+ return ERR_PTR(ret); - } - EXPORT_SYMBOL_GPL(icss_iep_get_idx); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/wangxun/libwx/wx_hw.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/wangxun/libwx/wx_hw.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/wangxun/libwx/wx_hw.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/wangxun/libwx/wx_hw.c 2025-10-22 13:53:56.587168794 -0400 -@@ -1912,7 +1912,6 @@ static void wx_configure_rx_ring(struct - struct wx_ring *ring) - { - u16 reg_idx = ring->reg_idx; -- union wx_rx_desc *rx_desc; - u64 rdba = ring->dma; - u32 rxdctl; - -@@ -1942,9 +1941,9 @@ static void wx_configure_rx_ring(struct - memset(ring->rx_buffer_info, 0, - sizeof(struct wx_rx_buffer) * ring->count); - -- /* initialize Rx descriptor 0 */ -- rx_desc = WX_RX_DESC(ring, 0); -- rx_desc->wb.upper.length = 0; -+ /* reset ntu and ntc to place SW in sync with hardware */ -+ ring->next_to_clean = 0; -+ ring->next_to_use = 0; - - /* enable receive descriptor ring */ - wr32m(wx, WX_PX_RR_CFG(reg_idx), -@@ -2072,10 +2071,6 @@ static void wx_setup_mrqc(struct wx *wx) - { - u32 rss_field = 0; - -- /* VT, and RSS do not coexist at the same time */ -- if (test_bit(WX_FLAG_VMDQ_ENABLED, wx->flags)) -- return; -- - /* Disable indicating checksum in descriptor, enables RSS hash */ - wr32m(wx, WX_PSR_CTL, WX_PSR_CTL_PCSD, WX_PSR_CTL_PCSD); - -@@ -2778,6 +2773,8 @@ void wx_update_stats(struct wx *wx) - hwstats->fdirmiss += rd32(wx, WX_RDB_FDIR_MISS); - } - -+ /* qmprc is not cleared on read, manual reset it */ -+ hwstats->qmprc = 0; - for (i = wx->num_vfs * wx->num_rx_queues_per_pool; - i < wx->mac.max_rx_queues; i++) - hwstats->qmprc += rd32(wx, WX_PX_MPRC(i)); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/wangxun/libwx/wx_lib.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/wangxun/libwx/wx_lib.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/wangxun/libwx/wx_lib.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/wangxun/libwx/wx_lib.c 2025-10-22 13:53:56.587168794 -0400 -@@ -174,10 +174,6 @@ static void wx_dma_sync_frag(struct wx_r - skb_frag_off(frag), - skb_frag_size(frag), - DMA_FROM_DEVICE); -- -- /* If the page was released, just unmap it. */ -- if (unlikely(WX_CB(skb)->page_released)) -- page_pool_put_full_page(rx_ring->page_pool, rx_buffer->page, false); - } - - static struct wx_rx_buffer *wx_get_rx_buffer(struct wx_ring *rx_ring, -@@ -227,10 +223,6 @@ static void wx_put_rx_buffer(struct wx_r - struct sk_buff *skb, - int rx_buffer_pgcnt) - { -- if (!IS_ERR(skb) && WX_CB(skb)->dma == rx_buffer->dma) -- /* the page has been released from the ring */ -- WX_CB(skb)->page_released = true; -- - /* clear contents of rx_buffer */ - rx_buffer->page = NULL; - rx_buffer->skb = NULL; -@@ -315,7 +307,7 @@ static bool wx_alloc_mapped_page(struct - return false; - dma = page_pool_get_dma_addr(page); - -- bi->page_dma = dma; -+ bi->dma = dma; - bi->page = page; - bi->page_offset = 0; - -@@ -352,7 +344,7 @@ void wx_alloc_rx_buffers(struct wx_ring - DMA_FROM_DEVICE); - - rx_desc->read.pkt_addr = -- cpu_to_le64(bi->page_dma + bi->page_offset); -+ cpu_to_le64(bi->dma + bi->page_offset); - - rx_desc++; - bi++; -@@ -365,6 +357,8 @@ void wx_alloc_rx_buffers(struct wx_ring - - /* clear the status bits for the next_to_use descriptor */ - rx_desc->wb.upper.status_error = 0; -+ /* clear the length for the next_to_use descriptor */ -+ rx_desc->wb.upper.length = 0; - - cleaned_count--; - } while (cleaned_count); -@@ -1705,6 +1699,7 @@ static void wx_set_rss_queues(struct wx - - clear_bit(WX_FLAG_FDIR_HASH, wx->flags); - -+ wx->ring_feature[RING_F_FDIR].indices = 1; - /* Use Flow Director in addition to RSS to ensure the best - * distribution of flows across cores, even when an FDIR flow - * isn't matched. -@@ -1746,7 +1741,7 @@ static void wx_set_num_queues(struct wx - */ - static int wx_acquire_msix_vectors(struct wx *wx) - { -- struct irq_affinity affd = { .pre_vectors = 1 }; -+ struct irq_affinity affd = { .post_vectors = 1 }; - int nvecs, i; - - /* We start by asking for one vector per queue pair */ -@@ -1783,16 +1778,24 @@ static int wx_acquire_msix_vectors(struc - return nvecs; - } - -- wx->msix_entry->entry = 0; -- wx->msix_entry->vector = pci_irq_vector(wx->pdev, 0); - nvecs -= 1; - for (i = 0; i < nvecs; i++) { - wx->msix_q_entries[i].entry = i; -- wx->msix_q_entries[i].vector = pci_irq_vector(wx->pdev, i + 1); -+ wx->msix_q_entries[i].vector = pci_irq_vector(wx->pdev, i); - } - - wx->num_q_vectors = nvecs; - -+ wx->msix_entry->entry = nvecs; -+ wx->msix_entry->vector = pci_irq_vector(wx->pdev, nvecs); -+ -+ if (test_bit(WX_FLAG_IRQ_VECTOR_SHARED, wx->flags)) { -+ wx->msix_entry->entry = 0; -+ wx->msix_entry->vector = pci_irq_vector(wx->pdev, 0); -+ wx->msix_q_entries[0].entry = 0; -+ wx->msix_q_entries[0].vector = pci_irq_vector(wx->pdev, 1); -+ } -+ - return 0; - } - -@@ -2291,6 +2294,8 @@ static void wx_set_ivar(struct wx *wx, s - - if (direction == -1) { - /* other causes */ -+ if (test_bit(WX_FLAG_IRQ_VECTOR_SHARED, wx->flags)) -+ msix_vector = 0; - msix_vector |= WX_PX_IVAR_ALLOC_VAL; - index = 0; - ivar = rd32(wx, WX_PX_MISC_IVAR); -@@ -2299,8 +2304,6 @@ static void wx_set_ivar(struct wx *wx, s - wr32(wx, WX_PX_MISC_IVAR, ivar); - } else { - /* tx or rx causes */ -- if (!(wx->mac.type == wx_mac_em && wx->num_vfs == 7)) -- msix_vector += 1; /* offset for queue vectors */ - msix_vector |= WX_PX_IVAR_ALLOC_VAL; - index = ((16 * (queue & 1)) + (8 * direction)); - ivar = rd32(wx, WX_PX_IVAR(queue >> 1)); -@@ -2339,7 +2342,7 @@ void wx_write_eitr(struct wx_q_vector *q - - itr_reg |= WX_PX_ITR_CNT_WDIS; - -- wr32(wx, WX_PX_ITR(v_idx + 1), itr_reg); -+ wr32(wx, WX_PX_ITR(v_idx), itr_reg); - } - - /** -@@ -2392,9 +2395,9 @@ void wx_configure_vectors(struct wx *wx) - wx_write_eitr(q_vector); - } - -- wx_set_ivar(wx, -1, 0, 0); -+ wx_set_ivar(wx, -1, 0, v_idx); - if (pdev->msix_enabled) -- wr32(wx, WX_PX_ITR(0), 1950); -+ wr32(wx, WX_PX_ITR(v_idx), 1950); - } - EXPORT_SYMBOL(wx_configure_vectors); - -@@ -2414,9 +2417,6 @@ static void wx_clean_rx_ring(struct wx_r - if (rx_buffer->skb) { - struct sk_buff *skb = rx_buffer->skb; - -- if (WX_CB(skb)->page_released) -- page_pool_put_full_page(rx_ring->page_pool, rx_buffer->page, false); -- - dev_kfree_skb(skb); - } - -@@ -2440,6 +2440,9 @@ static void wx_clean_rx_ring(struct wx_r - } - } - -+ /* Zero out the descriptor ring */ -+ memset(rx_ring->desc, 0, rx_ring->size); -+ - rx_ring->next_to_alloc = 0; - rx_ring->next_to_clean = 0; - rx_ring->next_to_use = 0; -@@ -2623,7 +2626,7 @@ static int wx_alloc_page_pool(struct wx_ - struct page_pool_params pp_params = { - .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV, - .order = 0, -- .pool_size = rx_ring->size, -+ .pool_size = rx_ring->count, - .nid = dev_to_node(rx_ring->dev), - .dev = rx_ring->dev, - .dma_dir = DMA_FROM_DEVICE, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/wangxun/libwx/wx_sriov.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/wangxun/libwx/wx_sriov.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/wangxun/libwx/wx_sriov.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/wangxun/libwx/wx_sriov.c 2025-10-22 13:53:56.587168794 -0400 -@@ -64,6 +64,7 @@ static void wx_sriov_clear_data(struct w - wr32m(wx, WX_PSR_VM_CTL, WX_PSR_VM_CTL_POOL_MASK, 0); - wx->ring_feature[RING_F_VMDQ].offset = 0; - -+ clear_bit(WX_FLAG_IRQ_VECTOR_SHARED, wx->flags); - clear_bit(WX_FLAG_SRIOV_ENABLED, wx->flags); - /* Disable VMDq flag so device will be set in NM mode */ - if (wx->ring_feature[RING_F_VMDQ].limit == 1) -@@ -78,6 +79,9 @@ static int __wx_enable_sriov(struct wx * - set_bit(WX_FLAG_SRIOV_ENABLED, wx->flags); - dev_info(&wx->pdev->dev, "SR-IOV enabled with %d VFs\n", num_vfs); - -+ if (num_vfs == 7 && wx->mac.type == wx_mac_em) -+ set_bit(WX_FLAG_IRQ_VECTOR_SHARED, wx->flags); -+ - /* Enable VMDq flag so device will be set in VM mode */ - set_bit(WX_FLAG_VMDQ_ENABLED, wx->flags); - if (!wx->ring_feature[RING_F_VMDQ].limit) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/wangxun/libwx/wx_type.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/wangxun/libwx/wx_type.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/wangxun/libwx/wx_type.h 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/wangxun/libwx/wx_type.h 2025-10-22 13:53:56.587168794 -0400 -@@ -909,7 +909,6 @@ enum wx_reset_type { - struct wx_cb { - dma_addr_t dma; - u16 append_cnt; /* number of skb's appended */ -- bool page_released; - bool dma_released; - }; - -@@ -998,7 +997,6 @@ struct wx_tx_buffer { - struct wx_rx_buffer { - struct sk_buff *skb; - dma_addr_t dma; -- dma_addr_t page_dma; - struct page *page; - unsigned int page_offset; - }; -@@ -1191,6 +1189,7 @@ enum wx_pf_flags { - WX_FLAG_VMDQ_ENABLED, - WX_FLAG_VLAN_PROMISC, - WX_FLAG_SRIOV_ENABLED, -+ WX_FLAG_IRQ_VECTOR_SHARED, - WX_FLAG_FDIR_CAPABLE, - WX_FLAG_FDIR_HASH, - WX_FLAG_FDIR_PERFECT, -@@ -1343,7 +1342,7 @@ struct wx { - }; - - #define WX_INTR_ALL (~0ULL) --#define WX_INTR_Q(i) BIT((i) + 1) -+#define WX_INTR_Q(i) BIT((i)) - - /* register operations */ - #define wr32(a, reg, value) writel((value), ((a)->hw_addr + (reg))) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c 2025-10-22 13:53:56.587168794 -0400 -@@ -161,7 +161,7 @@ static void ngbe_irq_enable(struct wx *w - if (queues) - wx_intr_enable(wx, NGBE_INTR_ALL); - else -- wx_intr_enable(wx, NGBE_INTR_MISC); -+ wx_intr_enable(wx, NGBE_INTR_MISC(wx)); - } - - /** -@@ -286,7 +286,7 @@ static int ngbe_request_msix_irqs(struct - * for queue. But when num_vfs == 7, vector[1] is assigned to vf6. - * Misc and queue should reuse interrupt vector[0]. - */ -- if (wx->num_vfs == 7) -+ if (test_bit(WX_FLAG_IRQ_VECTOR_SHARED, wx->flags)) - err = request_irq(wx->msix_entry->vector, - ngbe_misc_and_queue, 0, netdev->name, wx); - else -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h 2025-10-22 13:53:56.587168794 -0400 -@@ -87,7 +87,7 @@ - #define NGBE_PX_MISC_IC_TIMESYNC BIT(11) /* time sync */ - - #define NGBE_INTR_ALL 0x1FF --#define NGBE_INTR_MISC BIT(0) -+#define NGBE_INTR_MISC(A) BIT((A)->msix_entry->entry) - - #define NGBE_PHY_CONFIG(reg_offset) (0x14000 + ((reg_offset) * 4)) - #define NGBE_CFG_LAN_SPEED 0x14440 -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c 2025-10-22 13:53:56.587168794 -0400 -@@ -294,6 +294,7 @@ static void txgbe_mac_link_up_aml(struct - wx_fc_enable(wx, tx_pause, rx_pause); - - txgbe_reconfig_mac(wx); -+ txgbe_enable_sec_tx_path(wx); - - txcfg = rd32(wx, TXGBE_AML_MAC_TX_CFG); - txcfg &= ~TXGBE_AML_MAC_TX_CFG_SPEED_MASK; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c 2025-10-22 13:53:56.587168794 -0400 -@@ -31,7 +31,7 @@ void txgbe_irq_enable(struct wx *wx, boo - wr32(wx, WX_PX_MISC_IEN, misc_ien); - - /* unmask interrupt */ -- wx_intr_enable(wx, TXGBE_INTR_MISC); -+ wx_intr_enable(wx, TXGBE_INTR_MISC(wx)); - if (queues) - wx_intr_enable(wx, TXGBE_INTR_QALL(wx)); - } -@@ -78,7 +78,6 @@ free_queue_irqs: - free_irq(wx->msix_q_entries[vector].vector, - wx->q_vector[vector]); - } -- wx_reset_interrupt_capability(wx); - return err; - } - -@@ -132,7 +131,7 @@ static irqreturn_t txgbe_misc_irq_handle - txgbe->eicr = eicr; - if (eicr & TXGBE_PX_MISC_IC_VF_MBOX) { - wx_msg_task(txgbe->wx); -- wx_intr_enable(wx, TXGBE_INTR_MISC); -+ wx_intr_enable(wx, TXGBE_INTR_MISC(wx)); - } - return IRQ_WAKE_THREAD; - } -@@ -184,7 +183,7 @@ static irqreturn_t txgbe_misc_irq_thread - nhandled++; - } - -- wx_intr_enable(wx, TXGBE_INTR_MISC); -+ wx_intr_enable(wx, TXGBE_INTR_MISC(wx)); - return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE); - } - -@@ -211,6 +210,7 @@ void txgbe_free_misc_irq(struct txgbe *t - free_irq(txgbe->link_irq, txgbe); - free_irq(txgbe->misc.irq, txgbe); - txgbe_del_irq_domain(txgbe); -+ txgbe->wx->misc_irq_domain = false; - } - - int txgbe_setup_misc_irq(struct txgbe *txgbe) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c 2025-10-22 13:53:56.587168794 -0400 -@@ -458,10 +458,14 @@ static int txgbe_open(struct net_device - - wx_configure(wx); - -- err = txgbe_request_queue_irqs(wx); -+ err = txgbe_setup_misc_irq(wx->priv); - if (err) - goto err_free_resources; - -+ err = txgbe_request_queue_irqs(wx); -+ if (err) -+ goto err_free_misc_irq; -+ - /* Notify the stack of the actual queue counts. */ - err = netif_set_real_num_tx_queues(netdev, wx->num_tx_queues); - if (err) -@@ -479,6 +483,9 @@ static int txgbe_open(struct net_device - - err_free_irq: - wx_free_irq(wx); -+err_free_misc_irq: -+ txgbe_free_misc_irq(wx->priv); -+ wx_reset_interrupt_capability(wx); - err_free_resources: - wx_free_resources(wx); - err_reset: -@@ -519,6 +526,7 @@ static int txgbe_close(struct net_device - wx_ptp_stop(wx); - txgbe_down(wx); - wx_free_irq(wx); -+ txgbe_free_misc_irq(wx->priv); - wx_free_resources(wx); - txgbe_fdir_filter_exit(wx); - wx_control_hw(wx, false); -@@ -564,7 +572,6 @@ static void txgbe_shutdown(struct pci_de - int txgbe_setup_tc(struct net_device *dev, u8 tc) - { - struct wx *wx = netdev_priv(dev); -- struct txgbe *txgbe = wx->priv; - - /* Hardware has to reinitialize queues and interrupts to - * match packet buffer alignment. Unfortunately, the -@@ -575,7 +582,6 @@ int txgbe_setup_tc(struct net_device *de - else - txgbe_reset(wx); - -- txgbe_free_misc_irq(txgbe); - wx_clear_interrupt_scheme(wx); - - if (tc) -@@ -584,7 +590,6 @@ int txgbe_setup_tc(struct net_device *de - netdev_reset_tc(dev); - - wx_init_interrupt_scheme(wx); -- txgbe_setup_misc_irq(txgbe); - - if (netif_running(dev)) - txgbe_open(dev); -@@ -882,13 +887,9 @@ static int txgbe_probe(struct pci_dev *p - - txgbe_init_fdir(txgbe); - -- err = txgbe_setup_misc_irq(txgbe); -- if (err) -- goto err_release_hw; -- - err = txgbe_init_phy(txgbe); - if (err) -- goto err_free_misc_irq; -+ goto err_release_hw; - - err = register_netdev(netdev); - if (err) -@@ -916,8 +917,6 @@ static int txgbe_probe(struct pci_dev *p - - err_remove_phy: - txgbe_remove_phy(txgbe); --err_free_misc_irq: -- txgbe_free_misc_irq(txgbe); - err_release_hw: - wx_clear_interrupt_scheme(wx); - wx_control_hw(wx, false); -@@ -957,7 +956,6 @@ static void txgbe_remove(struct pci_dev - unregister_netdev(netdev); - - txgbe_remove_phy(txgbe); -- txgbe_free_misc_irq(txgbe); - wx_free_isb_resources(wx); - - pci_release_selected_regions(pdev, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h ---- BPI-Router-Linux-kernel/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h 2025-10-22 13:53:56.587168794 -0400 -@@ -302,8 +302,8 @@ struct txgbe_fdir_filter { - #define TXGBE_DEFAULT_RX_WORK 128 - #endif - --#define TXGBE_INTR_MISC BIT(0) --#define TXGBE_INTR_QALL(A) GENMASK((A)->num_q_vectors, 1) -+#define TXGBE_INTR_MISC(A) BIT((A)->num_q_vectors) -+#define TXGBE_INTR_QALL(A) (TXGBE_INTR_MISC(A) - 1) - - #define TXGBE_MAX_EITR GENMASK(11, 3) - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/xilinx/ll_temac_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/xilinx/ll_temac_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/xilinx/ll_temac_main.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/xilinx/ll_temac_main.c 2025-10-22 13:53:56.587168794 -0400 -@@ -1309,7 +1309,7 @@ ll_temac_ethtools_set_ringparam(struct n - if (ering->rx_pending > RX_BD_NUM_MAX || - ering->rx_mini_pending || - ering->rx_jumbo_pending || -- ering->rx_pending > TX_BD_NUM_MAX) -+ ering->tx_pending > TX_BD_NUM_MAX) - return -EINVAL; - - if (netif_running(ndev)) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/xilinx/xilinx_axienet_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/xilinx/xilinx_axienet_main.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/xilinx/xilinx_axienet_main.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/xilinx/xilinx_axienet_main.c 2025-10-22 13:53:56.587168794 -0400 -@@ -1160,6 +1160,7 @@ static void axienet_dma_rx_cb(void *data - struct axienet_local *lp = data; - struct sk_buff *skb; - u32 *app_metadata; -+ int i; - - skbuf_dma = axienet_get_rx_desc(lp, lp->rx_ring_tail++); - skb = skbuf_dma->skb; -@@ -1167,6 +1168,15 @@ static void axienet_dma_rx_cb(void *data - &meta_max_len); - dma_unmap_single(lp->dev, skbuf_dma->dma_address, lp->max_frm_size, - DMA_FROM_DEVICE); -+ -+ if (IS_ERR(app_metadata)) { -+ if (net_ratelimit()) -+ netdev_err(lp->ndev, "Failed to get RX metadata pointer\n"); -+ dev_kfree_skb_any(skb); -+ lp->ndev->stats.rx_dropped++; -+ goto rx_submit; -+ } -+ - /* TODO: Derive app word index programmatically */ - rx_len = (app_metadata[LEN_APP] & 0xFFFF); - skb_put(skb, rx_len); -@@ -1178,7 +1188,11 @@ static void axienet_dma_rx_cb(void *data - u64_stats_add(&lp->rx_packets, 1); - u64_stats_add(&lp->rx_bytes, rx_len); - u64_stats_update_end(&lp->rx_stat_sync); -- axienet_rx_submit_desc(lp->ndev); -+ -+rx_submit: -+ for (i = 0; i < CIRC_SPACE(lp->rx_ring_head, lp->rx_ring_tail, -+ RX_BUF_NUM_DEFAULT); i++) -+ axienet_rx_submit_desc(lp->ndev); - dma_async_issue_pending(lp->rx_chan); - } - -@@ -1457,7 +1471,6 @@ static void axienet_rx_submit_desc(struc - if (!skbuf_dma) - return; - -- lp->rx_ring_head++; - skb = netdev_alloc_skb(ndev, lp->max_frm_size); - if (!skb) - return; -@@ -1482,6 +1495,7 @@ static void axienet_rx_submit_desc(struc - skbuf_dma->desc = dma_rx_desc; - dma_rx_desc->callback_param = lp; - dma_rx_desc->callback_result = axienet_dma_rx_cb; -+ lp->rx_ring_head++; - dmaengine_submit(dma_rx_desc); - - return; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/xilinx/xilinx_emaclite.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/xilinx/xilinx_emaclite.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/xilinx/xilinx_emaclite.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/xilinx/xilinx_emaclite.c 2025-10-22 13:53:56.587168794 -0400 -@@ -286,7 +286,7 @@ static void xemaclite_aligned_read(u32 * - - /* Read the remaining data */ - for (; length > 0; length--) -- *to_u8_ptr = *from_u8_ptr; -+ *to_u8_ptr++ = *from_u8_ptr++; - } - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ethernet/xircom/xirc2ps_cs.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/xircom/xirc2ps_cs.c ---- BPI-Router-Linux-kernel/drivers/net/ethernet/xircom/xirc2ps_cs.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ethernet/xircom/xirc2ps_cs.c 2025-10-22 13:53:56.587168794 -0400 -@@ -1576,7 +1576,7 @@ do_reset(struct net_device *dev, int ful - msleep(40); /* wait 40 msec to let it complete */ - } - if (full_duplex) -- PutByte(XIRCREG1_ECR, GetByte(XIRCREG1_ECR | FullDuplex)); -+ PutByte(XIRCREG1_ECR, GetByte(XIRCREG1_ECR) | FullDuplex); - } else { /* No MII */ - SelectPage(0); - value = GetByte(XIRCREG_ESR); /* read the ESR */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/hamradio/bpqether.c BPI-Router-Linux-kernel-6.16.12/drivers/net/hamradio/bpqether.c ---- BPI-Router-Linux-kernel/drivers/net/hamradio/bpqether.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/hamradio/bpqether.c 2025-10-22 13:53:56.587168794 -0400 -@@ -138,7 +138,7 @@ static inline struct net_device *bpq_get - - static inline int dev_is_ethdev(struct net_device *dev) - { -- return dev->type == ARPHRD_ETHER && strncmp(dev->name, "dummy", 5); -+ return dev->type == ARPHRD_ETHER && !netdev_need_ops_lock(dev); - } - - /* ------------------------------------------------------------------------ */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/hyperv/hyperv_net.h BPI-Router-Linux-kernel-6.16.12/drivers/net/hyperv/hyperv_net.h ---- BPI-Router-Linux-kernel/drivers/net/hyperv/hyperv_net.h 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/hyperv/hyperv_net.h 2025-10-22 13:53:56.587168794 -0400 -@@ -1061,6 +1061,7 @@ struct net_device_context { - struct net_device __rcu *vf_netdev; - struct netvsc_vf_pcpu_stats __percpu *vf_stats; - struct delayed_work vf_takeover; -+ struct delayed_work vfns_work; - - /* 1: allocated, serial number is valid. 0: not allocated */ - u32 vf_alloc; -@@ -1075,6 +1076,8 @@ struct net_device_context { - struct netvsc_device_info *saved_netvsc_dev_info; - }; - -+void netvsc_vfns_work(struct work_struct *w); -+ - /* Azure hosts don't support non-TCP port numbers in hashing for fragmented - * packets. We can use ethtool to change UDP hash level when necessary. - */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/hyperv/netvsc.c BPI-Router-Linux-kernel-6.16.12/drivers/net/hyperv/netvsc.c ---- BPI-Router-Linux-kernel/drivers/net/hyperv/netvsc.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/hyperv/netvsc.c 2025-10-22 13:53:56.587168794 -0400 -@@ -1812,6 +1812,11 @@ struct netvsc_device *netvsc_device_add( - - /* Enable NAPI handler before init callbacks */ - netif_napi_add(ndev, &net_device->chan_table[0].napi, netvsc_poll); -+ napi_enable(&net_device->chan_table[0].napi); -+ netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_RX, -+ &net_device->chan_table[0].napi); -+ netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_TX, -+ &net_device->chan_table[0].napi); - - /* Open the channel */ - device->channel->next_request_id_callback = vmbus_next_request_id; -@@ -1831,12 +1836,6 @@ struct netvsc_device *netvsc_device_add( - /* Channel is opened */ - netdev_dbg(ndev, "hv_netvsc channel opened successfully\n"); - -- napi_enable(&net_device->chan_table[0].napi); -- netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_RX, -- &net_device->chan_table[0].napi); -- netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_TX, -- &net_device->chan_table[0].napi); -- - /* Connect with the NetVsp */ - ret = netvsc_connect_vsp(device, net_device, device_info); - if (ret != 0) { -@@ -1854,14 +1853,14 @@ struct netvsc_device *netvsc_device_add( - - close: - RCU_INIT_POINTER(net_device_ctx->nvdev, NULL); -- netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_TX, NULL); -- netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_RX, NULL); -- napi_disable(&net_device->chan_table[0].napi); - - /* Now, we can close the channel safely */ - vmbus_close(device->channel); - - cleanup: -+ netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_TX, NULL); -+ netif_queue_set_napi(ndev, 0, NETDEV_QUEUE_TYPE_RX, NULL); -+ napi_disable(&net_device->chan_table[0].napi); - netif_napi_del(&net_device->chan_table[0].napi); - - cleanup2: -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/hyperv/netvsc_drv.c BPI-Router-Linux-kernel-6.16.12/drivers/net/hyperv/netvsc_drv.c ---- BPI-Router-Linux-kernel/drivers/net/hyperv/netvsc_drv.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/hyperv/netvsc_drv.c 2025-10-22 13:53:56.587168794 -0400 -@@ -2317,8 +2317,11 @@ static int netvsc_prepare_bonding(struct - if (!ndev) - return NOTIFY_DONE; - -- /* set slave flag before open to prevent IPv6 addrconf */ -+ /* Set slave flag and no addrconf flag before open -+ * to prevent IPv6 addrconf. -+ */ - vf_netdev->flags |= IFF_SLAVE; -+ vf_netdev->priv_flags |= IFF_NO_ADDRCONF; - return NOTIFY_DONE; - } - -@@ -2527,6 +2530,7 @@ static int netvsc_probe(struct hv_device - spin_lock_init(&net_device_ctx->lock); - INIT_LIST_HEAD(&net_device_ctx->reconfig_events); - INIT_DELAYED_WORK(&net_device_ctx->vf_takeover, netvsc_vf_setup); -+ INIT_DELAYED_WORK(&net_device_ctx->vfns_work, netvsc_vfns_work); - - net_device_ctx->vf_stats - = netdev_alloc_pcpu_stats(struct netvsc_vf_pcpu_stats); -@@ -2671,6 +2675,8 @@ static void netvsc_remove(struct hv_devi - cancel_delayed_work_sync(&ndev_ctx->dwork); - - rtnl_lock(); -+ cancel_delayed_work_sync(&ndev_ctx->vfns_work); -+ - nvdev = rtnl_dereference(ndev_ctx->nvdev); - if (nvdev) { - cancel_work_sync(&nvdev->subchan_work); -@@ -2712,6 +2718,7 @@ static int netvsc_suspend(struct hv_devi - cancel_delayed_work_sync(&ndev_ctx->dwork); - - rtnl_lock(); -+ cancel_delayed_work_sync(&ndev_ctx->vfns_work); - - nvdev = rtnl_dereference(ndev_ctx->nvdev); - if (nvdev == NULL) { -@@ -2805,6 +2812,27 @@ static void netvsc_event_set_vf_ns(struc - } - } - -+void netvsc_vfns_work(struct work_struct *w) -+{ -+ struct net_device_context *ndev_ctx = -+ container_of(w, struct net_device_context, vfns_work.work); -+ struct net_device *ndev; -+ -+ if (!rtnl_trylock()) { -+ schedule_delayed_work(&ndev_ctx->vfns_work, 1); -+ return; -+ } -+ -+ ndev = hv_get_drvdata(ndev_ctx->device_ctx); -+ if (!ndev) -+ goto out; -+ -+ netvsc_event_set_vf_ns(ndev); -+ -+out: -+ rtnl_unlock(); -+} -+ - /* - * On Hyper-V, every VF interface is matched with a corresponding - * synthetic interface. The synthetic interface is presented first -@@ -2815,10 +2843,12 @@ static int netvsc_netdev_event(struct no - unsigned long event, void *ptr) - { - struct net_device *event_dev = netdev_notifier_info_to_dev(ptr); -+ struct net_device_context *ndev_ctx; - int ret = 0; - - if (event_dev->netdev_ops == &device_ops && event == NETDEV_REGISTER) { -- netvsc_event_set_vf_ns(event_dev); -+ ndev_ctx = netdev_priv(event_dev); -+ schedule_delayed_work(&ndev_ctx->vfns_work, 0); - return NOTIFY_DONE; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/hyperv/rndis_filter.c BPI-Router-Linux-kernel-6.16.12/drivers/net/hyperv/rndis_filter.c ---- BPI-Router-Linux-kernel/drivers/net/hyperv/rndis_filter.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/hyperv/rndis_filter.c 2025-10-22 13:53:56.587168794 -0400 -@@ -1252,17 +1252,26 @@ static void netvsc_sc_open(struct vmbus_ - new_sc->rqstor_size = netvsc_rqstor_size(netvsc_ring_bytes); - new_sc->max_pkt_size = NETVSC_MAX_PKT_SIZE; - -+ /* Enable napi before opening the vmbus channel to avoid races -+ * as the host placing data on the host->guest ring may be left -+ * out if napi was not enabled. -+ */ -+ napi_enable(&nvchan->napi); -+ netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_RX, -+ &nvchan->napi); -+ netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_TX, -+ &nvchan->napi); -+ - ret = vmbus_open(new_sc, netvsc_ring_bytes, - netvsc_ring_bytes, NULL, 0, - netvsc_channel_cb, nvchan); -- if (ret == 0) { -- napi_enable(&nvchan->napi); -- netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_RX, -- &nvchan->napi); -- netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_TX, -- &nvchan->napi); -- } else { -+ if (ret != 0) { - netdev_notice(ndev, "sub channel open failed: %d\n", ret); -+ netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_TX, -+ NULL); -+ netif_queue_set_napi(ndev, chn_index, NETDEV_QUEUE_TYPE_RX, -+ NULL); -+ napi_disable(&nvchan->napi); - } - - if (atomic_inc_return(&nvscdev->open_chn) == nvscdev->num_chn) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ipa/ipa_sysfs.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ipa/ipa_sysfs.c ---- BPI-Router-Linux-kernel/drivers/net/ipa/ipa_sysfs.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ipa/ipa_sysfs.c 2025-10-22 13:53:56.587168794 -0400 -@@ -37,8 +37,12 @@ static const char *ipa_version_string(st - return "4.11"; - case IPA_VERSION_5_0: - return "5.0"; -+ case IPA_VERSION_5_1: -+ return "5.1"; -+ case IPA_VERSION_5_5: -+ return "5.5"; - default: -- return "0.0"; /* Won't happen (checked at probe time) */ -+ return "0.0"; /* Should not happen */ - } - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ipa/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/net/ipa/Kconfig ---- BPI-Router-Linux-kernel/drivers/net/ipa/Kconfig 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ipa/Kconfig 2025-10-22 13:53:56.587168794 -0400 -@@ -5,7 +5,7 @@ config QCOM_IPA - depends on INTERCONNECT - depends on QCOM_RPROC_COMMON || (QCOM_RPROC_COMMON=n && COMPILE_TEST) - depends on QCOM_AOSS_QMP || QCOM_AOSS_QMP=n -- select QCOM_MDT_LOADER if ARCH_QCOM -+ select QCOM_MDT_LOADER - select QCOM_SCM - select QCOM_QMI_HELPERS - help -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/macsec.c BPI-Router-Linux-kernel-6.16.12/drivers/net/macsec.c ---- BPI-Router-Linux-kernel/drivers/net/macsec.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/macsec.c 2025-10-22 13:53:56.587168794 -0400 -@@ -247,15 +247,39 @@ static sci_t make_sci(const u8 *addr, __ - return sci; - } - --static sci_t macsec_frame_sci(struct macsec_eth_header *hdr, bool sci_present) -+static sci_t macsec_active_sci(struct macsec_secy *secy) - { -- sci_t sci; -+ struct macsec_rx_sc *rx_sc = rcu_dereference_bh(secy->rx_sc); -+ -+ /* Case single RX SC */ -+ if (rx_sc && !rcu_dereference_bh(rx_sc->next)) -+ return (rx_sc->active) ? rx_sc->sci : 0; -+ /* Case no RX SC or multiple */ -+ else -+ return 0; -+} -+ -+static sci_t macsec_frame_sci(struct macsec_eth_header *hdr, bool sci_present, -+ struct macsec_rxh_data *rxd) -+{ -+ struct macsec_dev *macsec; -+ sci_t sci = 0; - -- if (sci_present) -+ /* SC = 1 */ -+ if (sci_present) { - memcpy(&sci, hdr->secure_channel_id, - sizeof(hdr->secure_channel_id)); -- else -+ /* SC = 0; ES = 0 */ -+ } else if ((!(hdr->tci_an & (MACSEC_TCI_ES | MACSEC_TCI_SC))) && -+ (list_is_singular(&rxd->secys))) { -+ /* Only one SECY should exist on this scenario */ -+ macsec = list_first_or_null_rcu(&rxd->secys, struct macsec_dev, -+ secys); -+ if (macsec) -+ return macsec_active_sci(&macsec->secy); -+ } else { - sci = make_sci(hdr->eth.h_source, MACSEC_PORT_ES); -+ } - - return sci; - } -@@ -1109,7 +1133,7 @@ static rx_handler_result_t macsec_handle - struct macsec_rxh_data *rxd; - struct macsec_dev *macsec; - unsigned int len; -- sci_t sci; -+ sci_t sci = 0; - u32 hdr_pn; - bool cbit; - struct pcpu_rx_sc_stats *rxsc_stats; -@@ -1156,11 +1180,14 @@ static rx_handler_result_t macsec_handle - - macsec_skb_cb(skb)->has_sci = !!(hdr->tci_an & MACSEC_TCI_SC); - macsec_skb_cb(skb)->assoc_num = hdr->tci_an & MACSEC_AN_MASK; -- sci = macsec_frame_sci(hdr, macsec_skb_cb(skb)->has_sci); - - rcu_read_lock(); - rxd = macsec_data_rcu(skb->dev); - -+ sci = macsec_frame_sci(hdr, macsec_skb_cb(skb)->has_sci, rxd); -+ if (!sci) -+ goto drop_nosc; -+ - list_for_each_entry_rcu(macsec, &rxd->secys, secys) { - struct macsec_rx_sc *sc = find_rx_sc(&macsec->secy, sci); - -@@ -1283,6 +1310,7 @@ drop: - macsec_rxsa_put(rx_sa); - drop_nosa: - macsec_rxsc_put(rx_sc); -+drop_nosc: - rcu_read_unlock(); - drop_direct: - kfree_skb(skb); -@@ -1816,7 +1844,7 @@ static int macsec_add_rxsa(struct sk_buf - - if (tb_sa[MACSEC_SA_ATTR_PN]) { - spin_lock_bh(&rx_sa->lock); -- rx_sa->next_pn = nla_get_u64(tb_sa[MACSEC_SA_ATTR_PN]); -+ rx_sa->next_pn = nla_get_uint(tb_sa[MACSEC_SA_ATTR_PN]); - spin_unlock_bh(&rx_sa->lock); - } - -@@ -2058,7 +2086,7 @@ static int macsec_add_txsa(struct sk_buf - } - - spin_lock_bh(&tx_sa->lock); -- tx_sa->next_pn = nla_get_u64(tb_sa[MACSEC_SA_ATTR_PN]); -+ tx_sa->next_pn = nla_get_uint(tb_sa[MACSEC_SA_ATTR_PN]); - spin_unlock_bh(&tx_sa->lock); - - if (tb_sa[MACSEC_SA_ATTR_ACTIVE]) -@@ -2370,7 +2398,7 @@ static int macsec_upd_txsa(struct sk_buf - - spin_lock_bh(&tx_sa->lock); - prev_pn = tx_sa->next_pn_halves; -- tx_sa->next_pn = nla_get_u64(tb_sa[MACSEC_SA_ATTR_PN]); -+ tx_sa->next_pn = nla_get_uint(tb_sa[MACSEC_SA_ATTR_PN]); - spin_unlock_bh(&tx_sa->lock); - } - -@@ -2468,7 +2496,7 @@ static int macsec_upd_rxsa(struct sk_buf - - spin_lock_bh(&rx_sa->lock); - prev_pn = rx_sa->next_pn_halves; -- rx_sa->next_pn = nla_get_u64(tb_sa[MACSEC_SA_ATTR_PN]); -+ rx_sa->next_pn = nla_get_uint(tb_sa[MACSEC_SA_ATTR_PN]); - spin_unlock_bh(&rx_sa->lock); - } - -@@ -3840,7 +3868,7 @@ static void macsec_setup(struct net_devi - ether_setup(dev); - dev->min_mtu = 0; - dev->max_mtu = ETH_MAX_MTU; -- dev->priv_flags |= IFF_NO_QUEUE; -+ dev->priv_flags |= IFF_NO_QUEUE | IFF_UNICAST_FLT; - dev->netdev_ops = &macsec_netdev_ops; - dev->needs_free_netdev = true; - dev->priv_destructor = macsec_free_netdev; -@@ -4258,6 +4286,7 @@ static int macsec_newlink(struct net_dev - if (err < 0) - goto del_dev; - -+ netdev_update_features(dev); - netif_stacked_transfer_operstate(real_dev, dev); - linkwatch_fire_event(dev); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/mctp/mctp-usb.c BPI-Router-Linux-kernel-6.16.12/drivers/net/mctp/mctp-usb.c ---- BPI-Router-Linux-kernel/drivers/net/mctp/mctp-usb.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/mctp/mctp-usb.c 2025-10-22 13:53:56.587168794 -0400 -@@ -183,6 +183,7 @@ static void mctp_usb_in_complete(struct - struct mctp_usb_hdr *hdr; - u8 pkt_len; /* length of MCTP packet, no USB header */ - -+ skb_reset_mac_header(skb); - hdr = skb_pull_data(skb, sizeof(*hdr)); - if (!hdr) - break; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/mdio/mdio-bcm-unimac.c BPI-Router-Linux-kernel-6.16.12/drivers/net/mdio/mdio-bcm-unimac.c ---- BPI-Router-Linux-kernel/drivers/net/mdio/mdio-bcm-unimac.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/mdio/mdio-bcm-unimac.c 2025-10-22 13:53:56.587168794 -0400 -@@ -209,10 +209,9 @@ static int unimac_mdio_clk_set(struct un - if (ret) - return ret; - -- if (!priv->clk) -+ rate = clk_get_rate(priv->clk); -+ if (!rate) - rate = 250000000; -- else -- rate = clk_get_rate(priv->clk); - - div = (rate / (2 * priv->clk_freq)) - 1; - if (div & ~MDIO_CLK_DIV_MASK) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/netconsole.c BPI-Router-Linux-kernel-6.16.12/drivers/net/netconsole.c ---- BPI-Router-Linux-kernel/drivers/net/netconsole.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/netconsole.c 2025-10-22 13:53:56.587168794 -0400 -@@ -86,10 +86,10 @@ static DEFINE_SPINLOCK(target_list_lock) - static DEFINE_MUTEX(target_cleanup_list_lock); - - /* -- * Console driver for extended netconsoles. Registered on the first use to -- * avoid unnecessarily enabling ext message formatting. -+ * Console driver for netconsoles. Register only consoles that have -+ * an associated target of the same type. - */ --static struct console netconsole_ext; -+static struct console netconsole_ext, netconsole; - - struct netconsole_target_stats { - u64_stats_t xmit_drop_count; -@@ -97,6 +97,11 @@ struct netconsole_target_stats { - struct u64_stats_sync syncp; - }; - -+enum console_type { -+ CONS_BASIC = BIT(0), -+ CONS_EXTENDED = BIT(1), -+}; -+ - /* Features enabled in sysdata. Contrary to userdata, this data is populated by - * the kernel. The fields are designed as bitwise flags, allowing multiple - * features to be set in sysdata_fields. -@@ -491,6 +496,12 @@ static ssize_t enabled_store(struct conf - if (nt->extended && !console_is_registered(&netconsole_ext)) - register_console(&netconsole_ext); - -+ /* User might be enabling the basic format target for the very -+ * first time, make sure the console is registered. -+ */ -+ if (!nt->extended && !console_is_registered(&netconsole)) -+ register_console(&netconsole); -+ - /* - * Skip netpoll_parse_options() -- all the attributes are - * already configured via configfs. Just print them out. -@@ -1252,7 +1263,6 @@ static int sysdata_append_release(struct - */ - static int prepare_extradata(struct netconsole_target *nt) - { -- u32 fields = SYSDATA_CPU_NR | SYSDATA_TASKNAME; - int extradata_len; - - /* userdata was appended when configfs write helper was called -@@ -1260,7 +1270,7 @@ static int prepare_extradata(struct netc - */ - extradata_len = nt->userdata_length; - -- if (!(nt->sysdata_fields & fields)) -+ if (!nt->sysdata_fields) - goto out; - - if (nt->sysdata_fields & SYSDATA_CPU_NR) -@@ -1691,8 +1701,8 @@ static int __init init_netconsole(void) - { - int err; - struct netconsole_target *nt, *tmp; -+ u32 console_type_needed = 0; - unsigned int count = 0; -- bool extended = false; - unsigned long flags; - char *target_config; - char *input = config; -@@ -1708,9 +1718,10 @@ static int __init init_netconsole(void) - } - /* Dump existing printks when we register */ - if (nt->extended) { -- extended = true; -+ console_type_needed |= CONS_EXTENDED; - netconsole_ext.flags |= CON_PRINTBUFFER; - } else { -+ console_type_needed |= CONS_BASIC; - netconsole.flags |= CON_PRINTBUFFER; - } - -@@ -1729,9 +1740,10 @@ static int __init init_netconsole(void) - if (err) - goto undonotifier; - -- if (extended) -+ if (console_type_needed & CONS_EXTENDED) - register_console(&netconsole_ext); -- register_console(&netconsole); -+ if (console_type_needed & CONS_BASIC) -+ register_console(&netconsole); - pr_info("network logging started\n"); - - return err; -@@ -1761,7 +1773,8 @@ static void __exit cleanup_netconsole(vo - - if (console_is_registered(&netconsole_ext)) - unregister_console(&netconsole_ext); -- unregister_console(&netconsole); -+ if (console_is_registered(&netconsole)) -+ unregister_console(&netconsole); - dynamic_netconsole_exit(); - unregister_netdevice_notifier(&netconsole_netdev_notifier); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/netdevsim/netdev.c BPI-Router-Linux-kernel-6.16.12/drivers/net/netdevsim/netdev.c ---- BPI-Router-Linux-kernel/drivers/net/netdevsim/netdev.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/netdevsim/netdev.c 2025-10-22 13:53:56.587168794 -0400 -@@ -371,7 +371,8 @@ static int nsim_poll(struct napi_struct - int done; - - done = nsim_rcv(rq, budget); -- napi_complete(napi); -+ if (done < budget) -+ napi_complete_done(napi, done); - - return done; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ovpn/io.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ovpn/io.c ---- BPI-Router-Linux-kernel/drivers/net/ovpn/io.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ovpn/io.c 2025-10-22 13:53:56.587168794 -0400 -@@ -62,6 +62,13 @@ static void ovpn_netdev_write(struct ovp - unsigned int pkt_len; - int ret; - -+ /* -+ * GSO state from the transport layer is not valid for the tunnel/data -+ * path. Reset all GSO fields to prevent any further GSO processing -+ * from entering an inconsistent state. -+ */ -+ skb_gso_reset(skb); -+ - /* we can't guarantee the packet wasn't corrupted before entering the - * VPN, therefore we give other layers a chance to check that - */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ovpn/netlink.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ovpn/netlink.c ---- BPI-Router-Linux-kernel/drivers/net/ovpn/netlink.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ovpn/netlink.c 2025-10-22 13:53:56.591168775 -0400 -@@ -352,7 +352,7 @@ int ovpn_nl_peer_new_doit(struct sk_buff - return -EINVAL; - - ret = nla_parse_nested(attrs, OVPN_A_PEER_MAX, info->attrs[OVPN_A_PEER], -- ovpn_peer_nl_policy, info->extack); -+ ovpn_peer_new_input_nl_policy, info->extack); - if (ret) - return ret; - -@@ -476,7 +476,7 @@ int ovpn_nl_peer_set_doit(struct sk_buff - return -EINVAL; - - ret = nla_parse_nested(attrs, OVPN_A_PEER_MAX, info->attrs[OVPN_A_PEER], -- ovpn_peer_nl_policy, info->extack); -+ ovpn_peer_set_input_nl_policy, info->extack); - if (ret) - return ret; - -@@ -654,7 +654,7 @@ int ovpn_nl_peer_get_doit(struct sk_buff - struct ovpn_peer *peer; - struct sk_buff *msg; - u32 peer_id; -- int ret; -+ int ret, i; - - if (GENL_REQ_ATTR_CHECK(info, OVPN_A_PEER)) - return -EINVAL; -@@ -668,6 +668,23 @@ int ovpn_nl_peer_get_doit(struct sk_buff - OVPN_A_PEER_ID)) - return -EINVAL; - -+ /* OVPN_CMD_PEER_GET expects only the PEER_ID, therefore -+ * ensure that the user hasn't specified any other attribute. -+ * -+ * Unfortunately this check cannot be performed via netlink -+ * spec/policy and must be open-coded. -+ */ -+ for (i = 0; i < OVPN_A_PEER_MAX + 1; i++) { -+ if (i == OVPN_A_PEER_ID) -+ continue; -+ -+ if (attrs[i]) { -+ NL_SET_ERR_MSG_FMT_MOD(info->extack, -+ "unexpected attribute %u", i); -+ return -EINVAL; -+ } -+ } -+ - peer_id = nla_get_u32(attrs[OVPN_A_PEER_ID]); - peer = ovpn_peer_get_by_id(ovpn, peer_id); - if (!peer) { -@@ -768,7 +785,7 @@ int ovpn_nl_peer_del_doit(struct sk_buff - return -EINVAL; - - ret = nla_parse_nested(attrs, OVPN_A_PEER_MAX, info->attrs[OVPN_A_PEER], -- ovpn_peer_nl_policy, info->extack); -+ ovpn_peer_del_input_nl_policy, info->extack); - if (ret) - return ret; - -@@ -969,14 +986,14 @@ int ovpn_nl_key_get_doit(struct sk_buff - struct ovpn_peer *peer; - struct sk_buff *msg; - u32 peer_id; -- int ret; -+ int ret, i; - - if (GENL_REQ_ATTR_CHECK(info, OVPN_A_KEYCONF)) - return -EINVAL; - - ret = nla_parse_nested(attrs, OVPN_A_KEYCONF_MAX, - info->attrs[OVPN_A_KEYCONF], -- ovpn_keyconf_nl_policy, info->extack); -+ ovpn_keyconf_get_nl_policy, info->extack); - if (ret) - return ret; - -@@ -988,6 +1005,24 @@ int ovpn_nl_key_get_doit(struct sk_buff - OVPN_A_KEYCONF_SLOT)) - return -EINVAL; - -+ /* OVPN_CMD_KEY_GET expects only the PEER_ID and the SLOT, therefore -+ * ensure that the user hasn't specified any other attribute. -+ * -+ * Unfortunately this check cannot be performed via netlink -+ * spec/policy and must be open-coded. -+ */ -+ for (i = 0; i < OVPN_A_KEYCONF_MAX + 1; i++) { -+ if (i == OVPN_A_KEYCONF_PEER_ID || -+ i == OVPN_A_KEYCONF_SLOT) -+ continue; -+ -+ if (attrs[i]) { -+ NL_SET_ERR_MSG_FMT_MOD(info->extack, -+ "unexpected attribute %u", i); -+ return -EINVAL; -+ } -+ } -+ - peer_id = nla_get_u32(attrs[OVPN_A_KEYCONF_PEER_ID]); - peer = ovpn_peer_get_by_id(ovpn, peer_id); - if (!peer) { -@@ -1037,7 +1072,7 @@ int ovpn_nl_key_swap_doit(struct sk_buff - - ret = nla_parse_nested(attrs, OVPN_A_KEYCONF_MAX, - info->attrs[OVPN_A_KEYCONF], -- ovpn_keyconf_nl_policy, info->extack); -+ ovpn_keyconf_swap_input_nl_policy, info->extack); - if (ret) - return ret; - -@@ -1074,7 +1109,7 @@ int ovpn_nl_key_del_doit(struct sk_buff - - ret = nla_parse_nested(attrs, OVPN_A_KEYCONF_MAX, - info->attrs[OVPN_A_KEYCONF], -- ovpn_keyconf_nl_policy, info->extack); -+ ovpn_keyconf_del_input_nl_policy, info->extack); - if (ret) - return ret; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ovpn/netlink-gen.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ovpn/netlink-gen.c ---- BPI-Router-Linux-kernel/drivers/net/ovpn/netlink-gen.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ovpn/netlink-gen.c 2025-10-22 13:53:56.587168794 -0400 -@@ -29,6 +29,22 @@ const struct nla_policy ovpn_keyconf_nl_ - [OVPN_A_KEYCONF_DECRYPT_DIR] = NLA_POLICY_NESTED(ovpn_keydir_nl_policy), - }; - -+const struct nla_policy ovpn_keyconf_del_input_nl_policy[OVPN_A_KEYCONF_SLOT + 1] = { -+ [OVPN_A_KEYCONF_PEER_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_keyconf_peer_id_range), -+ [OVPN_A_KEYCONF_SLOT] = NLA_POLICY_MAX(NLA_U32, 1), -+}; -+ -+const struct nla_policy ovpn_keyconf_get_nl_policy[OVPN_A_KEYCONF_CIPHER_ALG + 1] = { -+ [OVPN_A_KEYCONF_PEER_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_keyconf_peer_id_range), -+ [OVPN_A_KEYCONF_SLOT] = NLA_POLICY_MAX(NLA_U32, 1), -+ [OVPN_A_KEYCONF_KEY_ID] = NLA_POLICY_MAX(NLA_U32, 7), -+ [OVPN_A_KEYCONF_CIPHER_ALG] = NLA_POLICY_MAX(NLA_U32, 2), -+}; -+ -+const struct nla_policy ovpn_keyconf_swap_input_nl_policy[OVPN_A_KEYCONF_PEER_ID + 1] = { -+ [OVPN_A_KEYCONF_PEER_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_keyconf_peer_id_range), -+}; -+ - const struct nla_policy ovpn_keydir_nl_policy[OVPN_A_KEYDIR_NONCE_TAIL + 1] = { - [OVPN_A_KEYDIR_CIPHER_KEY] = NLA_POLICY_MAX_LEN(256), - [OVPN_A_KEYDIR_NONCE_TAIL] = NLA_POLICY_EXACT_LEN(OVPN_NONCE_TAIL_SIZE), -@@ -60,16 +76,49 @@ const struct nla_policy ovpn_peer_nl_pol - [OVPN_A_PEER_LINK_TX_PACKETS] = { .type = NLA_UINT, }, - }; - -+const struct nla_policy ovpn_peer_del_input_nl_policy[OVPN_A_PEER_ID + 1] = { -+ [OVPN_A_PEER_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_peer_id_range), -+}; -+ -+const struct nla_policy ovpn_peer_new_input_nl_policy[OVPN_A_PEER_KEEPALIVE_TIMEOUT + 1] = { -+ [OVPN_A_PEER_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_peer_id_range), -+ [OVPN_A_PEER_REMOTE_IPV4] = { .type = NLA_BE32, }, -+ [OVPN_A_PEER_REMOTE_IPV6] = NLA_POLICY_EXACT_LEN(16), -+ [OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID] = { .type = NLA_U32, }, -+ [OVPN_A_PEER_REMOTE_PORT] = NLA_POLICY_MIN(NLA_BE16, 1), -+ [OVPN_A_PEER_SOCKET] = { .type = NLA_U32, }, -+ [OVPN_A_PEER_VPN_IPV4] = { .type = NLA_BE32, }, -+ [OVPN_A_PEER_VPN_IPV6] = NLA_POLICY_EXACT_LEN(16), -+ [OVPN_A_PEER_LOCAL_IPV4] = { .type = NLA_BE32, }, -+ [OVPN_A_PEER_LOCAL_IPV6] = NLA_POLICY_EXACT_LEN(16), -+ [OVPN_A_PEER_KEEPALIVE_INTERVAL] = { .type = NLA_U32, }, -+ [OVPN_A_PEER_KEEPALIVE_TIMEOUT] = { .type = NLA_U32, }, -+}; -+ -+const struct nla_policy ovpn_peer_set_input_nl_policy[OVPN_A_PEER_KEEPALIVE_TIMEOUT + 1] = { -+ [OVPN_A_PEER_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_peer_id_range), -+ [OVPN_A_PEER_REMOTE_IPV4] = { .type = NLA_BE32, }, -+ [OVPN_A_PEER_REMOTE_IPV6] = NLA_POLICY_EXACT_LEN(16), -+ [OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID] = { .type = NLA_U32, }, -+ [OVPN_A_PEER_REMOTE_PORT] = NLA_POLICY_MIN(NLA_BE16, 1), -+ [OVPN_A_PEER_VPN_IPV4] = { .type = NLA_BE32, }, -+ [OVPN_A_PEER_VPN_IPV6] = NLA_POLICY_EXACT_LEN(16), -+ [OVPN_A_PEER_LOCAL_IPV4] = { .type = NLA_BE32, }, -+ [OVPN_A_PEER_LOCAL_IPV6] = NLA_POLICY_EXACT_LEN(16), -+ [OVPN_A_PEER_KEEPALIVE_INTERVAL] = { .type = NLA_U32, }, -+ [OVPN_A_PEER_KEEPALIVE_TIMEOUT] = { .type = NLA_U32, }, -+}; -+ - /* OVPN_CMD_PEER_NEW - do */ - static const struct nla_policy ovpn_peer_new_nl_policy[OVPN_A_PEER + 1] = { - [OVPN_A_IFINDEX] = { .type = NLA_U32, }, -- [OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_nl_policy), -+ [OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_new_input_nl_policy), - }; - - /* OVPN_CMD_PEER_SET - do */ - static const struct nla_policy ovpn_peer_set_nl_policy[OVPN_A_PEER + 1] = { - [OVPN_A_IFINDEX] = { .type = NLA_U32, }, -- [OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_nl_policy), -+ [OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_set_input_nl_policy), - }; - - /* OVPN_CMD_PEER_GET - do */ -@@ -86,7 +135,7 @@ static const struct nla_policy ovpn_peer - /* OVPN_CMD_PEER_DEL - do */ - static const struct nla_policy ovpn_peer_del_nl_policy[OVPN_A_PEER + 1] = { - [OVPN_A_IFINDEX] = { .type = NLA_U32, }, -- [OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_nl_policy), -+ [OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_del_input_nl_policy), - }; - - /* OVPN_CMD_KEY_NEW - do */ -@@ -98,19 +147,19 @@ static const struct nla_policy ovpn_key_ - /* OVPN_CMD_KEY_GET - do */ - static const struct nla_policy ovpn_key_get_nl_policy[OVPN_A_KEYCONF + 1] = { - [OVPN_A_IFINDEX] = { .type = NLA_U32, }, -- [OVPN_A_KEYCONF] = NLA_POLICY_NESTED(ovpn_keyconf_nl_policy), -+ [OVPN_A_KEYCONF] = NLA_POLICY_NESTED(ovpn_keyconf_get_nl_policy), - }; - - /* OVPN_CMD_KEY_SWAP - do */ - static const struct nla_policy ovpn_key_swap_nl_policy[OVPN_A_KEYCONF + 1] = { - [OVPN_A_IFINDEX] = { .type = NLA_U32, }, -- [OVPN_A_KEYCONF] = NLA_POLICY_NESTED(ovpn_keyconf_nl_policy), -+ [OVPN_A_KEYCONF] = NLA_POLICY_NESTED(ovpn_keyconf_swap_input_nl_policy), - }; - - /* OVPN_CMD_KEY_DEL - do */ - static const struct nla_policy ovpn_key_del_nl_policy[OVPN_A_KEYCONF + 1] = { - [OVPN_A_IFINDEX] = { .type = NLA_U32, }, -- [OVPN_A_KEYCONF] = NLA_POLICY_NESTED(ovpn_keyconf_nl_policy), -+ [OVPN_A_KEYCONF] = NLA_POLICY_NESTED(ovpn_keyconf_del_input_nl_policy), - }; - - /* Ops table for ovpn */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ovpn/netlink-gen.h BPI-Router-Linux-kernel-6.16.12/drivers/net/ovpn/netlink-gen.h ---- BPI-Router-Linux-kernel/drivers/net/ovpn/netlink-gen.h 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ovpn/netlink-gen.h 2025-10-22 13:53:56.587168794 -0400 -@@ -13,8 +13,14 @@ - - /* Common nested types */ - extern const struct nla_policy ovpn_keyconf_nl_policy[OVPN_A_KEYCONF_DECRYPT_DIR + 1]; -+extern const struct nla_policy ovpn_keyconf_del_input_nl_policy[OVPN_A_KEYCONF_SLOT + 1]; -+extern const struct nla_policy ovpn_keyconf_get_nl_policy[OVPN_A_KEYCONF_CIPHER_ALG + 1]; -+extern const struct nla_policy ovpn_keyconf_swap_input_nl_policy[OVPN_A_KEYCONF_PEER_ID + 1]; - extern const struct nla_policy ovpn_keydir_nl_policy[OVPN_A_KEYDIR_NONCE_TAIL + 1]; - extern const struct nla_policy ovpn_peer_nl_policy[OVPN_A_PEER_LINK_TX_PACKETS + 1]; -+extern const struct nla_policy ovpn_peer_del_input_nl_policy[OVPN_A_PEER_ID + 1]; -+extern const struct nla_policy ovpn_peer_new_input_nl_policy[OVPN_A_PEER_KEEPALIVE_TIMEOUT + 1]; -+extern const struct nla_policy ovpn_peer_set_input_nl_policy[OVPN_A_PEER_KEEPALIVE_TIMEOUT + 1]; - - int ovpn_nl_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb, - struct genl_info *info); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ovpn/udp.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ovpn/udp.c ---- BPI-Router-Linux-kernel/drivers/net/ovpn/udp.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ovpn/udp.c 2025-10-22 13:53:56.591168775 -0400 -@@ -344,6 +344,7 @@ void ovpn_udp_send_skb(struct ovpn_peer - int ret; - - skb->dev = peer->ovpn->dev; -+ skb->mark = READ_ONCE(sk->sk_mark); - /* no checksum performed at this layer */ - skb->ip_summed = CHECKSUM_NONE; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/pcs/pcs-rzn1-miic.c BPI-Router-Linux-kernel-6.16.12/drivers/net/pcs/pcs-rzn1-miic.c ---- BPI-Router-Linux-kernel/drivers/net/pcs/pcs-rzn1-miic.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/pcs/pcs-rzn1-miic.c 2025-10-22 13:53:56.591168775 -0400 -@@ -19,7 +19,7 @@ - #define MIIC_PRCMD 0x0 - #define MIIC_ESID_CODE 0x4 - --#define MIIC_MODCTRL 0x20 -+#define MIIC_MODCTRL 0x8 - #define MIIC_MODCTRL_SW_MODE GENMASK(4, 0) - - #define MIIC_CONVCTRL(port) (0x100 + (port) * 4) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/pcs/pcs-xpcs-plat.c BPI-Router-Linux-kernel-6.16.12/drivers/net/pcs/pcs-xpcs-plat.c ---- BPI-Router-Linux-kernel/drivers/net/pcs/pcs-xpcs-plat.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/pcs/pcs-xpcs-plat.c 2025-10-22 13:53:56.591168775 -0400 -@@ -66,7 +66,7 @@ static int xpcs_mmio_read_reg_indirect(s - switch (pxpcs->reg_width) { - case 4: - writel(page, pxpcs->reg_base + (DW_VR_CSR_VIEWPORT << 2)); -- ret = readl(pxpcs->reg_base + (ofs << 2)); -+ ret = readl(pxpcs->reg_base + (ofs << 2)) & 0xffff; - break; - default: - writew(page, pxpcs->reg_base + (DW_VR_CSR_VIEWPORT << 1)); -@@ -124,7 +124,7 @@ static int xpcs_mmio_read_reg_direct(str - - switch (pxpcs->reg_width) { - case 4: -- ret = readl(pxpcs->reg_base + (csr << 2)); -+ ret = readl(pxpcs->reg_base + (csr << 2)) & 0xffff; - break; - default: - ret = readw(pxpcs->reg_base + (csr << 1)); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/phy/air_en8811h.c BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/air_en8811h.c ---- BPI-Router-Linux-kernel/drivers/net/phy/air_en8811h.c 2025-10-22 13:53:23.363328417 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/air_en8811h.c 2025-10-22 13:53:56.591168775 -0400 -@@ -11,6 +11,7 @@ - * Copyright (C) 2023 Airoha Technology Corp. - */ - -+#include - #include - #include - #include -@@ -157,6 +158,7 @@ struct en8811h_priv { - struct led led[EN8811H_LED_COUNT]; - struct clk_hw hw; - struct phy_device *phydev; -+ unsigned int cko_is_enabled; - }; - - enum { -@@ -865,11 +867,30 @@ static int en8811h_clk_is_enabled(struct - return (pbus_value & EN8811H_CLK_CGM_CKO); - } - -+static int en8811h_clk_save_context(struct clk_hw *hw) -+{ -+ struct en8811h_priv *priv = clk_hw_to_en8811h_priv(hw); -+ -+ priv->cko_is_enabled = en8811h_clk_is_enabled(hw); -+ -+ return 0; -+} -+ -+static void en8811h_clk_restore_context(struct clk_hw *hw) -+{ -+ struct en8811h_priv *priv = clk_hw_to_en8811h_priv(hw); -+ -+ if (!priv->cko_is_enabled) -+ en8811h_clk_disable(hw); -+} -+ - static const struct clk_ops en8811h_clk_ops = { -- .recalc_rate = en8811h_clk_recalc_rate, -- .enable = en8811h_clk_enable, -- .disable = en8811h_clk_disable, -- .is_enabled = en8811h_clk_is_enabled, -+ .recalc_rate = en8811h_clk_recalc_rate, -+ .enable = en8811h_clk_enable, -+ .disable = en8811h_clk_disable, -+ .is_enabled = en8811h_clk_is_enabled, -+ .save_context = en8811h_clk_save_context, -+ .restore_context = en8811h_clk_restore_context, - }; - - static int en8811h_clk_provider_setup(struct device *dev, struct clk_hw *hw) -@@ -1149,6 +1170,20 @@ static irqreturn_t en8811h_handle_interr - return IRQ_HANDLED; - } - -+static int en8811h_resume(struct phy_device *phydev) -+{ -+ clk_restore_context(); -+ -+ return genphy_resume(phydev); -+} -+ -+static int en8811h_suspend(struct phy_device *phydev) -+{ -+ clk_save_context(); -+ -+ return genphy_suspend(phydev); -+} -+ - static struct phy_driver en8811h_driver[] = { - { - PHY_ID_MATCH_MODEL(EN8811H_PHY_ID), -@@ -1159,6 +1194,8 @@ static struct phy_driver en8811h_driver[ - .get_rate_matching = en8811h_get_rate_matching, - .config_aneg = en8811h_config_aneg, - .read_status = en8811h_read_status, -+ .resume = en8811h_resume, -+ .suspend = en8811h_suspend, - .config_intr = en8811h_clear_intr, - .handle_interrupt = en8811h_handle_interrupt, - .led_hw_is_supported = en8811h_led_hw_is_supported, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/phy/bcm-phy-ptp.c BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/bcm-phy-ptp.c ---- BPI-Router-Linux-kernel/drivers/net/phy/bcm-phy-ptp.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/bcm-phy-ptp.c 2025-10-22 13:53:56.591168775 -0400 -@@ -597,10 +597,6 @@ static int bcm_ptp_perout_locked(struct - - period = BCM_MAX_PERIOD_8NS; /* write nonzero value */ - -- /* Reject unsupported flags */ -- if (req->flags & ~PTP_PEROUT_DUTY_CYCLE) -- return -EOPNOTSUPP; -- - if (req->flags & PTP_PEROUT_DUTY_CYCLE) - pulse = ktime_to_ns(ktime_set(req->on.sec, req->on.nsec)); - else -@@ -741,6 +737,8 @@ static const struct ptp_clock_info bcm_p - .n_pins = 1, - .n_per_out = 1, - .n_ext_ts = 1, -+ .supported_perout_flags = PTP_PEROUT_DUTY_CYCLE, -+ .supported_extts_flags = PTP_STRICT_FLAGS | PTP_RISING_EDGE, - }; - - static void bcm_ptp_txtstamp(struct mii_timestamper *mii_ts, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/phy/broadcom.c BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/broadcom.c ---- BPI-Router-Linux-kernel/drivers/net/phy/broadcom.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/broadcom.c 2025-10-22 13:53:56.591168775 -0400 -@@ -655,7 +655,7 @@ static int bcm5481x_read_abilities(struc - { - struct device_node *np = phydev->mdio.dev.of_node; - struct bcm54xx_phy_priv *priv = phydev->priv; -- int i, val, err; -+ int i, val, err, aneg; - - for (i = 0; i < ARRAY_SIZE(bcm54811_linkmodes); i++) - linkmode_clear_bit(bcm54811_linkmodes[i], phydev->supported); -@@ -676,9 +676,19 @@ static int bcm5481x_read_abilities(struc - if (val < 0) - return val; - -+ /* BCM54811 is not capable of LDS but the corresponding bit -+ * in LRESR is set to 1 and marked "Ignore" in the datasheet. -+ * So we must read the bcm54811 as unable to auto-negotiate -+ * in BroadR-Reach mode. -+ */ -+ if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54811) -+ aneg = 0; -+ else -+ aneg = val & LRESR_LDSABILITY; -+ - linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, - phydev->supported, -- val & LRESR_LDSABILITY); -+ aneg); - linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT, - phydev->supported, - val & LRESR_100_1PAIR); -@@ -735,8 +745,15 @@ static int bcm54811_config_aneg(struct p - - /* Aneg firstly. */ - if (priv->brr_mode) { -- /* BCM54811 is only capable of autonegotiation in IEEE mode */ -- phydev->autoneg = 0; -+ /* BCM54811 is only capable of autonegotiation in IEEE mode. -+ * In BroadR-Reach mode, disable the Long Distance Signaling, -+ * the BRR mode autoneg as supported in other Broadcom PHYs. -+ * This bit is marked as "Reserved" and "Default 1, must be -+ * written to 0 after every device reset" in the datasheet. -+ */ -+ ret = phy_modify(phydev, MII_BCM54XX_LRECR, LRECR_LDSEN, 0); -+ if (ret < 0) -+ return ret; - ret = bcm_config_lre_aneg(phydev, false); - } else { - ret = genphy_config_aneg(phydev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/phy/mdio_bus.c BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/mdio_bus.c ---- BPI-Router-Linux-kernel/drivers/net/phy/mdio_bus.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/mdio_bus.c 2025-10-22 13:53:56.591168775 -0400 -@@ -91,6 +91,7 @@ int mdiobus_unregister_device(struct mdi - if (mdiodev->bus->mdio_map[mdiodev->addr] != mdiodev) - return -EINVAL; - -+ gpiod_put(mdiodev->reset_gpio); - reset_control_put(mdiodev->reset_ctrl); - - mdiodev->bus->mdio_map[mdiodev->addr] = NULL; -@@ -445,6 +446,9 @@ int __mdiobus_read(struct mii_bus *bus, - - lockdep_assert_held_once(&bus->mdio_lock); - -+ if (addr >= PHY_MAX_ADDR) -+ return -ENXIO; -+ - if (bus->read) - retval = bus->read(bus, addr, regnum); - else -@@ -474,6 +478,9 @@ int __mdiobus_write(struct mii_bus *bus, - - lockdep_assert_held_once(&bus->mdio_lock); - -+ if (addr >= PHY_MAX_ADDR) -+ return -ENXIO; -+ - if (bus->write) - err = bus->write(bus, addr, regnum, val); - else -@@ -535,6 +542,9 @@ int __mdiobus_c45_read(struct mii_bus *b - - lockdep_assert_held_once(&bus->mdio_lock); - -+ if (addr >= PHY_MAX_ADDR) -+ return -ENXIO; -+ - if (bus->read_c45) - retval = bus->read_c45(bus, addr, devad, regnum); - else -@@ -566,6 +576,9 @@ int __mdiobus_c45_write(struct mii_bus * - - lockdep_assert_held_once(&bus->mdio_lock); - -+ if (addr >= PHY_MAX_ADDR) -+ return -ENXIO; -+ - if (bus->write_c45) - err = bus->write_c45(bus, addr, devad, regnum, val); - else -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/phy/mdio_bus_provider.c BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/mdio_bus_provider.c ---- BPI-Router-Linux-kernel/drivers/net/phy/mdio_bus_provider.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/mdio_bus_provider.c 2025-10-22 13:53:56.591168775 -0400 -@@ -444,9 +444,6 @@ void mdiobus_unregister(struct mii_bus * - if (!mdiodev) - continue; - -- if (mdiodev->reset_gpio) -- gpiod_put(mdiodev->reset_gpio); -- - mdiodev->device_remove(mdiodev); - mdiodev->device_free(mdiodev); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/phy/micrel.c BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/micrel.c ---- BPI-Router-Linux-kernel/drivers/net/phy/micrel.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/micrel.c 2025-10-22 13:53:56.591168775 -0400 -@@ -472,6 +472,8 @@ static const struct kszphy_type ksz8051_ - - static const struct kszphy_type ksz8081_type = { - .led_mode_reg = MII_KSZPHY_CTRL_2, -+ .cable_diag_reg = KSZ8081_LMD, -+ .pair_mask = KSZPHY_WIRE_PAIR_MASK, - .has_broadcast_disable = true, - .has_nand_tree_disable = true, - .has_rmii_ref_clk_sel = true, -@@ -5403,6 +5405,14 @@ static int lan8841_suspend(struct phy_de - return kszphy_generic_suspend(phydev); - } - -+static int ksz9131_resume(struct phy_device *phydev) -+{ -+ if (phydev->suspended && phy_interface_is_rgmii(phydev)) -+ ksz9131_config_rgmii_delay(phydev); -+ -+ return kszphy_resume(phydev); -+} -+ - static struct phy_driver ksphy_driver[] = { - { - .phy_id = PHY_ID_KS8737, -@@ -5649,7 +5659,7 @@ static struct phy_driver ksphy_driver[] - .get_strings = kszphy_get_strings, - .get_stats = kszphy_get_stats, - .suspend = kszphy_suspend, -- .resume = kszphy_resume, -+ .resume = ksz9131_resume, - .cable_test_start = ksz9x31_cable_test_start, - .cable_test_get_status = ksz9x31_cable_test_get_status, - .get_features = ksz9477_get_features, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/phy/microchip.c BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/microchip.c ---- BPI-Router-Linux-kernel/drivers/net/phy/microchip.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/microchip.c 2025-10-22 13:53:56.591168775 -0400 -@@ -332,7 +332,7 @@ static void lan88xx_link_change_notify(s - * As workaround, set to 10 before setting to 100 - * at forced 100 F/H mode. - */ -- if (!phydev->autoneg && phydev->speed == 100) { -+ if (phydev->state == PHY_NOLINK && !phydev->autoneg && phydev->speed == 100) { - /* disable phy interrupt */ - temp = phy_read(phydev, LAN88XX_INT_MASK); - temp &= ~LAN88XX_INT_MASK_MDINTPIN_EN_; -@@ -488,6 +488,7 @@ static struct phy_driver microchip_phy_d - .config_init = lan88xx_config_init, - .config_aneg = lan88xx_config_aneg, - .link_change_notify = lan88xx_link_change_notify, -+ .soft_reset = genphy_soft_reset, - - /* Interrupt handling is broken, do not define related - * functions to force polling. -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/phy/mscc/mscc.h BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/mscc/mscc.h ---- BPI-Router-Linux-kernel/drivers/net/phy/mscc/mscc.h 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/mscc/mscc.h 2025-10-22 13:53:56.591168775 -0400 -@@ -362,6 +362,13 @@ struct vsc85xx_hw_stat { - u16 mask; - }; - -+struct vsc8531_skb_cb { -+ u32 ns; -+}; -+ -+#define VSC8531_SKB_CB(skb) \ -+ ((struct vsc8531_skb_cb *)((skb)->cb)) -+ - struct vsc8531_private { - int rate_magic; - u16 supp_led_modes; -@@ -410,6 +417,11 @@ struct vsc8531_private { - */ - struct mutex ts_lock; - struct mutex phc_lock; -+ -+ /* list of skbs that were received and need timestamp information but it -+ * didn't received it yet -+ */ -+ struct sk_buff_head rx_skbs_list; - }; - - /* Shared structure between the PHYs of the same package. -@@ -469,6 +481,7 @@ static inline void vsc8584_config_macsec - void vsc85xx_link_change_notify(struct phy_device *phydev); - void vsc8584_config_ts_intr(struct phy_device *phydev); - int vsc8584_ptp_init(struct phy_device *phydev); -+void vsc8584_ptp_deinit(struct phy_device *phydev); - int vsc8584_ptp_probe_once(struct phy_device *phydev); - int vsc8584_ptp_probe(struct phy_device *phydev); - irqreturn_t vsc8584_handle_ts_interrupt(struct phy_device *phydev); -@@ -483,6 +496,9 @@ static inline int vsc8584_ptp_init(struc - { - return 0; - } -+static inline void vsc8584_ptp_deinit(struct phy_device *phydev) -+{ -+} - static inline int vsc8584_ptp_probe_once(struct phy_device *phydev) - { - return 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/phy/mscc/mscc_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/mscc/mscc_main.c ---- BPI-Router-Linux-kernel/drivers/net/phy/mscc/mscc_main.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/mscc/mscc_main.c 2025-10-22 13:53:56.591168775 -0400 -@@ -2336,6 +2336,11 @@ static int vsc85xx_probe(struct phy_devi - return vsc85xx_dt_led_modes_get(phydev, default_mode); - } - -+static void vsc85xx_remove(struct phy_device *phydev) -+{ -+ vsc8584_ptp_deinit(phydev); -+} -+ - /* Microsemi VSC85xx PHYs */ - static struct phy_driver vsc85xx_driver[] = { - { -@@ -2590,6 +2595,7 @@ static struct phy_driver vsc85xx_driver[ - .config_intr = &vsc85xx_config_intr, - .suspend = &genphy_suspend, - .resume = &genphy_resume, -+ .remove = &vsc85xx_remove, - .probe = &vsc8574_probe, - .set_wol = &vsc85xx_wol_set, - .get_wol = &vsc85xx_wol_get, -@@ -2615,6 +2621,7 @@ static struct phy_driver vsc85xx_driver[ - .config_intr = &vsc85xx_config_intr, - .suspend = &genphy_suspend, - .resume = &genphy_resume, -+ .remove = &vsc85xx_remove, - .probe = &vsc8574_probe, - .set_wol = &vsc85xx_wol_set, - .get_wol = &vsc85xx_wol_get, -@@ -2640,6 +2647,7 @@ static struct phy_driver vsc85xx_driver[ - .config_intr = &vsc85xx_config_intr, - .suspend = &genphy_suspend, - .resume = &genphy_resume, -+ .remove = &vsc85xx_remove, - .probe = &vsc8584_probe, - .get_tunable = &vsc85xx_get_tunable, - .set_tunable = &vsc85xx_set_tunable, -@@ -2663,6 +2671,7 @@ static struct phy_driver vsc85xx_driver[ - .config_intr = &vsc85xx_config_intr, - .suspend = &genphy_suspend, - .resume = &genphy_resume, -+ .remove = &vsc85xx_remove, - .probe = &vsc8584_probe, - .get_tunable = &vsc85xx_get_tunable, - .set_tunable = &vsc85xx_set_tunable, -@@ -2686,6 +2695,7 @@ static struct phy_driver vsc85xx_driver[ - .config_intr = &vsc85xx_config_intr, - .suspend = &genphy_suspend, - .resume = &genphy_resume, -+ .remove = &vsc85xx_remove, - .probe = &vsc8584_probe, - .get_tunable = &vsc85xx_get_tunable, - .set_tunable = &vsc85xx_set_tunable, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/phy/mscc/mscc_ptp.c BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/mscc/mscc_ptp.c ---- BPI-Router-Linux-kernel/drivers/net/phy/mscc/mscc_ptp.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/mscc/mscc_ptp.c 2025-10-22 13:53:56.591168775 -0400 -@@ -456,12 +456,12 @@ static void vsc85xx_dequeue_skb(struct v - *p++ = (reg >> 24) & 0xff; - } - -- len = skb_queue_len(&ptp->tx_queue); -+ len = skb_queue_len_lockless(&ptp->tx_queue); - if (len < 1) - return; - - while (len--) { -- skb = __skb_dequeue(&ptp->tx_queue); -+ skb = skb_dequeue(&ptp->tx_queue); - if (!skb) - return; - -@@ -486,7 +486,7 @@ static void vsc85xx_dequeue_skb(struct v - * packet in the FIFO right now, reschedule it for later - * packets. - */ -- __skb_queue_tail(&ptp->tx_queue, skb); -+ skb_queue_tail(&ptp->tx_queue, skb); - } - } - -@@ -900,6 +900,7 @@ static int vsc85xx_eth1_conf(struct phy_ - get_unaligned_be32(ptp_multicast)); - } else { - val |= ANA_ETH1_FLOW_ADDR_MATCH2_ANY_MULTICAST; -+ val |= ANA_ETH1_FLOW_ADDR_MATCH2_ANY_UNICAST; - vsc85xx_ts_write_csr(phydev, blk, - MSCC_ANA_ETH1_FLOW_ADDR_MATCH2(0), val); - vsc85xx_ts_write_csr(phydev, blk, -@@ -1067,6 +1068,7 @@ static int vsc85xx_hwtstamp(struct mii_t - case HWTSTAMP_TX_ON: - break; - case HWTSTAMP_TX_OFF: -+ skb_queue_purge(&vsc8531->ptp->tx_queue); - break; - default: - return -ERANGE; -@@ -1091,9 +1093,6 @@ static int vsc85xx_hwtstamp(struct mii_t - - mutex_lock(&vsc8531->ts_lock); - -- __skb_queue_purge(&vsc8531->ptp->tx_queue); -- __skb_queue_head_init(&vsc8531->ptp->tx_queue); -- - /* Disable predictor while configuring the 1588 block */ - val = vsc85xx_ts_read_csr(phydev, PROCESSOR, - MSCC_PHY_PTP_INGR_PREDICTOR); -@@ -1179,9 +1178,7 @@ static void vsc85xx_txtstamp(struct mii_ - - skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; - -- mutex_lock(&vsc8531->ts_lock); -- __skb_queue_tail(&vsc8531->ptp->tx_queue, skb); -- mutex_unlock(&vsc8531->ts_lock); -+ skb_queue_tail(&vsc8531->ptp->tx_queue, skb); - return; - - out: -@@ -1193,9 +1190,7 @@ static bool vsc85xx_rxtstamp(struct mii_ - { - struct vsc8531_private *vsc8531 = - container_of(mii_ts, struct vsc8531_private, mii_ts); -- struct skb_shared_hwtstamps *shhwtstamps = NULL; - struct vsc85xx_ptphdr *ptphdr; -- struct timespec64 ts; - unsigned long ns; - - if (!vsc8531->ptp->configured) -@@ -1205,27 +1200,52 @@ static bool vsc85xx_rxtstamp(struct mii_ - type == PTP_CLASS_NONE) - return false; - -- vsc85xx_gettime(&vsc8531->ptp->caps, &ts); -- - ptphdr = get_ptp_header_rx(skb, vsc8531->ptp->rx_filter); - if (!ptphdr) - return false; - -- shhwtstamps = skb_hwtstamps(skb); -- memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps)); -- - ns = ntohl(ptphdr->rsrvd2); - -- /* nsec is in reserved field */ -- if (ts.tv_nsec < ns) -- ts.tv_sec--; -+ VSC8531_SKB_CB(skb)->ns = ns; -+ skb_queue_tail(&vsc8531->rx_skbs_list, skb); - -- shhwtstamps->hwtstamp = ktime_set(ts.tv_sec, ns); -- netif_rx(skb); -+ ptp_schedule_worker(vsc8531->ptp->ptp_clock, 0); - - return true; - } - -+static long vsc85xx_do_aux_work(struct ptp_clock_info *info) -+{ -+ struct vsc85xx_ptp *ptp = container_of(info, struct vsc85xx_ptp, caps); -+ struct skb_shared_hwtstamps *shhwtstamps = NULL; -+ struct phy_device *phydev = ptp->phydev; -+ struct vsc8531_private *priv = phydev->priv; -+ struct sk_buff_head received; -+ struct sk_buff *rx_skb; -+ struct timespec64 ts; -+ unsigned long flags; -+ -+ __skb_queue_head_init(&received); -+ spin_lock_irqsave(&priv->rx_skbs_list.lock, flags); -+ skb_queue_splice_tail_init(&priv->rx_skbs_list, &received); -+ spin_unlock_irqrestore(&priv->rx_skbs_list.lock, flags); -+ -+ vsc85xx_gettime(info, &ts); -+ while ((rx_skb = __skb_dequeue(&received)) != NULL) { -+ shhwtstamps = skb_hwtstamps(rx_skb); -+ memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps)); -+ -+ if (ts.tv_nsec < VSC8531_SKB_CB(rx_skb)->ns) -+ ts.tv_sec--; -+ -+ shhwtstamps->hwtstamp = ktime_set(ts.tv_sec, -+ VSC8531_SKB_CB(rx_skb)->ns); -+ netif_rx(rx_skb); -+ } -+ -+ return -1; -+} -+ - static const struct ptp_clock_info vsc85xx_clk_caps = { - .owner = THIS_MODULE, - .name = "VSC85xx timer", -@@ -1239,6 +1259,7 @@ static const struct ptp_clock_info vsc85 - .adjfine = &vsc85xx_adjfine, - .gettime64 = &vsc85xx_gettime, - .settime64 = &vsc85xx_settime, -+ .do_aux_work = &vsc85xx_do_aux_work, - }; - - static struct vsc8531_private *vsc8584_base_priv(struct phy_device *phydev) -@@ -1273,7 +1294,6 @@ static void vsc8584_set_input_clk_config - - static int __vsc8584_init_ptp(struct phy_device *phydev) - { -- struct vsc8531_private *vsc8531 = phydev->priv; - static const u32 ltc_seq_e[] = { 0, 400000, 0, 0, 0 }; - static const u8 ltc_seq_a[] = { 8, 6, 5, 4, 2 }; - u32 val; -@@ -1490,17 +1510,7 @@ static int __vsc8584_init_ptp(struct phy - - vsc85xx_ts_eth_cmp1_sig(phydev); - -- vsc8531->mii_ts.rxtstamp = vsc85xx_rxtstamp; -- vsc8531->mii_ts.txtstamp = vsc85xx_txtstamp; -- vsc8531->mii_ts.hwtstamp = vsc85xx_hwtstamp; -- vsc8531->mii_ts.ts_info = vsc85xx_ts_info; -- phydev->mii_ts = &vsc8531->mii_ts; -- -- memcpy(&vsc8531->ptp->caps, &vsc85xx_clk_caps, sizeof(vsc85xx_clk_caps)); -- -- vsc8531->ptp->ptp_clock = ptp_clock_register(&vsc8531->ptp->caps, -- &phydev->mdio.dev); -- return PTR_ERR_OR_ZERO(vsc8531->ptp->ptp_clock); -+ return 0; - } - - void vsc8584_config_ts_intr(struct phy_device *phydev) -@@ -1527,6 +1537,17 @@ int vsc8584_ptp_init(struct phy_device * - return 0; - } - -+void vsc8584_ptp_deinit(struct phy_device *phydev) -+{ -+ struct vsc8531_private *vsc8531 = phydev->priv; -+ -+ if (vsc8531->ptp->ptp_clock) { -+ ptp_clock_unregister(vsc8531->ptp->ptp_clock); -+ skb_queue_purge(&vsc8531->rx_skbs_list); -+ skb_queue_purge(&vsc8531->ptp->tx_queue); -+ } -+} -+ - irqreturn_t vsc8584_handle_ts_interrupt(struct phy_device *phydev) - { - struct vsc8531_private *priv = phydev->priv; -@@ -1547,7 +1568,7 @@ irqreturn_t vsc8584_handle_ts_interrupt( - if (rc & VSC85XX_1588_INT_FIFO_ADD) { - vsc85xx_get_tx_ts(priv->ptp); - } else if (rc & VSC85XX_1588_INT_FIFO_OVERFLOW) { -- __skb_queue_purge(&priv->ptp->tx_queue); -+ skb_queue_purge(&priv->ptp->tx_queue); - vsc85xx_ts_reset_fifo(phydev); - } - -@@ -1566,6 +1587,8 @@ int vsc8584_ptp_probe(struct phy_device - - mutex_init(&vsc8531->phc_lock); - mutex_init(&vsc8531->ts_lock); -+ skb_queue_head_init(&vsc8531->rx_skbs_list); -+ skb_queue_head_init(&vsc8531->ptp->tx_queue); - - /* Retrieve the shared load/save GPIO. Request it as non exclusive as - * the same GPIO can be requested by all the PHYs of the same package. -@@ -1586,7 +1609,16 @@ int vsc8584_ptp_probe(struct phy_device - - vsc8531->ptp->phydev = phydev; - -- return 0; -+ vsc8531->mii_ts.rxtstamp = vsc85xx_rxtstamp; -+ vsc8531->mii_ts.txtstamp = vsc85xx_txtstamp; -+ vsc8531->mii_ts.hwtstamp = vsc85xx_hwtstamp; -+ vsc8531->mii_ts.ts_info = vsc85xx_ts_info; -+ phydev->mii_ts = &vsc8531->mii_ts; -+ -+ memcpy(&vsc8531->ptp->caps, &vsc85xx_clk_caps, sizeof(vsc85xx_clk_caps)); -+ vsc8531->ptp->ptp_clock = ptp_clock_register(&vsc8531->ptp->caps, -+ &phydev->mdio.dev); -+ return PTR_ERR_OR_ZERO(vsc8531->ptp->ptp_clock); - } - - int vsc8584_ptp_probe_once(struct phy_device *phydev) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/phy/mscc/mscc_ptp.h BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/mscc/mscc_ptp.h ---- BPI-Router-Linux-kernel/drivers/net/phy/mscc/mscc_ptp.h 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/mscc/mscc_ptp.h 2025-10-22 13:53:56.591168775 -0400 -@@ -98,6 +98,7 @@ - #define MSCC_ANA_ETH1_FLOW_ADDR_MATCH2(x) (MSCC_ANA_ETH1_FLOW_ENA(x) + 3) - #define ANA_ETH1_FLOW_ADDR_MATCH2_MASK_MASK GENMASK(22, 20) - #define ANA_ETH1_FLOW_ADDR_MATCH2_ANY_MULTICAST 0x400000 -+#define ANA_ETH1_FLOW_ADDR_MATCH2_ANY_UNICAST 0x200000 - #define ANA_ETH1_FLOW_ADDR_MATCH2_FULL_ADDR 0x100000 - #define ANA_ETH1_FLOW_ADDR_MATCH2_SRC_DEST_MASK GENMASK(17, 16) - #define ANA_ETH1_FLOW_ADDR_MATCH2_SRC_DEST 0x020000 -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/phy/nxp-c45-tja11xx.c BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/nxp-c45-tja11xx.c ---- BPI-Router-Linux-kernel/drivers/net/phy/nxp-c45-tja11xx.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/nxp-c45-tja11xx.c 2025-10-22 13:53:56.591168775 -0400 -@@ -1965,24 +1965,27 @@ static int nxp_c45_macsec_ability(struct - return macsec_ability; - } - -+static bool tja11xx_phy_id_compare(struct phy_device *phydev, -+ const struct phy_driver *phydrv) -+{ -+ u32 id = phydev->is_c45 ? phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] : -+ phydev->phy_id; -+ -+ return phy_id_compare(id, phydrv->phy_id, phydrv->phy_id_mask); -+} -+ - static int tja11xx_no_macsec_match_phy_device(struct phy_device *phydev, - const struct phy_driver *phydrv) - { -- if (!phy_id_compare(phydev->phy_id, phydrv->phy_id, -- phydrv->phy_id_mask)) -- return 0; -- -- return !nxp_c45_macsec_ability(phydev); -+ return tja11xx_phy_id_compare(phydev, phydrv) && -+ !nxp_c45_macsec_ability(phydev); - } - - static int tja11xx_macsec_match_phy_device(struct phy_device *phydev, - const struct phy_driver *phydrv) - { -- if (!phy_id_compare(phydev->phy_id, phydrv->phy_id, -- phydrv->phy_id_mask)) -- return 0; -- -- return nxp_c45_macsec_ability(phydev); -+ return tja11xx_phy_id_compare(phydev, phydrv) && -+ nxp_c45_macsec_ability(phydev); - } - - static const struct nxp_c45_regmap tja1120_regmap = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/phy/phy.c BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/phy.c ---- BPI-Router-Linux-kernel/drivers/net/phy/phy.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/phy.c 2025-10-22 13:53:56.591168775 -0400 -@@ -1065,23 +1065,19 @@ EXPORT_SYMBOL_GPL(phy_inband_caps); - */ - int phy_config_inband(struct phy_device *phydev, unsigned int modes) - { -- int err; -+ lockdep_assert_held(&phydev->lock); - - if (!!(modes & LINK_INBAND_DISABLE) + - !!(modes & LINK_INBAND_ENABLE) + - !!(modes & LINK_INBAND_BYPASS) != 1) - return -EINVAL; - -- mutex_lock(&phydev->lock); - if (!phydev->drv) -- err = -EIO; -+ return -EIO; - else if (!phydev->drv->config_inband) -- err = -EOPNOTSUPP; -- else -- err = phydev->drv->config_inband(phydev, modes); -- mutex_unlock(&phydev->lock); -+ return -EOPNOTSUPP; - -- return err; -+ return phydev->drv->config_inband(phydev, modes); - } - EXPORT_SYMBOL(phy_config_inband); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/phy/phy_caps.c BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/phy_caps.c ---- BPI-Router-Linux-kernel/drivers/net/phy/phy_caps.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/phy_caps.c 2025-10-22 13:53:56.591168775 -0400 -@@ -188,6 +188,9 @@ phy_caps_lookup_by_linkmode_rev(const un - * When @exact is not set, we return either an exact match, or matching capabilities - * at lower speed, or the lowest matching speed, or NULL. - * -+ * Non-exact matches will try to return an exact speed and duplex match, but may -+ * return matching capabilities with same speed but a different duplex. -+ * - * Returns: a matched link_capabilities according to the above process, NULL - * otherwise. - */ -@@ -195,7 +198,7 @@ const struct link_capabilities * - phy_caps_lookup(int speed, unsigned int duplex, const unsigned long *supported, - bool exact) - { -- const struct link_capabilities *lcap, *last = NULL; -+ const struct link_capabilities *lcap, *match = NULL, *last = NULL; - - for_each_link_caps_desc_speed(lcap) { - if (linkmode_intersects(lcap->linkmodes, supported)) { -@@ -204,16 +207,19 @@ phy_caps_lookup(int speed, unsigned int - if (lcap->speed == speed && lcap->duplex == duplex) { - return lcap; - } else if (!exact) { -- if (lcap->speed <= speed) -- return lcap; -+ if (!match && lcap->speed <= speed) -+ match = lcap; -+ -+ if (lcap->speed < speed) -+ break; - } - } - } - -- if (!exact) -- return last; -+ if (!match && !exact) -+ match = last; - -- return NULL; -+ return match; - } - EXPORT_SYMBOL_GPL(phy_caps_lookup); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/phy/phy_device.c BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/phy_device.c ---- BPI-Router-Linux-kernel/drivers/net/phy/phy_device.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/phy_device.c 2025-10-22 13:53:56.591168775 -0400 -@@ -3416,7 +3416,8 @@ static int phy_probe(struct device *dev) - /* Get the LEDs from the device tree, and instantiate standard - * LEDs for them. - */ -- if (IS_ENABLED(CONFIG_PHYLIB_LEDS)) -+ if (IS_ENABLED(CONFIG_PHYLIB_LEDS) && !phy_driver_is_genphy(phydev) && -+ !phy_driver_is_genphy_10g(phydev)) - err = of_phy_leds(phydev); - - out: -@@ -3433,7 +3434,8 @@ static int phy_remove(struct device *dev - - cancel_delayed_work_sync(&phydev->state_queue); - -- if (IS_ENABLED(CONFIG_PHYLIB_LEDS)) -+ if (IS_ENABLED(CONFIG_PHYLIB_LEDS) && !phy_driver_is_genphy(phydev) && -+ !phy_driver_is_genphy_10g(phydev)) - phy_leds_unregister(phydev); - - phydev->state = PHY_DOWN; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/phy/phylink.c BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/phylink.c ---- BPI-Router-Linux-kernel/drivers/net/phy/phylink.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/phylink.c 2025-10-22 13:53:56.591168775 -0400 -@@ -77,6 +77,8 @@ struct phylink { - struct timer_list link_poll; - - struct mutex state_mutex; -+ /* Serialize updates to pl->phydev with phylink_resolve() */ -+ struct mutex phydev_mutex; - struct phylink_link_state phy_state; - unsigned int phy_ib_mode; - struct work_struct resolve; -@@ -1543,6 +1545,7 @@ static void phylink_get_fixed_state(stru - static void phylink_mac_initial_config(struct phylink *pl, bool force_restart) - { - struct phylink_link_state link_state; -+ struct phy_device *phy = pl->phydev; - - switch (pl->req_link_an_mode) { - case MLO_AN_PHY: -@@ -1566,7 +1569,11 @@ static void phylink_mac_initial_config(s - link_state.link = false; - - phylink_apply_manual_flow(pl, &link_state); -+ if (phy) -+ mutex_lock(&phy->lock); - phylink_major_config(pl, force_restart, &link_state); -+ if (phy) -+ mutex_unlock(&phy->lock); - } - - static const char *phylink_pause_to_str(int pause) -@@ -1702,8 +1709,13 @@ static void phylink_resolve(struct work_ - struct phylink_link_state link_state; - bool mac_config = false; - bool retrigger = false; -+ struct phy_device *phy; - bool cur_link_state; - -+ mutex_lock(&pl->phydev_mutex); -+ phy = pl->phydev; -+ if (phy) -+ mutex_lock(&phy->lock); - mutex_lock(&pl->state_mutex); - cur_link_state = phylink_link_is_up(pl); - -@@ -1737,7 +1749,7 @@ static void phylink_resolve(struct work_ - /* If we have a phy, the "up" state is the union of both the - * PHY and the MAC - */ -- if (pl->phydev) -+ if (phy) - link_state.link &= pl->phy_state.link; - - /* Force mac_config if we need to reconfig the interface */ -@@ -1745,7 +1757,7 @@ static void phylink_resolve(struct work_ - mac_config = true; - - /* Only update if the PHY link is up */ -- if (pl->phydev && pl->phy_state.link) { -+ if (phy && pl->phy_state.link) { - /* If the interface has changed, force a link down - * event if the link isn't already down, and re-resolve. - */ -@@ -1811,6 +1823,9 @@ static void phylink_resolve(struct work_ - queue_work(system_power_efficient_wq, &pl->resolve); - } - mutex_unlock(&pl->state_mutex); -+ if (phy) -+ mutex_unlock(&phy->lock); -+ mutex_unlock(&pl->phydev_mutex); - } - - static void phylink_run_resolve(struct phylink *pl) -@@ -1992,6 +2007,7 @@ struct phylink *phylink_create(struct ph - if (!pl) - return ERR_PTR(-ENOMEM); - -+ mutex_init(&pl->phydev_mutex); - mutex_init(&pl->state_mutex); - INIT_WORK(&pl->resolve, phylink_resolve); - INIT_LIST_HEAD(&pl->pcs_list); -@@ -2278,6 +2294,7 @@ static int phylink_bringup_phy(struct ph - dev_name(&phy->mdio.dev), phy->drv->name, irq_str); - kfree(irq_str); - -+ mutex_lock(&pl->phydev_mutex); - mutex_lock(&phy->lock); - mutex_lock(&pl->state_mutex); - pl->phydev = phy; -@@ -2323,6 +2340,7 @@ static int phylink_bringup_phy(struct ph - - mutex_unlock(&pl->state_mutex); - mutex_unlock(&phy->lock); -+ mutex_unlock(&pl->phydev_mutex); - - phylink_dbg(pl, - "phy: %s setting supported %*pb advertising %*pb\n", -@@ -2501,6 +2519,7 @@ void phylink_disconnect_phy(struct phyli - - ASSERT_RTNL(); - -+ mutex_lock(&pl->phydev_mutex); - phy = pl->phydev; - if (phy) { - mutex_lock(&phy->lock); -@@ -2510,8 +2529,11 @@ void phylink_disconnect_phy(struct phyli - pl->mac_tx_clk_stop = false; - mutex_unlock(&pl->state_mutex); - mutex_unlock(&phy->lock); -- flush_work(&pl->resolve); -+ } -+ mutex_unlock(&pl->phydev_mutex); - -+ if (phy) { -+ flush_work(&pl->resolve); - phy_disconnect(phy); - } - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/phy/qcom/at803x.c BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/qcom/at803x.c ---- BPI-Router-Linux-kernel/drivers/net/phy/qcom/at803x.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/qcom/at803x.c 2025-10-22 13:53:56.591168775 -0400 -@@ -26,9 +26,6 @@ - - #define AT803X_LED_CONTROL 0x18 - --#define AT803X_PHY_MMD3_WOL_CTRL 0x8012 --#define AT803X_WOL_EN BIT(5) -- - #define AT803X_REG_CHIP_CONFIG 0x1f - #define AT803X_BT_BX_REG_SEL 0x8000 - -@@ -866,30 +863,6 @@ static int at8031_config_init(struct phy - return at803x_config_init(phydev); - } - --static int at8031_set_wol(struct phy_device *phydev, -- struct ethtool_wolinfo *wol) --{ -- int ret; -- -- /* First setup MAC address and enable WOL interrupt */ -- ret = at803x_set_wol(phydev, wol); -- if (ret) -- return ret; -- -- if (wol->wolopts & WAKE_MAGIC) -- /* Enable WOL function for 1588 */ -- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, -- AT803X_PHY_MMD3_WOL_CTRL, -- 0, AT803X_WOL_EN); -- else -- /* Disable WoL function for 1588 */ -- ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, -- AT803X_PHY_MMD3_WOL_CTRL, -- AT803X_WOL_EN, 0); -- -- return ret; --} -- - static int at8031_config_intr(struct phy_device *phydev) - { - struct at803x_priv *priv = phydev->priv; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/phy/qcom/qca808x.c BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/qcom/qca808x.c ---- BPI-Router-Linux-kernel/drivers/net/phy/qcom/qca808x.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/qcom/qca808x.c 2025-10-22 13:53:56.591168775 -0400 -@@ -633,7 +633,7 @@ static struct phy_driver qca808x_driver[ - .handle_interrupt = at803x_handle_interrupt, - .get_tunable = at803x_get_tunable, - .set_tunable = at803x_set_tunable, -- .set_wol = at803x_set_wol, -+ .set_wol = at8031_set_wol, - .get_wol = at803x_get_wol, - .get_features = qca808x_get_features, - .config_aneg = qca808x_config_aneg, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/phy/qcom/qcom.h BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/qcom/qcom.h ---- BPI-Router-Linux-kernel/drivers/net/phy/qcom/qcom.h 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/qcom/qcom.h 2025-10-22 13:53:56.591168775 -0400 -@@ -172,6 +172,9 @@ - #define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B - #define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A - -+#define AT803X_PHY_MMD3_WOL_CTRL 0x8012 -+#define AT803X_WOL_EN BIT(5) -+ - #define AT803X_DEBUG_ADDR 0x1D - #define AT803X_DEBUG_DATA 0x1E - -@@ -215,6 +218,8 @@ int at803x_debug_reg_mask(struct phy_dev - int at803x_debug_reg_write(struct phy_device *phydev, u16 reg, u16 data); - int at803x_set_wol(struct phy_device *phydev, - struct ethtool_wolinfo *wol); -+int at8031_set_wol(struct phy_device *phydev, -+ struct ethtool_wolinfo *wol); - void at803x_get_wol(struct phy_device *phydev, - struct ethtool_wolinfo *wol); - int at803x_ack_interrupt(struct phy_device *phydev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/phy/qcom/qcom-phy-lib.c BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/qcom/qcom-phy-lib.c ---- BPI-Router-Linux-kernel/drivers/net/phy/qcom/qcom-phy-lib.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/qcom/qcom-phy-lib.c 2025-10-22 13:53:56.591168775 -0400 -@@ -115,6 +115,31 @@ int at803x_set_wol(struct phy_device *ph - } - EXPORT_SYMBOL_GPL(at803x_set_wol); - -+int at8031_set_wol(struct phy_device *phydev, -+ struct ethtool_wolinfo *wol) -+{ -+ int ret; -+ -+ /* First setup MAC address and enable WOL interrupt */ -+ ret = at803x_set_wol(phydev, wol); -+ if (ret) -+ return ret; -+ -+ if (wol->wolopts & WAKE_MAGIC) -+ /* Enable WOL function for 1588 */ -+ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, -+ AT803X_PHY_MMD3_WOL_CTRL, -+ 0, AT803X_WOL_EN); -+ else -+ /* Disable WoL function for 1588 */ -+ ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, -+ AT803X_PHY_MMD3_WOL_CTRL, -+ AT803X_WOL_EN, 0); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(at8031_set_wol); -+ - void at803x_get_wol(struct phy_device *phydev, - struct ethtool_wolinfo *wol) - { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/phy/realtek/realtek_main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/realtek/realtek_main.c ---- BPI-Router-Linux-kernel/drivers/net/phy/realtek/realtek_main.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/realtek/realtek_main.c 2025-10-22 13:53:56.591168775 -0400 -@@ -436,9 +436,15 @@ static irqreturn_t rtl8211f_handle_inter - - static void rtl8211f_get_wol(struct phy_device *dev, struct ethtool_wolinfo *wol) - { -+ int wol_events; -+ - wol->supported = WAKE_MAGIC; -- if (phy_read_paged(dev, RTL8211F_WOL_SETTINGS_PAGE, RTL8211F_WOL_SETTINGS_EVENTS) -- & RTL8211F_WOL_EVENT_MAGIC) -+ -+ wol_events = phy_read_paged(dev, RTL8211F_WOL_SETTINGS_PAGE, RTL8211F_WOL_SETTINGS_EVENTS); -+ if (wol_events < 0) -+ return; -+ -+ if (wol_events & RTL8211F_WOL_EVENT_MAGIC) - wol->wolopts = WAKE_MAGIC; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/phy/sfp.c BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/sfp.c ---- BPI-Router-Linux-kernel/drivers/net/phy/sfp.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/sfp.c 2025-10-22 13:53:56.591168775 -0400 -@@ -361,6 +361,11 @@ static void sfp_fixup_ignore_tx_fault(st - sfp->state_ignore_mask |= SFP_F_TX_FAULT; - } - -+static void sfp_fixup_ignore_hw(struct sfp *sfp, unsigned int mask) -+{ -+ sfp->state_hw_mask &= ~mask; -+} -+ - static void sfp_fixup_nokia(struct sfp *sfp) - { - sfp_fixup_long_startup(sfp); -@@ -409,7 +414,19 @@ static void sfp_fixup_halny_gsfp(struct - * these are possibly used for other purposes on this - * module, e.g. a serial port. - */ -- sfp->state_hw_mask &= ~(SFP_F_TX_FAULT | SFP_F_LOS); -+ sfp_fixup_ignore_hw(sfp, SFP_F_TX_FAULT | SFP_F_LOS); -+} -+ -+static void sfp_fixup_potron(struct sfp *sfp) -+{ -+ /* -+ * The TX_FAULT and LOS pins on this device are used for serial -+ * communication, so ignore them. Additionally, provide extra -+ * time for this device to fully start up. -+ */ -+ -+ sfp_fixup_long_startup(sfp); -+ sfp_fixup_ignore_hw(sfp, SFP_F_TX_FAULT | SFP_F_LOS); - } - - static void sfp_fixup_rollball_cc(struct sfp *sfp) -@@ -475,6 +492,9 @@ static const struct sfp_quirk sfp_quirks - SFP_QUIRK("ALCATELLUCENT", "3FE46541AA", sfp_quirk_2500basex, - sfp_fixup_nokia), - -+ // FLYPRO SFP-10GT-CS-30M uses Rollball protocol to talk to the PHY. -+ SFP_QUIRK_F("FLYPRO", "SFP-10GT-CS-30M", sfp_fixup_rollball), -+ - // Fiberstore SFP-10G-T doesn't identify as copper, uses the Rollball - // protocol to talk to the PHY and needs 4 sec wait before probing the - // PHY. -@@ -512,6 +532,8 @@ static const struct sfp_quirk sfp_quirks - SFP_QUIRK_F("Walsun", "HXSX-ATRC-1", sfp_fixup_fs_10gt), - SFP_QUIRK_F("Walsun", "HXSX-ATRI-1", sfp_fixup_fs_10gt), - -+ SFP_QUIRK_F("YV", "SFP+ONU-XGSPON", sfp_fixup_potron), -+ - // OEM SFP-GE-T is a 1000Base-T module with broken TX_FAULT indicator - SFP_QUIRK_F("OEM", "SFP-GE-T", sfp_fixup_ignore_tx_fault), - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/phy/smsc.c BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/smsc.c ---- BPI-Router-Linux-kernel/drivers/net/phy/smsc.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/phy/smsc.c 2025-10-22 13:53:56.591168775 -0400 -@@ -155,10 +155,29 @@ static int smsc_phy_reset(struct phy_dev - - static int lan87xx_config_aneg(struct phy_device *phydev) - { -- int rc; -+ u8 mdix_ctrl; - int val; -+ int rc; -+ -+ /* When auto-negotiation is disabled (forced mode), the PHY's -+ * Auto-MDIX will continue toggling the TX/RX pairs. -+ * -+ * To establish a stable link, we must select a fixed MDI mode. -+ * If the user has not specified a fixed MDI mode (i.e., mdix_ctrl is -+ * 'auto'), we default to ETH_TP_MDI. This choice of a ETH_TP_MDI mode -+ * mirrors the behavior the hardware would exhibit if the AUTOMDIX_EN -+ * strap were configured for a fixed MDI connection. -+ */ -+ if (phydev->autoneg == AUTONEG_DISABLE) { -+ if (phydev->mdix_ctrl == ETH_TP_MDI_AUTO) -+ mdix_ctrl = ETH_TP_MDI; -+ else -+ mdix_ctrl = phydev->mdix_ctrl; -+ } else { -+ mdix_ctrl = phydev->mdix_ctrl; -+ } - -- switch (phydev->mdix_ctrl) { -+ switch (mdix_ctrl) { - case ETH_TP_MDI: - val = SPECIAL_CTRL_STS_OVRRD_AMDIX_; - break; -@@ -167,7 +186,8 @@ static int lan87xx_config_aneg(struct ph - SPECIAL_CTRL_STS_AMDIX_STATE_; - break; - case ETH_TP_MDI_AUTO: -- val = SPECIAL_CTRL_STS_AMDIX_ENABLE_; -+ val = SPECIAL_CTRL_STS_OVRRD_AMDIX_ | -+ SPECIAL_CTRL_STS_AMDIX_ENABLE_; - break; - default: - return genphy_config_aneg(phydev); -@@ -183,7 +203,7 @@ static int lan87xx_config_aneg(struct ph - rc |= val; - phy_write(phydev, SPECIAL_CTRL_STS, rc); - -- phydev->mdix = phydev->mdix_ctrl; -+ phydev->mdix = mdix_ctrl; - return genphy_config_aneg(phydev); - } - -@@ -261,6 +281,33 @@ int lan87xx_read_status(struct phy_devic - } - EXPORT_SYMBOL_GPL(lan87xx_read_status); - -+static int lan87xx_phy_config_init(struct phy_device *phydev) -+{ -+ int rc; -+ -+ /* The LAN87xx PHY's initial MDI-X mode is determined by the AUTOMDIX_EN -+ * hardware strap, but the driver cannot read the strap's status. This -+ * creates an unpredictable initial state. -+ * -+ * To ensure consistent and reliable behavior across all boards, -+ * override the strap configuration on initialization and force the PHY -+ * into a known state with Auto-MDIX enabled, which is the expected -+ * default for modern hardware. -+ */ -+ rc = phy_modify(phydev, SPECIAL_CTRL_STS, -+ SPECIAL_CTRL_STS_OVRRD_AMDIX_ | -+ SPECIAL_CTRL_STS_AMDIX_ENABLE_ | -+ SPECIAL_CTRL_STS_AMDIX_STATE_, -+ SPECIAL_CTRL_STS_OVRRD_AMDIX_ | -+ SPECIAL_CTRL_STS_AMDIX_ENABLE_); -+ if (rc < 0) -+ return rc; -+ -+ phydev->mdix_ctrl = ETH_TP_MDI_AUTO; -+ -+ return smsc_phy_config_init(phydev); -+} -+ - static int lan874x_phy_config_init(struct phy_device *phydev) - { - u16 val; -@@ -695,7 +742,7 @@ static struct phy_driver smsc_phy_driver - - /* basic functions */ - .read_status = lan87xx_read_status, -- .config_init = smsc_phy_config_init, -+ .config_init = lan87xx_phy_config_init, - .soft_reset = smsc_phy_reset, - .config_aneg = lan87xx_config_aneg, - -@@ -738,6 +785,7 @@ static struct phy_driver smsc_phy_driver - - /* PHY_BASIC_FEATURES */ - -+ .flags = PHY_RST_AFTER_CLK_EN, - .probe = smsc_phy_probe, - - /* basic functions */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ppp/ppp_generic.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ppp/ppp_generic.c ---- BPI-Router-Linux-kernel/drivers/net/ppp/ppp_generic.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ppp/ppp_generic.c 2025-10-22 13:53:56.591168775 -0400 -@@ -33,6 +33,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1612,11 +1613,14 @@ static int ppp_fill_forward_path(struct - if (ppp->flags & SC_MULTILINK) - return -EOPNOTSUPP; - -- if (list_empty(&ppp->channels)) -+ pch = list_first_or_null_rcu(&ppp->channels, struct channel, clist); -+ if (!pch) -+ return -ENODEV; -+ -+ chan = READ_ONCE(pch->chan); -+ if (!chan) - return -ENODEV; - -- pch = list_first_entry(&ppp->channels, struct channel, clist); -- chan = pch->chan; - if (!chan->ops->fill_forward_path) - return -EOPNOTSUPP; - -@@ -1748,7 +1752,6 @@ pad_compress_skb(struct ppp *ppp, struct - */ - if (net_ratelimit()) - netdev_err(ppp->dev, "ppp: compressor dropped pkt\n"); -- kfree_skb(skb); - consume_skb(new_skb); - new_skb = NULL; - } -@@ -1850,9 +1853,10 @@ ppp_send_frame(struct ppp *ppp, struct s - "down - pkt dropped.\n"); - goto drop; - } -- skb = pad_compress_skb(ppp, skb); -- if (!skb) -+ new_skb = pad_compress_skb(ppp, skb); -+ if (!new_skb) - goto drop; -+ skb = new_skb; - } - - /* -@@ -2999,7 +3003,7 @@ ppp_unregister_channel(struct ppp_channe - */ - down_write(&pch->chan_sem); - spin_lock_bh(&pch->downl); -- pch->chan = NULL; -+ WRITE_ONCE(pch->chan, NULL); - spin_unlock_bh(&pch->downl); - up_write(&pch->chan_sem); - ppp_disconnect_channel(pch); -@@ -3509,7 +3513,7 @@ ppp_connect_channel(struct channel *pch, - hdrlen = pch->file.hdrlen + 2; /* for protocol bytes */ - if (hdrlen > ppp->dev->hard_header_len) - ppp->dev->hard_header_len = hdrlen; -- list_add_tail(&pch->clist, &ppp->channels); -+ list_add_tail_rcu(&pch->clist, &ppp->channels); - ++ppp->n_channels; - pch->ppp = ppp; - refcount_inc(&ppp->file.refcnt); -@@ -3539,10 +3543,11 @@ ppp_disconnect_channel(struct channel *p - if (ppp) { - /* remove it from the ppp unit's list */ - ppp_lock(ppp); -- list_del(&pch->clist); -+ list_del_rcu(&pch->clist); - if (--ppp->n_channels == 0) - wake_up_interruptible(&ppp->file.rwait); - ppp_unlock(ppp); -+ synchronize_net(); - if (refcount_dec_and_test(&ppp->file.refcnt)) - ppp_destroy_interface(ppp); - err = 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/ppp/pptp.c BPI-Router-Linux-kernel-6.16.12/drivers/net/ppp/pptp.c ---- BPI-Router-Linux-kernel/drivers/net/ppp/pptp.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/ppp/pptp.c 2025-10-22 13:53:56.591168775 -0400 -@@ -159,19 +159,17 @@ static int pptp_xmit(struct ppp_channel - int len; - unsigned char *data; - __u32 seq_recv; -- -- - struct rtable *rt; - struct net_device *tdev; - struct iphdr *iph; - int max_headroom; - - if (sk_pppox(po)->sk_state & PPPOX_DEAD) -- goto tx_error; -+ goto tx_drop; - - rt = pptp_route_output(po, &fl4); - if (IS_ERR(rt)) -- goto tx_error; -+ goto tx_drop; - - tdev = rt->dst.dev; - -@@ -179,16 +177,20 @@ static int pptp_xmit(struct ppp_channel - - if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) { - struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); -- if (!new_skb) { -- ip_rt_put(rt); -+ -+ if (!new_skb) - goto tx_error; -- } -+ - if (skb->sk) - skb_set_owner_w(new_skb, skb->sk); - consume_skb(skb); - skb = new_skb; - } - -+ /* Ensure we can safely access protocol field and LCP code */ -+ if (!pskb_may_pull(skb, 3)) -+ goto tx_error; -+ - data = skb->data; - islcp = ((data[0] << 8) + data[1]) == PPP_LCP && 1 <= data[2] && data[2] <= 7; - -@@ -262,6 +264,8 @@ static int pptp_xmit(struct ppp_channel - return 1; - - tx_error: -+ ip_rt_put(rt); -+tx_drop: - kfree_skb(skb); - return 1; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/team/team_core.c BPI-Router-Linux-kernel-6.16.12/drivers/net/team/team_core.c ---- BPI-Router-Linux-kernel/drivers/net/team/team_core.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/team/team_core.c 2025-10-22 13:53:56.591168775 -0400 -@@ -933,7 +933,7 @@ static bool team_port_find(const struct - * Enable/disable port by adding to enabled port hashlist and setting - * port->index (Might be racy so reader could see incorrect ifindex when - * processing a flying packet, but that is not a problem). Write guarded -- * by team->lock. -+ * by RTNL. - */ - static void team_port_enable(struct team *team, - struct team_port *port) -@@ -1660,8 +1660,6 @@ static int team_init(struct net_device * - goto err_options_register; - netif_carrier_off(dev); - -- lockdep_register_key(&team->team_lock_key); -- __mutex_init(&team->lock, "team->team_lock_key", &team->team_lock_key); - netdev_lockdep_set_classes(dev); - - return 0; -@@ -1682,7 +1680,8 @@ static void team_uninit(struct net_devic - struct team_port *port; - struct team_port *tmp; - -- mutex_lock(&team->lock); -+ ASSERT_RTNL(); -+ - list_for_each_entry_safe(port, tmp, &team->port_list, list) - team_port_del(team, port->dev); - -@@ -1691,9 +1690,7 @@ static void team_uninit(struct net_devic - team_mcast_rejoin_fini(team); - team_notify_peers_fini(team); - team_queue_override_fini(team); -- mutex_unlock(&team->lock); - netdev_change_features(dev); -- lockdep_unregister_key(&team->team_lock_key); - } - - static void team_destructor(struct net_device *dev) -@@ -1778,7 +1775,8 @@ static void team_change_rx_flags(struct - struct team_port *port; - int inc; - -- mutex_lock(&team->lock); -+ ASSERT_RTNL(); -+ - list_for_each_entry(port, &team->port_list, list) { - if (change & IFF_PROMISC) { - inc = dev->flags & IFF_PROMISC ? 1 : -1; -@@ -1789,7 +1787,6 @@ static void team_change_rx_flags(struct - dev_set_allmulti(port->dev, inc); - } - } -- mutex_unlock(&team->lock); - } - - static void team_set_rx_mode(struct net_device *dev) -@@ -1811,14 +1808,14 @@ static int team_set_mac_address(struct n - struct team *team = netdev_priv(dev); - struct team_port *port; - -+ ASSERT_RTNL(); -+ - if (dev->type == ARPHRD_ETHER && !is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - dev_addr_set(dev, addr->sa_data); -- mutex_lock(&team->lock); - list_for_each_entry(port, &team->port_list, list) - if (team->ops.port_change_dev_addr) - team->ops.port_change_dev_addr(team, port); -- mutex_unlock(&team->lock); - return 0; - } - -@@ -1828,11 +1825,8 @@ static int team_change_mtu(struct net_de - struct team_port *port; - int err; - -- /* -- * Alhough this is reader, it's guarded by team lock. It's not possible -- * to traverse list in reverse under rcu_read_lock -- */ -- mutex_lock(&team->lock); -+ ASSERT_RTNL(); -+ - team->port_mtu_change_allowed = true; - list_for_each_entry(port, &team->port_list, list) { - err = dev_set_mtu(port->dev, new_mtu); -@@ -1843,7 +1837,6 @@ static int team_change_mtu(struct net_de - } - } - team->port_mtu_change_allowed = false; -- mutex_unlock(&team->lock); - - WRITE_ONCE(dev->mtu, new_mtu); - -@@ -1853,7 +1846,6 @@ unwind: - list_for_each_entry_continue_reverse(port, &team->port_list, list) - dev_set_mtu(port->dev, dev->mtu); - team->port_mtu_change_allowed = false; -- mutex_unlock(&team->lock); - - return err; - } -@@ -1903,24 +1895,19 @@ static int team_vlan_rx_add_vid(struct n - struct team_port *port; - int err; - -- /* -- * Alhough this is reader, it's guarded by team lock. It's not possible -- * to traverse list in reverse under rcu_read_lock -- */ -- mutex_lock(&team->lock); -+ ASSERT_RTNL(); -+ - list_for_each_entry(port, &team->port_list, list) { - err = vlan_vid_add(port->dev, proto, vid); - if (err) - goto unwind; - } -- mutex_unlock(&team->lock); - - return 0; - - unwind: - list_for_each_entry_continue_reverse(port, &team->port_list, list) - vlan_vid_del(port->dev, proto, vid); -- mutex_unlock(&team->lock); - - return err; - } -@@ -1930,10 +1917,10 @@ static int team_vlan_rx_kill_vid(struct - struct team *team = netdev_priv(dev); - struct team_port *port; - -- mutex_lock(&team->lock); -+ ASSERT_RTNL(); -+ - list_for_each_entry(port, &team->port_list, list) - vlan_vid_del(port->dev, proto, vid); -- mutex_unlock(&team->lock); - - return 0; - } -@@ -1955,9 +1942,9 @@ static void team_netpoll_cleanup(struct - { - struct team *team = netdev_priv(dev); - -- mutex_lock(&team->lock); -+ ASSERT_RTNL(); -+ - __team_netpoll_cleanup(team); -- mutex_unlock(&team->lock); - } - - static int team_netpoll_setup(struct net_device *dev) -@@ -1966,7 +1953,8 @@ static int team_netpoll_setup(struct net - struct team_port *port; - int err = 0; - -- mutex_lock(&team->lock); -+ ASSERT_RTNL(); -+ - list_for_each_entry(port, &team->port_list, list) { - err = __team_port_enable_netpoll(port); - if (err) { -@@ -1974,7 +1962,6 @@ static int team_netpoll_setup(struct net - break; - } - } -- mutex_unlock(&team->lock); - return err; - } - #endif -@@ -1985,9 +1972,9 @@ static int team_add_slave(struct net_dev - struct team *team = netdev_priv(dev); - int err; - -- mutex_lock(&team->lock); -+ ASSERT_RTNL(); -+ - err = team_port_add(team, port_dev, extack); -- mutex_unlock(&team->lock); - - if (!err) - netdev_change_features(dev); -@@ -2000,18 +1987,13 @@ static int team_del_slave(struct net_dev - struct team *team = netdev_priv(dev); - int err; - -- mutex_lock(&team->lock); -+ ASSERT_RTNL(); -+ - err = team_port_del(team, port_dev); -- mutex_unlock(&team->lock); - - if (err) - return err; - -- if (netif_is_team_master(port_dev)) { -- lockdep_unregister_key(&team->team_lock_key); -- lockdep_register_key(&team->team_lock_key); -- lockdep_set_class(&team->lock, &team->team_lock_key); -- } - netdev_change_features(dev); - - return err; -@@ -2304,9 +2286,10 @@ err_msg_put: - static struct team *team_nl_team_get(struct genl_info *info) - { - struct net *net = genl_info_net(info); -- int ifindex; - struct net_device *dev; -- struct team *team; -+ int ifindex; -+ -+ ASSERT_RTNL(); - - if (!info->attrs[TEAM_ATTR_TEAM_IFINDEX]) - return NULL; -@@ -2318,14 +2301,11 @@ static struct team *team_nl_team_get(str - return NULL; - } - -- team = netdev_priv(dev); -- mutex_lock(&team->lock); -- return team; -+ return netdev_priv(dev); - } - - static void team_nl_team_put(struct team *team) - { -- mutex_unlock(&team->lock); - dev_put(team->dev); - } - -@@ -2515,9 +2495,13 @@ int team_nl_options_get_doit(struct sk_b - int err; - LIST_HEAD(sel_opt_inst_list); - -+ rtnl_lock(); -+ - team = team_nl_team_get(info); -- if (!team) -- return -EINVAL; -+ if (!team) { -+ err = -EINVAL; -+ goto rtnl_unlock; -+ } - - list_for_each_entry(opt_inst, &team->option_inst_list, list) - list_add_tail(&opt_inst->tmp_list, &sel_opt_inst_list); -@@ -2527,6 +2511,9 @@ int team_nl_options_get_doit(struct sk_b - - team_nl_team_put(team); - -+rtnl_unlock: -+ rtnl_unlock(); -+ - return err; - } - -@@ -2805,15 +2792,22 @@ int team_nl_port_list_get_doit(struct sk - struct team *team; - int err; - -+ rtnl_lock(); -+ - team = team_nl_team_get(info); -- if (!team) -- return -EINVAL; -+ if (!team) { -+ err = -EINVAL; -+ goto rtnl_unlock; -+ } - - err = team_nl_send_port_list_get(team, info->snd_portid, info->snd_seq, - NLM_F_ACK, team_nl_send_unicast, NULL); - - team_nl_team_put(team); - -+rtnl_unlock: -+ rtnl_unlock(); -+ - return err; - } - -@@ -2961,11 +2955,9 @@ static void __team_port_change_port_remo - - static void team_port_change_check(struct team_port *port, bool linkup) - { -- struct team *team = port->team; -+ ASSERT_RTNL(); - -- mutex_lock(&team->lock); - __team_port_change_check(port, linkup); -- mutex_unlock(&team->lock); - } - - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/team/team_mode_activebackup.c BPI-Router-Linux-kernel-6.16.12/drivers/net/team/team_mode_activebackup.c ---- BPI-Router-Linux-kernel/drivers/net/team/team_mode_activebackup.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/team/team_mode_activebackup.c 2025-10-22 13:53:56.591168775 -0400 -@@ -67,8 +67,7 @@ static void ab_active_port_get(struct te - { - struct team_port *active_port; - -- active_port = rcu_dereference_protected(ab_priv(team)->active_port, -- lockdep_is_held(&team->lock)); -+ active_port = rtnl_dereference(ab_priv(team)->active_port); - if (active_port) - ctx->data.u32_val = active_port->dev->ifindex; - else -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/team/team_mode_loadbalance.c BPI-Router-Linux-kernel-6.16.12/drivers/net/team/team_mode_loadbalance.c ---- BPI-Router-Linux-kernel/drivers/net/team/team_mode_loadbalance.c 2025-10-22 13:53:23.367328397 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/team/team_mode_loadbalance.c 2025-10-22 13:53:56.595168756 -0400 -@@ -301,8 +301,7 @@ static int lb_bpf_func_set(struct team * - if (lb_priv->ex->orig_fprog) { - /* Clear old filter data */ - __fprog_destroy(lb_priv->ex->orig_fprog); -- orig_fp = rcu_dereference_protected(lb_priv->fp, -- lockdep_is_held(&team->lock)); -+ orig_fp = rtnl_dereference(lb_priv->fp); - } - - rcu_assign_pointer(lb_priv->fp, fp); -@@ -324,8 +323,7 @@ static void lb_bpf_func_free(struct team - return; - - __fprog_destroy(lb_priv->ex->orig_fprog); -- fp = rcu_dereference_protected(lb_priv->fp, -- lockdep_is_held(&team->lock)); -+ fp = rtnl_dereference(lb_priv->fp); - bpf_prog_destroy(fp); - } - -@@ -335,8 +333,7 @@ static void lb_tx_method_get(struct team - lb_select_tx_port_func_t *func; - char *name; - -- func = rcu_dereference_protected(lb_priv->select_tx_port_func, -- lockdep_is_held(&team->lock)); -+ func = rtnl_dereference(lb_priv->select_tx_port_func); - name = lb_select_tx_port_get_name(func); - BUG_ON(!name); - ctx->data.str_val = name; -@@ -478,7 +475,7 @@ static void lb_stats_refresh(struct work - team = lb_priv_ex->team; - lb_priv = get_lb_priv(team); - -- if (!mutex_trylock(&team->lock)) { -+ if (!rtnl_trylock()) { - schedule_delayed_work(&lb_priv_ex->stats.refresh_dw, 0); - return; - } -@@ -515,7 +512,7 @@ static void lb_stats_refresh(struct work - schedule_delayed_work(&lb_priv_ex->stats.refresh_dw, - (lb_priv_ex->stats.refresh_interval * HZ) / 10); - -- mutex_unlock(&team->lock); -+ rtnl_unlock(); - } - - static void lb_stats_refresh_interval_get(struct team *team, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/thunderbolt/main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/thunderbolt/main.c ---- BPI-Router-Linux-kernel/drivers/net/thunderbolt/main.c 2025-10-22 13:53:23.371328378 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/thunderbolt/main.c 2025-10-22 13:53:56.595168756 -0400 -@@ -396,9 +396,9 @@ static void tbnet_tear_down(struct tbnet - - ret = tb_xdomain_disable_paths(net->xd, - net->local_transmit_path, -- net->rx_ring.ring->hop, -+ net->tx_ring.ring->hop, - net->remote_transmit_path, -- net->tx_ring.ring->hop); -+ net->rx_ring.ring->hop); - if (ret) - netdev_warn(net->dev, "failed to disable DMA paths\n"); - -@@ -662,9 +662,9 @@ static void tbnet_connected_work(struct - goto err_free_rx_buffers; - - ret = tb_xdomain_enable_paths(net->xd, net->local_transmit_path, -- net->rx_ring.ring->hop, -+ net->tx_ring.ring->hop, - net->remote_transmit_path, -- net->tx_ring.ring->hop); -+ net->rx_ring.ring->hop); - if (ret) { - netdev_err(net->dev, "failed to enable DMA paths\n"); - goto err_free_tx_buffers; -@@ -924,8 +924,12 @@ static int tbnet_open(struct net_device - - netif_carrier_off(dev); - -- ring = tb_ring_alloc_tx(xd->tb->nhi, -1, TBNET_RING_SIZE, -- RING_FLAG_FRAME); -+ flags = RING_FLAG_FRAME; -+ /* Only enable full E2E if the other end supports it too */ -+ if (tbnet_e2e && net->svc->prtcstns & TBNET_E2E) -+ flags |= RING_FLAG_E2E; -+ -+ ring = tb_ring_alloc_tx(xd->tb->nhi, -1, TBNET_RING_SIZE, flags); - if (!ring) { - netdev_err(dev, "failed to allocate Tx ring\n"); - return -ENOMEM; -@@ -944,11 +948,6 @@ static int tbnet_open(struct net_device - sof_mask = BIT(TBIP_PDF_FRAME_START); - eof_mask = BIT(TBIP_PDF_FRAME_END); - -- flags = RING_FLAG_FRAME; -- /* Only enable full E2E if the other end supports it too */ -- if (tbnet_e2e && net->svc->prtcstns & TBNET_E2E) -- flags |= RING_FLAG_E2E; -- - ring = tb_ring_alloc_rx(xd->tb->nhi, -1, TBNET_RING_SIZE, flags, - net->tx_ring.ring->hop, sof_mask, - eof_mask, tbnet_start_poll, net); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/tun.c BPI-Router-Linux-kernel-6.16.12/drivers/net/tun.c ---- BPI-Router-Linux-kernel/drivers/net/tun.c 2025-10-22 13:53:23.371328378 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/tun.c 2025-10-22 13:53:56.595168756 -0400 -@@ -1863,6 +1863,9 @@ static ssize_t tun_get_user(struct tun_s - local_bh_enable(); - goto unlock_frags; - } -+ -+ if (frags && skb != tfile->napi.skb) -+ tfile->napi.skb = skb; - } - rcu_read_unlock(); - local_bh_enable(); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/usb/asix_devices.c BPI-Router-Linux-kernel-6.16.12/drivers/net/usb/asix_devices.c ---- BPI-Router-Linux-kernel/drivers/net/usb/asix_devices.c 2025-10-22 13:53:23.371328378 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/usb/asix_devices.c 2025-10-22 13:53:56.595168756 -0400 -@@ -676,6 +676,7 @@ static int ax88772_init_mdio(struct usbn - priv->mdio->read = &asix_mdio_bus_read; - priv->mdio->write = &asix_mdio_bus_write; - priv->mdio->name = "Asix MDIO Bus"; -+ priv->mdio->phy_mask = ~(BIT(priv->phy_addr & 0x1f) | BIT(AX_EMBD_PHY_ADDR)); - /* mii bus name is usb-- */ - snprintf(priv->mdio->id, MII_BUS_ID_SIZE, "usb-%03d:%03d", - dev->udev->bus->busnum, dev->udev->devnum); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/usb/cdc_ncm.c BPI-Router-Linux-kernel-6.16.12/drivers/net/usb/cdc_ncm.c ---- BPI-Router-Linux-kernel/drivers/net/usb/cdc_ncm.c 2025-10-22 13:53:23.371328378 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/usb/cdc_ncm.c 2025-10-22 13:53:56.595168756 -0400 -@@ -892,6 +892,10 @@ int cdc_ncm_bind_common(struct usbnet *d - } - } - -+ if (ctx->func_desc) -+ ctx->filtering_supported = !!(ctx->func_desc->bmNetworkCapabilities -+ & USB_CDC_NCM_NCAP_ETH_FILTER); -+ - iface_no = ctx->data->cur_altsetting->desc.bInterfaceNumber; - - /* Device-specific flags */ -@@ -1898,6 +1902,14 @@ static void cdc_ncm_status(struct usbnet - } - } - -+static void cdc_ncm_update_filter(struct usbnet *dev) -+{ -+ struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0]; -+ -+ if (ctx->filtering_supported) -+ usbnet_cdc_update_filter(dev); -+} -+ - static const struct driver_info cdc_ncm_info = { - .description = "CDC NCM (NO ZLP)", - .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET -@@ -1908,7 +1920,7 @@ static const struct driver_info cdc_ncm_ - .status = cdc_ncm_status, - .rx_fixup = cdc_ncm_rx_fixup, - .tx_fixup = cdc_ncm_tx_fixup, -- .set_rx_mode = usbnet_cdc_update_filter, -+ .set_rx_mode = cdc_ncm_update_filter, - }; - - /* Same as cdc_ncm_info, but with FLAG_SEND_ZLP */ -@@ -1922,7 +1934,7 @@ static const struct driver_info cdc_ncm_ - .status = cdc_ncm_status, - .rx_fixup = cdc_ncm_rx_fixup, - .tx_fixup = cdc_ncm_tx_fixup, -- .set_rx_mode = usbnet_cdc_update_filter, -+ .set_rx_mode = cdc_ncm_update_filter, - }; - - /* Same as cdc_ncm_info, but with FLAG_SEND_ZLP */ -@@ -1964,7 +1976,7 @@ static const struct driver_info wwan_inf - .status = cdc_ncm_status, - .rx_fixup = cdc_ncm_rx_fixup, - .tx_fixup = cdc_ncm_tx_fixup, -- .set_rx_mode = usbnet_cdc_update_filter, -+ .set_rx_mode = cdc_ncm_update_filter, - }; - - /* Same as wwan_info, but with FLAG_NOARP */ -@@ -1978,7 +1990,7 @@ static const struct driver_info wwan_noa - .status = cdc_ncm_status, - .rx_fixup = cdc_ncm_rx_fixup, - .tx_fixup = cdc_ncm_tx_fixup, -- .set_rx_mode = usbnet_cdc_update_filter, -+ .set_rx_mode = cdc_ncm_update_filter, - }; - - static const struct usb_device_id cdc_devs[] = { -@@ -2073,6 +2085,13 @@ static const struct usb_device_id cdc_de - USB_CLASS_COMM, - USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE), - .driver_info = (unsigned long)&wwan_info, -+ }, -+ -+ /* Intel modem (label from OEM reads Fibocom L850-GL) */ -+ { USB_DEVICE_AND_INTERFACE_INFO(0x8087, 0x095a, -+ USB_CLASS_COMM, -+ USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE), -+ .driver_info = (unsigned long)&wwan_info, - }, - - /* DisplayLink docking stations */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/usb/lan78xx.c BPI-Router-Linux-kernel-6.16.12/drivers/net/usb/lan78xx.c ---- BPI-Router-Linux-kernel/drivers/net/usb/lan78xx.c 2025-10-22 13:53:23.371328378 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/usb/lan78xx.c 2025-10-22 13:53:56.595168756 -0400 -@@ -4567,8 +4567,6 @@ static void lan78xx_disconnect(struct us - if (!dev) - return; - -- netif_napi_del(&dev->napi); -- - udev = interface_to_usbdev(intf); - net = dev->net; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/usb/qmi_wwan.c BPI-Router-Linux-kernel-6.16.12/drivers/net/usb/qmi_wwan.c ---- BPI-Router-Linux-kernel/drivers/net/usb/qmi_wwan.c 2025-10-22 13:53:23.371328378 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/usb/qmi_wwan.c 2025-10-22 13:53:56.595168756 -0400 -@@ -1355,12 +1355,16 @@ static const struct usb_device_id produc - {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ - {QMI_FIXED_INTF(0x2357, 0x9000, 4)}, /* TP-LINK MA260 */ - {QMI_QUIRK_SET_DTR(0x1bc7, 0x1031, 3)}, /* Telit LE910C1-EUX */ -+ {QMI_QUIRK_SET_DTR(0x1bc7, 0x1034, 2)}, /* Telit LE910C4-WWX */ -+ {QMI_QUIRK_SET_DTR(0x1bc7, 0x1037, 4)}, /* Telit LE910C4-WWX */ -+ {QMI_QUIRK_SET_DTR(0x1bc7, 0x1038, 3)}, /* Telit LE910C4-WWX */ - {QMI_QUIRK_SET_DTR(0x1bc7, 0x103a, 0)}, /* Telit LE910C4-WWX */ - {QMI_QUIRK_SET_DTR(0x1bc7, 0x1040, 2)}, /* Telit LE922A */ - {QMI_QUIRK_SET_DTR(0x1bc7, 0x1050, 2)}, /* Telit FN980 */ - {QMI_QUIRK_SET_DTR(0x1bc7, 0x1057, 2)}, /* Telit FN980 */ - {QMI_QUIRK_SET_DTR(0x1bc7, 0x1060, 2)}, /* Telit LN920 */ - {QMI_QUIRK_SET_DTR(0x1bc7, 0x1070, 2)}, /* Telit FN990A */ -+ {QMI_QUIRK_SET_DTR(0x1bc7, 0x1077, 2)}, /* Telit FN990A w/audio */ - {QMI_QUIRK_SET_DTR(0x1bc7, 0x1080, 2)}, /* Telit FE990A */ - {QMI_QUIRK_SET_DTR(0x1bc7, 0x10a0, 0)}, /* Telit FN920C04 */ - {QMI_QUIRK_SET_DTR(0x1bc7, 0x10a4, 0)}, /* Telit FN920C04 */ -@@ -1426,6 +1430,7 @@ static const struct usb_device_id produc - {QMI_QUIRK_SET_DTR(0x22de, 0x9051, 2)}, /* Hucom Wireless HM-211S/K */ - {QMI_FIXED_INTF(0x22de, 0x9061, 3)}, /* WeTelecom WPD-600N */ - {QMI_QUIRK_SET_DTR(0x1e0e, 0x9001, 5)}, /* SIMCom 7100E, 7230E, 7600E ++ */ -+ {QMI_QUIRK_SET_DTR(0x1e0e, 0x9071, 3)}, /* SIMCom 8230C ++ */ - {QMI_QUIRK_SET_DTR(0x2c7c, 0x0121, 4)}, /* Quectel EC21 Mini PCIe */ - {QMI_QUIRK_SET_DTR(0x2c7c, 0x0191, 4)}, /* Quectel EG91 */ - {QMI_QUIRK_SET_DTR(0x2c7c, 0x0195, 4)}, /* Quectel EG95 */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/usb/r8152.c BPI-Router-Linux-kernel-6.16.12/drivers/net/usb/r8152.c ---- BPI-Router-Linux-kernel/drivers/net/usb/r8152.c 2025-10-22 13:53:23.371328378 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/usb/r8152.c 2025-10-22 13:53:56.595168756 -0400 -@@ -10054,6 +10054,7 @@ static const struct usb_device_id rtl815 - { USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041) }, - { USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff) }, - { USB_DEVICE(VENDOR_ID_TPLINK, 0x0601) }, -+ { USB_DEVICE(VENDOR_ID_TPLINK, 0x0602) }, - { USB_DEVICE(VENDOR_ID_DLINK, 0xb301) }, - { USB_DEVICE(VENDOR_ID_DELL, 0xb097) }, - { USB_DEVICE(VENDOR_ID_ASUS, 0x1976) }, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/usb/sierra_net.c BPI-Router-Linux-kernel-6.16.12/drivers/net/usb/sierra_net.c ---- BPI-Router-Linux-kernel/drivers/net/usb/sierra_net.c 2025-10-22 13:53:23.371328378 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/usb/sierra_net.c 2025-10-22 13:53:56.595168756 -0400 -@@ -689,6 +689,10 @@ static int sierra_net_bind(struct usbnet - status); - return -ENODEV; - } -+ if (!dev->status) { -+ dev_err(&dev->udev->dev, "No status endpoint found"); -+ return -ENODEV; -+ } - /* Initialize sierra private data */ - priv = kzalloc(sizeof *priv, GFP_KERNEL); - if (!priv) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/usb/usbnet.c BPI-Router-Linux-kernel-6.16.12/drivers/net/usb/usbnet.c ---- BPI-Router-Linux-kernel/drivers/net/usb/usbnet.c 2025-10-22 13:53:23.371328378 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/usb/usbnet.c 2025-10-22 13:53:56.595168756 -0400 -@@ -1113,6 +1113,9 @@ static void __handle_link_change(struct - if (!test_bit(EVENT_DEV_OPEN, &dev->flags)) - return; - -+ if (test_and_clear_bit(EVENT_LINK_CARRIER_ON, &dev->flags)) -+ netif_carrier_on(dev->net); -+ - if (!netif_carrier_ok(dev->net)) { - /* kill URBs for reading packets to save bus bandwidth */ - unlink_urbs(dev, &dev->rxq); -@@ -2009,10 +2012,12 @@ EXPORT_SYMBOL(usbnet_manage_power); - void usbnet_link_change(struct usbnet *dev, bool link, bool need_reset) - { - /* update link after link is reseted */ -- if (link && !need_reset) -- netif_carrier_on(dev->net); -- else -+ if (link && !need_reset) { -+ set_bit(EVENT_LINK_CARRIER_ON, &dev->flags); -+ } else { -+ clear_bit(EVENT_LINK_CARRIER_ON, &dev->flags); - netif_carrier_off(dev->net); -+ } - - if (need_reset && link) - usbnet_defer_kevent(dev, EVENT_LINK_RESET); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/veth.c BPI-Router-Linux-kernel-6.16.12/drivers/net/veth.c ---- BPI-Router-Linux-kernel/drivers/net/veth.c 2025-10-22 13:53:23.371328378 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/veth.c 2025-10-22 13:53:56.595168756 -0400 -@@ -909,7 +909,7 @@ static int veth_xdp_rcv(struct veth_rq * - - /* NAPI functions as RCU section */ - peer_dev = rcu_dereference_check(priv->peer, rcu_read_lock_bh_held()); -- peer_txq = netdev_get_tx_queue(peer_dev, queue_idx); -+ peer_txq = peer_dev ? netdev_get_tx_queue(peer_dev, queue_idx) : NULL; - - for (i = 0; i < budget; i++) { - void *ptr = __ptr_ring_consume(&rq->xdp_ring); -@@ -959,7 +959,7 @@ static int veth_xdp_rcv(struct veth_rq * - rq->stats.vs.xdp_packets += done; - u64_stats_update_end(&rq->stats.syncp); - -- if (unlikely(netif_tx_queue_stopped(peer_txq))) -+ if (peer_txq && unlikely(netif_tx_queue_stopped(peer_txq))) - netif_tx_wake_queue(peer_txq); - - return done; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/virtio_net.c BPI-Router-Linux-kernel-6.16.12/drivers/net/virtio_net.c ---- BPI-Router-Linux-kernel/drivers/net/virtio_net.c 2025-10-22 13:53:23.371328378 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/virtio_net.c 2025-10-22 13:53:56.595168756 -0400 -@@ -778,6 +778,26 @@ static unsigned int mergeable_ctx_to_tru - return (unsigned long)mrg_ctx & ((1 << MRG_CTX_HEADER_SHIFT) - 1); - } - -+static int check_mergeable_len(struct net_device *dev, void *mrg_ctx, -+ unsigned int len) -+{ -+ unsigned int headroom, tailroom, room, truesize; -+ -+ truesize = mergeable_ctx_to_truesize(mrg_ctx); -+ headroom = mergeable_ctx_to_headroom(mrg_ctx); -+ tailroom = headroom ? sizeof(struct skb_shared_info) : 0; -+ room = SKB_DATA_ALIGN(headroom + tailroom); -+ -+ if (len > truesize - room) { -+ pr_debug("%s: rx error: len %u exceeds truesize %lu\n", -+ dev->name, len, (unsigned long)(truesize - room)); -+ DEV_STATS_INC(dev, rx_length_errors); -+ return -1; -+ } -+ -+ return 0; -+} -+ - static struct sk_buff *virtnet_build_skb(void *buf, unsigned int buflen, - unsigned int headroom, - unsigned int len) -@@ -1084,7 +1104,7 @@ static bool tx_may_stop(struct virtnet_i - * Since most packets only take 1 or 2 ring slots, stopping the queue - * early means 16 slots are typically wasted. - */ -- if (sq->vq->num_free < 2+MAX_SKB_FRAGS) { -+ if (sq->vq->num_free < MAX_SKB_FRAGS + 2) { - struct netdev_queue *txq = netdev_get_tx_queue(dev, qnum); - - netif_tx_stop_queue(txq); -@@ -1116,7 +1136,7 @@ static void check_sq_full_and_disable(st - } else if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) { - /* More just got used, free them then recheck. */ - free_old_xmit(sq, txq, false); -- if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) { -+ if (sq->vq->num_free >= MAX_SKB_FRAGS + 2) { - netif_start_subqueue(dev, qnum); - u64_stats_update_begin(&sq->stats.syncp); - u64_stats_inc(&sq->stats.wake); -@@ -1127,15 +1147,29 @@ static void check_sq_full_and_disable(st - } - } - -+/* Note that @len is the length of received data without virtio header */ - static struct xdp_buff *buf_to_xdp(struct virtnet_info *vi, -- struct receive_queue *rq, void *buf, u32 len) -+ struct receive_queue *rq, void *buf, -+ u32 len, bool first_buf) - { - struct xdp_buff *xdp; - u32 bufsize; - - xdp = (struct xdp_buff *)buf; - -- bufsize = xsk_pool_get_rx_frame_size(rq->xsk_pool) + vi->hdr_len; -+ /* In virtnet_add_recvbuf_xsk, we use part of XDP_PACKET_HEADROOM for -+ * virtio header and ask the vhost to fill data from -+ * hard_start + XDP_PACKET_HEADROOM - vi->hdr_len -+ * The first buffer has virtio header so the remaining region for frame -+ * data is -+ * xsk_pool_get_rx_frame_size() -+ * While other buffers than the first one do not have virtio header, so -+ * the maximum frame data's length can be -+ * xsk_pool_get_rx_frame_size() + vi->hdr_len -+ */ -+ bufsize = xsk_pool_get_rx_frame_size(rq->xsk_pool); -+ if (!first_buf) -+ bufsize += vi->hdr_len; - - if (unlikely(len > bufsize)) { - pr_debug("%s: rx error: len %u exceeds truesize %u\n", -@@ -1260,7 +1294,7 @@ static int xsk_append_merge_buffer(struc - - u64_stats_add(&stats->bytes, len); - -- xdp = buf_to_xdp(vi, rq, buf, len); -+ xdp = buf_to_xdp(vi, rq, buf, len, false); - if (!xdp) - goto err; - -@@ -1358,7 +1392,7 @@ static void virtnet_receive_xsk_buf(stru - - u64_stats_add(&stats->bytes, len); - -- xdp = buf_to_xdp(vi, rq, buf, len); -+ xdp = buf_to_xdp(vi, rq, buf, len, true); - if (!xdp) - return; - -@@ -1797,7 +1831,8 @@ static unsigned int virtnet_get_headroom - * across multiple buffers (num_buf > 1), and we make sure buffers - * have enough headroom. - */ --static struct page *xdp_linearize_page(struct receive_queue *rq, -+static struct page *xdp_linearize_page(struct net_device *dev, -+ struct receive_queue *rq, - int *num_buf, - struct page *p, - int offset, -@@ -1817,18 +1852,27 @@ static struct page *xdp_linearize_page(s - memcpy(page_address(page) + page_off, page_address(p) + offset, *len); - page_off += *len; - -+ /* Only mergeable mode can go inside this while loop. In small mode, -+ * *num_buf == 1, so it cannot go inside. -+ */ - while (--*num_buf) { - unsigned int buflen; - void *buf; -+ void *ctx; - int off; - -- buf = virtnet_rq_get_buf(rq, &buflen, NULL); -+ buf = virtnet_rq_get_buf(rq, &buflen, &ctx); - if (unlikely(!buf)) - goto err_buf; - - p = virt_to_head_page(buf); - off = buf - page_address(p); - -+ if (check_mergeable_len(dev, ctx, buflen)) { -+ put_page(p); -+ goto err_buf; -+ } -+ - /* guard against a misconfigured or uncooperative backend that - * is sending packet larger than the MTU. - */ -@@ -1917,7 +1961,7 @@ static struct sk_buff *receive_small_xdp - headroom = vi->hdr_len + header_offset; - buflen = SKB_DATA_ALIGN(GOOD_PACKET_LEN + headroom) + - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); -- xdp_page = xdp_linearize_page(rq, &num_buf, page, -+ xdp_page = xdp_linearize_page(dev, rq, &num_buf, page, - offset, header_offset, - &tlen); - if (!xdp_page) -@@ -2126,10 +2170,9 @@ static int virtnet_build_xdp_buff_mrg(st - struct virtnet_rq_stats *stats) - { - struct virtio_net_hdr_mrg_rxbuf *hdr = buf; -- unsigned int headroom, tailroom, room; -- unsigned int truesize, cur_frag_size; - struct skb_shared_info *shinfo; - unsigned int xdp_frags_truesz = 0; -+ unsigned int truesize; - struct page *page; - skb_frag_t *frag; - int offset; -@@ -2172,21 +2215,14 @@ static int virtnet_build_xdp_buff_mrg(st - page = virt_to_head_page(buf); - offset = buf - page_address(page); - -- truesize = mergeable_ctx_to_truesize(ctx); -- headroom = mergeable_ctx_to_headroom(ctx); -- tailroom = headroom ? sizeof(struct skb_shared_info) : 0; -- room = SKB_DATA_ALIGN(headroom + tailroom); -- -- cur_frag_size = truesize; -- xdp_frags_truesz += cur_frag_size; -- if (unlikely(len > truesize - room || cur_frag_size > PAGE_SIZE)) { -+ if (check_mergeable_len(dev, ctx, len)) { - put_page(page); -- pr_debug("%s: rx error: len %u exceeds truesize %lu\n", -- dev->name, len, (unsigned long)(truesize - room)); -- DEV_STATS_INC(dev, rx_length_errors); - goto err; - } - -+ truesize = mergeable_ctx_to_truesize(ctx); -+ xdp_frags_truesz += truesize; -+ - frag = &shinfo->frags[shinfo->nr_frags++]; - skb_frag_fill_page_desc(frag, page, offset, len); - if (page_is_pfmemalloc(page)) -@@ -2252,7 +2288,7 @@ static void *mergeable_xdp_get_buf(struc - */ - if (!xdp_prog->aux->xdp_has_frags) { - /* linearize data for XDP */ -- xdp_page = xdp_linearize_page(rq, num_buf, -+ xdp_page = xdp_linearize_page(vi->dev, rq, num_buf, - *page, offset, - XDP_PACKET_HEADROOM, - len); -@@ -2400,18 +2436,12 @@ static struct sk_buff *receive_mergeable - struct sk_buff *head_skb, *curr_skb; - unsigned int truesize = mergeable_ctx_to_truesize(ctx); - unsigned int headroom = mergeable_ctx_to_headroom(ctx); -- unsigned int tailroom = headroom ? sizeof(struct skb_shared_info) : 0; -- unsigned int room = SKB_DATA_ALIGN(headroom + tailroom); - - head_skb = NULL; - u64_stats_add(&stats->bytes, len - vi->hdr_len); - -- if (unlikely(len > truesize - room)) { -- pr_debug("%s: rx error: len %u exceeds truesize %lu\n", -- dev->name, len, (unsigned long)(truesize - room)); -- DEV_STATS_INC(dev, rx_length_errors); -+ if (check_mergeable_len(dev, ctx, len)) - goto err_skb; -- } - - if (unlikely(vi->xdp_enabled)) { - struct bpf_prog *xdp_prog; -@@ -2446,17 +2476,10 @@ static struct sk_buff *receive_mergeable - u64_stats_add(&stats->bytes, len); - page = virt_to_head_page(buf); - -- truesize = mergeable_ctx_to_truesize(ctx); -- headroom = mergeable_ctx_to_headroom(ctx); -- tailroom = headroom ? sizeof(struct skb_shared_info) : 0; -- room = SKB_DATA_ALIGN(headroom + tailroom); -- if (unlikely(len > truesize - room)) { -- pr_debug("%s: rx error: len %u exceeds truesize %lu\n", -- dev->name, len, (unsigned long)(truesize - room)); -- DEV_STATS_INC(dev, rx_length_errors); -+ if (check_mergeable_len(dev, ctx, len)) - goto err_skb; -- } - -+ truesize = mergeable_ctx_to_truesize(ctx); - curr_skb = virtnet_skb_append_frag(head_skb, curr_skb, page, - buf, len, truesize); - if (!curr_skb) -@@ -2998,7 +3021,7 @@ static void virtnet_poll_cleantx(struct - free_old_xmit(sq, txq, !!budget); - } while (unlikely(!virtqueue_enable_cb_delayed(sq->vq))); - -- if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS) { -+ if (sq->vq->num_free >= MAX_SKB_FRAGS + 2) { - if (netif_tx_queue_stopped(txq)) { - u64_stats_update_begin(&sq->stats.syncp); - u64_stats_inc(&sq->stats.wake); -@@ -3195,7 +3218,7 @@ static int virtnet_poll_tx(struct napi_s - else - free_old_xmit(sq, txq, !!budget); - -- if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS) { -+ if (sq->vq->num_free >= MAX_SKB_FRAGS + 2) { - if (netif_tx_queue_stopped(txq)) { - u64_stats_update_begin(&sq->stats.syncp); - u64_stats_inc(&sq->stats.wake); -@@ -3481,6 +3504,12 @@ static int virtnet_tx_resize(struct virt - { - int qindex, err; - -+ if (ring_num <= MAX_SKB_FRAGS + 2) { -+ netdev_err(vi->dev, "tx size (%d) cannot be smaller than %d\n", -+ ring_num, MAX_SKB_FRAGS + 2); -+ return -EINVAL; -+ } -+ - qindex = sq - vi->sq; - - virtnet_tx_pause(vi, sq); -@@ -7030,7 +7059,7 @@ static int virtnet_probe(struct virtio_d - otherwise get link status from config. */ - netif_carrier_off(dev); - if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) { -- virtnet_config_changed_work(&vi->config_work); -+ virtio_config_changed(vi->vdev); - } else { - vi->status = VIRTIO_NET_S_LINK_UP; - virtnet_update_settings(vi); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/vrf.c BPI-Router-Linux-kernel-6.16.12/drivers/net/vrf.c ---- BPI-Router-Linux-kernel/drivers/net/vrf.c 2025-10-22 13:53:23.371328378 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/vrf.c 2025-10-22 13:53:56.595168756 -0400 -@@ -1302,6 +1302,8 @@ static void vrf_ip6_input_dst(struct sk_ - struct net *net = dev_net(vrf_dev); - struct rt6_info *rt6; - -+ skb_dst_drop(skb); -+ - rt6 = vrf_ip6_route_lookup(net, vrf_dev, &fl6, ifindex, skb, - RT6_LOOKUP_F_HAS_SADDR | RT6_LOOKUP_F_IFACE); - if (unlikely(!rt6)) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/vxlan/vxlan_core.c BPI-Router-Linux-kernel-6.16.12/drivers/net/vxlan/vxlan_core.c ---- BPI-Router-Linux-kernel/drivers/net/vxlan/vxlan_core.c 2025-10-22 13:53:23.371328378 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/vxlan/vxlan_core.c 2025-10-22 13:53:56.595168756 -0400 -@@ -1445,6 +1445,10 @@ static enum skb_drop_reason vxlan_snoop( - if (READ_ONCE(f->updated) != now) - WRITE_ONCE(f->updated, now); - -+ /* Don't override an fdb with nexthop with a learnt entry */ -+ if (rcu_access_pointer(f->nh)) -+ return SKB_DROP_REASON_VXLAN_ENTRY_EXISTS; -+ - if (likely(vxlan_addr_equal(&rdst->remote_ip, src_ip) && - rdst->remote_ifindex == ifindex)) - return SKB_NOT_DROPPED_YET; -@@ -1453,10 +1457,6 @@ static enum skb_drop_reason vxlan_snoop( - if (f->state & (NUD_PERMANENT | NUD_NOARP)) - return SKB_DROP_REASON_VXLAN_ENTRY_EXISTS; - -- /* Don't override an fdb with nexthop with a learnt entry */ -- if (rcu_access_pointer(f->nh)) -- return SKB_DROP_REASON_VXLAN_ENTRY_EXISTS; -- - if (net_ratelimit()) - netdev_info(dev, - "%pM migrated from %pIS to %pIS\n", -@@ -1880,6 +1880,7 @@ static int arp_reduce(struct net_device - n = neigh_lookup(&arp_tbl, &tip, dev); - - if (n) { -+ struct vxlan_rdst *rdst = NULL; - struct vxlan_fdb *f; - struct sk_buff *reply; - -@@ -1890,7 +1891,9 @@ static int arp_reduce(struct net_device - - rcu_read_lock(); - f = vxlan_find_mac_tx(vxlan, n->ha, vni); -- if (f && vxlan_addr_any(&(first_remote_rcu(f)->remote_ip))) { -+ if (f) -+ rdst = first_remote_rcu(f); -+ if (rdst && vxlan_addr_any(&rdst->remote_ip)) { - /* bridge-local neighbor */ - neigh_release(n); - rcu_read_unlock(); -@@ -2047,6 +2050,7 @@ static int neigh_reduce(struct net_devic - n = neigh_lookup(ipv6_stub->nd_tbl, &msg->target, dev); - - if (n) { -+ struct vxlan_rdst *rdst = NULL; - struct vxlan_fdb *f; - struct sk_buff *reply; - -@@ -2056,7 +2060,9 @@ static int neigh_reduce(struct net_devic - } - - f = vxlan_find_mac_tx(vxlan, n->ha, vni); -- if (f && vxlan_addr_any(&(first_remote_rcu(f)->remote_ip))) { -+ if (f) -+ rdst = first_remote_rcu(f); -+ if (rdst && vxlan_addr_any(&rdst->remote_ip)) { - /* bridge-local neighbor */ - neigh_release(n); - goto out; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/vxlan/vxlan_private.h BPI-Router-Linux-kernel-6.16.12/drivers/net/vxlan/vxlan_private.h ---- BPI-Router-Linux-kernel/drivers/net/vxlan/vxlan_private.h 2025-10-22 13:53:23.371328378 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/vxlan/vxlan_private.h 2025-10-22 13:53:56.595168756 -0400 -@@ -61,9 +61,7 @@ static inline struct hlist_head *vs_head - return &vn->sock_list[hash_32(ntohs(port), PORT_HASH_BITS)]; - } - --/* First remote destination for a forwarding entry. -- * Guaranteed to be non-NULL because remotes are never deleted. -- */ -+/* First remote destination for a forwarding entry. */ - static inline struct vxlan_rdst *first_remote_rcu(struct vxlan_fdb *fdb) - { - if (rcu_access_pointer(fdb->nh)) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wan/lapbether.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wan/lapbether.c ---- BPI-Router-Linux-kernel/drivers/net/wan/lapbether.c 2025-10-22 13:53:23.371328378 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wan/lapbether.c 2025-10-22 13:53:56.595168756 -0400 -@@ -81,7 +81,7 @@ static struct lapbethdev *lapbeth_get_x2 - - static __inline__ int dev_is_ethdev(struct net_device *dev) - { -- return dev->type == ARPHRD_ETHER && strncmp(dev->name, "dummy", 5); -+ return dev->type == ARPHRD_ETHER && !netdev_need_ops_lock(dev); - } - - /* ------------------------------------------------------------------------ */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath10k/core.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath10k/core.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath10k/core.c 2025-10-22 13:53:23.371328378 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath10k/core.c 2025-10-22 13:53:56.595168756 -0400 -@@ -2491,12 +2491,50 @@ static int ath10k_init_hw_params(struct - return 0; - } - -+static bool ath10k_core_needs_recovery(struct ath10k *ar) -+{ -+ long time_left; -+ -+ /* Sometimes the recovery will fail and then the next all recovery fail, -+ * so avoid infinite recovery. -+ */ -+ if (atomic_read(&ar->fail_cont_count) >= ATH10K_RECOVERY_MAX_FAIL_COUNT) { -+ ath10k_err(ar, "consecutive fail %d times, will shutdown driver!", -+ atomic_read(&ar->fail_cont_count)); -+ ar->state = ATH10K_STATE_WEDGED; -+ return false; -+ } -+ -+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "total recovery count: %d", ++ar->recovery_count); -+ -+ if (atomic_read(&ar->pending_recovery)) { -+ /* Sometimes it happened another recovery work before the previous one -+ * completed, then the second recovery work will destroy the previous -+ * one, thus below is to avoid that. -+ */ -+ time_left = wait_for_completion_timeout(&ar->driver_recovery, -+ ATH10K_RECOVERY_TIMEOUT_HZ); -+ if (time_left) { -+ ath10k_warn(ar, "previous recovery succeeded, skip this!\n"); -+ return false; -+ } -+ -+ /* Record the continuous recovery fail count when recovery failed. */ -+ atomic_inc(&ar->fail_cont_count); -+ -+ /* Avoid having multiple recoveries at the same time. */ -+ return false; -+ } -+ -+ atomic_inc(&ar->pending_recovery); -+ -+ return true; -+} -+ - void ath10k_core_start_recovery(struct ath10k *ar) - { -- if (test_and_set_bit(ATH10K_FLAG_RESTARTING, &ar->dev_flags)) { -- ath10k_warn(ar, "already restarting\n"); -+ if (!ath10k_core_needs_recovery(ar)) - return; -- } - - queue_work(ar->workqueue, &ar->restart_work); - } -@@ -2532,6 +2570,8 @@ static void ath10k_core_restart(struct w - struct ath10k *ar = container_of(work, struct ath10k, restart_work); - int ret; - -+ reinit_completion(&ar->driver_recovery); -+ - set_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags); - - /* Place a barrier to make sure the compiler doesn't reorder -@@ -2596,8 +2636,6 @@ static void ath10k_core_restart(struct w - if (ret) - ath10k_warn(ar, "failed to send firmware crash dump via devcoredump: %d", - ret); -- -- complete(&ar->driver_recovery); - } - - static void ath10k_core_set_coverage_class_work(struct work_struct *work) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath10k/core.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath10k/core.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath10k/core.h 2025-10-22 13:53:23.371328378 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath10k/core.h 2025-10-22 13:53:56.595168756 -0400 -@@ -4,6 +4,7 @@ - * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. -+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. - */ - - #ifndef _CORE_H_ -@@ -87,6 +88,8 @@ - IEEE80211_IFACE_SKIP_SDATA_NOT_IN_DRIVER) - #define ATH10K_ITER_RESUME_FLAGS (IEEE80211_IFACE_ITER_RESUME_ALL |\ - IEEE80211_IFACE_SKIP_SDATA_NOT_IN_DRIVER) -+#define ATH10K_RECOVERY_TIMEOUT_HZ (5 * HZ) -+#define ATH10K_RECOVERY_MAX_FAIL_COUNT 4 - - struct ath10k; - -@@ -865,9 +868,6 @@ enum ath10k_dev_flags { - /* Per Station statistics service */ - ATH10K_FLAG_PEER_STATS, - -- /* Indicates that ath10k device is during recovery process and not complete */ -- ATH10K_FLAG_RESTARTING, -- - /* protected by conf_mutex */ - ATH10K_FLAG_NAPI_ENABLED, - }; -@@ -1211,6 +1211,11 @@ struct ath10k { - struct work_struct bundle_tx_work; - struct work_struct tx_complete_work; - -+ atomic_t pending_recovery; -+ unsigned int recovery_count; -+ /* continuous recovery fail count */ -+ atomic_t fail_cont_count; -+ - /* cycle count is reported twice for each visited channel during scan. - * access protected by data_lock - */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath10k/mac.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath10k/mac.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath10k/mac.c 2025-10-22 13:53:23.375328359 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath10k/mac.c 2025-10-22 13:53:56.599168736 -0400 -@@ -4,6 +4,7 @@ - * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. - */ - - #include "mac.h" -@@ -1022,6 +1023,26 @@ static inline int ath10k_vdev_setup_sync - return ar->last_wmi_vdev_start_status; - } - -+static inline int ath10k_vdev_delete_sync(struct ath10k *ar) -+{ -+ unsigned long time_left; -+ -+ lockdep_assert_held(&ar->conf_mutex); -+ -+ if (!test_bit(WMI_SERVICE_SYNC_DELETE_CMDS, ar->wmi.svc_map)) -+ return 0; -+ -+ if (test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) -+ return -ESHUTDOWN; -+ -+ time_left = wait_for_completion_timeout(&ar->vdev_delete_done, -+ ATH10K_VDEV_DELETE_TIMEOUT_HZ); -+ if (time_left == 0) -+ return -ETIMEDOUT; -+ -+ return 0; -+} -+ - static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id) - { - struct cfg80211_chan_def *chandef = NULL; -@@ -5900,7 +5921,6 @@ static void ath10k_remove_interface(stru - struct ath10k *ar = hw->priv; - struct ath10k_vif *arvif = (void *)vif->drv_priv; - struct ath10k_peer *peer; -- unsigned long time_left; - int ret; - int i; - -@@ -5940,13 +5960,10 @@ static void ath10k_remove_interface(stru - ath10k_warn(ar, "failed to delete WMI vdev %i: %d\n", - arvif->vdev_id, ret); - -- if (test_bit(WMI_SERVICE_SYNC_DELETE_CMDS, ar->wmi.svc_map)) { -- time_left = wait_for_completion_timeout(&ar->vdev_delete_done, -- ATH10K_VDEV_DELETE_TIMEOUT_HZ); -- if (time_left == 0) { -- ath10k_warn(ar, "Timeout in receiving vdev delete response\n"); -- goto out; -- } -+ ret = ath10k_vdev_delete_sync(ar); -+ if (ret) { -+ ath10k_warn(ar, "Error in receiving vdev delete response: %d\n", ret); -+ goto out; - } - - /* Some firmware revisions don't notify host about self-peer removal -@@ -8139,7 +8156,12 @@ static void ath10k_reconfig_complete(str - ath10k_info(ar, "device successfully recovered\n"); - ar->state = ATH10K_STATE_ON; - ieee80211_wake_queues(ar->hw); -- clear_bit(ATH10K_FLAG_RESTARTING, &ar->dev_flags); -+ -+ /* Clear recovery state. */ -+ complete(&ar->driver_recovery); -+ atomic_set(&ar->fail_cont_count, 0); -+ atomic_set(&ar->pending_recovery, 0); -+ - if (ar->hw_params.hw_restart_disconnect) { - list_for_each_entry(arvif, &ar->arvifs, list) { - if (arvif->is_up && arvif->vdev_type == WMI_VDEV_TYPE_STA) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath10k/snoc.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath10k/snoc.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath10k/snoc.c 2025-10-22 13:53:23.375328359 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath10k/snoc.c 2025-10-22 13:53:56.599168736 -0400 -@@ -938,7 +938,9 @@ static int ath10k_snoc_hif_start(struct - - dev_set_threaded(ar->napi_dev, true); - ath10k_core_napi_enable(ar); -- ath10k_snoc_irq_enable(ar); -+ /* IRQs are left enabled when we restart due to a firmware crash */ -+ if (!test_bit(ATH10K_SNOC_FLAG_RECOVERY, &ar_snoc->flags)) -+ ath10k_snoc_irq_enable(ar); - ath10k_snoc_rx_post(ar); - - clear_bit(ATH10K_SNOC_FLAG_RECOVERY, &ar_snoc->flags); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath10k/wmi.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath10k/wmi.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath10k/wmi.c 2025-10-22 13:53:23.375328359 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath10k/wmi.c 2025-10-22 13:53:56.599168736 -0400 -@@ -4,6 +4,7 @@ - * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. - */ - - #include -@@ -1941,6 +1942,11 @@ int ath10k_wmi_cmd_send(struct ath10k *a - } - - wait_event_timeout(ar->wmi.tx_credits_wq, ({ -+ if (ar->state == ATH10K_STATE_WEDGED) { -+ ret = -ESHUTDOWN; -+ ath10k_dbg(ar, ATH10K_DBG_WMI, -+ "drop wmi command %d, hardware is wedged\n", cmd_id); -+ } - /* try to send pending beacons first. they take priority */ - ath10k_wmi_tx_beacons_nowait(ar); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath11k/ce.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath11k/ce.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath11k/ce.c 2025-10-22 13:53:23.375328359 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath11k/ce.c 2025-10-22 13:53:56.599168736 -0400 -@@ -393,9 +393,6 @@ static int ath11k_ce_completed_recv_next - goto err; - } - -- /* Make sure descriptor is read after the head pointer. */ -- dma_rmb(); -- - *nbytes = ath11k_hal_ce_dst_status_get_length(desc); - - *skb = pipe->dest_ring->skb[sw_index]; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath11k/core.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath11k/core.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath11k/core.c 2025-10-22 13:53:23.375328359 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath11k/core.c 2025-10-22 13:53:56.599168736 -0400 -@@ -990,6 +990,7 @@ void ath11k_fw_stats_init(struct ath11k - INIT_LIST_HEAD(&ar->fw_stats.bcn); - - init_completion(&ar->fw_stats_complete); -+ init_completion(&ar->fw_stats_done); - } - - void ath11k_fw_stats_free(struct ath11k_fw_stats *stats) -@@ -2134,6 +2135,20 @@ int ath11k_core_qmi_firmware_ready(struc - { - int ret; - -+ switch (ath11k_crypto_mode) { -+ case ATH11K_CRYPT_MODE_SW: -+ set_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags); -+ set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags); -+ break; -+ case ATH11K_CRYPT_MODE_HW: -+ clear_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags); -+ clear_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags); -+ break; -+ default: -+ ath11k_info(ab, "invalid crypto_mode: %d\n", ath11k_crypto_mode); -+ return -EINVAL; -+ } -+ - ret = ath11k_core_start_firmware(ab, ab->fw_mode); - if (ret) { - ath11k_err(ab, "failed to start firmware: %d\n", ret); -@@ -2152,20 +2167,6 @@ int ath11k_core_qmi_firmware_ready(struc - goto err_firmware_stop; - } - -- switch (ath11k_crypto_mode) { -- case ATH11K_CRYPT_MODE_SW: -- set_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags); -- set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags); -- break; -- case ATH11K_CRYPT_MODE_HW: -- clear_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags); -- clear_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags); -- break; -- default: -- ath11k_info(ab, "invalid crypto_mode: %d\n", ath11k_crypto_mode); -- return -EINVAL; -- } -- - if (ath11k_frame_mode == ATH11K_HW_TXRX_RAW) - set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath11k/core.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath11k/core.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath11k/core.h 2025-10-22 13:53:23.375328359 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath11k/core.h 2025-10-22 13:53:56.599168736 -0400 -@@ -410,6 +410,8 @@ struct ath11k_vif { - bool do_not_send_tmpl; - struct ath11k_arp_ns_offload arp_ns_offload; - struct ath11k_rekey_data rekey_data; -+ u32 num_stations; -+ bool reinstall_group_keys; - - struct ath11k_reg_tpc_power_info reg_tpc_info; - -@@ -600,6 +602,8 @@ struct ath11k_fw_stats { - struct list_head pdevs; - struct list_head vdevs; - struct list_head bcn; -+ u32 num_vdev_recvd; -+ u32 num_bcn_recvd; - }; - - struct ath11k_dbg_htt_stats { -@@ -784,7 +788,7 @@ struct ath11k { - u8 alpha2[REG_ALPHA2_LEN + 1]; - struct ath11k_fw_stats fw_stats; - struct completion fw_stats_complete; -- bool fw_stats_done; -+ struct completion fw_stats_done; - - /* protected by conf_mutex */ - bool ps_state_enable; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath11k/debugfs.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath11k/debugfs.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath11k/debugfs.c 2025-10-22 13:53:23.375328359 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath11k/debugfs.c 2025-10-22 13:53:56.599168736 -0400 -@@ -1,7 +1,7 @@ - // SPDX-License-Identifier: BSD-3-Clause-Clear - /* - * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved. -- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved. - */ - - #include -@@ -93,57 +93,14 @@ void ath11k_debugfs_add_dbring_entry(str - spin_unlock_bh(&dbr_data->lock); - } - --static void ath11k_debugfs_fw_stats_reset(struct ath11k *ar) --{ -- spin_lock_bh(&ar->data_lock); -- ar->fw_stats_done = false; -- ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs); -- ath11k_fw_stats_vdevs_free(&ar->fw_stats.vdevs); -- spin_unlock_bh(&ar->data_lock); --} -- - void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *stats) - { - struct ath11k_base *ab = ar->ab; -- struct ath11k_pdev *pdev; -- bool is_end; -- static unsigned int num_vdev, num_bcn; -- size_t total_vdevs_started = 0; -- int i; -- -- /* WMI_REQUEST_PDEV_STAT request has been already processed */ -- -- if (stats->stats_id == WMI_REQUEST_RSSI_PER_CHAIN_STAT) { -- ar->fw_stats_done = true; -- return; -- } -- -- if (stats->stats_id == WMI_REQUEST_VDEV_STAT) { -- if (list_empty(&stats->vdevs)) { -- ath11k_warn(ab, "empty vdev stats"); -- return; -- } -- /* FW sends all the active VDEV stats irrespective of PDEV, -- * hence limit until the count of all VDEVs started -- */ -- for (i = 0; i < ab->num_radios; i++) { -- pdev = rcu_dereference(ab->pdevs_active[i]); -- if (pdev && pdev->ar) -- total_vdevs_started += ar->num_started_vdevs; -- } -- -- is_end = ((++num_vdev) == total_vdevs_started); -- -- list_splice_tail_init(&stats->vdevs, -- &ar->fw_stats.vdevs); -- -- if (is_end) { -- ar->fw_stats_done = true; -- num_vdev = 0; -- } -- return; -- } -+ bool is_end = true; - -+ /* WMI_REQUEST_PDEV_STAT, WMI_REQUEST_RSSI_PER_CHAIN_STAT and -+ * WMI_REQUEST_VDEV_STAT requests have been already processed. -+ */ - if (stats->stats_id == WMI_REQUEST_BCN_STAT) { - if (list_empty(&stats->bcn)) { - ath11k_warn(ab, "empty bcn stats"); -@@ -152,97 +109,18 @@ void ath11k_debugfs_fw_stats_process(str - /* Mark end until we reached the count of all started VDEVs - * within the PDEV - */ -- is_end = ((++num_bcn) == ar->num_started_vdevs); -+ if (ar->num_started_vdevs) -+ is_end = ((++ar->fw_stats.num_bcn_recvd) == -+ ar->num_started_vdevs); - - list_splice_tail_init(&stats->bcn, - &ar->fw_stats.bcn); - -- if (is_end) { -- ar->fw_stats_done = true; -- num_bcn = 0; -- } -+ if (is_end) -+ complete(&ar->fw_stats_done); - } - } - --static int ath11k_debugfs_fw_stats_request(struct ath11k *ar, -- struct stats_request_params *req_param) --{ -- struct ath11k_base *ab = ar->ab; -- unsigned long timeout, time_left; -- int ret; -- -- lockdep_assert_held(&ar->conf_mutex); -- -- /* FW stats can get split when exceeding the stats data buffer limit. -- * In that case, since there is no end marking for the back-to-back -- * received 'update stats' event, we keep a 3 seconds timeout in case, -- * fw_stats_done is not marked yet -- */ -- timeout = jiffies + secs_to_jiffies(3); -- -- ath11k_debugfs_fw_stats_reset(ar); -- -- reinit_completion(&ar->fw_stats_complete); -- -- ret = ath11k_wmi_send_stats_request_cmd(ar, req_param); -- -- if (ret) { -- ath11k_warn(ab, "could not request fw stats (%d)\n", -- ret); -- return ret; -- } -- -- time_left = wait_for_completion_timeout(&ar->fw_stats_complete, 1 * HZ); -- -- if (!time_left) -- return -ETIMEDOUT; -- -- for (;;) { -- if (time_after(jiffies, timeout)) -- break; -- -- spin_lock_bh(&ar->data_lock); -- if (ar->fw_stats_done) { -- spin_unlock_bh(&ar->data_lock); -- break; -- } -- spin_unlock_bh(&ar->data_lock); -- } -- return 0; --} -- --int ath11k_debugfs_get_fw_stats(struct ath11k *ar, u32 pdev_id, -- u32 vdev_id, u32 stats_id) --{ -- struct ath11k_base *ab = ar->ab; -- struct stats_request_params req_param; -- int ret; -- -- mutex_lock(&ar->conf_mutex); -- -- if (ar->state != ATH11K_STATE_ON) { -- ret = -ENETDOWN; -- goto err_unlock; -- } -- -- req_param.pdev_id = pdev_id; -- req_param.vdev_id = vdev_id; -- req_param.stats_id = stats_id; -- -- ret = ath11k_debugfs_fw_stats_request(ar, &req_param); -- if (ret) -- ath11k_warn(ab, "failed to request fw stats: %d\n", ret); -- -- ath11k_dbg(ab, ATH11K_DBG_WMI, -- "debug get fw stat pdev id %d vdev id %d stats id 0x%x\n", -- pdev_id, vdev_id, stats_id); -- --err_unlock: -- mutex_unlock(&ar->conf_mutex); -- -- return ret; --} -- - static int ath11k_open_pdev_stats(struct inode *inode, struct file *file) - { - struct ath11k *ar = inode->i_private; -@@ -268,7 +146,7 @@ static int ath11k_open_pdev_stats(struct - req_param.vdev_id = 0; - req_param.stats_id = WMI_REQUEST_PDEV_STAT; - -- ret = ath11k_debugfs_fw_stats_request(ar, &req_param); -+ ret = ath11k_mac_fw_stats_request(ar, &req_param); - if (ret) { - ath11k_warn(ab, "failed to request fw pdev stats: %d\n", ret); - goto err_free; -@@ -339,7 +217,7 @@ static int ath11k_open_vdev_stats(struct - req_param.vdev_id = 0; - req_param.stats_id = WMI_REQUEST_VDEV_STAT; - -- ret = ath11k_debugfs_fw_stats_request(ar, &req_param); -+ ret = ath11k_mac_fw_stats_request(ar, &req_param); - if (ret) { - ath11k_warn(ar->ab, "failed to request fw vdev stats: %d\n", ret); - goto err_free; -@@ -415,7 +293,7 @@ static int ath11k_open_bcn_stats(struct - continue; - - req_param.vdev_id = arvif->vdev_id; -- ret = ath11k_debugfs_fw_stats_request(ar, &req_param); -+ ret = ath11k_mac_fw_stats_request(ar, &req_param); - if (ret) { - ath11k_warn(ar->ab, "failed to request fw bcn stats: %d\n", ret); - goto err_free; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath11k/debugfs.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath11k/debugfs.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath11k/debugfs.h 2025-10-22 13:53:23.375328359 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath11k/debugfs.h 2025-10-22 13:53:56.599168736 -0400 -@@ -1,7 +1,7 @@ - /* SPDX-License-Identifier: BSD-3-Clause-Clear */ - /* - * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. -- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. -+ * Copyright (c) 2021-2022, 2025 Qualcomm Innovation Center, Inc. All rights reserved. - */ - - #ifndef _ATH11K_DEBUGFS_H_ -@@ -273,8 +273,6 @@ void ath11k_debugfs_unregister(struct at - void ath11k_debugfs_fw_stats_process(struct ath11k *ar, struct ath11k_fw_stats *stats); - - void ath11k_debugfs_fw_stats_init(struct ath11k *ar); --int ath11k_debugfs_get_fw_stats(struct ath11k *ar, u32 pdev_id, -- u32 vdev_id, u32 stats_id); - - static inline bool ath11k_debugfs_is_pktlog_lite_mode_enabled(struct ath11k *ar) - { -@@ -380,12 +378,6 @@ static inline int ath11k_debugfs_rx_filt - { - return 0; - } -- --static inline int ath11k_debugfs_get_fw_stats(struct ath11k *ar, -- u32 pdev_id, u32 vdev_id, u32 stats_id) --{ -- return 0; --} - - static inline void - ath11k_debugfs_add_dbring_entry(struct ath11k *ar, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath11k/dp_rx.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath11k/dp_rx.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath11k/dp_rx.c 2025-10-22 13:53:23.375328359 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath11k/dp_rx.c 2025-10-22 13:53:56.599168736 -0400 -@@ -2650,9 +2650,6 @@ int ath11k_dp_process_rx(struct ath11k_b - try_again: - ath11k_hal_srng_access_begin(ab, srng); - -- /* Make sure descriptor is read after the head pointer. */ -- dma_rmb(); -- - while (likely(desc = - (struct hal_reo_dest_ring *)ath11k_hal_srng_dst_get_next_entry(ab, - srng))) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath11k/hal.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath11k/hal.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath11k/hal.c 2025-10-22 13:53:23.375328359 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath11k/hal.c 2025-10-22 13:53:56.599168736 -0400 -@@ -823,13 +823,23 @@ u32 *ath11k_hal_srng_src_peek(struct ath - - void ath11k_hal_srng_access_begin(struct ath11k_base *ab, struct hal_srng *srng) - { -+ u32 hp; -+ - lockdep_assert_held(&srng->lock); - - if (srng->ring_dir == HAL_SRNG_DIR_SRC) { - srng->u.src_ring.cached_tp = - *(volatile u32 *)srng->u.src_ring.tp_addr; - } else { -- srng->u.dst_ring.cached_hp = READ_ONCE(*srng->u.dst_ring.hp_addr); -+ hp = READ_ONCE(*srng->u.dst_ring.hp_addr); -+ -+ if (hp != srng->u.dst_ring.cached_hp) { -+ srng->u.dst_ring.cached_hp = hp; -+ /* Make sure descriptor is read after the head -+ * pointer. -+ */ -+ dma_rmb(); -+ } - - /* Try to prefetch the next descriptor in the ring */ - if (srng->flags & HAL_SRNG_FLAGS_CACHED) -@@ -844,7 +854,6 @@ void ath11k_hal_srng_access_end(struct a - { - lockdep_assert_held(&srng->lock); - -- /* TODO: See if we need a write memory barrier here */ - if (srng->flags & HAL_SRNG_FLAGS_LMAC_RING) { - /* For LMAC rings, ring pointer updates are done through FW and - * hence written to a shared memory location that is read by FW -@@ -852,21 +861,37 @@ void ath11k_hal_srng_access_end(struct a - if (srng->ring_dir == HAL_SRNG_DIR_SRC) { - srng->u.src_ring.last_tp = - *(volatile u32 *)srng->u.src_ring.tp_addr; -- *srng->u.src_ring.hp_addr = srng->u.src_ring.hp; -+ /* Make sure descriptor is written before updating the -+ * head pointer. -+ */ -+ dma_wmb(); -+ WRITE_ONCE(*srng->u.src_ring.hp_addr, srng->u.src_ring.hp); - } else { - srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr; -- *srng->u.dst_ring.tp_addr = srng->u.dst_ring.tp; -+ /* Make sure descriptor is read before updating the -+ * tail pointer. -+ */ -+ dma_mb(); -+ WRITE_ONCE(*srng->u.dst_ring.tp_addr, srng->u.dst_ring.tp); - } - } else { - if (srng->ring_dir == HAL_SRNG_DIR_SRC) { - srng->u.src_ring.last_tp = - *(volatile u32 *)srng->u.src_ring.tp_addr; -+ /* Assume implementation use an MMIO write accessor -+ * which has the required wmb() so that the descriptor -+ * is written before the updating the head pointer. -+ */ - ath11k_hif_write32(ab, - (unsigned long)srng->u.src_ring.hp_addr - - (unsigned long)ab->mem, - srng->u.src_ring.hp); - } else { - srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr; -+ /* Make sure descriptor is read before updating the -+ * tail pointer. -+ */ -+ mb(); - ath11k_hif_write32(ab, - (unsigned long)srng->u.dst_ring.tp_addr - - (unsigned long)ab->mem, -@@ -1346,6 +1371,10 @@ EXPORT_SYMBOL(ath11k_hal_srng_init); - void ath11k_hal_srng_deinit(struct ath11k_base *ab) - { - struct ath11k_hal *hal = &ab->hal; -+ int i; -+ -+ for (i = 0; i < HAL_SRNG_RING_ID_MAX; i++) -+ ab->hal.srng_list[i].initialized = 0; - - ath11k_hal_unregister_srng_key(ab); - ath11k_hal_free_cont_rdp(ab); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath11k/mac.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath11k/mac.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath11k/mac.c 2025-10-22 13:53:23.375328359 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath11k/mac.c 2025-10-22 13:53:56.599168736 -0400 -@@ -4317,6 +4317,40 @@ static int ath11k_clear_peer_keys(struct - return first_errno; - } - -+static int ath11k_set_group_keys(struct ath11k_vif *arvif) -+{ -+ struct ath11k *ar = arvif->ar; -+ struct ath11k_base *ab = ar->ab; -+ const u8 *addr = arvif->bssid; -+ int i, ret, first_errno = 0; -+ struct ath11k_peer *peer; -+ -+ spin_lock_bh(&ab->base_lock); -+ peer = ath11k_peer_find(ab, arvif->vdev_id, addr); -+ spin_unlock_bh(&ab->base_lock); -+ -+ if (!peer) -+ return -ENOENT; -+ -+ for (i = 0; i < ARRAY_SIZE(peer->keys); i++) { -+ struct ieee80211_key_conf *key = peer->keys[i]; -+ -+ if (!key || (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) -+ continue; -+ -+ ret = ath11k_install_key(arvif, key, SET_KEY, addr, -+ WMI_KEY_GROUP); -+ if (ret < 0 && first_errno == 0) -+ first_errno = ret; -+ -+ if (ret < 0) -+ ath11k_warn(ab, "failed to set group key of idx %d for vdev %d: %d\n", -+ i, arvif->vdev_id, ret); -+ } -+ -+ return first_errno; -+} -+ - static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -@@ -4326,6 +4360,7 @@ static int ath11k_mac_op_set_key(struct - struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); - struct ath11k_peer *peer; - struct ath11k_sta *arsta; -+ bool is_ap_with_no_sta; - const u8 *peer_addr; - int ret = 0; - u32 flags = 0; -@@ -4386,16 +4421,57 @@ static int ath11k_mac_op_set_key(struct - else - flags |= WMI_KEY_GROUP; - -- ret = ath11k_install_key(arvif, key, cmd, peer_addr, flags); -- if (ret) { -- ath11k_warn(ab, "ath11k_install_key failed (%d)\n", ret); -- goto exit; -- } -+ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, -+ "%s for peer %pM on vdev %d flags 0x%X, type = %d, num_sta %d\n", -+ cmd == SET_KEY ? "SET_KEY" : "DEL_KEY", peer_addr, arvif->vdev_id, -+ flags, arvif->vdev_type, arvif->num_stations); -+ -+ /* Allow group key clearing only in AP mode when no stations are -+ * associated. There is a known race condition in firmware where -+ * group addressed packets may be dropped if the key is cleared -+ * and immediately set again during rekey. -+ * -+ * During GTK rekey, mac80211 issues a clear key (if the old key -+ * exists) followed by an install key operation for same key -+ * index. This causes ath11k to send two WMI commands in quick -+ * succession: one to clear the old key and another to install the -+ * new key in the same slot. -+ * -+ * Under certain conditions—especially under high load or time -+ * sensitive scenarios, firmware may process these commands -+ * asynchronously in a way that firmware assumes the key is -+ * cleared whereas hardware has a valid key. This inconsistency -+ * between hardware and firmware leads to group addressed packet -+ * drops after rekey. -+ * Only setting the same key again can restore a valid key in -+ * firmware and allow packets to be transmitted. -+ * -+ * There is a use case where an AP can transition from Secure mode -+ * to open mode without a vdev restart by just deleting all -+ * associated peers and clearing key, Hence allow clear key for -+ * that case alone. Mark arvif->reinstall_group_keys in such cases -+ * and reinstall the same key when the first peer is added, -+ * allowing firmware to recover from the race if it had occurred. -+ */ - -- ret = ath11k_dp_peer_rx_pn_replay_config(arvif, peer_addr, cmd, key); -- if (ret) { -- ath11k_warn(ab, "failed to offload PN replay detection %d\n", ret); -- goto exit; -+ is_ap_with_no_sta = (vif->type == NL80211_IFTYPE_AP && -+ !arvif->num_stations); -+ if ((flags & WMI_KEY_PAIRWISE) || cmd == SET_KEY || is_ap_with_no_sta) { -+ ret = ath11k_install_key(arvif, key, cmd, peer_addr, flags); -+ if (ret) { -+ ath11k_warn(ab, "ath11k_install_key failed (%d)\n", ret); -+ goto exit; -+ } -+ -+ ret = ath11k_dp_peer_rx_pn_replay_config(arvif, peer_addr, cmd, key); -+ if (ret) { -+ ath11k_warn(ab, "failed to offload PN replay detection %d\n", -+ ret); -+ goto exit; -+ } -+ -+ if ((flags & WMI_KEY_GROUP) && cmd == SET_KEY && is_ap_with_no_sta) -+ arvif->reinstall_group_keys = true; - } - - spin_lock_bh(&ab->base_lock); -@@ -4994,6 +5070,7 @@ static int ath11k_mac_inc_num_stations(s - return -ENOBUFS; - - ar->num_stations++; -+ arvif->num_stations++; - - return 0; - } -@@ -5009,6 +5086,7 @@ static void ath11k_mac_dec_num_stations( - return; - - ar->num_stations--; -+ arvif->num_stations--; - } - - static u32 ath11k_mac_ieee80211_sta_bw_to_wmi(struct ath11k *ar, -@@ -8740,9 +8818,9 @@ ath11k_mac_op_set_bitrate_mask(struct ie - arvif->vdev_id, ret); - return ret; - } -- ieee80211_iterate_stations_atomic(ar->hw, -- ath11k_mac_disable_peer_fixed_rate, -- arvif); -+ ieee80211_iterate_stations_mtx(ar->hw, -+ ath11k_mac_disable_peer_fixed_rate, -+ arvif); - } else if (ath11k_mac_bitrate_mask_get_single_nss(ar, arvif, band, mask, - &single_nss)) { - rate = WMI_FIXED_RATE_NONE; -@@ -8809,9 +8887,9 @@ ath11k_mac_op_set_bitrate_mask(struct ie - } - - mutex_lock(&ar->conf_mutex); -- ieee80211_iterate_stations_atomic(ar->hw, -- ath11k_mac_disable_peer_fixed_rate, -- arvif); -+ ieee80211_iterate_stations_mtx(ar->hw, -+ ath11k_mac_disable_peer_fixed_rate, -+ arvif); - - arvif->bitrate_mask = *mask; - ieee80211_iterate_stations_atomic(ar->hw, -@@ -8997,6 +9075,81 @@ static void ath11k_mac_put_chain_rssi(st - } - } - -+static void ath11k_mac_fw_stats_reset(struct ath11k *ar) -+{ -+ spin_lock_bh(&ar->data_lock); -+ ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs); -+ ath11k_fw_stats_vdevs_free(&ar->fw_stats.vdevs); -+ ar->fw_stats.num_vdev_recvd = 0; -+ ar->fw_stats.num_bcn_recvd = 0; -+ spin_unlock_bh(&ar->data_lock); -+} -+ -+int ath11k_mac_fw_stats_request(struct ath11k *ar, -+ struct stats_request_params *req_param) -+{ -+ struct ath11k_base *ab = ar->ab; -+ unsigned long time_left; -+ int ret; -+ -+ lockdep_assert_held(&ar->conf_mutex); -+ -+ ath11k_mac_fw_stats_reset(ar); -+ -+ reinit_completion(&ar->fw_stats_complete); -+ reinit_completion(&ar->fw_stats_done); -+ -+ ret = ath11k_wmi_send_stats_request_cmd(ar, req_param); -+ -+ if (ret) { -+ ath11k_warn(ab, "could not request fw stats (%d)\n", -+ ret); -+ return ret; -+ } -+ -+ time_left = wait_for_completion_timeout(&ar->fw_stats_complete, 1 * HZ); -+ if (!time_left) -+ return -ETIMEDOUT; -+ -+ /* FW stats can get split when exceeding the stats data buffer limit. -+ * In that case, since there is no end marking for the back-to-back -+ * received 'update stats' event, we keep a 3 seconds timeout in case, -+ * fw_stats_done is not marked yet -+ */ -+ time_left = wait_for_completion_timeout(&ar->fw_stats_done, 3 * HZ); -+ if (!time_left) -+ return -ETIMEDOUT; -+ -+ return 0; -+} -+ -+static int ath11k_mac_get_fw_stats(struct ath11k *ar, u32 pdev_id, -+ u32 vdev_id, u32 stats_id) -+{ -+ struct ath11k_base *ab = ar->ab; -+ struct stats_request_params req_param; -+ int ret; -+ -+ lockdep_assert_held(&ar->conf_mutex); -+ -+ if (ar->state != ATH11K_STATE_ON) -+ return -ENETDOWN; -+ -+ req_param.pdev_id = pdev_id; -+ req_param.vdev_id = vdev_id; -+ req_param.stats_id = stats_id; -+ -+ ret = ath11k_mac_fw_stats_request(ar, &req_param); -+ if (ret) -+ ath11k_warn(ab, "failed to request fw stats: %d\n", ret); -+ -+ ath11k_dbg(ab, ATH11K_DBG_WMI, -+ "debug get fw stat pdev id %d vdev id %d stats id 0x%x\n", -+ pdev_id, vdev_id, stats_id); -+ -+ return ret; -+} -+ - static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, -@@ -9031,11 +9184,12 @@ static void ath11k_mac_op_sta_statistics - - ath11k_mac_put_chain_rssi(sinfo, arsta, "ppdu", false); - -+ mutex_lock(&ar->conf_mutex); - if (!(sinfo->filled & BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL)) && - arsta->arvif->vdev_type == WMI_VDEV_TYPE_STA && - ar->ab->hw_params.supports_rssi_stats && -- !ath11k_debugfs_get_fw_stats(ar, ar->pdev->pdev_id, 0, -- WMI_REQUEST_RSSI_PER_CHAIN_STAT)) { -+ !ath11k_mac_get_fw_stats(ar, ar->pdev->pdev_id, 0, -+ WMI_REQUEST_RSSI_PER_CHAIN_STAT)) { - ath11k_mac_put_chain_rssi(sinfo, arsta, "fw stats", true); - } - -@@ -9043,9 +9197,10 @@ static void ath11k_mac_op_sta_statistics - if (!signal && - arsta->arvif->vdev_type == WMI_VDEV_TYPE_STA && - ar->ab->hw_params.supports_rssi_stats && -- !(ath11k_debugfs_get_fw_stats(ar, ar->pdev->pdev_id, 0, -- WMI_REQUEST_VDEV_STAT))) -+ !(ath11k_mac_get_fw_stats(ar, ar->pdev->pdev_id, 0, -+ WMI_REQUEST_VDEV_STAT))) - signal = arsta->rssi_beacon; -+ mutex_unlock(&ar->conf_mutex); - - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, - "sta statistics db2dbm %u rssi comb %d rssi beacon %d\n", -@@ -9380,38 +9535,6 @@ exit: - return ret; - } - --static int ath11k_fw_stats_request(struct ath11k *ar, -- struct stats_request_params *req_param) --{ -- struct ath11k_base *ab = ar->ab; -- unsigned long time_left; -- int ret; -- -- lockdep_assert_held(&ar->conf_mutex); -- -- spin_lock_bh(&ar->data_lock); -- ar->fw_stats_done = false; -- ath11k_fw_stats_pdevs_free(&ar->fw_stats.pdevs); -- spin_unlock_bh(&ar->data_lock); -- -- reinit_completion(&ar->fw_stats_complete); -- -- ret = ath11k_wmi_send_stats_request_cmd(ar, req_param); -- if (ret) { -- ath11k_warn(ab, "could not request fw stats (%d)\n", -- ret); -- return ret; -- } -- -- time_left = wait_for_completion_timeout(&ar->fw_stats_complete, -- 1 * HZ); -- -- if (!time_left) -- return -ETIMEDOUT; -- -- return 0; --} -- - static int ath11k_mac_op_get_txpower(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - unsigned int link_id, -@@ -9419,7 +9542,6 @@ static int ath11k_mac_op_get_txpower(str - { - struct ath11k *ar = hw->priv; - struct ath11k_base *ab = ar->ab; -- struct stats_request_params req_param = {0}; - struct ath11k_fw_stats_pdev *pdev; - int ret; - -@@ -9431,9 +9553,6 @@ static int ath11k_mac_op_get_txpower(str - */ - mutex_lock(&ar->conf_mutex); - -- if (ar->state != ATH11K_STATE_ON) -- goto err_fallback; -- - /* Firmware doesn't provide Tx power during CAC hence no need to fetch - * the stats. - */ -@@ -9442,10 +9561,8 @@ static int ath11k_mac_op_get_txpower(str - return -EAGAIN; - } - -- req_param.pdev_id = ar->pdev->pdev_id; -- req_param.stats_id = WMI_REQUEST_PDEV_STAT; -- -- ret = ath11k_fw_stats_request(ar, &req_param); -+ ret = ath11k_mac_get_fw_stats(ar, ar->pdev->pdev_id, 0, -+ WMI_REQUEST_PDEV_STAT); - if (ret) { - ath11k_warn(ab, "failed to request fw pdev stats: %d\n", ret); - goto err_fallback; -@@ -9497,6 +9614,21 @@ static int ath11k_mac_station_add(struct - goto exit; - } - -+ /* Driver allows the DEL KEY followed by SET KEY sequence for -+ * group keys for only when there is no clients associated, if at -+ * all firmware has entered the race during that window, -+ * reinstalling the same key when the first sta connects will allow -+ * firmware to recover from the race. -+ */ -+ if (arvif->num_stations == 1 && arvif->reinstall_group_keys) { -+ ath11k_dbg(ab, ATH11K_DBG_MAC, "set group keys on 1st station add for vdev %d\n", -+ arvif->vdev_id); -+ ret = ath11k_set_group_keys(arvif); -+ if (ret) -+ goto dec_num_station; -+ arvif->reinstall_group_keys = false; -+ } -+ - arsta->rx_stats = kzalloc(sizeof(*arsta->rx_stats), GFP_KERNEL); - if (!arsta->rx_stats) { - ret = -ENOMEM; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath11k/mac.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath11k/mac.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath11k/mac.h 2025-10-22 13:53:23.375328359 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath11k/mac.h 2025-10-22 13:53:56.599168736 -0400 -@@ -1,7 +1,7 @@ - /* SPDX-License-Identifier: BSD-3-Clause-Clear */ - /* - * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. -- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. -+ * Copyright (c) 2021-2023, 2025 Qualcomm Innovation Center, Inc. All rights reserved. - */ - - #ifndef ATH11K_MAC_H -@@ -179,4 +179,6 @@ int ath11k_mac_vif_set_keepalive(struct - void ath11k_mac_fill_reg_tpc_info(struct ath11k *ar, - struct ieee80211_vif *vif, - struct ieee80211_chanctx_conf *ctx); -+int ath11k_mac_fw_stats_request(struct ath11k *ar, -+ struct stats_request_params *req_param); - #endif -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath11k/qmi.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath11k/qmi.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath11k/qmi.c 2025-10-22 13:53:23.379328340 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath11k/qmi.c 2025-10-22 13:53:56.599168736 -0400 -@@ -2555,7 +2555,7 @@ static int ath11k_qmi_m3_load(struct ath - GFP_KERNEL); - if (!m3_mem->vaddr) { - ath11k_err(ab, "failed to allocate memory for M3 with size %zu\n", -- fw->size); -+ m3_len); - ret = -ENOMEM; - goto out; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath11k/wmi.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath11k/wmi.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath11k/wmi.c 2025-10-22 13:53:23.379328340 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath11k/wmi.c 2025-10-22 13:53:56.599168736 -0400 -@@ -8158,6 +8158,11 @@ static void ath11k_peer_assoc_conf_event - static void ath11k_update_stats_event(struct ath11k_base *ab, struct sk_buff *skb) - { - struct ath11k_fw_stats stats = {}; -+ size_t total_vdevs_started = 0; -+ struct ath11k_pdev *pdev; -+ bool is_end = true; -+ int i; -+ - struct ath11k *ar; - int ret; - -@@ -8184,25 +8189,57 @@ static void ath11k_update_stats_event(st - - spin_lock_bh(&ar->data_lock); - -- /* WMI_REQUEST_PDEV_STAT can be requested via .get_txpower mac ops or via -+ /* WMI_REQUEST_PDEV_STAT, WMI_REQUEST_VDEV_STAT and -+ * WMI_REQUEST_RSSI_PER_CHAIN_STAT can be requested via mac ops or via - * debugfs fw stats. Therefore, processing it separately. - */ - if (stats.stats_id == WMI_REQUEST_PDEV_STAT) { - list_splice_tail_init(&stats.pdevs, &ar->fw_stats.pdevs); -- ar->fw_stats_done = true; -+ complete(&ar->fw_stats_done); -+ goto complete; -+ } -+ -+ if (stats.stats_id == WMI_REQUEST_RSSI_PER_CHAIN_STAT) { -+ complete(&ar->fw_stats_done); -+ goto complete; -+ } -+ -+ if (stats.stats_id == WMI_REQUEST_VDEV_STAT) { -+ if (list_empty(&stats.vdevs)) { -+ ath11k_warn(ab, "empty vdev stats"); -+ goto complete; -+ } -+ /* FW sends all the active VDEV stats irrespective of PDEV, -+ * hence limit until the count of all VDEVs started -+ */ -+ for (i = 0; i < ab->num_radios; i++) { -+ pdev = rcu_dereference(ab->pdevs_active[i]); -+ if (pdev && pdev->ar) -+ total_vdevs_started += ar->num_started_vdevs; -+ } -+ -+ if (total_vdevs_started) -+ is_end = ((++ar->fw_stats.num_vdev_recvd) == -+ total_vdevs_started); -+ -+ list_splice_tail_init(&stats.vdevs, -+ &ar->fw_stats.vdevs); -+ -+ if (is_end) -+ complete(&ar->fw_stats_done); -+ - goto complete; - } - -- /* WMI_REQUEST_VDEV_STAT, WMI_REQUEST_BCN_STAT and WMI_REQUEST_RSSI_PER_CHAIN_STAT -- * are currently requested only via debugfs fw stats. Hence, processing these -- * in debugfs context -+ /* WMI_REQUEST_BCN_STAT is currently requested only via debugfs fw stats. -+ * Hence, processing it in debugfs context - */ - ath11k_debugfs_fw_stats_process(ar, &stats); - - complete: - complete(&ar->fw_stats_complete); -- rcu_read_unlock(); - spin_unlock_bh(&ar->data_lock); -+ rcu_read_unlock(); - - /* Since the stats's pdev, vdev and beacon list are spliced and reinitialised - * at this point, no need to free the individual list. -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/ce.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/ce.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/ce.c 2025-10-22 13:53:23.379328340 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/ce.c 2025-10-22 13:53:56.603168717 -0400 -@@ -433,9 +433,6 @@ static int ath12k_ce_completed_recv_next - goto err; - } - -- /* Make sure descriptor is read after the head pointer. */ -- dma_rmb(); -- - *nbytes = ath12k_hal_ce_dst_status_get_length(desc); - - *skb = pipe->dest_ring->skb[sw_index]; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/core.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/core.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/core.c 2025-10-22 13:53:23.379328340 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/core.c 2025-10-22 13:53:56.603168717 -0400 -@@ -1216,6 +1216,7 @@ void ath12k_fw_stats_init(struct ath12k - INIT_LIST_HEAD(&ar->fw_stats.pdevs); - INIT_LIST_HEAD(&ar->fw_stats.bcn); - init_completion(&ar->fw_stats_complete); -+ init_completion(&ar->fw_stats_done); - } - - void ath12k_fw_stats_free(struct ath12k_fw_stats *stats) -@@ -1228,8 +1229,9 @@ void ath12k_fw_stats_free(struct ath12k_ - void ath12k_fw_stats_reset(struct ath12k *ar) - { - spin_lock_bh(&ar->data_lock); -- ar->fw_stats.fw_stats_done = false; - ath12k_fw_stats_free(&ar->fw_stats); -+ ar->fw_stats.num_vdev_recvd = 0; -+ ar->fw_stats.num_bcn_recvd = 0; - spin_unlock_bh(&ar->data_lock); - } - -@@ -1407,6 +1409,7 @@ void ath12k_core_halt(struct ath12k *ar) - ath12k_mac_peer_cleanup_all(ar); - cancel_delayed_work_sync(&ar->scan.timeout); - cancel_work_sync(&ar->regd_update_work); -+ cancel_work_sync(&ar->regd_channel_update_work); - cancel_work_sync(&ab->rfkill_work); - cancel_work_sync(&ab->update_11d_work); - -@@ -2129,7 +2132,8 @@ int ath12k_core_init(struct ath12k_base - if (!ag) { - mutex_unlock(&ath12k_hw_group_mutex); - ath12k_warn(ab, "unable to get hw group\n"); -- return -ENODEV; -+ ret = -ENODEV; -+ goto err_unregister_notifier; - } - - mutex_unlock(&ath12k_hw_group_mutex); -@@ -2144,7 +2148,7 @@ int ath12k_core_init(struct ath12k_base - if (ret) { - mutex_unlock(&ag->mutex); - ath12k_warn(ab, "unable to create hw group\n"); -- goto err; -+ goto err_destroy_hw_group; - } - } - -@@ -2152,9 +2156,12 @@ int ath12k_core_init(struct ath12k_base - - return 0; - --err: -+err_destroy_hw_group: - ath12k_core_hw_group_destroy(ab->ag); - ath12k_core_hw_group_unassign(ab); -+err_unregister_notifier: -+ ath12k_core_panic_notifier_unregister(ab); -+ - return ret; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/core.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/core.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/core.h 2025-10-22 13:53:23.379328340 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/core.h 2025-10-22 13:53:56.603168717 -0400 -@@ -116,6 +116,7 @@ static inline u64 ath12k_le32hilo_to_u64 - enum ath12k_skb_flags { - ATH12K_SKB_HW_80211_ENCAP = BIT(0), - ATH12K_SKB_CIPHER_SET = BIT(1), -+ ATH12K_SKB_MLO_STA = BIT(2), - }; - - struct ath12k_skb_cb { -@@ -345,6 +346,10 @@ struct ath12k_link_vif { - bool is_sta_assoc_link; - - struct ath12k_reg_tpc_power_info reg_tpc_info; -+ -+ bool group_key_valid; -+ struct wmi_vdev_install_key_arg group_key; -+ bool pairwise_key_done; - }; - - struct ath12k_vif { -@@ -601,6 +606,12 @@ struct ath12k_sta { - #define ATH12K_NUM_CHANS 101 - #define ATH12K_MAX_5GHZ_CHAN 173 - -+static inline bool ath12k_is_2ghz_channel_freq(u32 freq) -+{ -+ return freq >= ATH12K_MIN_2GHZ_FREQ && -+ freq <= ATH12K_MAX_2GHZ_FREQ; -+} -+ - enum ath12k_hw_state { - ATH12K_HW_STATE_OFF, - ATH12K_HW_STATE_ON, -@@ -626,7 +637,8 @@ struct ath12k_fw_stats { - struct list_head pdevs; - struct list_head vdevs; - struct list_head bcn; -- bool fw_stats_done; -+ u32 num_vdev_recvd; -+ u32 num_bcn_recvd; - }; - - struct ath12k_dbg_htt_stats { -@@ -712,7 +724,7 @@ struct ath12k { - - /* protects the radio specific data like debug stats, ppdu_stats_info stats, - * vdev_stop_status info, scan data, ath12k_sta info, ath12k_link_vif info, -- * channel context data, survey info, test mode data. -+ * channel context data, survey info, test mode data, regd_channel_update_queue. - */ - spinlock_t data_lock; - -@@ -771,6 +783,8 @@ struct ath12k { - struct completion bss_survey_done; - - struct work_struct regd_update_work; -+ struct work_struct regd_channel_update_work; -+ struct list_head regd_channel_update_queue; - - struct wiphy_work wmi_mgmt_tx_work; - struct sk_buff_head wmi_mgmt_tx_queue; -@@ -806,6 +820,7 @@ struct ath12k { - bool regdom_set_by_user; - - struct completion fw_stats_complete; -+ struct completion fw_stats_done; - - struct completion mlo_setup_done; - u32 mlo_setup_status; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/debugfs.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/debugfs.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/debugfs.c 2025-10-22 13:53:23.379328340 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/debugfs.c 2025-10-22 13:53:56.603168717 -0400 -@@ -1251,64 +1251,6 @@ void ath12k_debugfs_soc_destroy(struct a - */ - } - --void --ath12k_debugfs_fw_stats_process(struct ath12k *ar, -- struct ath12k_fw_stats *stats) --{ -- struct ath12k_base *ab = ar->ab; -- struct ath12k_pdev *pdev; -- bool is_end; -- static unsigned int num_vdev, num_bcn; -- size_t total_vdevs_started = 0; -- int i; -- -- if (stats->stats_id == WMI_REQUEST_VDEV_STAT) { -- if (list_empty(&stats->vdevs)) { -- ath12k_warn(ab, "empty vdev stats"); -- return; -- } -- /* FW sends all the active VDEV stats irrespective of PDEV, -- * hence limit until the count of all VDEVs started -- */ -- rcu_read_lock(); -- for (i = 0; i < ab->num_radios; i++) { -- pdev = rcu_dereference(ab->pdevs_active[i]); -- if (pdev && pdev->ar) -- total_vdevs_started += pdev->ar->num_started_vdevs; -- } -- rcu_read_unlock(); -- -- is_end = ((++num_vdev) == total_vdevs_started); -- -- list_splice_tail_init(&stats->vdevs, -- &ar->fw_stats.vdevs); -- -- if (is_end) { -- ar->fw_stats.fw_stats_done = true; -- num_vdev = 0; -- } -- return; -- } -- if (stats->stats_id == WMI_REQUEST_BCN_STAT) { -- if (list_empty(&stats->bcn)) { -- ath12k_warn(ab, "empty beacon stats"); -- return; -- } -- /* Mark end until we reached the count of all started VDEVs -- * within the PDEV -- */ -- is_end = ((++num_bcn) == ar->num_started_vdevs); -- -- list_splice_tail_init(&stats->bcn, -- &ar->fw_stats.bcn); -- -- if (is_end) { -- ar->fw_stats.fw_stats_done = true; -- num_bcn = 0; -- } -- } --} -- - static int ath12k_open_vdev_stats(struct inode *inode, struct file *file) - { - struct ath12k *ar = inode->i_private; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/debugfs.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/debugfs.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/debugfs.h 2025-10-22 13:53:23.379328340 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/debugfs.h 2025-10-22 13:53:56.603168717 -0400 -@@ -12,8 +12,6 @@ void ath12k_debugfs_soc_create(struct at - void ath12k_debugfs_soc_destroy(struct ath12k_base *ab); - void ath12k_debugfs_register(struct ath12k *ar); - void ath12k_debugfs_unregister(struct ath12k *ar); --void ath12k_debugfs_fw_stats_process(struct ath12k *ar, -- struct ath12k_fw_stats *stats); - void ath12k_debugfs_op_vif_add(struct ieee80211_hw *hw, - struct ieee80211_vif *vif); - void ath12k_debugfs_pdev_create(struct ath12k_base *ab); -@@ -126,11 +124,6 @@ static inline void ath12k_debugfs_unregi - { - } - --static inline void ath12k_debugfs_fw_stats_process(struct ath12k *ar, -- struct ath12k_fw_stats *stats) --{ --} -- - static inline bool ath12k_debugfs_is_extd_rx_stats_enabled(struct ath12k *ar) - { - return false; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h 2025-10-22 13:53:23.379328340 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h 2025-10-22 13:53:56.603168717 -0400 -@@ -470,7 +470,7 @@ struct ath12k_htt_tx_pdev_rate_stats_tlv - [ATH12K_HTT_TX_PDEV_STATS_NUM_EXTRA_MCS_COUNTERS]; - __le32 tx_mcs_ext_2[ATH12K_HTT_TX_PDEV_STATS_NUM_EXTRA2_MCS_COUNTERS]; - __le32 tx_bw_320mhz; --}; -+} __packed; - - #define ATH12K_HTT_RX_PDEV_STATS_NUM_LEGACY_CCK_STATS 4 - #define ATH12K_HTT_RX_PDEV_STATS_NUM_LEGACY_OFDM_STATS 8 -@@ -550,7 +550,7 @@ struct ath12k_htt_rx_pdev_rate_stats_tlv - __le32 rx_ulofdma_non_data_nusers[ATH12K_HTT_RX_PDEV_MAX_OFDMA_NUM_USER]; - __le32 rx_ulofdma_data_nusers[ATH12K_HTT_RX_PDEV_MAX_OFDMA_NUM_USER]; - __le32 rx_mcs_ext[ATH12K_HTT_RX_PDEV_STATS_NUM_EXTRA_MCS_COUNTERS]; --}; -+} __packed; - - #define ATH12K_HTT_RX_PDEV_STATS_NUM_BW_EXT_COUNTERS 4 - #define ATH12K_HTT_RX_PDEV_STATS_NUM_MCS_COUNTERS_EXT 14 -@@ -580,7 +580,7 @@ struct ath12k_htt_rx_pdev_rate_ext_stats - __le32 rx_gi_ext_2[ATH12K_HTT_RX_PDEV_STATS_NUM_GI_COUNTERS] - [ATH12K_HTT_RX_PDEV_STATS_NUM_EXTRA2_MCS_COUNTERS]; - __le32 rx_su_punctured_mode[ATH12K_HTT_RX_PDEV_STATS_NUM_PUNCTURED_MODE_COUNTERS]; --}; -+} __packed; - - #define ATH12K_HTT_TX_PDEV_STATS_SCHED_PER_TXQ_MAC_ID GENMASK(7, 0) - #define ATH12K_HTT_TX_PDEV_STATS_SCHED_PER_TXQ_ID GENMASK(15, 8) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/dp.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/dp.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/dp.c 2025-10-22 13:53:23.379328340 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/dp.c 2025-10-22 13:53:56.603168717 -0400 -@@ -84,6 +84,7 @@ int ath12k_dp_peer_setup(struct ath12k * - ret = ath12k_dp_rx_peer_frag_setup(ar, addr, vdev_id); - if (ret) { - ath12k_warn(ab, "failed to setup rx defrag context\n"); -+ tid--; - goto peer_clean; - } - -@@ -101,7 +102,7 @@ peer_clean: - return -ENOENT; - } - -- for (; tid >= 0; tid--) -+ for (tid--; tid >= 0; tid--) - ath12k_dp_rx_peer_tid_delete(ar, peer, tid); - - spin_unlock_bh(&ab->base_lock); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/dp.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/dp.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/dp.h 2025-10-22 13:53:23.379328340 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/dp.h 2025-10-22 13:53:56.603168717 -0400 -@@ -469,6 +469,7 @@ enum htt_h2t_msg_type { - }; - - #define HTT_VER_REQ_INFO_MSG_ID GENMASK(7, 0) -+#define HTT_OPTION_TCL_METADATA_VER_V1 1 - #define HTT_OPTION_TCL_METADATA_VER_V2 2 - #define HTT_OPTION_TAG GENMASK(7, 0) - #define HTT_OPTION_LEN GENMASK(15, 8) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/dp_mon.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/dp_mon.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/dp_mon.c 2025-10-22 13:53:23.379328340 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/dp_mon.c 2025-10-22 13:53:56.603168717 -0400 -@@ -3610,7 +3610,6 @@ ath12k_dp_mon_rx_update_user_stats(struc - struct hal_rx_mon_ppdu_info *ppdu_info, - u32 uid) - { -- struct ath12k_sta *ahsta; - struct ath12k_link_sta *arsta; - struct ath12k_rx_peer_stats *rx_stats = NULL; - struct hal_rx_user_status *user_stats = &ppdu_info->userstats[uid]; -@@ -3628,8 +3627,13 @@ ath12k_dp_mon_rx_update_user_stats(struc - return; - } - -- ahsta = ath12k_sta_to_ahsta(peer->sta); -- arsta = &ahsta->deflink; -+ arsta = ath12k_peer_get_link_sta(ar->ab, peer); -+ if (!arsta) { -+ ath12k_warn(ar->ab, "link sta not found on peer %pM id %d\n", -+ peer->addr, peer->peer_id); -+ return; -+ } -+ - arsta->rssi_comb = ppdu_info->rssi_comb; - ewma_avg_rssi_add(&arsta->avg_rssi, ppdu_info->rssi_comb); - rx_stats = arsta->rx_stats; -@@ -3742,7 +3746,6 @@ int ath12k_dp_mon_srng_process(struct at - struct dp_srng *mon_dst_ring; - struct hal_srng *srng; - struct dp_rxdma_mon_ring *buf_ring; -- struct ath12k_sta *ahsta = NULL; - struct ath12k_link_sta *arsta; - struct ath12k_peer *peer; - struct sk_buff_head skb_list; -@@ -3761,7 +3764,6 @@ int ath12k_dp_mon_srng_process(struct at - ath12k_hal_srng_access_begin(ab, srng); - - while (likely(*budget)) { -- *budget -= 1; - mon_dst_desc = ath12k_hal_srng_dst_peek(ab, srng); - if (unlikely(!mon_dst_desc)) - break; -@@ -3869,8 +3871,15 @@ move_next: - } - - if (ppdu_info->reception_type == HAL_RX_RECEPTION_TYPE_SU) { -- ahsta = ath12k_sta_to_ahsta(peer->sta); -- arsta = &ahsta->deflink; -+ arsta = ath12k_peer_get_link_sta(ar->ab, peer); -+ if (!arsta) { -+ ath12k_warn(ar->ab, "link sta not found on peer %pM id %d\n", -+ peer->addr, peer->peer_id); -+ spin_unlock_bh(&ab->base_lock); -+ rcu_read_unlock(); -+ dev_kfree_skb_any(skb); -+ continue; -+ } - ath12k_dp_mon_rx_update_peer_su_stats(ar, arsta, - ppdu_info); - } else if ((ppdu_info->fc_valid) && -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/dp_rx.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/dp_rx.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/dp_rx.c 2025-10-22 13:53:23.379328340 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/dp_rx.c 2025-10-22 13:53:56.603168717 -0400 -@@ -1060,7 +1060,6 @@ int ath12k_dp_rx_peer_tid_setup(struct a - } - - rx_tid = &peer->rx_tid[tid]; -- paddr_aligned = rx_tid->qbuf.paddr_aligned; - /* Update the tid queue if it is already setup */ - if (rx_tid->active) { - ret = ath12k_peer_rx_tid_reo_update(ar, peer, rx_tid, -@@ -1072,6 +1071,7 @@ int ath12k_dp_rx_peer_tid_setup(struct a - } - - if (!ab->hw_params->reoq_lut_support) { -+ paddr_aligned = rx_tid->qbuf.paddr_aligned; - ret = ath12k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, - peer_mac, - paddr_aligned, tid, -@@ -1098,6 +1098,7 @@ int ath12k_dp_rx_peer_tid_setup(struct a - return ret; - } - -+ paddr_aligned = rx_tid->qbuf.paddr_aligned; - if (ab->hw_params->reoq_lut_support) { - /* Update the REO queue LUT at the corresponding peer id - * and tid with qaddr. -@@ -1417,8 +1418,6 @@ ath12k_update_per_peer_tx_stats(struct a - { - struct ath12k_base *ab = ar->ab; - struct ath12k_peer *peer; -- struct ieee80211_sta *sta; -- struct ath12k_sta *ahsta; - struct ath12k_link_sta *arsta; - struct htt_ppdu_stats_user_rate *user_rate; - struct ath12k_per_peer_tx_stats *peer_stats = &ar->peer_tx_stats; -@@ -1499,9 +1498,12 @@ ath12k_update_per_peer_tx_stats(struct a - return; - } - -- sta = peer->sta; -- ahsta = ath12k_sta_to_ahsta(sta); -- arsta = &ahsta->deflink; -+ arsta = ath12k_peer_get_link_sta(ab, peer); -+ if (!arsta) { -+ spin_unlock_bh(&ab->base_lock); -+ rcu_read_unlock(); -+ return; -+ } - - memset(&arsta->txrate, 0, sizeof(arsta->txrate)); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/dp_tx.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/dp_tx.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/dp_tx.c 2025-10-22 13:53:23.379328340 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/dp_tx.c 2025-10-22 13:53:56.603168717 -0400 -@@ -13,10 +13,9 @@ - #include "mac.h" - - static enum hal_tcl_encap_type --ath12k_dp_tx_get_encap_type(struct ath12k_link_vif *arvif, struct sk_buff *skb) -+ath12k_dp_tx_get_encap_type(struct ath12k_base *ab, struct sk_buff *skb) - { - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); -- struct ath12k_base *ab = arvif->ar->ab; - - if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags)) - return HAL_TCL_ENCAP_TYPE_RAW; -@@ -305,7 +304,7 @@ tcl_ring_sel: - u32_encode_bits(mcbc_gsn, HTT_TCL_META_DATA_GLOBAL_SEQ_NUM); - } - -- ti.encap_type = ath12k_dp_tx_get_encap_type(arvif, skb); -+ ti.encap_type = ath12k_dp_tx_get_encap_type(ab, skb); - ti.addr_search_flags = arvif->hal_addr_search_flags; - ti.search_type = arvif->search_type; - ti.type = HAL_TCL_DESC_TYPE_BUFFER; -@@ -1183,6 +1182,7 @@ int ath12k_dp_tx_htt_h2t_ver_req_msg(str - struct sk_buff *skb; - struct htt_ver_req_cmd *cmd; - int len = sizeof(*cmd); -+ u32 metadata_version; - int ret; - - init_completion(&dp->htt_tgt_version_received); -@@ -1195,12 +1195,14 @@ int ath12k_dp_tx_htt_h2t_ver_req_msg(str - cmd = (struct htt_ver_req_cmd *)skb->data; - cmd->ver_reg_info = le32_encode_bits(HTT_H2T_MSG_TYPE_VERSION_REQ, - HTT_OPTION_TAG); -+ metadata_version = ath12k_ftm_mode ? HTT_OPTION_TCL_METADATA_VER_V1 : -+ HTT_OPTION_TCL_METADATA_VER_V2; - - cmd->tcl_metadata_version = le32_encode_bits(HTT_TAG_TCL_METADATA_VERSION, - HTT_OPTION_TAG) | - le32_encode_bits(HTT_TCL_METADATA_VER_SZ, - HTT_OPTION_LEN) | -- le32_encode_bits(HTT_OPTION_TCL_METADATA_VER_V2, -+ le32_encode_bits(metadata_version, - HTT_OPTION_VALUE); - - ret = ath12k_htc_send(&ab->htc, dp->eid, skb); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/hal.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/hal.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/hal.c 2025-10-22 13:53:23.379328340 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/hal.c 2025-10-22 13:53:56.603168717 -0400 -@@ -2143,13 +2143,24 @@ void *ath12k_hal_srng_src_get_next_reape - - void ath12k_hal_srng_access_begin(struct ath12k_base *ab, struct hal_srng *srng) - { -+ u32 hp; -+ - lockdep_assert_held(&srng->lock); - -- if (srng->ring_dir == HAL_SRNG_DIR_SRC) -+ if (srng->ring_dir == HAL_SRNG_DIR_SRC) { - srng->u.src_ring.cached_tp = - *(volatile u32 *)srng->u.src_ring.tp_addr; -- else -- srng->u.dst_ring.cached_hp = READ_ONCE(*srng->u.dst_ring.hp_addr); -+ } else { -+ hp = READ_ONCE(*srng->u.dst_ring.hp_addr); -+ -+ if (hp != srng->u.dst_ring.cached_hp) { -+ srng->u.dst_ring.cached_hp = hp; -+ /* Make sure descriptor is read after the head -+ * pointer. -+ */ -+ dma_rmb(); -+ } -+ } - } - - /* Update cached ring head/tail pointers to HW. ath12k_hal_srng_access_begin() -@@ -2159,7 +2170,6 @@ void ath12k_hal_srng_access_end(struct a - { - lockdep_assert_held(&srng->lock); - -- /* TODO: See if we need a write memory barrier here */ - if (srng->flags & HAL_SRNG_FLAGS_LMAC_RING) { - /* For LMAC rings, ring pointer updates are done through FW and - * hence written to a shared memory location that is read by FW -@@ -2167,21 +2177,37 @@ void ath12k_hal_srng_access_end(struct a - if (srng->ring_dir == HAL_SRNG_DIR_SRC) { - srng->u.src_ring.last_tp = - *(volatile u32 *)srng->u.src_ring.tp_addr; -- *srng->u.src_ring.hp_addr = srng->u.src_ring.hp; -+ /* Make sure descriptor is written before updating the -+ * head pointer. -+ */ -+ dma_wmb(); -+ WRITE_ONCE(*srng->u.src_ring.hp_addr, srng->u.src_ring.hp); - } else { - srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr; -- *srng->u.dst_ring.tp_addr = srng->u.dst_ring.tp; -+ /* Make sure descriptor is read before updating the -+ * tail pointer. -+ */ -+ dma_mb(); -+ WRITE_ONCE(*srng->u.dst_ring.tp_addr, srng->u.dst_ring.tp); - } - } else { - if (srng->ring_dir == HAL_SRNG_DIR_SRC) { - srng->u.src_ring.last_tp = - *(volatile u32 *)srng->u.src_ring.tp_addr; -+ /* Assume implementation use an MMIO write accessor -+ * which has the required wmb() so that the descriptor -+ * is written before the updating the head pointer. -+ */ - ath12k_hif_write32(ab, - (unsigned long)srng->u.src_ring.hp_addr - - (unsigned long)ab->mem, - srng->u.src_ring.hp); - } else { - srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr; -+ /* Make sure descriptor is read before updating the -+ * tail pointer. -+ */ -+ mb(); - ath12k_hif_write32(ab, - (unsigned long)srng->u.dst_ring.tp_addr - - (unsigned long)ab->mem, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/hal.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/hal.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/hal.h 2025-10-22 13:53:23.379328340 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/hal.h 2025-10-22 13:53:56.603168717 -0400 -@@ -585,7 +585,8 @@ enum hal_reo_cmd_type { - * or cache was blocked - * @HAL_REO_CMD_FAILED: Command execution failed, could be due to - * invalid queue desc -- * @HAL_REO_CMD_RESOURCE_BLOCKED: -+ * @HAL_REO_CMD_RESOURCE_BLOCKED: Command could not be executed because -+ * one or more descriptors were blocked - * @HAL_REO_CMD_DRAIN: - */ - enum hal_reo_cmd_status { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/hw.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/hw.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/hw.c 2025-10-22 13:53:23.379328340 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/hw.c 2025-10-22 13:53:56.603168717 -0400 -@@ -14,6 +14,7 @@ - #include "hw.h" - #include "mhi.h" - #include "dp_rx.h" -+#include "peer.h" - - static const guid_t wcn7850_uuid = GUID_INIT(0xf634f534, 0x6147, 0x11ec, - 0x90, 0xd6, 0x02, 0x42, -@@ -49,6 +50,12 @@ static bool ath12k_dp_srng_is_comp_ring_ - return false; - } - -+static bool ath12k_is_frame_link_agnostic_qcn9274(struct ath12k_link_vif *arvif, -+ struct ieee80211_mgmt *mgmt) -+{ -+ return ieee80211_is_action(mgmt->frame_control); -+} -+ - static int ath12k_hw_mac_id_to_pdev_id_wcn7850(const struct ath12k_hw_params *hw, - int mac_id) - { -@@ -74,6 +81,52 @@ static bool ath12k_dp_srng_is_comp_ring_ - return false; - } - -+static bool ath12k_is_addba_resp_action_code(struct ieee80211_mgmt *mgmt) -+{ -+ if (!ieee80211_is_action(mgmt->frame_control)) -+ return false; -+ -+ if (mgmt->u.action.category != WLAN_CATEGORY_BACK) -+ return false; -+ -+ if (mgmt->u.action.u.addba_resp.action_code != WLAN_ACTION_ADDBA_RESP) -+ return false; -+ -+ return true; -+} -+ -+static bool ath12k_is_frame_link_agnostic_wcn7850(struct ath12k_link_vif *arvif, -+ struct ieee80211_mgmt *mgmt) -+{ -+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif); -+ struct ath12k_hw *ah = ath12k_ar_to_ah(arvif->ar); -+ struct ath12k_base *ab = arvif->ar->ab; -+ __le16 fc = mgmt->frame_control; -+ -+ spin_lock_bh(&ab->base_lock); -+ if (!ath12k_peer_find_by_addr(ab, mgmt->da) && -+ !ath12k_peer_ml_find(ah, mgmt->da)) { -+ spin_unlock_bh(&ab->base_lock); -+ return false; -+ } -+ spin_unlock_bh(&ab->base_lock); -+ -+ if (vif->type == NL80211_IFTYPE_STATION) -+ return arvif->is_up && -+ (vif->valid_links == vif->active_links) && -+ !ieee80211_is_probe_req(fc) && -+ !ieee80211_is_auth(fc) && -+ !ieee80211_is_deauth(fc) && -+ !ath12k_is_addba_resp_action_code(mgmt); -+ -+ if (vif->type == NL80211_IFTYPE_AP) -+ return !(ieee80211_is_probe_resp(fc) || ieee80211_is_auth(fc) || -+ ieee80211_is_assoc_resp(fc) || ieee80211_is_reassoc_resp(fc) || -+ ath12k_is_addba_resp_action_code(mgmt)); -+ -+ return false; -+} -+ - static const struct ath12k_hw_ops qcn9274_ops = { - .get_hw_mac_from_pdev_id = ath12k_hw_qcn9274_mac_from_pdev_id, - .mac_id_to_pdev_id = ath12k_hw_mac_id_to_pdev_id_qcn9274, -@@ -81,6 +134,7 @@ static const struct ath12k_hw_ops qcn927 - .rxdma_ring_sel_config = ath12k_dp_rxdma_ring_sel_config_qcn9274, - .get_ring_selector = ath12k_hw_get_ring_selector_qcn9274, - .dp_srng_is_tx_comp_ring = ath12k_dp_srng_is_comp_ring_qcn9274, -+ .is_frame_link_agnostic = ath12k_is_frame_link_agnostic_qcn9274, - }; - - static const struct ath12k_hw_ops wcn7850_ops = { -@@ -90,6 +144,7 @@ static const struct ath12k_hw_ops wcn785 - .rxdma_ring_sel_config = ath12k_dp_rxdma_ring_sel_config_wcn7850, - .get_ring_selector = ath12k_hw_get_ring_selector_wcn7850, - .dp_srng_is_tx_comp_ring = ath12k_dp_srng_is_comp_ring_wcn7850, -+ .is_frame_link_agnostic = ath12k_is_frame_link_agnostic_wcn7850, - }; - - #define ATH12K_TX_RING_MASK_0 0x1 -@@ -951,6 +1006,8 @@ static const struct ath12k_hw_regs qcn92 - .hal_umac_ce0_dest_reg_base = 0x01b81000, - .hal_umac_ce1_src_reg_base = 0x01b82000, - .hal_umac_ce1_dest_reg_base = 0x01b83000, -+ -+ .gcc_gcc_pcie_hot_rst = 0x1e38338, - }; - - static const struct ath12k_hw_regs qcn9274_v2_regs = { -@@ -1042,6 +1099,8 @@ static const struct ath12k_hw_regs qcn92 - .hal_umac_ce0_dest_reg_base = 0x01b81000, - .hal_umac_ce1_src_reg_base = 0x01b82000, - .hal_umac_ce1_dest_reg_base = 0x01b83000, -+ -+ .gcc_gcc_pcie_hot_rst = 0x1e38338, - }; - - static const struct ath12k_hw_regs ipq5332_regs = { -@@ -1215,6 +1274,8 @@ static const struct ath12k_hw_regs wcn78 - .hal_umac_ce0_dest_reg_base = 0x01b81000, - .hal_umac_ce1_src_reg_base = 0x01b82000, - .hal_umac_ce1_dest_reg_base = 0x01b83000, -+ -+ .gcc_gcc_pcie_hot_rst = 0x1e40304, - }; - - static const struct ath12k_hw_hal_params ath12k_hw_hal_params_qcn9274 = { -@@ -1472,7 +1533,7 @@ static const struct ath12k_hw_params ath - .download_calib = true, - .supports_suspend = false, - .tcl_ring_retry = true, -- .reoq_lut_support = false, -+ .reoq_lut_support = true, - .supports_shadow_regs = false, - - .num_tcl_banks = 48, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/hw.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/hw.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/hw.h 2025-10-22 13:53:23.379328340 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/hw.h 2025-10-22 13:53:56.603168717 -0400 -@@ -246,6 +246,8 @@ struct ath12k_hw_ops { - int (*rxdma_ring_sel_config)(struct ath12k_base *ab); - u8 (*get_ring_selector)(struct sk_buff *skb); - bool (*dp_srng_is_tx_comp_ring)(int ring_num); -+ bool (*is_frame_link_agnostic)(struct ath12k_link_vif *arvif, -+ struct ieee80211_mgmt *mgmt); - }; - - static inline -@@ -375,6 +377,8 @@ struct ath12k_hw_regs { - u32 hal_reo_cmd_ring_base; - - u32 hal_reo_status_ring_base; -+ -+ u32 gcc_gcc_pcie_hot_rst; - }; - - static inline const char *ath12k_bd_ie_type_str(enum ath12k_bd_ie_type type) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/mac.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/mac.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/mac.c 2025-10-22 13:53:23.383328321 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/mac.c 2025-10-22 13:53:56.603168717 -0400 -@@ -602,6 +602,33 @@ ath12k_mac_get_tx_arvif(struct ath12k_li - return NULL; - } - -+static const u8 *ath12k_mac_get_tx_bssid(struct ath12k_link_vif *arvif) -+{ -+ struct ieee80211_bss_conf *link_conf; -+ struct ath12k_link_vif *tx_arvif; -+ struct ath12k *ar = arvif->ar; -+ -+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); -+ -+ link_conf = ath12k_mac_get_link_bss_conf(arvif); -+ if (!link_conf) { -+ ath12k_warn(ar->ab, -+ "unable to access bss link conf for link %u required to retrieve transmitting link conf\n", -+ arvif->link_id); -+ return NULL; -+ } -+ if (link_conf->vif->type == NL80211_IFTYPE_STATION) { -+ if (link_conf->nontransmitted) -+ return link_conf->transmitter_bssid; -+ } else { -+ tx_arvif = ath12k_mac_get_tx_arvif(arvif, link_conf); -+ if (tx_arvif) -+ return tx_arvif->bssid; -+ } -+ -+ return NULL; -+} -+ - struct ieee80211_bss_conf * - ath12k_mac_get_link_bss_conf(struct ath12k_link_vif *arvif) - { -@@ -693,6 +720,9 @@ static void ath12k_get_arvif_iter(void * - if (WARN_ON(!arvif)) - continue; - -+ if (!arvif->is_created) -+ continue; -+ - if (arvif->vdev_id == arvif_iter->vdev_id && - arvif->ar == arvif_iter->ar) { - arvif_iter->arvif = arvif; -@@ -1688,8 +1718,6 @@ static void ath12k_control_beaconing(str - { - struct ath12k_wmi_vdev_up_params params = {}; - struct ath12k_vif *ahvif = arvif->ahvif; -- struct ieee80211_bss_conf *link_conf; -- struct ath12k_link_vif *tx_arvif; - struct ath12k *ar = arvif->ar; - int ret; - -@@ -1720,18 +1748,8 @@ static void ath12k_control_beaconing(str - params.vdev_id = arvif->vdev_id; - params.aid = ahvif->aid; - params.bssid = arvif->bssid; -- -- link_conf = ath12k_mac_get_link_bss_conf(arvif); -- if (!link_conf) { -- ath12k_warn(ar->ab, -- "unable to access bss link conf for link %u required to retrieve transmitting link conf\n", -- arvif->link_id); -- return; -- } -- -- tx_arvif = ath12k_mac_get_tx_arvif(arvif, link_conf); -- if (tx_arvif) { -- params.tx_bssid = tx_arvif->bssid; -+ params.tx_bssid = ath12k_mac_get_tx_bssid(arvif); -+ if (params.tx_bssid) { - params.nontx_profile_idx = info->bssid_index; - params.nontx_profile_cnt = 1 << info->bssid_indicator; - } -@@ -1755,7 +1773,7 @@ static void ath12k_mac_handle_beacon_ite - struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); - struct ath12k_link_vif *arvif = &ahvif->deflink; - -- if (vif->type != NL80211_IFTYPE_STATION) -+ if (vif->type != NL80211_IFTYPE_STATION || !arvif->is_created) - return; - - if (!ether_addr_equal(mgmt->bssid, vif->bss_conf.bssid)) -@@ -1778,16 +1796,16 @@ static void ath12k_mac_handle_beacon_mis - u32 *vdev_id = data; - struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); - struct ath12k_link_vif *arvif = &ahvif->deflink; -- struct ath12k *ar = arvif->ar; -- struct ieee80211_hw *hw = ath12k_ar_to_hw(ar); -+ struct ieee80211_hw *hw; - -- if (arvif->vdev_id != *vdev_id) -+ if (!arvif->is_created || arvif->vdev_id != *vdev_id) - return; - - if (!arvif->is_up) - return; - - ieee80211_beacon_loss(vif); -+ hw = ath12k_ar_to_hw(arvif->ar); - - /* Firmware doesn't report beacon loss events repeatedly. If AP probe - * (done by mac80211) succeeds but beacons do not resume then it -@@ -3232,6 +3250,7 @@ static void ath12k_bss_assoc(struct ath1 - - rcu_read_unlock(); - -+ peer_arg->is_assoc = true; - ret = ath12k_wmi_send_peer_assoc_cmd(ar, peer_arg); - if (ret) { - ath12k_warn(ar->ab, "failed to run peer assoc for %pM vdev %i: %d\n", -@@ -3261,6 +3280,11 @@ static void ath12k_bss_assoc(struct ath1 - params.vdev_id = arvif->vdev_id; - params.aid = ahvif->aid; - params.bssid = arvif->bssid; -+ params.tx_bssid = ath12k_mac_get_tx_bssid(arvif); -+ if (params.tx_bssid) { -+ params.nontx_profile_idx = bss_conf->bssid_index; -+ params.nontx_profile_cnt = 1 << bss_conf->bssid_indicator; -+ } - ret = ath12k_wmi_vdev_up(ar, ¶ms); - if (ret) { - ath12k_warn(ar->ab, "failed to set vdev %d up: %d\n", -@@ -3626,12 +3650,68 @@ static int ath12k_mac_fils_discovery(str - return ret; - } - -+static void ath12k_mac_vif_setup_ps(struct ath12k_link_vif *arvif) -+{ -+ struct ath12k *ar = arvif->ar; -+ struct ieee80211_vif *vif = arvif->ahvif->vif; -+ struct ieee80211_conf *conf = &ath12k_ar_to_hw(ar)->conf; -+ enum wmi_sta_powersave_param param; -+ struct ieee80211_bss_conf *info; -+ enum wmi_sta_ps_mode psmode; -+ int ret; -+ int timeout; -+ bool enable_ps; -+ -+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); -+ -+ if (vif->type != NL80211_IFTYPE_STATION) -+ return; -+ -+ enable_ps = arvif->ahvif->ps; -+ if (enable_ps) { -+ psmode = WMI_STA_PS_MODE_ENABLED; -+ param = WMI_STA_PS_PARAM_INACTIVITY_TIME; -+ -+ timeout = conf->dynamic_ps_timeout; -+ if (timeout == 0) { -+ info = ath12k_mac_get_link_bss_conf(arvif); -+ if (!info) { -+ ath12k_warn(ar->ab, "unable to access bss link conf in setup ps for vif %pM link %u\n", -+ vif->addr, arvif->link_id); -+ return; -+ } -+ -+ /* firmware doesn't like 0 */ -+ timeout = ieee80211_tu_to_usec(info->beacon_int) / 1000; -+ } -+ -+ ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param, -+ timeout); -+ if (ret) { -+ ath12k_warn(ar->ab, "failed to set inactivity time for vdev %d: %i\n", -+ arvif->vdev_id, ret); -+ return; -+ } -+ } else { -+ psmode = WMI_STA_PS_MODE_DISABLED; -+ } -+ -+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %d psmode %s\n", -+ arvif->vdev_id, psmode ? "enable" : "disable"); -+ -+ ret = ath12k_wmi_pdev_set_ps_mode(ar, arvif->vdev_id, psmode); -+ if (ret) -+ ath12k_warn(ar->ab, "failed to set sta power save mode %d for vdev %d: %d\n", -+ psmode, arvif->vdev_id, ret); -+} -+ - static void ath12k_mac_op_vif_cfg_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - u64 changed) - { - struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); - unsigned long links = ahvif->links_map; -+ struct ieee80211_vif_cfg *vif_cfg; - struct ieee80211_bss_conf *info; - struct ath12k_link_vif *arvif; - struct ieee80211_sta *sta; -@@ -3695,61 +3775,24 @@ static void ath12k_mac_op_vif_cfg_change - } - } - } --} -- --static void ath12k_mac_vif_setup_ps(struct ath12k_link_vif *arvif) --{ -- struct ath12k *ar = arvif->ar; -- struct ieee80211_vif *vif = arvif->ahvif->vif; -- struct ieee80211_conf *conf = &ath12k_ar_to_hw(ar)->conf; -- enum wmi_sta_powersave_param param; -- struct ieee80211_bss_conf *info; -- enum wmi_sta_ps_mode psmode; -- int ret; -- int timeout; -- bool enable_ps; - -- lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); -+ if (changed & BSS_CHANGED_PS) { -+ links = ahvif->links_map; -+ vif_cfg = &vif->cfg; - -- if (vif->type != NL80211_IFTYPE_STATION) -- return; -+ for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) { -+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]); -+ if (!arvif || !arvif->ar) -+ continue; - -- enable_ps = arvif->ahvif->ps; -- if (enable_ps) { -- psmode = WMI_STA_PS_MODE_ENABLED; -- param = WMI_STA_PS_PARAM_INACTIVITY_TIME; -+ ar = arvif->ar; - -- timeout = conf->dynamic_ps_timeout; -- if (timeout == 0) { -- info = ath12k_mac_get_link_bss_conf(arvif); -- if (!info) { -- ath12k_warn(ar->ab, "unable to access bss link conf in setup ps for vif %pM link %u\n", -- vif->addr, arvif->link_id); -- return; -+ if (ar->ab->hw_params->supports_sta_ps) { -+ ahvif->ps = vif_cfg->ps; -+ ath12k_mac_vif_setup_ps(arvif); - } -- -- /* firmware doesn't like 0 */ -- timeout = ieee80211_tu_to_usec(info->beacon_int) / 1000; -- } -- -- ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param, -- timeout); -- if (ret) { -- ath12k_warn(ar->ab, "failed to set inactivity time for vdev %d: %i\n", -- arvif->vdev_id, ret); -- return; - } -- } else { -- psmode = WMI_STA_PS_MODE_DISABLED; - } -- -- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %d psmode %s\n", -- arvif->vdev_id, psmode ? "enable" : "disable"); -- -- ret = ath12k_wmi_pdev_set_ps_mode(ar, arvif->vdev_id, psmode); -- if (ret) -- ath12k_warn(ar->ab, "failed to set sta power save mode %d for vdev %d: %d\n", -- psmode, arvif->vdev_id, ret); - } - - static bool ath12k_mac_supports_station_tpc(struct ath12k *ar, -@@ -3771,7 +3814,6 @@ static void ath12k_mac_bss_info_changed( - { - struct ath12k_vif *ahvif = arvif->ahvif; - struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif); -- struct ieee80211_vif_cfg *vif_cfg = &vif->cfg; - struct cfg80211_chan_def def; - u32 param_id, param_value; - enum nl80211_band band; -@@ -4045,12 +4087,6 @@ static void ath12k_mac_bss_info_changed( - } - - ath12k_mac_fils_discovery(arvif, info); -- -- if (changed & BSS_CHANGED_PS && -- ar->ab->hw_params->supports_sta_ps) { -- ahvif->ps = vif_cfg->ps; -- ath12k_mac_vif_setup_ps(arvif); -- } - } - - static struct ath12k_vif_cache *ath12k_ahvif_get_link_cache(struct ath12k_vif *ahvif, -@@ -4360,7 +4396,7 @@ int ath12k_mac_get_fw_stats(struct ath12 - { - struct ath12k_base *ab = ar->ab; - struct ath12k_hw *ah = ath12k_ar_to_ah(ar); -- unsigned long timeout, time_left; -+ unsigned long time_left; - int ret; - - guard(mutex)(&ah->hw_mutex); -@@ -4368,19 +4404,13 @@ int ath12k_mac_get_fw_stats(struct ath12 - if (ah->state != ATH12K_HW_STATE_ON) - return -ENETDOWN; - -- /* FW stats can get split when exceeding the stats data buffer limit. -- * In that case, since there is no end marking for the back-to-back -- * received 'update stats' event, we keep a 3 seconds timeout in case, -- * fw_stats_done is not marked yet -- */ -- timeout = jiffies + msecs_to_jiffies(3 * 1000); - ath12k_fw_stats_reset(ar); - - reinit_completion(&ar->fw_stats_complete); -+ reinit_completion(&ar->fw_stats_done); - - ret = ath12k_wmi_send_stats_request_cmd(ar, param->stats_id, - param->vdev_id, param->pdev_id); -- - if (ret) { - ath12k_warn(ab, "failed to request fw stats: %d\n", ret); - return ret; -@@ -4391,7 +4421,6 @@ int ath12k_mac_get_fw_stats(struct ath12 - param->pdev_id, param->vdev_id, param->stats_id); - - time_left = wait_for_completion_timeout(&ar->fw_stats_complete, 1 * HZ); -- - if (!time_left) { - ath12k_warn(ab, "time out while waiting for get fw stats\n"); - return -ETIMEDOUT; -@@ -4400,20 +4429,15 @@ int ath12k_mac_get_fw_stats(struct ath12 - /* Firmware sends WMI_UPDATE_STATS_EVENTID back-to-back - * when stats data buffer limit is reached. fw_stats_complete - * is completed once host receives first event from firmware, but -- * still end might not be marked in the TLV. -- * Below loop is to confirm that firmware completed sending all the event -- * and fw_stats_done is marked true when end is marked in the TLV. -+ * still there could be more events following. Below is to wait -+ * until firmware completes sending all the events. - */ -- for (;;) { -- if (time_after(jiffies, timeout)) -- break; -- spin_lock_bh(&ar->data_lock); -- if (ar->fw_stats.fw_stats_done) { -- spin_unlock_bh(&ar->data_lock); -- break; -- } -- spin_unlock_bh(&ar->data_lock); -+ time_left = wait_for_completion_timeout(&ar->fw_stats_done, 3 * HZ); -+ if (!time_left) { -+ ath12k_warn(ab, "time out while waiting for fw stats done\n"); -+ return -ETIMEDOUT; - } -+ - return 0; - } - -@@ -4731,14 +4755,13 @@ static int ath12k_install_key(struct ath - .key_len = key->keylen, - .key_data = key->key, - .key_flags = flags, -+ .ieee80211_key_cipher = key->cipher, - .macaddr = macaddr, - }; - struct ath12k_vif *ahvif = arvif->ahvif; - - lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); - -- reinit_completion(&ar->install_key_done); -- - if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags)) - return 0; - -@@ -4747,7 +4770,7 @@ static int ath12k_install_key(struct ath - /* arg.key_cipher = WMI_CIPHER_NONE; */ - arg.key_len = 0; - arg.key_data = NULL; -- goto install; -+ goto check_order; - } - - switch (key->cipher) { -@@ -4775,19 +4798,82 @@ static int ath12k_install_key(struct ath - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV | - IEEE80211_KEY_FLAG_RESERVE_TAILROOM; - -+check_order: -+ if (ahvif->vdev_type == WMI_VDEV_TYPE_STA && -+ arg.key_flags == WMI_KEY_GROUP) { -+ if (cmd == SET_KEY) { -+ if (arvif->pairwise_key_done) { -+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, -+ "vdev %u pairwise key done, go install group key\n", -+ arg.vdev_id); -+ goto install; -+ } else { -+ /* WCN7850 firmware requires pairwise key to be installed -+ * before group key. In case group key comes first, cache -+ * it and return. Will revisit it once pairwise key gets -+ * installed. -+ */ -+ arvif->group_key = arg; -+ arvif->group_key_valid = true; -+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, -+ "vdev %u group key before pairwise key, cache and skip\n", -+ arg.vdev_id); -+ -+ ret = 0; -+ goto out; -+ } -+ } else { -+ arvif->group_key_valid = false; -+ } -+ } -+ - install: -- ret = ath12k_wmi_vdev_install_key(arvif->ar, &arg); -+ reinit_completion(&ar->install_key_done); - -+ ret = ath12k_wmi_vdev_install_key(arvif->ar, &arg); - if (ret) - return ret; - - if (!wait_for_completion_timeout(&ar->install_key_done, 1 * HZ)) - return -ETIMEDOUT; - -- if (ether_addr_equal(macaddr, arvif->bssid)) -- ahvif->key_cipher = key->cipher; -+ if (ether_addr_equal(arg.macaddr, arvif->bssid)) -+ ahvif->key_cipher = arg.ieee80211_key_cipher; -+ -+ if (ar->install_key_status) { -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ if (ahvif->vdev_type == WMI_VDEV_TYPE_STA && -+ arg.key_flags == WMI_KEY_PAIRWISE) { -+ if (cmd == SET_KEY) { -+ arvif->pairwise_key_done = true; -+ if (arvif->group_key_valid) { -+ /* Install cached GTK */ -+ arvif->group_key_valid = false; -+ arg = arvif->group_key; -+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, -+ "vdev %u pairwise key done, group key ready, go install\n", -+ arg.vdev_id); -+ goto install; -+ } -+ } else { -+ arvif->pairwise_key_done = false; -+ } -+ } -+ -+out: -+ if (ret) { -+ /* In case of failure userspace may not do DISABLE_KEY -+ * but triggers re-connection directly, so manually reset -+ * status here. -+ */ -+ arvif->group_key_valid = false; -+ arvif->pairwise_key_done = false; -+ } - -- return ar->install_key_status ? -EINVAL : 0; -+ return ret; - } - - static int ath12k_clear_peer_keys(struct ath12k_link_vif *arvif, -@@ -5174,6 +5260,8 @@ static int ath12k_mac_station_assoc(stru - "invalid peer NSS %d\n", peer_arg->peer_nss); - return -EINVAL; - } -+ -+ peer_arg->is_assoc = true; - ret = ath12k_wmi_send_peer_assoc_cmd(ar, peer_arg); - if (ret) { - ath12k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n", -@@ -5420,6 +5508,7 @@ static void ath12k_sta_rc_update_wk(stru - ath12k_peer_assoc_prepare(ar, arvif, arsta, - peer_arg, true); - -+ peer_arg->is_assoc = false; - err = ath12k_wmi_send_peer_assoc_cmd(ar, peer_arg); - if (err) - ath12k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n", -@@ -5890,6 +5979,327 @@ exit: - return ret; - } - -+static bool ath12k_mac_is_freq_on_mac(struct ath12k_hw_mode_freq_range_arg *freq_range, -+ u32 freq, u8 mac_id) -+{ -+ return (freq >= freq_range[mac_id].low_2ghz_freq && -+ freq <= freq_range[mac_id].high_2ghz_freq) || -+ (freq >= freq_range[mac_id].low_5ghz_freq && -+ freq <= freq_range[mac_id].high_5ghz_freq); -+} -+ -+static bool -+ath12k_mac_2_freq_same_mac_in_freq_range(struct ath12k_base *ab, -+ struct ath12k_hw_mode_freq_range_arg *freq_range, -+ u32 freq_link1, u32 freq_link2) -+{ -+ u8 i; -+ -+ for (i = 0; i < MAX_RADIOS; i++) { -+ if (ath12k_mac_is_freq_on_mac(freq_range, freq_link1, i) && -+ ath12k_mac_is_freq_on_mac(freq_range, freq_link2, i)) -+ return true; -+ } -+ -+ return false; -+} -+ -+static bool ath12k_mac_is_hw_dbs_capable(struct ath12k_base *ab) -+{ -+ return test_bit(WMI_TLV_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT, -+ ab->wmi_ab.svc_map) && -+ ab->wmi_ab.hw_mode_info.support_dbs; -+} -+ -+static bool ath12k_mac_2_freq_same_mac_in_dbs(struct ath12k_base *ab, -+ u32 freq_link1, u32 freq_link2) -+{ -+ struct ath12k_hw_mode_freq_range_arg *freq_range; -+ -+ if (!ath12k_mac_is_hw_dbs_capable(ab)) -+ return true; -+ -+ freq_range = ab->wmi_ab.hw_mode_info.freq_range_caps[ATH12K_HW_MODE_DBS]; -+ return ath12k_mac_2_freq_same_mac_in_freq_range(ab, freq_range, -+ freq_link1, freq_link2); -+} -+ -+static bool ath12k_mac_is_hw_sbs_capable(struct ath12k_base *ab) -+{ -+ return test_bit(WMI_TLV_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT, -+ ab->wmi_ab.svc_map) && -+ ab->wmi_ab.hw_mode_info.support_sbs; -+} -+ -+static bool ath12k_mac_2_freq_same_mac_in_sbs(struct ath12k_base *ab, -+ u32 freq_link1, u32 freq_link2) -+{ -+ struct ath12k_hw_mode_info *info = &ab->wmi_ab.hw_mode_info; -+ struct ath12k_hw_mode_freq_range_arg *sbs_uppr_share; -+ struct ath12k_hw_mode_freq_range_arg *sbs_low_share; -+ struct ath12k_hw_mode_freq_range_arg *sbs_range; -+ -+ if (!ath12k_mac_is_hw_sbs_capable(ab)) -+ return true; -+ -+ if (ab->wmi_ab.sbs_lower_band_end_freq) { -+ sbs_uppr_share = info->freq_range_caps[ATH12K_HW_MODE_SBS_UPPER_SHARE]; -+ sbs_low_share = info->freq_range_caps[ATH12K_HW_MODE_SBS_LOWER_SHARE]; -+ -+ return ath12k_mac_2_freq_same_mac_in_freq_range(ab, sbs_low_share, -+ freq_link1, freq_link2) || -+ ath12k_mac_2_freq_same_mac_in_freq_range(ab, sbs_uppr_share, -+ freq_link1, freq_link2); -+ } -+ -+ sbs_range = info->freq_range_caps[ATH12K_HW_MODE_SBS]; -+ return ath12k_mac_2_freq_same_mac_in_freq_range(ab, sbs_range, -+ freq_link1, freq_link2); -+} -+ -+static bool ath12k_mac_freqs_on_same_mac(struct ath12k_base *ab, -+ u32 freq_link1, u32 freq_link2) -+{ -+ return ath12k_mac_2_freq_same_mac_in_dbs(ab, freq_link1, freq_link2) && -+ ath12k_mac_2_freq_same_mac_in_sbs(ab, freq_link1, freq_link2); -+} -+ -+static int ath12k_mac_mlo_sta_set_link_active(struct ath12k_base *ab, -+ enum wmi_mlo_link_force_reason reason, -+ enum wmi_mlo_link_force_mode mode, -+ u8 *mlo_vdev_id_lst, -+ u8 num_mlo_vdev, -+ u8 *mlo_inactive_vdev_lst, -+ u8 num_mlo_inactive_vdev) -+{ -+ struct wmi_mlo_link_set_active_arg param = {0}; -+ u32 entry_idx, entry_offset, vdev_idx; -+ u8 vdev_id; -+ -+ param.reason = reason; -+ param.force_mode = mode; -+ -+ for (vdev_idx = 0; vdev_idx < num_mlo_vdev; vdev_idx++) { -+ vdev_id = mlo_vdev_id_lst[vdev_idx]; -+ entry_idx = vdev_id / 32; -+ entry_offset = vdev_id % 32; -+ if (entry_idx >= WMI_MLO_LINK_NUM_SZ) { -+ ath12k_warn(ab, "Invalid entry_idx %d num_mlo_vdev %d vdev %d", -+ entry_idx, num_mlo_vdev, vdev_id); -+ return -EINVAL; -+ } -+ param.vdev_bitmap[entry_idx] |= 1 << entry_offset; -+ /* update entry number if entry index changed */ -+ if (param.num_vdev_bitmap < entry_idx + 1) -+ param.num_vdev_bitmap = entry_idx + 1; -+ } -+ -+ ath12k_dbg(ab, ATH12K_DBG_MAC, -+ "num_vdev_bitmap %d vdev_bitmap[0] = 0x%x, vdev_bitmap[1] = 0x%x", -+ param.num_vdev_bitmap, param.vdev_bitmap[0], param.vdev_bitmap[1]); -+ -+ if (mode == WMI_MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE) { -+ for (vdev_idx = 0; vdev_idx < num_mlo_inactive_vdev; vdev_idx++) { -+ vdev_id = mlo_inactive_vdev_lst[vdev_idx]; -+ entry_idx = vdev_id / 32; -+ entry_offset = vdev_id % 32; -+ if (entry_idx >= WMI_MLO_LINK_NUM_SZ) { -+ ath12k_warn(ab, "Invalid entry_idx %d num_mlo_vdev %d vdev %d", -+ entry_idx, num_mlo_inactive_vdev, vdev_id); -+ return -EINVAL; -+ } -+ param.inactive_vdev_bitmap[entry_idx] |= 1 << entry_offset; -+ /* update entry number if entry index changed */ -+ if (param.num_inactive_vdev_bitmap < entry_idx + 1) -+ param.num_inactive_vdev_bitmap = entry_idx + 1; -+ } -+ -+ ath12k_dbg(ab, ATH12K_DBG_MAC, -+ "num_vdev_bitmap %d inactive_vdev_bitmap[0] = 0x%x, inactive_vdev_bitmap[1] = 0x%x", -+ param.num_inactive_vdev_bitmap, -+ param.inactive_vdev_bitmap[0], -+ param.inactive_vdev_bitmap[1]); -+ } -+ -+ if (mode == WMI_MLO_LINK_FORCE_MODE_ACTIVE_LINK_NUM || -+ mode == WMI_MLO_LINK_FORCE_MODE_INACTIVE_LINK_NUM) { -+ param.num_link_entry = 1; -+ param.link_num[0].num_of_link = num_mlo_vdev - 1; -+ } -+ -+ return ath12k_wmi_send_mlo_link_set_active_cmd(ab, ¶m); -+} -+ -+static int ath12k_mac_mlo_sta_update_link_active(struct ath12k_base *ab, -+ struct ieee80211_hw *hw, -+ struct ath12k_vif *ahvif) -+{ -+ u8 mlo_vdev_id_lst[IEEE80211_MLD_MAX_NUM_LINKS] = {0}; -+ u32 mlo_freq_list[IEEE80211_MLD_MAX_NUM_LINKS] = {0}; -+ unsigned long links = ahvif->links_map; -+ enum wmi_mlo_link_force_reason reason; -+ struct ieee80211_chanctx_conf *conf; -+ enum wmi_mlo_link_force_mode mode; -+ struct ieee80211_bss_conf *info; -+ struct ath12k_link_vif *arvif; -+ u8 num_mlo_vdev = 0; -+ u8 link_id; -+ -+ for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) { -+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]); -+ /* make sure vdev is created on this device */ -+ if (!arvif || !arvif->is_created || arvif->ar->ab != ab) -+ continue; -+ -+ info = ath12k_mac_get_link_bss_conf(arvif); -+ conf = wiphy_dereference(hw->wiphy, info->chanctx_conf); -+ mlo_freq_list[num_mlo_vdev] = conf->def.chan->center_freq; -+ -+ mlo_vdev_id_lst[num_mlo_vdev] = arvif->vdev_id; -+ num_mlo_vdev++; -+ } -+ -+ /* It is not allowed to activate more links than a single device -+ * supported. Something goes wrong if we reach here. -+ */ -+ if (num_mlo_vdev > ATH12K_NUM_MAX_ACTIVE_LINKS_PER_DEVICE) { -+ WARN_ON_ONCE(1); -+ return -EINVAL; -+ } -+ -+ /* if 2 links are established and both link channels fall on the -+ * same hardware MAC, send command to firmware to deactivate one -+ * of them. -+ */ -+ if (num_mlo_vdev == 2 && -+ ath12k_mac_freqs_on_same_mac(ab, mlo_freq_list[0], -+ mlo_freq_list[1])) { -+ mode = WMI_MLO_LINK_FORCE_MODE_INACTIVE_LINK_NUM; -+ reason = WMI_MLO_LINK_FORCE_REASON_NEW_CONNECT; -+ return ath12k_mac_mlo_sta_set_link_active(ab, reason, mode, -+ mlo_vdev_id_lst, num_mlo_vdev, -+ NULL, 0); -+ } -+ -+ return 0; -+} -+ -+static bool ath12k_mac_are_sbs_chan(struct ath12k_base *ab, u32 freq_1, u32 freq_2) -+{ -+ if (!ath12k_mac_is_hw_sbs_capable(ab)) -+ return false; -+ -+ if (ath12k_is_2ghz_channel_freq(freq_1) || -+ ath12k_is_2ghz_channel_freq(freq_2)) -+ return false; -+ -+ return !ath12k_mac_2_freq_same_mac_in_sbs(ab, freq_1, freq_2); -+} -+ -+static bool ath12k_mac_are_dbs_chan(struct ath12k_base *ab, u32 freq_1, u32 freq_2) -+{ -+ if (!ath12k_mac_is_hw_dbs_capable(ab)) -+ return false; -+ -+ return !ath12k_mac_2_freq_same_mac_in_dbs(ab, freq_1, freq_2); -+} -+ -+static int ath12k_mac_select_links(struct ath12k_base *ab, -+ struct ieee80211_vif *vif, -+ struct ieee80211_hw *hw, -+ u16 *selected_links) -+{ -+ unsigned long useful_links = ieee80211_vif_usable_links(vif); -+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); -+ u8 num_useful_links = hweight_long(useful_links); -+ struct ieee80211_chanctx_conf *chanctx; -+ struct ath12k_link_vif *assoc_arvif; -+ u32 assoc_link_freq, partner_freq; -+ u16 sbs_links = 0, dbs_links = 0; -+ struct ieee80211_bss_conf *info; -+ struct ieee80211_channel *chan; -+ struct ieee80211_sta *sta; -+ struct ath12k_sta *ahsta; -+ u8 link_id; -+ -+ /* activate all useful links if less than max supported */ -+ if (num_useful_links <= ATH12K_NUM_MAX_ACTIVE_LINKS_PER_DEVICE) { -+ *selected_links = useful_links; -+ return 0; -+ } -+ -+ /* only in station mode we can get here, so it's safe -+ * to use ap_addr -+ */ -+ rcu_read_lock(); -+ sta = ieee80211_find_sta(vif, vif->cfg.ap_addr); -+ if (!sta) { -+ rcu_read_unlock(); -+ ath12k_warn(ab, "failed to find sta with addr %pM\n", vif->cfg.ap_addr); -+ return -EINVAL; -+ } -+ -+ ahsta = ath12k_sta_to_ahsta(sta); -+ assoc_arvif = wiphy_dereference(hw->wiphy, ahvif->link[ahsta->assoc_link_id]); -+ info = ath12k_mac_get_link_bss_conf(assoc_arvif); -+ chanctx = rcu_dereference(info->chanctx_conf); -+ assoc_link_freq = chanctx->def.chan->center_freq; -+ rcu_read_unlock(); -+ ath12k_dbg(ab, ATH12K_DBG_MAC, "assoc link %u freq %u\n", -+ assoc_arvif->link_id, assoc_link_freq); -+ -+ /* assoc link is already activated and has to be kept active, -+ * only need to select a partner link from others. -+ */ -+ useful_links &= ~BIT(assoc_arvif->link_id); -+ for_each_set_bit(link_id, &useful_links, IEEE80211_MLD_MAX_NUM_LINKS) { -+ info = wiphy_dereference(hw->wiphy, vif->link_conf[link_id]); -+ if (!info) { -+ ath12k_warn(ab, "failed to get link info for link: %u\n", -+ link_id); -+ return -ENOLINK; -+ } -+ -+ chan = info->chanreq.oper.chan; -+ if (!chan) { -+ ath12k_warn(ab, "failed to get chan for link: %u\n", link_id); -+ return -EINVAL; -+ } -+ -+ partner_freq = chan->center_freq; -+ if (ath12k_mac_are_sbs_chan(ab, assoc_link_freq, partner_freq)) { -+ sbs_links |= BIT(link_id); -+ ath12k_dbg(ab, ATH12K_DBG_MAC, "new SBS link %u freq %u\n", -+ link_id, partner_freq); -+ continue; -+ } -+ -+ if (ath12k_mac_are_dbs_chan(ab, assoc_link_freq, partner_freq)) { -+ dbs_links |= BIT(link_id); -+ ath12k_dbg(ab, ATH12K_DBG_MAC, "new DBS link %u freq %u\n", -+ link_id, partner_freq); -+ continue; -+ } -+ -+ ath12k_dbg(ab, ATH12K_DBG_MAC, "non DBS/SBS link %u freq %u\n", -+ link_id, partner_freq); -+ } -+ -+ /* choose the first candidate no matter how many is in the list */ -+ if (sbs_links) -+ link_id = __ffs(sbs_links); -+ else if (dbs_links) -+ link_id = __ffs(dbs_links); -+ else -+ link_id = ffs(useful_links) - 1; -+ -+ ath12k_dbg(ab, ATH12K_DBG_MAC, "select partner link %u\n", link_id); -+ -+ *selected_links = BIT(assoc_arvif->link_id) | BIT(link_id); -+ -+ return 0; -+} -+ - static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, -@@ -5899,10 +6309,13 @@ static int ath12k_mac_op_sta_state(struc - struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif); - struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta); - struct ath12k_hw *ah = ath12k_hw_to_ah(hw); -+ struct ath12k_base *prev_ab = NULL, *ab; - struct ath12k_link_vif *arvif; - struct ath12k_link_sta *arsta; - unsigned long valid_links; -- u8 link_id = 0; -+ u16 selected_links = 0; -+ u8 link_id = 0, i; -+ struct ath12k *ar; - int ret; - - lockdep_assert_wiphy(hw->wiphy); -@@ -5972,8 +6385,24 @@ static int ath12k_mac_op_sta_state(struc - * about to move to the associated state. - */ - if (ieee80211_vif_is_mld(vif) && vif->type == NL80211_IFTYPE_STATION && -- old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_ASSOC) -- ieee80211_set_active_links(vif, ieee80211_vif_usable_links(vif)); -+ old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_ASSOC) { -+ /* TODO: for now only do link selection for single device -+ * MLO case. Other cases would be handled in the future. -+ */ -+ ab = ah->radio[0].ab; -+ if (ab->ag->num_devices == 1) { -+ ret = ath12k_mac_select_links(ab, vif, hw, &selected_links); -+ if (ret) { -+ ath12k_warn(ab, -+ "failed to get selected links: %d\n", ret); -+ goto exit; -+ } -+ } else { -+ selected_links = ieee80211_vif_usable_links(vif); -+ } -+ -+ ieee80211_set_active_links(vif, selected_links); -+ } - - /* Handle all the other state transitions in generic way */ - valid_links = ahsta->links_map; -@@ -5997,6 +6426,24 @@ static int ath12k_mac_op_sta_state(struc - } - } - -+ if (ieee80211_vif_is_mld(vif) && vif->type == NL80211_IFTYPE_STATION && -+ old_state == IEEE80211_STA_ASSOC && new_state == IEEE80211_STA_AUTHORIZED) { -+ for_each_ar(ah, ar, i) { -+ ab = ar->ab; -+ if (prev_ab == ab) -+ continue; -+ -+ ret = ath12k_mac_mlo_sta_update_link_active(ab, hw, ahvif); -+ if (ret) { -+ ath12k_warn(ab, -+ "failed to update link active state on connect %d\n", -+ ret); -+ goto exit; -+ } -+ -+ prev_ab = ab; -+ } -+ } - /* IEEE80211_STA_NONE -> IEEE80211_STA_NOTEXIST: - * Remove the station from driver (handle ML sta here since that - * needs special handling. Normal sta will be handled in generic -@@ -7238,7 +7685,7 @@ static int ath12k_mac_mgmt_tx_wmi(struct - - skb_cb->paddr = paddr; - -- ret = ath12k_wmi_mgmt_send(ar, arvif->vdev_id, buf_id, skb); -+ ret = ath12k_wmi_mgmt_send(arvif, buf_id, skb); - if (ret) { - ath12k_warn(ar->ab, "failed to send mgmt frame: %d\n", ret); - goto err_unmap_buf; -@@ -7550,6 +7997,9 @@ static void ath12k_mac_op_tx(struct ieee - - skb_cb->flags |= ATH12K_SKB_HW_80211_ENCAP; - } else if (ieee80211_is_mgmt(hdr->frame_control)) { -+ if (sta && sta->mlo) -+ skb_cb->flags |= ATH12K_SKB_MLO_STA; -+ - ret = ath12k_mac_mgmt_tx(ar, skb, is_prb_rsp); - if (ret) { - ath12k_warn(ar->ab, "failed to queue management frame %d\n", -@@ -7814,14 +8264,9 @@ err: - - static void ath12k_drain_tx(struct ath12k_hw *ah) - { -- struct ath12k *ar = ah->radio; -+ struct ath12k *ar; - int i; - -- if (ath12k_ftm_mode) { -- ath12k_err(ar->ab, "fail to start mac operations in ftm mode\n"); -- return; -- } -- - lockdep_assert_wiphy(ah->hw->wiphy); - - for_each_ar(ah, ar, i) -@@ -7834,6 +8279,9 @@ static int ath12k_mac_op_start(struct ie - struct ath12k *ar; - int ret, i; - -+ if (ath12k_ftm_mode) -+ return -EPERM; -+ - lockdep_assert_wiphy(hw->wiphy); - - ath12k_drain_tx(ah); -@@ -7940,6 +8388,7 @@ static void ath12k_mac_stop(struct ath12 - { - struct ath12k_hw *ah = ar->ah; - struct htt_ppdu_stats_info *ppdu_stats, *tmp; -+ struct ath12k_wmi_scan_chan_list_arg *arg; - int ret; - - lockdep_assert_held(&ah->hw_mutex); -@@ -7954,6 +8403,7 @@ static void ath12k_mac_stop(struct ath12 - - cancel_delayed_work_sync(&ar->scan.timeout); - wiphy_work_cancel(ath12k_ar_to_hw(ar)->wiphy, &ar->scan.vdev_clean_wk); -+ cancel_work_sync(&ar->regd_channel_update_work); - cancel_work_sync(&ar->regd_update_work); - cancel_work_sync(&ar->ab->rfkill_work); - cancel_work_sync(&ar->ab->update_11d_work); -@@ -7961,10 +8411,18 @@ static void ath12k_mac_stop(struct ath12 - complete(&ar->completed_11d_scan); - - spin_lock_bh(&ar->data_lock); -+ - list_for_each_entry_safe(ppdu_stats, tmp, &ar->ppdu_stats_info, list) { - list_del(&ppdu_stats->list); - kfree(ppdu_stats); - } -+ -+ while ((arg = list_first_entry_or_null(&ar->regd_channel_update_queue, -+ struct ath12k_wmi_scan_chan_list_arg, -+ list))) { -+ list_del(&arg->list); -+ kfree(arg); -+ } - spin_unlock_bh(&ar->data_lock); - - rcu_assign_pointer(ar->ab->pdevs_active[ar->pdev_idx], NULL); -@@ -9472,7 +9930,7 @@ ath12k_mac_change_chanctx_cnt_iter(void - if (WARN_ON(!arvif)) - continue; - -- if (arvif->ar != arg->ar) -+ if (!arvif->is_created || arvif->ar != arg->ar) - continue; - - link_conf = wiphy_dereference(ahvif->ah->hw->wiphy, -@@ -9507,7 +9965,7 @@ ath12k_mac_change_chanctx_fill_iter(void - if (WARN_ON(!arvif)) - continue; - -- if (arvif->ar != arg->ar) -+ if (!arvif->is_created || arvif->ar != arg->ar) - continue; - - link_conf = wiphy_dereference(ahvif->ah->hw->wiphy, -@@ -9587,7 +10045,7 @@ ath12k_mac_update_vif_chan(struct ath12k - int n_vifs) - { - struct ath12k_wmi_vdev_up_params params = {}; -- struct ath12k_link_vif *arvif, *tx_arvif; -+ struct ath12k_link_vif *arvif; - struct ieee80211_bss_conf *link_conf; - struct ath12k_base *ab = ar->ab; - struct ieee80211_vif *vif; -@@ -9659,10 +10117,8 @@ ath12k_mac_update_vif_chan(struct ath12k - params.vdev_id = arvif->vdev_id; - params.aid = ahvif->aid; - params.bssid = arvif->bssid; -- -- tx_arvif = ath12k_mac_get_tx_arvif(arvif, link_conf); -- if (tx_arvif) { -- params.tx_bssid = tx_arvif->bssid; -+ params.tx_bssid = ath12k_mac_get_tx_bssid(arvif); -+ if (params.tx_bssid) { - params.nontx_profile_idx = link_conf->bssid_index; - params.nontx_profile_cnt = 1 << link_conf->bssid_indicator; - } -@@ -11858,6 +12314,7 @@ static void ath12k_mac_hw_unregister(str - int i; - - for_each_ar(ah, ar, i) { -+ cancel_work_sync(&ar->regd_channel_update_work); - cancel_work_sync(&ar->regd_update_work); - ath12k_debugfs_unregister(ar); - ath12k_fw_stats_reset(ar); -@@ -12080,6 +12537,7 @@ static int ath12k_mac_hw_register(struct - - wiphy->mbssid_max_interfaces = mbssid_max_interfaces; - wiphy->ema_max_profile_periodicity = TARGET_EMA_MAX_PROFILE_PERIOD; -+ ieee80211_hw_set(hw, SUPPORTS_MULTI_BSSID); - - if (is_6ghz) { - wiphy_ext_feature_set(wiphy, -@@ -12218,6 +12676,8 @@ static void ath12k_mac_setup(struct ath1 - - INIT_DELAYED_WORK(&ar->scan.timeout, ath12k_scan_timeout_work); - wiphy_work_init(&ar->scan.vdev_clean_wk, ath12k_scan_vdev_clean_work); -+ INIT_WORK(&ar->regd_channel_update_work, ath12k_regd_update_chan_list_work); -+ INIT_LIST_HEAD(&ar->regd_channel_update_queue); - INIT_WORK(&ar->regd_update_work, ath12k_regd_update_work); - - wiphy_work_init(&ar->wmi_mgmt_tx_work, ath12k_mgmt_over_wmi_tx_work); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/mac.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/mac.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/mac.h 2025-10-22 13:53:23.383328321 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/mac.h 2025-10-22 13:53:56.603168717 -0400 -@@ -54,6 +54,8 @@ struct ath12k_generic_iter { - #define ATH12K_DEFAULT_SCAN_LINK IEEE80211_MLD_MAX_NUM_LINKS - #define ATH12K_NUM_MAX_LINKS (IEEE80211_MLD_MAX_NUM_LINKS + 1) - -+#define ATH12K_NUM_MAX_ACTIVE_LINKS_PER_DEVICE 2 -+ - enum ath12k_supported_bw { - ATH12K_BW_20 = 0, - ATH12K_BW_40 = 1, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/p2p.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/p2p.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/p2p.c 2025-10-22 13:53:23.383328321 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/p2p.c 2025-10-22 13:53:56.603168717 -0400 -@@ -1,6 +1,7 @@ - // SPDX-License-Identifier: BSD-3-Clause-Clear - /* - * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. -+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. - */ - - #include -@@ -124,7 +125,7 @@ static void ath12k_p2p_noa_update_vdev_i - - WARN_ON(!rcu_read_lock_any_held()); - arvif = &ahvif->deflink; -- if (arvif->ar != arg->ar || arvif->vdev_id != arg->vdev_id) -+ if (!arvif->is_created || arvif->ar != arg->ar || arvif->vdev_id != arg->vdev_id) - return; - - ath12k_p2p_noa_update(arvif, arg->noa); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/pci.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/pci.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/pci.c 2025-10-22 13:53:23.383328321 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/pci.c 2025-10-22 13:53:56.603168717 -0400 -@@ -292,10 +292,10 @@ static void ath12k_pci_enable_ltssm(stru - - ath12k_dbg(ab, ATH12K_DBG_PCI, "pci ltssm 0x%x\n", val); - -- val = ath12k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST); -+ val = ath12k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST(ab)); - val |= GCC_GCC_PCIE_HOT_RST_VAL; -- ath12k_pci_write32(ab, GCC_GCC_PCIE_HOT_RST, val); -- val = ath12k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST); -+ ath12k_pci_write32(ab, GCC_GCC_PCIE_HOT_RST(ab), val); -+ val = ath12k_pci_read32(ab, GCC_GCC_PCIE_HOT_RST(ab)); - - ath12k_dbg(ab, ATH12K_DBG_PCI, "pci pcie_hot_rst 0x%x\n", val); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/pci.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/pci.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/pci.h 2025-10-22 13:53:23.383328321 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/pci.h 2025-10-22 13:53:56.603168717 -0400 -@@ -28,7 +28,9 @@ - #define PCIE_PCIE_PARF_LTSSM 0x1e081b0 - #define PARM_LTSSM_VALUE 0x111 - --#define GCC_GCC_PCIE_HOT_RST 0x1e38338 -+#define GCC_GCC_PCIE_HOT_RST(ab) \ -+ ((ab)->hw_params->regs->gcc_gcc_pcie_hot_rst) -+ - #define GCC_GCC_PCIE_HOT_RST_VAL 0x10 - - #define PCIE_PCIE_INT_ALL_CLEAR 0x1e08228 -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/peer.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/peer.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/peer.c 2025-10-22 13:53:23.383328321 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/peer.c 2025-10-22 13:53:56.603168717 -0400 -@@ -8,7 +8,7 @@ - #include "peer.h" - #include "debug.h" - --static struct ath12k_ml_peer *ath12k_peer_ml_find(struct ath12k_hw *ah, const u8 *addr) -+struct ath12k_ml_peer *ath12k_peer_ml_find(struct ath12k_hw *ah, const u8 *addr) - { - struct ath12k_ml_peer *ml_peer; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/peer.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/peer.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/peer.h 2025-10-22 13:53:23.383328321 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/peer.h 2025-10-22 13:53:56.603168717 -0400 -@@ -91,5 +91,33 @@ struct ath12k_peer *ath12k_peer_find_by_ - int ath12k_peer_ml_create(struct ath12k_hw *ah, struct ieee80211_sta *sta); - int ath12k_peer_ml_delete(struct ath12k_hw *ah, struct ieee80211_sta *sta); - int ath12k_peer_mlo_link_peers_delete(struct ath12k_vif *ahvif, struct ath12k_sta *ahsta); -+struct ath12k_ml_peer *ath12k_peer_ml_find(struct ath12k_hw *ah, -+ const u8 *addr); -+static inline -+struct ath12k_link_sta *ath12k_peer_get_link_sta(struct ath12k_base *ab, -+ struct ath12k_peer *peer) -+{ -+ struct ath12k_sta *ahsta; -+ struct ath12k_link_sta *arsta; -+ -+ if (!peer->sta) -+ return NULL; -+ -+ ahsta = ath12k_sta_to_ahsta(peer->sta); -+ if (peer->ml_id & ATH12K_PEER_ML_ID_VALID) { -+ if (!(ahsta->links_map & BIT(peer->link_id))) { -+ ath12k_warn(ab, "peer %pM id %d link_id %d can't found in STA link_map 0x%x\n", -+ peer->addr, peer->peer_id, peer->link_id, -+ ahsta->links_map); -+ return NULL; -+ } -+ arsta = rcu_dereference(ahsta->link[peer->link_id]); -+ if (!arsta) -+ return NULL; -+ } else { -+ arsta = &ahsta->deflink; -+ } -+ return arsta; -+} - - #endif /* _PEER_H_ */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/reg.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/reg.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/reg.c 2025-10-22 13:53:23.383328321 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/reg.c 2025-10-22 13:53:56.603168717 -0400 -@@ -137,32 +137,7 @@ int ath12k_reg_update_chan_list(struct a - struct ath12k_wmi_channel_arg *ch; - enum nl80211_band band; - int num_channels = 0; -- int i, ret, left; -- -- if (wait && ar->state_11d == ATH12K_11D_RUNNING) { -- left = wait_for_completion_timeout(&ar->completed_11d_scan, -- ATH12K_SCAN_TIMEOUT_HZ); -- if (!left) { -- ath12k_dbg(ar->ab, ATH12K_DBG_REG, -- "failed to receive 11d scan complete: timed out\n"); -- ar->state_11d = ATH12K_11D_IDLE; -- } -- ath12k_dbg(ar->ab, ATH12K_DBG_REG, -- "reg 11d scan wait left time %d\n", left); -- } -- -- if (wait && -- (ar->scan.state == ATH12K_SCAN_STARTING || -- ar->scan.state == ATH12K_SCAN_RUNNING)) { -- left = wait_for_completion_timeout(&ar->scan.completed, -- ATH12K_SCAN_TIMEOUT_HZ); -- if (!left) -- ath12k_dbg(ar->ab, ATH12K_DBG_REG, -- "failed to receive hw scan complete: timed out\n"); -- -- ath12k_dbg(ar->ab, ATH12K_DBG_REG, -- "reg hw scan wait left time %d\n", left); -- } -+ int i, ret = 0; - - if (ar->ah->state == ATH12K_HW_STATE_RESTARTING) - return 0; -@@ -244,6 +219,16 @@ int ath12k_reg_update_chan_list(struct a - } - } - -+ if (wait) { -+ spin_lock_bh(&ar->data_lock); -+ list_add_tail(&arg->list, &ar->regd_channel_update_queue); -+ spin_unlock_bh(&ar->data_lock); -+ -+ queue_work(ar->ab->workqueue, &ar->regd_channel_update_work); -+ -+ return 0; -+ } -+ - ret = ath12k_wmi_send_scan_chan_list_cmd(ar, arg); - kfree(arg); - -@@ -413,6 +398,29 @@ ath12k_map_fw_dfs_region(enum ath12k_dfs - } - } - -+static u32 ath12k_get_bw_reg_flags(u16 max_bw) -+{ -+ switch (max_bw) { -+ case 20: -+ return NL80211_RRF_NO_HT40 | -+ NL80211_RRF_NO_80MHZ | -+ NL80211_RRF_NO_160MHZ | -+ NL80211_RRF_NO_320MHZ; -+ case 40: -+ return NL80211_RRF_NO_80MHZ | -+ NL80211_RRF_NO_160MHZ | -+ NL80211_RRF_NO_320MHZ; -+ case 80: -+ return NL80211_RRF_NO_160MHZ | -+ NL80211_RRF_NO_320MHZ; -+ case 160: -+ return NL80211_RRF_NO_320MHZ; -+ case 320: -+ default: -+ return 0; -+ } -+} -+ - static u32 ath12k_map_fw_reg_flags(u16 reg_flags) - { - u32 flags = 0; -@@ -691,7 +699,7 @@ ath12k_reg_build_regd(struct ath12k_base - reg_rule = reg_info->reg_rules_2g_ptr + i; - max_bw = min_t(u16, reg_rule->max_bw, - reg_info->max_bw_2g); -- flags = 0; -+ flags = ath12k_get_bw_reg_flags(reg_info->max_bw_2g); - ath12k_reg_update_freq_range(&ab->reg_freq_2ghz, reg_rule); - } else if (reg_info->num_5g_reg_rules && - (j < reg_info->num_5g_reg_rules)) { -@@ -705,13 +713,15 @@ ath12k_reg_build_regd(struct ath12k_base - * BW correction if required and applies flags as - * per other BW rule flags we pass from here - */ -- flags = NL80211_RRF_AUTO_BW; -+ flags = NL80211_RRF_AUTO_BW | -+ ath12k_get_bw_reg_flags(reg_info->max_bw_5g); - ath12k_reg_update_freq_range(&ab->reg_freq_5ghz, reg_rule); - } else if (reg_info->is_ext_reg_event && reg_6ghz_number && - (k < reg_6ghz_number)) { - reg_rule = reg_rule_6ghz + k++; - max_bw = min_t(u16, reg_rule->max_bw, max_bw_6ghz); -- flags = NL80211_RRF_AUTO_BW; -+ flags = NL80211_RRF_AUTO_BW | -+ ath12k_get_bw_reg_flags(max_bw_6ghz); - if (reg_rule->psd_flag) - flags |= NL80211_RRF_PSD; - ath12k_reg_update_freq_range(&ab->reg_freq_6ghz, reg_rule); -@@ -764,6 +774,54 @@ ret: - return new_regd; - } - -+void ath12k_regd_update_chan_list_work(struct work_struct *work) -+{ -+ struct ath12k *ar = container_of(work, struct ath12k, -+ regd_channel_update_work); -+ struct ath12k_wmi_scan_chan_list_arg *arg; -+ struct list_head local_update_list; -+ int left; -+ -+ INIT_LIST_HEAD(&local_update_list); -+ -+ spin_lock_bh(&ar->data_lock); -+ list_splice_tail_init(&ar->regd_channel_update_queue, &local_update_list); -+ spin_unlock_bh(&ar->data_lock); -+ -+ while ((arg = list_first_entry_or_null(&local_update_list, -+ struct ath12k_wmi_scan_chan_list_arg, -+ list))) { -+ if (ar->state_11d != ATH12K_11D_IDLE) { -+ left = wait_for_completion_timeout(&ar->completed_11d_scan, -+ ATH12K_SCAN_TIMEOUT_HZ); -+ if (!left) { -+ ath12k_dbg(ar->ab, ATH12K_DBG_REG, -+ "failed to receive 11d scan complete: timed out\n"); -+ ar->state_11d = ATH12K_11D_IDLE; -+ } -+ -+ ath12k_dbg(ar->ab, ATH12K_DBG_REG, -+ "reg 11d scan wait left time %d\n", left); -+ } -+ -+ if ((ar->scan.state == ATH12K_SCAN_STARTING || -+ ar->scan.state == ATH12K_SCAN_RUNNING)) { -+ left = wait_for_completion_timeout(&ar->scan.completed, -+ ATH12K_SCAN_TIMEOUT_HZ); -+ if (!left) -+ ath12k_dbg(ar->ab, ATH12K_DBG_REG, -+ "failed to receive hw scan complete: timed out\n"); -+ -+ ath12k_dbg(ar->ab, ATH12K_DBG_REG, -+ "reg hw scan wait left time %d\n", left); -+ } -+ -+ ath12k_wmi_send_scan_chan_list_cmd(ar, arg); -+ list_del(&arg->list); -+ kfree(arg); -+ } -+} -+ - void ath12k_regd_update_work(struct work_struct *work) - { - struct ath12k *ar = container_of(work, struct ath12k, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/reg.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/reg.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/reg.h 2025-10-22 13:53:23.383328321 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/reg.h 2025-10-22 13:53:56.603168717 -0400 -@@ -113,6 +113,7 @@ int ath12k_reg_handle_chan_list(struct a - struct ath12k_reg_info *reg_info, - enum wmi_vdev_type vdev_type, - enum ieee80211_ap_reg_power power_type); -+void ath12k_regd_update_chan_list_work(struct work_struct *work); - enum wmi_reg_6g_ap_type - ath12k_reg_ap_pwr_convert(enum ieee80211_ap_reg_power power_type); - enum ath12k_reg_status ath12k_reg_validate_reg_info(struct ath12k_base *ab, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/wmi.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/wmi.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/wmi.c 2025-10-22 13:53:23.383328321 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/wmi.c 2025-10-22 13:53:56.607168698 -0400 -@@ -91,6 +91,11 @@ struct ath12k_wmi_svc_rdy_ext2_parse { - bool dma_ring_cap_done; - bool spectral_bin_scaling_done; - bool mac_phy_caps_ext_done; -+ bool hal_reg_caps_ext2_done; -+ bool scan_radio_caps_ext2_done; -+ bool twt_caps_done; -+ bool htt_msdu_idx_to_qtype_map_done; -+ bool dbs_or_sbs_cap_ext_done; - }; - - struct ath12k_wmi_rdy_parse { -@@ -777,20 +782,46 @@ struct sk_buff *ath12k_wmi_alloc_skb(str - return skb; - } - --int ath12k_wmi_mgmt_send(struct ath12k *ar, u32 vdev_id, u32 buf_id, -+int ath12k_wmi_mgmt_send(struct ath12k_link_vif *arvif, u32 buf_id, - struct sk_buff *frame) - { -+ struct ath12k *ar = arvif->ar; - struct ath12k_wmi_pdev *wmi = ar->wmi; - struct wmi_mgmt_send_cmd *cmd; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(frame); -- struct wmi_tlv *frame_tlv; -+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)frame->data; -+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif); -+ int cmd_len = sizeof(struct ath12k_wmi_mgmt_send_tx_params); -+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)hdr; -+ struct ath12k_wmi_mlo_mgmt_send_params *ml_params; -+ struct ath12k_base *ab = ar->ab; -+ struct wmi_tlv *frame_tlv, *tlv; -+ struct ath12k_skb_cb *skb_cb; -+ u32 buf_len, buf_len_aligned; -+ u32 vdev_id = arvif->vdev_id; -+ bool link_agnostic = false; - struct sk_buff *skb; -- u32 buf_len; - int ret, len; -+ void *ptr; - - buf_len = min_t(int, frame->len, WMI_MGMT_SEND_DOWNLD_LEN); - -- len = sizeof(*cmd) + sizeof(*frame_tlv) + roundup(buf_len, 4); -+ buf_len_aligned = roundup(buf_len, sizeof(u32)); -+ -+ len = sizeof(*cmd) + sizeof(*frame_tlv) + buf_len_aligned; -+ -+ if (ieee80211_vif_is_mld(vif)) { -+ skb_cb = ATH12K_SKB_CB(frame); -+ if ((skb_cb->flags & ATH12K_SKB_MLO_STA) && -+ ab->hw_params->hw_ops->is_frame_link_agnostic && -+ ab->hw_params->hw_ops->is_frame_link_agnostic(arvif, mgmt)) { -+ len += cmd_len + TLV_HDR_SIZE + sizeof(*ml_params); -+ ath12k_generic_dbg(ATH12K_DBG_MGMT, -+ "Sending Mgmt Frame fc 0x%0x as link agnostic", -+ mgmt->frame_control); -+ link_agnostic = true; -+ } -+ } - - skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len); - if (!skb) -@@ -809,10 +840,32 @@ int ath12k_wmi_mgmt_send(struct ath12k * - cmd->tx_params_valid = 0; - - frame_tlv = (struct wmi_tlv *)(skb->data + sizeof(*cmd)); -- frame_tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, buf_len); -+ frame_tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, buf_len_aligned); - - memcpy(frame_tlv->value, frame->data, buf_len); - -+ if (!link_agnostic) -+ goto send; -+ -+ ptr = skb->data + sizeof(*cmd) + sizeof(*frame_tlv) + buf_len_aligned; -+ -+ tlv = ptr; -+ -+ /* Tx params not used currently */ -+ tlv->header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_TX_SEND_PARAMS, cmd_len); -+ ptr += cmd_len; -+ -+ tlv = ptr; -+ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, sizeof(*ml_params)); -+ ptr += TLV_HDR_SIZE; -+ -+ ml_params = ptr; -+ ml_params->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_MLO_TX_SEND_PARAMS, -+ sizeof(*ml_params)); -+ -+ ml_params->hw_link_id = cpu_to_le32(WMI_MGMT_LINK_AGNOSTIC_ID); -+ -+send: - ret = ath12k_wmi_cmd_send(wmi, skb, WMI_MGMT_TX_SEND_CMDID); - if (ret) { - ath12k_warn(ar->ab, -@@ -2147,7 +2200,7 @@ static void ath12k_wmi_copy_peer_flags(s - cmd->peer_flags |= cpu_to_le32(WMI_PEER_AUTH); - if (arg->need_ptk_4_way) { - cmd->peer_flags |= cpu_to_le32(WMI_PEER_NEED_PTK_4_WAY); -- if (!hw_crypto_disabled) -+ if (!hw_crypto_disabled && arg->is_assoc) - cmd->peer_flags &= cpu_to_le32(~WMI_PEER_AUTH); - } - if (arg->need_gtk_2_way) -@@ -2365,6 +2418,7 @@ int ath12k_wmi_send_peer_assoc_cmd(struc - - eml_cap = arg->ml.eml_cap; - if (u16_get_bits(eml_cap, IEEE80211_EML_CAP_EMLSR_SUPP)) { -+ ml_params->flags |= cpu_to_le32(ATH12K_WMI_FLAG_MLO_EMLSR_SUPPORT); - /* Padding delay */ - eml_pad_delay = ieee80211_emlsr_pad_delay_in_us(eml_cap); - ml_params->emlsr_padding_delay_us = cpu_to_le32(eml_pad_delay); -@@ -4395,6 +4449,7 @@ static int ath12k_wmi_hw_mode_caps_parse - static int ath12k_wmi_hw_mode_caps(struct ath12k_base *soc, - u16 len, const void *ptr, void *data) - { -+ struct ath12k_svc_ext_info *svc_ext_info = &soc->wmi_ab.svc_ext_info; - struct ath12k_wmi_svc_rdy_ext_parse *svc_rdy_ext = data; - const struct ath12k_wmi_hw_mode_cap_params *hw_mode_caps; - enum wmi_host_hw_mode_config_type mode, pref; -@@ -4427,8 +4482,11 @@ static int ath12k_wmi_hw_mode_caps(struc - } - } - -- ath12k_dbg(soc, ATH12K_DBG_WMI, "preferred_hw_mode:%d\n", -- soc->wmi_ab.preferred_hw_mode); -+ svc_ext_info->num_hw_modes = svc_rdy_ext->n_hw_mode_caps; -+ -+ ath12k_dbg(soc, ATH12K_DBG_WMI, "num hw modes %u preferred_hw_mode %d\n", -+ svc_ext_info->num_hw_modes, soc->wmi_ab.preferred_hw_mode); -+ - if (soc->wmi_ab.preferred_hw_mode == WMI_HOST_HW_MODE_MAX) - return -EINVAL; - -@@ -4658,6 +4716,65 @@ free_dir_buff: - return ret; - } - -+static void -+ath12k_wmi_save_mac_phy_info(struct ath12k_base *ab, -+ const struct ath12k_wmi_mac_phy_caps_params *mac_phy_cap, -+ struct ath12k_svc_ext_mac_phy_info *mac_phy_info) -+{ -+ mac_phy_info->phy_id = __le32_to_cpu(mac_phy_cap->phy_id); -+ mac_phy_info->supported_bands = __le32_to_cpu(mac_phy_cap->supported_bands); -+ mac_phy_info->hw_freq_range.low_2ghz_freq = -+ __le32_to_cpu(mac_phy_cap->low_2ghz_chan_freq); -+ mac_phy_info->hw_freq_range.high_2ghz_freq = -+ __le32_to_cpu(mac_phy_cap->high_2ghz_chan_freq); -+ mac_phy_info->hw_freq_range.low_5ghz_freq = -+ __le32_to_cpu(mac_phy_cap->low_5ghz_chan_freq); -+ mac_phy_info->hw_freq_range.high_5ghz_freq = -+ __le32_to_cpu(mac_phy_cap->high_5ghz_chan_freq); -+} -+ -+static void -+ath12k_wmi_save_all_mac_phy_info(struct ath12k_base *ab, -+ struct ath12k_wmi_svc_rdy_ext_parse *svc_rdy_ext) -+{ -+ struct ath12k_svc_ext_info *svc_ext_info = &ab->wmi_ab.svc_ext_info; -+ const struct ath12k_wmi_mac_phy_caps_params *mac_phy_cap; -+ const struct ath12k_wmi_hw_mode_cap_params *hw_mode_cap; -+ struct ath12k_svc_ext_mac_phy_info *mac_phy_info; -+ u32 hw_mode_id, phy_bit_map; -+ u8 hw_idx; -+ -+ mac_phy_info = &svc_ext_info->mac_phy_info[0]; -+ mac_phy_cap = svc_rdy_ext->mac_phy_caps; -+ -+ for (hw_idx = 0; hw_idx < svc_ext_info->num_hw_modes; hw_idx++) { -+ hw_mode_cap = &svc_rdy_ext->hw_mode_caps[hw_idx]; -+ hw_mode_id = __le32_to_cpu(hw_mode_cap->hw_mode_id); -+ phy_bit_map = __le32_to_cpu(hw_mode_cap->phy_id_map); -+ -+ while (phy_bit_map) { -+ ath12k_wmi_save_mac_phy_info(ab, mac_phy_cap, mac_phy_info); -+ mac_phy_info->hw_mode_config_type = -+ le32_get_bits(hw_mode_cap->hw_mode_config_type, -+ WMI_HW_MODE_CAP_CFG_TYPE); -+ ath12k_dbg(ab, ATH12K_DBG_WMI, -+ "hw_idx %u hw_mode_id %u hw_mode_config_type %u supported_bands %u phy_id %u 2 GHz [%u - %u] 5 GHz [%u - %u]\n", -+ hw_idx, hw_mode_id, -+ mac_phy_info->hw_mode_config_type, -+ mac_phy_info->supported_bands, mac_phy_info->phy_id, -+ mac_phy_info->hw_freq_range.low_2ghz_freq, -+ mac_phy_info->hw_freq_range.high_2ghz_freq, -+ mac_phy_info->hw_freq_range.low_5ghz_freq, -+ mac_phy_info->hw_freq_range.high_5ghz_freq); -+ -+ mac_phy_cap++; -+ mac_phy_info++; -+ -+ phy_bit_map >>= 1; -+ } -+ } -+} -+ - static int ath12k_wmi_svc_rdy_ext_parse(struct ath12k_base *ab, - u16 tag, u16 len, - const void *ptr, void *data) -@@ -4706,6 +4823,8 @@ static int ath12k_wmi_svc_rdy_ext_parse( - return ret; - } - -+ ath12k_wmi_save_all_mac_phy_info(ab, svc_rdy_ext); -+ - svc_rdy_ext->mac_phy_done = true; - } else if (!svc_rdy_ext->ext_hal_reg_done) { - ret = ath12k_wmi_ext_hal_reg_caps(ab, len, ptr, svc_rdy_ext); -@@ -4922,10 +5041,449 @@ static int ath12k_wmi_tlv_mac_phy_caps_e - return 0; - } - -+static void -+ath12k_wmi_update_freq_info(struct ath12k_base *ab, -+ struct ath12k_svc_ext_mac_phy_info *mac_cap, -+ enum ath12k_hw_mode mode, -+ u32 phy_id) -+{ -+ struct ath12k_hw_mode_info *hw_mode_info = &ab->wmi_ab.hw_mode_info; -+ struct ath12k_hw_mode_freq_range_arg *mac_range; -+ -+ mac_range = &hw_mode_info->freq_range_caps[mode][phy_id]; -+ -+ if (mac_cap->supported_bands & WMI_HOST_WLAN_2GHZ_CAP) { -+ mac_range->low_2ghz_freq = max_t(u32, -+ mac_cap->hw_freq_range.low_2ghz_freq, -+ ATH12K_MIN_2GHZ_FREQ); -+ mac_range->high_2ghz_freq = mac_cap->hw_freq_range.high_2ghz_freq ? -+ min_t(u32, -+ mac_cap->hw_freq_range.high_2ghz_freq, -+ ATH12K_MAX_2GHZ_FREQ) : -+ ATH12K_MAX_2GHZ_FREQ; -+ } -+ -+ if (mac_cap->supported_bands & WMI_HOST_WLAN_5GHZ_CAP) { -+ mac_range->low_5ghz_freq = max_t(u32, -+ mac_cap->hw_freq_range.low_5ghz_freq, -+ ATH12K_MIN_5GHZ_FREQ); -+ mac_range->high_5ghz_freq = mac_cap->hw_freq_range.high_5ghz_freq ? -+ min_t(u32, -+ mac_cap->hw_freq_range.high_5ghz_freq, -+ ATH12K_MAX_6GHZ_FREQ) : -+ ATH12K_MAX_6GHZ_FREQ; -+ } -+} -+ -+static bool -+ath12k_wmi_all_phy_range_updated(struct ath12k_base *ab, -+ enum ath12k_hw_mode hwmode) -+{ -+ struct ath12k_hw_mode_info *hw_mode_info = &ab->wmi_ab.hw_mode_info; -+ struct ath12k_hw_mode_freq_range_arg *mac_range; -+ u8 phy_id; -+ -+ for (phy_id = 0; phy_id < MAX_RADIOS; phy_id++) { -+ mac_range = &hw_mode_info->freq_range_caps[hwmode][phy_id]; -+ /* modify SBS/DBS range only when both phy for DBS are filled */ -+ if (!mac_range->low_2ghz_freq && !mac_range->low_5ghz_freq) -+ return false; -+ } -+ -+ return true; -+} -+ -+static void ath12k_wmi_update_dbs_freq_info(struct ath12k_base *ab) -+{ -+ struct ath12k_hw_mode_info *hw_mode_info = &ab->wmi_ab.hw_mode_info; -+ struct ath12k_hw_mode_freq_range_arg *mac_range; -+ u8 phy_id; -+ -+ mac_range = hw_mode_info->freq_range_caps[ATH12K_HW_MODE_DBS]; -+ /* Reset 5 GHz range for shared mac for DBS */ -+ for (phy_id = 0; phy_id < MAX_RADIOS; phy_id++) { -+ if (mac_range[phy_id].low_2ghz_freq && -+ mac_range[phy_id].low_5ghz_freq) { -+ mac_range[phy_id].low_5ghz_freq = 0; -+ mac_range[phy_id].high_5ghz_freq = 0; -+ } -+ } -+} -+ -+static u32 -+ath12k_wmi_get_highest_5ghz_freq_from_range(struct ath12k_hw_mode_freq_range_arg *range) -+{ -+ u32 highest_freq = 0; -+ u8 phy_id; -+ -+ for (phy_id = 0; phy_id < MAX_RADIOS; phy_id++) { -+ if (range[phy_id].high_5ghz_freq > highest_freq) -+ highest_freq = range[phy_id].high_5ghz_freq; -+ } -+ -+ return highest_freq ? highest_freq : ATH12K_MAX_6GHZ_FREQ; -+} -+ -+static u32 -+ath12k_wmi_get_lowest_5ghz_freq_from_range(struct ath12k_hw_mode_freq_range_arg *range) -+{ -+ u32 lowest_freq = 0; -+ u8 phy_id; -+ -+ for (phy_id = 0; phy_id < MAX_RADIOS; phy_id++) { -+ if ((!lowest_freq && range[phy_id].low_5ghz_freq) || -+ range[phy_id].low_5ghz_freq < lowest_freq) -+ lowest_freq = range[phy_id].low_5ghz_freq; -+ } -+ -+ return lowest_freq ? lowest_freq : ATH12K_MIN_5GHZ_FREQ; -+} -+ -+static void -+ath12k_wmi_fill_upper_share_sbs_freq(struct ath12k_base *ab, -+ u16 sbs_range_sep, -+ struct ath12k_hw_mode_freq_range_arg *ref_freq) -+{ -+ struct ath12k_hw_mode_info *hw_mode_info = &ab->wmi_ab.hw_mode_info; -+ struct ath12k_hw_mode_freq_range_arg *upper_sbs_freq_range; -+ u8 phy_id; -+ -+ upper_sbs_freq_range = -+ hw_mode_info->freq_range_caps[ATH12K_HW_MODE_SBS_UPPER_SHARE]; -+ -+ for (phy_id = 0; phy_id < MAX_RADIOS; phy_id++) { -+ upper_sbs_freq_range[phy_id].low_2ghz_freq = -+ ref_freq[phy_id].low_2ghz_freq; -+ upper_sbs_freq_range[phy_id].high_2ghz_freq = -+ ref_freq[phy_id].high_2ghz_freq; -+ -+ /* update for shared mac */ -+ if (upper_sbs_freq_range[phy_id].low_2ghz_freq) { -+ upper_sbs_freq_range[phy_id].low_5ghz_freq = sbs_range_sep + 10; -+ upper_sbs_freq_range[phy_id].high_5ghz_freq = -+ ath12k_wmi_get_highest_5ghz_freq_from_range(ref_freq); -+ } else { -+ upper_sbs_freq_range[phy_id].low_5ghz_freq = -+ ath12k_wmi_get_lowest_5ghz_freq_from_range(ref_freq); -+ upper_sbs_freq_range[phy_id].high_5ghz_freq = sbs_range_sep; -+ } -+ } -+} -+ -+static void -+ath12k_wmi_fill_lower_share_sbs_freq(struct ath12k_base *ab, -+ u16 sbs_range_sep, -+ struct ath12k_hw_mode_freq_range_arg *ref_freq) -+{ -+ struct ath12k_hw_mode_info *hw_mode_info = &ab->wmi_ab.hw_mode_info; -+ struct ath12k_hw_mode_freq_range_arg *lower_sbs_freq_range; -+ u8 phy_id; -+ -+ lower_sbs_freq_range = -+ hw_mode_info->freq_range_caps[ATH12K_HW_MODE_SBS_LOWER_SHARE]; -+ -+ for (phy_id = 0; phy_id < MAX_RADIOS; phy_id++) { -+ lower_sbs_freq_range[phy_id].low_2ghz_freq = -+ ref_freq[phy_id].low_2ghz_freq; -+ lower_sbs_freq_range[phy_id].high_2ghz_freq = -+ ref_freq[phy_id].high_2ghz_freq; -+ -+ /* update for shared mac */ -+ if (lower_sbs_freq_range[phy_id].low_2ghz_freq) { -+ lower_sbs_freq_range[phy_id].low_5ghz_freq = -+ ath12k_wmi_get_lowest_5ghz_freq_from_range(ref_freq); -+ lower_sbs_freq_range[phy_id].high_5ghz_freq = sbs_range_sep; -+ } else { -+ lower_sbs_freq_range[phy_id].low_5ghz_freq = sbs_range_sep + 10; -+ lower_sbs_freq_range[phy_id].high_5ghz_freq = -+ ath12k_wmi_get_highest_5ghz_freq_from_range(ref_freq); -+ } -+ } -+} -+ -+static const char *ath12k_wmi_hw_mode_to_str(enum ath12k_hw_mode hw_mode) -+{ -+ static const char * const mode_str[] = { -+ [ATH12K_HW_MODE_SMM] = "SMM", -+ [ATH12K_HW_MODE_DBS] = "DBS", -+ [ATH12K_HW_MODE_SBS] = "SBS", -+ [ATH12K_HW_MODE_SBS_UPPER_SHARE] = "SBS_UPPER_SHARE", -+ [ATH12K_HW_MODE_SBS_LOWER_SHARE] = "SBS_LOWER_SHARE", -+ }; -+ -+ if (hw_mode >= ARRAY_SIZE(mode_str)) -+ return "Unknown"; -+ -+ return mode_str[hw_mode]; -+} -+ -+static void -+ath12k_wmi_dump_freq_range_per_mac(struct ath12k_base *ab, -+ struct ath12k_hw_mode_freq_range_arg *freq_range, -+ enum ath12k_hw_mode hw_mode) -+{ -+ u8 i; -+ -+ for (i = 0; i < MAX_RADIOS; i++) -+ if (freq_range[i].low_2ghz_freq || freq_range[i].low_5ghz_freq) -+ ath12k_dbg(ab, ATH12K_DBG_WMI, -+ "frequency range: %s(%d) mac %d 2 GHz [%d - %d] 5 GHz [%d - %d]", -+ ath12k_wmi_hw_mode_to_str(hw_mode), -+ hw_mode, i, -+ freq_range[i].low_2ghz_freq, -+ freq_range[i].high_2ghz_freq, -+ freq_range[i].low_5ghz_freq, -+ freq_range[i].high_5ghz_freq); -+} -+ -+static void ath12k_wmi_dump_freq_range(struct ath12k_base *ab) -+{ -+ struct ath12k_hw_mode_freq_range_arg *freq_range; -+ u8 i; -+ -+ for (i = ATH12K_HW_MODE_SMM; i < ATH12K_HW_MODE_MAX; i++) { -+ freq_range = ab->wmi_ab.hw_mode_info.freq_range_caps[i]; -+ ath12k_wmi_dump_freq_range_per_mac(ab, freq_range, i); -+ } -+} -+ -+static int ath12k_wmi_modify_sbs_freq(struct ath12k_base *ab, u8 phy_id) -+{ -+ struct ath12k_hw_mode_info *hw_mode_info = &ab->wmi_ab.hw_mode_info; -+ struct ath12k_hw_mode_freq_range_arg *sbs_mac_range, *shared_mac_range; -+ struct ath12k_hw_mode_freq_range_arg *non_shared_range; -+ u8 shared_phy_id; -+ -+ sbs_mac_range = &hw_mode_info->freq_range_caps[ATH12K_HW_MODE_SBS][phy_id]; -+ -+ /* if SBS mac range has both 2.4 and 5 GHz ranges, i.e. shared phy_id -+ * keep the range as it is in SBS -+ */ -+ if (sbs_mac_range->low_2ghz_freq && sbs_mac_range->low_5ghz_freq) -+ return 0; -+ -+ if (sbs_mac_range->low_2ghz_freq && !sbs_mac_range->low_5ghz_freq) { -+ ath12k_err(ab, "Invalid DBS/SBS mode with only 2.4Ghz"); -+ ath12k_wmi_dump_freq_range_per_mac(ab, sbs_mac_range, ATH12K_HW_MODE_SBS); -+ return -EINVAL; -+ } -+ -+ non_shared_range = sbs_mac_range; -+ /* if SBS mac range has only 5 GHz then it's the non-shared phy, so -+ * modify the range as per the shared mac. -+ */ -+ shared_phy_id = phy_id ? 0 : 1; -+ shared_mac_range = -+ &hw_mode_info->freq_range_caps[ATH12K_HW_MODE_SBS][shared_phy_id]; -+ -+ if (shared_mac_range->low_5ghz_freq > non_shared_range->low_5ghz_freq) { -+ ath12k_dbg(ab, ATH12K_DBG_WMI, "high 5 GHz shared"); -+ /* If the shared mac lower 5 GHz frequency is greater than -+ * non-shared mac lower 5 GHz frequency then the shared mac has -+ * high 5 GHz shared with 2.4 GHz. So non-shared mac's 5 GHz high -+ * freq should be less than the shared mac's low 5 GHz freq. -+ */ -+ if (non_shared_range->high_5ghz_freq >= -+ shared_mac_range->low_5ghz_freq) -+ non_shared_range->high_5ghz_freq = -+ max_t(u32, shared_mac_range->low_5ghz_freq - 10, -+ non_shared_range->low_5ghz_freq); -+ } else if (shared_mac_range->high_5ghz_freq < -+ non_shared_range->high_5ghz_freq) { -+ ath12k_dbg(ab, ATH12K_DBG_WMI, "low 5 GHz shared"); -+ /* If the shared mac high 5 GHz frequency is less than -+ * non-shared mac high 5 GHz frequency then the shared mac has -+ * low 5 GHz shared with 2.4 GHz. So non-shared mac's 5 GHz low -+ * freq should be greater than the shared mac's high 5 GHz freq. -+ */ -+ if (shared_mac_range->high_5ghz_freq >= -+ non_shared_range->low_5ghz_freq) -+ non_shared_range->low_5ghz_freq = -+ min_t(u32, shared_mac_range->high_5ghz_freq + 10, -+ non_shared_range->high_5ghz_freq); -+ } else { -+ ath12k_warn(ab, "invalid SBS range with all 5 GHz shared"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static void ath12k_wmi_update_sbs_freq_info(struct ath12k_base *ab) -+{ -+ struct ath12k_hw_mode_info *hw_mode_info = &ab->wmi_ab.hw_mode_info; -+ struct ath12k_hw_mode_freq_range_arg *mac_range; -+ u16 sbs_range_sep; -+ u8 phy_id; -+ int ret; -+ -+ mac_range = hw_mode_info->freq_range_caps[ATH12K_HW_MODE_SBS]; -+ -+ /* If sbs_lower_band_end_freq has a value, then the frequency range -+ * will be split using that value. -+ */ -+ sbs_range_sep = ab->wmi_ab.sbs_lower_band_end_freq; -+ if (sbs_range_sep) { -+ ath12k_wmi_fill_upper_share_sbs_freq(ab, sbs_range_sep, -+ mac_range); -+ ath12k_wmi_fill_lower_share_sbs_freq(ab, sbs_range_sep, -+ mac_range); -+ /* Hardware specifies the range boundary with sbs_range_sep, -+ * (i.e. the boundary between 5 GHz high and 5 GHz low), -+ * reset the original one to make sure it will not get used. -+ */ -+ memset(mac_range, 0, sizeof(*mac_range) * MAX_RADIOS); -+ return; -+ } -+ -+ /* If sbs_lower_band_end_freq is not set that means firmware will send one -+ * shared mac range and one non-shared mac range. so update that freq. -+ */ -+ for (phy_id = 0; phy_id < MAX_RADIOS; phy_id++) { -+ ret = ath12k_wmi_modify_sbs_freq(ab, phy_id); -+ if (ret) { -+ memset(mac_range, 0, sizeof(*mac_range) * MAX_RADIOS); -+ break; -+ } -+ } -+} -+ -+static void -+ath12k_wmi_update_mac_freq_info(struct ath12k_base *ab, -+ enum wmi_host_hw_mode_config_type hw_config_type, -+ u32 phy_id, -+ struct ath12k_svc_ext_mac_phy_info *mac_cap) -+{ -+ if (phy_id >= MAX_RADIOS) { -+ ath12k_err(ab, "mac more than two not supported: %d", phy_id); -+ return; -+ } -+ -+ ath12k_dbg(ab, ATH12K_DBG_WMI, -+ "hw_mode_cfg %d mac %d band 0x%x SBS cutoff freq %d 2 GHz [%d - %d] 5 GHz [%d - %d]", -+ hw_config_type, phy_id, mac_cap->supported_bands, -+ ab->wmi_ab.sbs_lower_band_end_freq, -+ mac_cap->hw_freq_range.low_2ghz_freq, -+ mac_cap->hw_freq_range.high_2ghz_freq, -+ mac_cap->hw_freq_range.low_5ghz_freq, -+ mac_cap->hw_freq_range.high_5ghz_freq); -+ -+ switch (hw_config_type) { -+ case WMI_HOST_HW_MODE_SINGLE: -+ if (phy_id) { -+ ath12k_dbg(ab, ATH12K_DBG_WMI, "mac phy 1 is not supported"); -+ break; -+ } -+ ath12k_wmi_update_freq_info(ab, mac_cap, ATH12K_HW_MODE_SMM, phy_id); -+ break; -+ -+ case WMI_HOST_HW_MODE_DBS: -+ if (!ath12k_wmi_all_phy_range_updated(ab, ATH12K_HW_MODE_DBS)) -+ ath12k_wmi_update_freq_info(ab, mac_cap, -+ ATH12K_HW_MODE_DBS, phy_id); -+ break; -+ case WMI_HOST_HW_MODE_DBS_SBS: -+ case WMI_HOST_HW_MODE_DBS_OR_SBS: -+ ath12k_wmi_update_freq_info(ab, mac_cap, ATH12K_HW_MODE_DBS, phy_id); -+ if (ab->wmi_ab.sbs_lower_band_end_freq || -+ mac_cap->hw_freq_range.low_5ghz_freq || -+ mac_cap->hw_freq_range.low_2ghz_freq) -+ ath12k_wmi_update_freq_info(ab, mac_cap, ATH12K_HW_MODE_SBS, -+ phy_id); -+ -+ if (ath12k_wmi_all_phy_range_updated(ab, ATH12K_HW_MODE_DBS)) -+ ath12k_wmi_update_dbs_freq_info(ab); -+ if (ath12k_wmi_all_phy_range_updated(ab, ATH12K_HW_MODE_SBS)) -+ ath12k_wmi_update_sbs_freq_info(ab); -+ break; -+ case WMI_HOST_HW_MODE_SBS: -+ case WMI_HOST_HW_MODE_SBS_PASSIVE: -+ ath12k_wmi_update_freq_info(ab, mac_cap, ATH12K_HW_MODE_SBS, phy_id); -+ if (ath12k_wmi_all_phy_range_updated(ab, ATH12K_HW_MODE_SBS)) -+ ath12k_wmi_update_sbs_freq_info(ab); -+ -+ break; -+ default: -+ break; -+ } -+} -+ -+static bool ath12k_wmi_sbs_range_present(struct ath12k_base *ab) -+{ -+ if (ath12k_wmi_all_phy_range_updated(ab, ATH12K_HW_MODE_SBS) || -+ (ab->wmi_ab.sbs_lower_band_end_freq && -+ ath12k_wmi_all_phy_range_updated(ab, ATH12K_HW_MODE_SBS_LOWER_SHARE) && -+ ath12k_wmi_all_phy_range_updated(ab, ATH12K_HW_MODE_SBS_UPPER_SHARE))) -+ return true; -+ -+ return false; -+} -+ -+static int ath12k_wmi_update_hw_mode_list(struct ath12k_base *ab) -+{ -+ struct ath12k_svc_ext_info *svc_ext_info = &ab->wmi_ab.svc_ext_info; -+ struct ath12k_hw_mode_info *info = &ab->wmi_ab.hw_mode_info; -+ enum wmi_host_hw_mode_config_type hw_config_type; -+ struct ath12k_svc_ext_mac_phy_info *tmp; -+ bool dbs_mode = false, sbs_mode = false; -+ u32 i, j = 0; -+ -+ if (!svc_ext_info->num_hw_modes) { -+ ath12k_err(ab, "invalid number of hw modes"); -+ return -EINVAL; -+ } -+ -+ ath12k_dbg(ab, ATH12K_DBG_WMI, "updated HW mode list: num modes %d", -+ svc_ext_info->num_hw_modes); -+ -+ memset(info->freq_range_caps, 0, sizeof(info->freq_range_caps)); -+ -+ for (i = 0; i < svc_ext_info->num_hw_modes; i++) { -+ if (j >= ATH12K_MAX_MAC_PHY_CAP) -+ return -EINVAL; -+ -+ /* Update for MAC0 */ -+ tmp = &svc_ext_info->mac_phy_info[j++]; -+ hw_config_type = tmp->hw_mode_config_type; -+ ath12k_wmi_update_mac_freq_info(ab, hw_config_type, tmp->phy_id, tmp); -+ -+ /* SBS and DBS have dual MAC. Up to 2 MACs are considered. */ -+ if (hw_config_type == WMI_HOST_HW_MODE_DBS || -+ hw_config_type == WMI_HOST_HW_MODE_SBS_PASSIVE || -+ hw_config_type == WMI_HOST_HW_MODE_SBS || -+ hw_config_type == WMI_HOST_HW_MODE_DBS_OR_SBS) { -+ if (j >= ATH12K_MAX_MAC_PHY_CAP) -+ return -EINVAL; -+ /* Update for MAC1 */ -+ tmp = &svc_ext_info->mac_phy_info[j++]; -+ ath12k_wmi_update_mac_freq_info(ab, hw_config_type, -+ tmp->phy_id, tmp); -+ -+ if (hw_config_type == WMI_HOST_HW_MODE_DBS || -+ hw_config_type == WMI_HOST_HW_MODE_DBS_OR_SBS) -+ dbs_mode = true; -+ -+ if (ath12k_wmi_sbs_range_present(ab) && -+ (hw_config_type == WMI_HOST_HW_MODE_SBS_PASSIVE || -+ hw_config_type == WMI_HOST_HW_MODE_SBS || -+ hw_config_type == WMI_HOST_HW_MODE_DBS_OR_SBS)) -+ sbs_mode = true; -+ } -+ } -+ -+ info->support_dbs = dbs_mode; -+ info->support_sbs = sbs_mode; -+ -+ ath12k_wmi_dump_freq_range(ab); -+ -+ return 0; -+} -+ - static int ath12k_wmi_svc_rdy_ext2_parse(struct ath12k_base *ab, - u16 tag, u16 len, - const void *ptr, void *data) - { -+ const struct ath12k_wmi_dbs_or_sbs_cap_params *dbs_or_sbs_caps; - struct ath12k_wmi_pdev *wmi_handle = &ab->wmi_ab.wmi[0]; - struct ath12k_wmi_svc_rdy_ext2_parse *parse = data; - int ret; -@@ -4967,7 +5525,32 @@ static int ath12k_wmi_svc_rdy_ext2_parse - } - - parse->mac_phy_caps_ext_done = true; -+ } else if (!parse->hal_reg_caps_ext2_done) { -+ parse->hal_reg_caps_ext2_done = true; -+ } else if (!parse->scan_radio_caps_ext2_done) { -+ parse->scan_radio_caps_ext2_done = true; -+ } else if (!parse->twt_caps_done) { -+ parse->twt_caps_done = true; -+ } else if (!parse->htt_msdu_idx_to_qtype_map_done) { -+ parse->htt_msdu_idx_to_qtype_map_done = true; -+ } else if (!parse->dbs_or_sbs_cap_ext_done) { -+ dbs_or_sbs_caps = ptr; -+ ab->wmi_ab.sbs_lower_band_end_freq = -+ __le32_to_cpu(dbs_or_sbs_caps->sbs_lower_band_end_freq); -+ -+ ath12k_dbg(ab, ATH12K_DBG_WMI, "sbs_lower_band_end_freq %u\n", -+ ab->wmi_ab.sbs_lower_band_end_freq); -+ -+ ret = ath12k_wmi_update_hw_mode_list(ab); -+ if (ret) { -+ ath12k_warn(ab, "failed to update hw mode list: %d\n", -+ ret); -+ return ret; -+ } -+ -+ parse->dbs_or_sbs_cap_ext_done = true; - } -+ - break; - default: - break; -@@ -5606,6 +6189,11 @@ static int wmi_process_mgmt_tx_comp(stru - dma_unmap_single(ar->ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); - - info = IEEE80211_SKB_CB(msdu); -+ memset(&info->status, 0, sizeof(info->status)); -+ -+ /* skip tx rate update from ieee80211_status*/ -+ info->status.rates[0].idx = -1; -+ - if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && !status) - info->flags |= IEEE80211_TX_STAT_ACK; - -@@ -6957,7 +7545,7 @@ static int ath12k_wmi_tlv_services_parse - void *data) - { - const struct wmi_service_available_event *ev; -- u32 *wmi_ext2_service_bitmap; -+ __le32 *wmi_ext2_service_bitmap; - int i, j; - u16 expected_len; - -@@ -6989,12 +7577,12 @@ static int ath12k_wmi_tlv_services_parse - ev->wmi_service_segment_bitmap[3]); - break; - case WMI_TAG_ARRAY_UINT32: -- wmi_ext2_service_bitmap = (u32 *)ptr; -+ wmi_ext2_service_bitmap = (__le32 *)ptr; - for (i = 0, j = WMI_MAX_EXT_SERVICE; - i < WMI_SERVICE_SEGMENT_BM_SIZE32 && j < WMI_MAX_EXT2_SERVICE; - i++) { - do { -- if (wmi_ext2_service_bitmap[i] & -+ if (__le32_to_cpu(wmi_ext2_service_bitmap[i]) & - BIT(j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32)) - set_bit(j, ab->wmi_ab.svc_map); - } while (++j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32); -@@ -7002,8 +7590,10 @@ static int ath12k_wmi_tlv_services_parse - - ath12k_dbg(ab, ATH12K_DBG_WMI, - "wmi_ext2_service_bitmap 0x%04x 0x%04x 0x%04x 0x%04x", -- wmi_ext2_service_bitmap[0], wmi_ext2_service_bitmap[1], -- wmi_ext2_service_bitmap[2], wmi_ext2_service_bitmap[3]); -+ __le32_to_cpu(wmi_ext2_service_bitmap[0]), -+ __le32_to_cpu(wmi_ext2_service_bitmap[1]), -+ __le32_to_cpu(wmi_ext2_service_bitmap[2]), -+ __le32_to_cpu(wmi_ext2_service_bitmap[3])); - break; - } - return 0; -@@ -7626,6 +8216,64 @@ static int ath12k_wmi_pull_fw_stats(stru - &parse); - } - -+static void ath12k_wmi_fw_stats_process(struct ath12k *ar, -+ struct ath12k_fw_stats *stats) -+{ -+ struct ath12k_base *ab = ar->ab; -+ struct ath12k_pdev *pdev; -+ bool is_end = true; -+ size_t total_vdevs_started = 0; -+ int i; -+ -+ if (stats->stats_id == WMI_REQUEST_VDEV_STAT) { -+ if (list_empty(&stats->vdevs)) { -+ ath12k_warn(ab, "empty vdev stats"); -+ return; -+ } -+ /* FW sends all the active VDEV stats irrespective of PDEV, -+ * hence limit until the count of all VDEVs started -+ */ -+ rcu_read_lock(); -+ for (i = 0; i < ab->num_radios; i++) { -+ pdev = rcu_dereference(ab->pdevs_active[i]); -+ if (pdev && pdev->ar) -+ total_vdevs_started += pdev->ar->num_started_vdevs; -+ } -+ rcu_read_unlock(); -+ -+ if (total_vdevs_started) -+ is_end = ((++ar->fw_stats.num_vdev_recvd) == -+ total_vdevs_started); -+ -+ list_splice_tail_init(&stats->vdevs, -+ &ar->fw_stats.vdevs); -+ -+ if (is_end) -+ complete(&ar->fw_stats_done); -+ -+ return; -+ } -+ -+ if (stats->stats_id == WMI_REQUEST_BCN_STAT) { -+ if (list_empty(&stats->bcn)) { -+ ath12k_warn(ab, "empty beacon stats"); -+ return; -+ } -+ /* Mark end until we reached the count of all started VDEVs -+ * within the PDEV -+ */ -+ if (ar->num_started_vdevs) -+ is_end = ((++ar->fw_stats.num_bcn_recvd) == -+ ar->num_started_vdevs); -+ -+ list_splice_tail_init(&stats->bcn, -+ &ar->fw_stats.bcn); -+ -+ if (is_end) -+ complete(&ar->fw_stats_done); -+ } -+} -+ - static void ath12k_update_stats_event(struct ath12k_base *ab, struct sk_buff *skb) - { - struct ath12k_fw_stats stats = {}; -@@ -7655,19 +8303,15 @@ static void ath12k_update_stats_event(st - - spin_lock_bh(&ar->data_lock); - -- /* WMI_REQUEST_PDEV_STAT can be requested via .get_txpower mac ops or via -- * debugfs fw stats. Therefore, processing it separately. -- */ -+ /* Handle WMI_REQUEST_PDEV_STAT status update */ - if (stats.stats_id == WMI_REQUEST_PDEV_STAT) { - list_splice_tail_init(&stats.pdevs, &ar->fw_stats.pdevs); -- ar->fw_stats.fw_stats_done = true; -+ complete(&ar->fw_stats_done); - goto complete; - } - -- /* WMI_REQUEST_VDEV_STAT and WMI_REQUEST_BCN_STAT are currently requested only -- * via debugfs fw stats. Hence, processing these in debugfs context. -- */ -- ath12k_debugfs_fw_stats_process(ar, &stats); -+ /* Handle WMI_REQUEST_VDEV_STAT and WMI_REQUEST_BCN_STAT updates. */ -+ ath12k_wmi_fw_stats_process(ar, &stats); - - complete: - complete(&ar->fw_stats_complete); -@@ -9911,3 +10555,224 @@ int ath12k_wmi_send_vdev_set_tpc_power(s - - return 0; - } -+ -+static int -+ath12k_wmi_fill_disallowed_bmap(struct ath12k_base *ab, -+ struct wmi_disallowed_mlo_mode_bitmap_params *dislw_bmap, -+ struct wmi_mlo_link_set_active_arg *arg) -+{ -+ struct wmi_ml_disallow_mode_bmap_arg *dislw_bmap_arg; -+ u8 i; -+ -+ if (arg->num_disallow_mode_comb > -+ ARRAY_SIZE(arg->disallow_bmap)) { -+ ath12k_warn(ab, "invalid num_disallow_mode_comb: %d", -+ arg->num_disallow_mode_comb); -+ return -EINVAL; -+ } -+ -+ dislw_bmap_arg = &arg->disallow_bmap[0]; -+ for (i = 0; i < arg->num_disallow_mode_comb; i++) { -+ dislw_bmap->tlv_header = -+ ath12k_wmi_tlv_cmd_hdr(0, sizeof(*dislw_bmap)); -+ dislw_bmap->disallowed_mode_bitmap = -+ cpu_to_le32(dislw_bmap_arg->disallowed_mode); -+ dislw_bmap->ieee_link_id_comb = -+ le32_encode_bits(dislw_bmap_arg->ieee_link_id[0], -+ WMI_DISALW_MLO_MODE_BMAP_IEEE_LINK_ID_COMB_1) | -+ le32_encode_bits(dislw_bmap_arg->ieee_link_id[1], -+ WMI_DISALW_MLO_MODE_BMAP_IEEE_LINK_ID_COMB_2) | -+ le32_encode_bits(dislw_bmap_arg->ieee_link_id[2], -+ WMI_DISALW_MLO_MODE_BMAP_IEEE_LINK_ID_COMB_3) | -+ le32_encode_bits(dislw_bmap_arg->ieee_link_id[3], -+ WMI_DISALW_MLO_MODE_BMAP_IEEE_LINK_ID_COMB_4); -+ -+ ath12k_dbg(ab, ATH12K_DBG_WMI, -+ "entry %d disallowed_mode %d ieee_link_id_comb 0x%x", -+ i, dislw_bmap_arg->disallowed_mode, -+ dislw_bmap_arg->ieee_link_id_comb); -+ dislw_bmap++; -+ dislw_bmap_arg++; -+ } -+ -+ return 0; -+} -+ -+int ath12k_wmi_send_mlo_link_set_active_cmd(struct ath12k_base *ab, -+ struct wmi_mlo_link_set_active_arg *arg) -+{ -+ struct wmi_disallowed_mlo_mode_bitmap_params *disallowed_mode_bmap; -+ struct wmi_mlo_set_active_link_number_params *link_num_param; -+ u32 num_link_num_param = 0, num_vdev_bitmap = 0; -+ struct ath12k_wmi_base *wmi_ab = &ab->wmi_ab; -+ struct wmi_mlo_link_set_active_cmd *cmd; -+ u32 num_inactive_vdev_bitmap = 0; -+ u32 num_disallow_mode_comb = 0; -+ struct wmi_tlv *tlv; -+ struct sk_buff *skb; -+ __le32 *vdev_bitmap; -+ void *buf_ptr; -+ int i, ret; -+ u32 len; -+ -+ if (!arg->num_vdev_bitmap && !arg->num_link_entry) { -+ ath12k_warn(ab, "Invalid num_vdev_bitmap and num_link_entry"); -+ return -EINVAL; -+ } -+ -+ switch (arg->force_mode) { -+ case WMI_MLO_LINK_FORCE_MODE_ACTIVE_LINK_NUM: -+ case WMI_MLO_LINK_FORCE_MODE_INACTIVE_LINK_NUM: -+ num_link_num_param = arg->num_link_entry; -+ fallthrough; -+ case WMI_MLO_LINK_FORCE_MODE_ACTIVE: -+ case WMI_MLO_LINK_FORCE_MODE_INACTIVE: -+ case WMI_MLO_LINK_FORCE_MODE_NO_FORCE: -+ num_vdev_bitmap = arg->num_vdev_bitmap; -+ break; -+ case WMI_MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE: -+ num_vdev_bitmap = arg->num_vdev_bitmap; -+ num_inactive_vdev_bitmap = arg->num_inactive_vdev_bitmap; -+ break; -+ default: -+ ath12k_warn(ab, "Invalid force mode: %u", arg->force_mode); -+ return -EINVAL; -+ } -+ -+ num_disallow_mode_comb = arg->num_disallow_mode_comb; -+ len = sizeof(*cmd) + -+ TLV_HDR_SIZE + sizeof(*link_num_param) * num_link_num_param + -+ TLV_HDR_SIZE + sizeof(*vdev_bitmap) * num_vdev_bitmap + -+ TLV_HDR_SIZE + TLV_HDR_SIZE + TLV_HDR_SIZE + -+ TLV_HDR_SIZE + sizeof(*disallowed_mode_bmap) * num_disallow_mode_comb; -+ if (arg->force_mode == WMI_MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE) -+ len += sizeof(*vdev_bitmap) * num_inactive_vdev_bitmap; -+ -+ skb = ath12k_wmi_alloc_skb(wmi_ab, len); -+ if (!skb) -+ return -ENOMEM; -+ -+ cmd = (struct wmi_mlo_link_set_active_cmd *)skb->data; -+ cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_MLO_LINK_SET_ACTIVE_CMD, -+ sizeof(*cmd)); -+ cmd->force_mode = cpu_to_le32(arg->force_mode); -+ cmd->reason = cpu_to_le32(arg->reason); -+ ath12k_dbg(ab, ATH12K_DBG_WMI, -+ "mode %d reason %d num_link_num_param %d num_vdev_bitmap %d inactive %d num_disallow_mode_comb %d", -+ arg->force_mode, arg->reason, num_link_num_param, -+ num_vdev_bitmap, num_inactive_vdev_bitmap, -+ num_disallow_mode_comb); -+ -+ buf_ptr = skb->data + sizeof(*cmd); -+ tlv = buf_ptr; -+ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, -+ sizeof(*link_num_param) * num_link_num_param); -+ buf_ptr += TLV_HDR_SIZE; -+ -+ if (num_link_num_param) { -+ cmd->ctrl_flags = -+ le32_encode_bits(arg->ctrl_flags.dync_force_link_num ? 1 : 0, -+ CRTL_F_DYNC_FORCE_LINK_NUM); -+ -+ link_num_param = buf_ptr; -+ for (i = 0; i < num_link_num_param; i++) { -+ link_num_param->tlv_header = -+ ath12k_wmi_tlv_cmd_hdr(0, sizeof(*link_num_param)); -+ link_num_param->num_of_link = -+ cpu_to_le32(arg->link_num[i].num_of_link); -+ link_num_param->vdev_type = -+ cpu_to_le32(arg->link_num[i].vdev_type); -+ link_num_param->vdev_subtype = -+ cpu_to_le32(arg->link_num[i].vdev_subtype); -+ link_num_param->home_freq = -+ cpu_to_le32(arg->link_num[i].home_freq); -+ ath12k_dbg(ab, ATH12K_DBG_WMI, -+ "entry %d num_of_link %d vdev type %d subtype %d freq %d control_flags %d", -+ i, arg->link_num[i].num_of_link, -+ arg->link_num[i].vdev_type, -+ arg->link_num[i].vdev_subtype, -+ arg->link_num[i].home_freq, -+ __le32_to_cpu(cmd->ctrl_flags)); -+ link_num_param++; -+ } -+ -+ buf_ptr += sizeof(*link_num_param) * num_link_num_param; -+ } -+ -+ tlv = buf_ptr; -+ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, -+ sizeof(*vdev_bitmap) * num_vdev_bitmap); -+ buf_ptr += TLV_HDR_SIZE; -+ -+ if (num_vdev_bitmap) { -+ vdev_bitmap = buf_ptr; -+ for (i = 0; i < num_vdev_bitmap; i++) { -+ vdev_bitmap[i] = cpu_to_le32(arg->vdev_bitmap[i]); -+ ath12k_dbg(ab, ATH12K_DBG_WMI, "entry %d vdev_id_bitmap 0x%x", -+ i, arg->vdev_bitmap[i]); -+ } -+ -+ buf_ptr += sizeof(*vdev_bitmap) * num_vdev_bitmap; -+ } -+ -+ if (arg->force_mode == WMI_MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE) { -+ tlv = buf_ptr; -+ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, -+ sizeof(*vdev_bitmap) * -+ num_inactive_vdev_bitmap); -+ buf_ptr += TLV_HDR_SIZE; -+ -+ if (num_inactive_vdev_bitmap) { -+ vdev_bitmap = buf_ptr; -+ for (i = 0; i < num_inactive_vdev_bitmap; i++) { -+ vdev_bitmap[i] = -+ cpu_to_le32(arg->inactive_vdev_bitmap[i]); -+ ath12k_dbg(ab, ATH12K_DBG_WMI, -+ "entry %d inactive_vdev_id_bitmap 0x%x", -+ i, arg->inactive_vdev_bitmap[i]); -+ } -+ -+ buf_ptr += sizeof(*vdev_bitmap) * num_inactive_vdev_bitmap; -+ } -+ } else { -+ /* add empty vdev bitmap2 tlv */ -+ tlv = buf_ptr; -+ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, 0); -+ buf_ptr += TLV_HDR_SIZE; -+ } -+ -+ /* add empty ieee_link_id_bitmap tlv */ -+ tlv = buf_ptr; -+ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, 0); -+ buf_ptr += TLV_HDR_SIZE; -+ -+ /* add empty ieee_link_id_bitmap2 tlv */ -+ tlv = buf_ptr; -+ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_UINT32, 0); -+ buf_ptr += TLV_HDR_SIZE; -+ -+ tlv = buf_ptr; -+ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, -+ sizeof(*disallowed_mode_bmap) * -+ arg->num_disallow_mode_comb); -+ buf_ptr += TLV_HDR_SIZE; -+ -+ ret = ath12k_wmi_fill_disallowed_bmap(ab, buf_ptr, arg); -+ if (ret) -+ goto free_skb; -+ -+ ret = ath12k_wmi_cmd_send(&wmi_ab->wmi[0], skb, WMI_MLO_LINK_SET_ACTIVE_CMDID); -+ if (ret) { -+ ath12k_warn(ab, -+ "failed to send WMI_MLO_LINK_SET_ACTIVE_CMDID: %d\n", ret); -+ goto free_skb; -+ } -+ -+ ath12k_dbg(ab, ATH12K_DBG_WMI, "WMI mlo link set active cmd"); -+ -+ return ret; -+ -+free_skb: -+ dev_kfree_skb(skb); -+ return ret; -+} -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/wmi.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/wmi.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath12k/wmi.h 2025-10-22 13:53:23.383328321 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath12k/wmi.h 2025-10-22 13:53:56.607168698 -0400 -@@ -1974,6 +1974,7 @@ enum wmi_tlv_tag { - WMI_TAG_TPC_STATS_CTL_PWR_TABLE_EVENT, - WMI_TAG_VDEV_SET_TPC_POWER_CMD = 0x3B5, - WMI_TAG_VDEV_CH_POWER_INFO, -+ WMI_TAG_MLO_LINK_SET_ACTIVE_CMD = 0x3BE, - WMI_TAG_EHT_RATE_SET = 0x3C4, - WMI_TAG_DCS_AWGN_INT_TYPE = 0x3C5, - WMI_TAG_MLO_TX_SEND_PARAMS, -@@ -2617,6 +2618,8 @@ struct ath12k_wmi_soc_mac_phy_hw_mode_ca - __le32 num_chainmask_tables; - } __packed; - -+#define WMI_HW_MODE_CAP_CFG_TYPE GENMASK(27, 0) -+ - struct ath12k_wmi_hw_mode_cap_params { - __le32 tlv_header; - __le32 hw_mode_id; -@@ -2666,6 +2669,12 @@ struct ath12k_wmi_mac_phy_caps_params { - __le32 he_cap_info_2g_ext; - __le32 he_cap_info_5g_ext; - __le32 he_cap_info_internal; -+ __le32 wireless_modes; -+ __le32 low_2ghz_chan_freq; -+ __le32 high_2ghz_chan_freq; -+ __le32 low_5ghz_chan_freq; -+ __le32 high_5ghz_chan_freq; -+ __le32 nss_ratio; - } __packed; - - struct ath12k_wmi_hal_reg_caps_ext_params { -@@ -2739,6 +2748,11 @@ struct wmi_service_ready_ext2_event { - __le32 default_num_msduq_supported_per_tid; - } __packed; - -+struct ath12k_wmi_dbs_or_sbs_cap_params { -+ __le32 hw_mode_id; -+ __le32 sbs_lower_band_end_freq; -+} __packed; -+ - struct ath12k_wmi_caps_ext_params { - __le32 hw_mode_id; - __le32 pdev_and_hw_link_ids; -@@ -3746,6 +3760,7 @@ struct wmi_vdev_install_key_arg { - u32 key_idx; - u32 key_flags; - u32 key_cipher; -+ u32 ieee80211_key_cipher; - u32 key_len; - u32 key_txmic_len; - u32 key_rxmic_len; -@@ -3934,6 +3949,7 @@ struct wmi_stop_scan_cmd { - } __packed; - - struct ath12k_wmi_scan_chan_list_arg { -+ struct list_head list; - u32 pdev_id; - u16 nallchans; - struct ath12k_wmi_channel_arg channel[]; -@@ -3947,6 +3963,7 @@ struct wmi_scan_chan_list_cmd { - } __packed; - - #define WMI_MGMT_SEND_DOWNLD_LEN 64 -+#define WMI_MGMT_LINK_AGNOSTIC_ID 0xFFFFFFFF - - #define WMI_TX_PARAMS_DWORD0_POWER GENMASK(7, 0) - #define WMI_TX_PARAMS_DWORD0_MCS_MASK GENMASK(19, 8) -@@ -3972,7 +3989,18 @@ struct wmi_mgmt_send_cmd { - - /* This TLV is followed by struct wmi_mgmt_frame */ - -- /* Followed by struct wmi_mgmt_send_params */ -+ /* Followed by struct ath12k_wmi_mlo_mgmt_send_params */ -+} __packed; -+ -+struct ath12k_wmi_mlo_mgmt_send_params { -+ __le32 tlv_header; -+ __le32 hw_link_id; -+} __packed; -+ -+struct ath12k_wmi_mgmt_send_tx_params { -+ __le32 tlv_header; -+ __le32 tx_param_dword0; -+ __le32 tx_param_dword1; - } __packed; - - struct wmi_sta_powersave_mode_cmd { -@@ -5049,6 +5077,53 @@ struct ath12k_wmi_pdev { - u32 rx_decap_mode; - }; - -+struct ath12k_hw_mode_freq_range_arg { -+ u32 low_2ghz_freq; -+ u32 high_2ghz_freq; -+ u32 low_5ghz_freq; -+ u32 high_5ghz_freq; -+}; -+ -+struct ath12k_svc_ext_mac_phy_info { -+ enum wmi_host_hw_mode_config_type hw_mode_config_type; -+ u32 phy_id; -+ u32 supported_bands; -+ struct ath12k_hw_mode_freq_range_arg hw_freq_range; -+}; -+ -+#define ATH12K_MAX_MAC_PHY_CAP 8 -+ -+struct ath12k_svc_ext_info { -+ u32 num_hw_modes; -+ struct ath12k_svc_ext_mac_phy_info mac_phy_info[ATH12K_MAX_MAC_PHY_CAP]; -+}; -+ -+/** -+ * enum ath12k_hw_mode - enum for host mode -+ * @ATH12K_HW_MODE_SMM: Single mac mode -+ * @ATH12K_HW_MODE_DBS: DBS mode -+ * @ATH12K_HW_MODE_SBS: SBS mode with either high share or low share -+ * @ATH12K_HW_MODE_SBS_UPPER_SHARE: Higher 5 GHz shared with 2.4 GHz -+ * @ATH12K_HW_MODE_SBS_LOWER_SHARE: Lower 5 GHz shared with 2.4 GHz -+ * @ATH12K_HW_MODE_MAX: Max, used to indicate invalid mode -+ */ -+enum ath12k_hw_mode { -+ ATH12K_HW_MODE_SMM, -+ ATH12K_HW_MODE_DBS, -+ ATH12K_HW_MODE_SBS, -+ ATH12K_HW_MODE_SBS_UPPER_SHARE, -+ ATH12K_HW_MODE_SBS_LOWER_SHARE, -+ ATH12K_HW_MODE_MAX, -+}; -+ -+struct ath12k_hw_mode_info { -+ bool support_dbs:1; -+ bool support_sbs:1; -+ -+ struct ath12k_hw_mode_freq_range_arg freq_range_caps[ATH12K_HW_MODE_MAX] -+ [MAX_RADIOS]; -+}; -+ - struct ath12k_wmi_base { - struct ath12k_base *ab; - struct ath12k_wmi_pdev wmi[MAX_RADIOS]; -@@ -5066,6 +5141,10 @@ struct ath12k_wmi_base { - enum wmi_host_hw_mode_config_type preferred_hw_mode; - - struct ath12k_wmi_target_cap_arg *targ_cap; -+ -+ struct ath12k_svc_ext_info svc_ext_info; -+ u32 sbs_lower_band_end_freq; -+ struct ath12k_hw_mode_info hw_mode_info; - }; - - struct wmi_pdev_set_bios_interface_cmd { -@@ -5997,6 +6076,118 @@ struct wmi_vdev_set_tpc_power_cmd { - */ - } __packed; - -+#define CRTL_F_DYNC_FORCE_LINK_NUM GENMASK(3, 2) -+ -+struct wmi_mlo_link_set_active_cmd { -+ __le32 tlv_header; -+ __le32 force_mode; -+ __le32 reason; -+ __le32 use_ieee_link_id_bitmap; -+ struct ath12k_wmi_mac_addr_params ap_mld_mac_addr; -+ __le32 ctrl_flags; -+} __packed; -+ -+struct wmi_mlo_set_active_link_number_params { -+ __le32 tlv_header; -+ __le32 num_of_link; -+ __le32 vdev_type; -+ __le32 vdev_subtype; -+ __le32 home_freq; -+} __packed; -+ -+#define WMI_DISALW_MLO_MODE_BMAP_IEEE_LINK_ID_COMB_1 GENMASK(7, 0) -+#define WMI_DISALW_MLO_MODE_BMAP_IEEE_LINK_ID_COMB_2 GENMASK(15, 8) -+#define WMI_DISALW_MLO_MODE_BMAP_IEEE_LINK_ID_COMB_3 GENMASK(23, 16) -+#define WMI_DISALW_MLO_MODE_BMAP_IEEE_LINK_ID_COMB_4 GENMASK(31, 24) -+ -+struct wmi_disallowed_mlo_mode_bitmap_params { -+ __le32 tlv_header; -+ __le32 disallowed_mode_bitmap; -+ __le32 ieee_link_id_comb; -+} __packed; -+ -+enum wmi_mlo_link_force_mode { -+ WMI_MLO_LINK_FORCE_MODE_ACTIVE = 1, -+ WMI_MLO_LINK_FORCE_MODE_INACTIVE = 2, -+ WMI_MLO_LINK_FORCE_MODE_ACTIVE_LINK_NUM = 3, -+ WMI_MLO_LINK_FORCE_MODE_INACTIVE_LINK_NUM = 4, -+ WMI_MLO_LINK_FORCE_MODE_NO_FORCE = 5, -+ WMI_MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE = 6, -+ WMI_MLO_LINK_FORCE_MODE_NON_FORCE_UPDATE = 7, -+}; -+ -+enum wmi_mlo_link_force_reason { -+ WMI_MLO_LINK_FORCE_REASON_NEW_CONNECT = 1, -+ WMI_MLO_LINK_FORCE_REASON_NEW_DISCONNECT = 2, -+ WMI_MLO_LINK_FORCE_REASON_LINK_REMOVAL = 3, -+ WMI_MLO_LINK_FORCE_REASON_TDLS = 4, -+ WMI_MLO_LINK_FORCE_REASON_REVERT_FAILURE = 5, -+ WMI_MLO_LINK_FORCE_REASON_LINK_DELETE = 6, -+ WMI_MLO_LINK_FORCE_REASON_SINGLE_LINK_EMLSR_OP = 7, -+}; -+ -+struct wmi_mlo_link_num_arg { -+ u32 num_of_link; -+ u32 vdev_type; -+ u32 vdev_subtype; -+ u32 home_freq; -+}; -+ -+struct wmi_mlo_control_flags_arg { -+ bool overwrite_force_active_bitmap; -+ bool overwrite_force_inactive_bitmap; -+ bool dync_force_link_num; -+ bool post_re_evaluate; -+ u8 post_re_evaluate_loops; -+ bool dont_reschedule_workqueue; -+}; -+ -+struct wmi_ml_link_force_cmd_arg { -+ u8 ap_mld_mac_addr[ETH_ALEN]; -+ u16 ieee_link_id_bitmap; -+ u16 ieee_link_id_bitmap2; -+ u8 link_num; -+}; -+ -+struct wmi_ml_disallow_mode_bmap_arg { -+ u32 disallowed_mode; -+ union { -+ u32 ieee_link_id_comb; -+ u8 ieee_link_id[4]; -+ }; -+}; -+ -+/* maximum size of link number param array -+ * for MLO link set active command -+ */ -+#define WMI_MLO_LINK_NUM_SZ 2 -+ -+/* maximum size of vdev bitmap array for -+ * MLO link set active command -+ */ -+#define WMI_MLO_VDEV_BITMAP_SZ 2 -+ -+/* Max number of disallowed bitmap combination -+ * sent to firmware -+ */ -+#define WMI_ML_MAX_DISALLOW_BMAP_COMB 4 -+ -+struct wmi_mlo_link_set_active_arg { -+ enum wmi_mlo_link_force_mode force_mode; -+ enum wmi_mlo_link_force_reason reason; -+ u32 num_link_entry; -+ u32 num_vdev_bitmap; -+ u32 num_inactive_vdev_bitmap; -+ struct wmi_mlo_link_num_arg link_num[WMI_MLO_LINK_NUM_SZ]; -+ u32 vdev_bitmap[WMI_MLO_VDEV_BITMAP_SZ]; -+ u32 inactive_vdev_bitmap[WMI_MLO_VDEV_BITMAP_SZ]; -+ struct wmi_mlo_control_flags_arg ctrl_flags; -+ bool use_ieee_link_id; -+ struct wmi_ml_link_force_cmd_arg force_cmd; -+ u32 num_disallow_mode_comb; -+ struct wmi_ml_disallow_mode_bmap_arg disallow_bmap[WMI_ML_MAX_DISALLOW_BMAP_COMB]; -+}; -+ - void ath12k_wmi_init_qcn9274(struct ath12k_base *ab, - struct ath12k_wmi_resource_config_arg *config); - void ath12k_wmi_init_wcn7850(struct ath12k_base *ab, -@@ -6004,7 +6195,7 @@ void ath12k_wmi_init_wcn7850(struct ath1 - int ath12k_wmi_cmd_send(struct ath12k_wmi_pdev *wmi, struct sk_buff *skb, - u32 cmd_id); - struct sk_buff *ath12k_wmi_alloc_skb(struct ath12k_wmi_base *wmi_sc, u32 len); --int ath12k_wmi_mgmt_send(struct ath12k *ar, u32 vdev_id, u32 buf_id, -+int ath12k_wmi_mgmt_send(struct ath12k_link_vif *arvif, u32 buf_id, - struct sk_buff *frame); - int ath12k_wmi_p2p_go_bcn_ie(struct ath12k *ar, u32 vdev_id, - const u8 *p2p_ie); -@@ -6195,5 +6386,6 @@ bool ath12k_wmi_supports_6ghz_cc_ext(str - int ath12k_wmi_send_vdev_set_tpc_power(struct ath12k *ar, - u32 vdev_id, - struct ath12k_reg_tpc_power_info *param); -- -+int ath12k_wmi_send_mlo_link_set_active_cmd(struct ath12k_base *ab, -+ struct wmi_mlo_link_set_active_arg *param); - #endif -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath6kl/bmi.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath6kl/bmi.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/ath6kl/bmi.c 2025-10-22 13:53:23.383328321 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/ath6kl/bmi.c 2025-10-22 13:53:56.607168698 -0400 -@@ -87,7 +87,9 @@ int ath6kl_bmi_get_target_info(struct at - * We need to do some backwards compatibility to make this work. - */ - if (le32_to_cpu(targ_info->byte_count) != sizeof(*targ_info)) { -- WARN_ON(1); -+ ath6kl_err("mismatched byte count %d vs. expected %zd\n", -+ le32_to_cpu(targ_info->byte_count), -+ sizeof(*targ_info)); - return -EINVAL; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/carl9170/usb.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/carl9170/usb.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/carl9170/usb.c 2025-10-22 13:53:23.383328321 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/carl9170/usb.c 2025-10-22 13:53:56.607168698 -0400 -@@ -438,14 +438,21 @@ static void carl9170_usb_rx_complete(str - - if (atomic_read(&ar->rx_anch_urbs) == 0) { - /* -- * The system is too slow to cope with -- * the enormous workload. We have simply -- * run out of active rx urbs and this -- * unfortunately leads to an unpredictable -- * device. -+ * At this point, either the system is too slow to -+ * cope with the enormous workload (so we have simply -+ * run out of active rx urbs and this unfortunately -+ * leads to an unpredictable device), or the device -+ * is not fully functional after an unsuccessful -+ * firmware loading attempts (so it doesn't pass -+ * ieee80211_register_hw() and there is no internal -+ * workqueue at all). - */ - -- ieee80211_queue_work(ar->hw, &ar->ping_work); -+ if (ar->registered) -+ ieee80211_queue_work(ar->hw, &ar->ping_work); -+ else -+ pr_warn_once("device %s is not registered\n", -+ dev_name(&ar->udev->dev)); - } - } else { - /* -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ath/wil6210/interrupt.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/wil6210/interrupt.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ath/wil6210/interrupt.c 2025-10-22 13:53:23.383328321 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ath/wil6210/interrupt.c 2025-10-22 13:53:56.607168698 -0400 -@@ -179,9 +179,11 @@ void wil_mask_irq(struct wil6210_priv *w - wil_dbg_irq(wil, "mask_irq\n"); - - wil6210_mask_irq_tx(wil); -- wil6210_mask_irq_tx_edma(wil); -+ if (wil->use_enhanced_dma_hw) -+ wil6210_mask_irq_tx_edma(wil); - wil6210_mask_irq_rx(wil); -- wil6210_mask_irq_rx_edma(wil); -+ if (wil->use_enhanced_dma_hw) -+ wil6210_mask_irq_rx_edma(wil); - wil6210_mask_irq_misc(wil, true); - wil6210_mask_irq_pseudo(wil); - } -@@ -190,10 +192,12 @@ void wil_unmask_irq(struct wil6210_priv - { - wil_dbg_irq(wil, "unmask_irq\n"); - -- wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, ICC), -- WIL_ICR_ICC_VALUE); -- wil_w(wil, RGF_DMA_EP_TX_ICR + offsetof(struct RGF_ICR, ICC), -- WIL_ICR_ICC_VALUE); -+ if (wil->use_enhanced_dma_hw) { -+ wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, ICC), -+ WIL_ICR_ICC_VALUE); -+ wil_w(wil, RGF_DMA_EP_TX_ICR + offsetof(struct RGF_ICR, ICC), -+ WIL_ICR_ICC_VALUE); -+ } - wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICC), - WIL_ICR_ICC_MISC_VALUE); - wil_w(wil, RGF_INT_GEN_TX_ICR + offsetof(struct RGF_ICR, ICC), -@@ -845,10 +849,12 @@ void wil6210_clear_irq(struct wil6210_pr - offsetof(struct RGF_ICR, ICR)); - wil_clear32(wil->csr + HOSTADDR(RGF_DMA_EP_TX_ICR) + - offsetof(struct RGF_ICR, ICR)); -- wil_clear32(wil->csr + HOSTADDR(RGF_INT_GEN_RX_ICR) + -- offsetof(struct RGF_ICR, ICR)); -- wil_clear32(wil->csr + HOSTADDR(RGF_INT_GEN_TX_ICR) + -- offsetof(struct RGF_ICR, ICR)); -+ if (wil->use_enhanced_dma_hw) { -+ wil_clear32(wil->csr + HOSTADDR(RGF_INT_GEN_RX_ICR) + -+ offsetof(struct RGF_ICR, ICR)); -+ wil_clear32(wil->csr + HOSTADDR(RGF_INT_GEN_TX_ICR) + -+ offsetof(struct RGF_ICR, ICR)); -+ } - wil_clear32(wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) + - offsetof(struct RGF_ICR, ICR)); - wmb(); /* make sure write completed */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c 2025-10-22 13:53:23.383328321 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c 2025-10-22 13:53:56.607168698 -0400 -@@ -393,10 +393,8 @@ void brcmf_btcoex_detach(struct brcmf_cf - if (!cfg->btcoex) - return; - -- if (cfg->btcoex->timer_on) { -- cfg->btcoex->timer_on = false; -- timer_shutdown_sync(&cfg->btcoex->timer); -- } -+ timer_shutdown_sync(&cfg->btcoex->timer); -+ cfg->btcoex->timer_on = false; - - cancel_work_sync(&cfg->btcoex->work); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c 2025-10-22 13:53:23.383328321 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c 2025-10-22 13:53:56.607168698 -0400 -@@ -1544,10 +1544,6 @@ brcmf_cfg80211_scan(struct wiphy *wiphy, - return -EAGAIN; - } - -- /* If scan req comes for p2p0, send it over primary I/F */ -- if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif) -- vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif; -- - brcmf_dbg(SCAN, "START ESCAN\n"); - - cfg->scan_request = request; -@@ -1563,6 +1559,10 @@ brcmf_cfg80211_scan(struct wiphy *wiphy, - if (err) - goto scan_out; - -+ /* If scan req comes for p2p0, send it over primary I/F */ -+ if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif) -+ vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif; -+ - err = brcmf_do_escan(vif->ifp, request); - if (err) - goto scan_out; -@@ -5527,8 +5527,7 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wip - struct brcmf_fil_action_frame_le *action_frame; - struct brcmf_fil_af_params_le *af_params; - bool ack; -- s32 chan_nr; -- u32 freq; -+ __le32 hw_ch; - - brcmf_dbg(TRACE, "Enter\n"); - -@@ -5589,25 +5588,34 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wip - /* Add the channel. Use the one specified as parameter if any or - * the current one (got from the firmware) otherwise - */ -- if (chan) -- freq = chan->center_freq; -- else -- brcmf_fil_cmd_int_get(vif->ifp, BRCMF_C_GET_CHANNEL, -- &freq); -- chan_nr = ieee80211_frequency_to_channel(freq); -- af_params->channel = cpu_to_le32(chan_nr); -+ if (chan) { -+ hw_ch = cpu_to_le32(chan->hw_value); -+ } else { -+ err = brcmf_fil_cmd_data_get(vif->ifp, -+ BRCMF_C_GET_CHANNEL, -+ &hw_ch, sizeof(hw_ch)); -+ if (err) { -+ bphy_err(drvr, -+ "unable to get current hw channel\n"); -+ goto free; -+ } -+ } -+ af_params->channel = hw_ch; -+ - af_params->dwell_time = cpu_to_le32(params->wait); - memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], - le16_to_cpu(action_frame->len)); - -- brcmf_dbg(TRACE, "Action frame, cookie=%lld, len=%d, freq=%d\n", -- *cookie, le16_to_cpu(action_frame->len), freq); -+ brcmf_dbg(TRACE, "Action frame, cookie=%lld, len=%d, channel=%d\n", -+ *cookie, le16_to_cpu(action_frame->len), -+ le32_to_cpu(af_params->channel)); - - ack = brcmf_p2p_send_action_frame(cfg, cfg_to_ndev(cfg), - af_params); - - cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack, - GFP_KERNEL); -+free: - kfree(af_params); - } else { - brcmf_dbg(TRACE, "Unhandled, fc=%04x!!\n", mgmt->frame_control); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/core.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/core.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/core.c 2025-10-22 13:53:23.383328321 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/core.c 2025-10-22 13:53:56.607168698 -0400 -@@ -112,8 +112,7 @@ int brcmf_cyw_mgmt_tx(struct wiphy *wiph - struct brcmf_cfg80211_vif *vif; - s32 err = 0; - bool ack = false; -- s32 chan_nr; -- u32 freq; -+ __le16 hw_ch; - struct brcmf_mf_params_le *mf_params; - u32 mf_params_len; - s32 ready; -@@ -143,13 +142,18 @@ int brcmf_cyw_mgmt_tx(struct wiphy *wiph - mf_params->len = cpu_to_le16(len - DOT11_MGMT_HDR_LEN); - mf_params->frame_control = mgmt->frame_control; - -- if (chan) -- freq = chan->center_freq; -- else -- brcmf_fil_cmd_int_get(vif->ifp, BRCMF_C_GET_CHANNEL, -- &freq); -- chan_nr = ieee80211_frequency_to_channel(freq); -- mf_params->channel = cpu_to_le16(chan_nr); -+ if (chan) { -+ hw_ch = cpu_to_le16(chan->hw_value); -+ } else { -+ err = brcmf_fil_cmd_data_get(vif->ifp, BRCMF_C_GET_CHANNEL, -+ &hw_ch, sizeof(hw_ch)); -+ if (err) { -+ bphy_err(drvr, "unable to get current hw channel\n"); -+ goto free; -+ } -+ } -+ mf_params->channel = hw_ch; -+ - memcpy(&mf_params->da[0], &mgmt->da[0], ETH_ALEN); - memcpy(&mf_params->bssid[0], &mgmt->bssid[0], ETH_ALEN); - mf_params->packet_id = cpu_to_le32(*cookie); -@@ -159,7 +163,8 @@ int brcmf_cyw_mgmt_tx(struct wiphy *wiph - brcmf_dbg(TRACE, "Auth frame, cookie=%d, fc=%04x, len=%d, channel=%d\n", - le32_to_cpu(mf_params->packet_id), - le16_to_cpu(mf_params->frame_control), -- le16_to_cpu(mf_params->len), chan_nr); -+ le16_to_cpu(mf_params->len), -+ le16_to_cpu(mf_params->channel)); - - vif->mgmt_tx_id = le32_to_cpu(mf_params->packet_id); - set_bit(BRCMF_MGMT_TX_SEND_FRAME, &vif->mgmt_tx_status); -@@ -185,6 +190,7 @@ int brcmf_cyw_mgmt_tx(struct wiphy *wiph - tx_status: - cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack, - GFP_KERNEL); -+free: - kfree(mf_params); - return err; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/fwil_types.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/fwil_types.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/fwil_types.h 2025-10-22 13:53:23.383328321 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/fwil_types.h 2025-10-22 13:53:56.607168698 -0400 -@@ -80,7 +80,7 @@ struct brcmf_mf_params_le { - u8 da[ETH_ALEN]; - u8 bssid[ETH_ALEN]; - __le32 packet_id; -- u8 data[] __counted_by(len); -+ u8 data[] __counted_by_le(len); - }; - - #endif /* CYW_FWIL_TYPES_H_ */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c 2025-10-22 13:53:23.383328321 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c 2025-10-22 13:53:56.607168698 -0400 -@@ -919,7 +919,7 @@ void wlc_lcnphy_read_table(struct brcms_ - - static void - wlc_lcnphy_common_read_table(struct brcms_phy *pi, u32 tbl_id, -- const u16 *tbl_ptr, u32 tbl_len, -+ u16 *tbl_ptr, u32 tbl_len, - u32 tbl_width, u32 tbl_offset) - { - struct phytbl_info tab; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlegacy/4965-mac.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlegacy/4965-mac.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlegacy/4965-mac.c 2025-10-22 13:53:23.387328302 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlegacy/4965-mac.c 2025-10-22 13:53:56.607168698 -0400 -@@ -1575,8 +1575,11 @@ il4965_tx_cmd_build_rate(struct il_priv - || rate_idx > RATE_COUNT_LEGACY) - rate_idx = rate_lowest_index(&il->bands[info->band], sta); - /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ -- if (info->band == NL80211_BAND_5GHZ) -+ if (info->band == NL80211_BAND_5GHZ) { - rate_idx += IL_FIRST_OFDM_RATE; -+ if (rate_idx > IL_LAST_OFDM_RATE) -+ rate_idx = IL_LAST_OFDM_RATE; -+ } - /* Get PLCP rate for tx_cmd->rate_n_flags */ - rate_plcp = il_rates[rate_idx].plcp; - /* Zero out flags for this packet */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlegacy/4965-rs.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlegacy/4965-rs.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlegacy/4965-rs.c 2025-10-22 13:53:23.387328302 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlegacy/4965-rs.c 2025-10-22 13:53:56.611168679 -0400 -@@ -203,7 +203,8 @@ il4965_rs_extract_rate(u32 rate_n_flags) - return (u8) (rate_n_flags & 0xFF); - } - --static void -+/* noinline works around https://github.com/llvm/llvm-project/issues/143908 */ -+static noinline_for_stack void - il4965_rs_rate_scale_clear_win(struct il_rate_scale_data *win) - { - win->data = 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/dvm/main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/dvm/main.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/dvm/main.c 2025-10-22 13:53:23.387328302 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/dvm/main.c 2025-10-22 13:53:56.611168679 -0400 -@@ -1049,9 +1049,11 @@ static void iwl_bg_restart(struct work_s - * - *****************************************************************************/ - --static void iwl_setup_deferred_work(struct iwl_priv *priv) -+static int iwl_setup_deferred_work(struct iwl_priv *priv) - { - priv->workqueue = alloc_ordered_workqueue(DRV_NAME, 0); -+ if (!priv->workqueue) -+ return -ENOMEM; - - INIT_WORK(&priv->restart, iwl_bg_restart); - INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); -@@ -1068,6 +1070,8 @@ static void iwl_setup_deferred_work(stru - timer_setup(&priv->statistics_periodic, iwl_bg_statistics_periodic, 0); - - timer_setup(&priv->ucode_trace, iwl_bg_ucode_trace, 0); -+ -+ return 0; - } - - void iwl_cancel_deferred_work(struct iwl_priv *priv) -@@ -1316,6 +1320,7 @@ static struct iwl_op_mode *iwl_op_mode_d - sizeof(trans->conf.no_reclaim_cmds)); - memcpy(trans->conf.no_reclaim_cmds, no_reclaim_cmds, - sizeof(no_reclaim_cmds)); -+ trans->conf.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds); - - switch (iwlwifi_mod_params.amsdu_size) { - case IWL_AMSDU_DEF: -@@ -1462,7 +1467,10 @@ static struct iwl_op_mode *iwl_op_mode_d - /******************** - * 6. Setup services - ********************/ -- iwl_setup_deferred_work(priv); -+ err = iwl_setup_deferred_work(priv); -+ if (err) -+ goto out_uninit_drv; -+ - iwl_setup_rx_handlers(priv); - - iwl_power_initialize(priv); -@@ -1501,6 +1509,7 @@ out_destroy_workqueue: - iwl_cancel_deferred_work(priv); - destroy_workqueue(priv->workqueue); - priv->workqueue = NULL; -+out_uninit_drv: - iwl_uninit_drv(priv); - out_free_eeprom_blob: - kfree(priv->eeprom_blob); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/dvm/rs.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/dvm/rs.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/dvm/rs.c 2025-10-22 13:53:23.387328302 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/dvm/rs.c 2025-10-22 13:53:56.611168679 -0400 -@@ -2899,7 +2899,7 @@ static void rs_fill_link_cmd(struct iwl_ - /* Repeat initial/next rate. - * For legacy IWL_NUMBER_TRY == 1, this loop will not execute. - * For HT IWL_HT_NUMBER_TRY == 3, this executes twice. */ -- while (repeat_rate > 0 && (index < LINK_QUAL_MAX_RETRY_NUM)) { -+ while (repeat_rate > 0 && index < (LINK_QUAL_MAX_RETRY_NUM - 1)) { - if (is_legacy(tbl_type.lq_type)) { - if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE) - ant_toggle_cnt++; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/fw/acpi.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/fw/acpi.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/fw/acpi.c 2025-10-22 13:53:23.387328302 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/fw/acpi.c 2025-10-22 13:53:56.611168679 -0400 -@@ -169,7 +169,7 @@ int iwl_acpi_get_dsm(struct iwl_fw_runti - - BUILD_BUG_ON(ARRAY_SIZE(acpi_dsm_size) != DSM_FUNC_NUM_FUNCS); - -- if (WARN_ON(func >= ARRAY_SIZE(acpi_dsm_size))) -+ if (WARN_ON(func >= ARRAY_SIZE(acpi_dsm_size) || !func)) - return -EINVAL; - - expected_size = acpi_dsm_size[func]; -@@ -178,6 +178,29 @@ int iwl_acpi_get_dsm(struct iwl_fw_runti - if (expected_size != sizeof(u8) && expected_size != sizeof(u32)) - return -EOPNOTSUPP; - -+ if (!fwrt->acpi_dsm_funcs_valid) { -+ ret = iwl_acpi_get_dsm_integer(fwrt->dev, ACPI_DSM_REV, -+ DSM_FUNC_QUERY, -+ &iwl_guid, &tmp, -+ acpi_dsm_size[DSM_FUNC_QUERY]); -+ if (ret) { -+ /* always indicate BIT(0) to avoid re-reading */ -+ fwrt->acpi_dsm_funcs_valid = BIT(0); -+ return ret; -+ } -+ -+ IWL_DEBUG_RADIO(fwrt, "ACPI DSM validity bitmap 0x%x\n", -+ (u32)tmp); -+ /* always indicate BIT(0) to avoid re-reading */ -+ fwrt->acpi_dsm_funcs_valid = tmp | BIT(0); -+ } -+ -+ if (!(fwrt->acpi_dsm_funcs_valid & BIT(func))) { -+ IWL_DEBUG_RADIO(fwrt, "ACPI DSM %d not indicated as valid\n", -+ func); -+ return -ENODATA; -+ } -+ - ret = iwl_acpi_get_dsm_integer(fwrt->dev, ACPI_DSM_REV, func, - &iwl_guid, &tmp, expected_size); - if (ret) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h 2025-10-22 13:53:23.387328302 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h 2025-10-22 13:53:56.611168679 -0400 -@@ -1,6 +1,6 @@ - /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ - /* -- * Copyright (C) 2012-2014, 2018-2024 Intel Corporation -+ * Copyright (C) 2012-2014, 2018-2025 Intel Corporation - * Copyright (C) 2013-2015 Intel Mobile Communications GmbH - * Copyright (C) 2016-2017 Intel Deutschland GmbH - */ -@@ -754,7 +754,7 @@ struct iwl_lari_config_change_cmd_v10 { - * according to the BIOS definitions. - * For LARI cmd version 11 - bits 0:4 are supported. - * For LARI cmd version 12 - bits 0:6 are supported and bits 7:31 are -- * reserved. No need to mask out the reserved bits. -+ * reserved. - * @force_disable_channels_bitmap: Bitmap of disabled bands/channels. - * Each bit represents a set of channels in a specific band that should be - * disabled -@@ -787,6 +787,7 @@ struct iwl_lari_config_change_cmd { - /* Activate UNII-1 (5.2GHz) for World Wide */ - #define ACTIVATE_5G2_IN_WW_MASK BIT(4) - #define CHAN_STATE_ACTIVE_BITMAP_CMD_V11 0x1F -+#define CHAN_STATE_ACTIVE_BITMAP_CMD_V12 0x7F - - /** - * struct iwl_pnvm_init_complete_ntfy - PNVM initialization complete -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/fw/dbg.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/fw/dbg.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/fw/dbg.c 2025-10-22 13:53:23.387328302 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/fw/dbg.c 2025-10-22 13:53:56.611168679 -0400 -@@ -3008,6 +3008,7 @@ int iwl_fw_dbg_collect(struct iwl_fw_run - struct iwl_fw_dump_desc *desc; - unsigned int delay = 0; - bool monitor_only = false; -+ int ret; - - if (trigger) { - u16 occurrences = le16_to_cpu(trigger->occurrences) - 1; -@@ -3038,7 +3039,11 @@ int iwl_fw_dbg_collect(struct iwl_fw_run - desc->trig_desc.type = cpu_to_le32(trig); - memcpy(desc->trig_desc.data, str, len); - -- return iwl_fw_dbg_collect_desc(fwrt, desc, monitor_only, delay); -+ ret = iwl_fw_dbg_collect_desc(fwrt, desc, monitor_only, delay); -+ if (ret) -+ kfree(desc); -+ -+ return ret; - } - IWL_EXPORT_SYMBOL(iwl_fw_dbg_collect); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c 2025-10-22 13:53:23.387328302 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c 2025-10-22 13:53:56.611168679 -0400 -@@ -614,6 +614,7 @@ int iwl_fill_lari_config(struct iwl_fw_r - - ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ACTIVATE_CHANNEL, &value); - if (!ret) { -+ value &= CHAN_STATE_ACTIVE_BITMAP_CMD_V12; - if (cmd_ver < 8) - value &= ~ACTIVATE_5G2_IN_WW_MASK; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/fw/runtime.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/fw/runtime.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/fw/runtime.h 2025-10-22 13:53:23.387328302 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/fw/runtime.h 2025-10-22 13:53:56.611168679 -0400 -@@ -113,6 +113,10 @@ struct iwl_txf_iter_data { - * @phy_filters: specific phy filters as read from WPFC BIOS table - * @ppag_bios_rev: PPAG BIOS revision - * @ppag_bios_source: see &enum bios_source -+ * @acpi_dsm_funcs_valid: bitmap indicating which DSM values are valid, -+ * zero (default initialization) means it hasn't been read yet, -+ * and BIT(0) is set when it has since function 0 also has this -+ * bitmap and is always supported - */ - struct iwl_fw_runtime { - struct iwl_trans *trans; -@@ -189,6 +193,10 @@ struct iwl_fw_runtime { - bool uats_valid; - u8 uefi_tables_lock_status; - struct iwl_phy_specific_cfg phy_filters; -+ -+#ifdef CONFIG_ACPI -+ u32 acpi_dsm_funcs_valid; -+#endif - }; - - void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/fw/uefi.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/fw/uefi.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/fw/uefi.c 2025-10-22 13:53:23.387328302 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/fw/uefi.c 2025-10-22 13:53:56.611168679 -0400 -@@ -747,6 +747,12 @@ int iwl_uefi_get_dsm(struct iwl_fw_runti - goto out; - } - -+ if (!(data->functions[DSM_FUNC_QUERY] & BIT(func))) { -+ IWL_DEBUG_RADIO(fwrt, "DSM func %d not in 0x%x\n", -+ func, data->functions[DSM_FUNC_QUERY]); -+ goto out; -+ } -+ - *value = data->functions[func]; - - IWL_DEBUG_RADIO(fwrt, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/iwl-drv.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/iwl-drv.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/iwl-drv.c 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/iwl-drv.c 2025-10-22 13:53:56.611168679 -0400 -@@ -298,13 +298,17 @@ static void iwl_get_ucode_api_versions(s - const struct iwl_family_base_params *base = trans->mac_cfg->base; - const struct iwl_rf_cfg *cfg = trans->cfg; - -- if (!base->ucode_api_max) { -+ /* if the MAC doesn't have range or if its range it higher than the RF's */ -+ if (!base->ucode_api_max || -+ (cfg->ucode_api_max && base->ucode_api_min > cfg->ucode_api_max)) { - *api_min = cfg->ucode_api_min; - *api_max = cfg->ucode_api_max; - return; - } - -- if (!cfg->ucode_api_max) { -+ /* if the RF doesn't have range or if its range it higher than the MAC's */ -+ if (!cfg->ucode_api_max || -+ (base->ucode_api_max && cfg->ucode_api_min > base->ucode_api_max)) { - *api_min = base->ucode_api_min; - *api_max = base->ucode_api_max; - return; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mld/agg.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mld/agg.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mld/agg.c 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mld/agg.c 2025-10-22 13:53:56.611168679 -0400 -@@ -305,10 +305,15 @@ iwl_mld_reorder(struct iwl_mld *mld, str - * already ahead and it will be dropped. - * If the last sub-frame is not on this queue - we will get frame - * release notification with up to date NSSN. -+ * If this is the first frame that is stored in the buffer, the head_sn -+ * may be outdated. Update it based on the last NSSN to make sure it -+ * will be released when the frame release notification arrives. - */ - if (!amsdu || last_subframe) - iwl_mld_reorder_release_frames(mld, sta, napi, baid_data, - buffer, nssn); -+ else if (buffer->num_stored == 1) -+ buffer->head_sn = nssn; - - return IWL_MLD_BUFFERED_SKB; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mld/iface.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mld/iface.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mld/iface.h 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mld/iface.h 2025-10-22 13:53:56.611168679 -0400 -@@ -87,6 +87,8 @@ enum iwl_mld_emlsr_exit { - * @last_exit_reason: Reason for the last EMLSR exit - * @last_exit_ts: Time of the last EMLSR exit (if @last_exit_reason is non-zero) - * @exit_repeat_count: Number of times EMLSR was exited for the same reason -+ * @last_entry_ts: the time of the last EMLSR entry (if iwl_mld_emlsr_active() -+ * is true) - * @unblock_tpt_wk: Unblock EMLSR because the throughput limit was reached - * @check_tpt_wk: a worker to check if IWL_MLD_EMLSR_BLOCKED_TPT should be - * added, for example if there is no longer enough traffic. -@@ -105,6 +107,7 @@ struct iwl_mld_emlsr { - enum iwl_mld_emlsr_exit last_exit_reason; - unsigned long last_exit_ts; - u8 exit_repeat_count; -+ unsigned long last_entry_ts; - ); - - struct wiphy_work unblock_tpt_wk; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mld/link.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mld/link.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mld/link.c 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mld/link.c 2025-10-22 13:53:56.611168679 -0400 -@@ -864,21 +864,23 @@ void iwl_mld_handle_missed_beacon_notif( - { - const struct iwl_missed_beacons_notif *notif = (const void *)pkt->data; - union iwl_dbg_tlv_tp_data tp_data = { .fw_pkt = pkt }; -- u32 link_id = le32_to_cpu(notif->link_id); -+ u32 fw_link_id = le32_to_cpu(notif->link_id); - u32 missed_bcon = le32_to_cpu(notif->consec_missed_beacons); - u32 missed_bcon_since_rx = - le32_to_cpu(notif->consec_missed_beacons_since_last_rx); - u32 scnd_lnk_bcn_lost = - le32_to_cpu(notif->consec_missed_beacons_other_link); - struct ieee80211_bss_conf *link_conf = -- iwl_mld_fw_id_to_link_conf(mld, link_id); -+ iwl_mld_fw_id_to_link_conf(mld, fw_link_id); - u32 bss_param_ch_cnt_link_id; - struct ieee80211_vif *vif; -+ u8 link_id; - - if (WARN_ON(!link_conf)) - return; - - vif = link_conf->vif; -+ link_id = link_conf->link_id; - bss_param_ch_cnt_link_id = link_conf->bss_param_ch_cnt_link_id; - - IWL_DEBUG_INFO(mld, -@@ -890,7 +892,7 @@ void iwl_mld_handle_missed_beacon_notif( - - mld->trans->dbg.dump_file_name_ext_valid = true; - snprintf(mld->trans->dbg.dump_file_name_ext, IWL_FW_INI_MAX_NAME, -- "LinkId_%d_MacType_%d", link_id, -+ "LinkId_%d_MacType_%d", fw_link_id, - iwl_mld_mac80211_iftype_to_fw(vif)); - - iwl_dbg_tlv_time_point(&mld->fwrt, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mld/mac80211.c 2025-10-22 13:53:56.611168679 -0400 -@@ -1002,6 +1002,7 @@ int iwl_mld_assign_vif_chanctx(struct ie - - /* Indicate to mac80211 that EML is enabled */ - vif->driver_flags |= IEEE80211_VIF_EML_ACTIVE; -+ mld_vif->emlsr.last_entry_ts = jiffies; - - if (vif->active_links & BIT(mld_vif->emlsr.selected_links)) - mld_vif->emlsr.primary = mld_vif->emlsr.selected_primary; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mld/mld.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mld/mld.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mld/mld.c 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mld/mld.c 2025-10-22 13:53:56.611168679 -0400 -@@ -77,6 +77,7 @@ void iwl_construct_mld(struct iwl_mld *m - - /* Setup async RX handling */ - spin_lock_init(&mld->async_handlers_lock); -+ INIT_LIST_HEAD(&mld->async_handlers_list); - wiphy_work_init(&mld->async_handlers_wk, - iwl_mld_async_handlers_wk); - -@@ -356,7 +357,7 @@ iwl_mld_configure_trans(struct iwl_op_mo - trans->conf.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds); - - trans->conf.rx_mpdu_cmd = REPLY_RX_MPDU_CMD; -- trans->conf.rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start); -+ trans->conf.rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_desc); - trans->conf.wide_cmd_header = true; - - iwl_trans_op_mode_enter(trans, op_mode); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mld/mlo.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mld/mlo.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mld/mlo.c 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mld/mlo.c 2025-10-22 13:53:56.611168679 -0400 -@@ -530,10 +530,12 @@ void iwl_mld_emlsr_check_tpt(struct wiph - /* - * TPT is unblocked, need to check if the TPT criteria is still met. - * -- * If EMLSR is active, then we also need to check the secondar link -- * requirements. -+ * If EMLSR is active for at least 5 seconds, then we also -+ * need to check the secondary link requirements. - */ -- if (iwl_mld_emlsr_active(vif)) { -+ if (iwl_mld_emlsr_active(vif) && -+ time_is_before_jiffies(mld_vif->emlsr.last_entry_ts + -+ IWL_MLD_TPT_COUNT_WINDOW)) { - sec_link_id = iwl_mld_get_other_link(vif, iwl_mld_get_primary_link(vif)); - sec_link = iwl_mld_link_dereference_check(mld_vif, sec_link_id); - if (WARN_ON_ONCE(!sec_link)) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mld/regulatory.c 2025-10-22 13:53:56.611168679 -0400 -@@ -251,8 +251,10 @@ void iwl_mld_configure_lari(struct iwl_m - cpu_to_le32(value &= DSM_UNII4_ALLOW_BITMAP); - - ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ACTIVATE_CHANNEL, &value); -- if (!ret) -+ if (!ret) { -+ value &= CHAN_STATE_ACTIVE_BITMAP_CMD_V12; - cmd.chan_state_active_bitmap = cpu_to_le32(value); -+ } - - ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_6E, &value); - if (!ret) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mld/rx.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mld/rx.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mld/rx.c 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mld/rx.c 2025-10-22 13:53:56.611168679 -0400 -@@ -1039,6 +1039,15 @@ static void iwl_mld_rx_eht(struct iwl_ml - rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT; - } - -+ /* update aggregation data for monitor sake on default queue */ -+ if (!queue && (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD) && -+ (phy_info & IWL_RX_MPDU_PHY_AMPDU) && phy_data->first_subframe) { -+ rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT_KNOWN; -+ if (phy_data->data0 & -+ cpu_to_le32(IWL_RX_PHY_DATA0_EHT_DELIM_EOF)) -+ rx_status->flag |= RX_FLAG_AMPDU_EOF_BIT; -+ } -+ - if (phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD) - iwl_mld_decode_eht_phy_data(mld, phy_data, rx_status, eht, usig); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mld/scan.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mld/scan.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mld/scan.c 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mld/scan.c 2025-10-22 13:53:56.611168679 -0400 -@@ -359,7 +359,7 @@ iwl_mld_scan_fits(struct iwl_mld *mld, i - struct ieee80211_scan_ies *ies, int n_channels) - { - return ((n_ssids <= PROBE_OPTION_MAX) && -- (n_channels <= mld->fw->ucode_capa.n_scan_channels) & -+ (n_channels <= mld->fw->ucode_capa.n_scan_channels) && - (ies->common_ie_len + ies->len[NL80211_BAND_2GHZ] + - ies->len[NL80211_BAND_5GHZ] + ies->len[NL80211_BAND_6GHZ] <= - iwl_mld_scan_max_template_size())); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mld/scan.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mld/scan.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mld/scan.h 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mld/scan.h 2025-10-22 13:53:56.611168679 -0400 -@@ -130,7 +130,7 @@ struct iwl_mld_scan { - void *cmd; - unsigned long last_6ghz_passive_jiffies; - unsigned long last_start_time_jiffies; -- unsigned long last_mlo_scan_time; -+ u64 last_mlo_scan_time; - }; - - #endif /* __iwl_mld_scan_h__ */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mvm/d3.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mvm/d3.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mvm/d3.c 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mvm/d3.c 2025-10-22 13:53:56.611168679 -0400 -@@ -2385,6 +2385,7 @@ static void iwl_mvm_convert_gtk_v2(struc - - status->gtk[0].len = data->key_len; - status->gtk[0].flags = data->key_flags; -+ status->gtk[0].id = status->gtk[0].flags & IWL_WOWLAN_GTK_IDX_MASK; - - memcpy(status->gtk[0].key, data->key, sizeof(data->key)); - -@@ -2735,6 +2736,7 @@ iwl_mvm_send_wowlan_get_status(struct iw - * currently used key. - */ - status->gtk[0].flags = v6->gtk.key_index | BIT(7); -+ status->gtk[0].id = v6->gtk.key_index; - } else if (notif_ver == 7) { - struct iwl_wowlan_status_v7 *v7 = (void *)cmd.resp_pkt->data; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c 2025-10-22 13:53:56.611168679 -0400 -@@ -32,9 +32,9 @@ static void iwl_mvm_mld_mac_ctxt_cmd_com - unsigned int link_id; - int cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, - WIDE_ID(MAC_CONF_GROUP, -- MAC_CONFIG_CMD), 0); -+ MAC_CONFIG_CMD), 1); - -- if (WARN_ON(cmd_ver < 1 && cmd_ver > 3)) -+ if (WARN_ON(cmd_ver > 3)) - return; - - cmd->id_and_color = cpu_to_le32(mvmvif->id); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mvm/ops.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mvm/ops.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mvm/ops.c 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mvm/ops.c 2025-10-22 13:53:56.611168679 -0400 -@@ -61,8 +61,10 @@ static int __init iwl_mvm_init(void) - } - - ret = iwl_opmode_register("iwlmvm", &iwl_mvm_ops); -- if (ret) -+ if (ret) { - pr_err("Unable to register MVM op_mode: %d\n", ret); -+ iwl_mvm_rate_control_unregister(); -+ } - - return ret; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c 2025-10-22 13:53:56.611168679 -0400 -@@ -854,10 +854,15 @@ static bool iwl_mvm_reorder(struct iwl_m - * already ahead and it will be dropped. - * If the last sub-frame is not on this queue - we will get frame - * release notification with up to date NSSN. -+ * If this is the first frame that is stored in the buffer, the head_sn -+ * may be outdated. Update it based on the last NSSN to make sure it -+ * will be released when the frame release notification arrives. - */ - if (!amsdu || last_subframe) - iwl_mvm_release_frames(mvm, sta, napi, baid_data, - buffer, nssn); -+ else if (buffer->num_stored == 1) -+ buffer->head_sn = nssn; - - spin_unlock_bh(&buffer->lock); - return true; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mvm/scan.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mvm/scan.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/mvm/scan.c 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/mvm/scan.c 2025-10-22 13:53:56.615168659 -0400 -@@ -835,7 +835,7 @@ static inline bool iwl_mvm_scan_fits(str - int n_channels) - { - return ((n_ssids <= PROBE_OPTION_MAX) && -- (n_channels <= mvm->fw->ucode_capa.n_scan_channels) & -+ (n_channels <= mvm->fw->ucode_capa.n_scan_channels) && - (ies->common_ie_len + - ies->len[NL80211_BAND_2GHZ] + ies->len[NL80211_BAND_5GHZ] + - ies->len[NL80211_BAND_6GHZ] <= -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c 2025-10-22 13:53:56.615168659 -0400 -@@ -166,7 +166,7 @@ int iwl_pcie_ctxt_info_init(struct iwl_t - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_context_info *ctxt_info; - struct iwl_context_info_rbd_cfg *rx_cfg; -- u32 control_flags = 0, rb_size; -+ u32 control_flags = 0, rb_size, cb_size; - dma_addr_t phys; - int ret; - -@@ -202,11 +202,12 @@ int iwl_pcie_ctxt_info_init(struct iwl_t - rb_size = IWL_CTXT_INFO_RB_SIZE_4K; - } - -- WARN_ON(RX_QUEUE_CB_SIZE(iwl_trans_get_num_rbds(trans)) > 12); -+ cb_size = RX_QUEUE_CB_SIZE(iwl_trans_get_num_rbds(trans)); -+ if (WARN_ON(cb_size > 12)) -+ cb_size = 12; -+ - control_flags = IWL_CTXT_INFO_TFD_FORMAT_LONG; -- control_flags |= -- u32_encode_bits(RX_QUEUE_CB_SIZE(iwl_trans_get_num_rbds(trans)), -- IWL_CTXT_INFO_RB_CB_SIZE); -+ control_flags |= u32_encode_bits(cb_size, IWL_CTXT_INFO_RB_CB_SIZE); - control_flags |= u32_encode_bits(rb_size, IWL_CTXT_INFO_RB_SIZE); - ctxt_info->control.control_flags = cpu_to_le32(control_flags); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/pcie/drv.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/pcie/drv.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/pcie/drv.c 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/pcie/drv.c 2025-10-22 13:53:56.615168659 -0400 -@@ -124,13 +124,13 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct pc - {IWL_PCI_DEVICE(0x0082, 0x1304, iwl6005_mac_cfg)},/* low 5GHz active */ - {IWL_PCI_DEVICE(0x0082, 0x1305, iwl6005_mac_cfg)},/* high 5GHz active */ - --/* 6x30 Series */ -- {IWL_PCI_DEVICE(0x008A, 0x5305, iwl1000_mac_cfg)}, -- {IWL_PCI_DEVICE(0x008A, 0x5307, iwl1000_mac_cfg)}, -- {IWL_PCI_DEVICE(0x008A, 0x5325, iwl1000_mac_cfg)}, -- {IWL_PCI_DEVICE(0x008A, 0x5327, iwl1000_mac_cfg)}, -- {IWL_PCI_DEVICE(0x008B, 0x5315, iwl1000_mac_cfg)}, -- {IWL_PCI_DEVICE(0x008B, 0x5317, iwl1000_mac_cfg)}, -+/* 1030/6x30 Series */ -+ {IWL_PCI_DEVICE(0x008A, 0x5305, iwl6030_mac_cfg)}, -+ {IWL_PCI_DEVICE(0x008A, 0x5307, iwl6030_mac_cfg)}, -+ {IWL_PCI_DEVICE(0x008A, 0x5325, iwl6030_mac_cfg)}, -+ {IWL_PCI_DEVICE(0x008A, 0x5327, iwl6030_mac_cfg)}, -+ {IWL_PCI_DEVICE(0x008B, 0x5315, iwl6030_mac_cfg)}, -+ {IWL_PCI_DEVICE(0x008B, 0x5317, iwl6030_mac_cfg)}, - {IWL_PCI_DEVICE(0x0090, 0x5211, iwl6030_mac_cfg)}, - {IWL_PCI_DEVICE(0x0090, 0x5215, iwl6030_mac_cfg)}, - {IWL_PCI_DEVICE(0x0090, 0x5216, iwl6030_mac_cfg)}, -@@ -181,12 +181,12 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct pc - {IWL_PCI_DEVICE(0x08AE, 0x1027, iwl1000_mac_cfg)}, - - /* 130 Series WiFi */ -- {IWL_PCI_DEVICE(0x0896, 0x5005, iwl1000_mac_cfg)}, -- {IWL_PCI_DEVICE(0x0896, 0x5007, iwl1000_mac_cfg)}, -- {IWL_PCI_DEVICE(0x0897, 0x5015, iwl1000_mac_cfg)}, -- {IWL_PCI_DEVICE(0x0897, 0x5017, iwl1000_mac_cfg)}, -- {IWL_PCI_DEVICE(0x0896, 0x5025, iwl1000_mac_cfg)}, -- {IWL_PCI_DEVICE(0x0896, 0x5027, iwl1000_mac_cfg)}, -+ {IWL_PCI_DEVICE(0x0896, 0x5005, iwl6030_mac_cfg)}, -+ {IWL_PCI_DEVICE(0x0896, 0x5007, iwl6030_mac_cfg)}, -+ {IWL_PCI_DEVICE(0x0897, 0x5015, iwl6030_mac_cfg)}, -+ {IWL_PCI_DEVICE(0x0897, 0x5017, iwl6030_mac_cfg)}, -+ {IWL_PCI_DEVICE(0x0896, 0x5025, iwl6030_mac_cfg)}, -+ {IWL_PCI_DEVICE(0x0896, 0x5027, iwl6030_mac_cfg)}, - - /* 2x00 Series */ - {IWL_PCI_DEVICE(0x0890, 0x4022, iwl2000_mac_cfg)}, -@@ -670,6 +670,8 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct iw - - IWL_DEV_INFO(iwl6005_n_cfg, iwl6005_2agn_sff_name, - DEVICE(0x0082), SUBDEV_MASKED(0xC000, 0xF000)), -+ IWL_DEV_INFO(iwl6005_n_cfg, iwl6005_2agn_sff_name, -+ DEVICE(0x0085), SUBDEV_MASKED(0xC000, 0xF000)), - IWL_DEV_INFO(iwl6005_n_cfg, iwl6005_2agn_d_name, - DEVICE(0x0082), SUBDEV(0x4820)), - IWL_DEV_INFO(iwl6005_n_cfg, iwl6005_2agn_mow1_name, -@@ -726,10 +728,10 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct iw - DEVICE(0x0083), SUBDEV_MASKED(0x5, 0xF)), - IWL_DEV_INFO(iwl1000_bg_cfg, iwl1000_bg_name, - DEVICE(0x0083), SUBDEV_MASKED(0x6, 0xF)), -+ IWL_DEV_INFO(iwl1000_bgn_cfg, iwl1000_bgn_name, -+ DEVICE(0x0084), SUBDEV_MASKED(0x5, 0xF)), - IWL_DEV_INFO(iwl1000_bg_cfg, iwl1000_bg_name, -- DEVICE(0x0084), SUBDEV(0x1216)), -- IWL_DEV_INFO(iwl1000_bg_cfg, iwl1000_bg_name, -- DEVICE(0x0084), SUBDEV(0x1316)), -+ DEVICE(0x0084), SUBDEV_MASKED(0x6, 0xF)), - - /* 100 Series WiFi */ - IWL_DEV_INFO(iwl100_bgn_cfg, iwl100_bgn_name, -@@ -961,6 +963,12 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct iw - DEVICE(0x24F3), SUBDEV(0x0004)), - IWL_DEV_INFO(iwl8260_cfg, iwl8260_2n_name, - DEVICE(0x24F3), SUBDEV(0x0044)), -+ IWL_DEV_INFO(iwl8260_cfg, iwl8260_2ac_name, -+ DEVICE(0x24F4)), -+ IWL_DEV_INFO(iwl8260_cfg, iwl4165_2ac_name, -+ DEVICE(0x24F5)), -+ IWL_DEV_INFO(iwl8260_cfg, iwl4165_2ac_name, -+ DEVICE(0x24F6)), - IWL_DEV_INFO(iwl8265_cfg, iwl8265_2ac_name, - DEVICE(0x24FD)), - IWL_DEV_INFO(iwl8265_cfg, iwl8275_2ac_name, -@@ -1501,11 +1509,31 @@ static int _iwl_pci_resume(struct device - * Scratch value was altered, this means the device was powered off, we - * need to reset it completely. - * Note: MAC (bits 0:7) will be cleared upon suspend even with wowlan, -- * so assume that any bits there mean that the device is usable. -+ * but not bits [15:8]. So if we have bits set in lower word, assume -+ * the device is alive. -+ * Alternatively, if the scratch value is 0xFFFFFFFF, then we no longer -+ * have access to the device and consider it powered off. -+ * For older devices, just try silently to grab the NIC. - */ -- if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ && -- !iwl_read32(trans, CSR_FUNC_SCRATCH)) -- device_was_powered_off = true; -+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { -+ u32 scratch = iwl_read32(trans, CSR_FUNC_SCRATCH); -+ -+ if (!(scratch & CSR_FUNC_SCRATCH_POWER_OFF_MASK) || -+ scratch == ~0U) -+ device_was_powered_off = true; -+ } else { -+ /* -+ * bh are re-enabled by iwl_trans_pcie_release_nic_access, -+ * so re-enable them if _iwl_trans_pcie_grab_nic_access fails. -+ */ -+ local_bh_disable(); -+ if (_iwl_trans_pcie_grab_nic_access(trans, true)) { -+ iwl_trans_pcie_release_nic_access(trans); -+ } else { -+ device_was_powered_off = true; -+ local_bh_enable(); -+ } -+ } - - if (restore || device_was_powered_off) { - trans->state = IWL_TRANS_NO_FW; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/pcie/internal.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/pcie/internal.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/pcie/internal.h 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/pcie/internal.h 2025-10-22 13:53:56.615168659 -0400 -@@ -1074,6 +1074,7 @@ void iwl_pcie_rx_allocator_work(struct w - - /* common trans ops for all generations transports */ - void iwl_trans_pcie_op_mode_enter(struct iwl_trans *trans); -+int _iwl_trans_pcie_start_hw(struct iwl_trans *trans); - int iwl_trans_pcie_start_hw(struct iwl_trans *trans); - void iwl_trans_pcie_op_mode_leave(struct iwl_trans *trans); - void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/pcie/trans.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/pcie/trans.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/pcie/trans.c 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/pcie/trans.c 2025-10-22 13:53:56.615168659 -0400 -@@ -1845,7 +1845,7 @@ static int iwl_pcie_gen2_force_power_gat - return iwl_trans_pcie_sw_reset(trans, true); - } - --static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans) -+int _iwl_trans_pcie_start_hw(struct iwl_trans *trans) - { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - int err; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c 2025-10-22 13:53:56.615168659 -0400 -@@ -546,8 +546,10 @@ again: - } - - if (WARN_ON(trans->do_top_reset && -- trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_SC)) -- return -EINVAL; -+ trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_SC)) { -+ ret = -EINVAL; -+ goto out; -+ } - - /* we need to wait later - set state */ - if (trans->do_top_reset) -@@ -610,6 +612,11 @@ again: - msleep(10); - IWL_INFO(trans, "TOP reset successful, reinit now\n"); - /* now load the firmware again properly */ -+ ret = _iwl_trans_pcie_start_hw(trans); -+ if (ret) { -+ IWL_ERR(trans, "failed to start HW after TOP reset\n"); -+ goto out; -+ } - trans_pcie->prph_scratch->ctrl_cfg.control.control_flags &= - ~cpu_to_le32(IWL_PRPH_SCRATCH_TOP_RESET); - top_reset_done = true; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/pcie/tx.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/pcie/tx.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/intel/iwlwifi/pcie/tx.c 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/intel/iwlwifi/pcie/tx.c 2025-10-22 13:53:56.615168659 -0400 -@@ -2093,7 +2093,8 @@ static void iwl_txq_gen1_update_byte_cnt - break; - } - -- if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) -+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_7000 && -+ trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) - len = DIV_ROUND_UP(len, 4); - - if (WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX)) -@@ -2101,10 +2102,10 @@ static void iwl_txq_gen1_update_byte_cnt - - bc_ent = cpu_to_le16(len | (sta_id << 12)); - -- scd_bc_tbl[txq_id * BC_TABLE_SIZE + write_ptr].tfd_offset = bc_ent; -+ scd_bc_tbl[txq_id * TFD_QUEUE_BC_SIZE + write_ptr].tfd_offset = bc_ent; - - if (write_ptr < TFD_QUEUE_SIZE_BC_DUP) -- scd_bc_tbl[txq_id * BC_TABLE_SIZE + TFD_QUEUE_SIZE_MAX + write_ptr].tfd_offset = -+ scd_bc_tbl[txq_id * TFD_QUEUE_BC_SIZE + TFD_QUEUE_SIZE_MAX + write_ptr].tfd_offset = - bc_ent; - } - -@@ -2328,10 +2329,10 @@ static void iwl_txq_gen1_inval_byte_cnt_ - - bc_ent = cpu_to_le16(1 | (sta_id << 12)); - -- scd_bc_tbl[txq_id * BC_TABLE_SIZE + read_ptr].tfd_offset = bc_ent; -+ scd_bc_tbl[txq_id * TFD_QUEUE_BC_SIZE + read_ptr].tfd_offset = bc_ent; - - if (read_ptr < TFD_QUEUE_SIZE_BC_DUP) -- scd_bc_tbl[txq_id * BC_TABLE_SIZE + TFD_QUEUE_SIZE_MAX + read_ptr].tfd_offset = -+ scd_bc_tbl[txq_id * TFD_QUEUE_BC_SIZE + TFD_QUEUE_SIZE_MAX + read_ptr].tfd_offset = - bc_ent; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/marvell/libertas/cfg.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/marvell/libertas/cfg.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/marvell/libertas/cfg.c 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/marvell/libertas/cfg.c 2025-10-22 13:53:56.615168659 -0400 -@@ -1151,10 +1151,13 @@ static int lbs_associate(struct lbs_priv - /* add SSID TLV */ - rcu_read_lock(); - ssid_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SSID); -- if (ssid_eid) -- pos += lbs_add_ssid_tlv(pos, ssid_eid + 2, ssid_eid[1]); -- else -+ if (ssid_eid) { -+ u32 ssid_len = min(ssid_eid[1], IEEE80211_MAX_SSID_LEN); -+ -+ pos += lbs_add_ssid_tlv(pos, ssid_eid + 2, ssid_len); -+ } else { - lbs_deb_assoc("no SSID\n"); -+ } - rcu_read_unlock(); - - /* add DS param TLV */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/marvell/mwifiex/11n.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/marvell/mwifiex/11n.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/marvell/mwifiex/11n.c 2025-10-22 13:53:23.391328283 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/marvell/mwifiex/11n.c 2025-10-22 13:53:56.615168659 -0400 -@@ -403,14 +403,12 @@ mwifiex_cmd_append_11n_tlv(struct mwifie - - if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && - bss_desc->bcn_ht_oper->ht_param & -- IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) { -- chan_list->chan_scan_param[0].radio_type |= -- CHAN_BW_40MHZ << 2; -+ IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) - SET_SECONDARYCHAN(chan_list->chan_scan_param[0]. - radio_type, - (bss_desc->bcn_ht_oper->ht_param & - IEEE80211_HT_PARAM_CHA_SEC_OFFSET)); -- } -+ - *buffer += struct_size(chan_list, chan_scan_param, 1); - ret_len += struct_size(chan_list, chan_scan_param, 1); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/marvell/mwifiex/cfg80211.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/marvell/mwifiex/cfg80211.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/marvell/mwifiex/cfg80211.c 2025-10-22 13:53:23.395328263 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/marvell/mwifiex/cfg80211.c 2025-10-22 13:53:56.615168659 -0400 -@@ -4668,8 +4668,9 @@ int mwifiex_init_channel_scan_gap(struct - * additional active scan request for hidden SSIDs on passive channels. - */ - adapter->num_in_chan_stats = 2 * (n_channels_bg + n_channels_a); -- adapter->chan_stats = vmalloc(array_size(sizeof(*adapter->chan_stats), -- adapter->num_in_chan_stats)); -+ adapter->chan_stats = kcalloc(adapter->num_in_chan_stats, -+ sizeof(*adapter->chan_stats), -+ GFP_KERNEL); - - if (!adapter->chan_stats) - return -ENOMEM; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/marvell/mwifiex/main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/marvell/mwifiex/main.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/marvell/mwifiex/main.c 2025-10-22 13:53:23.395328263 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/marvell/mwifiex/main.c 2025-10-22 13:53:56.615168659 -0400 -@@ -642,7 +642,7 @@ static int _mwifiex_fw_dpc(const struct - goto done; - - err_add_intf: -- vfree(adapter->chan_stats); -+ kfree(adapter->chan_stats); - err_init_chan_scan: - wiphy_unregister(adapter->wiphy); - wiphy_free(adapter->wiphy); -@@ -1485,7 +1485,7 @@ static void mwifiex_uninit_sw(struct mwi - wiphy_free(adapter->wiphy); - adapter->wiphy = NULL; - -- vfree(adapter->chan_stats); -+ kfree(adapter->chan_stats); - mwifiex_free_cmd_buffers(adapter); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/marvell/mwifiex/util.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/marvell/mwifiex/util.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/marvell/mwifiex/util.c 2025-10-22 13:53:23.395328263 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/marvell/mwifiex/util.c 2025-10-22 13:53:56.615168659 -0400 -@@ -459,7 +459,9 @@ mwifiex_process_mgmt_packet(struct mwifi - "auth: receive authentication from %pM\n", - ieee_hdr->addr3); - } else { -- if (!priv->wdev.connected) -+ if (!priv->wdev.connected || -+ !ether_addr_equal(ieee_hdr->addr3, -+ priv->curr_bss_params.bss_descriptor.mac_address)) - return 0; - - if (ieee80211_is_deauth(ieee_hdr->frame_control)) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/marvell/mwl8k.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/marvell/mwl8k.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/marvell/mwl8k.c 2025-10-22 13:53:23.395328263 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/marvell/mwl8k.c 2025-10-22 13:53:56.615168659 -0400 -@@ -1227,6 +1227,10 @@ static int rxq_refill(struct ieee80211_h - - addr = dma_map_single(&priv->pdev->dev, skb->data, - MWL8K_RX_MAXSZ, DMA_FROM_DEVICE); -+ if (dma_mapping_error(&priv->pdev->dev, addr)) { -+ kfree_skb(skb); -+ break; -+ } - - rxq->rxd_count++; - rx = rxq->tail++; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/channel.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/channel.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/channel.c 2025-10-22 13:53:23.395328263 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/channel.c 2025-10-22 13:53:56.615168659 -0400 -@@ -173,13 +173,13 @@ void mt76_unassign_vif_chanctx(struct ie - if (!mlink) - goto out; - -- if (link_conf != &vif->bss_conf) -+ if (mlink != (struct mt76_vif_link *)vif->drv_priv) - rcu_assign_pointer(mvif->link[link_id], NULL); - - dev->drv->vif_link_remove(phy, vif, link_conf, mlink); - mlink->ctx = NULL; - -- if (link_conf != &vif->bss_conf) -+ if (mlink != (struct mt76_vif_link *)vif->drv_priv) - kfree_rcu(mlink, rcu_head); - - out: -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mac80211.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mac80211.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mac80211.c 2025-10-22 13:53:23.395328263 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mac80211.c 2025-10-22 13:53:56.615168659 -0400 -@@ -818,6 +818,43 @@ void mt76_free_device(struct mt76_dev *d - } - EXPORT_SYMBOL_GPL(mt76_free_device); - -+static void mt76_reset_phy(struct mt76_phy *phy) -+{ -+ if (!phy) -+ return; -+ -+ INIT_LIST_HEAD(&phy->tx_list); -+} -+ -+void mt76_reset_device(struct mt76_dev *dev) -+{ -+ int i; -+ -+ rcu_read_lock(); -+ for (i = 0; i < ARRAY_SIZE(dev->wcid); i++) { -+ struct mt76_wcid *wcid; -+ -+ wcid = rcu_dereference(dev->wcid[i]); -+ if (!wcid) -+ continue; -+ -+ wcid->sta = 0; -+ mt76_wcid_cleanup(dev, wcid); -+ rcu_assign_pointer(dev->wcid[i], NULL); -+ } -+ rcu_read_unlock(); -+ -+ INIT_LIST_HEAD(&dev->wcid_list); -+ INIT_LIST_HEAD(&dev->sta_poll_list); -+ dev->vif_mask = 0; -+ memset(dev->wcid_mask, 0, sizeof(dev->wcid_mask)); -+ -+ mt76_reset_phy(&dev->phy); -+ for (i = 0; i < ARRAY_SIZE(dev->phys); i++) -+ mt76_reset_phy(dev->phys[i]); -+} -+EXPORT_SYMBOL_GPL(mt76_reset_device); -+ - struct mt76_phy *mt76_vif_phy(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) - { -@@ -1679,6 +1716,10 @@ void mt76_wcid_cleanup(struct mt76_dev * - skb_queue_splice_tail_init(&wcid->tx_pending, &list); - spin_unlock(&wcid->tx_pending.lock); - -+ spin_lock(&wcid->tx_offchannel.lock); -+ skb_queue_splice_tail_init(&wcid->tx_offchannel, &list); -+ spin_unlock(&wcid->tx_offchannel.lock); -+ - spin_unlock_bh(&phy->tx_lock); - - while ((skb = __skb_dequeue(&list)) != NULL) { -@@ -1690,7 +1731,7 @@ EXPORT_SYMBOL_GPL(mt76_wcid_cleanup); - - void mt76_wcid_add_poll(struct mt76_dev *dev, struct mt76_wcid *wcid) - { -- if (test_bit(MT76_MCU_RESET, &dev->phy.state)) -+ if (test_bit(MT76_MCU_RESET, &dev->phy.state) || !wcid->sta) - return; - - spin_lock_bh(&dev->sta_poll_lock); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7603/dma.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7603/dma.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7603/dma.c 2025-10-22 13:53:23.395328263 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7603/dma.c 2025-10-22 13:53:56.615168659 -0400 -@@ -44,7 +44,7 @@ mt7603_rx_loopback_skb(struct mt7603_dev - if (idx >= MT7603_WTBL_STA - 1) - goto free; - -- wcid = rcu_dereference(dev->mt76.wcid[idx]); -+ wcid = mt76_wcid_ptr(dev, idx); - if (!wcid) - goto free; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7603/mac.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7603/mac.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7603/mac.c 2025-10-22 13:53:23.395328263 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7603/mac.c 2025-10-22 13:53:56.615168659 -0400 -@@ -487,10 +487,7 @@ mt7603_rx_get_wcid(struct mt7603_dev *de - struct mt7603_sta *sta; - struct mt76_wcid *wcid; - -- if (idx >= MT7603_WTBL_SIZE) -- return NULL; -- -- wcid = rcu_dereference(dev->mt76.wcid[idx]); -+ wcid = mt76_wcid_ptr(dev, idx); - if (unicast || !wcid) - return wcid; - -@@ -1266,12 +1263,9 @@ void mt7603_mac_add_txs(struct mt7603_de - if (pid == MT_PACKET_ID_NO_ACK) - return; - -- if (wcidx >= MT7603_WTBL_SIZE) -- return; -- - rcu_read_lock(); - -- wcid = rcu_dereference(dev->mt76.wcid[wcidx]); -+ wcid = mt76_wcid_ptr(dev, wcidx); - if (!wcid) - goto out; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7615/mac.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7615/mac.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7615/mac.c 2025-10-22 13:53:23.395328263 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7615/mac.c 2025-10-22 13:53:56.615168659 -0400 -@@ -90,10 +90,7 @@ static struct mt76_wcid *mt7615_rx_get_w - struct mt7615_sta *sta; - struct mt76_wcid *wcid; - -- if (idx >= MT7615_WTBL_SIZE) -- return NULL; -- -- wcid = rcu_dereference(dev->mt76.wcid[idx]); -+ wcid = mt76_wcid_ptr(dev, idx); - if (unicast || !wcid) - return wcid; - -@@ -1504,7 +1501,7 @@ static void mt7615_mac_add_txs(struct mt - - rcu_read_lock(); - -- wcid = rcu_dereference(dev->mt76.wcid[wcidx]); -+ wcid = mt76_wcid_ptr(dev, wcidx); - if (!wcid) - goto out; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c 2025-10-22 13:53:23.395328263 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c 2025-10-22 13:53:56.615168659 -0400 -@@ -1172,7 +1172,7 @@ void mt76_connac2_txwi_free(struct mt76_ - wcid_idx = wcid->idx; - } else { - wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); -- wcid = rcu_dereference(dev->wcid[wcid_idx]); -+ wcid = __mt76_wcid_ptr(dev, wcid_idx); - - if (wcid && wcid->sta) { - sta = container_of((void *)wcid, struct ieee80211_sta, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c 2025-10-22 13:53:23.395328263 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c 2025-10-22 13:53:56.615168659 -0400 -@@ -287,7 +287,7 @@ __mt76_connac_mcu_alloc_sta_req(struct m - - mt76_connac_mcu_get_wlan_idx(dev, wcid, &hdr.wlan_idx_lo, - &hdr.wlan_idx_hi); -- skb = mt76_mcu_msg_alloc(dev, NULL, len); -+ skb = __mt76_mcu_msg_alloc(dev, NULL, len, len, GFP_ATOMIC); - if (!skb) - return ERR_PTR(-ENOMEM); - -@@ -1740,8 +1740,8 @@ int mt76_connac_mcu_hw_scan(struct mt76_ - if (!sreq->ssids[i].ssid_len) - continue; - -- req->ssids[i].ssid_len = cpu_to_le32(sreq->ssids[i].ssid_len); -- memcpy(req->ssids[i].ssid, sreq->ssids[i].ssid, -+ req->ssids[n_ssids].ssid_len = cpu_to_le32(sreq->ssids[i].ssid_len); -+ memcpy(req->ssids[n_ssids].ssid, sreq->ssids[i].ssid, - sreq->ssids[i].ssid_len); - n_ssids++; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt76.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt76.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt76.h 2025-10-22 13:53:23.395328263 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt76.h 2025-10-22 13:53:56.615168659 -0400 -@@ -1224,6 +1224,16 @@ static inline int mt76_wed_dma_setup(str - #define mt76_dereference(p, dev) \ - rcu_dereference_protected(p, lockdep_is_held(&(dev)->mutex)) - -+static inline struct mt76_wcid * -+__mt76_wcid_ptr(struct mt76_dev *dev, u16 idx) -+{ -+ if (idx >= ARRAY_SIZE(dev->wcid)) -+ return NULL; -+ return rcu_dereference(dev->wcid[idx]); -+} -+ -+#define mt76_wcid_ptr(dev, idx) __mt76_wcid_ptr(&(dev)->mt76, idx) -+ - struct mt76_dev *mt76_alloc_device(struct device *pdev, unsigned int size, - const struct ieee80211_ops *ops, - const struct mt76_driver_ops *drv_ops); -@@ -1231,6 +1241,7 @@ int mt76_register_device(struct mt76_dev - struct ieee80211_rate *rates, int n_rates); - void mt76_unregister_device(struct mt76_dev *dev); - void mt76_free_device(struct mt76_dev *dev); -+void mt76_reset_device(struct mt76_dev *dev); - void mt76_unregister_phy(struct mt76_phy *phy); - - struct mt76_phy *mt76_alloc_radio_phy(struct mt76_dev *dev, unsigned int size, -@@ -1864,6 +1875,9 @@ mt76_vif_link(struct mt76_dev *dev, stru - struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv; - struct mt76_vif_data *mvif = mlink->mvif; - -+ if (!link_id) -+ return mlink; -+ - return mt76_dereference(mvif->link[link_id], dev); - } - -@@ -1874,7 +1888,7 @@ mt76_vif_conf_link(struct mt76_dev *dev, - struct mt76_vif_link *mlink = (struct mt76_vif_link *)vif->drv_priv; - struct mt76_vif_data *mvif = mlink->mvif; - -- if (link_conf == &vif->bss_conf) -+ if (link_conf == &vif->bss_conf || !link_conf->link_id) - return mlink; - - return mt76_dereference(mvif->link[link_conf->link_id], dev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt76x02.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt76x02.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt76x02.h 2025-10-22 13:53:23.395328263 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt76x02.h 2025-10-22 13:53:56.615168659 -0400 -@@ -262,10 +262,7 @@ mt76x02_rx_get_sta(struct mt76_dev *dev, - { - struct mt76_wcid *wcid; - -- if (idx >= MT76x02_N_WCIDS) -- return NULL; -- -- wcid = rcu_dereference(dev->wcid[idx]); -+ wcid = __mt76_wcid_ptr(dev, idx); - if (!wcid) - return NULL; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c 2025-10-22 13:53:23.395328263 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c 2025-10-22 13:53:56.615168659 -0400 -@@ -564,9 +564,7 @@ void mt76x02_send_tx_status(struct mt76x - - rcu_read_lock(); - -- if (stat->wcid < MT76x02_N_WCIDS) -- wcid = rcu_dereference(dev->mt76.wcid[stat->wcid]); -- -+ wcid = mt76_wcid_ptr(dev, stat->wcid); - if (wcid && wcid->sta) { - void *priv; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7915/mac.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7915/mac.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7915/mac.c 2025-10-22 13:53:23.395328263 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7915/mac.c 2025-10-22 13:53:56.615168659 -0400 -@@ -56,10 +56,7 @@ static struct mt76_wcid *mt7915_rx_get_w - struct mt7915_sta *sta; - struct mt76_wcid *wcid; - -- if (idx >= ARRAY_SIZE(dev->mt76.wcid)) -- return NULL; -- -- wcid = rcu_dereference(dev->mt76.wcid[idx]); -+ wcid = mt76_wcid_ptr(dev, idx); - if (unicast || !wcid) - return wcid; - -@@ -917,7 +914,7 @@ mt7915_mac_tx_free(struct mt7915_dev *de - u16 idx; - - idx = FIELD_GET(MT_TX_FREE_WLAN_ID, info); -- wcid = rcu_dereference(dev->mt76.wcid[idx]); -+ wcid = mt76_wcid_ptr(dev, idx); - sta = wcid_to_sta(wcid); - if (!sta) - continue; -@@ -1013,12 +1010,9 @@ static void mt7915_mac_add_txs(struct mt - if (pid < MT_PACKET_ID_WED) - return; - -- if (wcidx >= mt7915_wtbl_size(dev)) -- return; -- - rcu_read_lock(); - -- wcid = rcu_dereference(dev->mt76.wcid[wcidx]); -+ wcid = mt76_wcid_ptr(dev, wcidx); - if (!wcid) - goto out; - -@@ -1466,17 +1460,15 @@ mt7915_mac_full_reset(struct mt7915_dev - if (i == 10) - dev_err(dev->mt76.dev, "chip full reset failed\n"); - -- spin_lock_bh(&dev->mt76.sta_poll_lock); -- while (!list_empty(&dev->mt76.sta_poll_list)) -- list_del_init(dev->mt76.sta_poll_list.next); -- spin_unlock_bh(&dev->mt76.sta_poll_lock); -- -- memset(dev->mt76.wcid_mask, 0, sizeof(dev->mt76.wcid_mask)); -- dev->mt76.vif_mask = 0; - dev->phy.omac_mask = 0; - if (phy2) - phy2->omac_mask = 0; - -+ mt76_reset_device(&dev->mt76); -+ -+ INIT_LIST_HEAD(&dev->sta_rc_list); -+ INIT_LIST_HEAD(&dev->twt_list); -+ - i = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA); - dev->mt76.global_wcid.idx = i; - dev->recovery.hw_full_reset = false; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c 2025-10-22 13:53:23.395328263 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c 2025-10-22 13:53:56.619168640 -0400 -@@ -208,6 +208,9 @@ mt7915_mcu_set_timeout(struct mt76_dev * - case MCU_EXT_CMD_BSS_INFO_UPDATE: - mdev->mcu.timeout = 2 * HZ; - return; -+ case MCU_EXT_CMD_EFUSE_BUFFER_MODE: -+ mdev->mcu.timeout = 10 * HZ; -+ return; - default: - break; - } -@@ -2110,16 +2113,21 @@ static int mt7915_load_firmware(struct m - { - int ret; - -- /* make sure fw is download state */ -- if (mt7915_firmware_state(dev, false)) { -- /* restart firmware once */ -- mt76_connac_mcu_restart(&dev->mt76); -- ret = mt7915_firmware_state(dev, false); -- if (ret) { -- dev_err(dev->mt76.dev, -- "Firmware is not ready for download\n"); -- return ret; -- } -+ /* Release Semaphore if taken by previous failed attempt */ -+ ret = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, false); -+ if (ret != PATCH_REL_SEM_SUCCESS) { -+ dev_err(dev->mt76.dev, "Could not release semaphore\n"); -+ /* Continue anyways */ -+ } -+ -+ /* Always restart MCU firmware */ -+ mt76_connac_mcu_restart(&dev->mt76); -+ -+ /* Check if MCU is ready */ -+ ret = mt7915_firmware_state(dev, false); -+ if (ret) { -+ dev_err(dev->mt76.dev, "Firmware did not enter download state\n"); -+ return ret; - } - - ret = mt76_connac2_load_patch(&dev->mt76, fw_name_var(dev, ROM_PATCH)); -@@ -3986,7 +3994,7 @@ int mt7915_mcu_wed_wa_tx_stats(struct mt - - rcu_read_lock(); - -- wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]); -+ wcid = mt76_wcid_ptr(dev, wlan_idx); - if (wcid) - wcid->stats.tx_packets += le32_to_cpu(res->tx_packets); - else -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c 2025-10-22 13:53:23.395328263 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c 2025-10-22 13:53:56.619168640 -0400 -@@ -587,12 +587,9 @@ static void mt7915_mmio_wed_update_rx_st - - dev = container_of(wed, struct mt7915_dev, mt76.mmio.wed); - -- if (idx >= mt7915_wtbl_size(dev)) -- return; -- - rcu_read_lock(); - -- wcid = rcu_dereference(dev->mt76.wcid[idx]); -+ wcid = mt76_wcid_ptr(dev, idx); - if (wcid) { - wcid->stats.rx_bytes += le32_to_cpu(stats->rx_byte_cnt); - wcid->stats.rx_packets += le32_to_cpu(stats->rx_pkt_cnt); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7921/mac.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7921/mac.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7921/mac.c 2025-10-22 13:53:23.395328263 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7921/mac.c 2025-10-22 13:53:56.619168640 -0400 -@@ -465,7 +465,7 @@ void mt7921_mac_add_txs(struct mt792x_de - - rcu_read_lock(); - -- wcid = rcu_dereference(dev->mt76.wcid[wcidx]); -+ wcid = mt76_wcid_ptr(dev, wcidx); - if (!wcid) - goto out; - -@@ -516,7 +516,7 @@ static void mt7921_mac_tx_free(struct mt - - count++; - idx = FIELD_GET(MT_TX_FREE_WLAN_ID, info); -- wcid = rcu_dereference(dev->mt76.wcid[idx]); -+ wcid = mt76_wcid_ptr(dev, idx); - sta = wcid_to_sta(wcid); - if (!sta) - continue; -@@ -816,7 +816,7 @@ void mt7921_usb_sdio_tx_complete_skb(str - u16 idx; - - idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); -- wcid = rcu_dereference(mdev->wcid[idx]); -+ wcid = __mt76_wcid_ptr(mdev, idx); - sta = wcid_to_sta(wcid); - - if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE))) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7921/main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7921/main.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7921/main.c 2025-10-22 13:53:23.395328263 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7921/main.c 2025-10-22 13:53:56.619168640 -0400 -@@ -1180,6 +1180,9 @@ static void mt7921_sta_set_decap_offload - struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv; - struct mt792x_dev *dev = mt792x_hw_dev(hw); - -+ if (!msta->deflink.wcid.sta) -+ return; -+ - mt792x_mutex_acquire(dev); - - if (enabled) -@@ -1454,11 +1457,8 @@ static int mt7921_pre_channel_switch(str - if (vif->type != NL80211_IFTYPE_STATION || !vif->cfg.assoc) - return -EOPNOTSUPP; - -- /* Avoid beacon loss due to the CAC(Channel Availability Check) time -- * of the AP. -- */ - if (!cfg80211_chandef_usable(hw->wiphy, &chsw->chandef, -- IEEE80211_CHAN_RADAR)) -+ IEEE80211_CHAN_DISABLED)) - return -EOPNOTSUPP; - - return 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7925/init.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7925/init.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7925/init.c 2025-10-22 13:53:23.395328263 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7925/init.c 2025-10-22 13:53:56.619168640 -0400 -@@ -52,6 +52,8 @@ static int mt7925_thermal_init(struct mt - - name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7925_%s", - wiphy_name(wiphy)); -+ if (!name) -+ return -ENOMEM; - - hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy, - mt7925_hwmon_groups); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7925/mac.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7925/mac.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7925/mac.c 2025-10-22 13:53:23.395328263 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7925/mac.c 2025-10-22 13:53:56.619168640 -0400 -@@ -1040,7 +1040,7 @@ void mt7925_mac_add_txs(struct mt792x_de - - rcu_read_lock(); - -- wcid = rcu_dereference(dev->mt76.wcid[wcidx]); -+ wcid = mt76_wcid_ptr(dev, wcidx); - if (!wcid) - goto out; - -@@ -1122,7 +1122,7 @@ mt7925_mac_tx_free(struct mt792x_dev *de - u16 idx; - - idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info); -- wcid = rcu_dereference(dev->mt76.wcid[idx]); -+ wcid = mt76_wcid_ptr(dev, idx); - sta = wcid_to_sta(wcid); - if (!sta) - continue; -@@ -1445,11 +1445,11 @@ void mt7925_usb_sdio_tx_complete_skb(str - u16 idx; - - idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); -- wcid = rcu_dereference(mdev->wcid[idx]); -+ wcid = __mt76_wcid_ptr(mdev, idx); - sta = wcid_to_sta(wcid); - - if (sta && likely(e->skb->protocol != cpu_to_be16(ETH_P_PAE))) -- mt76_connac2_tx_check_aggr(sta, txwi); -+ mt7925_tx_check_aggr(sta, e->skb, wcid); - - skb_pull(e->skb, headroom); - mt76_tx_complete_skb(mdev, e->wcid, e->skb); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7925/main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7925/main.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7925/main.c 2025-10-22 13:53:23.395328263 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7925/main.c 2025-10-22 13:53:56.619168640 -0400 -@@ -1191,6 +1191,9 @@ mt7925_mac_sta_remove_links(struct mt792 - struct mt792x_bss_conf *mconf; - struct mt792x_link_sta *mlink; - -+ if (vif->type == NL80211_IFTYPE_AP) -+ break; -+ - link_sta = mt792x_sta_to_link_sta(vif, sta, link_id); - if (!link_sta) - continue; -@@ -1481,7 +1484,7 @@ mt7925_start_sched_scan(struct ieee80211 - - mt792x_mutex_acquire(dev); - -- err = mt7925_mcu_sched_scan_req(mphy, vif, req); -+ err = mt7925_mcu_sched_scan_req(mphy, vif, req, ies); - if (err < 0) - goto out; - -@@ -1603,6 +1606,9 @@ static void mt7925_sta_set_decap_offload - unsigned long valid = mvif->valid_links; - u8 i; - -+ if (!msta->vif) -+ return; -+ - mt792x_mutex_acquire(dev); - - valid = ieee80211_vif_is_mld(vif) ? mvif->valid_links : BIT(0); -@@ -1617,6 +1623,9 @@ static void mt7925_sta_set_decap_offload - else - clear_bit(MT_WCID_FLAG_HDR_TRANS, &mlink->wcid.flags); - -+ if (!mlink->wcid.sta) -+ continue; -+ - mt7925_mcu_wtbl_update_hdr_trans(dev, vif, sta, i); - } - -@@ -2061,8 +2070,10 @@ mt7925_change_vif_links(struct ieee80211 - GFP_KERNEL); - mlink = devm_kzalloc(dev->mt76.dev, sizeof(*mlink), - GFP_KERNEL); -- if (!mconf || !mlink) -+ if (!mconf || !mlink) { -+ mt792x_mutex_release(dev); - return -ENOMEM; -+ } - } - - mconfs[link_id] = mconf; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c 2025-10-22 13:53:56.619168640 -0400 -@@ -164,6 +164,7 @@ mt7925_connac_mcu_set_wow_ctrl(struct mt - bool suspend, struct cfg80211_wowlan *wowlan) - { - struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; -+ struct ieee80211_scan_ies ies = {}; - struct mt76_dev *dev = phy->dev; - struct { - struct { -@@ -194,7 +195,7 @@ mt7925_connac_mcu_set_wow_ctrl(struct mt - req.wow_ctrl_tlv.trigger |= (UNI_WOW_DETECT_TYPE_DISCONNECT | - UNI_WOW_DETECT_TYPE_BCN_LOST); - if (wowlan->nd_config) { -- mt7925_mcu_sched_scan_req(phy, vif, wowlan->nd_config); -+ mt7925_mcu_sched_scan_req(phy, vif, wowlan->nd_config, &ies); - req.wow_ctrl_tlv.trigger |= UNI_WOW_DETECT_TYPE_SCH_SCAN_HIT; - mt7925_mcu_sched_scan_enable(phy, vif, suspend); - } -@@ -1833,13 +1834,13 @@ mt7925_mcu_sta_eht_mld_tlv(struct sk_buf - struct tlv *tlv; - u16 eml_cap; - -+ if (!ieee80211_vif_is_mld(vif)) -+ return; -+ - tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_EHT_MLD, sizeof(*eht_mld)); - eht_mld = (struct sta_rec_eht_mld *)tlv; - eht_mld->mld_type = 0xff; - -- if (!ieee80211_vif_is_mld(vif)) -- return; -- - ext_capa = cfg80211_get_iftype_ext_capa(wiphy, - ieee80211_vif_type_p2p(vif)); - if (!ext_capa) -@@ -1911,6 +1912,7 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy, - struct mt76_dev *dev = phy->dev; - struct mt792x_bss_conf *mconf; - struct sk_buff *skb; -+ int conn_state; - - mconf = mt792x_vif_to_link(mvif, info->wcid->link_id); - -@@ -1919,10 +1921,13 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy, - if (IS_ERR(skb)) - return PTR_ERR(skb); - -+ conn_state = info->enable ? CONN_STATE_PORT_SECURE : -+ CONN_STATE_DISCONNECT; -+ - if (info->enable && info->link_sta) { - mt76_connac_mcu_sta_basic_tlv(dev, skb, info->link_conf, - info->link_sta, -- info->enable, info->newly); -+ conn_state, info->newly); - mt7925_mcu_sta_phy_tlv(skb, info->vif, info->link_sta); - mt7925_mcu_sta_ht_tlv(skb, info->link_sta); - mt7925_mcu_sta_vht_tlv(skb, info->link_sta); -@@ -2818,6 +2823,54 @@ int mt7925_mcu_set_dbdc(struct mt76_phy - return err; - } - -+static void -+mt7925_mcu_build_scan_ie_tlv(struct mt76_dev *mdev, -+ struct sk_buff *skb, -+ struct ieee80211_scan_ies *scan_ies) -+{ -+ u32 max_len = sizeof(struct scan_ie_tlv) + MT76_CONNAC_SCAN_IE_LEN; -+ struct scan_ie_tlv *ie; -+ enum nl80211_band i; -+ struct tlv *tlv; -+ const u8 *ies; -+ u16 ies_len; -+ -+ for (i = 0; i <= NL80211_BAND_6GHZ; i++) { -+ if (i == NL80211_BAND_60GHZ) -+ continue; -+ -+ ies = scan_ies->ies[i]; -+ ies_len = scan_ies->len[i]; -+ -+ if (!ies || !ies_len) -+ continue; -+ -+ if (ies_len > max_len) -+ return; -+ -+ tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_IE, -+ sizeof(*ie) + ies_len); -+ ie = (struct scan_ie_tlv *)tlv; -+ -+ memcpy(ie->ies, ies, ies_len); -+ ie->ies_len = cpu_to_le16(ies_len); -+ -+ switch (i) { -+ case NL80211_BAND_2GHZ: -+ ie->band = 1; -+ break; -+ case NL80211_BAND_6GHZ: -+ ie->band = 3; -+ break; -+ default: -+ ie->band = 2; -+ break; -+ } -+ -+ max_len -= (sizeof(*ie) + ies_len); -+ } -+} -+ - int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif, - struct ieee80211_scan_request *scan_req) - { -@@ -2843,7 +2896,8 @@ int mt7925_mcu_hw_scan(struct mt76_phy * - - max_len = sizeof(*hdr) + sizeof(*req) + sizeof(*ssid) + - sizeof(*bssid) * MT7925_RNR_SCAN_MAX_BSSIDS + -- sizeof(*chan_info) + sizeof(*misc) + sizeof(*ie); -+ sizeof(*chan_info) + sizeof(*misc) + sizeof(*ie) + -+ MT76_CONNAC_SCAN_IE_LEN; - - skb = mt76_mcu_msg_alloc(mdev, NULL, max_len); - if (!skb) -@@ -2866,11 +2920,11 @@ int mt7925_mcu_hw_scan(struct mt76_phy * - for (i = 0; i < sreq->n_ssids; i++) { - if (!sreq->ssids[i].ssid_len) - continue; -- if (i > MT7925_RNR_SCAN_MAX_BSSIDS) -+ if (i >= MT7925_RNR_SCAN_MAX_BSSIDS) - break; - -- ssid->ssids[i].ssid_len = cpu_to_le32(sreq->ssids[i].ssid_len); -- memcpy(ssid->ssids[i].ssid, sreq->ssids[i].ssid, -+ ssid->ssids[n_ssids].ssid_len = cpu_to_le32(sreq->ssids[i].ssid_len); -+ memcpy(ssid->ssids[n_ssids].ssid, sreq->ssids[i].ssid, - sreq->ssids[i].ssid_len); - n_ssids++; - } -@@ -2883,7 +2937,7 @@ int mt7925_mcu_hw_scan(struct mt76_phy * - mt76_connac_mcu_build_rnr_scan_param(mdev, sreq); - - for (j = 0; j < mdev->rnr.bssid_num; j++) { -- if (j > MT7925_RNR_SCAN_MAX_BSSIDS) -+ if (j >= MT7925_RNR_SCAN_MAX_BSSIDS) - break; - - tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_BSSID, -@@ -2925,13 +2979,6 @@ int mt7925_mcu_hw_scan(struct mt76_phy * - } - chan_info->channel_type = sreq->n_channels ? 4 : 0; - -- tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_IE, sizeof(*ie)); -- ie = (struct scan_ie_tlv *)tlv; -- if (sreq->ie_len > 0) { -- memcpy(ie->ies, sreq->ie, sreq->ie_len); -- ie->ies_len = cpu_to_le16(sreq->ie_len); -- } -- - req->scan_func |= SCAN_FUNC_SPLIT_SCAN; - - tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_MISC, sizeof(*misc)); -@@ -2942,6 +2989,9 @@ int mt7925_mcu_hw_scan(struct mt76_phy * - req->scan_func |= SCAN_FUNC_RANDOM_MAC; - } - -+ /* Append scan probe IEs as the last tlv */ -+ mt7925_mcu_build_scan_ie_tlv(mdev, skb, &scan_req->ies); -+ - err = mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SCAN_REQ), - true); - if (err < 0) -@@ -2953,7 +3003,8 @@ EXPORT_SYMBOL_GPL(mt7925_mcu_hw_scan); - - int mt7925_mcu_sched_scan_req(struct mt76_phy *phy, - struct ieee80211_vif *vif, -- struct cfg80211_sched_scan_request *sreq) -+ struct cfg80211_sched_scan_request *sreq, -+ struct ieee80211_scan_ies *ies) - { - struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; - struct ieee80211_channel **scan_list = sreq->channels; -@@ -3041,12 +3092,8 @@ int mt7925_mcu_sched_scan_req(struct mt7 - } - chan_info->channel_type = sreq->n_channels ? 4 : 0; - -- tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_IE, sizeof(*ie)); -- ie = (struct scan_ie_tlv *)tlv; -- if (sreq->ie_len > 0) { -- memcpy(ie->ies, sreq->ie, sreq->ie_len); -- ie->ies_len = cpu_to_le16(sreq->ie_len); -- } -+ /* Append scan probe IEs as the last tlv */ -+ mt7925_mcu_build_scan_ie_tlv(mdev, skb, ies); - - return mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SCAN_REQ), - true); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h 2025-10-22 13:53:56.619168640 -0400 -@@ -269,7 +269,7 @@ struct scan_ie_tlv { - __le16 ies_len; - u8 band; - u8 pad; -- u8 ies[MT76_CONNAC_SCAN_IE_LEN]; -+ u8 ies[]; - }; - - struct scan_misc_tlv { -@@ -673,7 +673,8 @@ int mt7925_mcu_cancel_hw_scan(struct mt7 - struct ieee80211_vif *vif); - int mt7925_mcu_sched_scan_req(struct mt76_phy *phy, - struct ieee80211_vif *vif, -- struct cfg80211_sched_scan_request *sreq); -+ struct cfg80211_sched_scan_request *sreq, -+ struct ieee80211_scan_ies *ies); - int mt7925_mcu_sched_scan_enable(struct mt76_phy *phy, - struct ieee80211_vif *vif, - bool enable); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7925/regs.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7925/regs.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7925/regs.h 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7925/regs.h 2025-10-22 13:53:56.619168640 -0400 -@@ -58,7 +58,7 @@ - - #define MT_INT_TX_DONE_MCU (MT_INT_TX_DONE_MCU_WM | \ - MT_INT_TX_DONE_FWDL) --#define MT_INT_TX_DONE_ALL (MT_INT_TX_DONE_MCU_WM | \ -+#define MT_INT_TX_DONE_ALL (MT_INT_TX_DONE_MCU | \ - MT_INT_TX_DONE_BAND0 | \ - GENMASK(18, 4)) - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt792x_core.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt792x_core.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt792x_core.c 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt792x_core.c 2025-10-22 13:53:56.619168640 -0400 -@@ -28,7 +28,7 @@ static const struct ieee80211_iface_comb - }, - }; - --static const struct ieee80211_iface_limit if_limits_chanctx[] = { -+static const struct ieee80211_iface_limit if_limits_chanctx_mcc[] = { - { - .max = 2, - .types = BIT(NL80211_IFTYPE_STATION) | -@@ -36,8 +36,23 @@ static const struct ieee80211_iface_limi - }, - { - .max = 1, -- .types = BIT(NL80211_IFTYPE_AP) | -- BIT(NL80211_IFTYPE_P2P_GO) -+ .types = BIT(NL80211_IFTYPE_P2P_GO) -+ }, -+ { -+ .max = 1, -+ .types = BIT(NL80211_IFTYPE_P2P_DEVICE) -+ } -+}; -+ -+static const struct ieee80211_iface_limit if_limits_chanctx_scc[] = { -+ { -+ .max = 2, -+ .types = BIT(NL80211_IFTYPE_STATION) | -+ BIT(NL80211_IFTYPE_P2P_CLIENT) -+ }, -+ { -+ .max = 1, -+ .types = BIT(NL80211_IFTYPE_AP) - }, - { - .max = 1, -@@ -47,11 +62,18 @@ static const struct ieee80211_iface_limi - - static const struct ieee80211_iface_combination if_comb_chanctx[] = { - { -- .limits = if_limits_chanctx, -- .n_limits = ARRAY_SIZE(if_limits_chanctx), -+ .limits = if_limits_chanctx_mcc, -+ .n_limits = ARRAY_SIZE(if_limits_chanctx_mcc), - .max_interfaces = 3, - .num_different_channels = 2, - .beacon_int_infra_match = false, -+ }, -+ { -+ .limits = if_limits_chanctx_scc, -+ .n_limits = ARRAY_SIZE(if_limits_chanctx_scc), -+ .max_interfaces = 3, -+ .num_different_channels = 1, -+ .beacon_int_infra_match = false, - } - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt792x_mac.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt792x_mac.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt792x_mac.c 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt792x_mac.c 2025-10-22 13:53:56.619168640 -0400 -@@ -142,10 +142,7 @@ struct mt76_wcid *mt792x_rx_get_wcid(str - struct mt792x_sta *sta; - struct mt76_wcid *wcid; - -- if (idx >= ARRAY_SIZE(dev->mt76.wcid)) -- return NULL; -- -- wcid = rcu_dereference(dev->mt76.wcid[idx]); -+ wcid = mt76_wcid_ptr(dev, idx); - if (unicast || !wcid) - return wcid; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7996/mac.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7996/mac.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7996/mac.c 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7996/mac.c 2025-10-22 13:53:56.619168640 -0400 -@@ -61,11 +61,8 @@ static struct mt76_wcid *mt7996_rx_get_w - struct mt76_wcid *wcid; - int i; - -- if (idx >= ARRAY_SIZE(dev->mt76.wcid)) -- return NULL; -- -- wcid = rcu_dereference(dev->mt76.wcid[idx]); -- if (!wcid) -+ wcid = mt76_wcid_ptr(dev, idx); -+ if (!wcid || !wcid->sta) - return NULL; - - if (!mt7996_band_valid(dev, band_idx)) -@@ -906,8 +903,12 @@ void mt7996_mac_write_txwi(struct mt7996 - IEEE80211_TX_CTRL_MLO_LINK); - - mvif = vif ? (struct mt7996_vif *)vif->drv_priv : NULL; -- if (mvif) -- mlink = rcu_dereference(mvif->mt76.link[link_id]); -+ if (mvif) { -+ if (wcid->offchannel) -+ mlink = rcu_dereference(mvif->mt76.offchannel_link); -+ if (!mlink) -+ mlink = rcu_dereference(mvif->mt76.link[link_id]); -+ } - - if (mlink) { - omac_idx = mlink->omac_idx; -@@ -1087,9 +1088,9 @@ int mt7996_tx_prepare_skb(struct mt76_de - if (wcid->offchannel) - mlink = rcu_dereference(mvif->mt76.offchannel_link); - if (!mlink) -- mlink = &mvif->deflink.mt76; -+ mlink = rcu_dereference(mvif->mt76.link[wcid->link_id]); - -- txp->fw.bss_idx = mlink->idx; -+ txp->fw.bss_idx = mlink ? mlink->idx : mvif->deflink.mt76.idx; - } - - txp->fw.token = cpu_to_le16(id); -@@ -1249,7 +1250,7 @@ mt7996_mac_tx_free(struct mt7996_dev *de - u16 idx; - - idx = FIELD_GET(MT_TXFREE_INFO_WLAN_ID, info); -- wcid = rcu_dereference(dev->mt76.wcid[idx]); -+ wcid = mt76_wcid_ptr(dev, idx); - sta = wcid_to_sta(wcid); - if (!sta) - goto next; -@@ -1471,12 +1472,9 @@ static void mt7996_mac_add_txs(struct mt - if (pid < MT_PACKET_ID_NO_SKB) - return; - -- if (wcidx >= mt7996_wtbl_size(dev)) -- return; -- - rcu_read_lock(); - -- wcid = rcu_dereference(dev->mt76.wcid[wcidx]); -+ wcid = mt76_wcid_ptr(dev, wcidx); - if (!wcid) - goto out; - -@@ -1702,43 +1700,53 @@ mt7996_wait_reset_state(struct mt7996_de - static void - mt7996_update_vif_beacon(void *priv, u8 *mac, struct ieee80211_vif *vif) - { -- struct ieee80211_hw *hw = priv; -+ struct ieee80211_bss_conf *link_conf; -+ struct mt7996_phy *phy = priv; -+ struct mt7996_dev *dev = phy->dev; -+ unsigned int link_id; -+ - - switch (vif->type) { - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_AP: -- mt7996_mcu_add_beacon(hw, vif, &vif->bss_conf); - break; - default: -- break; -+ return; -+ } -+ -+ for_each_vif_active_link(vif, link_conf, link_id) { -+ struct mt7996_vif_link *link; -+ -+ link = mt7996_vif_link(dev, vif, link_id); -+ if (!link || link->phy != phy) -+ continue; -+ -+ mt7996_mcu_add_beacon(dev->mt76.hw, vif, link_conf); - } - } - -+void mt7996_mac_update_beacons(struct mt7996_phy *phy) -+{ -+ ieee80211_iterate_active_interfaces(phy->mt76->hw, -+ IEEE80211_IFACE_ITER_RESUME_ALL, -+ mt7996_update_vif_beacon, phy); -+} -+ - static void - mt7996_update_beacons(struct mt7996_dev *dev) - { - struct mt76_phy *phy2, *phy3; - -- ieee80211_iterate_active_interfaces(dev->mt76.hw, -- IEEE80211_IFACE_ITER_RESUME_ALL, -- mt7996_update_vif_beacon, dev->mt76.hw); -+ mt7996_mac_update_beacons(&dev->phy); - - phy2 = dev->mt76.phys[MT_BAND1]; -- if (!phy2) -- return; -- -- ieee80211_iterate_active_interfaces(phy2->hw, -- IEEE80211_IFACE_ITER_RESUME_ALL, -- mt7996_update_vif_beacon, phy2->hw); -+ if (phy2) -+ mt7996_mac_update_beacons(phy2->priv); - - phy3 = dev->mt76.phys[MT_BAND2]; -- if (!phy3) -- return; -- -- ieee80211_iterate_active_interfaces(phy3->hw, -- IEEE80211_IFACE_ITER_RESUME_ALL, -- mt7996_update_vif_beacon, phy3->hw); -+ if (phy3) -+ mt7996_mac_update_beacons(phy3->priv); - } - - void mt7996_tx_token_put(struct mt7996_dev *dev) -@@ -2353,20 +2361,12 @@ void mt7996_mac_update_stats(struct mt79 - void mt7996_mac_sta_rc_work(struct work_struct *work) - { - struct mt7996_dev *dev = container_of(work, struct mt7996_dev, rc_work); -- struct ieee80211_bss_conf *link_conf; -- struct ieee80211_link_sta *link_sta; - struct mt7996_sta_link *msta_link; -- struct mt7996_vif_link *link; -- struct mt76_vif_link *mlink; -- struct ieee80211_sta *sta; - struct ieee80211_vif *vif; -- struct mt7996_sta *msta; - struct mt7996_vif *mvif; - LIST_HEAD(list); - u32 changed; -- u8 link_id; - -- rcu_read_lock(); - spin_lock_bh(&dev->mt76.sta_poll_lock); - list_splice_init(&dev->sta_rc_list, &list); - -@@ -2377,46 +2377,28 @@ void mt7996_mac_sta_rc_work(struct work_ - - changed = msta_link->changed; - msta_link->changed = 0; -- -- sta = wcid_to_sta(&msta_link->wcid); -- link_id = msta_link->wcid.link_id; -- msta = msta_link->sta; -- mvif = msta->vif; -- vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv); -- -- mlink = rcu_dereference(mvif->mt76.link[link_id]); -- if (!mlink) -- continue; -- -- link_sta = rcu_dereference(sta->link[link_id]); -- if (!link_sta) -- continue; -- -- link_conf = rcu_dereference(vif->link_conf[link_id]); -- if (!link_conf) -- continue; -+ mvif = msta_link->sta->vif; -+ vif = container_of((void *)mvif, struct ieee80211_vif, -+ drv_priv); - - spin_unlock_bh(&dev->mt76.sta_poll_lock); - -- link = (struct mt7996_vif_link *)mlink; -- - if (changed & (IEEE80211_RC_SUPP_RATES_CHANGED | - IEEE80211_RC_NSS_CHANGED | - IEEE80211_RC_BW_CHANGED)) -- mt7996_mcu_add_rate_ctrl(dev, vif, link_conf, -- link_sta, link, msta_link, -+ mt7996_mcu_add_rate_ctrl(dev, msta_link->sta, vif, -+ msta_link->wcid.link_id, - true); - - if (changed & IEEE80211_RC_SMPS_CHANGED) -- mt7996_mcu_set_fixed_field(dev, link_sta, link, -- msta_link, NULL, -+ mt7996_mcu_set_fixed_field(dev, msta_link->sta, NULL, -+ msta_link->wcid.link_id, - RATE_PARAM_MMPS_UPDATE); - - spin_lock_bh(&dev->mt76.sta_poll_lock); - } - - spin_unlock_bh(&dev->mt76.sta_poll_lock); -- rcu_read_unlock(); - } - - void mt7996_mac_work(struct work_struct *work) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7996/main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7996/main.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7996/main.c 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7996/main.c 2025-10-22 13:53:56.619168640 -0400 -@@ -516,6 +516,9 @@ int mt7996_set_channel(struct mt76_phy * - struct mt7996_phy *phy = mphy->priv; - int ret; - -+ if (mphy->offchannel) -+ mt7996_mac_update_beacons(phy); -+ - ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_SWITCH); - if (ret) - goto out; -@@ -533,6 +536,8 @@ int mt7996_set_channel(struct mt76_phy * - - mt7996_mac_reset_counters(phy); - phy->noise = 0; -+ if (!mphy->offchannel) -+ mt7996_mac_update_beacons(phy); - - out: - ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, -@@ -1061,7 +1066,7 @@ mt7996_mac_sta_add(struct mt76_phy *mphy - struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); - struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv; - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; -- unsigned long links = sta->mlo ? sta->valid_links : BIT(0); -+ unsigned long links = sta->valid_links ? sta->valid_links : BIT(0); - int err; - - mutex_lock(&mdev->mutex); -@@ -1112,9 +1117,8 @@ mt7996_mac_sta_event(struct mt7996_dev * - if (err) - return err; - -- err = mt7996_mcu_add_rate_ctrl(dev, vif, link_conf, -- link_sta, link, -- msta_link, false); -+ err = mt7996_mcu_add_rate_ctrl(dev, msta_link->sta, vif, -+ link_id, false); - if (err) - return err; - -@@ -1156,7 +1160,7 @@ mt7996_mac_sta_remove(struct mt76_phy *m - { - struct mt76_dev *mdev = mphy->dev; - struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); -- unsigned long links = sta->mlo ? sta->valid_links : BIT(0); -+ unsigned long links = sta->valid_links ? sta->valid_links : BIT(0); - - mutex_lock(&mdev->mutex); - -@@ -1217,10 +1221,17 @@ static void mt7996_tx(struct ieee80211_h - - if (vif) { - struct mt7996_vif *mvif = (void *)vif->drv_priv; -- struct mt76_vif_link *mlink; -+ struct mt76_vif_link *mlink = &mvif->deflink.mt76; -+ -+ if (link_id < IEEE80211_LINK_UNSPECIFIED) -+ mlink = rcu_dereference(mvif->mt76.link[link_id]); -+ -+ if (!mlink) { -+ ieee80211_free_txskb(hw, skb); -+ goto unlock; -+ } - -- mlink = rcu_dereference(mvif->mt76.link[link_id]); -- if (mlink && mlink->wcid) -+ if (mlink->wcid) - wcid = mlink->wcid; - - if (mvif->mt76.roc_phy && -@@ -1229,7 +1240,7 @@ static void mt7996_tx(struct ieee80211_h - if (mphy->roc_link) - wcid = mphy->roc_link->wcid; - } else { -- mphy = mt76_vif_link_phy(&mvif->deflink.mt76); -+ mphy = mt76_vif_link_phy(mlink); - } - } - -@@ -1238,7 +1249,7 @@ static void mt7996_tx(struct ieee80211_h - goto unlock; - } - -- if (control->sta) { -+ if (control->sta && link_id < IEEE80211_LINK_UNSPECIFIED) { - struct mt7996_sta *msta = (void *)control->sta->drv_priv; - struct mt7996_sta_link *msta_link; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c 2025-10-22 13:53:56.619168640 -0400 -@@ -555,7 +555,7 @@ mt7996_mcu_rx_all_sta_info_event(struct - switch (le16_to_cpu(res->tag)) { - case UNI_ALL_STA_TXRX_RATE: - wlan_idx = le16_to_cpu(res->rate[i].wlan_idx); -- wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]); -+ wcid = mt76_wcid_ptr(dev, wlan_idx); - - if (!wcid) - break; -@@ -565,7 +565,7 @@ mt7996_mcu_rx_all_sta_info_event(struct - break; - case UNI_ALL_STA_TXRX_ADM_STAT: - wlan_idx = le16_to_cpu(res->adm_stat[i].wlan_idx); -- wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]); -+ wcid = mt76_wcid_ptr(dev, wlan_idx); - - if (!wcid) - break; -@@ -579,7 +579,7 @@ mt7996_mcu_rx_all_sta_info_event(struct - break; - case UNI_ALL_STA_TXRX_MSDU_COUNT: - wlan_idx = le16_to_cpu(res->msdu_cnt[i].wlan_idx); -- wcid = rcu_dereference(dev->mt76.wcid[wlan_idx]); -+ wcid = mt76_wcid_ptr(dev, wlan_idx); - - if (!wcid) - break; -@@ -676,10 +676,7 @@ mt7996_mcu_wed_rro_event(struct mt7996_d - - e = (void *)skb->data; - idx = le16_to_cpu(e->wlan_id); -- if (idx >= ARRAY_SIZE(dev->mt76.wcid)) -- break; -- -- wcid = rcu_dereference(dev->mt76.wcid[idx]); -+ wcid = mt76_wcid_ptr(dev, idx); - if (!wcid || !wcid->sta) - break; - -@@ -1882,8 +1879,8 @@ mt7996_mcu_get_mmps_mode(enum ieee80211_ - int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev, - void *data, u16 version) - { -+ struct uni_header hdr = {}; - struct ra_fixed_rate *req; -- struct uni_header hdr; - struct sk_buff *skb; - struct tlv *tlv; - int len; -@@ -1905,22 +1902,35 @@ int mt7996_mcu_set_fixed_rate_ctrl(struc - MCU_WM_UNI_CMD(RA), true); - } - --int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, -- struct ieee80211_link_sta *link_sta, -- struct mt7996_vif_link *link, -- struct mt7996_sta_link *msta_link, -- void *data, u32 field) -+int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct mt7996_sta *msta, -+ void *data, u8 link_id, u32 field) - { -- struct sta_phy_uni *phy = data; -+ struct mt7996_vif *mvif = msta->vif; -+ struct mt7996_sta_link *msta_link; - struct sta_rec_ra_fixed_uni *ra; -+ struct sta_phy_uni *phy = data; -+ struct mt76_vif_link *mlink; - struct sk_buff *skb; -+ int err = -ENODEV; - struct tlv *tlv; - -- skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76, -+ rcu_read_lock(); -+ -+ mlink = rcu_dereference(mvif->mt76.link[link_id]); -+ if (!mlink) -+ goto error_unlock; -+ -+ msta_link = rcu_dereference(msta->link[link_id]); -+ if (!msta_link) -+ goto error_unlock; -+ -+ skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, mlink, - &msta_link->wcid, - MT7996_STA_UPDATE_MAX_SIZE); -- if (IS_ERR(skb)) -- return PTR_ERR(skb); -+ if (IS_ERR(skb)) { -+ err = PTR_ERR(skb); -+ goto error_unlock; -+ } - - tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA_UPDATE, sizeof(*ra)); - ra = (struct sta_rec_ra_fixed_uni *)tlv; -@@ -1935,106 +1945,149 @@ int mt7996_mcu_set_fixed_field(struct mt - if (phy) - ra->phy = *phy; - break; -- case RATE_PARAM_MMPS_UPDATE: -+ case RATE_PARAM_MMPS_UPDATE: { -+ struct ieee80211_sta *sta = wcid_to_sta(&msta_link->wcid); -+ struct ieee80211_link_sta *link_sta; -+ -+ link_sta = rcu_dereference(sta->link[link_id]); -+ if (!link_sta) { -+ dev_kfree_skb(skb); -+ goto error_unlock; -+ } -+ - ra->mmps_mode = mt7996_mcu_get_mmps_mode(link_sta->smps_mode); - break; -+ } - default: - break; - } - ra->field = cpu_to_le32(field); - -+ rcu_read_unlock(); -+ - return mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true); -+error_unlock: -+ rcu_read_unlock(); -+ -+ return err; - } - - static int --mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, -- struct ieee80211_link_sta *link_sta, -- struct mt7996_vif_link *link, -- struct mt7996_sta_link *msta_link) -+mt7996_mcu_add_rate_ctrl_fixed(struct mt7996_dev *dev, struct mt7996_sta *msta, -+ struct ieee80211_vif *vif, u8 link_id) - { -- struct cfg80211_chan_def *chandef = &link->phy->mt76->chandef; -- struct cfg80211_bitrate_mask *mask = &link->bitrate_mask; -- enum nl80211_band band = chandef->chan->band; -+ struct ieee80211_link_sta *link_sta; -+ struct cfg80211_bitrate_mask mask; -+ struct mt7996_sta_link *msta_link; -+ struct mt7996_vif_link *link; - struct sta_phy_uni phy = {}; -- int ret, nrates = 0; -+ struct ieee80211_sta *sta; -+ int ret, nrates = 0, idx; -+ enum nl80211_band band; -+ bool has_he; - - #define __sta_phy_bitrate_mask_check(_mcs, _gi, _ht, _he) \ - do { \ -- u8 i, gi = mask->control[band]._gi; \ -+ u8 i, gi = mask.control[band]._gi; \ - gi = (_he) ? gi : gi == NL80211_TXRATE_FORCE_SGI; \ - phy.sgi = gi; \ -- phy.he_ltf = mask->control[band].he_ltf; \ -- for (i = 0; i < ARRAY_SIZE(mask->control[band]._mcs); i++) { \ -- if (!mask->control[band]._mcs[i]) \ -+ phy.he_ltf = mask.control[band].he_ltf; \ -+ for (i = 0; i < ARRAY_SIZE(mask.control[band]._mcs); i++) { \ -+ if (!mask.control[band]._mcs[i]) \ - continue; \ -- nrates += hweight16(mask->control[band]._mcs[i]); \ -- phy.mcs = ffs(mask->control[band]._mcs[i]) - 1; \ -+ nrates += hweight16(mask.control[band]._mcs[i]); \ -+ phy.mcs = ffs(mask.control[band]._mcs[i]) - 1; \ - if (_ht) \ - phy.mcs += 8 * i; \ - } \ - } while (0) - -- if (link_sta->he_cap.has_he) { -+ rcu_read_lock(); -+ -+ link = mt7996_vif_link(dev, vif, link_id); -+ if (!link) -+ goto error_unlock; -+ -+ msta_link = rcu_dereference(msta->link[link_id]); -+ if (!msta_link) -+ goto error_unlock; -+ -+ sta = wcid_to_sta(&msta_link->wcid); -+ link_sta = rcu_dereference(sta->link[link_id]); -+ if (!link_sta) -+ goto error_unlock; -+ -+ band = link->phy->mt76->chandef.chan->band; -+ has_he = link_sta->he_cap.has_he; -+ mask = link->bitrate_mask; -+ idx = msta_link->wcid.idx; -+ -+ if (has_he) { - __sta_phy_bitrate_mask_check(he_mcs, he_gi, 0, 1); - } else if (link_sta->vht_cap.vht_supported) { - __sta_phy_bitrate_mask_check(vht_mcs, gi, 0, 0); - } else if (link_sta->ht_cap.ht_supported) { - __sta_phy_bitrate_mask_check(ht_mcs, gi, 1, 0); - } else { -- nrates = hweight32(mask->control[band].legacy); -- phy.mcs = ffs(mask->control[band].legacy) - 1; -+ nrates = hweight32(mask.control[band].legacy); -+ phy.mcs = ffs(mask.control[band].legacy) - 1; - } -+ -+ rcu_read_unlock(); -+ - #undef __sta_phy_bitrate_mask_check - - /* fall back to auto rate control */ -- if (mask->control[band].gi == NL80211_TXRATE_DEFAULT_GI && -- mask->control[band].he_gi == GENMASK(7, 0) && -- mask->control[band].he_ltf == GENMASK(7, 0) && -+ if (mask.control[band].gi == NL80211_TXRATE_DEFAULT_GI && -+ mask.control[band].he_gi == GENMASK(7, 0) && -+ mask.control[band].he_ltf == GENMASK(7, 0) && - nrates != 1) - return 0; - - /* fixed single rate */ - if (nrates == 1) { -- ret = mt7996_mcu_set_fixed_field(dev, link_sta, link, -- msta_link, &phy, -+ ret = mt7996_mcu_set_fixed_field(dev, msta, &phy, link_id, - RATE_PARAM_FIXED_MCS); - if (ret) - return ret; - } - - /* fixed GI */ -- if (mask->control[band].gi != NL80211_TXRATE_DEFAULT_GI || -- mask->control[band].he_gi != GENMASK(7, 0)) { -+ if (mask.control[band].gi != NL80211_TXRATE_DEFAULT_GI || -+ mask.control[band].he_gi != GENMASK(7, 0)) { - u32 addr; - - /* firmware updates only TXCMD but doesn't take WTBL into - * account, so driver should update here to reflect the - * actual txrate hardware sends out. - */ -- addr = mt7996_mac_wtbl_lmac_addr(dev, msta_link->wcid.idx, 7); -- if (link_sta->he_cap.has_he) -+ addr = mt7996_mac_wtbl_lmac_addr(dev, idx, 7); -+ if (has_he) - mt76_rmw_field(dev, addr, GENMASK(31, 24), phy.sgi); - else - mt76_rmw_field(dev, addr, GENMASK(15, 12), phy.sgi); - -- ret = mt7996_mcu_set_fixed_field(dev, link_sta, link, -- msta_link, &phy, -+ ret = mt7996_mcu_set_fixed_field(dev, msta, &phy, link_id, - RATE_PARAM_FIXED_GI); - if (ret) - return ret; - } - - /* fixed HE_LTF */ -- if (mask->control[band].he_ltf != GENMASK(7, 0)) { -- ret = mt7996_mcu_set_fixed_field(dev, link_sta, link, -- msta_link, &phy, -+ if (mask.control[band].he_ltf != GENMASK(7, 0)) { -+ ret = mt7996_mcu_set_fixed_field(dev, msta, &phy, link_id, - RATE_PARAM_FIXED_HE_LTF); - if (ret) - return ret; - } - - return 0; -+ -+error_unlock: -+ rcu_read_unlock(); -+ -+ return -ENODEV; - } - - static void -@@ -2145,21 +2198,44 @@ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_b - memset(ra->rx_rcpi, INIT_RCPI, sizeof(ra->rx_rcpi)); - } - --int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, -- struct ieee80211_vif *vif, -- struct ieee80211_bss_conf *link_conf, -- struct ieee80211_link_sta *link_sta, -- struct mt7996_vif_link *link, -- struct mt7996_sta_link *msta_link, bool changed) -+int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct mt7996_sta *msta, -+ struct ieee80211_vif *vif, u8 link_id, -+ bool changed) - { -+ struct ieee80211_bss_conf *link_conf; -+ struct ieee80211_link_sta *link_sta; -+ struct mt7996_sta_link *msta_link; -+ struct mt7996_vif_link *link; -+ struct ieee80211_sta *sta; - struct sk_buff *skb; -- int ret; -+ int ret = -ENODEV; -+ -+ rcu_read_lock(); -+ -+ link = mt7996_vif_link(dev, vif, link_id); -+ if (!link) -+ goto error_unlock; -+ -+ msta_link = rcu_dereference(msta->link[link_id]); -+ if (!msta_link) -+ goto error_unlock; -+ -+ sta = wcid_to_sta(&msta_link->wcid); -+ link_sta = rcu_dereference(sta->link[link_id]); -+ if (!link_sta) -+ goto error_unlock; -+ -+ link_conf = rcu_dereference(vif->link_conf[link_id]); -+ if (!link_conf) -+ goto error_unlock; - - skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76, - &msta_link->wcid, - MT7996_STA_UPDATE_MAX_SIZE); -- if (IS_ERR(skb)) -- return PTR_ERR(skb); -+ if (IS_ERR(skb)) { -+ ret = PTR_ERR(skb); -+ goto error_unlock; -+ } - - /* firmware rc algorithm refers to sta_rec_he for HE control. - * once dev->rc_work changes the settings driver should also -@@ -2173,12 +2249,19 @@ int mt7996_mcu_add_rate_ctrl(struct mt79 - */ - mt7996_mcu_sta_rate_ctrl_tlv(skb, dev, vif, link_conf, link_sta, link); - -+ rcu_read_unlock(); -+ - ret = mt76_mcu_skb_send_msg(&dev->mt76, skb, - MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true); - if (ret) - return ret; - -- return mt7996_mcu_add_rate_ctrl_fixed(dev, link_sta, link, msta_link); -+ return mt7996_mcu_add_rate_ctrl_fixed(dev, msta, vif, link_id); -+ -+error_unlock: -+ rcu_read_unlock(); -+ -+ return ret; - } - - static int -@@ -2243,8 +2326,7 @@ mt7996_mcu_sta_mld_setup_tlv(struct mt79 - - if (nlinks > 1) { - link_id = __ffs(links & ~BIT(msta->deflink_id)); -- msta_link = mt76_dereference(msta->link[msta->deflink_id], -- &dev->mt76); -+ msta_link = mt76_dereference(msta->link[link_id], &dev->mt76); - if (!msta_link) - return; - } -@@ -2673,13 +2755,15 @@ int mt7996_mcu_add_beacon(struct ieee802 - struct ieee80211_bss_conf *link_conf) - { - struct mt7996_dev *dev = mt7996_hw_dev(hw); -- struct mt76_vif_link *mlink = mt76_vif_conf_link(&dev->mt76, vif, link_conf); -+ struct mt7996_vif_link *link = mt7996_vif_conf_link(dev, vif, link_conf); -+ struct mt76_vif_link *mlink = link ? &link->mt76 : NULL; - struct ieee80211_mutable_offsets offs; - struct ieee80211_tx_info *info; - struct sk_buff *skb, *rskb; - struct tlv *tlv; - struct bss_bcn_content_tlv *bcn; - int len, extra_len = 0; -+ bool enabled = link_conf->enable_beacon; - - if (link_conf->nontransmitted) - return 0; -@@ -2687,13 +2771,16 @@ int mt7996_mcu_add_beacon(struct ieee802 - if (!mlink) - return -EINVAL; - -+ if (link->phy && link->phy->mt76->offchannel) -+ enabled = false; -+ - rskb = __mt7996_mcu_alloc_bss_req(&dev->mt76, mlink, - MT7996_MAX_BSS_OFFLOAD_SIZE); - if (IS_ERR(rskb)) - return PTR_ERR(rskb); - - skb = ieee80211_beacon_get_template(hw, vif, &offs, link_conf->link_id); -- if (link_conf->enable_beacon && !skb) { -+ if (enabled && !skb) { - dev_kfree_skb(rskb); - return -EINVAL; - } -@@ -2712,7 +2799,7 @@ int mt7996_mcu_add_beacon(struct ieee802 - len = ALIGN(sizeof(*bcn) + MT_TXD_SIZE + extra_len, 4); - tlv = mt7996_mcu_add_uni_tlv(rskb, UNI_BSS_INFO_BCN_CONTENT, len); - bcn = (struct bss_bcn_content_tlv *)tlv; -- bcn->enable = link_conf->enable_beacon; -+ bcn->enable = enabled; - if (!bcn->enable) - goto out; - -@@ -3290,7 +3377,7 @@ int mt7996_mcu_set_hdr_trans(struct mt79 - { - struct { - u8 __rsv[4]; -- } __packed hdr; -+ } __packed hdr = {}; - struct hdr_trans_blacklist *req_blacklist; - struct hdr_trans_en *req_en; - struct sk_buff *skb; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h 2025-10-22 13:53:56.619168640 -0400 -@@ -620,23 +620,17 @@ int mt7996_mcu_beacon_inband_discov(stru - int mt7996_mcu_add_obss_spr(struct mt7996_phy *phy, - struct mt7996_vif_link *link, - struct ieee80211_he_obss_pd *he_obss_pd); --int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, -- struct ieee80211_vif *vif, -- struct ieee80211_bss_conf *link_conf, -- struct ieee80211_link_sta *link_sta, -- struct mt7996_vif_link *link, -- struct mt7996_sta_link *msta_link, bool changed); -+int mt7996_mcu_add_rate_ctrl(struct mt7996_dev *dev, struct mt7996_sta *msta, -+ struct ieee80211_vif *vif, u8 link_id, -+ bool changed); - int mt7996_set_channel(struct mt76_phy *mphy); - int mt7996_mcu_set_chan_info(struct mt7996_phy *phy, u16 tag); - int mt7996_mcu_set_tx(struct mt7996_dev *dev, struct ieee80211_vif *vif, - struct ieee80211_bss_conf *link_conf); - int mt7996_mcu_set_fixed_rate_ctrl(struct mt7996_dev *dev, - void *data, u16 version); --int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, -- struct ieee80211_link_sta *link_sta, -- struct mt7996_vif_link *link, -- struct mt7996_sta_link *msta_link, -- void *data, u32 field); -+int mt7996_mcu_set_fixed_field(struct mt7996_dev *dev, struct mt7996_sta *msta, -+ void *data, u8 link_id, u32 field); - int mt7996_mcu_set_eeprom(struct mt7996_dev *dev); - int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset, u8 *buf, u32 buf_len); - int mt7996_mcu_get_eeprom_free_block(struct mt7996_dev *dev, u8 *block_num); -@@ -738,6 +732,7 @@ void mt7996_mac_write_txwi(struct mt7996 - struct sk_buff *skb, struct mt76_wcid *wcid, - struct ieee80211_key_conf *key, int pid, - enum mt76_txq_id qid, u32 changed); -+void mt7996_mac_update_beacons(struct mt7996_phy *phy); - void mt7996_mac_set_coverage_class(struct mt7996_phy *phy); - void mt7996_mac_work(struct work_struct *work); - void mt7996_mac_reset_work(struct work_struct *work); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/tx.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/tx.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/tx.c 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/tx.c 2025-10-22 13:53:56.619168640 -0400 -@@ -64,7 +64,7 @@ mt76_tx_status_unlock(struct mt76_dev *d - struct mt76_tx_cb *cb = mt76_tx_skb_cb(skb); - struct mt76_wcid *wcid; - -- wcid = rcu_dereference(dev->wcid[cb->wcid]); -+ wcid = __mt76_wcid_ptr(dev, cb->wcid); - if (wcid) { - status.sta = wcid_to_sta(wcid); - if (status.sta && (wcid->rate.flags || wcid->rate.legacy)) { -@@ -251,9 +251,7 @@ void __mt76_tx_complete_skb(struct mt76_ - - rcu_read_lock(); - -- if (wcid_idx < ARRAY_SIZE(dev->wcid)) -- wcid = rcu_dereference(dev->wcid[wcid_idx]); -- -+ wcid = __mt76_wcid_ptr(dev, wcid_idx); - mt76_tx_check_non_aql(dev, wcid, skb); - - #ifdef CONFIG_NL80211_TESTMODE -@@ -334,6 +332,7 @@ mt76_tx(struct mt76_phy *phy, struct iee - struct mt76_wcid *wcid, struct sk_buff *skb) - { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -+ struct ieee80211_hdr *hdr = (void *)skb->data; - struct sk_buff_head *head; - - if (mt76_testmode_enabled(phy)) { -@@ -351,7 +350,8 @@ mt76_tx(struct mt76_phy *phy, struct iee - info->hw_queue |= FIELD_PREP(MT_TX_HW_QUEUE_PHY, phy->band_idx); - - if ((info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) || -- (info->control.flags & IEEE80211_TX_CTRL_DONT_USE_RATE_MASK)) -+ ((info->control.flags & IEEE80211_TX_CTRL_DONT_USE_RATE_MASK) && -+ ieee80211_is_probe_req(hdr->frame_control))) - head = &wcid->tx_offchannel; - else - head = &wcid->tx_pending; -@@ -538,7 +538,7 @@ mt76_txq_schedule_list(struct mt76_phy * - break; - - mtxq = (struct mt76_txq *)txq->drv_priv; -- wcid = rcu_dereference(dev->wcid[mtxq->wcid]); -+ wcid = __mt76_wcid_ptr(dev, mtxq->wcid); - if (!wcid || test_bit(MT_WCID_FLAG_PS, &wcid->flags)) - continue; - -@@ -617,7 +617,8 @@ mt76_txq_schedule_pending_wcid(struct mt - if ((dev->drv->drv_flags & MT_DRV_HW_MGMT_TXQ) && - !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) && - !ieee80211_is_data(hdr->frame_control) && -- !ieee80211_is_bufferable_mmpdu(skb)) -+ (!ieee80211_is_bufferable_mmpdu(skb) || -+ ieee80211_is_deauth(hdr->frame_control))) - qid = MT_TXQ_PSD; - - q = phy->q_tx[qid]; -@@ -645,6 +646,7 @@ mt76_txq_schedule_pending_wcid(struct mt - static void mt76_txq_schedule_pending(struct mt76_phy *phy) - { - LIST_HEAD(tx_list); -+ int ret = 0; - - if (list_empty(&phy->tx_list)) - return; -@@ -656,13 +658,13 @@ static void mt76_txq_schedule_pending(st - list_splice_init(&phy->tx_list, &tx_list); - while (!list_empty(&tx_list)) { - struct mt76_wcid *wcid; -- int ret; - - wcid = list_first_entry(&tx_list, struct mt76_wcid, tx_list); - list_del_init(&wcid->tx_list); - - spin_unlock(&phy->tx_lock); -- ret = mt76_txq_schedule_pending_wcid(phy, wcid, &wcid->tx_offchannel); -+ if (ret >= 0) -+ ret = mt76_txq_schedule_pending_wcid(phy, wcid, &wcid->tx_offchannel); - if (ret >= 0 && !phy->offchannel) - ret = mt76_txq_schedule_pending_wcid(phy, wcid, &wcid->tx_pending); - spin_lock(&phy->tx_lock); -@@ -671,9 +673,6 @@ static void mt76_txq_schedule_pending(st - !skb_queue_empty(&wcid->tx_offchannel) && - list_empty(&wcid->tx_list)) - list_add_tail(&wcid->tx_list, &phy->tx_list); -- -- if (ret < 0) -- break; - } - spin_unlock(&phy->tx_lock); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/util.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/util.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/mediatek/mt76/util.c 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/mediatek/mt76/util.c 2025-10-22 13:53:56.619168640 -0400 -@@ -83,7 +83,7 @@ int mt76_get_min_avg_rssi(struct mt76_de - if (!(mask & 1)) - continue; - -- wcid = rcu_dereference(dev->wcid[j]); -+ wcid = __mt76_wcid_ptr(dev, j); - if (!wcid || wcid->phy_idx != phy_idx) - continue; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/microchip/wilc1000/wlan_cfg.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/microchip/wilc1000/wlan_cfg.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/microchip/wilc1000/wlan_cfg.c 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/microchip/wilc1000/wlan_cfg.c 2025-10-22 13:53:56.619168640 -0400 -@@ -41,10 +41,10 @@ static const struct wilc_cfg_word g_cfg_ - }; - - static const struct wilc_cfg_str g_cfg_str[] = { -- {WID_FIRMWARE_VERSION, NULL}, -- {WID_MAC_ADDR, NULL}, -- {WID_ASSOC_RES_INFO, NULL}, -- {WID_NIL, NULL} -+ {WID_FIRMWARE_VERSION, 0, NULL}, -+ {WID_MAC_ADDR, 0, NULL}, -+ {WID_ASSOC_RES_INFO, 0, NULL}, -+ {WID_NIL, 0, NULL} - }; - - #define WILC_RESP_MSG_TYPE_CONFIG_REPLY 'R' -@@ -147,44 +147,58 @@ static void wilc_wlan_parse_response_fra - - switch (FIELD_GET(WILC_WID_TYPE, wid)) { - case WID_CHAR: -+ len = 3; -+ if (len + 2 > size) -+ return; -+ - while (cfg->b[i].id != WID_NIL && cfg->b[i].id != wid) - i++; - - if (cfg->b[i].id == wid) - cfg->b[i].val = info[4]; - -- len = 3; - break; - - case WID_SHORT: -+ len = 4; -+ if (len + 2 > size) -+ return; -+ - while (cfg->hw[i].id != WID_NIL && cfg->hw[i].id != wid) - i++; - - if (cfg->hw[i].id == wid) - cfg->hw[i].val = get_unaligned_le16(&info[4]); - -- len = 4; - break; - - case WID_INT: -+ len = 6; -+ if (len + 2 > size) -+ return; -+ - while (cfg->w[i].id != WID_NIL && cfg->w[i].id != wid) - i++; - - if (cfg->w[i].id == wid) - cfg->w[i].val = get_unaligned_le32(&info[4]); - -- len = 6; - break; - - case WID_STR: -+ len = 2 + get_unaligned_le16(&info[2]); -+ - while (cfg->s[i].id != WID_NIL && cfg->s[i].id != wid) - i++; - -- if (cfg->s[i].id == wid) -+ if (cfg->s[i].id == wid) { -+ if (len > cfg->s[i].len || (len + 2 > size)) -+ return; -+ - memcpy(cfg->s[i].str, &info[2], -- get_unaligned_le16(&info[2]) + 2); -+ len); -+ } - -- len = 2 + get_unaligned_le16(&info[2]); - break; - - default: -@@ -384,12 +398,15 @@ int wilc_wlan_cfg_init(struct wilc *wl) - /* store the string cfg parameters */ - wl->cfg.s[i].id = WID_FIRMWARE_VERSION; - wl->cfg.s[i].str = str_vals->firmware_version; -+ wl->cfg.s[i].len = sizeof(str_vals->firmware_version); - i++; - wl->cfg.s[i].id = WID_MAC_ADDR; - wl->cfg.s[i].str = str_vals->mac_address; -+ wl->cfg.s[i].len = sizeof(str_vals->mac_address); - i++; - wl->cfg.s[i].id = WID_ASSOC_RES_INFO; - wl->cfg.s[i].str = str_vals->assoc_rsp; -+ wl->cfg.s[i].len = sizeof(str_vals->assoc_rsp); - i++; - wl->cfg.s[i].id = WID_NIL; - wl->cfg.s[i].str = NULL; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/microchip/wilc1000/wlan_cfg.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/microchip/wilc1000/wlan_cfg.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/microchip/wilc1000/wlan_cfg.h 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/microchip/wilc1000/wlan_cfg.h 2025-10-22 13:53:56.619168640 -0400 -@@ -24,12 +24,13 @@ struct wilc_cfg_word { - - struct wilc_cfg_str { - u16 id; -+ u16 len; - u8 *str; - }; - - struct wilc_cfg_str_vals { -- u8 mac_address[7]; -- u8 firmware_version[129]; -+ u8 mac_address[8]; -+ u8 firmware_version[130]; - u8 assoc_rsp[WILC_MAX_ASSOC_RESP_FRAME_SIZE]; - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/purelifi/plfxlc/mac.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/purelifi/plfxlc/mac.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/purelifi/plfxlc/mac.c 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/purelifi/plfxlc/mac.c 2025-10-22 13:53:56.619168640 -0400 -@@ -99,11 +99,6 @@ int plfxlc_mac_init_hw(struct ieee80211_ - return r; - } - --void plfxlc_mac_release(struct plfxlc_mac *mac) --{ -- plfxlc_chip_release(&mac->chip); --} -- - int plfxlc_op_start(struct ieee80211_hw *hw) - { - plfxlc_hw_mac(hw)->chip.usb.initialized = 1; -@@ -755,3 +750,9 @@ struct ieee80211_hw *plfxlc_mac_alloc_hw - SET_IEEE80211_DEV(hw, &intf->dev); - return hw; - } -+ -+void plfxlc_mac_release_hw(struct ieee80211_hw *hw) -+{ -+ plfxlc_chip_release(&plfxlc_hw_mac(hw)->chip); -+ ieee80211_free_hw(hw); -+} -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/purelifi/plfxlc/mac.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/purelifi/plfxlc/mac.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/purelifi/plfxlc/mac.h 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/purelifi/plfxlc/mac.h 2025-10-22 13:53:56.619168640 -0400 -@@ -168,7 +168,7 @@ static inline u8 *plfxlc_mac_get_perm_ad - } - - struct ieee80211_hw *plfxlc_mac_alloc_hw(struct usb_interface *intf); --void plfxlc_mac_release(struct plfxlc_mac *mac); -+void plfxlc_mac_release_hw(struct ieee80211_hw *hw); - - int plfxlc_mac_preinit_hw(struct ieee80211_hw *hw, const u8 *hw_address); - int plfxlc_mac_init_hw(struct ieee80211_hw *hw); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/purelifi/plfxlc/usb.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/purelifi/plfxlc/usb.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/purelifi/plfxlc/usb.c 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/purelifi/plfxlc/usb.c 2025-10-22 13:53:56.619168640 -0400 -@@ -604,7 +604,7 @@ static int probe(struct usb_interface *i - r = plfxlc_upload_mac_and_serial(intf, hw_address, serial_number); - if (r) { - dev_err(&intf->dev, "MAC and Serial upload failed (%d)\n", r); -- goto error; -+ goto error_free_hw; - } - - chip->unit_type = STA; -@@ -613,13 +613,13 @@ static int probe(struct usb_interface *i - r = plfxlc_mac_preinit_hw(hw, hw_address); - if (r) { - dev_err(&intf->dev, "Init mac failed (%d)\n", r); -- goto error; -+ goto error_free_hw; - } - - r = ieee80211_register_hw(hw); - if (r) { - dev_err(&intf->dev, "Register device failed (%d)\n", r); -- goto error; -+ goto error_free_hw; - } - - if ((le16_to_cpu(interface_to_usbdev(intf)->descriptor.idVendor) == -@@ -632,7 +632,7 @@ static int probe(struct usb_interface *i - } - if (r != 0) { - dev_err(&intf->dev, "FPGA download failed (%d)\n", r); -- goto error; -+ goto error_unreg_hw; - } - - tx->mac_fifo_full = 0; -@@ -642,21 +642,21 @@ static int probe(struct usb_interface *i - r = plfxlc_usb_init_hw(usb); - if (r < 0) { - dev_err(&intf->dev, "usb_init_hw failed (%d)\n", r); -- goto error; -+ goto error_unreg_hw; - } - - msleep(PLF_MSLEEP_TIME); - r = plfxlc_chip_switch_radio(chip, PLFXLC_RADIO_ON); - if (r < 0) { - dev_dbg(&intf->dev, "chip_switch_radio_on failed (%d)\n", r); -- goto error; -+ goto error_unreg_hw; - } - - msleep(PLF_MSLEEP_TIME); - r = plfxlc_chip_set_rate(chip, 8); - if (r < 0) { - dev_dbg(&intf->dev, "chip_set_rate failed (%d)\n", r); -- goto error; -+ goto error_unreg_hw; - } - - msleep(PLF_MSLEEP_TIME); -@@ -664,7 +664,7 @@ static int probe(struct usb_interface *i - hw_address, ETH_ALEN, USB_REQ_MAC_WR); - if (r < 0) { - dev_dbg(&intf->dev, "MAC_WR failure (%d)\n", r); -- goto error; -+ goto error_unreg_hw; - } - - plfxlc_chip_enable_rxtx(chip); -@@ -691,12 +691,12 @@ static int probe(struct usb_interface *i - plfxlc_mac_init_hw(hw); - usb->initialized = true; - return 0; -+ -+error_unreg_hw: -+ ieee80211_unregister_hw(hw); -+error_free_hw: -+ plfxlc_mac_release_hw(hw); - error: -- if (hw) { -- plfxlc_mac_release(plfxlc_hw_mac(hw)); -- ieee80211_unregister_hw(hw); -- ieee80211_free_hw(hw); -- } - dev_err(&intf->dev, "pureLifi:Device error"); - return r; - } -@@ -730,8 +730,7 @@ static void disconnect(struct usb_interf - */ - usb_reset_device(interface_to_usbdev(intf)); - -- plfxlc_mac_release(mac); -- ieee80211_free_hw(hw); -+ plfxlc_mac_release_hw(hw); - } - - static void plfxlc_usb_resume(struct plfxlc_usb *usb) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c 2025-10-22 13:53:56.619168640 -0400 -@@ -108,7 +108,7 @@ exit_free_device: - } - EXPORT_SYMBOL_GPL(rt2x00soc_probe); - --int rt2x00soc_remove(struct platform_device *pdev) -+void rt2x00soc_remove(struct platform_device *pdev) - { - struct ieee80211_hw *hw = platform_get_drvdata(pdev); - struct rt2x00_dev *rt2x00dev = hw->priv; -@@ -119,8 +119,6 @@ int rt2x00soc_remove(struct platform_dev - rt2x00lib_remove_dev(rt2x00dev); - rt2x00soc_free_reg(rt2x00dev); - ieee80211_free_hw(hw); -- -- return 0; - } - EXPORT_SYMBOL_GPL(rt2x00soc_remove); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/ralink/rt2x00/rt2x00soc.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ralink/rt2x00/rt2x00soc.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/ralink/rt2x00/rt2x00soc.h 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/ralink/rt2x00/rt2x00soc.h 2025-10-22 13:53:56.619168640 -0400 -@@ -17,7 +17,7 @@ - * SoC driver handlers. - */ - int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops); --int rt2x00soc_remove(struct platform_device *pdev); -+void rt2x00soc_remove(struct platform_device *pdev); - #ifdef CONFIG_PM - int rt2x00soc_suspend(struct platform_device *pdev, pm_message_t state); - int rt2x00soc_resume(struct platform_device *pdev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c 2025-10-22 13:53:56.619168640 -0400 -@@ -1041,10 +1041,11 @@ static void rtl8187_stop(struct ieee8021 - rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - -+ usb_kill_anchored_urbs(&priv->anchored); -+ - while ((skb = skb_dequeue(&priv->b_tx_status.queue))) - dev_kfree_skb_any(skb); - -- usb_kill_anchored_urbs(&priv->anchored); - mutex_unlock(&priv->conf_mutex); - - if (!priv->is_rtl8187b) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtl8xxxu/core.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtl8xxxu/core.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtl8xxxu/core.c 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtl8xxxu/core.c 2025-10-22 13:53:56.619168640 -0400 -@@ -6617,7 +6617,7 @@ static int rtl8xxxu_submit_rx_urb(struct - skb_size = fops->rx_agg_buf_size; - skb_size += (rx_desc_sz + sizeof(struct rtl8723au_phy_stats)); - } else { -- skb_size = IEEE80211_MAX_FRAME_LEN; -+ skb_size = IEEE80211_MAX_FRAME_LEN + rx_desc_sz; - } - - skb = __netdev_alloc_skb(NULL, skb_size, GFP_KERNEL); -@@ -8170,8 +8170,6 @@ static const struct usb_device_id dev_ta - .driver_info = (unsigned long)&rtl8192cu_fops}, - {USB_DEVICE_AND_INTERFACE_INFO(0x06f8, 0xe033, 0xff, 0xff, 0xff), - .driver_info = (unsigned long)&rtl8192cu_fops}, --{USB_DEVICE_AND_INTERFACE_INFO(0x07b8, 0x8188, 0xff, 0xff, 0xff), -- .driver_info = (unsigned long)&rtl8192cu_fops}, - {USB_DEVICE_AND_INTERFACE_INFO(0x07b8, 0x8189, 0xff, 0xff, 0xff), - .driver_info = (unsigned long)&rtl8192cu_fops}, - {USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9041, 0xff, 0xff, 0xff), -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtlwifi/pci.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtlwifi/pci.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtlwifi/pci.c 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtlwifi/pci.c 2025-10-22 13:53:56.619168640 -0400 -@@ -572,8 +572,11 @@ remap: - dma_map_single(&rtlpci->pdev->dev, skb_tail_pointer(skb), - rtlpci->rxbuffersize, DMA_FROM_DEVICE); - bufferaddress = *((dma_addr_t *)skb->cb); -- if (dma_mapping_error(&rtlpci->pdev->dev, bufferaddress)) -+ if (dma_mapping_error(&rtlpci->pdev->dev, bufferaddress)) { -+ if (!new_skb) -+ kfree_skb(skb); - return 0; -+ } - rtlpci->rx_ring[rxring_idx].rx_buf[desc_idx] = skb; - if (rtlpriv->use_new_trx_flow) { - /* skb->cb may be 64 bit address */ -@@ -802,13 +805,19 @@ new_trx_end: - skb = new_skb; - no_new: - if (rtlpriv->use_new_trx_flow) { -- _rtl_pci_init_one_rxdesc(hw, skb, (u8 *)buffer_desc, -- rxring_idx, -- rtlpci->rx_ring[rxring_idx].idx); -+ if (!_rtl_pci_init_one_rxdesc(hw, skb, (u8 *)buffer_desc, -+ rxring_idx, -+ rtlpci->rx_ring[rxring_idx].idx)) { -+ if (new_skb) -+ dev_kfree_skb_any(skb); -+ } - } else { -- _rtl_pci_init_one_rxdesc(hw, skb, (u8 *)pdesc, -- rxring_idx, -- rtlpci->rx_ring[rxring_idx].idx); -+ if (!_rtl_pci_init_one_rxdesc(hw, skb, (u8 *)pdesc, -+ rxring_idx, -+ rtlpci->rx_ring[rxring_idx].idx)) { -+ if (new_skb) -+ dev_kfree_skb_any(skb); -+ } - if (rtlpci->rx_ring[rxring_idx].idx == - rtlpci->rxringcount - 1) - rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c 2025-10-22 13:53:56.619168640 -0400 -@@ -291,7 +291,6 @@ static const struct usb_device_id rtl819 - {RTL_USB_DEVICE(0x050d, 0x1102, rtl92cu_hal_cfg)}, /*Belkin - Edimax*/ - {RTL_USB_DEVICE(0x050d, 0x11f2, rtl92cu_hal_cfg)}, /*Belkin - ISY*/ - {RTL_USB_DEVICE(0x06f8, 0xe033, rtl92cu_hal_cfg)}, /*Hercules - Edimax*/ -- {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/ - {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/ - {RTL_USB_DEVICE(0x0846, 0x9041, rtl92cu_hal_cfg)}, /*NetGear WNA1000M*/ - {RTL_USB_DEVICE(0x0846, 0x9043, rtl92cu_hal_cfg)}, /*NG WNA1000Mv2*/ -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw88/main.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw88/main.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw88/main.c 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw88/main.c 2025-10-22 13:53:56.619168640 -0400 -@@ -349,7 +349,7 @@ int rtw_sta_add(struct rtw_dev *rtwdev, - struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; - int i; - -- if (vif->type == NL80211_IFTYPE_STATION) { -+ if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { - si->mac_id = rtwvif->mac_id; - } else { - si->mac_id = rtw_acquire_macid(rtwdev); -@@ -386,7 +386,7 @@ void rtw_sta_remove(struct rtw_dev *rtwd - - cancel_work_sync(&si->rc_work); - -- if (vif->type != NL80211_IFTYPE_STATION) -+ if (vif->type != NL80211_IFTYPE_STATION || sta->tdls) - rtw_release_macid(rtwdev, si->mac_id); - if (fw_exist) - rtw_fw_media_status_report(rtwdev, si->mac_id, false); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/chan.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/chan.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/chan.c 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/chan.c 2025-10-22 13:53:56.619168640 -0400 -@@ -1595,6 +1595,35 @@ static bool rtw89_mcc_duration_decision_ - return false; - } - -+void rtw89_mcc_prepare_done_work(struct wiphy *wiphy, struct wiphy_work *work) -+{ -+ struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, -+ mcc_prepare_done_work.work); -+ -+ lockdep_assert_wiphy(wiphy); -+ -+ ieee80211_wake_queues(rtwdev->hw); -+} -+ -+static void rtw89_mcc_prepare(struct rtw89_dev *rtwdev, bool start) -+{ -+ struct rtw89_mcc_info *mcc = &rtwdev->mcc; -+ struct rtw89_mcc_config *config = &mcc->config; -+ -+ if (start) { -+ ieee80211_stop_queues(rtwdev->hw); -+ -+ wiphy_delayed_work_queue(rtwdev->hw->wiphy, -+ &rtwdev->mcc_prepare_done_work, -+ usecs_to_jiffies(config->prepare_delay)); -+ } else { -+ wiphy_delayed_work_queue(rtwdev->hw->wiphy, -+ &rtwdev->mcc_prepare_done_work, 0); -+ wiphy_delayed_work_flush(rtwdev->hw->wiphy, -+ &rtwdev->mcc_prepare_done_work); -+ } -+} -+ - static int rtw89_mcc_fill_start_tsf(struct rtw89_dev *rtwdev) - { - struct rtw89_mcc_info *mcc = &rtwdev->mcc; -@@ -1630,6 +1659,8 @@ static int rtw89_mcc_fill_start_tsf(stru - - config->start_tsf = start_tsf; - config->start_tsf_in_aux_domain = tsf_aux + start_tsf - tsf; -+ config->prepare_delay = start_tsf - tsf; -+ - return 0; - } - -@@ -2219,6 +2250,8 @@ static int rtw89_mcc_start(struct rtw89_ - rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_START); - - rtw89_mcc_start_beacon_noa(rtwdev); -+ -+ rtw89_mcc_prepare(rtwdev, true); - return 0; - } - -@@ -2307,6 +2340,8 @@ static void rtw89_mcc_stop(struct rtw89_ - rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_STOP); - - rtw89_mcc_stop_beacon_noa(rtwdev); -+ -+ rtw89_mcc_prepare(rtwdev, false); - } - - static int rtw89_mcc_update(struct rtw89_dev *rtwdev) -@@ -2816,6 +2851,9 @@ int rtw89_chanctx_ops_assign_vif(struct - rtwvif_link->chanctx_assigned = true; - cfg->ref_count++; - -+ if (rtwdev->scanning) -+ rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif); -+ - if (list_empty(&rtwvif->mgnt_entry)) - list_add_tail(&rtwvif->mgnt_entry, &mgnt->active_list); - -@@ -2855,6 +2893,9 @@ void rtw89_chanctx_ops_unassign_vif(stru - rtwvif_link->chanctx_assigned = false; - cfg->ref_count--; - -+ if (rtwdev->scanning) -+ rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif); -+ - if (!rtw89_vif_is_active_role(rtwvif)) - list_del_init(&rtwvif->mgnt_entry); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/chan.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/chan.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/chan.h 2025-10-22 13:53:23.399328244 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/chan.h 2025-10-22 13:53:56.623168621 -0400 -@@ -129,6 +129,8 @@ const struct rtw89_chan *__rtw89_mgnt_ch - #define rtw89_mgnt_chan_get(rtwdev, link_index) \ - __rtw89_mgnt_chan_get(rtwdev, __func__, link_index) - -+void rtw89_mcc_prepare_done_work(struct wiphy *wiphy, struct wiphy_work *work); -+ - int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev, - struct ieee80211_chanctx_conf *ctx); - void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev, -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/coex.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/coex.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/coex.c 2025-10-22 13:53:23.403328224 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/coex.c 2025-10-22 13:53:56.623168621 -0400 -@@ -3836,13 +3836,13 @@ void rtw89_btc_set_policy_v1(struct rtw8 - - switch (policy_type) { - case BTC_CXP_OFFE_2GBWISOB: /* for normal-case */ -- _slot_set(btc, CXST_E2G, 0, tbl_w1, SLOT_ISO); -+ _slot_set(btc, CXST_E2G, 5, tbl_w1, SLOT_ISO); - _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, - s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); - _slot_set_dur(btc, CXST_EBT, dur_2); - break; - case BTC_CXP_OFFE_2GISOB: /* for bt no-link */ -- _slot_set(btc, CXST_E2G, 0, cxtbl[1], SLOT_ISO); -+ _slot_set(btc, CXST_E2G, 5, cxtbl[1], SLOT_ISO); - _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, - s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); - _slot_set_dur(btc, CXST_EBT, dur_2); -@@ -3868,15 +3868,15 @@ void rtw89_btc_set_policy_v1(struct rtw8 - break; - case BTC_CXP_OFFE_2GBWMIXB: - if (a2dp->exist) -- _slot_set(btc, CXST_E2G, 0, cxtbl[2], SLOT_MIX); -+ _slot_set(btc, CXST_E2G, 5, cxtbl[2], SLOT_MIX); - else -- _slot_set(btc, CXST_E2G, 0, tbl_w1, SLOT_MIX); -+ _slot_set(btc, CXST_E2G, 5, tbl_w1, SLOT_MIX); - _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur, - s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype); - break; - case BTC_CXP_OFFE_WL: /* for 4-way */ -- _slot_set(btc, CXST_E2G, 0, cxtbl[1], SLOT_MIX); -- _slot_set(btc, CXST_EBT, 0, cxtbl[1], SLOT_MIX); -+ _slot_set(btc, CXST_E2G, 5, cxtbl[1], SLOT_MIX); -+ _slot_set(btc, CXST_EBT, 5, cxtbl[1], SLOT_MIX); - break; - default: - break; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/core.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/core.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/core.c 2025-10-22 13:53:23.403328224 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/core.c 2025-10-22 13:53:56.623168621 -0400 -@@ -1050,6 +1050,14 @@ rtw89_core_tx_update_desc_info(struct rt - } - } - -+static void rtw89_tx_wait_work(struct wiphy *wiphy, struct wiphy_work *work) -+{ -+ struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, -+ tx_wait_work.work); -+ -+ rtw89_tx_wait_list_clear(rtwdev); -+} -+ - void rtw89_core_tx_kick_off(struct rtw89_dev *rtwdev, u8 qsel) - { - u8 ch_dma; -@@ -1067,6 +1075,8 @@ int rtw89_core_tx_kick_off_and_wait(stru - unsigned long time_left; - int ret = 0; - -+ lockdep_assert_wiphy(rtwdev->hw->wiphy); -+ - wait = kzalloc(sizeof(*wait), GFP_KERNEL); - if (!wait) { - rtw89_core_tx_kick_off(rtwdev, qsel); -@@ -1074,18 +1084,23 @@ int rtw89_core_tx_kick_off_and_wait(stru - } - - init_completion(&wait->completion); -+ wait->skb = skb; - rcu_assign_pointer(skb_data->wait, wait); - - rtw89_core_tx_kick_off(rtwdev, qsel); - time_left = wait_for_completion_timeout(&wait->completion, - msecs_to_jiffies(timeout)); -- if (time_left == 0) -- ret = -ETIMEDOUT; -- else if (!wait->tx_done) -- ret = -EAGAIN; - -- rcu_assign_pointer(skb_data->wait, NULL); -- kfree_rcu(wait, rcu_head); -+ if (time_left == 0) { -+ ret = -ETIMEDOUT; -+ list_add_tail(&wait->list, &rtwdev->tx_waits); -+ wiphy_delayed_work_queue(rtwdev->hw->wiphy, &rtwdev->tx_wait_work, -+ RTW89_TX_WAIT_WORK_TIMEOUT); -+ } else { -+ if (!wait->tx_done) -+ ret = -EAGAIN; -+ rtw89_tx_wait_release(wait); -+ } - - return ret; - } -@@ -2158,6 +2173,11 @@ static void rtw89_core_cancel_6ghz_probe - if (rx_status->band != NL80211_BAND_6GHZ) - return; - -+ if (unlikely(!(rtwdev->chip->support_bands & BIT(NL80211_BAND_6GHZ)))) { -+ rtw89_debug(rtwdev, RTW89_DBG_UNEXP, "invalid rx on unsupported 6 GHz\n"); -+ return; -+ } -+ - ssid_ie = cfg80211_find_ie(WLAN_EID_SSID, ies, skb->len); - - list_for_each_entry(info, &pkt_list[NL80211_BAND_6GHZ], list) { -@@ -2834,6 +2854,9 @@ static enum rtw89_ps_mode rtw89_update_p - { - const struct rtw89_chip_info *chip = rtwdev->chip; - -+ if (rtwdev->hci.type != RTW89_HCI_TYPE_PCIE) -+ return RTW89_PS_MODE_NONE; -+ - if (rtw89_disable_ps_mode || !chip->ps_mode_supported || - RTW89_CHK_FW_FEATURE(NO_DEEP_PS, &rtwdev->fw)) - return RTW89_PS_MODE_NONE; -@@ -4802,12 +4825,14 @@ void rtw89_core_stop(struct rtw89_dev *r - wiphy_work_cancel(wiphy, &btc->dhcp_notify_work); - wiphy_work_cancel(wiphy, &btc->icmp_notify_work); - cancel_delayed_work_sync(&rtwdev->txq_reinvoke_work); -+ wiphy_delayed_work_cancel(wiphy, &rtwdev->tx_wait_work); - wiphy_delayed_work_cancel(wiphy, &rtwdev->track_work); - wiphy_delayed_work_cancel(wiphy, &rtwdev->chanctx_work); - wiphy_delayed_work_cancel(wiphy, &rtwdev->coex_act1_work); - wiphy_delayed_work_cancel(wiphy, &rtwdev->coex_bt_devinfo_work); - wiphy_delayed_work_cancel(wiphy, &rtwdev->coex_rfk_chk_work); - wiphy_delayed_work_cancel(wiphy, &rtwdev->cfo_track_work); -+ wiphy_delayed_work_cancel(wiphy, &rtwdev->mcc_prepare_done_work); - cancel_delayed_work_sync(&rtwdev->forbid_ba_work); - wiphy_delayed_work_cancel(wiphy, &rtwdev->antdiv_work); - -@@ -5025,6 +5050,7 @@ int rtw89_core_init(struct rtw89_dev *rt - INIT_LIST_HEAD(&rtwdev->scan_info.pkt_list[band]); - } - INIT_LIST_HEAD(&rtwdev->scan_info.chan_list); -+ INIT_LIST_HEAD(&rtwdev->tx_waits); - INIT_WORK(&rtwdev->ba_work, rtw89_core_ba_work); - INIT_WORK(&rtwdev->txq_work, rtw89_core_txq_work); - INIT_DELAYED_WORK(&rtwdev->txq_reinvoke_work, rtw89_core_txq_reinvoke_work); -@@ -5034,6 +5060,8 @@ int rtw89_core_init(struct rtw89_dev *rt - wiphy_delayed_work_init(&rtwdev->coex_bt_devinfo_work, rtw89_coex_bt_devinfo_work); - wiphy_delayed_work_init(&rtwdev->coex_rfk_chk_work, rtw89_coex_rfk_chk_work); - wiphy_delayed_work_init(&rtwdev->cfo_track_work, rtw89_phy_cfo_track_work); -+ wiphy_delayed_work_init(&rtwdev->mcc_prepare_done_work, rtw89_mcc_prepare_done_work); -+ wiphy_delayed_work_init(&rtwdev->tx_wait_work, rtw89_tx_wait_work); - INIT_DELAYED_WORK(&rtwdev->forbid_ba_work, rtw89_forbid_ba_work); - wiphy_delayed_work_init(&rtwdev->antdiv_work, rtw89_phy_antdiv_work); - rtwdev->txq_wq = alloc_workqueue("rtw89_tx_wq", WQ_UNBOUND | WQ_HIGHPRI, 0); -@@ -5239,7 +5267,8 @@ int rtw89_core_mlsr_switch(struct rtw89_ - if (unlikely(!ieee80211_vif_is_mld(vif))) - return -EOPNOTSUPP; - -- if (unlikely(!(usable_links & BIT(link_id)))) { -+ if (unlikely(link_id >= IEEE80211_MLD_MAX_NUM_LINKS || -+ !(usable_links & BIT(link_id)))) { - rtw89_warn(rtwdev, "%s: link id %u is not usable\n", __func__, - link_id); - return -ENOLINK; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/core.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/core.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/core.h 2025-10-22 13:53:23.403328224 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/core.h 2025-10-22 13:53:56.623168621 -0400 -@@ -3429,9 +3429,12 @@ struct rtw89_phy_rate_pattern { - bool enable; - }; - -+#define RTW89_TX_WAIT_WORK_TIMEOUT msecs_to_jiffies(500) - struct rtw89_tx_wait_info { - struct rcu_head rcu_head; -+ struct list_head list; - struct completion completion; -+ struct sk_buff *skb; - bool tx_done; - }; - -@@ -5728,6 +5731,7 @@ struct rtw89_mcc_config { - struct rtw89_mcc_sync sync; - u64 start_tsf; - u64 start_tsf_in_aux_domain; -+ u64 prepare_delay; - u16 mcc_interval; /* TU */ - u16 beacon_offset; /* TU */ - }; -@@ -5801,6 +5805,9 @@ struct rtw89_dev { - /* used to protect rpwm */ - spinlock_t rpwm_lock; - -+ struct list_head tx_waits; -+ struct wiphy_delayed_work tx_wait_work; -+ - struct rtw89_cam_info cam_info; - - struct sk_buff_head c2h_queue; -@@ -5858,6 +5865,7 @@ struct rtw89_dev { - struct wiphy_delayed_work coex_bt_devinfo_work; - struct wiphy_delayed_work coex_rfk_chk_work; - struct wiphy_delayed_work cfo_track_work; -+ struct wiphy_delayed_work mcc_prepare_done_work; - struct delayed_work forbid_ba_work; - struct wiphy_delayed_work antdiv_work; - struct rtw89_ppdu_sts_info ppdu_sts; -@@ -6054,6 +6062,26 @@ rtw89_assoc_link_rcu_dereference(struct - list_first_entry_or_null(&p->dlink_pool, typeof(*p->links_inst), dlink_schd); \ - }) - -+static inline void rtw89_tx_wait_release(struct rtw89_tx_wait_info *wait) -+{ -+ dev_kfree_skb_any(wait->skb); -+ kfree_rcu(wait, rcu_head); -+} -+ -+static inline void rtw89_tx_wait_list_clear(struct rtw89_dev *rtwdev) -+{ -+ struct rtw89_tx_wait_info *wait, *tmp; -+ -+ lockdep_assert_wiphy(rtwdev->hw->wiphy); -+ -+ list_for_each_entry_safe(wait, tmp, &rtwdev->tx_waits, list) { -+ if (!completion_done(&wait->completion)) -+ continue; -+ list_del(&wait->list); -+ rtw89_tx_wait_release(wait); -+ } -+} -+ - static inline int rtw89_hci_tx_write(struct rtw89_dev *rtwdev, - struct rtw89_core_tx_request *tx_req) - { -@@ -6063,6 +6091,7 @@ static inline int rtw89_hci_tx_write(str - static inline void rtw89_hci_reset(struct rtw89_dev *rtwdev) - { - rtwdev->hci.ops->reset(rtwdev); -+ rtw89_tx_wait_list_clear(rtwdev); - } - - static inline int rtw89_hci_start(struct rtw89_dev *rtwdev) -@@ -7120,11 +7149,12 @@ static inline struct sk_buff *rtw89_allo - return dev_alloc_skb(length); - } - --static inline void rtw89_core_tx_wait_complete(struct rtw89_dev *rtwdev, -+static inline bool rtw89_core_tx_wait_complete(struct rtw89_dev *rtwdev, - struct rtw89_tx_skb_data *skb_data, - bool tx_done) - { - struct rtw89_tx_wait_info *wait; -+ bool ret = false; - - rcu_read_lock(); - -@@ -7132,11 +7162,14 @@ static inline void rtw89_core_tx_wait_co - if (!wait) - goto out; - -+ ret = true; - wait->tx_done = tx_done; -- complete(&wait->completion); -+ /* Don't access skb anymore after completion */ -+ complete_all(&wait->completion); - - out: - rcu_read_unlock(); -+ return ret; - } - - static inline bool rtw89_is_mlo_1_1(struct rtw89_dev *rtwdev) -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/fw.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/fw.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/fw.c 2025-10-22 13:53:23.403328224 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/fw.c 2025-10-22 13:53:56.623168621 -0400 -@@ -838,6 +838,7 @@ static const struct __fw_feat_cfg fw_fea - __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 40, 0, CRASH_TRIGGER), - __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 56, 10, BEACON_FILTER), - __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 80, 0, WOW_REASON_V1), -+ __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 128, 0, BEACON_LOSS_COUNT_V1), - __CFG_FW_FEAT(RTL8922A, ge, 0, 34, 30, 0, CRASH_TRIGGER), - __CFG_FW_FEAT(RTL8922A, ge, 0, 34, 11, 0, MACID_PAUSE_SLEEP), - __CFG_FW_FEAT(RTL8922A, ge, 0, 34, 35, 0, SCAN_OFFLOAD), -@@ -6506,13 +6507,18 @@ static int rtw89_fw_read_c2h_reg(struct - const struct rtw89_chip_info *chip = rtwdev->chip; - struct rtw89_fw_info *fw_info = &rtwdev->fw; - const u32 *c2h_reg = chip->c2h_regs; -- u32 ret; -+ u32 ret, timeout; - u8 i, val; - - info->id = RTW89_FWCMD_C2HREG_FUNC_NULL; - -+ if (rtwdev->hci.type == RTW89_HCI_TYPE_USB) -+ timeout = RTW89_C2H_TIMEOUT_USB; -+ else -+ timeout = RTW89_C2H_TIMEOUT; -+ - ret = read_poll_timeout_atomic(rtw89_read8, val, val, 1, -- RTW89_C2H_TIMEOUT, false, rtwdev, -+ timeout, false, rtwdev, - chip->c2h_ctrl_reg); - if (ret) { - rtw89_warn(rtwdev, "c2h reg timeout\n"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/fw.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/fw.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/fw.h 2025-10-22 13:53:23.403328224 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/fw.h 2025-10-22 13:53:56.623168621 -0400 -@@ -112,6 +112,8 @@ struct rtw89_h2creg_sch_tx_en { - #define RTW89_C2HREG_HDR_LEN 2 - #define RTW89_H2CREG_HDR_LEN 2 - #define RTW89_C2H_TIMEOUT 1000000 -+#define RTW89_C2H_TIMEOUT_USB 4000 -+ - struct rtw89_mac_c2h_info { - u8 id; - u8 content_len; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/mac.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/mac.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/mac.c 2025-10-22 13:53:23.403328224 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/mac.c 2025-10-22 13:53:56.623168621 -0400 -@@ -1441,6 +1441,23 @@ void rtw89_mac_notify_wake(struct rtw89_ - rtw89_mac_send_rpwm(rtwdev, state, true); - } - -+static void rtw89_mac_power_switch_boot_mode(struct rtw89_dev *rtwdev) -+{ -+ u32 boot_mode; -+ -+ if (rtwdev->hci.type != RTW89_HCI_TYPE_USB) -+ return; -+ -+ boot_mode = rtw89_read32_mask(rtwdev, R_AX_GPIO_MUXCFG, B_AX_BOOT_MODE); -+ if (!boot_mode) -+ return; -+ -+ rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFN_ONMAC); -+ rtw89_write32_clr(rtwdev, R_AX_SYS_STATUS1, B_AX_AUTO_WLPON); -+ rtw89_write32_clr(rtwdev, R_AX_GPIO_MUXCFG, B_AX_BOOT_MODE); -+ rtw89_write32_clr(rtwdev, R_AX_RSV_CTRL, B_AX_R_DIS_PRST); -+} -+ - static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on) - { - #define PWR_ACT 1 -@@ -1451,6 +1468,8 @@ static int rtw89_mac_power_switch(struct - int ret; - u8 val; - -+ rtw89_mac_power_switch_boot_mode(rtwdev); -+ - if (on) { - cfg_seq = chip->pwr_on_seq; - cfg_func = chip->ops->pwr_on_func; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/pci.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/pci.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/pci.c 2025-10-22 13:53:23.403328224 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/pci.c 2025-10-22 13:53:56.623168621 -0400 -@@ -464,7 +464,8 @@ static void rtw89_pci_tx_status(struct r - struct rtw89_tx_skb_data *skb_data = RTW89_TX_SKB_CB(skb); - struct ieee80211_tx_info *info; - -- rtw89_core_tx_wait_complete(rtwdev, skb_data, tx_status == RTW89_TX_DONE); -+ if (rtw89_core_tx_wait_complete(rtwdev, skb_data, tx_status == RTW89_TX_DONE)) -+ return; - - info = IEEE80211_SKB_CB(skb); - ieee80211_tx_info_clear_status(info); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/phy.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/phy.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/phy.c 2025-10-22 13:53:23.407328206 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/phy.c 2025-10-22 13:53:56.623168621 -0400 -@@ -119,10 +119,12 @@ static u64 get_eht_mcs_ra_mask(u8 *max_n - return mask; - } - --static u64 get_eht_ra_mask(struct ieee80211_link_sta *link_sta) -+static u64 get_eht_ra_mask(struct rtw89_vif_link *rtwvif_link, -+ struct ieee80211_link_sta *link_sta) - { -- struct ieee80211_sta_eht_cap *eht_cap = &link_sta->eht_cap; -+ struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); - struct ieee80211_eht_mcs_nss_supp_20mhz_only *mcs_nss_20mhz; -+ struct ieee80211_sta_eht_cap *eht_cap = &link_sta->eht_cap; - struct ieee80211_eht_mcs_nss_supp_bw *mcs_nss; - u8 *he_phy_cap = link_sta->he_cap.he_cap_elem.phy_cap_info; - -@@ -136,8 +138,8 @@ static u64 get_eht_ra_mask(struct ieee80 - /* MCS 9, 11, 13 */ - return get_eht_mcs_ra_mask(mcs_nss->rx_tx_max_nss, 9, 3); - case IEEE80211_STA_RX_BW_20: -- if (!(he_phy_cap[0] & -- IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL)) { -+ if (vif->type == NL80211_IFTYPE_AP && -+ !(he_phy_cap[0] & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_MASK_ALL)) { - mcs_nss_20mhz = &eht_cap->eht_mcs_nss_supp.only_20mhz; - /* MCS 7, 9, 11, 13 */ - return get_eht_mcs_ra_mask(mcs_nss_20mhz->rx_tx_max_nss, 7, 4); -@@ -332,7 +334,7 @@ static void rtw89_phy_ra_sta_update(stru - /* Set the ra mask from sta's capability */ - if (link_sta->eht_cap.has_eht) { - mode |= RTW89_RA_MODE_EHT; -- ra_mask |= get_eht_ra_mask(link_sta); -+ ra_mask |= get_eht_ra_mask(rtwvif_link, link_sta); - - if (rtwdev->hal.no_mcs_12_13) - high_rate_masks = rtw89_ra_mask_eht_mcs0_11; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/reg.h BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/reg.h ---- BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/reg.h 2025-10-22 13:53:23.407328206 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/reg.h 2025-10-22 13:53:56.627168602 -0400 -@@ -182,6 +182,7 @@ - - #define R_AX_SYS_STATUS1 0x00F4 - #define B_AX_SEL_0XC0_MASK GENMASK(17, 16) -+#define B_AX_AUTO_WLPON BIT(10) - #define B_AX_PAD_HCI_SEL_V2_MASK GENMASK(5, 3) - #define MAC_AX_HCI_SEL_SDIO_UART 0 - #define MAC_AX_HCI_SEL_MULTI_USB 1 -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/sar.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/sar.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/sar.c 2025-10-22 13:53:23.407328206 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/sar.c 2025-10-22 13:53:56.627168602 -0400 -@@ -199,7 +199,8 @@ struct rtw89_sar_handler rtw89_sar_handl - typeof(_dev) _d = (_dev); \ - BUILD_BUG_ON(!rtw89_sar_handlers[_s].descr_sar_source); \ - BUILD_BUG_ON(!rtw89_sar_handlers[_s].query_sar_config); \ -- lockdep_assert_wiphy(_d->hw->wiphy); \ -+ if (test_bit(RTW89_FLAG_PROBE_DONE, _d->flags)) \ -+ lockdep_assert_wiphy(_d->hw->wiphy); \ - _d->sar._cfg_name = *(_cfg_data); \ - _d->sar.src = _s; \ - } while (0) -@@ -499,8 +500,6 @@ static void rtw89_set_sar_from_acpi(stru - struct rtw89_sar_cfg_acpi *cfg; - int ret; - -- lockdep_assert_wiphy(rtwdev->hw->wiphy); -- - cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); - if (!cfg) - return; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/ser.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/ser.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/ser.c 2025-10-22 13:53:23.407328206 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/ser.c 2025-10-22 13:53:56.627168602 -0400 -@@ -501,7 +501,9 @@ static void ser_reset_trx_st_hdl(struct - } - - drv_stop_rx(ser); -+ wiphy_lock(wiphy); - drv_trx_reset(ser); -+ wiphy_unlock(wiphy); - - /* wait m3 */ - hal_send_m2_event(ser); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/wow.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/wow.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/realtek/rtw89/wow.c 2025-10-22 13:53:23.407328206 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/realtek/rtw89/wow.c 2025-10-22 13:53:56.627168602 -0400 -@@ -1412,6 +1412,8 @@ static void rtw89_fw_release_pno_pkt_lis - static int rtw89_pno_scan_update_probe_req(struct rtw89_dev *rtwdev, - struct rtw89_vif_link *rtwvif_link) - { -+ static const u8 basic_rate_ie[] = {WLAN_EID_SUPP_RATES, 0x08, -+ 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c}; - struct rtw89_wow_param *rtw_wow = &rtwdev->wow; - struct cfg80211_sched_scan_request *nd_config = rtw_wow->nd_config; - u8 num = nd_config->n_match_sets, i; -@@ -1423,10 +1425,11 @@ static int rtw89_pno_scan_update_probe_r - skb = ieee80211_probereq_get(rtwdev->hw, rtwvif_link->mac_addr, - nd_config->match_sets[i].ssid.ssid, - nd_config->match_sets[i].ssid.ssid_len, -- nd_config->ie_len); -+ nd_config->ie_len + sizeof(basic_rate_ie)); - if (!skb) - return -ENOMEM; - -+ skb_put_data(skb, basic_rate_ie, sizeof(basic_rate_ie)); - skb_put_data(skb, nd_config->ie, nd_config->ie_len); - - info = kzalloc(sizeof(*info), GFP_KERNEL); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/st/cw1200/sta.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/st/cw1200/sta.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/st/cw1200/sta.c 2025-10-22 13:53:23.407328206 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/st/cw1200/sta.c 2025-10-22 13:53:56.627168602 -0400 -@@ -1290,7 +1290,7 @@ static void cw1200_do_join(struct cw1200 - rcu_read_lock(); - ssidie = ieee80211_bss_get_ie(bss, WLAN_EID_SSID); - if (ssidie) { -- join.ssid_len = ssidie[1]; -+ join.ssid_len = min(ssidie[1], IEEE80211_MAX_SSID_LEN); - memcpy(join.ssid, &ssidie[2], join.ssid_len); - } - rcu_read_unlock(); -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/virtual/virt_wifi.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/virtual/virt_wifi.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/virtual/virt_wifi.c 2025-10-22 13:53:23.407328206 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/virtual/virt_wifi.c 2025-10-22 13:53:56.627168602 -0400 -@@ -277,7 +277,9 @@ static void virt_wifi_connect_complete(s - priv->is_connected = true; - - /* Schedules an event that acquires the rtnl lock. */ -- cfg80211_connect_result(priv->upperdev, requested_bss, NULL, 0, NULL, 0, -+ cfg80211_connect_result(priv->upperdev, -+ priv->is_connected ? fake_router_bssid : NULL, -+ NULL, 0, NULL, 0, - status, GFP_KERNEL); - netif_carrier_on(priv->upperdev); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/wireless/zydas/zd1211rw/zd_mac.c BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/zydas/zd1211rw/zd_mac.c ---- BPI-Router-Linux-kernel/drivers/net/wireless/zydas/zd1211rw/zd_mac.c 2025-10-22 13:53:23.407328206 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/wireless/zydas/zd1211rw/zd_mac.c 2025-10-22 13:53:56.627168602 -0400 -@@ -583,7 +583,11 @@ void zd_mac_tx_to_dev(struct sk_buff *sk - - skb_queue_tail(q, skb); - while (skb_queue_len(q) > ZD_MAC_MAX_ACK_WAITERS) { -- zd_mac_tx_status(hw, skb_dequeue(q), -+ skb = skb_dequeue(q); -+ if (!skb) -+ break; -+ -+ zd_mac_tx_status(hw, skb, - mac->ack_pending ? mac->ack_signal : 0, - NULL); - mac->ack_pending = 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/net/xen-netfront.c BPI-Router-Linux-kernel-6.16.12/drivers/net/xen-netfront.c ---- BPI-Router-Linux-kernel/drivers/net/xen-netfront.c 2025-10-22 13:53:23.407328206 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/net/xen-netfront.c 2025-10-22 13:53:56.627168602 -0400 -@@ -638,8 +638,6 @@ static int xennet_xdp_xmit_one(struct ne - tx_stats->packets++; - u64_stats_update_end(&tx_stats->syncp); - -- xennet_tx_buf_gc(queue); -- - return 0; - } - -@@ -849,9 +847,6 @@ static netdev_tx_t xennet_start_xmit(str - tx_stats->packets++; - u64_stats_update_end(&tx_stats->syncp); - -- /* Note: It is not safe to access skb after xennet_tx_buf_gc()! */ -- xennet_tx_buf_gc(queue); -- - if (!netfront_tx_slot_available(queue)) - netif_tx_stop_queue(netdev_get_tx_queue(dev, queue->id)); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/nvme/host/core.c BPI-Router-Linux-kernel-6.16.12/drivers/nvme/host/core.c ---- BPI-Router-Linux-kernel/drivers/nvme/host/core.c 2025-10-22 13:53:23.407328206 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/nvme/host/core.c 2025-10-22 13:53:56.627168602 -0400 -@@ -381,12 +381,12 @@ static void nvme_log_err_passthru(struct - nr->status & NVME_SC_MASK, /* Status Code */ - nr->status & NVME_STATUS_MORE ? "MORE " : "", - nr->status & NVME_STATUS_DNR ? "DNR " : "", -- nr->cmd->common.cdw10, -- nr->cmd->common.cdw11, -- nr->cmd->common.cdw12, -- nr->cmd->common.cdw13, -- nr->cmd->common.cdw14, -- nr->cmd->common.cdw14); -+ le32_to_cpu(nr->cmd->common.cdw10), -+ le32_to_cpu(nr->cmd->common.cdw11), -+ le32_to_cpu(nr->cmd->common.cdw12), -+ le32_to_cpu(nr->cmd->common.cdw13), -+ le32_to_cpu(nr->cmd->common.cdw14), -+ le32_to_cpu(nr->cmd->common.cdw15)); - } - - enum nvme_disposition { -@@ -764,6 +764,10 @@ blk_status_t nvme_fail_nonready_command( - !test_bit(NVME_CTRL_FAILFAST_EXPIRED, &ctrl->flags) && - !blk_noretry_request(rq) && !(rq->cmd_flags & REQ_NVME_MPATH)) - return BLK_STS_RESOURCE; -+ -+ if (!(rq->rq_flags & RQF_DONTPREP)) -+ nvme_clear_nvme_request(rq); -+ - return nvme_host_path_error(rq); - } - EXPORT_SYMBOL_GPL(nvme_fail_nonready_command); -@@ -899,6 +903,15 @@ static void nvme_set_ref_tag(struct nvme - u32 upper, lower; - u64 ref48; - -+ /* only type1 and type 2 PI formats have a reftag */ -+ switch (ns->head->pi_type) { -+ case NVME_NS_DPS_PI_TYPE1: -+ case NVME_NS_DPS_PI_TYPE2: -+ break; -+ default: -+ return; -+ } -+ - /* both rw and write zeroes share the same reftag format */ - switch (ns->head->guard_type) { - case NVME_NVM_NS_16B_GUARD: -@@ -938,13 +951,7 @@ static inline blk_status_t nvme_setup_wr - - if (nvme_ns_has_pi(ns->head)) { - cmnd->write_zeroes.control |= cpu_to_le16(NVME_RW_PRINFO_PRACT); -- -- switch (ns->head->pi_type) { -- case NVME_NS_DPS_PI_TYPE1: -- case NVME_NS_DPS_PI_TYPE2: -- nvme_set_ref_tag(ns, cmnd, req); -- break; -- } -+ nvme_set_ref_tag(ns, cmnd, req); - } - - return BLK_STS_OK; -@@ -1035,6 +1042,7 @@ static inline blk_status_t nvme_setup_rw - if (WARN_ON_ONCE(!nvme_ns_has_pi(ns->head))) - return BLK_STS_NOTSUPP; - control |= NVME_RW_PRINFO_PRACT; -+ nvme_set_ref_tag(ns, cmnd, req); - } - - if (bio_integrity_flagged(req->bio, BIP_CHECK_GUARD)) -@@ -2015,21 +2023,41 @@ static void nvme_configure_metadata(stru - } - - --static void nvme_update_atomic_write_disk_info(struct nvme_ns *ns, -- struct nvme_id_ns *id, struct queue_limits *lim, -- u32 bs, u32 atomic_bs) -+static u32 nvme_configure_atomic_write(struct nvme_ns *ns, -+ struct nvme_id_ns *id, struct queue_limits *lim, u32 bs) - { -- unsigned int boundary = 0; -+ u32 atomic_bs, boundary = 0; -+ -+ /* -+ * We do not support an offset for the atomic boundaries. -+ */ -+ if (id->nabo) -+ return bs; - -- if (id->nsfeat & NVME_NS_FEAT_ATOMICS && id->nawupf) { -- if (le16_to_cpu(id->nabspf)) -+ if ((id->nsfeat & NVME_NS_FEAT_ATOMICS) && id->nawupf) { -+ /* -+ * Use the per-namespace atomic write unit when available. -+ */ -+ atomic_bs = (1 + le16_to_cpu(id->nawupf)) * bs; -+ if (id->nabspf) - boundary = (le16_to_cpu(id->nabspf) + 1) * bs; -+ } else { -+ /* -+ * Use the controller wide atomic write unit. This sucks -+ * because the limit is defined in terms of logical blocks while -+ * namespaces can have different formats, and because there is -+ * no clear language in the specification prohibiting different -+ * values for different controllers in the subsystem. -+ */ -+ atomic_bs = (1 + ns->ctrl->subsys->awupf) * bs; - } -+ - lim->atomic_write_hw_max = atomic_bs; - lim->atomic_write_hw_boundary = boundary; - lim->atomic_write_hw_unit_min = bs; - lim->atomic_write_hw_unit_max = rounddown_pow_of_two(atomic_bs); - lim->features |= BLK_FEAT_ATOMIC_WRITES; -+ return atomic_bs; - } - - static u32 nvme_max_drv_segments(struct nvme_ctrl *ctrl) -@@ -2067,34 +2095,8 @@ static bool nvme_update_disk_info(struct - valid = false; - } - -- atomic_bs = phys_bs = bs; -- if (id->nabo == 0) { -- /* -- * Bit 1 indicates whether NAWUPF is defined for this namespace -- * and whether it should be used instead of AWUPF. If NAWUPF == -- * 0 then AWUPF must be used instead. -- */ -- if (id->nsfeat & NVME_NS_FEAT_ATOMICS && id->nawupf) -- atomic_bs = (1 + le16_to_cpu(id->nawupf)) * bs; -- else -- atomic_bs = (1 + ns->ctrl->awupf) * bs; -- -- /* -- * Set subsystem atomic bs. -- */ -- if (ns->ctrl->subsys->atomic_bs) { -- if (atomic_bs != ns->ctrl->subsys->atomic_bs) { -- dev_err_ratelimited(ns->ctrl->device, -- "%s: Inconsistent Atomic Write Size, Namespace will not be added: Subsystem=%d bytes, Controller/Namespace=%d bytes\n", -- ns->disk ? ns->disk->disk_name : "?", -- ns->ctrl->subsys->atomic_bs, -- atomic_bs); -- } -- } else -- ns->ctrl->subsys->atomic_bs = atomic_bs; -- -- nvme_update_atomic_write_disk_info(ns, id, lim, bs, atomic_bs); -- } -+ phys_bs = bs; -+ atomic_bs = nvme_configure_atomic_write(ns, id, lim, bs); - - if (id->nsfeat & NVME_NS_FEAT_IO_OPT) { - /* NPWG = Namespace Preferred Write Granularity */ -@@ -2382,16 +2384,6 @@ static int nvme_update_ns_info_block(str - if (!nvme_update_disk_info(ns, id, &lim)) - capacity = 0; - -- /* -- * Validate the max atomic write size fits within the subsystem's -- * atomic write capabilities. -- */ -- if (lim.atomic_write_hw_max > ns->ctrl->subsys->atomic_bs) { -- blk_mq_unfreeze_queue(ns->disk->queue, memflags); -- ret = -ENXIO; -- goto out; -- } -- - nvme_config_discard(ns, &lim); - if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) && - ns->head->ids.csi == NVME_CSI_ZNS) -@@ -3215,6 +3207,7 @@ static int nvme_init_subsystem(struct nv - memcpy(subsys->model, id->mn, sizeof(subsys->model)); - subsys->vendor_id = le16_to_cpu(id->vid); - subsys->cmic = id->cmic; -+ subsys->awupf = le16_to_cpu(id->awupf); - - /* Versions prior to 1.4 don't necessarily report a valid type */ - if (id->cntrltype == NVME_CTRL_DISC || -@@ -3647,7 +3640,6 @@ static int nvme_init_identify(struct nvm - dev_pm_qos_expose_latency_tolerance(ctrl->device); - else if (!ctrl->apst_enabled && prev_apst_enabled) - dev_pm_qos_hide_latency_tolerance(ctrl->device); -- ctrl->awupf = le16_to_cpu(id->awupf); - out_free: - kfree(id); - return ret; -@@ -4036,6 +4028,10 @@ static int nvme_init_ns_head(struct nvme - list_add_tail_rcu(&ns->siblings, &head->list); - ns->head = head; - mutex_unlock(&ctrl->subsys->lock); -+ -+#ifdef CONFIG_NVME_MULTIPATH -+ cancel_delayed_work(&head->remove_work); -+#endif - return 0; - - out_put_ns_head: -@@ -4080,7 +4076,7 @@ static void nvme_ns_add_to_ctrl_list(str - return; - } - } -- list_add(&ns->list, &ns->ctrl->namespaces); -+ list_add_rcu(&ns->list, &ns->ctrl->namespaces); - } - - static void nvme_alloc_ns(struct nvme_ctrl *ctrl, struct nvme_ns_info *info) -@@ -4089,6 +4085,7 @@ static void nvme_alloc_ns(struct nvme_ct - struct nvme_ns *ns; - struct gendisk *disk; - int node = ctrl->numa_node; -+ bool last_path = false; - - ns = kzalloc_node(sizeof(*ns), GFP_KERNEL, node); - if (!ns) -@@ -4181,9 +4178,22 @@ static void nvme_alloc_ns(struct nvme_ct - out_unlink_ns: - mutex_lock(&ctrl->subsys->lock); - list_del_rcu(&ns->siblings); -- if (list_empty(&ns->head->list)) -+ if (list_empty(&ns->head->list)) { - list_del_init(&ns->head->entry); -+ /* -+ * If multipath is not configured, we still create a namespace -+ * head (nshead), but head->disk is not initialized in that -+ * case. As a result, only a single reference to nshead is held -+ * (via kref_init()) when it is created. Therefore, ensure that -+ * we do not release the reference to nshead twice if head->disk -+ * is not present. -+ */ -+ if (ns->head->disk) -+ last_path = true; -+ } - mutex_unlock(&ctrl->subsys->lock); -+ if (last_path) -+ nvme_put_ns_head(ns->head); - nvme_put_ns_head(ns->head); - out_cleanup_disk: - put_disk(disk); -diff -purNx .git BPI-Router-Linux-kernel/drivers/nvme/host/ioctl.c BPI-Router-Linux-kernel-6.16.12/drivers/nvme/host/ioctl.c ---- BPI-Router-Linux-kernel/drivers/nvme/host/ioctl.c 2025-10-22 13:53:23.407328206 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/nvme/host/ioctl.c 2025-10-22 13:53:56.627168602 -0400 -@@ -429,21 +429,14 @@ static enum rq_end_io_ret nvme_uring_cmd - pdu->result = le64_to_cpu(nvme_req(req)->result.u64); - - /* -- * For iopoll, complete it directly. Note that using the uring_cmd -- * helper for this is safe only because we check blk_rq_is_poll(). -- * As that returns false if we're NOT on a polled queue, then it's -- * safe to use the polled completion helper. -- * -- * Otherwise, move the completion to task work. -+ * IOPOLL could potentially complete this request directly, but -+ * if multiple rings are polling on the same queue, then it's possible -+ * for one ring to find completions for another ring. Punting the -+ * completion via task_work will always direct it to the right -+ * location, rather than potentially complete requests for ringA -+ * under iopoll invocations from ringB. - */ -- if (blk_rq_is_poll(req)) { -- if (pdu->bio) -- blk_rq_unmap_user(pdu->bio); -- io_uring_cmd_iopoll_done(ioucmd, pdu->result, pdu->status); -- } else { -- io_uring_cmd_do_in_task_lazy(ioucmd, nvme_uring_task_cb); -- } -- -+ io_uring_cmd_do_in_task_lazy(ioucmd, nvme_uring_task_cb); - return RQ_END_IO_FREE; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/nvme/host/multipath.c BPI-Router-Linux-kernel-6.16.12/drivers/nvme/host/multipath.c ---- BPI-Router-Linux-kernel/drivers/nvme/host/multipath.c 2025-10-22 13:53:23.411328187 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/nvme/host/multipath.c 2025-10-22 13:53:56.627168602 -0400 -@@ -690,8 +690,8 @@ static void nvme_remove_head(struct nvme - nvme_cdev_del(&head->cdev, &head->cdev_device); - synchronize_srcu(&head->srcu); - del_gendisk(head->disk); -- nvme_put_ns_head(head); - } -+ nvme_put_ns_head(head); - } - - static void nvme_remove_head_work(struct work_struct *work) -@@ -1200,7 +1200,8 @@ void nvme_mpath_add_sysfs_link(struct nv - */ - srcu_idx = srcu_read_lock(&head->srcu); - -- list_for_each_entry_rcu(ns, &head->list, siblings) { -+ list_for_each_entry_srcu(ns, &head->list, siblings, -+ srcu_read_lock_held(&head->srcu)) { - /* - * Ensure that ns path disk node is already added otherwise we - * may get invalid kobj name for target -@@ -1291,6 +1292,9 @@ void nvme_mpath_remove_disk(struct nvme_ - { - bool remove = false; - -+ if (!head->disk) -+ return; -+ - mutex_lock(&head->subsys->lock); - /* - * We are called when all paths have been removed, and at that point -@@ -1311,7 +1315,7 @@ void nvme_mpath_remove_disk(struct nvme_ - */ - if (!try_module_get(THIS_MODULE)) - goto out; -- queue_delayed_work(nvme_wq, &head->remove_work, -+ mod_delayed_work(nvme_wq, &head->remove_work, - head->delayed_removal_secs * HZ); - } else { - list_del_init(&head->entry); -diff -purNx .git BPI-Router-Linux-kernel/drivers/nvme/host/nvme.h BPI-Router-Linux-kernel-6.16.12/drivers/nvme/host/nvme.h ---- BPI-Router-Linux-kernel/drivers/nvme/host/nvme.h 2025-10-22 13:53:23.411328187 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/nvme/host/nvme.h 2025-10-22 13:53:56.627168602 -0400 -@@ -410,7 +410,6 @@ struct nvme_ctrl { - - enum nvme_ctrl_type cntrltype; - enum nvme_dctype dctype; -- u16 awupf; /* 0's based value. */ - }; - - static inline enum nvme_ctrl_state nvme_ctrl_state(struct nvme_ctrl *ctrl) -@@ -443,11 +442,11 @@ struct nvme_subsystem { - u8 cmic; - enum nvme_subsys_type subtype; - u16 vendor_id; -+ u16 awupf; /* 0's based value. */ - struct ida ns_ida; - #ifdef CONFIG_NVME_MULTIPATH - enum nvme_iopolicy iopolicy; - #endif -- u32 atomic_bs; - }; - - /* -diff -purNx .git BPI-Router-Linux-kernel/drivers/nvme/host/pci.c BPI-Router-Linux-kernel-6.16.12/drivers/nvme/host/pci.c ---- BPI-Router-Linux-kernel/drivers/nvme/host/pci.c 2025-10-22 13:53:23.411328187 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/nvme/host/pci.c 2025-10-22 13:53:56.627168602 -0400 -@@ -1958,8 +1958,28 @@ static int nvme_pci_configure_admin_queu - * might be pointing at! - */ - result = nvme_disable_ctrl(&dev->ctrl, false); -- if (result < 0) -- return result; -+ if (result < 0) { -+ struct pci_dev *pdev = to_pci_dev(dev->dev); -+ -+ /* -+ * The NVMe Controller Reset method did not get an expected -+ * CSTS.RDY transition, so something with the device appears to -+ * be stuck. Use the lower level and bigger hammer PCIe -+ * Function Level Reset to attempt restoring the device to its -+ * initial state, and try again. -+ */ -+ result = pcie_reset_flr(pdev, false); -+ if (result < 0) -+ return result; -+ -+ pci_restore_state(pdev); -+ result = nvme_disable_ctrl(&dev->ctrl, false); -+ if (result < 0) -+ return result; -+ -+ dev_info(dev->ctrl.device, -+ "controller reset completed after pcie flr\n"); -+ } - - result = nvme_alloc_queue(dev, 0, NVME_AQ_DEPTH); - if (result) -@@ -2101,8 +2121,6 @@ static void nvme_map_cmb(struct nvme_dev - if ((dev->cmbsz & (NVME_CMBSZ_WDS | NVME_CMBSZ_RDS)) == - (NVME_CMBSZ_WDS | NVME_CMBSZ_RDS)) - pci_p2pmem_publish(pdev, true); -- -- nvme_update_attrs(dev); - } - - static int nvme_set_host_mem(struct nvme_dev *dev, u32 bits) -@@ -3010,6 +3028,8 @@ static void nvme_reset_work(struct work_ - if (result < 0) - goto out; - -+ nvme_update_attrs(dev); -+ - result = nvme_setup_io_queues(dev); - if (result) - goto out; -@@ -3343,6 +3363,8 @@ static int nvme_probe(struct pci_dev *pd - if (result < 0) - goto out_disable; - -+ nvme_update_attrs(dev); -+ - result = nvme_setup_io_queues(dev); - if (result) - goto out_disable; -diff -purNx .git BPI-Router-Linux-kernel/drivers/nvme/host/tcp.c BPI-Router-Linux-kernel-6.16.12/drivers/nvme/host/tcp.c ---- BPI-Router-Linux-kernel/drivers/nvme/host/tcp.c 2025-10-22 13:53:23.411328187 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/nvme/host/tcp.c 2025-10-22 13:53:56.627168602 -0400 -@@ -1745,9 +1745,14 @@ static int nvme_tcp_start_tls(struct nvm - qid, ret); - tls_handshake_cancel(queue->sock->sk); - } else { -- dev_dbg(nctrl->device, -- "queue %d: TLS handshake complete, error %d\n", -- qid, queue->tls_err); -+ if (queue->tls_err) { -+ dev_err(nctrl->device, -+ "queue %d: TLS handshake complete, error %d\n", -+ qid, queue->tls_err); -+ } else { -+ dev_dbg(nctrl->device, -+ "queue %d: TLS handshake complete\n", qid); -+ } - ret = queue->tls_err; - } - return ret; -diff -purNx .git BPI-Router-Linux-kernel/drivers/nvme/target/core.c BPI-Router-Linux-kernel-6.16.12/drivers/nvme/target/core.c ---- BPI-Router-Linux-kernel/drivers/nvme/target/core.c 2025-10-22 13:53:23.411328187 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/nvme/target/core.c 2025-10-22 13:53:56.627168602 -0400 -@@ -1962,24 +1962,24 @@ static int __init nvmet_init(void) - if (!nvmet_wq) - goto out_free_buffered_work_queue; - -- error = nvmet_init_discovery(); -+ error = nvmet_init_debugfs(); - if (error) - goto out_free_nvmet_work_queue; - -- error = nvmet_init_debugfs(); -+ error = nvmet_init_discovery(); - if (error) -- goto out_exit_discovery; -+ goto out_exit_debugfs; - - error = nvmet_init_configfs(); - if (error) -- goto out_exit_debugfs; -+ goto out_exit_discovery; - - return 0; - --out_exit_debugfs: -- nvmet_exit_debugfs(); - out_exit_discovery: - nvmet_exit_discovery(); -+out_exit_debugfs: -+ nvmet_exit_debugfs(); - out_free_nvmet_work_queue: - destroy_workqueue(nvmet_wq); - out_free_buffered_work_queue: -@@ -1994,8 +1994,8 @@ out_destroy_bvec_cache: - static void __exit nvmet_exit(void) - { - nvmet_exit_configfs(); -- nvmet_exit_debugfs(); - nvmet_exit_discovery(); -+ nvmet_exit_debugfs(); - ida_destroy(&cntlid_ida); - destroy_workqueue(nvmet_wq); - destroy_workqueue(buffered_io_wq); -diff -purNx .git BPI-Router-Linux-kernel/drivers/nvme/target/nvmet.h BPI-Router-Linux-kernel-6.16.12/drivers/nvme/target/nvmet.h ---- BPI-Router-Linux-kernel/drivers/nvme/target/nvmet.h 2025-10-22 13:53:23.411328187 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/nvme/target/nvmet.h 2025-10-22 13:53:56.627168602 -0400 -@@ -867,6 +867,8 @@ static inline void nvmet_req_bio_put(str - { - if (bio != &req->b.inline_bio) - bio_put(bio); -+ else -+ bio_uninit(bio); - } - - #ifdef CONFIG_NVME_TARGET_TCP_TLS -diff -purNx .git BPI-Router-Linux-kernel/drivers/nvme/target/pci-epf.c BPI-Router-Linux-kernel-6.16.12/drivers/nvme/target/pci-epf.c ---- BPI-Router-Linux-kernel/drivers/nvme/target/pci-epf.c 2025-10-22 13:53:23.411328187 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/nvme/target/pci-epf.c 2025-10-22 13:53:56.627168602 -0400 -@@ -1242,8 +1242,11 @@ static void nvmet_pci_epf_queue_response - - iod->status = le16_to_cpu(req->cqe->status) >> 1; - -- /* If we have no data to transfer, directly complete the command. */ -- if (!iod->data_len || iod->dma_dir != DMA_TO_DEVICE) { -+ /* -+ * If the command failed or we have no data to transfer, complete the -+ * command immediately. -+ */ -+ if (iod->status || !iod->data_len || iod->dma_dir != DMA_TO_DEVICE) { - nvmet_pci_epf_complete_iod(iod); - return; - } -@@ -1604,8 +1607,13 @@ static void nvmet_pci_epf_exec_iod_work( - goto complete; - } - -+ /* -+ * If nvmet_req_init() fails (e.g., unsupported opcode) it will call -+ * __nvmet_req_complete() internally which will call -+ * nvmet_pci_epf_queue_response() and will complete the command directly. -+ */ - if (!nvmet_req_init(req, &iod->sq->nvme_sq, &nvmet_pci_epf_fabrics_ops)) -- goto complete; -+ return; - - iod->data_len = nvmet_req_transfer_len(req); - if (iod->data_len) { -@@ -1643,10 +1651,11 @@ static void nvmet_pci_epf_exec_iod_work( - - wait_for_completion(&iod->done); - -- if (iod->status == NVME_SC_SUCCESS) { -- WARN_ON_ONCE(!iod->data_len || iod->dma_dir != DMA_TO_DEVICE); -- nvmet_pci_epf_transfer_iod_data(iod); -- } -+ if (iod->status != NVME_SC_SUCCESS) -+ return; -+ -+ WARN_ON_ONCE(!iod->data_len || iod->dma_dir != DMA_TO_DEVICE); -+ nvmet_pci_epf_transfer_iod_data(iod); - - complete: - nvmet_pci_epf_complete_iod(iod); -diff -purNx .git BPI-Router-Linux-kernel/drivers/nvme/target/tcp.c BPI-Router-Linux-kernel-6.16.12/drivers/nvme/target/tcp.c ---- BPI-Router-Linux-kernel/drivers/nvme/target/tcp.c 2025-10-22 13:53:23.411328187 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/nvme/target/tcp.c 2025-10-22 13:53:56.627168602 -0400 -@@ -1928,10 +1928,10 @@ static void nvmet_tcp_alloc_queue(struct - struct sock *sk = queue->sock->sk; - - /* Restore the default callbacks before starting upcall */ -- read_lock_bh(&sk->sk_callback_lock); -+ write_lock_bh(&sk->sk_callback_lock); - sk->sk_user_data = NULL; - sk->sk_data_ready = port->data_ready; -- read_unlock_bh(&sk->sk_callback_lock); -+ write_unlock_bh(&sk->sk_callback_lock); - if (!nvmet_tcp_try_peek_pdu(queue)) { - if (!nvmet_tcp_tls_handshake(queue)) - return; -diff -purNx .git BPI-Router-Linux-kernel/drivers/nvmem/imx-ocotp.c BPI-Router-Linux-kernel-6.16.12/drivers/nvmem/imx-ocotp.c ---- BPI-Router-Linux-kernel/drivers/nvmem/imx-ocotp.c 2025-10-22 13:53:23.411328187 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/nvmem/imx-ocotp.c 2025-10-22 13:53:56.631168582 -0400 -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include /* ETH_ALEN */ - - #define IMX_OCOTP_OFFSET_B0W0 0x400 /* Offset from base address of the - * OTP Bank0 Word0 -@@ -227,9 +228,11 @@ static int imx_ocotp_cell_pp(void *conte - int i; - - /* Deal with some post processing of nvmem cell data */ -- if (id && !strcmp(id, "mac-address")) -+ if (id && !strcmp(id, "mac-address")) { -+ bytes = min(bytes, ETH_ALEN); - for (i = 0; i < bytes / 2; i++) - swap(buf[i], buf[bytes - i - 1]); -+ } - - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/nvmem/imx-ocotp-ele.c BPI-Router-Linux-kernel-6.16.12/drivers/nvmem/imx-ocotp-ele.c ---- BPI-Router-Linux-kernel/drivers/nvmem/imx-ocotp-ele.c 2025-10-22 13:53:23.411328187 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/nvmem/imx-ocotp-ele.c 2025-10-22 13:53:56.627168602 -0400 -@@ -12,6 +12,7 @@ - #include - #include - #include -+#include /* ETH_ALEN */ - - enum fuse_type { - FUSE_FSB = BIT(0), -@@ -118,9 +119,11 @@ static int imx_ocotp_cell_pp(void *conte - int i; - - /* Deal with some post processing of nvmem cell data */ -- if (id && !strcmp(id, "mac-address")) -+ if (id && !strcmp(id, "mac-address")) { -+ bytes = min(bytes, ETH_ALEN); - for (i = 0; i < bytes / 2; i++) - swap(buf[i], buf[bytes - i - 1]); -+ } - - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/nvmem/layouts/u-boot-env.c BPI-Router-Linux-kernel-6.16.12/drivers/nvmem/layouts/u-boot-env.c ---- BPI-Router-Linux-kernel/drivers/nvmem/layouts/u-boot-env.c 2025-10-22 13:53:23.411328187 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/nvmem/layouts/u-boot-env.c 2025-10-22 13:53:56.631168582 -0400 -@@ -92,7 +92,7 @@ int u_boot_env_parse(struct device *dev, - size_t crc32_data_offset; - size_t crc32_data_len; - size_t crc32_offset; -- __le32 *crc32_addr; -+ uint32_t *crc32_addr; - size_t data_offset; - size_t data_len; - size_t dev_size; -@@ -143,8 +143,8 @@ int u_boot_env_parse(struct device *dev, - goto err_kfree; - } - -- crc32_addr = (__le32 *)(buf + crc32_offset); -- crc32 = le32_to_cpu(*crc32_addr); -+ crc32_addr = (uint32_t *)(buf + crc32_offset); -+ crc32 = *crc32_addr; - crc32_data_len = dev_size - crc32_data_offset; - data_len = dev_size - data_offset; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/nvmem/layouts.c BPI-Router-Linux-kernel-6.16.12/drivers/nvmem/layouts.c ---- BPI-Router-Linux-kernel/drivers/nvmem/layouts.c 2025-10-22 13:53:23.411328187 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/nvmem/layouts.c 2025-10-22 13:53:56.631168582 -0400 -@@ -45,11 +45,24 @@ static void nvmem_layout_bus_remove(stru - return drv->remove(layout); - } - -+static int nvmem_layout_bus_uevent(const struct device *dev, -+ struct kobj_uevent_env *env) -+{ -+ int ret; -+ -+ ret = of_device_uevent_modalias(dev, env); -+ if (ret != ENODEV) -+ return ret; -+ -+ return 0; -+} -+ - static const struct bus_type nvmem_layout_bus_type = { - .name = "nvmem-layout", - .match = nvmem_layout_bus_match, - .probe = nvmem_layout_bus_probe, - .remove = nvmem_layout_bus_remove, -+ .uevent = nvmem_layout_bus_uevent, - }; - - int __nvmem_layout_driver_register(struct nvmem_layout_driver *drv, -diff -purNx .git BPI-Router-Linux-kernel/drivers/of/dynamic.c BPI-Router-Linux-kernel-6.16.12/drivers/of/dynamic.c ---- BPI-Router-Linux-kernel/drivers/of/dynamic.c 2025-10-22 13:53:23.411328187 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/of/dynamic.c 2025-10-22 13:53:56.631168582 -0400 -@@ -935,10 +935,15 @@ static int of_changeset_add_prop_helper( - return -ENOMEM; - - ret = of_changeset_add_property(ocs, np, new_pp); -- if (ret) -+ if (ret) { - __of_prop_free(new_pp); -+ return ret; -+ } - -- return ret; -+ new_pp->next = np->deadprops; -+ np->deadprops = new_pp; -+ -+ return 0; - } - - /** -diff -purNx .git BPI-Router-Linux-kernel/drivers/of/of_numa.c BPI-Router-Linux-kernel-6.16.12/drivers/of/of_numa.c ---- BPI-Router-Linux-kernel/drivers/of/of_numa.c 2025-10-22 13:53:23.411328187 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/of/of_numa.c 2025-10-22 13:53:56.631168582 -0400 -@@ -59,8 +59,11 @@ static int __init of_numa_parse_memory_n - r = -EINVAL; - } - -- for (i = 0; !r && !of_address_to_resource(np, i, &rsrc); i++) -+ for (i = 0; !r && !of_address_to_resource(np, i, &rsrc); i++) { - r = numa_add_memblk(nid, rsrc.start, rsrc.end + 1); -+ if (!r) -+ node_set(nid, numa_nodes_parsed); -+ } - - if (!i || r) { - of_node_put(np); -diff -purNx .git BPI-Router-Linux-kernel/drivers/of/of_reserved_mem.c BPI-Router-Linux-kernel-6.16.12/drivers/of/of_reserved_mem.c ---- BPI-Router-Linux-kernel/drivers/of/of_reserved_mem.c 2025-10-22 13:53:23.411328187 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/of/of_reserved_mem.c 2025-10-22 13:53:56.631168582 -0400 -@@ -25,6 +25,7 @@ - #include - #include - #include -+#include - - #include "of_private.h" - -@@ -175,13 +176,17 @@ static int __init __reserved_mem_reserve - base = dt_mem_next_cell(dt_root_addr_cells, &prop); - size = dt_mem_next_cell(dt_root_size_cells, &prop); - -- if (size && -- early_init_dt_reserve_memory(base, size, nomap) == 0) -+ if (size && early_init_dt_reserve_memory(base, size, nomap) == 0) { -+ /* Architecture specific contiguous memory fixup. */ -+ if (of_flat_dt_is_compatible(node, "shared-dma-pool") && -+ of_get_flat_dt_prop(node, "reusable", NULL)) -+ dma_contiguous_early_fixup(base, size); - pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %lu MiB\n", - uname, &base, (unsigned long)(size / SZ_1M)); -- else -+ } else { - pr_err("Reserved memory: failed to reserve memory for node '%s': base %pa, size %lu MiB\n", - uname, &base, (unsigned long)(size / SZ_1M)); -+ } - - len -= t_len; - } -@@ -472,7 +477,10 @@ static int __init __reserved_mem_alloc_s - uname, (unsigned long)(size / SZ_1M)); - return -ENOMEM; - } -- -+ /* Architecture specific contiguous memory fixup. */ -+ if (of_flat_dt_is_compatible(node, "shared-dma-pool") && -+ of_get_flat_dt_prop(node, "reusable", NULL)) -+ dma_contiguous_early_fixup(base, size); - /* Save region in the reserved_mem array */ - fdt_reserved_mem_save_node(node, uname, base, size); - return 0; -@@ -771,6 +779,7 @@ int of_reserved_mem_region_to_resource(c - return -EINVAL; - - resource_set_range(res, rmem->base, rmem->size); -+ res->flags = IORESOURCE_MEM; - res->name = rmem->name; - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/controller/dwc/pcie-designware.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/dwc/pcie-designware.c ---- BPI-Router-Linux-kernel/drivers/pci/controller/dwc/pcie-designware.c 2025-10-22 13:53:23.411328187 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/dwc/pcie-designware.c 2025-10-22 13:53:56.631168582 -0400 -@@ -714,6 +714,14 @@ int dw_pcie_wait_for_link(struct dw_pcie - return -ETIMEDOUT; - } - -+ /* -+ * As per PCIe r6.0, sec 6.6.1, a Downstream Port that supports Link -+ * speeds greater than 5.0 GT/s, software must wait a minimum of 100 ms -+ * after Link training completes before sending a Configuration Request. -+ */ -+ if (pci->max_link_speed > 2) -+ msleep(PCIE_RESET_CONFIG_WAIT_MS); -+ - offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); - val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/controller/dwc/pcie-dw-rockchip.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/dwc/pcie-dw-rockchip.c ---- BPI-Router-Linux-kernel/drivers/pci/controller/dwc/pcie-dw-rockchip.c 2025-10-22 13:53:23.411328187 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/dwc/pcie-dw-rockchip.c 2025-10-22 13:53:56.631168582 -0400 -@@ -58,6 +58,8 @@ - - /* Hot Reset Control Register */ - #define PCIE_CLIENT_HOT_RESET_CTRL 0x180 -+#define PCIE_LTSSM_APP_DLY2_EN BIT(1) -+#define PCIE_LTSSM_APP_DLY2_DONE BIT(3) - #define PCIE_LTSSM_ENABLE_ENHANCE BIT(4) - - /* LTSSM Status Register */ -@@ -458,6 +460,7 @@ static irqreturn_t rockchip_pcie_rc_sys_ - - if (reg & PCIE_RDLH_LINK_UP_CHGED) { - if (rockchip_pcie_link_up(pci)) { -+ msleep(PCIE_RESET_CONFIG_WAIT_MS); - dev_dbg(dev, "Received Link up event. Starting enumeration!\n"); - /* Rescan the bus to enumerate endpoint devices */ - pci_lock_rescan_remove(); -@@ -474,7 +477,7 @@ static irqreturn_t rockchip_pcie_ep_sys_ - struct rockchip_pcie *rockchip = arg; - struct dw_pcie *pci = &rockchip->pci; - struct device *dev = pci->dev; -- u32 reg; -+ u32 reg, val; - - reg = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_INTR_STATUS_MISC); - rockchip_pcie_writel_apb(rockchip, reg, PCIE_CLIENT_INTR_STATUS_MISC); -@@ -485,6 +488,10 @@ static irqreturn_t rockchip_pcie_ep_sys_ - if (reg & PCIE_LINK_REQ_RST_NOT_INT) { - dev_dbg(dev, "hot reset or link-down reset\n"); - dw_pcie_ep_linkdown(&pci->ep); -+ /* Stop delaying link training. */ -+ val = HIWORD_UPDATE_BIT(PCIE_LTSSM_APP_DLY2_DONE); -+ rockchip_pcie_writel_apb(rockchip, val, -+ PCIE_CLIENT_HOT_RESET_CTRL); - } - - if (reg & PCIE_RDLH_LINK_UP_CHGED) { -@@ -566,8 +573,11 @@ static int rockchip_pcie_configure_ep(st - return ret; - } - -- /* LTSSM enable control mode */ -- val = HIWORD_UPDATE_BIT(PCIE_LTSSM_ENABLE_ENHANCE); -+ /* -+ * LTSSM enable control mode, and automatically delay link training on -+ * hot reset/link-down reset. -+ */ -+ val = HIWORD_UPDATE_BIT(PCIE_LTSSM_ENABLE_ENHANCE | PCIE_LTSSM_APP_DLY2_EN); - rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_HOT_RESET_CTRL); - - rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_EP_MODE, -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/controller/dwc/pcie-qcom.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/dwc/pcie-qcom.c ---- BPI-Router-Linux-kernel/drivers/pci/controller/dwc/pcie-qcom.c 2025-10-22 13:53:23.411328187 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/dwc/pcie-qcom.c 2025-10-22 13:53:56.631168582 -0400 -@@ -1564,6 +1564,7 @@ static irqreturn_t qcom_pcie_global_irq_ - writel_relaxed(status, pcie->parf + PARF_INT_ALL_CLEAR); - - if (FIELD_GET(PARF_INT_ALL_LINK_UP, status)) { -+ msleep(PCIE_RESET_CONFIG_WAIT_MS); - dev_dbg(dev, "Received Link up event. Starting enumeration!\n"); - /* Rescan the bus to enumerate endpoint devices */ - pci_lock_rescan_remove(); -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/controller/dwc/pci-imx6.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/dwc/pci-imx6.c ---- BPI-Router-Linux-kernel/drivers/pci/controller/dwc/pci-imx6.c 2025-10-22 13:53:23.411328187 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/dwc/pci-imx6.c 2025-10-22 13:53:56.631168582 -0400 -@@ -860,7 +860,6 @@ static int imx95_pcie_core_reset(struct - static void imx_pcie_assert_core_reset(struct imx_pcie *imx_pcie) - { - reset_control_assert(imx_pcie->pciephy_reset); -- reset_control_assert(imx_pcie->apps_reset); - - if (imx_pcie->drvdata->core_reset) - imx_pcie->drvdata->core_reset(imx_pcie, true); -@@ -872,7 +871,6 @@ static void imx_pcie_assert_core_reset(s - static int imx_pcie_deassert_core_reset(struct imx_pcie *imx_pcie) - { - reset_control_deassert(imx_pcie->pciephy_reset); -- reset_control_deassert(imx_pcie->apps_reset); - - if (imx_pcie->drvdata->core_reset) - imx_pcie->drvdata->core_reset(imx_pcie, false); -@@ -1247,6 +1245,9 @@ static int imx_pcie_host_init(struct dw_ - } - } - -+ /* Make sure that PCIe LTSSM is cleared */ -+ imx_pcie_ltssm_disable(dev); -+ - ret = imx_pcie_deassert_core_reset(imx_pcie); - if (ret < 0) { - dev_err(dev, "pcie deassert core reset failed: %d\n", ret); -@@ -1385,6 +1386,8 @@ static const struct pci_epc_features imx - .msix_capable = false, - .bar[BAR_1] = { .type = BAR_RESERVED, }, - .bar[BAR_3] = { .type = BAR_RESERVED, }, -+ .bar[BAR_4] = { .type = BAR_FIXED, .fixed_size = SZ_256, }, -+ .bar[BAR_5] = { .type = BAR_RESERVED, }, - .align = SZ_64K, - }; - -@@ -1465,9 +1468,6 @@ static int imx_add_pcie_ep(struct imx_pc - - pci_epc_init_notify(ep->epc); - -- /* Start LTSSM. */ -- imx_pcie_ltssm_enable(dev); -- - return 0; - } - -@@ -1912,7 +1912,7 @@ static const struct imx_pcie_drvdata drv - .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE, - .mode_off[1] = IOMUXC_GPR12, - .mode_mask[1] = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE, -- .epc_features = &imx8m_pcie_epc_features, -+ .epc_features = &imx8q_pcie_epc_features, - .init_phy = imx8mq_pcie_init_phy, - .enable_ref_clk = imx8mm_pcie_enable_ref_clk, - }, -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/controller/pcie-apple.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/pcie-apple.c ---- BPI-Router-Linux-kernel/drivers/pci/controller/pcie-apple.c 2025-10-22 13:53:23.415328168 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/pcie-apple.c 2025-10-22 13:53:56.631168582 -0400 -@@ -187,6 +187,7 @@ struct apple_pcie { - const struct hw_info *hw; - unsigned long *bitmap; - struct list_head ports; -+ struct list_head entry; - struct completion event; - struct irq_fwspec fwspec; - u32 nvecs; -@@ -205,6 +206,9 @@ struct apple_pcie_port { - int idx; - }; - -+static LIST_HEAD(pcie_list); -+static DEFINE_MUTEX(pcie_list_lock); -+ - static void rmw_set(u32 set, void __iomem *addr) - { - writel_relaxed(readl_relaxed(addr) | set, addr); -@@ -720,13 +724,45 @@ static int apple_msi_init(struct apple_p - return 0; - } - -+static void apple_pcie_register(struct apple_pcie *pcie) -+{ -+ guard(mutex)(&pcie_list_lock); -+ -+ list_add_tail(&pcie->entry, &pcie_list); -+} -+ -+static void apple_pcie_unregister(struct apple_pcie *pcie) -+{ -+ guard(mutex)(&pcie_list_lock); -+ -+ list_del(&pcie->entry); -+} -+ -+static struct apple_pcie *apple_pcie_lookup(struct device *dev) -+{ -+ struct apple_pcie *pcie; -+ -+ guard(mutex)(&pcie_list_lock); -+ -+ list_for_each_entry(pcie, &pcie_list, entry) { -+ if (pcie->dev == dev) -+ return pcie; -+ } -+ -+ return NULL; -+} -+ - static struct apple_pcie_port *apple_pcie_get_port(struct pci_dev *pdev) - { - struct pci_config_window *cfg = pdev->sysdata; -- struct apple_pcie *pcie = cfg->priv; -+ struct apple_pcie *pcie; - struct pci_dev *port_pdev; - struct apple_pcie_port *port; - -+ pcie = apple_pcie_lookup(cfg->parent); -+ if (WARN_ON(!pcie)) -+ return NULL; -+ - /* Find the root port this device is on */ - port_pdev = pcie_find_root_port(pdev); - -@@ -806,10 +842,14 @@ static void apple_pcie_disable_device(st - - static int apple_pcie_init(struct pci_config_window *cfg) - { -- struct apple_pcie *pcie = cfg->priv; - struct device *dev = cfg->parent; -+ struct apple_pcie *pcie; - int ret; - -+ pcie = apple_pcie_lookup(dev); -+ if (WARN_ON(!pcie)) -+ return -ENOENT; -+ - for_each_available_child_of_node_scoped(dev->of_node, of_port) { - ret = apple_pcie_setup_port(pcie, of_port); - if (ret) { -@@ -852,13 +892,18 @@ static int apple_pcie_probe(struct platf - - mutex_init(&pcie->lock); - INIT_LIST_HEAD(&pcie->ports); -- dev_set_drvdata(dev, pcie); - - ret = apple_msi_init(pcie); - if (ret) - return ret; - -- return pci_host_common_init(pdev, &apple_pcie_cfg_ecam_ops); -+ apple_pcie_register(pcie); -+ -+ ret = pci_host_common_init(pdev, &apple_pcie_cfg_ecam_ops); -+ if (ret) -+ apple_pcie_unregister(pcie); -+ -+ return ret; - } - - static const struct of_device_id apple_pcie_of_match[] = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/controller/pcie-rockchip-ep.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/pcie-rockchip-ep.c ---- BPI-Router-Linux-kernel/drivers/pci/controller/pcie-rockchip-ep.c 2025-10-22 13:53:23.415328168 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/pcie-rockchip-ep.c 2025-10-22 13:53:56.631168582 -0400 -@@ -518,9 +518,9 @@ static void rockchip_pcie_ep_retrain_lin - { - u32 status; - -- status = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_LCS); -+ status = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_BASE + PCI_EXP_LNKCTL); - status |= PCI_EXP_LNKCTL_RL; -- rockchip_pcie_write(rockchip, status, PCIE_EP_CONFIG_LCS); -+ rockchip_pcie_write(rockchip, status, PCIE_EP_CONFIG_BASE + PCI_EXP_LNKCTL); - } - - static bool rockchip_pcie_ep_link_up(struct rockchip_pcie *rockchip) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/controller/pcie-rockchip.h BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/pcie-rockchip.h ---- BPI-Router-Linux-kernel/drivers/pci/controller/pcie-rockchip.h 2025-10-22 13:53:23.415328168 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/pcie-rockchip.h 2025-10-22 13:53:56.631168582 -0400 -@@ -155,17 +155,7 @@ - #define PCIE_EP_CONFIG_DID_VID (PCIE_EP_CONFIG_BASE + 0x00) - #define PCIE_EP_CONFIG_LCS (PCIE_EP_CONFIG_BASE + 0xd0) - #define PCIE_RC_CONFIG_RID_CCR (PCIE_RC_CONFIG_BASE + 0x08) --#define PCIE_RC_CONFIG_DCR (PCIE_RC_CONFIG_BASE + 0xc4) --#define PCIE_RC_CONFIG_DCR_CSPL_SHIFT 18 --#define PCIE_RC_CONFIG_DCR_CSPL_LIMIT 0xff --#define PCIE_RC_CONFIG_DCR_CPLS_SHIFT 26 --#define PCIE_RC_CONFIG_DCSR (PCIE_RC_CONFIG_BASE + 0xc8) --#define PCIE_RC_CONFIG_DCSR_MPS_MASK GENMASK(7, 5) --#define PCIE_RC_CONFIG_DCSR_MPS_256 (0x1 << 5) --#define PCIE_RC_CONFIG_LINK_CAP (PCIE_RC_CONFIG_BASE + 0xcc) --#define PCIE_RC_CONFIG_LINK_CAP_L0S BIT(10) --#define PCIE_RC_CONFIG_LCS (PCIE_RC_CONFIG_BASE + 0xd0) --#define PCIE_EP_CONFIG_LCS (PCIE_EP_CONFIG_BASE + 0xd0) -+#define PCIE_RC_CONFIG_CR (PCIE_RC_CONFIG_BASE + 0xc0) - #define PCIE_RC_CONFIG_L1_SUBSTATE_CTRL2 (PCIE_RC_CONFIG_BASE + 0x90c) - #define PCIE_RC_CONFIG_THP_CAP (PCIE_RC_CONFIG_BASE + 0x274) - #define PCIE_RC_CONFIG_THP_CAP_NEXT_MASK GENMASK(31, 20) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/controller/pcie-rockchip-host.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/pcie-rockchip-host.c ---- BPI-Router-Linux-kernel/drivers/pci/controller/pcie-rockchip-host.c 2025-10-22 13:53:23.415328168 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/pcie-rockchip-host.c 2025-10-22 13:53:56.631168582 -0400 -@@ -11,6 +11,7 @@ - * ARM PCI Host generic driver. - */ - -+#include - #include - #include - #include -@@ -40,18 +41,18 @@ static void rockchip_pcie_enable_bw_int( - { - u32 status; - -- status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS); -+ status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); - status |= (PCI_EXP_LNKCTL_LBMIE | PCI_EXP_LNKCTL_LABIE); -- rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS); -+ rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); - } - - static void rockchip_pcie_clr_bw_int(struct rockchip_pcie *rockchip) - { - u32 status; - -- status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS); -+ status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); - status |= (PCI_EXP_LNKSTA_LBMS | PCI_EXP_LNKSTA_LABS) << 16; -- rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS); -+ rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); - } - - static void rockchip_pcie_update_txcredit_mui(struct rockchip_pcie *rockchip) -@@ -269,7 +270,7 @@ static void rockchip_pcie_set_power_limi - scale = 3; /* 0.001x */ - curr = curr / 1000; /* convert to mA */ - power = (curr * 3300) / 1000; /* milliwatt */ -- while (power > PCIE_RC_CONFIG_DCR_CSPL_LIMIT) { -+ while (power > FIELD_MAX(PCI_EXP_DEVCAP_PWR_VAL)) { - if (!scale) { - dev_warn(rockchip->dev, "invalid power supply\n"); - return; -@@ -278,10 +279,10 @@ static void rockchip_pcie_set_power_limi - power = power / 10; - } - -- status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_DCR); -- status |= (power << PCIE_RC_CONFIG_DCR_CSPL_SHIFT) | -- (scale << PCIE_RC_CONFIG_DCR_CPLS_SHIFT); -- rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_DCR); -+ status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_DEVCAP); -+ status |= FIELD_PREP(PCI_EXP_DEVCAP_PWR_VAL, power); -+ status |= FIELD_PREP(PCI_EXP_DEVCAP_PWR_SCL, scale); -+ rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_DEVCAP); - } - - /** -@@ -309,14 +310,14 @@ static int rockchip_pcie_host_init_port( - rockchip_pcie_set_power_limit(rockchip); - - /* Set RC's clock architecture as common clock */ -- status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS); -+ status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); - status |= PCI_EXP_LNKSTA_SLC << 16; -- rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS); -+ rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); - - /* Set RC's RCB to 128 */ -- status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS); -+ status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); - status |= PCI_EXP_LNKCTL_RCB; -- rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS); -+ rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); - - /* Enable Gen1 training */ - rockchip_pcie_write(rockchip, PCIE_CLIENT_LINK_TRAIN_ENABLE, -@@ -341,9 +342,13 @@ static int rockchip_pcie_host_init_port( - * Enable retrain for gen2. This should be configured only after - * gen1 finished. - */ -- status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS); -+ status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL2); -+ status &= ~PCI_EXP_LNKCTL2_TLS; -+ status |= PCI_EXP_LNKCTL2_TLS_5_0GT; -+ rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL2); -+ status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); - status |= PCI_EXP_LNKCTL_RL; -- rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS); -+ rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCTL); - - err = readl_poll_timeout(rockchip->apb_base + PCIE_CORE_CTRL, - status, PCIE_LINK_IS_GEN2(status), 20, -@@ -380,15 +385,15 @@ static int rockchip_pcie_host_init_port( - - /* Clear L0s from RC's link cap */ - if (of_property_read_bool(dev->of_node, "aspm-no-l0s")) { -- status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LINK_CAP); -- status &= ~PCIE_RC_CONFIG_LINK_CAP_L0S; -- rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LINK_CAP); -+ status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCAP); -+ status &= ~PCI_EXP_LNKCAP_ASPM_L0S; -+ rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_LNKCAP); - } - -- status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_DCSR); -- status &= ~PCIE_RC_CONFIG_DCSR_MPS_MASK; -- status |= PCIE_RC_CONFIG_DCSR_MPS_256; -- rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_DCSR); -+ status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_CR + PCI_EXP_DEVCTL); -+ status &= ~PCI_EXP_DEVCTL_PAYLOAD; -+ status |= PCI_EXP_DEVCTL_PAYLOAD_256B; -+ rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_CR + PCI_EXP_DEVCTL); - - return 0; - err_power_off_phy: -@@ -439,7 +444,7 @@ static irqreturn_t rockchip_pcie_subsys_ - dev_dbg(dev, "malformed TLP received from the link\n"); - - if (sub_reg & PCIE_CORE_INT_UCR) -- dev_dbg(dev, "malformed TLP received from the link\n"); -+ dev_dbg(dev, "Unexpected Completion received from the link\n"); - - if (sub_reg & PCIE_CORE_INT_FCE) - dev_dbg(dev, "an error was observed in the flow control advertisements from the other side\n"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/controller/pci-host-common.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/pci-host-common.c ---- BPI-Router-Linux-kernel/drivers/pci/controller/pci-host-common.c 2025-10-22 13:53:23.411328187 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/pci-host-common.c 2025-10-22 13:53:56.631168582 -0400 -@@ -64,13 +64,13 @@ int pci_host_common_init(struct platform - - of_pci_check_probe_only(); - -+ platform_set_drvdata(pdev, bridge); -+ - /* Parse and map our Configuration Space windows */ - cfg = gen_pci_init(dev, bridge, ops); - if (IS_ERR(cfg)) - return PTR_ERR(cfg); - -- platform_set_drvdata(pdev, bridge); -- - bridge->sysdata = cfg; - bridge->ops = (struct pci_ops *)&ops->pci_ops; - bridge->enable_device = ops->enable_device; -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/controller/pci-hyperv.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/pci-hyperv.c ---- BPI-Router-Linux-kernel/drivers/pci/controller/pci-hyperv.c 2025-10-22 13:53:23.415328168 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/pci-hyperv.c 2025-10-22 13:53:56.631168582 -0400 -@@ -600,7 +600,7 @@ static unsigned int hv_msi_get_int_vecto - #define hv_msi_prepare pci_msi_prepare - - /** -- * hv_arch_irq_unmask() - "Unmask" the IRQ by setting its current -+ * hv_irq_retarget_interrupt() - "Unmask" the IRQ by setting its current - * affinity. - * @data: Describes the IRQ - * -@@ -609,7 +609,7 @@ static unsigned int hv_msi_get_int_vecto - * is built out of this PCI bus's instance GUID and the function - * number of the device. - */ --static void hv_arch_irq_unmask(struct irq_data *data) -+static void hv_irq_retarget_interrupt(struct irq_data *data) - { - struct msi_desc *msi_desc = irq_data_get_msi_desc(data); - struct hv_retarget_device_interrupt *params; -@@ -714,6 +714,20 @@ out: - dev_err(&hbus->hdev->device, - "%s() failed: %#llx", __func__, res); - } -+ -+static void hv_arch_irq_unmask(struct irq_data *data) -+{ -+ if (hv_root_partition()) -+ /* -+ * In case of the nested root partition, the nested hypervisor -+ * is taking care of interrupt remapping and thus the -+ * MAP_DEVICE_INTERRUPT hypercall is required instead of -+ * RETARGET_INTERRUPT. -+ */ -+ (void)hv_map_msi_interrupt(data, NULL); -+ else -+ hv_irq_retarget_interrupt(data); -+} - #elif defined(CONFIG_ARM64) - /* - * SPI vectors to use for vPCI; arch SPIs range is [32, 1019], but leaving a bit -@@ -4144,6 +4158,9 @@ static int __init init_hv_pci_drv(void) - if (!hv_is_hyperv_initialized()) - return -ENODEV; - -+ if (hv_root_partition() && !hv_nested) -+ return -ENODEV; -+ - ret = hv_pci_irqchip_init(); - if (ret) - return ret; -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/controller/pci-hyperv-intf.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/pci-hyperv-intf.c ---- BPI-Router-Linux-kernel/drivers/pci/controller/pci-hyperv-intf.c 2025-10-22 13:53:23.411328187 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/pci-hyperv-intf.c 2025-10-22 13:53:56.631168582 -0400 -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - - struct hyperv_pci_block_ops hvpci_block_ops; - EXPORT_SYMBOL_GPL(hvpci_block_ops); -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/controller/pci-mvebu.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/pci-mvebu.c ---- BPI-Router-Linux-kernel/drivers/pci/controller/pci-mvebu.c 2025-10-22 13:53:23.415328168 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/pci-mvebu.c 2025-10-22 13:53:56.631168582 -0400 -@@ -1168,12 +1168,6 @@ static void __iomem *mvebu_pcie_map_regi - return devm_ioremap_resource(&pdev->dev, &port->regs); - } - --#define DT_FLAGS_TO_TYPE(flags) (((flags) >> 24) & 0x03) --#define DT_TYPE_IO 0x1 --#define DT_TYPE_MEM32 0x2 --#define DT_CPUADDR_TO_TARGET(cpuaddr) (((cpuaddr) >> 56) & 0xFF) --#define DT_CPUADDR_TO_ATTR(cpuaddr) (((cpuaddr) >> 48) & 0xFF) -- - static int mvebu_get_tgt_attr(struct device_node *np, int devfn, - unsigned long type, - unsigned int *tgt, -@@ -1189,19 +1183,12 @@ static int mvebu_get_tgt_attr(struct dev - return -EINVAL; - - for_each_of_range(&parser, &range) { -- unsigned long rtype; - u32 slot = upper_32_bits(range.bus_addr); - -- if (DT_FLAGS_TO_TYPE(range.flags) == DT_TYPE_IO) -- rtype = IORESOURCE_IO; -- else if (DT_FLAGS_TO_TYPE(range.flags) == DT_TYPE_MEM32) -- rtype = IORESOURCE_MEM; -- else -- continue; -- -- if (slot == PCI_SLOT(devfn) && type == rtype) { -- *tgt = DT_CPUADDR_TO_TARGET(range.cpu_addr); -- *attr = DT_CPUADDR_TO_ATTR(range.cpu_addr); -+ if (slot == PCI_SLOT(devfn) && -+ type == (range.flags & IORESOURCE_TYPE_BITS)) { -+ *tgt = (range.parent_bus_addr >> 56) & 0xFF; -+ *attr = (range.parent_bus_addr >> 48) & 0xFF; - return 0; - } - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/controller/plda/pcie-starfive.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/plda/pcie-starfive.c ---- BPI-Router-Linux-kernel/drivers/pci/controller/plda/pcie-starfive.c 2025-10-22 13:53:23.415328168 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/controller/plda/pcie-starfive.c 2025-10-22 13:53:56.631168582 -0400 -@@ -368,7 +368,7 @@ static int starfive_pcie_host_init(struc - * of 100ms following exit from a conventional reset before - * sending a configuration request to the device. - */ -- msleep(PCIE_RESET_CONFIG_DEVICE_WAIT_MS); -+ msleep(PCIE_RESET_CONFIG_WAIT_MS); - - if (starfive_pcie_host_wait_for_link(pcie)) - dev_info(dev, "port link down\n"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/ecam.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/ecam.c ---- BPI-Router-Linux-kernel/drivers/pci/ecam.c 2025-10-22 13:53:23.415328168 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/ecam.c 2025-10-22 13:53:56.631168582 -0400 -@@ -84,8 +84,6 @@ struct pci_config_window *pci_ecam_creat - goto err_exit_iomap; - } - -- cfg->priv = dev_get_drvdata(dev); -- - if (ops->init) { - err = ops->init(cfg); - if (err) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/endpoint/functions/pci-epf-vntb.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/endpoint/functions/pci-epf-vntb.c ---- BPI-Router-Linux-kernel/drivers/pci/endpoint/functions/pci-epf-vntb.c 2025-10-22 13:53:23.415328168 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/endpoint/functions/pci-epf-vntb.c 2025-10-22 13:53:56.631168582 -0400 -@@ -510,7 +510,7 @@ static int epf_ntb_db_bar_init(struct ep - struct device *dev = &ntb->epf->dev; - int ret; - struct pci_epf_bar *epf_bar; -- void __iomem *mw_addr; -+ void *mw_addr; - enum pci_barno barno; - size_t size = sizeof(u32) * ntb->db_count; - -@@ -680,7 +680,7 @@ static int epf_ntb_init_epc_bar(struct e - barno = pci_epc_get_next_free_bar(epc_features, barno); - if (barno < 0) { - dev_err(dev, "Fail to get NTB function BAR\n"); -- return barno; -+ return -ENOENT; - } - ntb->epf_ntb_bar[bar] = barno; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/endpoint/pci-ep-cfs.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/endpoint/pci-ep-cfs.c ---- BPI-Router-Linux-kernel/drivers/pci/endpoint/pci-ep-cfs.c 2025-10-22 13:53:23.415328168 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/endpoint/pci-ep-cfs.c 2025-10-22 13:53:56.631168582 -0400 -@@ -691,6 +691,7 @@ void pci_ep_cfs_remove_epf_group(struct - if (IS_ERR_OR_NULL(group)) - return; - -+ list_del(&group->group_entry); - configfs_unregister_default_group(group); - } - EXPORT_SYMBOL(pci_ep_cfs_remove_epf_group); -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/endpoint/pci-epf-core.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/endpoint/pci-epf-core.c ---- BPI-Router-Linux-kernel/drivers/pci/endpoint/pci-epf-core.c 2025-10-22 13:53:23.415328168 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/endpoint/pci-epf-core.c 2025-10-22 13:53:56.631168582 -0400 -@@ -338,7 +338,7 @@ static void pci_epf_remove_cfs(struct pc - mutex_lock(&pci_epf_mutex); - list_for_each_entry_safe(group, tmp, &driver->epf_group, group_entry) - pci_ep_cfs_remove_epf_group(group); -- list_del(&driver->epf_group); -+ WARN_ON(!list_empty(&driver->epf_group)); - mutex_unlock(&pci_epf_mutex); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/hotplug/pciehp_hpc.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/hotplug/pciehp_hpc.c ---- BPI-Router-Linux-kernel/drivers/pci/hotplug/pciehp_hpc.c 2025-10-22 13:53:23.415328168 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/hotplug/pciehp_hpc.c 2025-10-22 13:53:56.631168582 -0400 -@@ -771,7 +771,7 @@ static irqreturn_t pciehp_ist(int irq, v - u16 ignored_events = PCI_EXP_SLTSTA_DLLSC; - - if (!ctrl->inband_presence_disabled) -- ignored_events |= events & PCI_EXP_SLTSTA_PDC; -+ ignored_events |= PCI_EXP_SLTSTA_PDC; - - events &= ~ignored_events; - pciehp_ignore_link_change(ctrl, pdev, irq, ignored_events); -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/hotplug/pnv_php.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/hotplug/pnv_php.c ---- BPI-Router-Linux-kernel/drivers/pci/hotplug/pnv_php.c 2025-10-22 13:53:23.415328168 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/hotplug/pnv_php.c 2025-10-22 13:53:56.631168582 -0400 -@@ -3,12 +3,15 @@ - * PCI Hotplug Driver for PowerPC PowerNV platform. - * - * Copyright Gavin Shan, IBM Corporation 2016. -+ * Copyright (C) 2025 Raptor Engineering, LLC -+ * Copyright (C) 2025 Raptor Computing Systems, LLC - */ - - #include - #include - #include - #include -+#include - #include - #include - -@@ -36,8 +39,10 @@ static void pnv_php_register(struct devi - static void pnv_php_unregister_one(struct device_node *dn); - static void pnv_php_unregister(struct device_node *dn); - -+static void pnv_php_enable_irq(struct pnv_php_slot *php_slot); -+ - static void pnv_php_disable_irq(struct pnv_php_slot *php_slot, -- bool disable_device) -+ bool disable_device, bool disable_msi) - { - struct pci_dev *pdev = php_slot->pdev; - u16 ctrl; -@@ -53,19 +58,15 @@ static void pnv_php_disable_irq(struct p - php_slot->irq = 0; - } - -- if (php_slot->wq) { -- destroy_workqueue(php_slot->wq); -- php_slot->wq = NULL; -- } -- -- if (disable_device) { -+ if (disable_device || disable_msi) { - if (pdev->msix_enabled) - pci_disable_msix(pdev); - else if (pdev->msi_enabled) - pci_disable_msi(pdev); -+ } - -+ if (disable_device) - pci_disable_device(pdev); -- } - } - - static void pnv_php_free_slot(struct kref *kref) -@@ -74,7 +75,8 @@ static void pnv_php_free_slot(struct kre - struct pnv_php_slot, kref); - - WARN_ON(!list_empty(&php_slot->children)); -- pnv_php_disable_irq(php_slot, false); -+ pnv_php_disable_irq(php_slot, false, false); -+ destroy_workqueue(php_slot->wq); - kfree(php_slot->name); - kfree(php_slot); - } -@@ -391,6 +393,20 @@ static int pnv_php_get_power_state(struc - return 0; - } - -+static int pcie_check_link_active(struct pci_dev *pdev) -+{ -+ u16 lnk_status; -+ int ret; -+ -+ ret = pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status); -+ if (ret == PCIBIOS_DEVICE_NOT_FOUND || PCI_POSSIBLE_ERROR(lnk_status)) -+ return -ENODEV; -+ -+ ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA); -+ -+ return ret; -+} -+ - static int pnv_php_get_adapter_state(struct hotplug_slot *slot, u8 *state) - { - struct pnv_php_slot *php_slot = to_pnv_php_slot(slot); -@@ -403,6 +419,19 @@ static int pnv_php_get_adapter_state(str - */ - ret = pnv_pci_get_presence_state(php_slot->id, &presence); - if (ret >= 0) { -+ if (pci_pcie_type(php_slot->pdev) == PCI_EXP_TYPE_DOWNSTREAM && -+ presence == OPAL_PCI_SLOT_EMPTY) { -+ /* -+ * Similar to pciehp_hpc, check whether the Link Active -+ * bit is set to account for broken downstream bridges -+ * that don't properly assert Presence Detect State, as -+ * was observed on the Microsemi Switchtec PM8533 PFX -+ * [11f8:8533]. -+ */ -+ if (pcie_check_link_active(php_slot->pdev) > 0) -+ presence = OPAL_PCI_SLOT_PRESENT; -+ } -+ - *state = presence; - ret = 0; - } else { -@@ -442,6 +471,61 @@ static int pnv_php_set_attention_state(s - return 0; - } - -+static int pnv_php_activate_slot(struct pnv_php_slot *php_slot, -+ struct hotplug_slot *slot) -+{ -+ int ret, i; -+ -+ /* -+ * Issue initial slot activation command to firmware -+ * -+ * Firmware will power slot on, attempt to train the link, and -+ * discover any downstream devices. If this process fails, firmware -+ * will return an error code and an invalid device tree. Failure -+ * can be caused for multiple reasons, including a faulty -+ * downstream device, poor connection to the downstream device, or -+ * a previously latched PHB fence. On failure, issue fundamental -+ * reset up to three times before aborting. -+ */ -+ ret = pnv_php_set_slot_power_state(slot, OPAL_PCI_SLOT_POWER_ON); -+ if (ret) { -+ SLOT_WARN( -+ php_slot, -+ "PCI slot activation failed with error code %d, possible frozen PHB", -+ ret); -+ SLOT_WARN( -+ php_slot, -+ "Attempting complete PHB reset before retrying slot activation\n"); -+ for (i = 0; i < 3; i++) { -+ /* -+ * Slot activation failed, PHB may be fenced from a -+ * prior device failure. -+ * -+ * Use the OPAL fundamental reset call to both try a -+ * device reset and clear any potentially active PHB -+ * fence / freeze. -+ */ -+ SLOT_WARN(php_slot, "Try %d...\n", i + 1); -+ pci_set_pcie_reset_state(php_slot->pdev, -+ pcie_warm_reset); -+ msleep(250); -+ pci_set_pcie_reset_state(php_slot->pdev, -+ pcie_deassert_reset); -+ -+ ret = pnv_php_set_slot_power_state( -+ slot, OPAL_PCI_SLOT_POWER_ON); -+ if (!ret) -+ break; -+ } -+ -+ if (i >= 3) -+ SLOT_WARN(php_slot, -+ "Failed to bring slot online, aborting!\n"); -+ } -+ -+ return ret; -+} -+ - static int pnv_php_enable(struct pnv_php_slot *php_slot, bool rescan) - { - struct hotplug_slot *slot = &php_slot->slot; -@@ -504,7 +588,7 @@ static int pnv_php_enable(struct pnv_php - goto scan; - - /* Power is off, turn it on and then scan the slot */ -- ret = pnv_php_set_slot_power_state(slot, OPAL_PCI_SLOT_POWER_ON); -+ ret = pnv_php_activate_slot(php_slot, slot); - if (ret) - return ret; - -@@ -561,8 +645,58 @@ static int pnv_php_reset_slot(struct hot - static int pnv_php_enable_slot(struct hotplug_slot *slot) - { - struct pnv_php_slot *php_slot = to_pnv_php_slot(slot); -+ u32 prop32; -+ int ret; -+ -+ ret = pnv_php_enable(php_slot, true); -+ if (ret) -+ return ret; -+ -+ /* (Re-)enable interrupt if the slot supports surprise hotplug */ -+ ret = of_property_read_u32(php_slot->dn, "ibm,slot-surprise-pluggable", -+ &prop32); -+ if (!ret && prop32) -+ pnv_php_enable_irq(php_slot); -+ -+ return 0; -+} -+ -+/* -+ * Disable any hotplug interrupts for all slots on the provided bus, as well as -+ * all downstream slots in preparation for a hot unplug. -+ */ -+static int pnv_php_disable_all_irqs(struct pci_bus *bus) -+{ -+ struct pci_bus *child_bus; -+ struct pci_slot *slot; -+ -+ /* First go down child buses */ -+ list_for_each_entry(child_bus, &bus->children, node) -+ pnv_php_disable_all_irqs(child_bus); - -- return pnv_php_enable(php_slot, true); -+ /* Disable IRQs for all pnv_php slots on this bus */ -+ list_for_each_entry(slot, &bus->slots, list) { -+ struct pnv_php_slot *php_slot = to_pnv_php_slot(slot->hotplug); -+ -+ pnv_php_disable_irq(php_slot, false, true); -+ } -+ -+ return 0; -+} -+ -+/* -+ * Disable any hotplug interrupts for all downstream slots on the provided -+ * bus in preparation for a hot unplug. -+ */ -+static int pnv_php_disable_all_downstream_irqs(struct pci_bus *bus) -+{ -+ struct pci_bus *child_bus; -+ -+ /* Go down child buses, recursively deactivating their IRQs */ -+ list_for_each_entry(child_bus, &bus->children, node) -+ pnv_php_disable_all_irqs(child_bus); -+ -+ return 0; - } - - static int pnv_php_disable_slot(struct hotplug_slot *slot) -@@ -579,6 +713,13 @@ static int pnv_php_disable_slot(struct h - php_slot->state != PNV_PHP_STATE_REGISTERED) - return 0; - -+ /* -+ * Free all IRQ resources from all child slots before remove. -+ * Note that we do not disable the root slot IRQ here as that -+ * would also deactivate the slot hot (re)plug interrupt! -+ */ -+ pnv_php_disable_all_downstream_irqs(php_slot->bus); -+ - /* Remove all devices behind the slot */ - pci_lock_rescan_remove(); - pci_hp_remove_devices(php_slot->bus); -@@ -647,6 +788,15 @@ static struct pnv_php_slot *pnv_php_allo - return NULL; - } - -+ /* Allocate workqueue for this slot's interrupt handling */ -+ php_slot->wq = alloc_workqueue("pciehp-%s", 0, 0, php_slot->name); -+ if (!php_slot->wq) { -+ SLOT_WARN(php_slot, "Cannot alloc workqueue\n"); -+ kfree(php_slot->name); -+ kfree(php_slot); -+ return NULL; -+ } -+ - if (dn->child && PCI_DN(dn->child)) - php_slot->slot_no = PCI_SLOT(PCI_DN(dn->child)->devfn); - else -@@ -745,16 +895,63 @@ static int pnv_php_enable_msix(struct pn - return entry.vector; - } - -+static void -+pnv_php_detect_clear_suprise_removal_freeze(struct pnv_php_slot *php_slot) -+{ -+ struct pci_dev *pdev = php_slot->pdev; -+ struct eeh_dev *edev; -+ struct eeh_pe *pe; -+ int i, rc; -+ -+ /* -+ * When a device is surprise removed from a downstream bridge slot, -+ * the upstream bridge port can still end up frozen due to related EEH -+ * events, which will in turn block the MSI interrupts for slot hotplug -+ * detection. -+ * -+ * Detect and thaw any frozen upstream PE after slot deactivation. -+ */ -+ edev = pci_dev_to_eeh_dev(pdev); -+ pe = edev ? edev->pe : NULL; -+ rc = eeh_pe_get_state(pe); -+ if ((rc == -ENODEV) || (rc == -ENOENT)) { -+ SLOT_WARN( -+ php_slot, -+ "Upstream bridge PE state unknown, hotplug detect may fail\n"); -+ } else { -+ if (pe->state & EEH_PE_ISOLATED) { -+ SLOT_WARN( -+ php_slot, -+ "Upstream bridge PE %02x frozen, thawing...\n", -+ pe->addr); -+ for (i = 0; i < 3; i++) -+ if (!eeh_unfreeze_pe(pe)) -+ break; -+ if (i >= 3) -+ SLOT_WARN( -+ php_slot, -+ "Unable to thaw PE %02x, hotplug detect will fail!\n", -+ pe->addr); -+ else -+ SLOT_WARN(php_slot, -+ "PE %02x thawed successfully\n", -+ pe->addr); -+ } -+ } -+} -+ - static void pnv_php_event_handler(struct work_struct *work) - { - struct pnv_php_event *event = - container_of(work, struct pnv_php_event, work); - struct pnv_php_slot *php_slot = event->php_slot; - -- if (event->added) -+ if (event->added) { - pnv_php_enable_slot(&php_slot->slot); -- else -+ } else { - pnv_php_disable_slot(&php_slot->slot); -+ pnv_php_detect_clear_suprise_removal_freeze(php_slot); -+ } - - kfree(event); - } -@@ -843,14 +1040,6 @@ static void pnv_php_init_irq(struct pnv_ - u16 sts, ctrl; - int ret; - -- /* Allocate workqueue */ -- php_slot->wq = alloc_workqueue("pciehp-%s", 0, 0, php_slot->name); -- if (!php_slot->wq) { -- SLOT_WARN(php_slot, "Cannot alloc workqueue\n"); -- pnv_php_disable_irq(php_slot, true); -- return; -- } -- - /* Check PDC (Presence Detection Change) is broken or not */ - ret = of_property_read_u32(php_slot->dn, "ibm,slot-broken-pdc", - &broken_pdc); -@@ -869,7 +1058,7 @@ static void pnv_php_init_irq(struct pnv_ - ret = request_irq(irq, pnv_php_interrupt, IRQF_SHARED, - php_slot->name, php_slot); - if (ret) { -- pnv_php_disable_irq(php_slot, true); -+ pnv_php_disable_irq(php_slot, true, true); - SLOT_WARN(php_slot, "Error %d enabling IRQ %d\n", ret, irq); - return; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/msi/msi.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/msi/msi.c ---- BPI-Router-Linux-kernel/drivers/pci/msi/msi.c 2025-10-22 13:53:23.415328168 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/msi/msi.c 2025-10-22 13:53:56.631168582 -0400 -@@ -934,10 +934,12 @@ int pci_msix_write_tph_tag(struct pci_de - if (!pdev->msix_enabled) - return -ENXIO; - -- guard(msi_descs_lock)(&pdev->dev); - virq = msi_get_virq(&pdev->dev, index); - if (!virq) - return -ENXIO; -+ -+ guard(msi_descs_lock)(&pdev->dev); -+ - /* - * This is a horrible hack, but short of implementing a PCI - * specific interrupt chip callback and a huge pile of -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/pci-acpi.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/pci-acpi.c ---- BPI-Router-Linux-kernel/drivers/pci/pci-acpi.c 2025-10-22 13:53:23.415328168 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/pci-acpi.c 2025-10-22 13:53:56.631168582 -0400 -@@ -816,13 +816,11 @@ int pci_acpi_program_hp_params(struct pc - bool pciehp_is_native(struct pci_dev *bridge) - { - const struct pci_host_bridge *host; -- u32 slot_cap; - - if (!IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE)) - return false; - -- pcie_capability_read_dword(bridge, PCI_EXP_SLTCAP, &slot_cap); -- if (!(slot_cap & PCI_EXP_SLTCAP_HPC)) -+ if (!bridge->is_pciehp) - return false; - - if (pcie_ports_native) -@@ -1676,19 +1674,24 @@ struct pci_bus *pci_acpi_scan_root(struc - return NULL; - - root_ops = kzalloc(sizeof(*root_ops), GFP_KERNEL); -- if (!root_ops) -- goto free_ri; -+ if (!root_ops) { -+ kfree(ri); -+ return NULL; -+ } - - ri->cfg = pci_acpi_setup_ecam_mapping(root); -- if (!ri->cfg) -- goto free_root_ops; -+ if (!ri->cfg) { -+ kfree(ri); -+ kfree(root_ops); -+ return NULL; -+ } - - root_ops->release_info = pci_acpi_generic_release_info; - root_ops->prepare_resources = pci_acpi_root_prepare_resources; - root_ops->pci_ops = (struct pci_ops *)&ri->cfg->ops->pci_ops; - bus = acpi_pci_root_create(root, root_ops, &ri->common, ri->cfg); - if (!bus) -- goto free_cfg; -+ return NULL; - - /* If we must preserve the resource configuration, claim now */ - host = pci_find_host_bridge(bus); -@@ -1705,14 +1708,6 @@ struct pci_bus *pci_acpi_scan_root(struc - pcie_bus_configure_settings(child); - - return bus; -- --free_cfg: -- pci_ecam_free(ri->cfg); --free_root_ops: -- kfree(root_ops); --free_ri: -- kfree(ri); -- return NULL; - } - - void pcibios_add_bus(struct pci_bus *bus) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/pci.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/pci.c ---- BPI-Router-Linux-kernel/drivers/pci/pci.c 2025-10-22 13:53:23.415328168 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/pci.c 2025-10-22 13:53:56.631168582 -0400 -@@ -3030,8 +3030,12 @@ static const struct dmi_system_id bridge - * pci_bridge_d3_possible - Is it possible to put the bridge into D3 - * @bridge: Bridge to check - * -- * This function checks if it is possible to move the bridge to D3. - * Currently we only allow D3 for some PCIe ports and for Thunderbolt. -+ * -+ * Return: Whether it is possible to move the bridge to D3. -+ * -+ * The return value is guaranteed to be constant across the entire lifetime -+ * of the bridge, including its hot-removal. - */ - bool pci_bridge_d3_possible(struct pci_dev *bridge) - { -@@ -3217,14 +3221,14 @@ void pci_pm_init(struct pci_dev *dev) - /* find PCI PM capability in list */ - pm = pci_find_capability(dev, PCI_CAP_ID_PM); - if (!pm) -- return; -+ goto poweron; - /* Check device's ability to generate PME# */ - pci_read_config_word(dev, pm + PCI_PM_PMC, &pmc); - - if ((pmc & PCI_PM_CAP_VER_MASK) > 3) { - pci_err(dev, "unsupported PM cap regs version (%u)\n", - pmc & PCI_PM_CAP_VER_MASK); -- return; -+ goto poweron; - } - - dev->pm_cap = pm; -@@ -3269,6 +3273,7 @@ void pci_pm_init(struct pci_dev *dev) - pci_read_config_word(dev, PCI_STATUS, &status); - if (status & PCI_STATUS_IMM_READY) - dev->imm_ready = 1; -+poweron: - pci_pm_power_up_and_verify_state(dev); - pm_runtime_forbid(&dev->dev); - pm_runtime_set_active(&dev->dev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/pci-driver.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/pci-driver.c ---- BPI-Router-Linux-kernel/drivers/pci/pci-driver.c 2025-10-22 13:53:23.415328168 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/pci-driver.c 2025-10-22 13:53:56.631168582 -0400 -@@ -1628,7 +1628,7 @@ static int pci_bus_num_vf(struct device - */ - static int pci_dma_configure(struct device *dev) - { -- struct pci_driver *driver = to_pci_driver(dev->driver); -+ const struct device_driver *drv = READ_ONCE(dev->driver); - struct device *bridge; - int ret = 0; - -@@ -1645,8 +1645,8 @@ static int pci_dma_configure(struct devi - - pci_put_host_bridge_device(bridge); - -- /* @driver may not be valid when we're called from the IOMMU layer */ -- if (!ret && dev->driver && !driver->driver_managed_dma) { -+ /* @drv may not be valid when we're called from the IOMMU layer */ -+ if (!ret && drv && !to_pci_driver(drv)->driver_managed_dma) { - ret = iommu_device_use_default_domain(dev); - if (ret) - arch_teardown_dma_ops(dev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/pcie/portdrv.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/pcie/portdrv.c ---- BPI-Router-Linux-kernel/drivers/pci/pcie/portdrv.c 2025-10-22 13:53:23.419328148 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/pcie/portdrv.c 2025-10-22 13:53:56.631168582 -0400 -@@ -220,7 +220,7 @@ static int get_port_device_capability(st - struct pci_host_bridge *host = pci_find_host_bridge(dev->bus); - int services = 0; - -- if (dev->is_hotplug_bridge && -+ if (dev->is_pciehp && - (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT || - pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) && - (pcie_ports_native || host->native_pcie_hotplug)) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/pcie/ptm.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/pcie/ptm.c ---- BPI-Router-Linux-kernel/drivers/pci/pcie/ptm.c 2025-10-22 13:53:23.419328148 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/pcie/ptm.c 2025-10-22 13:53:56.631168582 -0400 -@@ -254,6 +254,7 @@ bool pcie_ptm_enabled(struct pci_dev *de - } - EXPORT_SYMBOL(pcie_ptm_enabled); - -+#if IS_ENABLED(CONFIG_DEBUG_FS) - static ssize_t context_update_write(struct file *file, const char __user *ubuf, - size_t count, loff_t *ppos) - { -@@ -552,3 +553,4 @@ void pcie_ptm_destroy_debugfs(struct pci - debugfs_remove_recursive(ptm_debugfs->debugfs); - } - EXPORT_SYMBOL_GPL(pcie_ptm_destroy_debugfs); -+#endif -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/pci.h BPI-Router-Linux-kernel-6.16.12/drivers/pci/pci.h ---- BPI-Router-Linux-kernel/drivers/pci/pci.h 2025-10-22 13:53:23.415328168 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/pci.h 2025-10-22 13:53:56.631168582 -0400 -@@ -61,7 +61,7 @@ struct pcie_tlp_log; - * completes before sending a Configuration Request to the device - * immediately below that Port." - */ --#define PCIE_RESET_CONFIG_DEVICE_WAIT_MS 100 -+#define PCIE_RESET_CONFIG_WAIT_MS 100 - - /* Message Routing (r[2:0]); PCIe r6.0, sec 2.2.8 */ - #define PCIE_MSG_TYPE_R_RC 0 -@@ -391,12 +391,14 @@ void pci_bus_put(struct pci_bus *bus); - - #define PCIE_LNKCAP_SLS2SPEED(lnkcap) \ - ({ \ -- ((lnkcap) == PCI_EXP_LNKCAP_SLS_64_0GB ? PCIE_SPEED_64_0GT : \ -- (lnkcap) == PCI_EXP_LNKCAP_SLS_32_0GB ? PCIE_SPEED_32_0GT : \ -- (lnkcap) == PCI_EXP_LNKCAP_SLS_16_0GB ? PCIE_SPEED_16_0GT : \ -- (lnkcap) == PCI_EXP_LNKCAP_SLS_8_0GB ? PCIE_SPEED_8_0GT : \ -- (lnkcap) == PCI_EXP_LNKCAP_SLS_5_0GB ? PCIE_SPEED_5_0GT : \ -- (lnkcap) == PCI_EXP_LNKCAP_SLS_2_5GB ? PCIE_SPEED_2_5GT : \ -+ u32 lnkcap_sls = (lnkcap) & PCI_EXP_LNKCAP_SLS; \ -+ \ -+ (lnkcap_sls == PCI_EXP_LNKCAP_SLS_64_0GB ? PCIE_SPEED_64_0GT : \ -+ lnkcap_sls == PCI_EXP_LNKCAP_SLS_32_0GB ? PCIE_SPEED_32_0GT : \ -+ lnkcap_sls == PCI_EXP_LNKCAP_SLS_16_0GB ? PCIE_SPEED_16_0GT : \ -+ lnkcap_sls == PCI_EXP_LNKCAP_SLS_8_0GB ? PCIE_SPEED_8_0GT : \ -+ lnkcap_sls == PCI_EXP_LNKCAP_SLS_5_0GB ? PCIE_SPEED_5_0GT : \ -+ lnkcap_sls == PCI_EXP_LNKCAP_SLS_2_5GB ? PCIE_SPEED_2_5GT : \ - PCI_SPEED_UNKNOWN); \ - }) - -@@ -411,13 +413,17 @@ void pci_bus_put(struct pci_bus *bus); - PCI_SPEED_UNKNOWN) - - #define PCIE_LNKCTL2_TLS2SPEED(lnkctl2) \ -- ((lnkctl2) == PCI_EXP_LNKCTL2_TLS_64_0GT ? PCIE_SPEED_64_0GT : \ -- (lnkctl2) == PCI_EXP_LNKCTL2_TLS_32_0GT ? PCIE_SPEED_32_0GT : \ -- (lnkctl2) == PCI_EXP_LNKCTL2_TLS_16_0GT ? PCIE_SPEED_16_0GT : \ -- (lnkctl2) == PCI_EXP_LNKCTL2_TLS_8_0GT ? PCIE_SPEED_8_0GT : \ -- (lnkctl2) == PCI_EXP_LNKCTL2_TLS_5_0GT ? PCIE_SPEED_5_0GT : \ -- (lnkctl2) == PCI_EXP_LNKCTL2_TLS_2_5GT ? PCIE_SPEED_2_5GT : \ -- PCI_SPEED_UNKNOWN) -+({ \ -+ u16 lnkctl2_tls = (lnkctl2) & PCI_EXP_LNKCTL2_TLS; \ -+ \ -+ (lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_64_0GT ? PCIE_SPEED_64_0GT : \ -+ lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_32_0GT ? PCIE_SPEED_32_0GT : \ -+ lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_16_0GT ? PCIE_SPEED_16_0GT : \ -+ lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_8_0GT ? PCIE_SPEED_8_0GT : \ -+ lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_5_0GT ? PCIE_SPEED_5_0GT : \ -+ lnkctl2_tls == PCI_EXP_LNKCTL2_TLS_2_5GT ? PCIE_SPEED_2_5GT : \ -+ PCI_SPEED_UNKNOWN); \ -+}) - - /* PCIe speed to Mb/s reduced by encoding overhead */ - #define PCIE_SPEED2MBS_ENC(speed) \ -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/probe.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/probe.c ---- BPI-Router-Linux-kernel/drivers/pci/probe.c 2025-10-22 13:53:23.419328148 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/probe.c 2025-10-22 13:53:56.631168582 -0400 -@@ -1678,7 +1678,7 @@ void set_pcie_hotplug_bridge(struct pci_ - - pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, ®32); - if (reg32 & PCI_EXP_SLTCAP_HPC) -- pdev->is_hotplug_bridge = 1; -+ pdev->is_hotplug_bridge = pdev->is_pciehp = 1; - } - - static void set_pcie_thunderbolt(struct pci_dev *dev) -@@ -2508,6 +2508,7 @@ bool pci_bus_read_dev_vendor_id(struct p - } - EXPORT_SYMBOL(pci_bus_read_dev_vendor_id); - -+#if IS_ENABLED(CONFIG_PCI_PWRCTRL) - static struct platform_device *pci_pwrctrl_create_device(struct pci_bus *bus, int devfn) - { - struct pci_host_bridge *host = pci_find_host_bridge(bus); -@@ -2537,6 +2538,12 @@ static struct platform_device *pci_pwrct - - return pdev; - } -+#else -+static struct platform_device *pci_pwrctrl_create_device(struct pci_bus *bus, int devfn) -+{ -+ return NULL; -+} -+#endif - - /* - * Read the config data for a PCI device, sanity-check it, -diff -purNx .git BPI-Router-Linux-kernel/drivers/pci/quirks.c BPI-Router-Linux-kernel-6.16.12/drivers/pci/quirks.c ---- BPI-Router-Linux-kernel/drivers/pci/quirks.c 2025-10-22 13:53:23.419328148 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pci/quirks.c 2025-10-22 13:53:56.635168563 -0400 -@@ -105,13 +105,13 @@ int pcie_failed_link_retrain(struct pci_ - !pcie_cap_has_lnkctl2(dev) || !dev->link_active_reporting) - return ret; - -- pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &lnkctl2); - pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta); - if (!(lnksta & PCI_EXP_LNKSTA_DLLLA) && pcie_lbms_seen(dev, lnksta)) { -- u16 oldlnkctl2 = lnkctl2; -+ u16 oldlnkctl2; - - pci_info(dev, "broken device, retraining non-functional downstream link at 2.5GT/s\n"); - -+ pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &oldlnkctl2); - ret = pcie_set_target_speed(dev, PCIE_SPEED_2_5GT, false); - if (ret) { - pci_info(dev, "retraining failed\n"); -@@ -123,6 +123,8 @@ int pcie_failed_link_retrain(struct pci_ - pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &lnksta); - } - -+ pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &lnkctl2); -+ - if ((lnksta & PCI_EXP_LNKSTA_DLLLA) && - (lnkctl2 & PCI_EXP_LNKCTL2_TLS) == PCI_EXP_LNKCTL2_TLS_2_5GT && - pci_match_id(ids, dev)) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/pcmcia/omap_cf.c BPI-Router-Linux-kernel-6.16.12/drivers/pcmcia/omap_cf.c ---- BPI-Router-Linux-kernel/drivers/pcmcia/omap_cf.c 2025-10-22 13:53:23.419328148 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pcmcia/omap_cf.c 2025-10-22 13:53:56.635168563 -0400 -@@ -215,6 +215,8 @@ static int __init omap_cf_probe(struct p - return -EINVAL; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!res) -+ return -EINVAL; - - cf = kzalloc(sizeof *cf, GFP_KERNEL); - if (!cf) -@@ -302,7 +304,13 @@ static void __exit omap_cf_remove(struct - kfree(cf); - } - --static struct platform_driver omap_cf_driver = { -+/* -+ * omap_cf_remove() lives in .exit.text. For drivers registered via -+ * platform_driver_probe() this is ok because they cannot get unbound at -+ * runtime. So mark the driver struct with __refdata to prevent modpost -+ * triggering a section mismatch warning. -+ */ -+static struct platform_driver omap_cf_driver __refdata = { - .driver = { - .name = driver_name, - }, -diff -purNx .git BPI-Router-Linux-kernel/drivers/pcmcia/rsrc_iodyn.c BPI-Router-Linux-kernel-6.16.12/drivers/pcmcia/rsrc_iodyn.c ---- BPI-Router-Linux-kernel/drivers/pcmcia/rsrc_iodyn.c 2025-10-22 13:53:23.419328148 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pcmcia/rsrc_iodyn.c 2025-10-22 13:53:56.635168563 -0400 -@@ -62,6 +62,9 @@ static struct resource *__iodyn_find_io_ - unsigned long min = base; - int ret; - -+ if (!res) -+ return NULL; -+ - data.mask = align - 1; - data.offset = base & data.mask; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/pcmcia/rsrc_nonstatic.c BPI-Router-Linux-kernel-6.16.12/drivers/pcmcia/rsrc_nonstatic.c ---- BPI-Router-Linux-kernel/drivers/pcmcia/rsrc_nonstatic.c 2025-10-22 13:53:23.419328148 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pcmcia/rsrc_nonstatic.c 2025-10-22 13:53:56.635168563 -0400 -@@ -375,7 +375,9 @@ static int do_validate_mem(struct pcmcia - - if (validate && !s->fake_cis) { - /* move it to the validated data set */ -- add_interval(&s_data->mem_db_valid, base, size); -+ ret = add_interval(&s_data->mem_db_valid, base, size); -+ if (ret) -+ return ret; - sub_interval(&s_data->mem_db, base, size); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/perf/arm-cmn.c BPI-Router-Linux-kernel-6.16.12/drivers/perf/arm-cmn.c ---- BPI-Router-Linux-kernel/drivers/perf/arm-cmn.c 2025-10-22 13:53:23.419328148 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/perf/arm-cmn.c 2025-10-22 13:53:56.635168563 -0400 -@@ -2655,6 +2655,7 @@ static struct platform_driver arm_cmn_dr - .name = "arm-cmn", - .of_match_table = of_match_ptr(arm_cmn_of_match), - .acpi_match_table = ACPI_PTR(arm_cmn_acpi_match), -+ .suppress_bind_attrs = true, - }, - .probe = arm_cmn_probe, - .remove = arm_cmn_remove, -diff -purNx .git BPI-Router-Linux-kernel/drivers/perf/arm-ni.c BPI-Router-Linux-kernel-6.16.12/drivers/perf/arm-ni.c ---- BPI-Router-Linux-kernel/drivers/perf/arm-ni.c 2025-10-22 13:53:23.419328148 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/perf/arm-ni.c 2025-10-22 13:53:56.635168563 -0400 -@@ -544,6 +544,8 @@ static int arm_ni_init_cd(struct arm_ni - return err; - - cd->cpu = cpumask_local_spread(0, dev_to_node(ni->dev)); -+ irq_set_affinity(cd->irq, cpumask_of(cd->cpu)); -+ - cd->pmu = (struct pmu) { - .module = THIS_MODULE, - .parent = ni->dev, -@@ -707,6 +709,7 @@ static struct platform_driver arm_ni_dri - .name = "arm-ni", - .of_match_table = of_match_ptr(arm_ni_of_match), - .acpi_match_table = ACPI_PTR(arm_ni_acpi_match), -+ .suppress_bind_attrs = true, - }, - .probe = arm_ni_probe, - .remove = arm_ni_remove, -diff -purNx .git BPI-Router-Linux-kernel/drivers/perf/cxl_pmu.c BPI-Router-Linux-kernel-6.16.12/drivers/perf/cxl_pmu.c ---- BPI-Router-Linux-kernel/drivers/perf/cxl_pmu.c 2025-10-22 13:53:23.419328148 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/perf/cxl_pmu.c 2025-10-22 13:53:56.635168563 -0400 -@@ -873,7 +873,7 @@ static int cxl_pmu_probe(struct device * - return rc; - irq = rc; - -- irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s_overflow\n", dev_name); -+ irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s_overflow", dev_name); - if (!irq_name) - return -ENOMEM; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/phy/phy-core.c BPI-Router-Linux-kernel-6.16.12/drivers/phy/phy-core.c ---- BPI-Router-Linux-kernel/drivers/phy/phy-core.c 2025-10-22 13:53:23.419328148 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/phy/phy-core.c 2025-10-22 13:53:56.635168563 -0400 -@@ -994,7 +994,8 @@ struct phy *phy_create(struct device *de - } - - device_initialize(&phy->dev); -- mutex_init(&phy->mutex); -+ lockdep_register_key(&phy->lockdep_key); -+ mutex_init_with_key(&phy->mutex, &phy->lockdep_key); - - phy->dev.class = &phy_class; - phy->dev.parent = dev; -@@ -1259,6 +1260,8 @@ static void phy_release(struct device *d - dev_vdbg(dev, "releasing '%s'\n", dev_name(dev)); - debugfs_remove_recursive(phy->debugfs); - regulator_put(phy->pwr); -+ mutex_destroy(&phy->mutex); -+ lockdep_unregister_key(&phy->lockdep_key); - ida_free(&phy_ida, phy->id); - kfree(phy); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/phy/phy-snps-eusb2.c BPI-Router-Linux-kernel-6.16.12/drivers/phy/phy-snps-eusb2.c ---- BPI-Router-Linux-kernel/drivers/phy/phy-snps-eusb2.c 2025-10-22 13:53:23.419328148 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/phy/phy-snps-eusb2.c 2025-10-22 13:53:56.635168563 -0400 -@@ -437,6 +437,9 @@ static int qcom_snps_eusb2_hsphy_init(st - snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_HS_PHY_CTRL2, - USB2_SUSPEND_N_SEL, 0); - -+ snps_eusb2_hsphy_write_mask(phy->base, QCOM_USB_PHY_CFG0, -+ CMN_CTRL_OVERRIDE_EN, 0); -+ - return 0; - } - -@@ -567,9 +570,11 @@ static int snps_eusb2_hsphy_probe(struct - } - } - -- if (IS_ERR_OR_NULL(phy->ref_clk)) -- return dev_err_probe(dev, PTR_ERR(phy->ref_clk), -+ if (IS_ERR_OR_NULL(phy->ref_clk)) { -+ ret = phy->ref_clk ? PTR_ERR(phy->ref_clk) : -ENOENT; -+ return dev_err_probe(dev, ret, - "failed to get ref clk\n"); -+ } - - num = ARRAY_SIZE(phy->vregs); - for (i = 0; i < num; i++) -diff -purNx .git BPI-Router-Linux-kernel/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c BPI-Router-Linux-kernel-6.16.12/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c ---- BPI-Router-Linux-kernel/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c 2025-10-22 13:53:23.419328148 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/phy/qualcomm/phy-qcom-eusb2-repeater.c 2025-10-22 13:53:56.635168563 -0400 -@@ -37,32 +37,13 @@ - #define EUSB2_TUNE_EUSB_EQU 0x5A - #define EUSB2_TUNE_EUSB_HS_COMP_CUR 0x5B - --enum eusb2_reg_layout { -- TUNE_EUSB_HS_COMP_CUR, -- TUNE_EUSB_EQU, -- TUNE_EUSB_SLEW, -- TUNE_USB2_HS_COMP_CUR, -- TUNE_USB2_PREEM, -- TUNE_USB2_EQU, -- TUNE_USB2_SLEW, -- TUNE_SQUELCH_U, -- TUNE_HSDISC, -- TUNE_RES_FSDIF, -- TUNE_IUSB2, -- TUNE_USB2_CROSSOVER, -- NUM_TUNE_FIELDS, -- -- FORCE_VAL_5 = NUM_TUNE_FIELDS, -- FORCE_EN_5, -- -- EN_CTL1, -- -- RPTR_STATUS, -- LAYOUT_SIZE, -+struct eusb2_repeater_init_tbl_reg { -+ unsigned int reg; -+ unsigned int value; - }; - - struct eusb2_repeater_cfg { -- const u32 *init_tbl; -+ const struct eusb2_repeater_init_tbl_reg *init_tbl; - int init_tbl_num; - const char * const *vreg_list; - int num_vregs; -@@ -82,16 +63,16 @@ static const char * const pm8550b_vreg_l - "vdd18", "vdd3", - }; - --static const u32 pm8550b_init_tbl[NUM_TUNE_FIELDS] = { -- [TUNE_IUSB2] = 0x8, -- [TUNE_SQUELCH_U] = 0x3, -- [TUNE_USB2_PREEM] = 0x5, -+static const struct eusb2_repeater_init_tbl_reg pm8550b_init_tbl[] = { -+ { EUSB2_TUNE_IUSB2, 0x8 }, -+ { EUSB2_TUNE_SQUELCH_U, 0x3 }, -+ { EUSB2_TUNE_USB2_PREEM, 0x5 }, - }; - --static const u32 smb2360_init_tbl[NUM_TUNE_FIELDS] = { -- [TUNE_IUSB2] = 0x5, -- [TUNE_SQUELCH_U] = 0x3, -- [TUNE_USB2_PREEM] = 0x2, -+static const struct eusb2_repeater_init_tbl_reg smb2360_init_tbl[] = { -+ { EUSB2_TUNE_IUSB2, 0x5 }, -+ { EUSB2_TUNE_SQUELCH_U, 0x3 }, -+ { EUSB2_TUNE_USB2_PREEM, 0x2 }, - }; - - static const struct eusb2_repeater_cfg pm8550b_eusb2_cfg = { -@@ -129,17 +110,10 @@ static int eusb2_repeater_init(struct ph - struct eusb2_repeater *rptr = phy_get_drvdata(phy); - struct device_node *np = rptr->dev->of_node; - struct regmap *regmap = rptr->regmap; -- const u32 *init_tbl = rptr->cfg->init_tbl; -- u8 tune_usb2_preem = init_tbl[TUNE_USB2_PREEM]; -- u8 tune_hsdisc = init_tbl[TUNE_HSDISC]; -- u8 tune_iusb2 = init_tbl[TUNE_IUSB2]; - u32 base = rptr->base; -- u32 val; -+ u32 poll_val; - int ret; -- -- of_property_read_u8(np, "qcom,tune-usb2-amplitude", &tune_iusb2); -- of_property_read_u8(np, "qcom,tune-usb2-disc-thres", &tune_hsdisc); -- of_property_read_u8(np, "qcom,tune-usb2-preem", &tune_usb2_preem); -+ u8 val; - - ret = regulator_bulk_enable(rptr->cfg->num_vregs, rptr->vregs); - if (ret) -@@ -147,21 +121,24 @@ static int eusb2_repeater_init(struct ph - - regmap_write(regmap, base + EUSB2_EN_CTL1, EUSB2_RPTR_EN); - -- regmap_write(regmap, base + EUSB2_TUNE_EUSB_HS_COMP_CUR, init_tbl[TUNE_EUSB_HS_COMP_CUR]); -- regmap_write(regmap, base + EUSB2_TUNE_EUSB_EQU, init_tbl[TUNE_EUSB_EQU]); -- regmap_write(regmap, base + EUSB2_TUNE_EUSB_SLEW, init_tbl[TUNE_EUSB_SLEW]); -- regmap_write(regmap, base + EUSB2_TUNE_USB2_HS_COMP_CUR, init_tbl[TUNE_USB2_HS_COMP_CUR]); -- regmap_write(regmap, base + EUSB2_TUNE_USB2_EQU, init_tbl[TUNE_USB2_EQU]); -- regmap_write(regmap, base + EUSB2_TUNE_USB2_SLEW, init_tbl[TUNE_USB2_SLEW]); -- regmap_write(regmap, base + EUSB2_TUNE_SQUELCH_U, init_tbl[TUNE_SQUELCH_U]); -- regmap_write(regmap, base + EUSB2_TUNE_RES_FSDIF, init_tbl[TUNE_RES_FSDIF]); -- regmap_write(regmap, base + EUSB2_TUNE_USB2_CROSSOVER, init_tbl[TUNE_USB2_CROSSOVER]); -- -- regmap_write(regmap, base + EUSB2_TUNE_USB2_PREEM, tune_usb2_preem); -- regmap_write(regmap, base + EUSB2_TUNE_HSDISC, tune_hsdisc); -- regmap_write(regmap, base + EUSB2_TUNE_IUSB2, tune_iusb2); -- -- ret = regmap_read_poll_timeout(regmap, base + EUSB2_RPTR_STATUS, val, val & RPTR_OK, 10, 5); -+ /* Write registers from init table */ -+ for (int i = 0; i < rptr->cfg->init_tbl_num; i++) -+ regmap_write(regmap, base + rptr->cfg->init_tbl[i].reg, -+ rptr->cfg->init_tbl[i].value); -+ -+ /* Override registers from devicetree values */ -+ if (!of_property_read_u8(np, "qcom,tune-usb2-preem", &val)) -+ regmap_write(regmap, base + EUSB2_TUNE_USB2_PREEM, val); -+ -+ if (!of_property_read_u8(np, "qcom,tune-usb2-disc-thres", &val)) -+ regmap_write(regmap, base + EUSB2_TUNE_HSDISC, val); -+ -+ if (!of_property_read_u8(np, "qcom,tune-usb2-amplitude", &val)) -+ regmap_write(regmap, base + EUSB2_TUNE_IUSB2, val); -+ -+ /* Wait for status OK */ -+ ret = regmap_read_poll_timeout(regmap, base + EUSB2_RPTR_STATUS, poll_val, -+ poll_val & RPTR_OK, 10, 5); - if (ret) - dev_err(rptr->dev, "initialization timed-out\n"); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/phy/qualcomm/phy-qcom-m31.c BPI-Router-Linux-kernel-6.16.12/drivers/phy/qualcomm/phy-qcom-m31.c ---- BPI-Router-Linux-kernel/drivers/phy/qualcomm/phy-qcom-m31.c 2025-10-22 13:53:23.419328148 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/phy/qualcomm/phy-qcom-m31.c 2025-10-22 13:53:56.635168563 -0400 -@@ -58,14 +58,16 @@ - #define USB2_0_TX_ENABLE BIT(2) - - #define USB2PHY_USB_PHY_M31_XCFGI_4 0xc8 -- #define HSTX_SLEW_RATE_565PS GENMASK(1, 0) -+ #define HSTX_SLEW_RATE_400PS GENMASK(2, 0) - #define PLL_CHARGING_PUMP_CURRENT_35UA GENMASK(4, 3) - #define ODT_VALUE_38_02_OHM GENMASK(7, 6) - - #define USB2PHY_USB_PHY_M31_XCFGI_5 0xcc -- #define ODT_VALUE_45_02_OHM BIT(2) - #define HSTX_PRE_EMPHASIS_LEVEL_0_55MA BIT(0) - -+#define USB2PHY_USB_PHY_M31_XCFGI_9 0xdc -+ #define HSTX_CURRENT_17_1MA_385MV BIT(1) -+ - #define USB2PHY_USB_PHY_M31_XCFGI_11 0xe4 - #define XCFG_COARSE_TUNE_NUM BIT(1) - #define XCFG_FINE_TUNE_NUM BIT(3) -@@ -164,7 +166,7 @@ static struct m31_phy_regs m31_ipq5332_r - }, - { - USB2PHY_USB_PHY_M31_XCFGI_4, -- HSTX_SLEW_RATE_565PS | PLL_CHARGING_PUMP_CURRENT_35UA | ODT_VALUE_38_02_OHM, -+ HSTX_SLEW_RATE_400PS | PLL_CHARGING_PUMP_CURRENT_35UA | ODT_VALUE_38_02_OHM, - 0 - }, - { -@@ -174,10 +176,14 @@ static struct m31_phy_regs m31_ipq5332_r - }, - { - USB2PHY_USB_PHY_M31_XCFGI_5, -- ODT_VALUE_45_02_OHM | HSTX_PRE_EMPHASIS_LEVEL_0_55MA, -+ HSTX_PRE_EMPHASIS_LEVEL_0_55MA, - 4 - }, - { -+ USB2PHY_USB_PHY_M31_XCFGI_9, -+ HSTX_CURRENT_17_1MA_385MV, -+ }, -+ { - USB_PHY_UTMI_CTRL5, - 0x0, - 0 -diff -purNx .git BPI-Router-Linux-kernel/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c BPI-Router-Linux-kernel-6.16.12/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c ---- BPI-Router-Linux-kernel/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c 2025-10-22 13:53:56.635168563 -0400 -@@ -3064,6 +3064,14 @@ struct qmp_pcie { - struct clk_fixed_rate aux_clk_fixed; - }; - -+static bool qphy_checkbits(const void __iomem *base, u32 offset, u32 val) -+{ -+ u32 reg; -+ -+ reg = readl(base + offset); -+ return (reg & val) == val; -+} -+ - static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val) - { - u32 reg; -@@ -4332,16 +4340,21 @@ static int qmp_pcie_init(struct phy *phy - struct qmp_pcie *qmp = phy_get_drvdata(phy); - const struct qmp_phy_cfg *cfg = qmp->cfg; - void __iomem *pcs = qmp->pcs; -- bool phy_initialized = !!(readl(pcs + cfg->regs[QPHY_START_CTRL])); - int ret; - -- qmp->skip_init = qmp->nocsr_reset && phy_initialized; - /* -- * We need to check the existence of init sequences in two cases: -- * 1. The PHY doesn't support no_csr reset. -- * 2. The PHY supports no_csr reset but isn't initialized by bootloader. -- * As we can't skip init in these two cases. -+ * We can skip PHY initialization if all of the following conditions -+ * are met: -+ * 1. The PHY supports the nocsr_reset that preserves the PHY config. -+ * 2. The PHY was started (and not powered down again) by the -+ * bootloader, with all of the expected bits set correctly. -+ * In this case, we can continue without having the init sequence -+ * defined in the driver. - */ -+ qmp->skip_init = qmp->nocsr_reset && -+ qphy_checkbits(pcs, cfg->regs[QPHY_START_CTRL], SERDES_START | PCS_START) && -+ qphy_checkbits(pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], cfg->pwrdn_ctrl); -+ - if (!qmp->skip_init && !cfg->tbls.serdes_num) { - dev_err(qmp->dev, "Init sequence not available\n"); - return -ENODATA; -diff -purNx .git BPI-Router-Linux-kernel/drivers/phy/rockchip/phy-rockchip-pcie.c BPI-Router-Linux-kernel-6.16.12/drivers/phy/rockchip/phy-rockchip-pcie.c ---- BPI-Router-Linux-kernel/drivers/phy/rockchip/phy-rockchip-pcie.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/phy/rockchip/phy-rockchip-pcie.c 2025-10-22 13:53:56.635168563 -0400 -@@ -30,9 +30,8 @@ - #define PHY_CFG_ADDR_SHIFT 1 - #define PHY_CFG_DATA_MASK 0xf - #define PHY_CFG_ADDR_MASK 0x3f --#define PHY_CFG_RD_MASK 0x3ff - #define PHY_CFG_WR_ENABLE 1 --#define PHY_CFG_WR_DISABLE 1 -+#define PHY_CFG_WR_DISABLE 0 - #define PHY_CFG_WR_SHIFT 0 - #define PHY_CFG_WR_MASK 1 - #define PHY_CFG_PLL_LOCK 0x10 -@@ -160,6 +159,12 @@ static int rockchip_pcie_phy_power_on(st - - guard(mutex)(&rk_phy->pcie_mutex); - -+ regmap_write(rk_phy->reg_base, -+ rk_phy->phy_data->pcie_laneoff, -+ HIWORD_UPDATE(!PHY_LANE_IDLE_OFF, -+ PHY_LANE_IDLE_MASK, -+ PHY_LANE_IDLE_A_SHIFT + inst->index)); -+ - if (rk_phy->pwr_cnt++) { - return 0; - } -@@ -176,12 +181,6 @@ static int rockchip_pcie_phy_power_on(st - PHY_CFG_ADDR_MASK, - PHY_CFG_ADDR_SHIFT)); - -- regmap_write(rk_phy->reg_base, -- rk_phy->phy_data->pcie_laneoff, -- HIWORD_UPDATE(!PHY_LANE_IDLE_OFF, -- PHY_LANE_IDLE_MASK, -- PHY_LANE_IDLE_A_SHIFT + inst->index)); -- - /* - * No documented timeout value for phy operation below, - * so we make it large enough here. And we use loop-break -diff -purNx .git BPI-Router-Linux-kernel/drivers/phy/tegra/xusb.h BPI-Router-Linux-kernel-6.16.12/drivers/phy/tegra/xusb.h ---- BPI-Router-Linux-kernel/drivers/phy/tegra/xusb.h 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/phy/tegra/xusb.h 2025-10-22 13:53:56.635168563 -0400 -@@ -434,6 +434,7 @@ struct tegra_xusb_padctl_soc { - bool need_fake_usb3_port; - bool poll_trk_completed; - bool trk_hw_mode; -+ bool trk_update_on_idle; - bool supports_lp_cfg_en; - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/phy/tegra/xusb-tegra186.c BPI-Router-Linux-kernel-6.16.12/drivers/phy/tegra/xusb-tegra186.c ---- BPI-Router-Linux-kernel/drivers/phy/tegra/xusb-tegra186.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/phy/tegra/xusb-tegra186.c 2025-10-22 13:53:56.635168563 -0400 -@@ -648,14 +648,15 @@ static void tegra186_utmi_bias_pad_power - udelay(100); - } - -- if (padctl->soc->trk_hw_mode) { -- value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL2); -- value |= USB2_TRK_HW_MODE; -+ value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL2); -+ if (padctl->soc->trk_update_on_idle) - value &= ~CYA_TRK_CODE_UPDATE_ON_IDLE; -- padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL2); -- } else { -+ if (padctl->soc->trk_hw_mode) -+ value |= USB2_TRK_HW_MODE; -+ padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL2); -+ -+ if (!padctl->soc->trk_hw_mode) - clk_disable_unprepare(priv->usb2_trk_clk); -- } - } - - static void tegra186_utmi_bias_pad_power_off(struct tegra_xusb_padctl *padctl) -@@ -782,13 +783,15 @@ static int tegra186_xusb_padctl_vbus_ove - } - - static int tegra186_xusb_padctl_id_override(struct tegra_xusb_padctl *padctl, -- bool status) -+ struct tegra_xusb_usb2_port *port, bool status) - { -- u32 value; -+ u32 value, id_override; -+ int err = 0; - - dev_dbg(padctl->dev, "%s id override\n", status ? "set" : "clear"); - - value = padctl_readl(padctl, USB2_VBUS_ID); -+ id_override = value & ID_OVERRIDE(~0); - - if (status) { - if (value & VBUS_OVERRIDE) { -@@ -799,14 +802,34 @@ static int tegra186_xusb_padctl_id_overr - value = padctl_readl(padctl, USB2_VBUS_ID); - } - -- value &= ~ID_OVERRIDE(~0); -- value |= ID_OVERRIDE_GROUNDED; -+ if (id_override != ID_OVERRIDE_GROUNDED) { -+ value &= ~ID_OVERRIDE(~0); -+ value |= ID_OVERRIDE_GROUNDED; -+ padctl_writel(padctl, value, USB2_VBUS_ID); -+ -+ err = regulator_enable(port->supply); -+ if (err) { -+ dev_err(padctl->dev, "Failed to enable regulator: %d\n", err); -+ return err; -+ } -+ } - } else { -- value &= ~ID_OVERRIDE(~0); -- value |= ID_OVERRIDE_FLOATING; -- } -+ if (id_override == ID_OVERRIDE_GROUNDED) { -+ /* -+ * The regulator is disabled only when the role transitions -+ * from USB_ROLE_HOST to USB_ROLE_NONE. -+ */ -+ err = regulator_disable(port->supply); -+ if (err) { -+ dev_err(padctl->dev, "Failed to disable regulator: %d\n", err); -+ return err; -+ } - -- padctl_writel(padctl, value, USB2_VBUS_ID); -+ value &= ~ID_OVERRIDE(~0); -+ value |= ID_OVERRIDE_FLOATING; -+ padctl_writel(padctl, value, USB2_VBUS_ID); -+ } -+ } - - return 0; - } -@@ -826,27 +849,20 @@ static int tegra186_utmi_phy_set_mode(st - - if (mode == PHY_MODE_USB_OTG) { - if (submode == USB_ROLE_HOST) { -- tegra186_xusb_padctl_id_override(padctl, true); -- -- err = regulator_enable(port->supply); -+ err = tegra186_xusb_padctl_id_override(padctl, port, true); -+ if (err) -+ goto out; - } else if (submode == USB_ROLE_DEVICE) { - tegra186_xusb_padctl_vbus_override(padctl, true); - } else if (submode == USB_ROLE_NONE) { -- /* -- * When port is peripheral only or role transitions to -- * USB_ROLE_NONE from USB_ROLE_DEVICE, regulator is not -- * enabled. -- */ -- if (regulator_is_enabled(port->supply)) -- regulator_disable(port->supply); -- -- tegra186_xusb_padctl_id_override(padctl, false); -+ err = tegra186_xusb_padctl_id_override(padctl, port, false); -+ if (err) -+ goto out; - tegra186_xusb_padctl_vbus_override(padctl, false); - } - } -- -+out: - mutex_unlock(&padctl->lock); -- - return err; - } - -@@ -1710,7 +1726,8 @@ const struct tegra_xusb_padctl_soc tegra - .num_supplies = ARRAY_SIZE(tegra194_xusb_padctl_supply_names), - .supports_gen2 = true, - .poll_trk_completed = true, -- .trk_hw_mode = true, -+ .trk_hw_mode = false, -+ .trk_update_on_idle = true, - .supports_lp_cfg_en = true, - }; - EXPORT_SYMBOL_GPL(tegra234_xusb_padctl_soc); -diff -purNx .git BPI-Router-Linux-kernel/drivers/phy/tegra/xusb-tegra210.c BPI-Router-Linux-kernel-6.16.12/drivers/phy/tegra/xusb-tegra210.c ---- BPI-Router-Linux-kernel/drivers/phy/tegra/xusb-tegra210.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/phy/tegra/xusb-tegra210.c 2025-10-22 13:53:56.635168563 -0400 -@@ -3164,18 +3164,22 @@ tegra210_xusb_padctl_probe(struct device - } - - pdev = of_find_device_by_node(np); -+ of_node_put(np); - if (!pdev) { - dev_warn(dev, "PMC device is not available\n"); - goto out; - } - -- if (!platform_get_drvdata(pdev)) -+ if (!platform_get_drvdata(pdev)) { -+ put_device(&pdev->dev); - return ERR_PTR(-EPROBE_DEFER); -+ } - - padctl->regmap = dev_get_regmap(&pdev->dev, "usb_sleepwalk"); - if (!padctl->regmap) - dev_info(dev, "failed to find PMC regmap\n"); - -+ put_device(&pdev->dev); - out: - return &padctl->base; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/phy/ti/phy-omap-usb2.c BPI-Router-Linux-kernel-6.16.12/drivers/phy/ti/phy-omap-usb2.c ---- BPI-Router-Linux-kernel/drivers/phy/ti/phy-omap-usb2.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/phy/ti/phy-omap-usb2.c 2025-10-22 13:53:56.635168563 -0400 -@@ -363,6 +363,13 @@ static void omap_usb2_init_errata(struct - phy->flags |= OMAP_USB2_DISABLE_CHRG_DET; - } - -+static void omap_usb2_put_device(void *_dev) -+{ -+ struct device *dev = _dev; -+ -+ put_device(dev); -+} -+ - static int omap_usb2_probe(struct platform_device *pdev) - { - struct omap_usb *phy; -@@ -373,6 +380,7 @@ static int omap_usb2_probe(struct platfo - struct device_node *control_node; - struct platform_device *control_pdev; - const struct usb_phy_data *phy_data; -+ int ret; - - phy_data = device_get_match_data(&pdev->dev); - if (!phy_data) -@@ -423,6 +431,11 @@ static int omap_usb2_probe(struct platfo - return -EINVAL; - } - phy->control_dev = &control_pdev->dev; -+ -+ ret = devm_add_action_or_reset(&pdev->dev, omap_usb2_put_device, -+ phy->control_dev); -+ if (ret) -+ return ret; - } else { - if (of_property_read_u32_index(node, - "syscon-phy-power", 1, -diff -purNx .git BPI-Router-Linux-kernel/drivers/phy/ti/phy-ti-pipe3.c BPI-Router-Linux-kernel-6.16.12/drivers/phy/ti/phy-ti-pipe3.c ---- BPI-Router-Linux-kernel/drivers/phy/ti/phy-ti-pipe3.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/phy/ti/phy-ti-pipe3.c 2025-10-22 13:53:56.635168563 -0400 -@@ -667,12 +667,20 @@ static int ti_pipe3_get_clk(struct ti_pi - return 0; - } - -+static void ti_pipe3_put_device(void *_dev) -+{ -+ struct device *dev = _dev; -+ -+ put_device(dev); -+} -+ - static int ti_pipe3_get_sysctrl(struct ti_pipe3 *phy) - { - struct device *dev = phy->dev; - struct device_node *node = dev->of_node; - struct device_node *control_node; - struct platform_device *control_pdev; -+ int ret; - - phy->phy_power_syscon = syscon_regmap_lookup_by_phandle(node, - "syscon-phy-power"); -@@ -704,6 +712,11 @@ static int ti_pipe3_get_sysctrl(struct t - } - - phy->control_dev = &control_pdev->dev; -+ -+ ret = devm_add_action_or_reset(dev, ti_pipe3_put_device, -+ phy->control_dev); -+ if (ret) -+ return ret; - } - - if (phy->mode == PIPE3_MODE_PCIE) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/berlin/berlin.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/berlin/berlin.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/berlin/berlin.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/berlin/berlin.c 2025-10-22 13:53:56.635168563 -0400 -@@ -204,6 +204,7 @@ static int berlin_pinctrl_build_state(st - const struct berlin_desc_group *desc_group; - const struct berlin_desc_function *desc_function; - int i, max_functions = 0; -+ struct pinfunction *new_functions; - - pctrl->nfunctions = 0; - -@@ -229,12 +230,15 @@ static int berlin_pinctrl_build_state(st - } - } - -- pctrl->functions = krealloc(pctrl->functions, -+ new_functions = krealloc(pctrl->functions, - pctrl->nfunctions * sizeof(*pctrl->functions), - GFP_KERNEL); -- if (!pctrl->functions) -+ if (!new_functions) { -+ kfree(pctrl->functions); - return -ENOMEM; -+ } - -+ pctrl->functions = new_functions; - /* map functions to theirs groups */ - for (i = 0; i < pctrl->desc->ngroups; i++) { - desc_group = pctrl->desc->groups + i; -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/cirrus/pinctrl-madera-core.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/cirrus/pinctrl-madera-core.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/cirrus/pinctrl-madera-core.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/cirrus/pinctrl-madera-core.c 2025-10-22 13:53:56.635168563 -0400 -@@ -1061,8 +1061,9 @@ static int madera_pin_probe(struct platf - - /* if the configuration is provided through pdata, apply it */ - if (pdata->gpio_configs) { -- ret = pinctrl_register_mappings(pdata->gpio_configs, -- pdata->n_gpio_configs); -+ ret = devm_pinctrl_register_mappings(priv->dev, -+ pdata->gpio_configs, -+ pdata->n_gpio_configs); - if (ret) - return dev_err_probe(priv->dev, ret, - "Failed to register pdata mappings\n"); -@@ -1081,17 +1082,8 @@ static int madera_pin_probe(struct platf - return 0; - } - --static void madera_pin_remove(struct platform_device *pdev) --{ -- struct madera_pin_private *priv = platform_get_drvdata(pdev); -- -- if (priv->madera->pdata.gpio_configs) -- pinctrl_unregister_mappings(priv->madera->pdata.gpio_configs); --} -- - static struct platform_driver madera_pin_driver = { - .probe = madera_pin_probe, -- .remove = madera_pin_remove, - .driver = { - .name = "madera-pinctrl", - }, -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/Kconfig ---- BPI-Router-Linux-kernel/drivers/pinctrl/Kconfig 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/Kconfig 2025-10-22 13:53:56.635168563 -0400 -@@ -527,6 +527,7 @@ config PINCTRL_STMFX - tristate "STMicroelectronics STMFX GPIO expander pinctrl driver" - depends on I2C - depends on OF_GPIO -+ depends on HAS_IOMEM - select GENERIC_PINCONF - select GPIOLIB_IRQCHIP - select MFD_STMFX -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/mediatek/pinctrl-airoha.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/mediatek/pinctrl-airoha.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/mediatek/pinctrl-airoha.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/mediatek/pinctrl-airoha.c 2025-10-22 13:53:56.635168563 -0400 -@@ -108,6 +108,9 @@ - #define JTAG_UDI_EN_MASK BIT(4) - #define JTAG_DFD_EN_MASK BIT(3) - -+#define REG_FORCE_GPIO_EN 0x0228 -+#define FORCE_GPIO_EN(n) BIT(n) -+ - /* LED MAP */ - #define REG_LAN_LED0_MAPPING 0x027c - #define REG_LAN_LED1_MAPPING 0x0280 -@@ -719,16 +722,16 @@ static const struct airoha_pinctrl_func_ - .name = "mdio", - .regmap[0] = { - AIROHA_FUNC_MUX, -- REG_GPIO_PON_MODE, -- GPIO_SGMII_MDIO_MODE_MASK, -- GPIO_SGMII_MDIO_MODE_MASK -- }, -- .regmap[1] = { -- AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, - GPIO_MDC_IO_MASTER_MODE_MODE, - GPIO_MDC_IO_MASTER_MODE_MODE - }, -+ .regmap[1] = { -+ AIROHA_FUNC_MUX, -+ REG_FORCE_GPIO_EN, -+ FORCE_GPIO_EN(1) | FORCE_GPIO_EN(2), -+ FORCE_GPIO_EN(1) | FORCE_GPIO_EN(2) -+ }, - .regmap_size = 2, - }, - }; -@@ -1752,8 +1755,8 @@ static const struct airoha_pinctrl_func_ - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, -- GPIO_LAN3_LED0_MODE_MASK, -- GPIO_LAN3_LED0_MODE_MASK -+ GPIO_LAN3_LED1_MODE_MASK, -+ GPIO_LAN3_LED1_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, -@@ -1816,8 +1819,8 @@ static const struct airoha_pinctrl_func_ - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, -- GPIO_LAN3_LED0_MODE_MASK, -- GPIO_LAN3_LED0_MODE_MASK -+ GPIO_LAN3_LED1_MODE_MASK, -+ GPIO_LAN3_LED1_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, -@@ -1880,8 +1883,8 @@ static const struct airoha_pinctrl_func_ - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, -- GPIO_LAN3_LED0_MODE_MASK, -- GPIO_LAN3_LED0_MODE_MASK -+ GPIO_LAN3_LED1_MODE_MASK, -+ GPIO_LAN3_LED1_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, -@@ -1944,8 +1947,8 @@ static const struct airoha_pinctrl_func_ - .regmap[0] = { - AIROHA_FUNC_MUX, - REG_GPIO_2ND_I2C_MODE, -- GPIO_LAN3_LED0_MODE_MASK, -- GPIO_LAN3_LED0_MODE_MASK -+ GPIO_LAN3_LED1_MODE_MASK, -+ GPIO_LAN3_LED1_MODE_MASK - }, - .regmap[1] = { - AIROHA_FUNC_MUX, -@@ -2696,7 +2699,7 @@ static int airoha_pinconf_get(struct pin - arg = 1; - break; - default: -- return -EOPNOTSUPP; -+ return -ENOTSUPP; - } - - *config = pinconf_to_config_packed(param, arg); -@@ -2788,7 +2791,7 @@ static int airoha_pinconf_set(struct pin - break; - } - default: -- return -EOPNOTSUPP; -+ return -ENOTSUPP; - } - } - -@@ -2805,10 +2808,10 @@ static int airoha_pinconf_group_get(stru - if (airoha_pinconf_get(pctrl_dev, - airoha_pinctrl_groups[group].pins[i], - config)) -- return -EOPNOTSUPP; -+ return -ENOTSUPP; - - if (i && cur_config != *config) -- return -EOPNOTSUPP; -+ return -ENOTSUPP; - - cur_config = *config; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/nuvoton/pinctrl-ma35.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/nuvoton/pinctrl-ma35.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/nuvoton/pinctrl-ma35.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/nuvoton/pinctrl-ma35.c 2025-10-22 13:53:56.635168563 -0400 -@@ -1074,7 +1074,10 @@ static int ma35_pinctrl_probe_dt(struct - u32 idx = 0; - int ret; - -- for_each_gpiochip_node(dev, child) { -+ device_for_each_child_node(dev, child) { -+ if (fwnode_property_present(child, "gpio-controller")) -+ continue; -+ - npctl->nfunctions++; - npctl->ngroups += of_get_child_count(to_of_node(child)); - } -@@ -1092,7 +1095,10 @@ static int ma35_pinctrl_probe_dt(struct - if (!npctl->groups) - return -ENOMEM; - -- for_each_gpiochip_node(dev, child) { -+ device_for_each_child_node(dev, child) { -+ if (fwnode_property_present(child, "gpio-controller")) -+ continue; -+ - ret = ma35_pinctrl_parse_functions(child, npctl, idx++); - if (ret) { - fwnode_handle_put(child); -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/pinctrl-amd.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/pinctrl-amd.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/pinctrl-amd.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/pinctrl-amd.c 2025-10-22 13:53:56.635168563 -0400 -@@ -979,6 +979,17 @@ static int amd_gpio_suspend_hibernate_co - pin, is_suspend ? "suspend" : "hibernate"); - } - -+ /* -+ * debounce enabled over suspend has shown issues with a GPIO -+ * being unable to wake the system, as we're only interested in -+ * the actual wakeup event, clear it. -+ */ -+ if (gpio_dev->saved_regs[i] & (DB_CNTRl_MASK << DB_CNTRL_OFF)) { -+ amd_gpio_set_debounce(gpio_dev, pin, 0); -+ pm_pr_dbg("Clearing debounce for GPIO #%d during %s.\n", -+ pin, is_suspend ? "suspend" : "hibernate"); -+ } -+ - raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/pinctrl-aw9523.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/pinctrl-aw9523.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/pinctrl-aw9523.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/pinctrl-aw9523.c 2025-10-22 13:53:56.635168563 -0400 -@@ -784,7 +784,7 @@ static int aw9523_init_gpiochip(struct a - gc->set_config = gpiochip_generic_config; - gc->parent = dev; - gc->owner = THIS_MODULE; -- gc->can_sleep = false; -+ gc->can_sleep = true; - - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/pinctrl-k230.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/pinctrl-k230.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/pinctrl-k230.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/pinctrl-k230.c 2025-10-22 13:53:56.635168563 -0400 -@@ -477,6 +477,10 @@ static int k230_pinctrl_parse_groups(str - grp->name = np->name; - - list = of_get_property(np, "pinmux", &size); -+ if (!list) { -+ dev_err(dev, "failed to get pinmux property\n"); -+ return -EINVAL; -+ } - size /= sizeof(*list); - - grp->num_pins = size; -@@ -586,6 +590,7 @@ static int k230_pinctrl_probe(struct pla - struct device *dev = &pdev->dev; - struct k230_pinctrl *info; - struct pinctrl_desc *pctl; -+ int ret; - - info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); - if (!info) -@@ -611,19 +616,21 @@ static int k230_pinctrl_probe(struct pla - return dev_err_probe(dev, PTR_ERR(info->regmap_base), - "failed to init regmap\n"); - -+ ret = k230_pinctrl_parse_dt(pdev, info); -+ if (ret) -+ return ret; -+ - info->pctl_dev = devm_pinctrl_register(dev, pctl, info); - if (IS_ERR(info->pctl_dev)) - return dev_err_probe(dev, PTR_ERR(info->pctl_dev), - "devm_pinctrl_register failed\n"); - -- k230_pinctrl_parse_dt(pdev, info); -- - return 0; - } - - static const struct of_device_id k230_dt_ids[] = { - { .compatible = "canaan,k230-pinctrl", }, -- { /* sintenel */ } -+ { /* sentinel */ } - }; - MODULE_DEVICE_TABLE(of, k230_dt_ids); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/pinctrl-st.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/pinctrl-st.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/pinctrl-st.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/pinctrl-st.c 2025-10-22 13:53:56.635168563 -0400 -@@ -374,11 +374,6 @@ static struct st_pio_control *st_get_pio - } - - /* Low level functions.. */ --static inline int st_gpio_bank(int gpio) --{ -- return gpio/ST_GPIO_PINS_PER_BANK; --} -- - static inline int st_gpio_pin(int gpio) - { - return gpio%ST_GPIO_PINS_PER_BANK; -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/pinctrl-tb10x.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/pinctrl-tb10x.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/pinctrl-tb10x.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/pinctrl-tb10x.c 2025-10-22 13:53:56.635168563 -0400 -@@ -823,7 +823,7 @@ static struct platform_driver tb10x_pinc - .remove = tb10x_pinctrl_remove, - .driver = { - .name = "tb10x_pinctrl", -- .of_match_table = of_match_ptr(tb10x_pinctrl_dt_ids), -+ .of_match_table = tb10x_pinctrl_dt_ids, - } - }; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/pinmux.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/pinmux.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/pinmux.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/pinmux.c 2025-10-22 13:53:56.635168563 -0400 -@@ -236,18 +236,7 @@ static const char *pin_free(struct pinct - if (desc->mux_usecount) - return NULL; - } -- } -- -- /* -- * If there is no kind of request function for the pin we just assume -- * we got it by default and proceed. -- */ -- if (gpio_range && ops->gpio_disable_free) -- ops->gpio_disable_free(pctldev, gpio_range, pin); -- else if (ops->free) -- ops->free(pctldev, pin); - -- scoped_guard(mutex, &desc->mux_lock) { - if (gpio_range) { - owner = desc->gpio_owner; - desc->gpio_owner = NULL; -@@ -258,6 +247,15 @@ static const char *pin_free(struct pinct - } - } - -+ /* -+ * If there is no kind of request function for the pin we just assume -+ * we got it by default and proceed. -+ */ -+ if (gpio_range && ops->gpio_disable_free) -+ ops->gpio_disable_free(pctldev, gpio_range, pin); -+ else if (ops->free) -+ ops->free(pctldev, pin); -+ - module_put(pctldev->owner); - - return owner; -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-apq8064.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-apq8064.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-apq8064.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-apq8064.c 2025-10-22 13:53:56.635168563 -0400 -@@ -629,7 +629,6 @@ static struct platform_driver apq8064_pi - .of_match_table = apq8064_pinctrl_of_match, - }, - .probe = apq8064_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init apq8064_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-apq8084.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-apq8084.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-apq8084.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-apq8084.c 2025-10-22 13:53:56.635168563 -0400 -@@ -1207,7 +1207,6 @@ static struct platform_driver apq8084_pi - .of_match_table = apq8084_pinctrl_of_match, - }, - .probe = apq8084_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init apq8084_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-ipq4019.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-ipq4019.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-ipq4019.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-ipq4019.c 2025-10-22 13:53:56.635168563 -0400 -@@ -710,7 +710,6 @@ static struct platform_driver ipq4019_pi - .of_match_table = ipq4019_pinctrl_of_match, - }, - .probe = ipq4019_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init ipq4019_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-ipq5018.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-ipq5018.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-ipq5018.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-ipq5018.c 2025-10-22 13:53:56.635168563 -0400 -@@ -754,7 +754,6 @@ static struct platform_driver ipq5018_pi - .of_match_table = ipq5018_pinctrl_of_match, - }, - .probe = ipq5018_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init ipq5018_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-ipq5332.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-ipq5332.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-ipq5332.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-ipq5332.c 2025-10-22 13:53:56.635168563 -0400 -@@ -834,7 +834,6 @@ static struct platform_driver ipq5332_pi - .of_match_table = ipq5332_pinctrl_of_match, - }, - .probe = ipq5332_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init ipq5332_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-ipq5424.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-ipq5424.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-ipq5424.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-ipq5424.c 2025-10-22 13:53:56.635168563 -0400 -@@ -791,7 +791,6 @@ static struct platform_driver ipq5424_pi - .of_match_table = ipq5424_pinctrl_of_match, - }, - .probe = ipq5424_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init ipq5424_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-ipq6018.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-ipq6018.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-ipq6018.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-ipq6018.c 2025-10-22 13:53:56.635168563 -0400 -@@ -1080,7 +1080,6 @@ static struct platform_driver ipq6018_pi - .of_match_table = ipq6018_pinctrl_of_match, - }, - .probe = ipq6018_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init ipq6018_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-ipq8064.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-ipq8064.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-ipq8064.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-ipq8064.c 2025-10-22 13:53:56.635168563 -0400 -@@ -631,7 +631,6 @@ static struct platform_driver ipq8064_pi - .of_match_table = ipq8064_pinctrl_of_match, - }, - .probe = ipq8064_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init ipq8064_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-ipq8074.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-ipq8074.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-ipq8074.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-ipq8074.c 2025-10-22 13:53:56.635168563 -0400 -@@ -1041,7 +1041,6 @@ static struct platform_driver ipq8074_pi - .of_match_table = ipq8074_pinctrl_of_match, - }, - .probe = ipq8074_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init ipq8074_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-ipq9574.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-ipq9574.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-ipq9574.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-ipq9574.c 2025-10-22 13:53:56.639168544 -0400 -@@ -799,7 +799,6 @@ static struct platform_driver ipq9574_pi - .of_match_table = ipq9574_pinctrl_of_match, - }, - .probe = ipq9574_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init ipq9574_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-mdm9607.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-mdm9607.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-mdm9607.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-mdm9607.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1059,7 +1059,6 @@ static struct platform_driver mdm9607_pi - .of_match_table = mdm9607_pinctrl_of_match, - }, - .probe = mdm9607_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init mdm9607_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-mdm9615.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-mdm9615.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-mdm9615.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-mdm9615.c 2025-10-22 13:53:56.639168544 -0400 -@@ -446,7 +446,6 @@ static struct platform_driver mdm9615_pi - .of_match_table = mdm9615_pinctrl_of_match, - }, - .probe = mdm9615_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init mdm9615_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8226.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8226.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8226.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8226.c 2025-10-22 13:53:56.639168544 -0400 -@@ -654,7 +654,6 @@ static struct platform_driver msm8226_pi - .of_match_table = msm8226_pinctrl_of_match, - }, - .probe = msm8226_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init msm8226_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8660.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8660.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8660.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8660.c 2025-10-22 13:53:56.639168544 -0400 -@@ -981,7 +981,6 @@ static struct platform_driver msm8660_pi - .of_match_table = msm8660_pinctrl_of_match, - }, - .probe = msm8660_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init msm8660_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8909.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8909.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8909.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8909.c 2025-10-22 13:53:56.639168544 -0400 -@@ -929,7 +929,6 @@ static struct platform_driver msm8909_pi - .of_match_table = msm8909_pinctrl_of_match, - }, - .probe = msm8909_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init msm8909_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8916.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8916.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8916.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8916.c 2025-10-22 13:53:56.639168544 -0400 -@@ -969,7 +969,6 @@ static struct platform_driver msm8916_pi - .of_match_table = msm8916_pinctrl_of_match, - }, - .probe = msm8916_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init msm8916_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8917.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8917.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8917.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8917.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1607,7 +1607,6 @@ static struct platform_driver msm8917_pi - .of_match_table = msm8917_pinctrl_of_match, - }, - .probe = msm8917_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init msm8917_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8953.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8953.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8953.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8953.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1816,7 +1816,6 @@ static struct platform_driver msm8953_pi - .of_match_table = msm8953_pinctrl_of_match, - }, - .probe = msm8953_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init msm8953_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8960.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8960.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8960.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8960.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1246,7 +1246,6 @@ static struct platform_driver msm8960_pi - .of_match_table = msm8960_pinctrl_of_match, - }, - .probe = msm8960_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init msm8960_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8976.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8976.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8976.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8976.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1096,7 +1096,6 @@ static struct platform_driver msm8976_pi - .of_match_table = msm8976_pinctrl_of_match, - }, - .probe = msm8976_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init msm8976_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8994.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8994.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8994.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8994.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1343,7 +1343,6 @@ static struct platform_driver msm8994_pi - .of_match_table = msm8994_pinctrl_of_match, - }, - .probe = msm8994_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init msm8994_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8996.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8996.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8996.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8996.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1920,7 +1920,6 @@ static struct platform_driver msm8996_pi - .of_match_table = msm8996_pinctrl_of_match, - }, - .probe = msm8996_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init msm8996_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8998.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8998.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8998.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8998.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1535,7 +1535,6 @@ static struct platform_driver msm8998_pi - .of_match_table = msm8998_pinctrl_of_match, - }, - .probe = msm8998_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init msm8998_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8x74.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8x74.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm8x74.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm8x74.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1083,7 +1083,6 @@ static struct platform_driver msm8x74_pi - .of_match_table = msm8x74_pinctrl_of_match, - }, - .probe = msm8x74_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init msm8x74_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm.c 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1038,6 +1038,25 @@ static bool msm_gpio_needs_dual_edge_par - test_bit(d->hwirq, pctrl->skip_wake_irqs); - } - -+static void msm_gpio_irq_init_valid_mask(struct gpio_chip *gc, -+ unsigned long *valid_mask, -+ unsigned int ngpios) -+{ -+ struct msm_pinctrl *pctrl = gpiochip_get_data(gc); -+ const struct msm_pingroup *g; -+ int i; -+ -+ bitmap_fill(valid_mask, ngpios); -+ -+ for (i = 0; i < ngpios; i++) { -+ g = &pctrl->soc->groups[i]; -+ -+ if (g->intr_detection_width != 1 && -+ g->intr_detection_width != 2) -+ clear_bit(i, valid_mask); -+ } -+} -+ - static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type) - { - struct gpio_chip *gc = irq_data_get_irq_chip_data(d); -@@ -1441,8 +1460,9 @@ static int msm_gpio_init(struct msm_pinc - girq->default_type = IRQ_TYPE_NONE; - girq->handler = handle_bad_irq; - girq->parents[0] = pctrl->irq; -+ girq->init_valid_mask = msm_gpio_irq_init_valid_mask; - -- ret = gpiochip_add_data(&pctrl->chip, pctrl); -+ ret = devm_gpiochip_add_data(pctrl->dev, &pctrl->chip, pctrl); - if (ret) { - dev_err(pctrl->dev, "Failed register gpiochip\n"); - return ret; -@@ -1463,7 +1483,6 @@ static int msm_gpio_init(struct msm_pinc - dev_name(pctrl->dev), 0, 0, chip->ngpio); - if (ret) { - dev_err(pctrl->dev, "Failed to add pin range\n"); -- gpiochip_remove(&pctrl->chip); - return ret; - } - } -@@ -1599,13 +1618,5 @@ int msm_pinctrl_probe(struct platform_de - } - EXPORT_SYMBOL(msm_pinctrl_probe); - --void msm_pinctrl_remove(struct platform_device *pdev) --{ -- struct msm_pinctrl *pctrl = platform_get_drvdata(pdev); -- -- gpiochip_remove(&pctrl->chip); --} --EXPORT_SYMBOL(msm_pinctrl_remove); -- - MODULE_DESCRIPTION("Qualcomm Technologies, Inc. TLMM driver"); - MODULE_LICENSE("GPL v2"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm.h BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm.h ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-msm.h 2025-10-22 13:53:23.423328129 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-msm.h 2025-10-22 13:53:56.639168544 -0400 -@@ -171,6 +171,5 @@ extern const struct dev_pm_ops msm_pinct - - int msm_pinctrl_probe(struct platform_device *pdev, - const struct msm_pinctrl_soc_data *soc_data); --void msm_pinctrl_remove(struct platform_device *pdev); - - #endif -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-qcm2290.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-qcm2290.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-qcm2290.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-qcm2290.c 2025-10-22 13:53:56.639168544 -0400 -@@ -167,6 +167,10 @@ static const struct pinctrl_pin_desc qcm - PINCTRL_PIN(62, "GPIO_62"), - PINCTRL_PIN(63, "GPIO_63"), - PINCTRL_PIN(64, "GPIO_64"), -+ PINCTRL_PIN(65, "GPIO_65"), -+ PINCTRL_PIN(66, "GPIO_66"), -+ PINCTRL_PIN(67, "GPIO_67"), -+ PINCTRL_PIN(68, "GPIO_68"), - PINCTRL_PIN(69, "GPIO_69"), - PINCTRL_PIN(70, "GPIO_70"), - PINCTRL_PIN(71, "GPIO_71"), -@@ -181,12 +185,17 @@ static const struct pinctrl_pin_desc qcm - PINCTRL_PIN(80, "GPIO_80"), - PINCTRL_PIN(81, "GPIO_81"), - PINCTRL_PIN(82, "GPIO_82"), -+ PINCTRL_PIN(83, "GPIO_83"), -+ PINCTRL_PIN(84, "GPIO_84"), -+ PINCTRL_PIN(85, "GPIO_85"), - PINCTRL_PIN(86, "GPIO_86"), - PINCTRL_PIN(87, "GPIO_87"), - PINCTRL_PIN(88, "GPIO_88"), - PINCTRL_PIN(89, "GPIO_89"), - PINCTRL_PIN(90, "GPIO_90"), - PINCTRL_PIN(91, "GPIO_91"), -+ PINCTRL_PIN(92, "GPIO_92"), -+ PINCTRL_PIN(93, "GPIO_93"), - PINCTRL_PIN(94, "GPIO_94"), - PINCTRL_PIN(95, "GPIO_95"), - PINCTRL_PIN(96, "GPIO_96"), -@@ -1125,7 +1134,6 @@ static struct platform_driver qcm2290_pi - .of_match_table = qcm2290_pinctrl_of_match, - }, - .probe = qcm2290_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init qcm2290_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-qcs404.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-qcs404.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-qcs404.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-qcs404.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1644,7 +1644,6 @@ static struct platform_driver qcs404_pin - .of_match_table = qcs404_pinctrl_of_match, - }, - .probe = qcs404_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init qcs404_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-qcs615.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-qcs615.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-qcs615.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-qcs615.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1087,7 +1087,6 @@ static struct platform_driver qcs615_tlm - .of_match_table = qcs615_tlmm_of_match, - }, - .probe = qcs615_tlmm_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init qcs615_tlmm_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-qcs8300.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-qcs8300.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-qcs8300.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-qcs8300.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1227,7 +1227,6 @@ static struct platform_driver qcs8300_pi - .of_match_table = qcs8300_pinctrl_of_match, - }, - .probe = qcs8300_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init qcs8300_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c 2025-10-22 13:53:56.639168544 -0400 -@@ -145,7 +145,6 @@ static struct platform_driver qdf2xxx_pi - .acpi_match_table = qdf2xxx_acpi_ids, - }, - .probe = qdf2xxx_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init qdf2xxx_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-qdu1000.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-qdu1000.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-qdu1000.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-qdu1000.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1248,7 +1248,6 @@ static struct platform_driver qdu1000_tl - .of_match_table = qdu1000_tlmm_of_match, - }, - .probe = qdu1000_tlmm_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init qdu1000_tlmm_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sa8775p.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sa8775p.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sa8775p.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sa8775p.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1540,7 +1540,6 @@ static struct platform_driver sa8775p_pi - .of_match_table = sa8775p_pinctrl_of_match, - }, - .probe = sa8775p_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sa8775p_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sar2130p.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sar2130p.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sar2130p.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sar2130p.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1486,7 +1486,6 @@ static struct platform_driver sar2130p_t - .of_match_table = sar2130p_tlmm_of_match, - }, - .probe = sar2130p_tlmm_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sar2130p_tlmm_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sc7180.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sc7180.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sc7180.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sc7180.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1159,7 +1159,6 @@ static struct platform_driver sc7180_pin - .of_match_table = sc7180_pinctrl_of_match, - }, - .probe = sc7180_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sc7180_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sc7280.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sc7280.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sc7280.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sc7280.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1505,7 +1505,6 @@ static struct platform_driver sc7280_pin - .of_match_table = sc7280_pinctrl_of_match, - }, - .probe = sc7280_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sc7280_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sc8180x.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sc8180x.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sc8180x.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sc8180x.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1720,7 +1720,6 @@ static struct platform_driver sc8180x_pi - .acpi_match_table = sc8180x_pinctrl_acpi_match, - }, - .probe = sc8180x_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sc8180x_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sc8280xp.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sc8280xp.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sc8280xp.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sc8280xp.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1926,7 +1926,6 @@ static struct platform_driver sc8280xp_p - .of_match_table = sc8280xp_pinctrl_of_match, - }, - .probe = sc8280xp_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sc8280xp_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sdm660.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sdm660.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sdm660.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sdm660.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1442,7 +1442,6 @@ static struct platform_driver sdm660_pin - .of_match_table = sdm660_pinctrl_of_match, - }, - .probe = sdm660_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sdm660_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sdm670.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sdm670.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sdm670.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sdm670.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1337,7 +1337,6 @@ static struct platform_driver sdm670_pin - .of_match_table = sdm670_pinctrl_of_match, - }, - .probe = sdm670_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sdm670_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sdm845.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sdm845.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sdm845.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sdm845.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1351,7 +1351,6 @@ static struct platform_driver sdm845_pin - .acpi_match_table = ACPI_PTR(sdm845_pinctrl_acpi_match), - }, - .probe = sdm845_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sdm845_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sdx55.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sdx55.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sdx55.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sdx55.c 2025-10-22 13:53:56.639168544 -0400 -@@ -990,7 +990,6 @@ static struct platform_driver sdx55_pinc - .of_match_table = sdx55_pinctrl_of_match, - }, - .probe = sdx55_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sdx55_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sdx65.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sdx65.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sdx65.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sdx65.c 2025-10-22 13:53:56.639168544 -0400 -@@ -939,7 +939,6 @@ static struct platform_driver sdx65_pinc - .of_match_table = sdx65_pinctrl_of_match, - }, - .probe = sdx65_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sdx65_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sdx75.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sdx75.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sdx75.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sdx75.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1124,7 +1124,6 @@ static struct platform_driver sdx75_pinc - .of_match_table = sdx75_pinctrl_of_match, - }, - .probe = sdx75_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sdx75_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm4450.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm4450.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm4450.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm4450.c 2025-10-22 13:53:56.639168544 -0400 -@@ -994,7 +994,6 @@ static struct platform_driver sm4450_tlm - .of_match_table = sm4450_tlmm_of_match, - }, - .probe = sm4450_tlmm_probe, -- .remove = msm_pinctrl_remove, - }; - MODULE_DEVICE_TABLE(of, sm4450_tlmm_of_match); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm6115.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm6115.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm6115.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm6115.c 2025-10-22 13:53:56.639168544 -0400 -@@ -907,7 +907,6 @@ static struct platform_driver sm6115_tlm - .of_match_table = sm6115_tlmm_of_match, - }, - .probe = sm6115_tlmm_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sm6115_tlmm_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm6125.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm6125.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm6125.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm6125.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1266,7 +1266,6 @@ static struct platform_driver sm6125_tlm - .of_match_table = sm6125_tlmm_of_match, - }, - .probe = sm6125_tlmm_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sm6125_tlmm_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm6350.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm6350.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm6350.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm6350.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1373,7 +1373,6 @@ static struct platform_driver sm6350_tlm - .of_match_table = sm6350_tlmm_of_match, - }, - .probe = sm6350_tlmm_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sm6350_tlmm_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm6375.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm6375.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm6375.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm6375.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1516,7 +1516,6 @@ static struct platform_driver sm6375_tlm - .of_match_table = sm6375_tlmm_of_match, - }, - .probe = sm6375_tlmm_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sm6375_tlmm_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm7150.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm7150.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm7150.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm7150.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1255,7 +1255,6 @@ static struct platform_driver sm7150_tlm - .of_match_table = sm7150_tlmm_of_match, - }, - .probe = sm7150_tlmm_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sm7150_tlmm_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm8150.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm8150.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm8150.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm8150.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1542,7 +1542,6 @@ static struct platform_driver sm8150_pin - .of_match_table = sm8150_pinctrl_of_match, - }, - .probe = sm8150_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sm8150_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm8250.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm8250.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm8250.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm8250.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1351,7 +1351,6 @@ static struct platform_driver sm8250_pin - .of_match_table = sm8250_pinctrl_of_match, - }, - .probe = sm8250_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sm8250_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm8350.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm8350.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm8350.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm8350.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1642,7 +1642,6 @@ static struct platform_driver sm8350_tlm - .of_match_table = sm8350_tlmm_of_match, - }, - .probe = sm8350_tlmm_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sm8350_tlmm_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm8450.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm8450.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm8450.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm8450.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1677,7 +1677,6 @@ static struct platform_driver sm8450_tlm - .of_match_table = sm8450_tlmm_of_match, - }, - .probe = sm8450_tlmm_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sm8450_tlmm_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm8550.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm8550.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm8550.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm8550.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1762,7 +1762,6 @@ static struct platform_driver sm8550_tlm - .of_match_table = sm8550_tlmm_of_match, - }, - .probe = sm8550_tlmm_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sm8550_tlmm_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm8650.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm8650.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm8650.c 2025-10-22 13:53:23.427328110 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm8650.c 2025-10-22 13:53:56.639168544 -0400 -@@ -1742,7 +1742,6 @@ static struct platform_driver sm8650_tlm - .of_match_table = sm8650_tlmm_of_match, - }, - .probe = sm8650_tlmm_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sm8650_tlmm_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm8750.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm8750.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-sm8750.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-sm8750.c 2025-10-22 13:53:56.643168524 -0400 -@@ -1711,7 +1711,6 @@ static struct platform_driver sm8750_tlm - .of_match_table = sm8750_tlmm_of_match, - }, - .probe = sm8750_tlmm_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init sm8750_tlmm_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-x1e80100.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-x1e80100.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/qcom/pinctrl-x1e80100.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/qcom/pinctrl-x1e80100.c 2025-10-22 13:53:56.643168524 -0400 -@@ -1861,7 +1861,6 @@ static struct platform_driver x1e80100_p - .of_match_table = x1e80100_pinctrl_of_match, - }, - .probe = x1e80100_pinctrl_probe, -- .remove = msm_pinctrl_remove, - }; - - static int __init x1e80100_pinctrl_init(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/stm32/pinctrl-stm32.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/stm32/pinctrl-stm32.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/stm32/pinctrl-stm32.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/stm32/pinctrl-stm32.c 2025-10-22 13:53:56.643168524 -0400 -@@ -411,6 +411,7 @@ static struct irq_chip stm32_gpio_irq_ch - .irq_set_wake = irq_chip_set_wake_parent, - .irq_request_resources = stm32_gpio_irq_request_resources, - .irq_release_resources = stm32_gpio_irq_release_resources, -+ .irq_set_affinity = IS_ENABLED(CONFIG_SMP) ? irq_chip_set_affinity_parent : NULL, - }; - - static int stm32_gpio_domain_translate(struct irq_domain *d, -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/sunxi/pinctrl-sunxi.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/sunxi/pinctrl-sunxi.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/sunxi/pinctrl-sunxi.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/sunxi/pinctrl-sunxi.c 2025-10-22 13:53:56.643168524 -0400 -@@ -408,6 +408,7 @@ static int sunxi_pctrl_dt_node_to_map(st - const char *function, *pin_prop; - const char *group; - int ret, npins, nmaps, configlen = 0, i = 0; -+ struct pinctrl_map *new_map; - - *map = NULL; - *num_maps = 0; -@@ -482,9 +483,13 @@ static int sunxi_pctrl_dt_node_to_map(st - * We know have the number of maps we need, we can resize our - * map array - */ -- *map = krealloc(*map, i * sizeof(struct pinctrl_map), GFP_KERNEL); -- if (!*map) -- return -ENOMEM; -+ new_map = krealloc(*map, i * sizeof(struct pinctrl_map), GFP_KERNEL); -+ if (!new_map) { -+ ret = -ENOMEM; -+ goto err_free_map; -+ } -+ -+ *map = new_map; - - return 0; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c ---- BPI-Router-Linux-kernel/drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c 2025-10-22 13:53:56.643168524 -0400 -@@ -143,7 +143,7 @@ static struct sunxi_desc_pin *init_pins_ - */ - static int prepare_function_table(struct device *dev, struct device_node *pnode, - struct sunxi_desc_pin *pins, int npins, -- const u8 *irq_bank_muxes) -+ unsigned pin_base, const u8 *irq_bank_muxes) - { - struct device_node *node; - struct property *prop; -@@ -166,7 +166,7 @@ static int prepare_function_table(struct - */ - for (i = 0; i < npins; i++) { - struct sunxi_desc_pin *pin = &pins[i]; -- int bank = pin->pin.number / PINS_PER_BANK; -+ int bank = (pin->pin.number - pin_base) / PINS_PER_BANK; - - if (irq_bank_muxes[bank]) { - pin->variant++; -@@ -211,7 +211,7 @@ static int prepare_function_table(struct - last_bank = 0; - for (i = 0; i < npins; i++) { - struct sunxi_desc_pin *pin = &pins[i]; -- int bank = pin->pin.number / PINS_PER_BANK; -+ int bank = (pin->pin.number - pin_base) / PINS_PER_BANK; - int lastfunc = pin->variant + 1; - int irq_mux = irq_bank_muxes[bank]; - -@@ -353,7 +353,7 @@ int sunxi_pinctrl_dt_table_init(struct p - return PTR_ERR(pins); - - ret = prepare_function_table(&pdev->dev, pnode, pins, desc->npins, -- irq_bank_muxes); -+ desc->pin_base, irq_bank_muxes); - if (ret) - return ret; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/arm64/huawei-gaokun-ec.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/arm64/huawei-gaokun-ec.c ---- BPI-Router-Linux-kernel/drivers/platform/arm64/huawei-gaokun-ec.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/arm64/huawei-gaokun-ec.c 2025-10-22 13:53:56.643168524 -0400 -@@ -662,6 +662,7 @@ static void gaokun_aux_release(struct de - { - struct auxiliary_device *adev = to_auxiliary_dev(dev); - -+ of_node_put(dev->of_node); - kfree(adev); - } - -@@ -693,6 +694,7 @@ static int gaokun_aux_init(struct device - - ret = auxiliary_device_init(adev); - if (ret) { -+ of_node_put(adev->dev.of_node); - kfree(adev); - return ret; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/chrome/cros_ec.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/chrome/cros_ec.c ---- BPI-Router-Linux-kernel/drivers/platform/chrome/cros_ec.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/chrome/cros_ec.c 2025-10-22 13:53:56.643168524 -0400 -@@ -318,6 +318,9 @@ EXPORT_SYMBOL(cros_ec_register); - */ - void cros_ec_unregister(struct cros_ec_device *ec_dev) - { -+ if (ec_dev->mkbp_event_supported) -+ blocking_notifier_chain_unregister(&ec_dev->event_notifier, -+ &ec_dev->notifier_ready); - platform_device_unregister(ec_dev->pd); - platform_device_unregister(ec_dev->ec); - mutex_destroy(&ec_dev->lock); -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/chrome/cros_ec_sensorhub.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/chrome/cros_ec_sensorhub.c ---- BPI-Router-Linux-kernel/drivers/platform/chrome/cros_ec_sensorhub.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/chrome/cros_ec_sensorhub.c 2025-10-22 13:53:56.643168524 -0400 -@@ -8,6 +8,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -18,6 +19,7 @@ - #include - - #define DRV_NAME "cros-ec-sensorhub" -+#define CROS_EC_CMD_INFO_RETRIES 50 - - static void cros_ec_sensorhub_free_sensor(void *arg) - { -@@ -53,7 +55,7 @@ static int cros_ec_sensorhub_register(st - int sensor_type[MOTIONSENSE_TYPE_MAX] = { 0 }; - struct cros_ec_command *msg = sensorhub->msg; - struct cros_ec_dev *ec = sensorhub->ec; -- int ret, i; -+ int ret, i, retries; - char *name; - - -@@ -65,12 +67,25 @@ static int cros_ec_sensorhub_register(st - sensorhub->params->cmd = MOTIONSENSE_CMD_INFO; - sensorhub->params->info.sensor_num = i; - -- ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); -+ retries = CROS_EC_CMD_INFO_RETRIES; -+ do { -+ ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); -+ if (ret == -EBUSY) { -+ /* The EC is still busy initializing sensors. */ -+ usleep_range(5000, 6000); -+ retries--; -+ } -+ } while (ret == -EBUSY && retries); -+ - if (ret < 0) { -- dev_warn(dev, "no info for EC sensor %d : %d/%d\n", -- i, ret, msg->result); -+ dev_err(dev, "no info for EC sensor %d : %d/%d\n", -+ i, ret, msg->result); - continue; - } -+ if (retries < CROS_EC_CMD_INFO_RETRIES) { -+ dev_warn(dev, "%d retries needed to bring up sensor %d\n", -+ CROS_EC_CMD_INFO_RETRIES - retries, i); -+ } - - switch (sensorhub->resp->info.type) { - case MOTIONSENSE_TYPE_ACCEL: -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/chrome/cros_ec_typec.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/chrome/cros_ec_typec.c ---- BPI-Router-Linux-kernel/drivers/platform/chrome/cros_ec_typec.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/chrome/cros_ec_typec.c 2025-10-22 13:53:56.643168524 -0400 -@@ -1272,8 +1272,8 @@ static int cros_typec_probe(struct platf - - typec->ec = dev_get_drvdata(pdev->dev.parent); - if (!typec->ec) { -- dev_err(dev, "couldn't find parent EC device\n"); -- return -ENODEV; -+ dev_warn(dev, "couldn't find parent EC device\n"); -+ return -EPROBE_DEFER; - } - - platform_set_drvdata(pdev, typec); -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/mellanox/mlxbf-pmc.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/mellanox/mlxbf-pmc.c ---- BPI-Router-Linux-kernel/drivers/platform/mellanox/mlxbf-pmc.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/mellanox/mlxbf-pmc.c 2025-10-22 13:53:56.643168524 -0400 -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - - #define MLXBF_PMC_WRITE_REG_32 0x82000009 -@@ -715,7 +716,7 @@ static const struct mlxbf_pmc_events mlx - {101, "GDC_BANK0_HIT_DCL_PARTIAL"}, - {102, "GDC_BANK0_EVICT_DCL"}, - {103, "GDC_BANK0_G_RSE_PIPE_CACHE_DATA0"}, -- {103, "GDC_BANK0_G_RSE_PIPE_CACHE_DATA1"}, -+ {104, "GDC_BANK0_G_RSE_PIPE_CACHE_DATA1"}, - {105, "GDC_BANK0_ARB_STRB"}, - {106, "GDC_BANK0_ARB_WAIT"}, - {107, "GDC_BANK0_GGA_STRB"}, -@@ -1222,7 +1223,7 @@ static int mlxbf_pmc_get_event_num(const - return -ENODEV; - } - --/* Get the event number given the name */ -+/* Get the event name given the number */ - static char *mlxbf_pmc_get_event_name(const char *blk, u32 evt) - { - const struct mlxbf_pmc_events *events; -@@ -1784,6 +1785,7 @@ static ssize_t mlxbf_pmc_event_store(str - attr, struct mlxbf_pmc_attribute, dev_attr); - unsigned int blk_num, cnt_num; - bool is_l3 = false; -+ char *evt_name; - int evt_num; - int err; - -@@ -1791,14 +1793,23 @@ static ssize_t mlxbf_pmc_event_store(str - cnt_num = attr_event->index; - - if (isalpha(buf[0])) { -+ /* Remove the trailing newline character if present */ -+ evt_name = kstrdup_and_replace(buf, '\n', '\0', GFP_KERNEL); -+ if (!evt_name) -+ return -ENOMEM; -+ - evt_num = mlxbf_pmc_get_event_num(pmc->block_name[blk_num], -- buf); -+ evt_name); -+ kfree(evt_name); - if (evt_num < 0) - return -EINVAL; - } else { - err = kstrtouint(buf, 0, &evt_num); - if (err < 0) - return err; -+ -+ if (!mlxbf_pmc_get_event_name(pmc->block_name[blk_num], evt_num)) -+ return -EINVAL; - } - - if (strstr(pmc->block_name[blk_num], "l3cache")) -@@ -1879,13 +1890,14 @@ static ssize_t mlxbf_pmc_enable_store(st - { - struct mlxbf_pmc_attribute *attr_enable = container_of( - attr, struct mlxbf_pmc_attribute, dev_attr); -- unsigned int en, blk_num; -+ unsigned int blk_num; - u32 word; - int err; -+ bool en; - - blk_num = attr_enable->nr; - -- err = kstrtouint(buf, 0, &en); -+ err = kstrtobool(buf, &en); - if (err < 0) - return err; - -@@ -1905,14 +1917,11 @@ static ssize_t mlxbf_pmc_enable_store(st - MLXBF_PMC_CRSPACE_PERFMON_CTL(pmc->block[blk_num].counters), - MLXBF_PMC_WRITE_REG_32, word); - } else { -- if (en && en != 1) -- return -EINVAL; -- - err = mlxbf_pmc_config_l3_counters(blk_num, false, !!en); - if (err) - return err; - -- if (en == 1) { -+ if (en) { - err = mlxbf_pmc_config_l3_counters(blk_num, true, false); - if (err) - return err; -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/mellanox/mlxbf-tmfifo.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/mellanox/mlxbf-tmfifo.c ---- BPI-Router-Linux-kernel/drivers/platform/mellanox/mlxbf-tmfifo.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/mellanox/mlxbf-tmfifo.c 2025-10-22 13:53:56.643168524 -0400 -@@ -281,7 +281,8 @@ static int mlxbf_tmfifo_alloc_vrings(str - vring->align = SMP_CACHE_BYTES; - vring->index = i; - vring->vdev_id = tm_vdev->vdev.id.device; -- vring->drop_desc.len = VRING_DROP_DESC_MAX_LEN; -+ vring->drop_desc.len = cpu_to_virtio32(&tm_vdev->vdev, -+ VRING_DROP_DESC_MAX_LEN); - dev = &tm_vdev->vdev.dev; - - size = vring_size(vring->num, vring->align); -@@ -1287,7 +1288,7 @@ static void mlxbf_tmfifo_get_cfg_mac(u8 - ether_addr_copy(mac, mlxbf_tmfifo_net_default_mac); - } - --/* Set TmFifo thresolds which is used to trigger interrupts. */ -+/* Set TmFifo thresholds which is used to trigger interrupts. */ - static void mlxbf_tmfifo_set_threshold(struct mlxbf_tmfifo *fifo) - { - u64 ctl; -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/mellanox/mlxreg-dpu.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/mellanox/mlxreg-dpu.c ---- BPI-Router-Linux-kernel/drivers/platform/mellanox/mlxreg-dpu.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/mellanox/mlxreg-dpu.c 2025-10-22 13:53:56.643168524 -0400 -@@ -483,7 +483,7 @@ static int mlxreg_dpu_config_init(struct - mlxreg_dpu->io_data, - sizeof(*mlxreg_dpu->io_data)); - if (IS_ERR(mlxreg_dpu->io_regs)) { -- dev_err(dev, "Failed to create regio for client %s at bus %d at addr 0x%02x\n", -+ dev_err(dev, "Failed to create region for client %s at bus %d at addr 0x%02x\n", - data->hpdev.brdinfo->type, data->hpdev.nr, - data->hpdev.brdinfo->addr); - return PTR_ERR(mlxreg_dpu->io_regs); -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/mellanox/mlxreg-lc.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/mellanox/mlxreg-lc.c ---- BPI-Router-Linux-kernel/drivers/platform/mellanox/mlxreg-lc.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/mellanox/mlxreg-lc.c 2025-10-22 13:53:56.643168524 -0400 -@@ -57,9 +57,9 @@ enum mlxreg_lc_state { - * @dev: platform device; - * @lock: line card lock; - * @par_regmap: parent device regmap handle; -- * @data: pltaform core data; -+ * @data: platform core data; - * @io_data: register access platform data; -- * @led_data: LED platform data ; -+ * @led_data: LED platform data; - * @mux_data: MUX platform data; - * @led: LED device; - * @io_regs: register access device; -@@ -171,7 +171,7 @@ static int mlxreg_lc_chan[] = { - 0x4e, 0x4f - }; - --/* Defaul mux configuration. */ -+/* Default mux configuration. */ - static struct mlxcpld_mux_plat_data mlxreg_lc_mux_data[] = { - { - .chan_ids = mlxreg_lc_chan, -@@ -181,7 +181,7 @@ static struct mlxcpld_mux_plat_data mlxr - }, - }; - --/* Defaul mux board info. */ -+/* Default mux board info. */ - static struct i2c_board_info mlxreg_lc_mux_brdinfo = { - I2C_BOARD_INFO("i2c-mux-mlxcpld", 0x32), - }; -@@ -688,7 +688,7 @@ static int mlxreg_lc_completion_notify(v - if (regval & mlxreg_lc->data->mask) { - mlxreg_lc->state |= MLXREG_LC_SYNCED; - mlxreg_lc_state_update_locked(mlxreg_lc, MLXREG_LC_SYNCED, 1); -- if (mlxreg_lc->state & ~MLXREG_LC_POWERED) { -+ if (!(mlxreg_lc->state & MLXREG_LC_POWERED)) { - err = mlxreg_lc_power_on_off(mlxreg_lc, 1); - if (err) - goto mlxreg_lc_regmap_power_on_off_fail; -@@ -758,7 +758,7 @@ mlxreg_lc_config_init(struct mlxreg_lc * - platform_device_register_resndata(dev, "mlxreg-io", data->hpdev.nr, NULL, 0, - mlxreg_lc->io_data, sizeof(*mlxreg_lc->io_data)); - if (IS_ERR(mlxreg_lc->io_regs)) { -- dev_err(dev, "Failed to create regio for client %s at bus %d at addr 0x%02x\n", -+ dev_err(dev, "Failed to create region for client %s at bus %d at addr 0x%02x\n", - data->hpdev.brdinfo->type, data->hpdev.nr, - data->hpdev.brdinfo->addr); - err = PTR_ERR(mlxreg_lc->io_regs); -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/mellanox/nvsw-sn2201.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/mellanox/nvsw-sn2201.c ---- BPI-Router-Linux-kernel/drivers/platform/mellanox/nvsw-sn2201.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/mellanox/nvsw-sn2201.c 2025-10-22 13:53:56.643168524 -0400 -@@ -1181,7 +1181,7 @@ static int nvsw_sn2201_i2c_completion_no - if (!nvsw_sn2201->main_mux_devs->adapter) { - err = -ENODEV; - dev_err(nvsw_sn2201->dev, "Failed to get adapter for bus %d\n", -- nvsw_sn2201->cpld_devs->nr); -+ nvsw_sn2201->main_mux_devs->nr); - goto i2c_get_adapter_main_fail; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/acer-wmi.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/acer-wmi.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/acer-wmi.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/acer-wmi.c 2025-10-22 13:53:56.643168524 -0400 -@@ -129,6 +129,7 @@ enum acer_wmi_predator_v4_oc { - enum acer_wmi_gaming_misc_setting { - ACER_WMID_MISC_SETTING_OC_1 = 0x0005, - ACER_WMID_MISC_SETTING_OC_2 = 0x0007, -+ /* Unreliable on some models */ - ACER_WMID_MISC_SETTING_SUPPORTED_PROFILES = 0x000A, - ACER_WMID_MISC_SETTING_PLATFORM_PROFILE = 0x000B, - }; -@@ -794,9 +795,6 @@ static bool platform_profile_support; - */ - static int last_non_turbo_profile = INT_MIN; - --/* The most performant supported profile */ --static int acer_predator_v4_max_perf; -- - enum acer_predator_v4_thermal_profile { - ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET = 0x00, - ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED = 0x01, -@@ -2014,7 +2012,7 @@ acer_predator_v4_platform_profile_set(st - if (err) - return err; - -- if (tp != acer_predator_v4_max_perf) -+ if (tp != ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO) - last_non_turbo_profile = tp; - - return 0; -@@ -2023,55 +2021,14 @@ acer_predator_v4_platform_profile_set(st - static int - acer_predator_v4_platform_profile_probe(void *drvdata, unsigned long *choices) - { -- unsigned long supported_profiles; -- int err; -+ set_bit(PLATFORM_PROFILE_PERFORMANCE, choices); -+ set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices); -+ set_bit(PLATFORM_PROFILE_BALANCED, choices); -+ set_bit(PLATFORM_PROFILE_QUIET, choices); -+ set_bit(PLATFORM_PROFILE_LOW_POWER, choices); - -- err = WMID_gaming_get_misc_setting(ACER_WMID_MISC_SETTING_SUPPORTED_PROFILES, -- (u8 *)&supported_profiles); -- if (err) -- return err; -- -- /* Iterate through supported profiles in order of increasing performance */ -- if (test_bit(ACER_PREDATOR_V4_THERMAL_PROFILE_ECO, &supported_profiles)) { -- set_bit(PLATFORM_PROFILE_LOW_POWER, choices); -- acer_predator_v4_max_perf = ACER_PREDATOR_V4_THERMAL_PROFILE_ECO; -- last_non_turbo_profile = ACER_PREDATOR_V4_THERMAL_PROFILE_ECO; -- } -- -- if (test_bit(ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET, &supported_profiles)) { -- set_bit(PLATFORM_PROFILE_QUIET, choices); -- acer_predator_v4_max_perf = ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET; -- last_non_turbo_profile = ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET; -- } -- -- if (test_bit(ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED, &supported_profiles)) { -- set_bit(PLATFORM_PROFILE_BALANCED, choices); -- acer_predator_v4_max_perf = ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED; -- last_non_turbo_profile = ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED; -- } -- -- if (test_bit(ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE, &supported_profiles)) { -- set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices); -- acer_predator_v4_max_perf = ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE; -- -- /* We only use this profile as a fallback option in case no prior -- * profile is supported. -- */ -- if (last_non_turbo_profile < 0) -- last_non_turbo_profile = ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE; -- } -- -- if (test_bit(ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO, &supported_profiles)) { -- set_bit(PLATFORM_PROFILE_PERFORMANCE, choices); -- acer_predator_v4_max_perf = ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO; -- -- /* We need to handle the hypothetical case where only the turbo profile -- * is supported. In this case the turbo toggle will essentially be a -- * no-op. -- */ -- if (last_non_turbo_profile < 0) -- last_non_turbo_profile = ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO; -- } -+ /* Set default non-turbo profile */ -+ last_non_turbo_profile = ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED; - - return 0; - } -@@ -2108,19 +2065,15 @@ static int acer_thermal_profile_change(v - if (cycle_gaming_thermal_profile) { - platform_profile_cycle(); - } else { -- /* Do nothing if no suitable platform profiles where found */ -- if (last_non_turbo_profile < 0) -- return 0; -- - err = WMID_gaming_get_misc_setting( - ACER_WMID_MISC_SETTING_PLATFORM_PROFILE, ¤t_tp); - if (err) - return err; - -- if (current_tp == acer_predator_v4_max_perf) -+ if (current_tp == ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO) - tp = last_non_turbo_profile; - else -- tp = acer_predator_v4_max_perf; -+ tp = ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO; - - err = WMID_gaming_set_misc_setting( - ACER_WMID_MISC_SETTING_PLATFORM_PROFILE, tp); -@@ -2128,7 +2081,7 @@ static int acer_thermal_profile_change(v - return err; - - /* Store last profile for toggle */ -- if (current_tp != acer_predator_v4_max_perf) -+ if (current_tp != ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO) - last_non_turbo_profile = current_tp; - - platform_profile_notify(platform_profile_device); -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/amd/amd_isp4.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/amd/amd_isp4.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/amd/amd_isp4.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/amd/amd_isp4.c 2025-10-22 13:53:56.643168524 -0400 -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -20,6 +21,9 @@ - #define AMDISP_OV05C10_REMOTE_EP_NAME "ov05c10_isp_4_1_1" - #define AMD_ISP_PLAT_DRV_NAME "amd-isp4" - -+static const struct software_node isp4_mipi1_endpoint_node; -+static const struct software_node ov05c10_endpoint_node; -+ - /* - * AMD ISP platform info definition to initialize sensor - * specific platform configuration to prepare the amdisp -@@ -42,55 +46,116 @@ struct amdisp_platform { - struct mutex lock; /* protects i2c client creation */ - }; - --/* Top-level OV05C10 camera node property table */ -+/* Root AMD CAMERA SWNODE */ -+ -+/* Root amd camera node definition */ -+static const struct software_node amd_camera_node = { -+ .name = "amd_camera", -+}; -+ -+/* ISP4 SWNODE */ -+ -+/* ISP4 OV05C10 camera node definition */ -+static const struct software_node isp4_node = { -+ .name = "isp4", -+ .parent = &amd_camera_node, -+}; -+ -+/* -+ * ISP4 Ports node definition. No properties defined for -+ * ports node. -+ */ -+static const struct software_node isp4_ports = { -+ .name = "ports", -+ .parent = &isp4_node, -+}; -+ -+/* -+ * ISP4 Port node definition. No properties defined for -+ * port node. -+ */ -+static const struct software_node isp4_port_node = { -+ .name = "port@0", -+ .parent = &isp4_ports, -+}; -+ -+/* -+ * ISP4 MIPI1 remote endpoint points to OV05C10 endpoint -+ * node. -+ */ -+static const struct software_node_ref_args isp4_refs[] = { -+ SOFTWARE_NODE_REFERENCE(&ov05c10_endpoint_node), -+}; -+ -+/* ISP4 MIPI1 endpoint node properties table */ -+static const struct property_entry isp4_mipi1_endpoint_props[] = { -+ PROPERTY_ENTRY_REF_ARRAY("remote-endpoint", isp4_refs), -+ { } -+}; -+ -+/* ISP4 MIPI1 endpoint node definition */ -+static const struct software_node isp4_mipi1_endpoint_node = { -+ .name = "endpoint", -+ .parent = &isp4_port_node, -+ .properties = isp4_mipi1_endpoint_props, -+}; -+ -+/* I2C1 SWNODE */ -+ -+/* I2C1 camera node property table */ -+static const struct property_entry i2c1_camera_props[] = { -+ PROPERTY_ENTRY_U32("clock-frequency", 1 * HZ_PER_MHZ), -+ { } -+}; -+ -+/* I2C1 camera node definition */ -+static const struct software_node i2c1_node = { -+ .name = "i2c1", -+ .parent = &amd_camera_node, -+ .properties = i2c1_camera_props, -+}; -+ -+/* I2C1 camera node property table */ - static const struct property_entry ov05c10_camera_props[] = { - PROPERTY_ENTRY_U32("clock-frequency", 24 * HZ_PER_MHZ), - { } - }; - --/* Root AMD ISP OV05C10 camera node definition */ --static const struct software_node camera_node = { -+/* OV05C10 camera node definition */ -+static const struct software_node ov05c10_camera_node = { - .name = AMDISP_OV05C10_HID, -+ .parent = &i2c1_node, - .properties = ov05c10_camera_props, - }; - - /* -- * AMD ISP OV05C10 Ports node definition. No properties defined for -+ * OV05C10 Ports node definition. No properties defined for - * ports node for OV05C10. - */ --static const struct software_node ports = { -+static const struct software_node ov05c10_ports = { - .name = "ports", -- .parent = &camera_node, --}; -- --/* -- * AMD ISP OV05C10 Port node definition. No properties defined for -- * port node for OV05C10. -- */ --static const struct software_node port_node = { -- .name = "port@", -- .parent = &ports, -+ .parent = &ov05c10_camera_node, - }; - - /* -- * Remote endpoint AMD ISP node definition. No properties defined for -- * remote endpoint node for OV05C10. -+ * OV05C10 Port node definition. - */ --static const struct software_node remote_ep_isp_node = { -- .name = AMDISP_OV05C10_REMOTE_EP_NAME, -+static const struct software_node ov05c10_port_node = { -+ .name = "port@0", -+ .parent = &ov05c10_ports, - }; - - /* -- * Remote endpoint reference for isp node included in the -- * OV05C10 endpoint. -+ * OV05C10 remote endpoint points to ISP4 MIPI1 endpoint -+ * node. - */ - static const struct software_node_ref_args ov05c10_refs[] = { -- SOFTWARE_NODE_REFERENCE(&remote_ep_isp_node), -+ SOFTWARE_NODE_REFERENCE(&isp4_mipi1_endpoint_node), - }; - - /* OV05C10 supports one single link frequency */ - static const u64 ov05c10_link_freqs[] = { -- 925 * HZ_PER_MHZ, -+ 900 * HZ_PER_MHZ, - }; - - /* OV05C10 supports only 2-lane configuration */ -@@ -110,27 +175,64 @@ static const struct property_entry ov05c - { } - }; - --/* AMD ISP endpoint node definition */ --static const struct software_node endpoint_node = { -+/* OV05C10 endpoint node definition */ -+static const struct software_node ov05c10_endpoint_node = { - .name = "endpoint", -- .parent = &port_node, -+ .parent = &ov05c10_port_node, - .properties = ov05c10_endpoint_props, - }; - - /* -- * AMD ISP swnode graph uses 5 nodes and also its relationship is -- * fixed to align with the structure that v4l2 expects for successful -- * endpoint fwnode parsing. -+ * AMD Camera swnode graph uses 10 nodes and also its relationship is -+ * fixed to align with the structure that v4l2 and i2c frameworks expects -+ * for successful parsing of fwnodes and its properties with standard names. - * - * It is only the node property_entries that will vary for each platform - * supporting different sensor modules. -+ * -+ * AMD ISP4 SWNODE GRAPH Structure -+ * -+ * amd_camera { -+ * isp4 { -+ * ports { -+ * port@0 { -+ * isp4_mipi1_ep: endpoint { -+ * remote-endpoint = &OMNI5C10_ep; -+ * }; -+ * }; -+ * }; -+ * }; -+ * -+ * i2c1 { -+ * clock-frequency = 1 MHz; -+ * OMNI5C10 { -+ * clock-frequency = 24MHz; -+ * ports { -+ * port@0 { -+ * OMNI5C10_ep: endpoint { -+ * bus-type = 4; -+ * data-lanes = <1 2>; -+ * link-frequencies = 900MHz; -+ * remote-endpoint = &isp4_mipi1; -+ * }; -+ * }; -+ * }; -+ * }; -+ * }; -+ * }; -+ * - */ --static const struct software_node *ov05c10_nodes[] = { -- &camera_node, -- &ports, -- &port_node, -- &endpoint_node, -- &remote_ep_isp_node, -+static const struct software_node *amd_isp4_nodes[] = { -+ &amd_camera_node, -+ &isp4_node, -+ &isp4_ports, -+ &isp4_port_node, -+ &isp4_mipi1_endpoint_node, -+ &i2c1_node, -+ &ov05c10_camera_node, -+ &ov05c10_ports, -+ &ov05c10_port_node, -+ &ov05c10_endpoint_node, - NULL - }; - -@@ -140,7 +242,7 @@ static const struct amdisp_platform_info - .dev_name = "ov05c10", - I2C_BOARD_INFO("ov05c10", AMDISP_OV05C10_I2C_ADDR), - }, -- .swnodes = ov05c10_nodes, -+ .swnodes = amd_isp4_nodes, - }; - - static const struct acpi_device_id amdisp_sensor_ids[] = { -@@ -151,7 +253,7 @@ MODULE_DEVICE_TABLE(acpi, amdisp_sensor_ - - static inline bool is_isp_i2c_adapter(struct i2c_adapter *adap) - { -- return !strcmp(adap->owner->name, "i2c_designware_amdisp"); -+ return !strcmp(adap->name, AMDISP_I2C_ADAP_NAME); - } - - static void instantiate_isp_i2c_client(struct amdisp_platform *isp4_platform, -@@ -232,7 +334,8 @@ static struct amdisp_platform *prepare_a - if (ret) - return ERR_PTR(ret); - -- isp4_platform->board_info.swnode = src->swnodes[0]; -+ /* initialize ov05c10_camera_node */ -+ isp4_platform->board_info.swnode = src->swnodes[6]; - - return isp4_platform; - } -@@ -257,6 +360,7 @@ static int amd_isp_probe(struct platform - { - const struct amdisp_platform_info *pinfo; - struct amdisp_platform *isp4_platform; -+ struct acpi_device *adev; - int ret; - - pinfo = device_get_match_data(&pdev->dev); -@@ -274,6 +378,10 @@ static int amd_isp_probe(struct platform - if (ret) - goto error_unregister_sw_node; - -+ adev = ACPI_COMPANION(&pdev->dev); -+ /* initialize root amd_camera_node */ -+ adev->driver_data = (void *)pinfo->swnodes[0]; -+ - /* check if adapter is already registered and create i2c client instance */ - i2c_for_each_dev(isp4_platform, try_to_instantiate_i2c_client); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/amd/hsmp/hsmp.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/amd/hsmp/hsmp.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/amd/hsmp/hsmp.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/amd/hsmp/hsmp.c 2025-10-22 13:53:56.643168524 -0400 -@@ -97,7 +97,7 @@ static int __hsmp_send_message(struct hs - short_sleep = jiffies + msecs_to_jiffies(HSMP_SHORT_SLEEP); - timeout = jiffies + msecs_to_jiffies(HSMP_MSG_TIMEOUT); - -- while (time_before(jiffies, timeout)) { -+ while (true) { - ret = sock->amd_hsmp_rdwr(sock, mbinfo->msg_resp_off, &mbox_status, HSMP_RD); - if (ret) { - dev_err(sock->dev, "Error %d reading mailbox status\n", ret); -@@ -106,6 +106,10 @@ static int __hsmp_send_message(struct hs - - if (mbox_status != HSMP_STATUS_NOT_READY) - break; -+ -+ if (!time_before(jiffies, timeout)) -+ break; -+ - if (time_before(jiffies, short_sleep)) - usleep_range(50, 100); - else -@@ -210,13 +214,7 @@ int hsmp_send_message(struct hsmp_messag - return -ENODEV; - sock = &hsmp_pdev.sock[msg->sock_ind]; - -- /* -- * The time taken by smu operation to complete is between -- * 10us to 1ms. Sometime it may take more time. -- * In SMP system timeout of 100 millisecs should -- * be enough for the previous thread to finish the operation -- */ -- ret = down_timeout(&sock->hsmp_sem, msecs_to_jiffies(HSMP_MSG_TIMEOUT)); -+ ret = down_interruptible(&sock->hsmp_sem); - if (ret < 0) - return ret; - -@@ -358,6 +356,11 @@ ssize_t hsmp_metric_tbl_read(struct hsmp - if (!sock || !buf) - return -EINVAL; - -+ if (!sock->metric_tbl_addr) { -+ dev_err(sock->dev, "Metrics table address not available\n"); -+ return -ENOMEM; -+ } -+ - /* Do not support lseek(), also don't allow more than the size of metric table */ - if (size != sizeof(struct hsmp_metric_table)) { - dev_err(sock->dev, "Wrong buffer size\n"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/amd/pmc/pmc.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/amd/pmc/pmc.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/amd/pmc/pmc.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/amd/pmc/pmc.c 2025-10-22 13:53:56.643168524 -0400 -@@ -157,6 +157,8 @@ static int amd_pmc_setup_smu_logging(str - return -ENOMEM; - } - -+ memset_io(dev->smu_virt_addr, 0, sizeof(struct smu_metrics)); -+ - /* Start the logging */ - amd_pmc_send_cmd(dev, 0, NULL, SMU_MSG_LOG_RESET, false); - amd_pmc_send_cmd(dev, 0, NULL, SMU_MSG_LOG_START, false); -@@ -528,19 +530,6 @@ static int amd_pmc_get_os_hint(struct am - static int amd_pmc_wa_irq1(struct amd_pmc_dev *pdev) - { - struct device *d; -- int rc; -- -- /* cezanne platform firmware has a fix in 64.66.0 */ -- if (pdev->cpu_id == AMD_CPU_ID_CZN) { -- if (!pdev->major) { -- rc = amd_pmc_get_smu_version(pdev); -- if (rc) -- return rc; -- } -- -- if (pdev->major > 64 || (pdev->major == 64 && pdev->minor > 65)) -- return 0; -- } - - d = bus_find_device_by_name(&serio_bus, NULL, "serio0"); - if (!d) -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/amd/pmc/pmc-quirks.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/amd/pmc/pmc-quirks.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/amd/pmc/pmc-quirks.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/amd/pmc/pmc-quirks.c 2025-10-22 13:53:56.643168524 -0400 -@@ -11,7 +11,7 @@ - #include - #include - #include --#include -+#include - - #include "pmc.h" - -@@ -28,10 +28,15 @@ static struct quirk_entry quirk_spurious - .spurious_8042 = true, - }; - -+static struct quirk_entry quirk_s2idle_spurious_8042 = { -+ .s2idle_bug_mmio = FCH_PM_BASE + FCH_PM_SCRATCH, -+ .spurious_8042 = true, -+}; -+ - static const struct dmi_system_id fwbug_list[] = { - { - .ident = "L14 Gen2 AMD", -- .driver_data = &quirk_s2idle_bug, -+ .driver_data = &quirk_s2idle_spurious_8042, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "20X5"), -@@ -39,7 +44,7 @@ static const struct dmi_system_id fwbug_ - }, - { - .ident = "T14s Gen2 AMD", -- .driver_data = &quirk_s2idle_bug, -+ .driver_data = &quirk_s2idle_spurious_8042, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "20XF"), -@@ -47,7 +52,7 @@ static const struct dmi_system_id fwbug_ - }, - { - .ident = "X13 Gen2 AMD", -- .driver_data = &quirk_s2idle_bug, -+ .driver_data = &quirk_s2idle_spurious_8042, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "20XH"), -@@ -55,7 +60,7 @@ static const struct dmi_system_id fwbug_ - }, - { - .ident = "T14 Gen2 AMD", -- .driver_data = &quirk_s2idle_bug, -+ .driver_data = &quirk_s2idle_spurious_8042, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "20XK"), -@@ -63,7 +68,7 @@ static const struct dmi_system_id fwbug_ - }, - { - .ident = "T14 Gen1 AMD", -- .driver_data = &quirk_s2idle_bug, -+ .driver_data = &quirk_s2idle_spurious_8042, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "20UD"), -@@ -71,7 +76,7 @@ static const struct dmi_system_id fwbug_ - }, - { - .ident = "T14 Gen1 AMD", -- .driver_data = &quirk_s2idle_bug, -+ .driver_data = &quirk_s2idle_spurious_8042, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "20UE"), -@@ -79,7 +84,7 @@ static const struct dmi_system_id fwbug_ - }, - { - .ident = "T14s Gen1 AMD", -- .driver_data = &quirk_s2idle_bug, -+ .driver_data = &quirk_s2idle_spurious_8042, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "20UH"), -@@ -87,7 +92,7 @@ static const struct dmi_system_id fwbug_ - }, - { - .ident = "T14s Gen1 AMD", -- .driver_data = &quirk_s2idle_bug, -+ .driver_data = &quirk_s2idle_spurious_8042, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "20UJ"), -@@ -95,7 +100,7 @@ static const struct dmi_system_id fwbug_ - }, - { - .ident = "P14s Gen1 AMD", -- .driver_data = &quirk_s2idle_bug, -+ .driver_data = &quirk_s2idle_spurious_8042, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "20Y1"), -@@ -103,7 +108,7 @@ static const struct dmi_system_id fwbug_ - }, - { - .ident = "P14s Gen2 AMD", -- .driver_data = &quirk_s2idle_bug, -+ .driver_data = &quirk_s2idle_spurious_8042, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "21A0"), -@@ -111,7 +116,7 @@ static const struct dmi_system_id fwbug_ - }, - { - .ident = "P14s Gen2 AMD", -- .driver_data = &quirk_s2idle_bug, -+ .driver_data = &quirk_s2idle_spurious_8042, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "21A1"), -@@ -152,7 +157,7 @@ static const struct dmi_system_id fwbug_ - }, - { - .ident = "IdeaPad 1 14AMN7", -- .driver_data = &quirk_s2idle_bug, -+ .driver_data = &quirk_s2idle_spurious_8042, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "82VF"), -@@ -160,7 +165,7 @@ static const struct dmi_system_id fwbug_ - }, - { - .ident = "IdeaPad 1 15AMN7", -- .driver_data = &quirk_s2idle_bug, -+ .driver_data = &quirk_s2idle_spurious_8042, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "82VG"), -@@ -168,7 +173,7 @@ static const struct dmi_system_id fwbug_ - }, - { - .ident = "IdeaPad 1 15AMN7", -- .driver_data = &quirk_s2idle_bug, -+ .driver_data = &quirk_s2idle_spurious_8042, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "82X5"), -@@ -176,7 +181,7 @@ static const struct dmi_system_id fwbug_ - }, - { - .ident = "IdeaPad Slim 3 14AMN8", -- .driver_data = &quirk_s2idle_bug, -+ .driver_data = &quirk_s2idle_spurious_8042, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "82XN"), -@@ -184,16 +189,25 @@ static const struct dmi_system_id fwbug_ - }, - { - .ident = "IdeaPad Slim 3 15AMN8", -- .driver_data = &quirk_s2idle_bug, -+ .driver_data = &quirk_s2idle_spurious_8042, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "82XQ"), - } - }, -+ /* https://gitlab.freedesktop.org/drm/amd/-/issues/4434 */ -+ { -+ .ident = "Lenovo Yoga 6 13ALC6", -+ .driver_data = &quirk_s2idle_spurious_8042, -+ .matches = { -+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), -+ DMI_MATCH(DMI_PRODUCT_NAME, "82ND"), -+ } -+ }, - /* https://gitlab.freedesktop.org/drm/amd/-/issues/2684 */ - { - .ident = "HP Laptop 15s-eq2xxx", -- .driver_data = &quirk_s2idle_bug, -+ .driver_data = &quirk_s2idle_spurious_8042, - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "HP"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP Laptop 15s-eq2xxx"), -@@ -225,6 +239,44 @@ static const struct dmi_system_id fwbug_ - DMI_MATCH(DMI_BOARD_NAME, "WUJIE14-GX4HRXL"), - } - }, -+ { -+ .ident = "MECHREVO Yilong15Pro Series GM5HG7A", -+ .driver_data = &quirk_spurious_8042, -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "MECHREVO"), -+ DMI_MATCH(DMI_PRODUCT_NAME, "Yilong15Pro Series GM5HG7A"), -+ } -+ }, -+ /* https://bugzilla.kernel.org/show_bug.cgi?id=220116 */ -+ { -+ .ident = "PCSpecialist Lafite Pro V 14M", -+ .driver_data = &quirk_spurious_8042, -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "PCSpecialist"), -+ DMI_MATCH(DMI_PRODUCT_NAME, "Lafite Pro V 14M"), -+ } -+ }, -+ { -+ .ident = "TUXEDO Stellaris Slim 15 AMD Gen6", -+ .driver_data = &quirk_spurious_8042, -+ .matches = { -+ DMI_MATCH(DMI_BOARD_NAME, "GMxHGxx"), -+ } -+ }, -+ { -+ .ident = "TUXEDO InfinityBook Pro 14/15 AMD Gen10", -+ .driver_data = &quirk_spurious_8042, -+ .matches = { -+ DMI_MATCH(DMI_BOARD_NAME, "XxHP4NAx"), -+ } -+ }, -+ { -+ .ident = "TUXEDO InfinityBook Pro 14/15 AMD Gen10", -+ .driver_data = &quirk_spurious_8042, -+ .matches = { -+ DMI_MATCH(DMI_BOARD_NAME, "XxKK4NAx_XxSP4NAx"), -+ } -+ }, - {} - }; - -@@ -267,6 +319,16 @@ void amd_pmc_quirks_init(struct amd_pmc_ - { - const struct dmi_system_id *dmi_id; - -+ /* -+ * IRQ1 may cause an interrupt during resume even without a keyboard -+ * press. -+ * -+ * Affects Renoir, Cezanne and Barcelo SoCs -+ * -+ * A solution is available in PMFW 64.66.0, but it must be activated by -+ * SBIOS. If SBIOS is known to have the fix a quirk can be added for -+ * a given system to avoid workaround. -+ */ - if (dev->cpu_id == AMD_CPU_ID_CZN) - dev->disable_8042_wakeup = true; - -@@ -277,6 +339,5 @@ void amd_pmc_quirks_init(struct amd_pmc_ - if (dev->quirks->s2idle_bug_mmio) - pr_info("Using s2idle quirk to avoid %s platform firmware bug\n", - dmi_id->ident); -- if (dev->quirks->spurious_8042) -- dev->disable_8042_wakeup = true; -+ dev->disable_8042_wakeup = dev->quirks->spurious_8042; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/amd/pmf/core.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/amd/pmf/core.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/amd/pmf/core.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/amd/pmf/core.c 2025-10-22 13:53:56.643168524 -0400 -@@ -280,7 +280,7 @@ int amd_pmf_set_dram_addr(struct amd_pmf - dev_err(dev->dev, "Invalid CPU id: 0x%x", dev->cpu_id); - } - -- dev->buf = kzalloc(dev->mtable_size, GFP_KERNEL); -+ dev->buf = devm_kzalloc(dev->dev, dev->mtable_size, GFP_KERNEL); - if (!dev->buf) - return -ENOMEM; - } -@@ -403,6 +403,7 @@ static const struct acpi_device_id amd_p - {"AMDI0103", 0}, - {"AMDI0105", 0}, - {"AMDI0107", 0}, -+ {"AMDI0108", 0}, - { } - }; - MODULE_DEVICE_TABLE(acpi, amd_pmf_acpi_ids); -@@ -493,7 +494,6 @@ static void amd_pmf_remove(struct platfo - mutex_destroy(&dev->lock); - mutex_destroy(&dev->update_mutex); - mutex_destroy(&dev->cb_mutex); -- kfree(dev->buf); - } - - static const struct attribute_group *amd_pmf_driver_groups[] = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/amd/pmf/tee-if.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/amd/pmf/tee-if.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/amd/pmf/tee-if.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/amd/pmf/tee-if.c 2025-10-22 13:53:56.643168524 -0400 -@@ -358,30 +358,28 @@ static ssize_t amd_pmf_get_pb_data(struc - return -EINVAL; - - /* re-alloc to the new buffer length of the policy binary */ -- new_policy_buf = memdup_user(buf, length); -- if (IS_ERR(new_policy_buf)) -- return PTR_ERR(new_policy_buf); -+ new_policy_buf = devm_kzalloc(dev->dev, length, GFP_KERNEL); -+ if (!new_policy_buf) -+ return -ENOMEM; -+ -+ if (copy_from_user(new_policy_buf, buf, length)) { -+ devm_kfree(dev->dev, new_policy_buf); -+ return -EFAULT; -+ } - -- kfree(dev->policy_buf); -+ devm_kfree(dev->dev, dev->policy_buf); - dev->policy_buf = new_policy_buf; - dev->policy_sz = length; - -- if (!amd_pmf_pb_valid(dev)) { -- ret = -EINVAL; -- goto cleanup; -- } -+ if (!amd_pmf_pb_valid(dev)) -+ return -EINVAL; - - amd_pmf_hex_dump_pb(dev); - ret = amd_pmf_start_policy_engine(dev); - if (ret < 0) -- goto cleanup; -+ return ret; - - return length; -- --cleanup: -- kfree(dev->policy_buf); -- dev->policy_buf = NULL; -- return ret; - } - - static const struct file_operations pb_fops = { -@@ -422,12 +420,12 @@ static int amd_pmf_ta_open_session(struc - rc = tee_client_open_session(ctx, &sess_arg, NULL); - if (rc < 0 || sess_arg.ret != 0) { - pr_err("Failed to open TEE session err:%#x, rc:%d\n", sess_arg.ret, rc); -- return rc; -+ return rc ?: -EINVAL; - } - - *id = sess_arg.session; - -- return rc; -+ return 0; - } - - static int amd_pmf_register_input_device(struct amd_pmf_dev *dev) -@@ -462,7 +460,9 @@ static int amd_pmf_tee_init(struct amd_p - dev->tee_ctx = tee_client_open_context(NULL, amd_pmf_amdtee_ta_match, NULL, NULL); - if (IS_ERR(dev->tee_ctx)) { - dev_err(dev->dev, "Failed to open TEE context\n"); -- return PTR_ERR(dev->tee_ctx); -+ ret = PTR_ERR(dev->tee_ctx); -+ dev->tee_ctx = NULL; -+ return ret; - } - - ret = amd_pmf_ta_open_session(dev->tee_ctx, &dev->session_id, uuid); -@@ -502,9 +502,12 @@ out_ctx: - - static void amd_pmf_tee_deinit(struct amd_pmf_dev *dev) - { -+ if (!dev->tee_ctx) -+ return; - tee_shm_free(dev->fw_shm_pool); - tee_client_close_session(dev->tee_ctx, dev->session_id); - tee_client_close_context(dev->tee_ctx); -+ dev->tee_ctx = NULL; - } - - int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev) -@@ -527,64 +530,45 @@ int amd_pmf_init_smart_pc(struct amd_pmf - - ret = amd_pmf_set_dram_addr(dev, true); - if (ret) -- goto err_cancel_work; -+ return ret; - - dev->policy_base = devm_ioremap_resource(dev->dev, dev->res); -- if (IS_ERR(dev->policy_base)) { -- ret = PTR_ERR(dev->policy_base); -- goto err_free_dram_buf; -- } -+ if (IS_ERR(dev->policy_base)) -+ return PTR_ERR(dev->policy_base); - -- dev->policy_buf = kzalloc(dev->policy_sz, GFP_KERNEL); -- if (!dev->policy_buf) { -- ret = -ENOMEM; -- goto err_free_dram_buf; -- } -+ dev->policy_buf = devm_kzalloc(dev->dev, dev->policy_sz, GFP_KERNEL); -+ if (!dev->policy_buf) -+ return -ENOMEM; - - memcpy_fromio(dev->policy_buf, dev->policy_base, dev->policy_sz); - - if (!amd_pmf_pb_valid(dev)) { - dev_info(dev->dev, "No Smart PC policy present\n"); -- ret = -EINVAL; -- goto err_free_policy; -+ return -EINVAL; - } - - amd_pmf_hex_dump_pb(dev); - -- dev->prev_data = kzalloc(sizeof(*dev->prev_data), GFP_KERNEL); -- if (!dev->prev_data) { -- ret = -ENOMEM; -- goto err_free_policy; -- } -+ dev->prev_data = devm_kzalloc(dev->dev, sizeof(*dev->prev_data), GFP_KERNEL); -+ if (!dev->prev_data) -+ return -ENOMEM; - - for (i = 0; i < ARRAY_SIZE(amd_pmf_ta_uuid); i++) { - ret = amd_pmf_tee_init(dev, &amd_pmf_ta_uuid[i]); - if (ret) -- goto err_free_prev_data; -+ return ret; - - ret = amd_pmf_start_policy_engine(dev); -- switch (ret) { -- case TA_PMF_TYPE_SUCCESS: -- status = true; -- break; -- case TA_ERROR_CRYPTO_INVALID_PARAM: -- case TA_ERROR_CRYPTO_BIN_TOO_LARGE: -- amd_pmf_tee_deinit(dev); -- status = false; -- break; -- default: -- ret = -EINVAL; -- amd_pmf_tee_deinit(dev); -- goto err_free_prev_data; -- } -- -+ dev_dbg(dev->dev, "start policy engine ret: %d\n", ret); -+ status = ret == TA_PMF_TYPE_SUCCESS; - if (status) - break; -+ amd_pmf_tee_deinit(dev); - } - - if (!status && !pb_side_load) { - ret = -EINVAL; -- goto err_free_prev_data; -+ goto err; - } - - if (pb_side_load) -@@ -592,22 +576,12 @@ int amd_pmf_init_smart_pc(struct amd_pmf - - ret = amd_pmf_register_input_device(dev); - if (ret) -- goto err_pmf_remove_pb; -+ goto err; - - return 0; - --err_pmf_remove_pb: -- if (pb_side_load && dev->esbin) -- amd_pmf_remove_pb(dev); -- amd_pmf_tee_deinit(dev); --err_free_prev_data: -- kfree(dev->prev_data); --err_free_policy: -- kfree(dev->policy_buf); --err_free_dram_buf: -- kfree(dev->buf); --err_cancel_work: -- cancel_delayed_work_sync(&dev->pb_work); -+err: -+ amd_pmf_deinit_smart_pc(dev); - - return ret; - } -@@ -621,11 +595,5 @@ void amd_pmf_deinit_smart_pc(struct amd_ - amd_pmf_remove_pb(dev); - - cancel_delayed_work_sync(&dev->pb_work); -- kfree(dev->prev_data); -- dev->prev_data = NULL; -- kfree(dev->policy_buf); -- dev->policy_buf = NULL; -- kfree(dev->buf); -- dev->buf = NULL; - amd_pmf_tee_deinit(dev); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/asus-nb-wmi.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/asus-nb-wmi.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/asus-nb-wmi.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/asus-nb-wmi.c 2025-10-22 13:53:56.643168524 -0400 -@@ -147,7 +147,12 @@ static struct quirk_entry quirk_asus_ign - }; - - static struct quirk_entry quirk_asus_zenbook_duo_kbd = { -- .ignore_key_wlan = true, -+ .key_wlan_event = ASUS_WMI_KEY_IGNORE, -+}; -+ -+static struct quirk_entry quirk_asus_z13 = { -+ .key_wlan_event = ASUS_WMI_KEY_ARMOURY, -+ .tablet_switch_mode = asus_wmi_kbd_dock_devid, - }; - - static int dmi_matched(const struct dmi_system_id *dmi) -@@ -530,6 +535,24 @@ static const struct dmi_system_id asus_q - }, - .driver_data = &quirk_asus_zenbook_duo_kbd, - }, -+ { -+ .callback = dmi_matched, -+ .ident = "ASUS Zenbook Duo UX8406CA", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), -+ DMI_MATCH(DMI_PRODUCT_NAME, "UX8406CA"), -+ }, -+ .driver_data = &quirk_asus_zenbook_duo_kbd, -+ }, -+ { -+ .callback = dmi_matched, -+ .ident = "ASUS ROG Z13", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), -+ DMI_MATCH(DMI_PRODUCT_NAME, "ROG Flow Z13"), -+ }, -+ .driver_data = &quirk_asus_z13, -+ }, - {}, - }; - -@@ -627,6 +650,7 @@ static const struct key_entry asus_nb_wm - { KE_IGNORE, 0xCF, }, /* AC mode */ - { KE_KEY, 0xFA, { KEY_PROG2 } }, /* Lid flip action */ - { KE_KEY, 0xBD, { KEY_PROG2 } }, /* Lid flip action on ROG xflow laptops */ -+ { KE_KEY, ASUS_WMI_KEY_ARMOURY, { KEY_PROG3 } }, - { KE_END, 0}, - }; - -@@ -647,10 +671,10 @@ static void asus_nb_wmi_key_filter(struc - *code = ASUS_WMI_KEY_IGNORE; - break; - case 0x5D: /* Wireless console Toggle */ -- case 0x5E: /* Wireless console Enable */ -- case 0x5F: /* Wireless console Disable */ -- if (quirks->ignore_key_wlan) -- *code = ASUS_WMI_KEY_IGNORE; -+ case 0x5E: /* Wireless console Enable / Keyboard Attach, Detach */ -+ case 0x5F: /* Wireless console Disable / Special Key */ -+ if (quirks->key_wlan_event) -+ *code = quirks->key_wlan_event; - break; - } - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/asus-wmi.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/asus-wmi.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/asus-wmi.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/asus-wmi.c 2025-10-22 13:53:56.643168524 -0400 -@@ -5088,16 +5088,22 @@ static int asus_wmi_probe(struct platfor - - asus_s2idle_check_register(); - -- return asus_wmi_add(pdev); -+ ret = asus_wmi_add(pdev); -+ if (ret) -+ asus_s2idle_check_unregister(); -+ -+ return ret; - } - - static bool used; -+static DEFINE_MUTEX(register_mutex); - - int __init_or_module asus_wmi_register_driver(struct asus_wmi_driver *driver) - { - struct platform_driver *platform_driver; - struct platform_device *platform_device; - -+ guard(mutex)(®ister_mutex); - if (used) - return -EBUSY; - -@@ -5120,6 +5126,7 @@ EXPORT_SYMBOL_GPL(asus_wmi_register_driv - - void asus_wmi_unregister_driver(struct asus_wmi_driver *driver) - { -+ guard(mutex)(®ister_mutex); - asus_s2idle_check_unregister(); - - platform_device_unregister(driver->platform_device); -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/asus-wmi.h BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/asus-wmi.h ---- BPI-Router-Linux-kernel/drivers/platform/x86/asus-wmi.h 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/asus-wmi.h 2025-10-22 13:53:56.643168524 -0400 -@@ -18,6 +18,7 @@ - #include - - #define ASUS_WMI_KEY_IGNORE (-1) -+#define ASUS_WMI_KEY_ARMOURY 0xffff01 - #define ASUS_WMI_BRN_DOWN 0x2e - #define ASUS_WMI_BRN_UP 0x2f - -@@ -40,7 +41,7 @@ struct quirk_entry { - bool wmi_force_als_set; - bool wmi_ignore_fan; - bool filter_i8042_e1_extended_codes; -- bool ignore_key_wlan; -+ int key_wlan_event; - enum asus_wmi_tablet_switch_mode tablet_switch_mode; - int wapf; - /* -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/dell/alienware-wmi-wmax.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/dell/alienware-wmi-wmax.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/dell/alienware-wmi-wmax.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/dell/alienware-wmi-wmax.c 2025-10-22 13:53:56.643168524 -0400 -@@ -90,6 +90,14 @@ static struct awcc_quirks empty_quirks; - - static const struct dmi_system_id awcc_dmi_table[] __initconst = { - { -+ .ident = "Alienware Area-51m", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), -+ DMI_MATCH(DMI_PRODUCT_NAME, "Alienware Area-51m"), -+ }, -+ .driver_data = &generic_quirks, -+ }, -+ { - .ident = "Alienware Area-51m R2", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), -@@ -98,6 +106,14 @@ static const struct dmi_system_id awcc_d - .driver_data = &generic_quirks, - }, - { -+ .ident = "Alienware m15 R5", -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), -+ DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m15 R5"), -+ }, -+ .driver_data = &generic_quirks, -+ }, -+ { - .ident = "Alienware m15 R7", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), -@@ -119,7 +135,7 @@ static const struct dmi_system_id awcc_d - DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), - DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m16 R1 AMD"), - }, -- .driver_data = &g_series_quirks, -+ .driver_data = &generic_quirks, - }, - { - .ident = "Alienware m16 R2", -@@ -233,6 +249,7 @@ static const struct dmi_system_id awcc_d - }, - .driver_data = &g_series_quirks, - }, -+ {} - }; - - enum AWCC_GET_FAN_SENSORS_OPERATIONS { -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/dell/dell-lis3lv02d.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/dell/dell-lis3lv02d.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/dell/dell-lis3lv02d.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/dell/dell-lis3lv02d.c 2025-10-22 13:53:56.643168524 -0400 -@@ -45,9 +45,11 @@ static const struct dmi_system_id lis3lv - * Additional individual entries were added after verification. - */ - DELL_LIS3LV02D_DMI_ENTRY("Latitude 5480", 0x29), -+ DELL_LIS3LV02D_DMI_ENTRY("Latitude 5500", 0x29), - DELL_LIS3LV02D_DMI_ENTRY("Latitude E6330", 0x29), - DELL_LIS3LV02D_DMI_ENTRY("Latitude E6430", 0x29), - DELL_LIS3LV02D_DMI_ENTRY("Precision 3540", 0x29), -+ DELL_LIS3LV02D_DMI_ENTRY("Precision 3551", 0x29), - DELL_LIS3LV02D_DMI_ENTRY("Precision M6800", 0x29), - DELL_LIS3LV02D_DMI_ENTRY("Vostro V131", 0x1d), - DELL_LIS3LV02D_DMI_ENTRY("Vostro 5568", 0x29), -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/dell/dell_rbu.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/dell/dell_rbu.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/dell/dell_rbu.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/dell/dell_rbu.c 2025-10-22 13:53:56.643168524 -0400 -@@ -45,7 +45,7 @@ - MODULE_AUTHOR("Abhay Salunke "); - MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); - MODULE_LICENSE("GPL"); --MODULE_VERSION("3.2"); -+MODULE_VERSION("3.3"); - - #define BIOS_SCAN_LIMIT 0xffffffff - #define MAX_IMAGE_LENGTH 16 -@@ -91,7 +91,7 @@ static void init_packet_head(void) - rbu_data.imagesize = 0; - } - --static int create_packet(void *data, size_t length) -+static int create_packet(void *data, size_t length) __must_hold(&rbu_data.lock) - { - struct packet_data *newpacket; - int ordernum = 0; -@@ -292,7 +292,7 @@ static int packet_read_list(char *data, - remaining_bytes = *pread_length; - bytes_read = rbu_data.packet_read_count; - -- list_for_each_entry(newpacket, (&packet_data_head.list)->next, list) { -+ list_for_each_entry(newpacket, &packet_data_head.list, list) { - bytes_copied = do_packet_read(pdest, newpacket, - remaining_bytes, bytes_read, &temp_count); - remaining_bytes -= bytes_copied; -@@ -315,14 +315,14 @@ static void packet_empty_list(void) - { - struct packet_data *newpacket, *tmp; - -- list_for_each_entry_safe(newpacket, tmp, (&packet_data_head.list)->next, list) { -+ list_for_each_entry_safe(newpacket, tmp, &packet_data_head.list, list) { - list_del(&newpacket->list); - - /* - * zero out the RBU packet memory before freeing - * to make sure there are no stale RBU packets left in memory - */ -- memset(newpacket->data, 0, rbu_data.packetsize); -+ memset(newpacket->data, 0, newpacket->length); - set_memory_wb((unsigned long)newpacket->data, - 1 << newpacket->ordernum); - free_pages((unsigned long) newpacket->data, -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/dell/dell-wmi-ddv.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/dell/dell-wmi-ddv.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/dell/dell-wmi-ddv.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/dell/dell-wmi-ddv.c 2025-10-22 13:53:56.643168524 -0400 -@@ -689,9 +689,13 @@ static int dell_wmi_ddv_battery_translat - - dev_dbg(&data->wdev->dev, "Translation cache miss\n"); - -- /* Perform a translation between a ACPI battery and a battery index */ -- -- ret = power_supply_get_property(battery, POWER_SUPPLY_PROP_SERIAL_NUMBER, &val); -+ /* -+ * Perform a translation between a ACPI battery and a battery index. -+ * We have to use power_supply_get_property_direct() here because this -+ * function will also get called from the callbacks of the power supply -+ * extension. -+ */ -+ ret = power_supply_get_property_direct(battery, POWER_SUPPLY_PROP_SERIAL_NUMBER, &val); - if (ret < 0) - return ret; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/dell/dell-wmi-sysman/dell-wmi-sysman.h BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/dell/dell-wmi-sysman/dell-wmi-sysman.h ---- BPI-Router-Linux-kernel/drivers/platform/x86/dell/dell-wmi-sysman/dell-wmi-sysman.h 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/dell/dell-wmi-sysman/dell-wmi-sysman.h 2025-10-22 13:53:56.643168524 -0400 -@@ -89,6 +89,11 @@ extern struct wmi_sysman_priv wmi_priv; - - enum { ENUM, INT, STR, PO }; - -+#define ENUM_MIN_ELEMENTS 8 -+#define INT_MIN_ELEMENTS 9 -+#define STR_MIN_ELEMENTS 8 -+#define PO_MIN_ELEMENTS 4 -+ - enum { - ATTR_NAME, - DISPL_NAME_LANG_CODE, -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/dell/dell-wmi-sysman/enum-attributes.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/dell/dell-wmi-sysman/enum-attributes.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/dell/dell-wmi-sysman/enum-attributes.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/dell/dell-wmi-sysman/enum-attributes.c 2025-10-22 13:53:56.643168524 -0400 -@@ -23,9 +23,10 @@ static ssize_t current_value_show(struct - obj = get_wmiobj_pointer(instance_id, DELL_WMI_BIOS_ENUMERATION_ATTRIBUTE_GUID); - if (!obj) - return -EIO; -- if (obj->package.elements[CURRENT_VAL].type != ACPI_TYPE_STRING) { -+ if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count < ENUM_MIN_ELEMENTS || -+ obj->package.elements[CURRENT_VAL].type != ACPI_TYPE_STRING) { - kfree(obj); -- return -EINVAL; -+ return -EIO; - } - ret = snprintf(buf, PAGE_SIZE, "%s\n", obj->package.elements[CURRENT_VAL].string.pointer); - kfree(obj); -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/dell/dell-wmi-sysman/int-attributes.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/dell/dell-wmi-sysman/int-attributes.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/dell/dell-wmi-sysman/int-attributes.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/dell/dell-wmi-sysman/int-attributes.c 2025-10-22 13:53:56.643168524 -0400 -@@ -25,9 +25,10 @@ static ssize_t current_value_show(struct - obj = get_wmiobj_pointer(instance_id, DELL_WMI_BIOS_INTEGER_ATTRIBUTE_GUID); - if (!obj) - return -EIO; -- if (obj->package.elements[CURRENT_VAL].type != ACPI_TYPE_INTEGER) { -+ if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count < INT_MIN_ELEMENTS || -+ obj->package.elements[CURRENT_VAL].type != ACPI_TYPE_INTEGER) { - kfree(obj); -- return -EINVAL; -+ return -EIO; - } - ret = snprintf(buf, PAGE_SIZE, "%lld\n", obj->package.elements[CURRENT_VAL].integer.value); - kfree(obj); -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/dell/dell-wmi-sysman/passobj-attributes.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/dell/dell-wmi-sysman/passobj-attributes.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/dell/dell-wmi-sysman/passobj-attributes.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/dell/dell-wmi-sysman/passobj-attributes.c 2025-10-22 13:53:56.643168524 -0400 -@@ -26,9 +26,10 @@ static ssize_t is_enabled_show(struct ko - obj = get_wmiobj_pointer(instance_id, DELL_WMI_BIOS_PASSOBJ_ATTRIBUTE_GUID); - if (!obj) - return -EIO; -- if (obj->package.elements[IS_PASS_SET].type != ACPI_TYPE_INTEGER) { -+ if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count < PO_MIN_ELEMENTS || -+ obj->package.elements[IS_PASS_SET].type != ACPI_TYPE_INTEGER) { - kfree(obj); -- return -EINVAL; -+ return -EIO; - } - ret = snprintf(buf, PAGE_SIZE, "%lld\n", obj->package.elements[IS_PASS_SET].integer.value); - kfree(obj); -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/dell/dell-wmi-sysman/string-attributes.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/dell/dell-wmi-sysman/string-attributes.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/dell/dell-wmi-sysman/string-attributes.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/dell/dell-wmi-sysman/string-attributes.c 2025-10-22 13:53:56.643168524 -0400 -@@ -25,9 +25,10 @@ static ssize_t current_value_show(struct - obj = get_wmiobj_pointer(instance_id, DELL_WMI_BIOS_STRING_ATTRIBUTE_GUID); - if (!obj) - return -EIO; -- if (obj->package.elements[CURRENT_VAL].type != ACPI_TYPE_STRING) { -+ if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count < STR_MIN_ELEMENTS || -+ obj->package.elements[CURRENT_VAL].type != ACPI_TYPE_STRING) { - kfree(obj); -- return -EINVAL; -+ return -EIO; - } - ret = snprintf(buf, PAGE_SIZE, "%s\n", obj->package.elements[CURRENT_VAL].string.pointer); - kfree(obj); -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c 2025-10-22 13:53:56.643168524 -0400 -@@ -407,10 +407,10 @@ static int init_bios_attributes(int attr - return retval; - - switch (attr_type) { -- case ENUM: min_elements = 8; break; -- case INT: min_elements = 9; break; -- case STR: min_elements = 8; break; -- case PO: min_elements = 4; break; -+ case ENUM: min_elements = ENUM_MIN_ELEMENTS; break; -+ case INT: min_elements = INT_MIN_ELEMENTS; break; -+ case STR: min_elements = STR_MIN_ELEMENTS; break; -+ case PO: min_elements = PO_MIN_ELEMENTS; break; - default: - pr_err("Error: Unknown attr_type: %d\n", attr_type); - return -EINVAL; -@@ -597,7 +597,7 @@ err_release_attributes_data: - release_attributes_data(); - - err_destroy_classdev: -- device_destroy(&firmware_attributes_class, MKDEV(0, 0)); -+ device_unregister(wmi_priv.class_dev); - - err_exit_bios_attr_pass_interface: - exit_bios_attr_pass_interface(); -@@ -611,7 +611,7 @@ err_exit_bios_attr_set_interface: - static void __exit sysman_exit(void) - { - release_attributes_data(); -- device_destroy(&firmware_attributes_class, MKDEV(0, 0)); -+ device_unregister(wmi_priv.class_dev); - exit_bios_attr_set_interface(); - exit_bios_attr_pass_interface(); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/hp/hp-bioscfg/bioscfg.c 2025-10-22 13:53:56.643168524 -0400 -@@ -1034,7 +1034,7 @@ err_release_attributes_data: - release_attributes_data(); - - err_destroy_classdev: -- device_destroy(&firmware_attributes_class, MKDEV(0, 0)); -+ device_unregister(bioscfg_drv.class_dev); - - err_unregister_class: - hp_exit_attr_set_interface(); -@@ -1045,7 +1045,7 @@ err_unregister_class: - static void __exit hp_exit(void) - { - release_attributes_data(); -- device_destroy(&firmware_attributes_class, MKDEV(0, 0)); -+ device_unregister(bioscfg_drv.class_dev); - - hp_exit_attr_set_interface(); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/ideapad-laptop.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/ideapad-laptop.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/ideapad-laptop.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/ideapad-laptop.c 2025-10-22 13:53:56.643168524 -0400 -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -267,6 +268,20 @@ static void ideapad_shared_exit(struct i - */ - #define IDEAPAD_EC_TIMEOUT 200 /* in ms */ - -+/* -+ * Some models (e.g., ThinkBook since 2024) have a low tolerance for being -+ * polled too frequently. Doing so may break the state machine in the EC, -+ * resulting in a hard shutdown. -+ * -+ * It is also observed that frequent polls may disturb the ongoing operation -+ * and notably delay the availability of EC response. -+ * -+ * These values are used as the delay before the first poll and the interval -+ * between subsequent polls to solve the above issues. -+ */ -+#define IDEAPAD_EC_POLL_MIN_US 150 -+#define IDEAPAD_EC_POLL_MAX_US 300 -+ - static int eval_int(acpi_handle handle, const char *name, unsigned long *res) - { - unsigned long long result; -@@ -383,7 +398,7 @@ static int read_ec_data(acpi_handle hand - end_jiffies = jiffies + msecs_to_jiffies(IDEAPAD_EC_TIMEOUT) + 1; - - while (time_before(jiffies, end_jiffies)) { -- schedule(); -+ usleep_range(IDEAPAD_EC_POLL_MIN_US, IDEAPAD_EC_POLL_MAX_US); - - err = eval_vpcr(handle, 1, &val); - if (err) -@@ -414,7 +429,7 @@ static int write_ec_cmd(acpi_handle hand - end_jiffies = jiffies + msecs_to_jiffies(IDEAPAD_EC_TIMEOUT) + 1; - - while (time_before(jiffies, end_jiffies)) { -- schedule(); -+ usleep_range(IDEAPAD_EC_POLL_MIN_US, IDEAPAD_EC_POLL_MAX_US); - - err = eval_vpcr(handle, 1, &val); - if (err) -@@ -1654,7 +1669,7 @@ static int ideapad_kbd_bl_init(struct id - priv->kbd_bl.led.name = "platform::" LED_FUNCTION_KBD_BACKLIGHT; - priv->kbd_bl.led.brightness_get = ideapad_kbd_bl_led_cdev_brightness_get; - priv->kbd_bl.led.brightness_set_blocking = ideapad_kbd_bl_led_cdev_brightness_set; -- priv->kbd_bl.led.flags = LED_BRIGHT_HW_CHANGED; -+ priv->kbd_bl.led.flags = LED_BRIGHT_HW_CHANGED | LED_RETAIN_AT_SHUTDOWN; - - err = led_classdev_register(&priv->platform_device->dev, &priv->kbd_bl.led); - if (err) -@@ -1713,7 +1728,7 @@ static int ideapad_fn_lock_led_init(stru - priv->fn_lock.led.name = "platform::" LED_FUNCTION_FNLOCK; - priv->fn_lock.led.brightness_get = ideapad_fn_lock_led_cdev_get; - priv->fn_lock.led.brightness_set_blocking = ideapad_fn_lock_led_cdev_set; -- priv->fn_lock.led.flags = LED_BRIGHT_HW_CHANGED; -+ priv->fn_lock.led.flags = LED_BRIGHT_HW_CHANGED | LED_RETAIN_AT_SHUTDOWN; - - err = led_classdev_register(&priv->platform_device->dev, &priv->fn_lock.led); - if (err) -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/intel/hid.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/intel/hid.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/intel/hid.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/intel/hid.c 2025-10-22 13:53:56.643168524 -0400 -@@ -54,6 +54,7 @@ static const struct acpi_device_id intel - { "INTC107B" }, - { "INTC10CB" }, - { "INTC10CC" }, -+ { "INTC10F1" }, - { } - }; - MODULE_DEVICE_TABLE(acpi, intel_hid_ids); -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/intel/int3472/discrete.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/intel/int3472/discrete.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/intel/int3472/discrete.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/intel/int3472/discrete.c 2025-10-22 13:53:56.643168524 -0400 -@@ -193,6 +193,10 @@ static void int3472_get_con_id_and_polar - *con_id = "privacy-led"; - *gpio_flags = GPIO_ACTIVE_HIGH; - break; -+ case INT3472_GPIO_TYPE_HOTPLUG_DETECT: -+ *con_id = "hpd"; -+ *gpio_flags = GPIO_ACTIVE_HIGH; -+ break; - case INT3472_GPIO_TYPE_POWER_ENABLE: - *con_id = "avdd"; - *gpio_flags = GPIO_ACTIVE_HIGH; -@@ -223,6 +227,7 @@ static void int3472_get_con_id_and_polar - * 0x0b Power enable - * 0x0c Clock enable - * 0x0d Privacy LED -+ * 0x13 Hotplug detect - * - * There are some known platform specific quirks where that does not quite - * hold up; for example where a pin with type 0x01 (Power down) is mapped to -@@ -292,6 +297,7 @@ static int skl_int3472_handle_gpio_resou - switch (type) { - case INT3472_GPIO_TYPE_RESET: - case INT3472_GPIO_TYPE_POWERDOWN: -+ case INT3472_GPIO_TYPE_HOTPLUG_DETECT: - ret = skl_int3472_map_gpio_to_sensor(int3472, agpio, con_id, gpio_flags); - if (ret) - err_msg = "Failed to map GPIO pin to sensor\n"; -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/intel/pmc/core.h BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/intel/pmc/core.h ---- BPI-Router-Linux-kernel/drivers/platform/x86/intel/pmc/core.h 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/intel/pmc/core.h 2025-10-22 13:53:56.643168524 -0400 -@@ -299,6 +299,13 @@ enum ppfear_regs { - #define PTL_PCD_PMC_MMIO_REG_LEN 0x31A8 - - /* SSRAM PMC Device ID */ -+/* LNL */ -+#define PMC_DEVID_LNL_SOCM 0xa87f -+ -+/* PTL */ -+#define PMC_DEVID_PTL_PCDH 0xe37f -+#define PMC_DEVID_PTL_PCDP 0xe47f -+ - /* ARL */ - #define PMC_DEVID_ARL_SOCM 0x777f - #define PMC_DEVID_ARL_SOCS 0xae7f -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/intel/pmc/ssram_telemetry.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/intel/pmc/ssram_telemetry.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/intel/pmc/ssram_telemetry.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/intel/pmc/ssram_telemetry.c 2025-10-22 13:53:56.643168524 -0400 -@@ -187,6 +187,9 @@ static const struct pci_device_id intel_ - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_MTL_SOCM) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_ARL_SOCS) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_ARL_SOCM) }, -+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_LNL_SOCM) }, -+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_PTL_PCDH) }, -+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PMC_DEVID_PTL_PCDP) }, - { } - }; - MODULE_DEVICE_TABLE(pci, intel_pmc_ssram_telemetry_pci_ids); -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/intel/pmt/class.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/intel/pmt/class.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/intel/pmt/class.c 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/intel/pmt/class.c 2025-10-22 13:53:56.643168524 -0400 -@@ -97,7 +97,7 @@ intel_pmt_read(struct file *filp, struct - if (count > entry->size - off) - count = entry->size - off; - -- count = pmt_telem_read_mmio(entry->ep->pcidev, entry->cb, entry->header.guid, buf, -+ count = pmt_telem_read_mmio(entry->pcidev, entry->cb, entry->header.guid, buf, - entry->base, off, count); - - return count; -@@ -252,6 +252,7 @@ static int intel_pmt_populate_entry(stru - return -EINVAL; - } - -+ entry->pcidev = pci_dev; - entry->guid = header->guid; - entry->size = header->size; - entry->cb = ivdev->priv_data; -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/intel/pmt/class.h BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/intel/pmt/class.h ---- BPI-Router-Linux-kernel/drivers/platform/x86/intel/pmt/class.h 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/intel/pmt/class.h 2025-10-22 13:53:56.643168524 -0400 -@@ -39,6 +39,7 @@ struct intel_pmt_header { - - struct intel_pmt_entry { - struct telem_endpoint *ep; -+ struct pci_dev *pcidev; - struct intel_pmt_header header; - struct bin_attribute pmt_bin_attr; - struct kobject *kobj; -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/intel/tpmi_power_domains.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/intel/tpmi_power_domains.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/intel/tpmi_power_domains.c 2025-10-22 13:53:23.435328072 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/intel/tpmi_power_domains.c 2025-10-22 13:53:56.643168524 -0400 -@@ -178,7 +178,7 @@ static int tpmi_get_logical_id(unsigned - - info->punit_thread_id = FIELD_GET(LP_ID_MASK, data); - info->punit_core_id = FIELD_GET(MODULE_ID_MASK, data); -- info->pkg_id = topology_physical_package_id(cpu); -+ info->pkg_id = topology_logical_package_id(cpu); - info->linux_cpu = cpu; - - return 0; -@@ -228,8 +228,10 @@ static int __init tpmi_init(void) - - domain_die_map = kcalloc(size_mul(topology_max_packages(), MAX_POWER_DOMAINS), - sizeof(*domain_die_map), GFP_KERNEL); -- if (!domain_die_map) -+ if (!domain_die_map) { -+ ret = -ENOMEM; - goto free_domain_mask; -+ } - - ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, - "platform/x86/tpmi_power_domains:online", -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c 2025-10-22 13:53:23.435328072 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c 2025-10-22 13:53:56.643168524 -0400 -@@ -58,7 +58,7 @@ static ssize_t show_agent_types(struct k - if (length) - length += sysfs_emit_at(buf, length, " "); - -- length += sysfs_emit_at(buf, length, agent_name[agent]); -+ length += sysfs_emit_at(buf, length, "%s", agent_name[agent]); - } - - length += sysfs_emit_at(buf, length, "\n"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c 2025-10-22 13:53:23.435328072 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c 2025-10-22 13:53:56.643168524 -0400 -@@ -191,9 +191,14 @@ static int uncore_read_control_freq(stru - static int write_eff_lat_ctrl(struct uncore_data *data, unsigned int val, enum uncore_index index) - { - struct tpmi_uncore_cluster_info *cluster_info; -+ struct tpmi_uncore_struct *uncore_root; - u64 control; - - cluster_info = container_of(data, struct tpmi_uncore_cluster_info, uncore_data); -+ uncore_root = cluster_info->uncore_root; -+ -+ if (uncore_root->write_blocked) -+ return -EPERM; - - if (cluster_info->root_domain) - return -ENODATA; -@@ -511,10 +516,13 @@ static int uncore_probe(struct auxiliary - - /* Get the package ID from the TPMI core */ - plat_info = tpmi_get_platform_data(auxdev); -- if (plat_info) -- pkg = plat_info->package_id; -- else -+ if (unlikely(!plat_info)) { - dev_info(&auxdev->dev, "Platform information is NULL\n"); -+ ret = -ENODEV; -+ goto err_rem_common; -+ } -+ -+ pkg = plat_info->package_id; - - for (i = 0; i < num_resources; ++i) { - struct tpmi_uncore_power_domain_info *pd_info; -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/lenovo-wmi-hotkey-utilities.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/lenovo-wmi-hotkey-utilities.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/lenovo-wmi-hotkey-utilities.c 2025-10-22 13:53:23.435328072 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/lenovo-wmi-hotkey-utilities.c 2025-10-22 13:53:56.643168524 -0400 -@@ -122,26 +122,35 @@ static int lenovo_super_hotkey_wmi_led_i - return -EIO; - - union acpi_object *obj __free(kfree) = output.pointer; -- if (obj && obj->type == ACPI_TYPE_INTEGER) -- led_version = obj->integer.value; -- else -+ if (!obj || obj->type != ACPI_TYPE_INTEGER) - return -EIO; - -- wpriv->cdev[led_type].max_brightness = LED_ON; -- wpriv->cdev[led_type].flags = LED_CORE_SUSPENDRESUME; -+ led_version = obj->integer.value; -+ -+ /* -+ * Output parameters define: 0 means mute LED is not supported, Non-zero means -+ * mute LED can be supported. -+ */ -+ if (led_version == 0) -+ return 0; -+ - - switch (led_type) { - case MIC_MUTE: -- if (led_version != WMI_LUD_SUPPORT_MICMUTE_LED_VER) -- return -EIO; -+ if (led_version != WMI_LUD_SUPPORT_MICMUTE_LED_VER) { -+ pr_warn("The MIC_MUTE LED of this device isn't supported.\n"); -+ return 0; -+ } - - wpriv->cdev[led_type].name = "platform::micmute"; - wpriv->cdev[led_type].brightness_set_blocking = &lsh_wmi_micmute_led_set; - wpriv->cdev[led_type].default_trigger = "audio-micmute"; - break; - case AUDIO_MUTE: -- if (led_version != WMI_LUD_SUPPORT_AUDIOMUTE_LED_VER) -- return -EIO; -+ if (led_version != WMI_LUD_SUPPORT_AUDIOMUTE_LED_VER) { -+ pr_warn("The AUDIO_MUTE LED of this device isn't supported.\n"); -+ return 0; -+ } - - wpriv->cdev[led_type].name = "platform::mute"; - wpriv->cdev[led_type].brightness_set_blocking = &lsh_wmi_audiomute_led_set; -@@ -152,6 +161,9 @@ static int lenovo_super_hotkey_wmi_led_i - return -EINVAL; - } - -+ wpriv->cdev[led_type].max_brightness = LED_ON; -+ wpriv->cdev[led_type].flags = LED_CORE_SUSPENDRESUME; -+ - err = devm_led_classdev_register(dev, &wpriv->cdev[led_type]); - if (err < 0) { - dev_err(dev, "Could not register mute LED %d : %d\n", led_type, err); -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/lg-laptop.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/lg-laptop.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/lg-laptop.c 2025-10-22 13:53:23.435328072 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/lg-laptop.c 2025-10-22 13:53:56.643168524 -0400 -@@ -8,6 +8,7 @@ - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -+#include - #include - #include - #include -@@ -75,6 +76,9 @@ MODULE_PARM_DESC(fw_debug, "Enable print - #define WMBB_USB_CHARGE 0x10B - #define WMBB_BATT_LIMIT 0x10C - -+#define FAN_MODE_LOWER GENMASK(1, 0) -+#define FAN_MODE_UPPER GENMASK(5, 4) -+ - #define PLATFORM_NAME "lg-laptop" - - MODULE_ALIAS("wmi:" WMI_EVENT_GUID0); -@@ -274,29 +278,19 @@ static ssize_t fan_mode_store(struct dev - struct device_attribute *attr, - const char *buffer, size_t count) - { -- bool value; -+ unsigned long value; - union acpi_object *r; -- u32 m; - int ret; - -- ret = kstrtobool(buffer, &value); -+ ret = kstrtoul(buffer, 10, &value); - if (ret) - return ret; -+ if (value >= 3) -+ return -EINVAL; - -- r = lg_wmab(dev, WM_FAN_MODE, WM_GET, 0); -- if (!r) -- return -EIO; -- -- if (r->type != ACPI_TYPE_INTEGER) { -- kfree(r); -- return -EIO; -- } -- -- m = r->integer.value; -- kfree(r); -- r = lg_wmab(dev, WM_FAN_MODE, WM_SET, (m & 0xffffff0f) | (value << 4)); -- kfree(r); -- r = lg_wmab(dev, WM_FAN_MODE, WM_SET, (m & 0xfffffff0) | value); -+ r = lg_wmab(dev, WM_FAN_MODE, WM_SET, -+ FIELD_PREP(FAN_MODE_LOWER, value) | -+ FIELD_PREP(FAN_MODE_UPPER, value)); - kfree(r); - - return count; -@@ -305,7 +299,7 @@ static ssize_t fan_mode_store(struct dev - static ssize_t fan_mode_show(struct device *dev, - struct device_attribute *attr, char *buffer) - { -- unsigned int status; -+ unsigned int mode; - union acpi_object *r; - - r = lg_wmab(dev, WM_FAN_MODE, WM_GET, 0); -@@ -317,10 +311,10 @@ static ssize_t fan_mode_show(struct devi - return -EIO; - } - -- status = r->integer.value & 0x01; -+ mode = FIELD_GET(FAN_MODE_LOWER, r->integer.value); - kfree(r); - -- return sysfs_emit(buffer, "%d\n", status); -+ return sysfs_emit(buffer, "%d\n", mode); - } - - static ssize_t usb_charge_store(struct device *dev, -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/Makefile BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/Makefile ---- BPI-Router-Linux-kernel/drivers/platform/x86/Makefile 2025-10-22 13:53:23.431328091 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/Makefile 2025-10-22 13:53:56.643168524 -0400 -@@ -58,6 +58,8 @@ obj-$(CONFIG_X86_PLATFORM_DRIVERS_HP) += - # Hewlett Packard Enterprise - obj-$(CONFIG_UV_SYSFS) += uv_sysfs.o - -+obj-$(CONFIG_FW_ATTR_CLASS) += firmware_attributes_class.o -+ - # IBM Thinkpad and Lenovo - obj-$(CONFIG_IBM_RTL) += ibm_rtl.o - obj-$(CONFIG_IDEAPAD_LAPTOP) += ideapad-laptop.o -@@ -128,7 +130,6 @@ obj-$(CONFIG_SYSTEM76_ACPI) += system76_ - obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o - - # Platform drivers --obj-$(CONFIG_FW_ATTR_CLASS) += firmware_attributes_class.o - obj-$(CONFIG_SERIAL_MULTI_INSTANTIATE) += serial-multi-instantiate.o - obj-$(CONFIG_TOUCHSCREEN_DMI) += touchscreen_dmi.o - obj-$(CONFIG_WIRELESS_HOTKEY) += wireless-hotkey.o -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/oxpec.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/oxpec.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/oxpec.c 2025-10-22 13:53:23.435328072 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/oxpec.c 2025-10-22 13:53:56.643168524 -0400 -@@ -58,7 +58,8 @@ enum oxp_board { - oxp_mini_amd_a07, - oxp_mini_amd_pro, - oxp_x1, -- oxp_g1, -+ oxp_g1_i, -+ oxp_g1_a, - }; - - static enum oxp_board board; -@@ -247,14 +248,14 @@ static const struct dmi_system_id dmi_ta - DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"), - DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER G1 A"), - }, -- .driver_data = (void *)oxp_g1, -+ .driver_data = (void *)oxp_g1_a, - }, - { - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"), - DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER G1 i"), - }, -- .driver_data = (void *)oxp_g1, -+ .driver_data = (void *)oxp_g1_i, - }, - { - .matches = { -@@ -294,10 +295,24 @@ static const struct dmi_system_id dmi_ta - { - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"), -+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER X1Mini Pro"), -+ }, -+ .driver_data = (void *)oxp_x1, -+ }, -+ { -+ .matches = { -+ DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"), - DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER X1Pro"), - }, - .driver_data = (void *)oxp_x1, - }, -+ { -+ .matches = { -+ DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"), -+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER X1Pro EVA-02"), -+ }, -+ .driver_data = (void *)oxp_x1, -+ }, - {}, - }; - -@@ -352,7 +367,8 @@ static umode_t tt_toggle_is_visible(stru - case oxp_mini_amd_a07: - case oxp_mini_amd_pro: - case oxp_x1: -- case oxp_g1: -+ case oxp_g1_i: -+ case oxp_g1_a: - return attr->mode; - default: - break; -@@ -381,12 +397,13 @@ static ssize_t tt_toggle_store(struct de - case aok_zoe_a1: - case oxp_fly: - case oxp_mini_amd_pro: -+ case oxp_g1_a: - reg = OXP_TURBO_SWITCH_REG; - mask = OXP_TURBO_TAKE_VAL; - break; - case oxp_2: - case oxp_x1: -- case oxp_g1: -+ case oxp_g1_i: - reg = OXP_2_TURBO_SWITCH_REG; - mask = OXP_TURBO_TAKE_VAL; - break; -@@ -426,12 +443,13 @@ static ssize_t tt_toggle_show(struct dev - case aok_zoe_a1: - case oxp_fly: - case oxp_mini_amd_pro: -+ case oxp_g1_a: - reg = OXP_TURBO_SWITCH_REG; - mask = OXP_TURBO_TAKE_VAL; - break; - case oxp_2: - case oxp_x1: -- case oxp_g1: -+ case oxp_g1_i: - reg = OXP_2_TURBO_SWITCH_REG; - mask = OXP_TURBO_TAKE_VAL; - break; -@@ -520,7 +538,8 @@ static bool oxp_psy_ext_supported(void) - { - switch (board) { - case oxp_x1: -- case oxp_g1: -+ case oxp_g1_i: -+ case oxp_g1_a: - case oxp_fly: - return true; - default: -@@ -659,7 +678,8 @@ static int oxp_pwm_enable(void) - case oxp_mini_amd_a07: - case oxp_mini_amd_pro: - case oxp_x1: -- case oxp_g1: -+ case oxp_g1_i: -+ case oxp_g1_a: - return write_to_ec(OXP_SENSOR_PWM_ENABLE_REG, PWM_MODE_MANUAL); - default: - return -EINVAL; -@@ -686,7 +706,8 @@ static int oxp_pwm_disable(void) - case oxp_mini_amd_a07: - case oxp_mini_amd_pro: - case oxp_x1: -- case oxp_g1: -+ case oxp_g1_i: -+ case oxp_g1_a: - return write_to_ec(OXP_SENSOR_PWM_ENABLE_REG, PWM_MODE_AUTO); - default: - return -EINVAL; -@@ -713,7 +734,8 @@ static int oxp_pwm_read(long *val) - case oxp_mini_amd_a07: - case oxp_mini_amd_pro: - case oxp_x1: -- case oxp_g1: -+ case oxp_g1_i: -+ case oxp_g1_a: - return read_from_ec(OXP_SENSOR_PWM_ENABLE_REG, 1, val); - default: - return -EOPNOTSUPP; -@@ -742,7 +764,7 @@ static int oxp_pwm_fan_speed(long *val) - return read_from_ec(ORANGEPI_SENSOR_FAN_REG, 2, val); - case oxp_2: - case oxp_x1: -- case oxp_g1: -+ case oxp_g1_i: - return read_from_ec(OXP_2_SENSOR_FAN_REG, 2, val); - case aok_zoe_a1: - case aya_neo_2: -@@ -757,6 +779,7 @@ static int oxp_pwm_fan_speed(long *val) - case oxp_mini_amd: - case oxp_mini_amd_a07: - case oxp_mini_amd_pro: -+ case oxp_g1_a: - return read_from_ec(OXP_SENSOR_FAN_REG, 2, val); - default: - return -EOPNOTSUPP; -@@ -776,7 +799,7 @@ static int oxp_pwm_input_write(long val) - return write_to_ec(ORANGEPI_SENSOR_PWM_REG, val); - case oxp_2: - case oxp_x1: -- case oxp_g1: -+ case oxp_g1_i: - /* scale to range [0-184] */ - val = (val * 184) / 255; - return write_to_ec(OXP_SENSOR_PWM_REG, val); -@@ -796,6 +819,7 @@ static int oxp_pwm_input_write(long val) - case aok_zoe_a1: - case oxp_fly: - case oxp_mini_amd_pro: -+ case oxp_g1_a: - return write_to_ec(OXP_SENSOR_PWM_REG, val); - default: - return -EOPNOTSUPP; -@@ -816,7 +840,7 @@ static int oxp_pwm_input_read(long *val) - break; - case oxp_2: - case oxp_x1: -- case oxp_g1: -+ case oxp_g1_i: - ret = read_from_ec(OXP_SENSOR_PWM_REG, 1, val); - if (ret) - return ret; -@@ -842,6 +866,7 @@ static int oxp_pwm_input_read(long *val) - case aok_zoe_a1: - case oxp_fly: - case oxp_mini_amd_pro: -+ case oxp_g1_a: - default: - ret = read_from_ec(OXP_SENSOR_PWM_REG, 1, val); - if (ret) -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/portwell-ec.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/portwell-ec.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/portwell-ec.c 2025-10-22 13:53:23.435328072 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/portwell-ec.c 2025-10-22 13:53:56.643168524 -0400 -@@ -236,6 +236,7 @@ static int pwec_probe(struct platform_de - return ret; - } - -+ ec_wdt_dev.parent = &pdev->dev; - ret = devm_watchdog_register_device(&pdev->dev, &ec_wdt_dev); - if (ret < 0) { - dev_err(&pdev->dev, "failed to register Portwell EC Watchdog\n"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/samsung-galaxybook.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/samsung-galaxybook.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/samsung-galaxybook.c 2025-10-22 13:53:23.435328072 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/samsung-galaxybook.c 2025-10-22 13:53:56.643168524 -0400 -@@ -1403,6 +1403,7 @@ static int galaxybook_probe(struct platf - } - - static const struct acpi_device_id galaxybook_device_ids[] = { -+ { "SAM0426" }, - { "SAM0427" }, - { "SAM0428" }, - { "SAM0429" }, -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/think-lmi.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/think-lmi.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/think-lmi.c 2025-10-22 13:53:23.435328072 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/think-lmi.c 2025-10-22 13:53:56.647168505 -0400 -@@ -973,6 +973,7 @@ static const struct attribute_group auth - .is_visible = auth_attr_is_visible, - .attrs = auth_attrs, - }; -+__ATTRIBUTE_GROUPS(auth_attr); - - /* ---- Attributes sysfs --------------------------------------------------------- */ - static ssize_t display_name_show(struct kobject *kobj, struct kobj_attribute *attr, -@@ -1188,6 +1189,7 @@ static const struct attribute_group tlmi - .is_visible = attr_is_visible, - .attrs = tlmi_attrs, - }; -+__ATTRIBUTE_GROUPS(tlmi_attr); - - static void tlmi_attr_setting_release(struct kobject *kobj) - { -@@ -1207,11 +1209,13 @@ static void tlmi_pwd_setting_release(str - static const struct kobj_type tlmi_attr_setting_ktype = { - .release = &tlmi_attr_setting_release, - .sysfs_ops = &kobj_sysfs_ops, -+ .default_groups = tlmi_attr_groups, - }; - - static const struct kobj_type tlmi_pwd_setting_ktype = { - .release = &tlmi_pwd_setting_release, - .sysfs_ops = &kobj_sysfs_ops, -+ .default_groups = auth_attr_groups, - }; - - static ssize_t pending_reboot_show(struct kobject *kobj, struct kobj_attribute *attr, -@@ -1380,21 +1384,18 @@ static struct kobj_attribute debug_cmd = - /* ---- Initialisation --------------------------------------------------------- */ - static void tlmi_release_attr(void) - { -- int i; -+ struct kobject *pos, *n; - - /* Attribute structures */ -- for (i = 0; i < TLMI_SETTINGS_COUNT; i++) { -- if (tlmi_priv.setting[i]) { -- sysfs_remove_group(&tlmi_priv.setting[i]->kobj, &tlmi_attr_group); -- kobject_put(&tlmi_priv.setting[i]->kobj); -- } -- } - sysfs_remove_file(&tlmi_priv.attribute_kset->kobj, &pending_reboot.attr); - sysfs_remove_file(&tlmi_priv.attribute_kset->kobj, &save_settings.attr); - - if (tlmi_priv.can_debug_cmd && debug_support) - sysfs_remove_file(&tlmi_priv.attribute_kset->kobj, &debug_cmd.attr); - -+ list_for_each_entry_safe(pos, n, &tlmi_priv.attribute_kset->list, entry) -+ kobject_put(pos); -+ - kset_unregister(tlmi_priv.attribute_kset); - - /* Free up any saved signatures */ -@@ -1402,19 +1403,8 @@ static void tlmi_release_attr(void) - kfree(tlmi_priv.pwd_admin->save_signature); - - /* Authentication structures */ -- sysfs_remove_group(&tlmi_priv.pwd_admin->kobj, &auth_attr_group); -- kobject_put(&tlmi_priv.pwd_admin->kobj); -- sysfs_remove_group(&tlmi_priv.pwd_power->kobj, &auth_attr_group); -- kobject_put(&tlmi_priv.pwd_power->kobj); -- -- if (tlmi_priv.opcode_support) { -- sysfs_remove_group(&tlmi_priv.pwd_system->kobj, &auth_attr_group); -- kobject_put(&tlmi_priv.pwd_system->kobj); -- sysfs_remove_group(&tlmi_priv.pwd_hdd->kobj, &auth_attr_group); -- kobject_put(&tlmi_priv.pwd_hdd->kobj); -- sysfs_remove_group(&tlmi_priv.pwd_nvme->kobj, &auth_attr_group); -- kobject_put(&tlmi_priv.pwd_nvme->kobj); -- } -+ list_for_each_entry_safe(pos, n, &tlmi_priv.authentication_kset->list, entry) -+ kobject_put(pos); - - kset_unregister(tlmi_priv.authentication_kset); - } -@@ -1455,6 +1445,14 @@ static int tlmi_sysfs_init(void) - goto fail_device_created; - } - -+ tlmi_priv.authentication_kset = kset_create_and_add("authentication", NULL, -+ &tlmi_priv.class_dev->kobj); -+ if (!tlmi_priv.authentication_kset) { -+ kset_unregister(tlmi_priv.attribute_kset); -+ ret = -ENOMEM; -+ goto fail_device_created; -+ } -+ - for (i = 0; i < TLMI_SETTINGS_COUNT; i++) { - /* Check if index is a valid setting - skip if it isn't */ - if (!tlmi_priv.setting[i]) -@@ -1471,12 +1469,8 @@ static int tlmi_sysfs_init(void) - - /* Build attribute */ - tlmi_priv.setting[i]->kobj.kset = tlmi_priv.attribute_kset; -- ret = kobject_add(&tlmi_priv.setting[i]->kobj, NULL, -- "%s", tlmi_priv.setting[i]->display_name); -- if (ret) -- goto fail_create_attr; -- -- ret = sysfs_create_group(&tlmi_priv.setting[i]->kobj, &tlmi_attr_group); -+ ret = kobject_init_and_add(&tlmi_priv.setting[i]->kobj, &tlmi_attr_setting_ktype, -+ NULL, "%s", tlmi_priv.setting[i]->display_name); - if (ret) - goto fail_create_attr; - } -@@ -1496,55 +1490,34 @@ static int tlmi_sysfs_init(void) - } - - /* Create authentication entries */ -- tlmi_priv.authentication_kset = kset_create_and_add("authentication", NULL, -- &tlmi_priv.class_dev->kobj); -- if (!tlmi_priv.authentication_kset) { -- ret = -ENOMEM; -- goto fail_create_attr; -- } - tlmi_priv.pwd_admin->kobj.kset = tlmi_priv.authentication_kset; -- ret = kobject_add(&tlmi_priv.pwd_admin->kobj, NULL, "%s", "Admin"); -- if (ret) -- goto fail_create_attr; -- -- ret = sysfs_create_group(&tlmi_priv.pwd_admin->kobj, &auth_attr_group); -+ ret = kobject_init_and_add(&tlmi_priv.pwd_admin->kobj, &tlmi_pwd_setting_ktype, -+ NULL, "%s", "Admin"); - if (ret) - goto fail_create_attr; - - tlmi_priv.pwd_power->kobj.kset = tlmi_priv.authentication_kset; -- ret = kobject_add(&tlmi_priv.pwd_power->kobj, NULL, "%s", "Power-on"); -- if (ret) -- goto fail_create_attr; -- -- ret = sysfs_create_group(&tlmi_priv.pwd_power->kobj, &auth_attr_group); -+ ret = kobject_init_and_add(&tlmi_priv.pwd_power->kobj, &tlmi_pwd_setting_ktype, -+ NULL, "%s", "Power-on"); - if (ret) - goto fail_create_attr; - - if (tlmi_priv.opcode_support) { - tlmi_priv.pwd_system->kobj.kset = tlmi_priv.authentication_kset; -- ret = kobject_add(&tlmi_priv.pwd_system->kobj, NULL, "%s", "System"); -- if (ret) -- goto fail_create_attr; -- -- ret = sysfs_create_group(&tlmi_priv.pwd_system->kobj, &auth_attr_group); -+ ret = kobject_init_and_add(&tlmi_priv.pwd_system->kobj, &tlmi_pwd_setting_ktype, -+ NULL, "%s", "System"); - if (ret) - goto fail_create_attr; - - tlmi_priv.pwd_hdd->kobj.kset = tlmi_priv.authentication_kset; -- ret = kobject_add(&tlmi_priv.pwd_hdd->kobj, NULL, "%s", "HDD"); -- if (ret) -- goto fail_create_attr; -- -- ret = sysfs_create_group(&tlmi_priv.pwd_hdd->kobj, &auth_attr_group); -+ ret = kobject_init_and_add(&tlmi_priv.pwd_hdd->kobj, &tlmi_pwd_setting_ktype, -+ NULL, "%s", "HDD"); - if (ret) - goto fail_create_attr; - - tlmi_priv.pwd_nvme->kobj.kset = tlmi_priv.authentication_kset; -- ret = kobject_add(&tlmi_priv.pwd_nvme->kobj, NULL, "%s", "NVMe"); -- if (ret) -- goto fail_create_attr; -- -- ret = sysfs_create_group(&tlmi_priv.pwd_nvme->kobj, &auth_attr_group); -+ ret = kobject_init_and_add(&tlmi_priv.pwd_nvme->kobj, &tlmi_pwd_setting_ktype, -+ NULL, "%s", "NVMe"); - if (ret) - goto fail_create_attr; - } -@@ -1554,7 +1527,7 @@ static int tlmi_sysfs_init(void) - fail_create_attr: - tlmi_release_attr(); - fail_device_created: -- device_destroy(&firmware_attributes_class, MKDEV(0, 0)); -+ device_unregister(tlmi_priv.class_dev); - fail_class_created: - return ret; - } -@@ -1577,8 +1550,6 @@ static struct tlmi_pwd_setting *tlmi_cre - new_pwd->maxlen = tlmi_priv.pwdcfg.core.max_length; - new_pwd->index = 0; - -- kobject_init(&new_pwd->kobj, &tlmi_pwd_setting_ktype); -- - return new_pwd; - } - -@@ -1683,7 +1654,6 @@ static int tlmi_analyze(struct wmi_devic - if (setting->possible_values) - strreplace(setting->possible_values, ',', ';'); - -- kobject_init(&setting->kobj, &tlmi_attr_setting_ktype); - tlmi_priv.setting[i] = setting; - kfree(item); - } -@@ -1781,7 +1751,7 @@ fail_clear_attr: - static void tlmi_remove(struct wmi_device *wdev) - { - tlmi_release_attr(); -- device_destroy(&firmware_attributes_class, MKDEV(0, 0)); -+ device_unregister(tlmi_priv.class_dev); - } - - static int tlmi_probe(struct wmi_device *wdev, const void *context) -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/thinkpad_acpi.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/thinkpad_acpi.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/thinkpad_acpi.c 2025-10-22 13:53:23.435328072 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/thinkpad_acpi.c 2025-10-22 13:53:56.647168505 -0400 -@@ -559,12 +559,12 @@ static unsigned long __init tpacpi_check - return 0; - } - --static inline bool __pure __init tpacpi_is_lenovo(void) -+static __always_inline bool __pure __init tpacpi_is_lenovo(void) - { - return thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO; - } - --static inline bool __pure __init tpacpi_is_ibm(void) -+static __always_inline bool __pure __init tpacpi_is_ibm(void) - { - return thinkpad_id.vendor == PCI_VENDOR_ID_IBM; - } -@@ -3295,6 +3295,7 @@ static const struct key_entry keymap_len - */ - { KE_KEY, 0x131d, { KEY_VENDOR } }, /* System debug info, similar to old ThinkPad key */ - { KE_KEY, 0x1320, { KEY_LINK_PHONE } }, -+ { KE_KEY, 0x1402, { KEY_LINK_PHONE } }, - { KE_KEY, TP_HKEY_EV_TRACK_DOUBLETAP /* 0x8036 */, { KEY_PROG4 } }, - { KE_END } - }; -diff -purNx .git BPI-Router-Linux-kernel/drivers/platform/x86/wmi.c BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/wmi.c ---- BPI-Router-Linux-kernel/drivers/platform/x86/wmi.c 2025-10-22 13:53:23.435328072 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/platform/x86/wmi.c 2025-10-22 13:53:56.647168505 -0400 -@@ -177,16 +177,22 @@ static int wmi_device_enable(struct wmi_ - acpi_handle handle; - acpi_status status; - -- if (!(wblock->gblock.flags & ACPI_WMI_EXPENSIVE)) -- return 0; -- - if (wblock->dev.dev.type == &wmi_type_method) - return 0; - -- if (wblock->dev.dev.type == &wmi_type_event) -+ if (wblock->dev.dev.type == &wmi_type_event) { -+ /* -+ * Windows always enables/disables WMI events, even when they are -+ * not marked as being expensive. We follow this behavior for -+ * compatibility reasons. -+ */ - snprintf(method, sizeof(method), "WE%02X", wblock->gblock.notify_id); -- else -+ } else { -+ if (!(wblock->gblock.flags & ACPI_WMI_EXPENSIVE)) -+ return 0; -+ - get_acpi_method_name(wblock, 'C', method); -+ } - - /* - * Not all WMI devices marked as expensive actually implement the -diff -purNx .git BPI-Router-Linux-kernel/drivers/pmdomain/governor.c BPI-Router-Linux-kernel-6.16.12/drivers/pmdomain/governor.c ---- BPI-Router-Linux-kernel/drivers/pmdomain/governor.c 2025-10-22 13:53:23.435328072 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pmdomain/governor.c 2025-10-22 13:53:56.647168505 -0400 -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -349,6 +350,8 @@ static bool cpu_power_down_ok(struct dev - struct cpuidle_device *dev; - ktime_t domain_wakeup, next_hrtimer; - ktime_t now = ktime_get(); -+ struct device *cpu_dev; -+ s64 cpu_constraint, global_constraint; - s64 idle_duration_ns; - int cpu, i; - -@@ -359,6 +362,7 @@ static bool cpu_power_down_ok(struct dev - if (!(genpd->flags & GENPD_FLAG_CPU_DOMAIN)) - return true; - -+ global_constraint = cpu_latency_qos_limit(); - /* - * Find the next wakeup for any of the online CPUs within the PM domain - * and its subdomains. Note, we only need the genpd->cpus, as it already -@@ -372,8 +376,16 @@ static bool cpu_power_down_ok(struct dev - if (ktime_before(next_hrtimer, domain_wakeup)) - domain_wakeup = next_hrtimer; - } -+ -+ cpu_dev = get_cpu_device(cpu); -+ if (cpu_dev) { -+ cpu_constraint = dev_pm_qos_raw_resume_latency(cpu_dev); -+ if (cpu_constraint < global_constraint) -+ global_constraint = cpu_constraint; -+ } - } - -+ global_constraint *= NSEC_PER_USEC; - /* The minimum idle duration is from now - until the next wakeup. */ - idle_duration_ns = ktime_to_ns(ktime_sub(domain_wakeup, now)); - if (idle_duration_ns <= 0) -@@ -389,8 +401,10 @@ static bool cpu_power_down_ok(struct dev - */ - i = genpd->state_idx; - do { -- if (idle_duration_ns >= (genpd->states[i].residency_ns + -- genpd->states[i].power_off_latency_ns)) { -+ if ((idle_duration_ns >= (genpd->states[i].residency_ns + -+ genpd->states[i].power_off_latency_ns)) && -+ (global_constraint >= (genpd->states[i].power_on_latency_ns + -+ genpd->states[i].power_off_latency_ns))) { - genpd->state_idx = i; - genpd->gd->last_enter = now; - genpd->gd->reflect_residency = true; -diff -purNx .git BPI-Router-Linux-kernel/drivers/pmdomain/imx/imx8m-blk-ctrl.c BPI-Router-Linux-kernel-6.16.12/drivers/pmdomain/imx/imx8m-blk-ctrl.c ---- BPI-Router-Linux-kernel/drivers/pmdomain/imx/imx8m-blk-ctrl.c 2025-10-22 13:53:23.435328072 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pmdomain/imx/imx8m-blk-ctrl.c 2025-10-22 13:53:56.647168505 -0400 -@@ -665,6 +665,11 @@ static const struct imx8m_blk_ctrl_data - #define LCDIF_1_RD_HURRY GENMASK(15, 13) - #define LCDIF_0_RD_HURRY GENMASK(12, 10) - -+#define ISI_CACHE_CTRL 0x50 -+#define ISI_V_WR_HURRY GENMASK(28, 26) -+#define ISI_U_WR_HURRY GENMASK(25, 23) -+#define ISI_Y_WR_HURRY GENMASK(22, 20) -+ - static int imx8mp_media_power_notifier(struct notifier_block *nb, - unsigned long action, void *data) - { -@@ -694,6 +699,11 @@ static int imx8mp_media_power_notifier(s - regmap_set_bits(bc->regmap, LCDIF_ARCACHE_CTRL, - FIELD_PREP(LCDIF_1_RD_HURRY, 7) | - FIELD_PREP(LCDIF_0_RD_HURRY, 7)); -+ /* Same here for ISI */ -+ regmap_set_bits(bc->regmap, ISI_CACHE_CTRL, -+ FIELD_PREP(ISI_V_WR_HURRY, 7) | -+ FIELD_PREP(ISI_U_WR_HURRY, 7) | -+ FIELD_PREP(ISI_Y_WR_HURRY, 7)); - } - - return NOTIFY_OK; -diff -purNx .git BPI-Router-Linux-kernel/drivers/pmdomain/ti/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/pmdomain/ti/Kconfig ---- BPI-Router-Linux-kernel/drivers/pmdomain/ti/Kconfig 2025-10-22 13:53:23.435328072 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pmdomain/ti/Kconfig 2025-10-22 13:53:56.647168505 -0400 -@@ -10,7 +10,7 @@ if SOC_TI - config TI_SCI_PM_DOMAINS - tristate "TI SCI PM Domains Driver" - depends on TI_SCI_PROTOCOL -- depends on PM_GENERIC_DOMAINS -+ select PM_GENERIC_DOMAINS if PM - help - Generic power domain implementation for TI device implementing - the TI SCI protocol. -diff -purNx .git BPI-Router-Linux-kernel/drivers/power/reset/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/power/reset/Kconfig ---- BPI-Router-Linux-kernel/drivers/power/reset/Kconfig 2025-10-22 13:53:23.435328072 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/power/reset/Kconfig 2025-10-22 13:53:56.647168505 -0400 -@@ -218,6 +218,7 @@ config POWER_RESET_ST - - config POWER_RESET_TORADEX_EC - tristate "Toradex Embedded Controller power-off and reset driver" -+ depends on ARCH_MXC || COMPILE_TEST - depends on I2C - select REGMAP_I2C - help -diff -purNx .git BPI-Router-Linux-kernel/drivers/power/sequencing/pwrseq-qcom-wcn.c BPI-Router-Linux-kernel-6.16.12/drivers/power/sequencing/pwrseq-qcom-wcn.c ---- BPI-Router-Linux-kernel/drivers/power/sequencing/pwrseq-qcom-wcn.c 2025-10-22 13:53:23.435328072 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/power/sequencing/pwrseq-qcom-wcn.c 2025-10-22 13:53:56.647168505 -0400 -@@ -155,7 +155,7 @@ static const struct pwrseq_unit_data pwr - }; - - static const struct pwrseq_unit_data pwrseq_qcom_wcn6855_bt_unit_data = { -- .name = "wlan-enable", -+ .name = "bluetooth-enable", - .deps = pwrseq_qcom_wcn6855_unit_deps, - .enable = pwrseq_qcom_wcn_bt_enable, - .disable = pwrseq_qcom_wcn_bt_disable, -diff -purNx .git BPI-Router-Linux-kernel/drivers/power/supply/bq27xxx_battery.c BPI-Router-Linux-kernel-6.16.12/drivers/power/supply/bq27xxx_battery.c ---- BPI-Router-Linux-kernel/drivers/power/supply/bq27xxx_battery.c 2025-10-22 13:53:23.435328072 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/power/supply/bq27xxx_battery.c 2025-10-22 13:53:56.647168505 -0400 -@@ -1919,8 +1919,8 @@ static void bq27xxx_battery_update_unloc - bool has_singe_flag = di->opts & BQ27XXX_O_ZERO; - - cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, has_singe_flag); -- if ((cache.flags & 0xff) == 0xff) -- cache.flags = -1; /* read error */ -+ if (di->chip == BQ27000 && (cache.flags & 0xff) == 0xff) -+ cache.flags = -ENODEV; /* bq27000 hdq read error */ - if (cache.flags >= 0) { - cache.capacity = bq27xxx_battery_read_soc(di); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/power/supply/cpcap-charger.c BPI-Router-Linux-kernel-6.16.12/drivers/power/supply/cpcap-charger.c ---- BPI-Router-Linux-kernel/drivers/power/supply/cpcap-charger.c 2025-10-22 13:53:23.435328072 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/power/supply/cpcap-charger.c 2025-10-22 13:53:56.647168505 -0400 -@@ -689,9 +689,8 @@ static void cpcap_usb_detect(struct work - struct power_supply *battery; - - battery = power_supply_get_by_name("battery"); -- if (IS_ERR_OR_NULL(battery)) { -- dev_err(ddata->dev, "battery power_supply not available %li\n", -- PTR_ERR(battery)); -+ if (!battery) { -+ dev_err(ddata->dev, "battery power_supply not available\n"); - return; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/power/supply/max14577_charger.c BPI-Router-Linux-kernel-6.16.12/drivers/power/supply/max14577_charger.c ---- BPI-Router-Linux-kernel/drivers/power/supply/max14577_charger.c 2025-10-22 13:53:23.435328072 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/power/supply/max14577_charger.c 2025-10-22 13:53:56.647168505 -0400 -@@ -501,7 +501,7 @@ static struct max14577_charger_platform_ - static struct max14577_charger_platform_data *max14577_charger_dt_init( - struct platform_device *pdev) - { -- return NULL; -+ return ERR_PTR(-ENODATA); - } - #endif /* CONFIG_OF */ - -@@ -572,7 +572,7 @@ static int max14577_charger_probe(struct - chg->max14577 = max14577; - - chg->pdata = max14577_charger_dt_init(pdev); -- if (IS_ERR_OR_NULL(chg->pdata)) -+ if (IS_ERR(chg->pdata)) - return PTR_ERR(chg->pdata); - - ret = max14577_charger_reg_init(chg); -diff -purNx .git BPI-Router-Linux-kernel/drivers/power/supply/max1720x_battery.c BPI-Router-Linux-kernel-6.16.12/drivers/power/supply/max1720x_battery.c ---- BPI-Router-Linux-kernel/drivers/power/supply/max1720x_battery.c 2025-10-22 13:53:23.435328072 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/power/supply/max1720x_battery.c 2025-10-22 13:53:56.647168505 -0400 -@@ -288,9 +288,10 @@ static int max172xx_voltage_to_ps(unsign - return reg * 1250; /* in uV */ - } - --static int max172xx_capacity_to_ps(unsigned int reg) -+static int max172xx_capacity_to_ps(unsigned int reg, -+ struct max1720x_device_info *info) - { -- return reg * 500; /* in uAh */ -+ return reg * (500000 / info->rsense); /* in uAh */ - } - - /* -@@ -394,11 +395,11 @@ static int max1720x_battery_get_property - break; - case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: - ret = regmap_read(info->regmap, MAX172XX_DESIGN_CAP, ®_val); -- val->intval = max172xx_capacity_to_ps(reg_val); -+ val->intval = max172xx_capacity_to_ps(reg_val, info); - break; - case POWER_SUPPLY_PROP_CHARGE_AVG: - ret = regmap_read(info->regmap, MAX172XX_REPCAP, ®_val); -- val->intval = max172xx_capacity_to_ps(reg_val); -+ val->intval = max172xx_capacity_to_ps(reg_val, info); - break; - case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: - ret = regmap_read(info->regmap, MAX172XX_TTE, ®_val); -@@ -422,7 +423,7 @@ static int max1720x_battery_get_property - break; - case POWER_SUPPLY_PROP_CHARGE_FULL: - ret = regmap_read(info->regmap, MAX172XX_FULL_CAP, ®_val); -- val->intval = max172xx_capacity_to_ps(reg_val); -+ val->intval = max172xx_capacity_to_ps(reg_val, info); - break; - case POWER_SUPPLY_PROP_MODEL_NAME: - ret = regmap_read(info->regmap, MAX172XX_DEV_NAME, ®_val); -diff -purNx .git BPI-Router-Linux-kernel/drivers/power/supply/power_supply_core.c BPI-Router-Linux-kernel-6.16.12/drivers/power/supply/power_supply_core.c ---- BPI-Router-Linux-kernel/drivers/power/supply/power_supply_core.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/power/supply/power_supply_core.c 2025-10-22 13:53:56.647168505 -0400 -@@ -1235,9 +1235,8 @@ bool power_supply_has_property(struct po - return false; - } - --int power_supply_get_property(struct power_supply *psy, -- enum power_supply_property psp, -- union power_supply_propval *val) -+static int __power_supply_get_property(struct power_supply *psy, enum power_supply_property psp, -+ union power_supply_propval *val, bool use_extensions) - { - struct power_supply_ext_registration *reg; - -@@ -1247,10 +1246,14 @@ int power_supply_get_property(struct pow - return -ENODEV; - } - -- scoped_guard(rwsem_read, &psy->extensions_sem) { -- power_supply_for_each_extension(reg, psy) { -- if (power_supply_ext_has_property(reg->ext, psp)) -+ if (use_extensions) { -+ scoped_guard(rwsem_read, &psy->extensions_sem) { -+ power_supply_for_each_extension(reg, psy) { -+ if (!power_supply_ext_has_property(reg->ext, psp)) -+ continue; -+ - return reg->ext->get_property(psy, reg->ext, reg->data, psp, val); -+ } - } - } - -@@ -1261,20 +1264,49 @@ int power_supply_get_property(struct pow - else - return -EINVAL; - } -+ -+int power_supply_get_property(struct power_supply *psy, enum power_supply_property psp, -+ union power_supply_propval *val) -+{ -+ return __power_supply_get_property(psy, psp, val, true); -+} - EXPORT_SYMBOL_GPL(power_supply_get_property); - --int power_supply_set_property(struct power_supply *psy, -- enum power_supply_property psp, -- const union power_supply_propval *val) -+/** -+ * power_supply_get_property_direct - Read a power supply property without checking for extensions -+ * @psy: The power supply -+ * @psp: The power supply property to read -+ * @val: The resulting value of the power supply property -+ * -+ * Read a power supply property without taking into account any power supply extensions registered -+ * on the given power supply. This is mostly useful for power supply extensions that want to access -+ * their own power supply as using power_supply_get_property() directly will result in a potential -+ * deadlock. -+ * -+ * Return: 0 on success or negative error code on failure. -+ */ -+int power_supply_get_property_direct(struct power_supply *psy, enum power_supply_property psp, -+ union power_supply_propval *val) -+{ -+ return __power_supply_get_property(psy, psp, val, false); -+} -+EXPORT_SYMBOL_GPL(power_supply_get_property_direct); -+ -+ -+static int __power_supply_set_property(struct power_supply *psy, enum power_supply_property psp, -+ const union power_supply_propval *val, bool use_extensions) - { - struct power_supply_ext_registration *reg; - - if (atomic_read(&psy->use_cnt) <= 0) - return -ENODEV; - -- scoped_guard(rwsem_read, &psy->extensions_sem) { -- power_supply_for_each_extension(reg, psy) { -- if (power_supply_ext_has_property(reg->ext, psp)) { -+ if (use_extensions) { -+ scoped_guard(rwsem_read, &psy->extensions_sem) { -+ power_supply_for_each_extension(reg, psy) { -+ if (!power_supply_ext_has_property(reg->ext, psp)) -+ continue; -+ - if (reg->ext->set_property) - return reg->ext->set_property(psy, reg->ext, reg->data, - psp, val); -@@ -1289,8 +1321,34 @@ int power_supply_set_property(struct pow - - return psy->desc->set_property(psy, psp, val); - } -+ -+int power_supply_set_property(struct power_supply *psy, enum power_supply_property psp, -+ const union power_supply_propval *val) -+{ -+ return __power_supply_set_property(psy, psp, val, true); -+} - EXPORT_SYMBOL_GPL(power_supply_set_property); - -+/** -+ * power_supply_set_property_direct - Write a power supply property without checking for extensions -+ * @psy: The power supply -+ * @psp: The power supply property to write -+ * @val: The value to write to the power supply property -+ * -+ * Write a power supply property without taking into account any power supply extensions registered -+ * on the given power supply. This is mostly useful for power supply extensions that want to access -+ * their own power supply as using power_supply_set_property() directly will result in a potential -+ * deadlock. -+ * -+ * Return: 0 on success or negative error code on failure. -+ */ -+int power_supply_set_property_direct(struct power_supply *psy, enum power_supply_property psp, -+ const union power_supply_propval *val) -+{ -+ return __power_supply_set_property(psy, psp, val, false); -+} -+EXPORT_SYMBOL_GPL(power_supply_set_property_direct); -+ - int power_supply_property_is_writeable(struct power_supply *psy, - enum power_supply_property psp) - { -diff -purNx .git BPI-Router-Linux-kernel/drivers/power/supply/qcom_battmgr.c BPI-Router-Linux-kernel-6.16.12/drivers/power/supply/qcom_battmgr.c ---- BPI-Router-Linux-kernel/drivers/power/supply/qcom_battmgr.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/power/supply/qcom_battmgr.c 2025-10-22 13:53:56.647168505 -0400 -@@ -981,6 +981,8 @@ static unsigned int qcom_battmgr_sc8280x - { - if (!strncmp(chemistry, "LIO", BATTMGR_CHEMISTRY_LEN)) - return POWER_SUPPLY_TECHNOLOGY_LION; -+ if (!strncmp(chemistry, "LIP", BATTMGR_CHEMISTRY_LEN)) -+ return POWER_SUPPLY_TECHNOLOGY_LIPO; - - pr_err("Unknown battery technology '%s'\n", chemistry); - return POWER_SUPPLY_TECHNOLOGY_UNKNOWN; -diff -purNx .git BPI-Router-Linux-kernel/drivers/power/supply/qcom_pmi8998_charger.c BPI-Router-Linux-kernel-6.16.12/drivers/power/supply/qcom_pmi8998_charger.c ---- BPI-Router-Linux-kernel/drivers/power/supply/qcom_pmi8998_charger.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/power/supply/qcom_pmi8998_charger.c 2025-10-22 13:53:56.647168505 -0400 -@@ -1016,7 +1016,9 @@ static int smb2_probe(struct platform_de - if (rc < 0) - return rc; - -- rc = dev_pm_set_wake_irq(chip->dev, chip->cable_irq); -+ devm_device_init_wakeup(chip->dev); -+ -+ rc = devm_pm_set_wake_irq(chip->dev, chip->cable_irq); - if (rc < 0) - return dev_err_probe(chip->dev, rc, "Couldn't set wake irq\n"); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/power/supply/test_power.c BPI-Router-Linux-kernel-6.16.12/drivers/power/supply/test_power.c ---- BPI-Router-Linux-kernel/drivers/power/supply/test_power.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/power/supply/test_power.c 2025-10-22 13:53:56.647168505 -0400 -@@ -259,6 +259,7 @@ static const struct power_supply_config - static int test_power_battery_extmanufacture_year = 1234; - static int test_power_battery_exttemp_max = 1000; - static const enum power_supply_property test_power_battery_extprops[] = { -+ POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, - POWER_SUPPLY_PROP_MANUFACTURE_YEAR, - POWER_SUPPLY_PROP_TEMP_MAX, - }; -@@ -270,6 +271,9 @@ static int test_power_battery_extget_pro - union power_supply_propval *val) - { - switch (psp) { -+ case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: -+ return power_supply_get_property_direct(psy, POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, -+ val); - case POWER_SUPPLY_PROP_MANUFACTURE_YEAR: - val->intval = test_power_battery_extmanufacture_year; - break; -diff -purNx .git BPI-Router-Linux-kernel/drivers/powercap/dtpm_cpu.c BPI-Router-Linux-kernel-6.16.12/drivers/powercap/dtpm_cpu.c ---- BPI-Router-Linux-kernel/drivers/powercap/dtpm_cpu.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/powercap/dtpm_cpu.c 2025-10-22 13:53:56.647168505 -0400 -@@ -96,6 +96,8 @@ static u64 get_pd_power_uw(struct dtpm * - int i; - - pd = em_cpu_get(dtpm_cpu->cpu); -+ if (!pd) -+ return 0; - - pd_mask = em_span_cpus(pd); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/powercap/intel_rapl_common.c BPI-Router-Linux-kernel-6.16.12/drivers/powercap/intel_rapl_common.c ---- BPI-Router-Linux-kernel/drivers/powercap/intel_rapl_common.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/powercap/intel_rapl_common.c 2025-10-22 13:53:56.647168505 -0400 -@@ -341,12 +341,28 @@ static int set_domain_enable(struct powe - { - struct rapl_domain *rd = power_zone_to_rapl_domain(power_zone); - struct rapl_defaults *defaults = get_defaults(rd->rp); -+ u64 val; - int ret; - - cpus_read_lock(); - ret = rapl_write_pl_data(rd, POWER_LIMIT1, PL_ENABLE, mode); -- if (!ret && defaults->set_floor_freq) -+ if (ret) -+ goto end; -+ -+ ret = rapl_read_pl_data(rd, POWER_LIMIT1, PL_ENABLE, false, &val); -+ if (ret) -+ goto end; -+ -+ if (mode != val) { -+ pr_debug("%s cannot be %s\n", power_zone->name, -+ str_enabled_disabled(mode)); -+ goto end; -+ } -+ -+ if (defaults->set_floor_freq) - defaults->set_floor_freq(rd, mode); -+ -+end: - cpus_read_unlock(); - - return ret; -diff -purNx .git BPI-Router-Linux-kernel/drivers/pps/clients/pps-gpio.c BPI-Router-Linux-kernel-6.16.12/drivers/pps/clients/pps-gpio.c ---- BPI-Router-Linux-kernel/drivers/pps/clients/pps-gpio.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pps/clients/pps-gpio.c 2025-10-22 13:53:56.647168505 -0400 -@@ -210,8 +210,8 @@ static int pps_gpio_probe(struct platfor - } - - /* register IRQ interrupt handler */ -- ret = devm_request_irq(dev, data->irq, pps_gpio_irq_handler, -- get_irqf_trigger_flags(data), data->info.name, data); -+ ret = request_irq(data->irq, pps_gpio_irq_handler, -+ get_irqf_trigger_flags(data), data->info.name, data); - if (ret) { - pps_unregister_source(data->pps); - dev_err(dev, "failed to acquire IRQ %d\n", data->irq); -@@ -228,6 +228,7 @@ static void pps_gpio_remove(struct platf - { - struct pps_gpio_device_data *data = platform_get_drvdata(pdev); - -+ free_irq(data->irq, data); - pps_unregister_source(data->pps); - timer_delete_sync(&data->echo_timer); - /* reset echo pin in any case */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/pps/pps.c BPI-Router-Linux-kernel-6.16.12/drivers/pps/pps.c ---- BPI-Router-Linux-kernel/drivers/pps/pps.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pps/pps.c 2025-10-22 13:53:56.647168505 -0400 -@@ -41,6 +41,9 @@ static __poll_t pps_cdev_poll(struct fil - - poll_wait(file, &pps->queue, wait); - -+ if (pps->last_fetched_ev == pps->last_ev) -+ return 0; -+ - return EPOLLIN | EPOLLRDNORM; - } - -@@ -186,9 +189,11 @@ static long pps_cdev_ioctl(struct file * - if (err) - return err; - -- /* Return the fetched timestamp */ -+ /* Return the fetched timestamp and save last fetched event */ - spin_lock_irq(&pps->lock); - -+ pps->last_fetched_ev = pps->last_ev; -+ - fdata.info.assert_sequence = pps->assert_sequence; - fdata.info.clear_sequence = pps->clear_sequence; - fdata.info.assert_tu = pps->assert_tu; -@@ -272,9 +277,11 @@ static long pps_cdev_compat_ioctl(struct - if (err) - return err; - -- /* Return the fetched timestamp */ -+ /* Return the fetched timestamp and save last fetched event */ - spin_lock_irq(&pps->lock); - -+ pps->last_fetched_ev = pps->last_ev; -+ - compat.info.assert_sequence = pps->assert_sequence; - compat.info.clear_sequence = pps->clear_sequence; - compat.info.current_mode = pps->current_mode; -diff -purNx .git BPI-Router-Linux-kernel/drivers/ptp/ptp_clock.c BPI-Router-Linux-kernel-6.16.12/drivers/ptp/ptp_clock.c ---- BPI-Router-Linux-kernel/drivers/ptp/ptp_clock.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/ptp/ptp_clock.c 2025-10-22 13:53:56.647168505 -0400 -@@ -96,7 +96,7 @@ static int ptp_clock_settime(struct posi - struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock); - - if (ptp_clock_freerun(ptp)) { -- pr_err("ptp: physical clock is free running\n"); -+ pr_err_ratelimited("ptp: physical clock is free running\n"); - return -EBUSY; - } - -@@ -121,7 +121,8 @@ static int ptp_clock_adjtime(struct posi - struct ptp_clock_info *ops; - int err = -EOPNOTSUPP; - -- if (ptp_clock_freerun(ptp)) { -+ if (tx->modes & (ADJ_SETOFFSET | ADJ_FREQUENCY | ADJ_OFFSET) && -+ ptp_clock_freerun(ptp)) { - pr_err("ptp: physical clock is free running\n"); - return -EBUSY; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/ptp/ptp_ocp.c BPI-Router-Linux-kernel-6.16.12/drivers/ptp/ptp_ocp.c ---- BPI-Router-Linux-kernel/drivers/ptp/ptp_ocp.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/ptp/ptp_ocp.c 2025-10-22 13:53:56.647168505 -0400 -@@ -4557,8 +4557,7 @@ ptp_ocp_detach(struct ptp_ocp *bp) - ptp_ocp_debugfs_remove_device(bp); - ptp_ocp_detach_sysfs(bp); - ptp_ocp_attr_group_del(bp); -- if (timer_pending(&bp->watchdog)) -- timer_delete_sync(&bp->watchdog); -+ timer_delete_sync(&bp->watchdog); - if (bp->ts0) - ptp_ocp_unregister_ext(bp->ts0); - if (bp->ts1) -diff -purNx .git BPI-Router-Linux-kernel/drivers/ptp/ptp_private.h BPI-Router-Linux-kernel-6.16.12/drivers/ptp/ptp_private.h ---- BPI-Router-Linux-kernel/drivers/ptp/ptp_private.h 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/ptp/ptp_private.h 2025-10-22 13:53:56.647168505 -0400 -@@ -24,6 +24,11 @@ - #define PTP_DEFAULT_MAX_VCLOCKS 20 - #define PTP_MAX_CHANNELS 2048 - -+enum { -+ PTP_LOCK_PHYSICAL = 0, -+ PTP_LOCK_VIRTUAL, -+}; -+ - struct timestamp_event_queue { - struct ptp_extts_event buf[PTP_MAX_TIMESTAMPS]; - int head; -@@ -100,10 +105,20 @@ static inline bool ptp_vclock_in_use(str - { - bool in_use = false; - -+ /* Virtual clocks can't be stacked on top of virtual clocks. -+ * Avoid acquiring the n_vclocks_mux on virtual clocks, to allow this -+ * function to be called from code paths where the n_vclocks_mux of the -+ * parent physical clock is already held. Functionally that's not an -+ * issue, but lockdep would complain, because they have the same lock -+ * class. -+ */ -+ if (ptp->is_virtual_clock) -+ return false; -+ - if (mutex_lock_interruptible(&ptp->n_vclocks_mux)) - return true; - -- if (!ptp->is_virtual_clock && ptp->n_vclocks) -+ if (ptp->n_vclocks) - in_use = true; - - mutex_unlock(&ptp->n_vclocks_mux); -diff -purNx .git BPI-Router-Linux-kernel/drivers/ptp/ptp_vclock.c BPI-Router-Linux-kernel-6.16.12/drivers/ptp/ptp_vclock.c ---- BPI-Router-Linux-kernel/drivers/ptp/ptp_vclock.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/ptp/ptp_vclock.c 2025-10-22 13:53:56.647168505 -0400 -@@ -154,6 +154,11 @@ static long ptp_vclock_refresh(struct pt - return PTP_VCLOCK_REFRESH_INTERVAL; - } - -+static void ptp_vclock_set_subclass(struct ptp_clock *ptp) -+{ -+ lockdep_set_subclass(&ptp->clock.rwsem, PTP_LOCK_VIRTUAL); -+} -+ - static const struct ptp_clock_info ptp_vclock_info = { - .owner = THIS_MODULE, - .name = "ptp virtual clock", -@@ -213,6 +218,8 @@ struct ptp_vclock *ptp_vclock_register(s - return NULL; - } - -+ ptp_vclock_set_subclass(vclock->clock); -+ - timecounter_init(&vclock->tc, &vclock->cc, 0); - ptp_schedule_worker(vclock->clock, PTP_VCLOCK_REFRESH_INTERVAL); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/pwm/core.c BPI-Router-Linux-kernel-6.16.12/drivers/pwm/core.c ---- BPI-Router-Linux-kernel/drivers/pwm/core.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pwm/core.c 2025-10-22 13:53:56.647168505 -0400 -@@ -596,7 +596,7 @@ static bool pwm_state_valid(const struct - * and supposed to be ignored. So also ignore any strange values and - * consider the state ok. - */ -- if (state->enabled) -+ if (!state->enabled) - return true; - - if (!state->period) -diff -purNx .git BPI-Router-Linux-kernel/drivers/pwm/pwm-imx-tpm.c BPI-Router-Linux-kernel-6.16.12/drivers/pwm/pwm-imx-tpm.c ---- BPI-Router-Linux-kernel/drivers/pwm/pwm-imx-tpm.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pwm/pwm-imx-tpm.c 2025-10-22 13:53:56.647168505 -0400 -@@ -205,6 +205,15 @@ static int pwm_imx_tpm_apply_hw(struct p - writel(val, tpm->base + PWM_IMX_TPM_SC); - - /* -+ * if the counter is disabled (CMOD == 0), programming the new -+ * period length (MOD) will not reset the counter (CNT). If -+ * CNT.COUNT happens to be bigger than the new MOD value then -+ * the counter will end up being reset way too late. Therefore, -+ * manually reset it to 0. -+ */ -+ if (!cmod) -+ writel(0x0, tpm->base + PWM_IMX_TPM_CNT); -+ /* - * set period count: - * if the PWM is disabled (CMOD[1:0] = 2b00), then MOD register - * is updated when MOD register is written. -diff -purNx .git BPI-Router-Linux-kernel/drivers/pwm/pwm-mediatek.c BPI-Router-Linux-kernel-6.16.12/drivers/pwm/pwm-mediatek.c ---- BPI-Router-Linux-kernel/drivers/pwm/pwm-mediatek.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/pwm/pwm-mediatek.c 2025-10-22 13:53:56.647168505 -0400 -@@ -115,6 +115,26 @@ static inline void pwm_mediatek_writel(s - writel(value, chip->regs + chip->soc->reg_offset[num] + offset); - } - -+static void pwm_mediatek_enable(struct pwm_chip *chip, struct pwm_device *pwm) -+{ -+ struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip); -+ u32 value; -+ -+ value = readl(pc->regs); -+ value |= BIT(pwm->hwpwm); -+ writel(value, pc->regs); -+} -+ -+static void pwm_mediatek_disable(struct pwm_chip *chip, struct pwm_device *pwm) -+{ -+ struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip); -+ u32 value; -+ -+ value = readl(pc->regs); -+ value &= ~BIT(pwm->hwpwm); -+ writel(value, pc->regs); -+} -+ - static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm, - int duty_ns, int period_ns) - { -@@ -130,8 +150,10 @@ static int pwm_mediatek_config(struct pw - return ret; - - clk_rate = clk_get_rate(pc->clk_pwms[pwm->hwpwm]); -- if (!clk_rate) -- return -EINVAL; -+ if (!clk_rate) { -+ ret = -EINVAL; -+ goto out; -+ } - - /* Make sure we use the bus clock and not the 26MHz clock */ - if (pc->soc->has_ck_26m_sel) -@@ -142,7 +164,10 @@ static int pwm_mediatek_config(struct pw - do_div(resolution, clk_rate); - - cnt_period = DIV_ROUND_CLOSEST_ULL((u64)period_ns * 1000, resolution); -- while (cnt_period > 8191) { -+ if (!cnt_period) -+ return -EINVAL; -+ -+ while (cnt_period > 8192) { - resolution *= 2; - clkdiv++; - cnt_period = DIV_ROUND_CLOSEST_ULL((u64)period_ns * 1000, -@@ -150,9 +175,9 @@ static int pwm_mediatek_config(struct pw - } - - if (clkdiv > PWM_CLK_DIV_MAX) { -- pwm_mediatek_clk_disable(chip, pwm); - dev_err(pwmchip_parent(chip), "period of %d ns not supported\n", period_ns); -- return -EINVAL; -+ ret = -EINVAL; -+ goto out; - } - - if (pc->soc->pwm45_fixup && pwm->hwpwm > 2) { -@@ -165,42 +190,21 @@ static int pwm_mediatek_config(struct pw - } - - cnt_duty = DIV_ROUND_CLOSEST_ULL((u64)duty_ns * 1000, resolution); -- pwm_mediatek_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | clkdiv); -- pwm_mediatek_writel(pc, pwm->hwpwm, reg_width, cnt_period); -- pwm_mediatek_writel(pc, pwm->hwpwm, reg_thres, cnt_duty); -- -- pwm_mediatek_clk_disable(chip, pwm); - -- return 0; --} -- --static int pwm_mediatek_enable(struct pwm_chip *chip, struct pwm_device *pwm) --{ -- struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip); -- u32 value; -- int ret; -- -- ret = pwm_mediatek_clk_enable(chip, pwm); -- if (ret < 0) -- return ret; -- -- value = readl(pc->regs); -- value |= BIT(pwm->hwpwm); -- writel(value, pc->regs); -- -- return 0; --} -- --static void pwm_mediatek_disable(struct pwm_chip *chip, struct pwm_device *pwm) --{ -- struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip); -- u32 value; -+ pwm_mediatek_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | clkdiv); -+ pwm_mediatek_writel(pc, pwm->hwpwm, reg_width, cnt_period - 1); - -- value = readl(pc->regs); -- value &= ~BIT(pwm->hwpwm); -- writel(value, pc->regs); -+ if (cnt_duty) { -+ pwm_mediatek_writel(pc, pwm->hwpwm, reg_thres, cnt_duty - 1); -+ pwm_mediatek_enable(chip, pwm); -+ } else { -+ pwm_mediatek_disable(chip, pwm); -+ } - -+out: - pwm_mediatek_clk_disable(chip, pwm); -+ -+ return ret; - } - - static int pwm_mediatek_apply(struct pwm_chip *chip, struct pwm_device *pwm, -@@ -212,8 +216,10 @@ static int pwm_mediatek_apply(struct pwm - return -EINVAL; - - if (!state->enabled) { -- if (pwm->state.enabled) -+ if (pwm->state.enabled) { - pwm_mediatek_disable(chip, pwm); -+ pwm_mediatek_clk_disable(chip, pwm); -+ } - - return 0; - } -@@ -223,7 +229,7 @@ static int pwm_mediatek_apply(struct pwm - return err; - - if (!pwm->state.enabled) -- err = pwm_mediatek_enable(chip, pwm); -+ err = pwm_mediatek_clk_enable(chip, pwm); - - return err; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/rapidio/rio_cm.c BPI-Router-Linux-kernel-6.16.12/drivers/rapidio/rio_cm.c ---- BPI-Router-Linux-kernel/drivers/rapidio/rio_cm.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/rapidio/rio_cm.c 2025-10-22 13:53:56.647168505 -0400 -@@ -783,6 +783,9 @@ static int riocm_ch_send(u16 ch_id, void - if (buf == NULL || ch_id == 0 || len == 0 || len > RIO_MAX_MSG_SIZE) - return -EINVAL; - -+ if (len < sizeof(struct rio_ch_chan_hdr)) -+ return -EINVAL; /* insufficient data from user */ -+ - ch = riocm_get_channel(ch_id); - if (!ch) { - riocm_error("%s(%d) ch_%d not found", current->comm, -diff -purNx .git BPI-Router-Linux-kernel/drivers/regulator/core.c BPI-Router-Linux-kernel-6.16.12/drivers/regulator/core.c ---- BPI-Router-Linux-kernel/drivers/regulator/core.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/regulator/core.c 2025-10-22 13:53:56.647168505 -0400 -@@ -5639,6 +5639,7 @@ static void regulator_remove_coupling(st - ERR_PTR(err)); - } - -+ rdev->coupling_desc.n_coupled = 0; - kfree(rdev->coupling_desc.coupled_rdevs); - rdev->coupling_desc.coupled_rdevs = NULL; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/regulator/fan53555.c BPI-Router-Linux-kernel-6.16.12/drivers/regulator/fan53555.c ---- BPI-Router-Linux-kernel/drivers/regulator/fan53555.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/regulator/fan53555.c 2025-10-22 13:53:56.647168505 -0400 -@@ -147,6 +147,7 @@ struct fan53555_device_info { - unsigned int slew_mask; - const unsigned int *ramp_delay_table; - unsigned int n_ramp_values; -+ unsigned int enable_time; - unsigned int slew_rate; - }; - -@@ -282,6 +283,7 @@ static int fan53526_voltages_setup_fairc - di->slew_mask = CTL_SLEW_MASK; - di->ramp_delay_table = slew_rates; - di->n_ramp_values = ARRAY_SIZE(slew_rates); -+ di->enable_time = 250; - di->vsel_count = FAN53526_NVOLTAGES; - - return 0; -@@ -296,10 +298,12 @@ static int fan53555_voltages_setup_fairc - case FAN53555_CHIP_REV_00: - di->vsel_min = 600000; - di->vsel_step = 10000; -+ di->enable_time = 400; - break; - case FAN53555_CHIP_REV_13: - di->vsel_min = 800000; - di->vsel_step = 10000; -+ di->enable_time = 400; - break; - default: - dev_err(di->dev, -@@ -311,13 +315,19 @@ static int fan53555_voltages_setup_fairc - case FAN53555_CHIP_ID_01: - case FAN53555_CHIP_ID_03: - case FAN53555_CHIP_ID_05: -+ di->vsel_min = 600000; -+ di->vsel_step = 10000; -+ di->enable_time = 400; -+ break; - case FAN53555_CHIP_ID_08: - di->vsel_min = 600000; - di->vsel_step = 10000; -+ di->enable_time = 175; - break; - case FAN53555_CHIP_ID_04: - di->vsel_min = 603000; - di->vsel_step = 12826; -+ di->enable_time = 400; - break; - default: - dev_err(di->dev, -@@ -350,6 +360,7 @@ static int fan53555_voltages_setup_rockc - di->slew_mask = CTL_SLEW_MASK; - di->ramp_delay_table = slew_rates; - di->n_ramp_values = ARRAY_SIZE(slew_rates); -+ di->enable_time = 360; - di->vsel_count = FAN53555_NVOLTAGES; - - return 0; -@@ -372,6 +383,7 @@ static int rk8602_voltages_setup_rockchi - di->slew_mask = CTL_SLEW_MASK; - di->ramp_delay_table = slew_rates; - di->n_ramp_values = ARRAY_SIZE(slew_rates); -+ di->enable_time = 360; - di->vsel_count = RK8602_NVOLTAGES; - - return 0; -@@ -395,6 +407,7 @@ static int fan53555_voltages_setup_siler - di->slew_mask = CTL_SLEW_MASK; - di->ramp_delay_table = slew_rates; - di->n_ramp_values = ARRAY_SIZE(slew_rates); -+ di->enable_time = 400; - di->vsel_count = FAN53555_NVOLTAGES; - - return 0; -@@ -594,6 +607,7 @@ static int fan53555_regulator_register(s - rdesc->ramp_mask = di->slew_mask; - rdesc->ramp_delay_table = di->ramp_delay_table; - rdesc->n_ramp_values = di->n_ramp_values; -+ rdesc->enable_time = di->enable_time; - rdesc->owner = THIS_MODULE; - - rdev = devm_regulator_register(di->dev, &di->desc, config); -diff -purNx .git BPI-Router-Linux-kernel/drivers/regulator/gpio-regulator.c BPI-Router-Linux-kernel-6.16.12/drivers/regulator/gpio-regulator.c ---- BPI-Router-Linux-kernel/drivers/regulator/gpio-regulator.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/regulator/gpio-regulator.c 2025-10-22 13:53:56.647168505 -0400 -@@ -260,8 +260,10 @@ static int gpio_regulator_probe(struct p - return -ENOMEM; - } - -- drvdata->gpiods = devm_kzalloc(dev, sizeof(struct gpio_desc *), -- GFP_KERNEL); -+ drvdata->gpiods = devm_kcalloc(dev, config->ngpios, -+ sizeof(struct gpio_desc *), GFP_KERNEL); -+ if (!drvdata->gpiods) -+ return -ENOMEM; - - if (config->input_supply) { - drvdata->desc.supply_name = devm_kstrdup(&pdev->dev, -@@ -274,8 +276,6 @@ static int gpio_regulator_probe(struct p - } - } - -- if (!drvdata->gpiods) -- return -ENOMEM; - for (i = 0; i < config->ngpios; i++) { - drvdata->gpiods[i] = devm_gpiod_get_index(dev, - NULL, -diff -purNx .git BPI-Router-Linux-kernel/drivers/regulator/max20086-regulator.c BPI-Router-Linux-kernel-6.16.12/drivers/regulator/max20086-regulator.c ---- BPI-Router-Linux-kernel/drivers/regulator/max20086-regulator.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/regulator/max20086-regulator.c 2025-10-22 13:53:56.647168505 -0400 -@@ -5,6 +5,7 @@ - // Copyright (C) 2022 Laurent Pinchart - // Copyright (C) 2018 Avnet, Inc. - -+#include - #include - #include - #include -@@ -133,11 +134,11 @@ static int max20086_regulators_register( - static int max20086_parse_regulators_dt(struct max20086 *chip, bool *boot_on) - { - struct of_regulator_match *matches; -- struct device_node *node; - unsigned int i; - int ret; - -- node = of_get_child_by_name(chip->dev->of_node, "regulators"); -+ struct device_node *node __free(device_node) = -+ of_get_child_by_name(chip->dev->of_node, "regulators"); - if (!node) { - dev_err(chip->dev, "regulators node not found\n"); - return -ENODEV; -@@ -153,7 +154,6 @@ static int max20086_parse_regulators_dt( - - ret = of_regulator_match(chip->dev, node, matches, - chip->info->num_outputs); -- of_node_put(node); - if (ret < 0) { - dev_err(chip->dev, "Failed to match regulators\n"); - return -EINVAL; -diff -purNx .git BPI-Router-Linux-kernel/drivers/regulator/mp886x.c BPI-Router-Linux-kernel-6.16.12/drivers/regulator/mp886x.c ---- BPI-Router-Linux-kernel/drivers/regulator/mp886x.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/regulator/mp886x.c 2025-10-22 13:53:56.647168505 -0400 -@@ -348,7 +348,8 @@ static const struct of_device_id mp886x_ - MODULE_DEVICE_TABLE(of, mp886x_dt_ids); - - static const struct i2c_device_id mp886x_id[] = { -- { "mp886x", (kernel_ulong_t)&mp8869_ci }, -+ { "mp8867", (kernel_ulong_t)&mp8867_ci }, -+ { "mp8869", (kernel_ulong_t)&mp8869_ci }, - { }, - }; - MODULE_DEVICE_TABLE(i2c, mp886x_id); -diff -purNx .git BPI-Router-Linux-kernel/drivers/regulator/pca9450-regulator.c BPI-Router-Linux-kernel-6.16.12/drivers/regulator/pca9450-regulator.c ---- BPI-Router-Linux-kernel/drivers/regulator/pca9450-regulator.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/regulator/pca9450-regulator.c 2025-10-22 13:53:56.651168486 -0400 -@@ -34,7 +34,6 @@ struct pca9450 { - struct device *dev; - struct regmap *regmap; - struct gpio_desc *sd_vsel_gpio; -- struct notifier_block restart_nb; - enum pca9450_chip_type type; - unsigned int rcnt; - int irq; -@@ -967,10 +966,9 @@ static irqreturn_t pca9450_irq_handler(i - return IRQ_HANDLED; - } - --static int pca9450_i2c_restart_handler(struct notifier_block *nb, -- unsigned long action, void *data) -+static int pca9450_i2c_restart_handler(struct sys_off_data *data) - { -- struct pca9450 *pca9450 = container_of(nb, struct pca9450, restart_nb); -+ struct pca9450 *pca9450 = data->cb_data; - struct i2c_client *i2c = container_of(pca9450->dev, struct i2c_client, dev); - - dev_dbg(&i2c->dev, "Restarting device..\n"); -@@ -1128,10 +1126,9 @@ static int pca9450_i2c_probe(struct i2c_ - pca9450->sd_vsel_fixed_low = - of_property_read_bool(ldo5->dev.of_node, "nxp,sd-vsel-fixed-low"); - -- pca9450->restart_nb.notifier_call = pca9450_i2c_restart_handler; -- pca9450->restart_nb.priority = PCA9450_RESTART_HANDLER_PRIORITY; -- -- if (register_restart_handler(&pca9450->restart_nb)) -+ if (devm_register_sys_off_handler(&i2c->dev, SYS_OFF_MODE_RESTART, -+ PCA9450_RESTART_HANDLER_PRIORITY, -+ pca9450_i2c_restart_handler, pca9450)) - dev_warn(&i2c->dev, "Failed to register restart handler\n"); - - dev_info(&i2c->dev, "%s probed.\n", -diff -purNx .git BPI-Router-Linux-kernel/drivers/regulator/sy7636a-regulator.c BPI-Router-Linux-kernel-6.16.12/drivers/regulator/sy7636a-regulator.c ---- BPI-Router-Linux-kernel/drivers/regulator/sy7636a-regulator.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/regulator/sy7636a-regulator.c 2025-10-22 13:53:56.651168486 -0400 -@@ -83,9 +83,11 @@ static int sy7636a_regulator_probe(struc - if (!regmap) - return -EPROBE_DEFER; - -- gdp = devm_gpiod_get(pdev->dev.parent, "epd-pwr-good", GPIOD_IN); -+ device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent); -+ -+ gdp = devm_gpiod_get(&pdev->dev, "epd-pwr-good", GPIOD_IN); - if (IS_ERR(gdp)) { -- dev_err(pdev->dev.parent, "Power good GPIO fault %ld\n", PTR_ERR(gdp)); -+ dev_err(&pdev->dev, "Power good GPIO fault %ld\n", PTR_ERR(gdp)); - return PTR_ERR(gdp); - } - -@@ -105,7 +107,6 @@ static int sy7636a_regulator_probe(struc - } - - config.dev = &pdev->dev; -- config.dev->of_node = pdev->dev.parent->of_node; - config.regmap = regmap; - - rdev = devm_regulator_register(&pdev->dev, &desc, &config); -diff -purNx .git BPI-Router-Linux-kernel/drivers/regulator/sy8824x.c BPI-Router-Linux-kernel-6.16.12/drivers/regulator/sy8824x.c ---- BPI-Router-Linux-kernel/drivers/regulator/sy8824x.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/regulator/sy8824x.c 2025-10-22 13:53:56.651168486 -0400 -@@ -213,7 +213,10 @@ static const struct of_device_id sy8824_ - MODULE_DEVICE_TABLE(of, sy8824_dt_ids); - - static const struct i2c_device_id sy8824_id[] = { -- { "sy8824", (kernel_ulong_t)&sy8824c_cfg }, -+ { "sy8824c", (kernel_ulong_t)&sy8824c_cfg }, -+ { "sy8824e", (kernel_ulong_t)&sy8824e_cfg }, -+ { "sy20276", (kernel_ulong_t)&sy20276_cfg }, -+ { "sy20278", (kernel_ulong_t)&sy20278_cfg }, - { } - }; - MODULE_DEVICE_TABLE(i2c, sy8824_id); -diff -purNx .git BPI-Router-Linux-kernel/drivers/regulator/tps65219-regulator.c BPI-Router-Linux-kernel-6.16.12/drivers/regulator/tps65219-regulator.c ---- BPI-Router-Linux-kernel/drivers/regulator/tps65219-regulator.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/regulator/tps65219-regulator.c 2025-10-22 13:53:56.651168486 -0400 -@@ -436,50 +436,50 @@ static int tps65219_regulator_probe(stru - pmic->rdesc[i].name); - } - -- irq_data = devm_kmalloc(tps->dev, pmic->common_irq_size, GFP_KERNEL); -- if (!irq_data) -- return -ENOMEM; -- - for (i = 0; i < pmic->common_irq_size; ++i) { - irq_type = &pmic->common_irq_types[i]; - irq = platform_get_irq_byname(pdev, irq_type->irq_name); - if (irq < 0) - return -EINVAL; - -- irq_data[i].dev = tps->dev; -- irq_data[i].type = irq_type; -+ irq_data = devm_kmalloc(tps->dev, sizeof(*irq_data), GFP_KERNEL); -+ if (!irq_data) -+ return -ENOMEM; -+ -+ irq_data->dev = tps->dev; -+ irq_data->type = irq_type; - error = devm_request_threaded_irq(tps->dev, irq, NULL, - tps65219_regulator_irq_handler, - IRQF_ONESHOT, - irq_type->irq_name, -- &irq_data[i]); -+ irq_data); - if (error) -- return dev_err_probe(tps->dev, PTR_ERR(rdev), -- "Failed to request %s IRQ %d: %d\n", -- irq_type->irq_name, irq, error); -+ return dev_err_probe(tps->dev, error, -+ "Failed to request %s IRQ %d\n", -+ irq_type->irq_name, irq); - } - -- irq_data = devm_kmalloc(tps->dev, pmic->dev_irq_size, GFP_KERNEL); -- if (!irq_data) -- return -ENOMEM; -- - for (i = 0; i < pmic->dev_irq_size; ++i) { - irq_type = &pmic->irq_types[i]; - irq = platform_get_irq_byname(pdev, irq_type->irq_name); - if (irq < 0) - return -EINVAL; - -- irq_data[i].dev = tps->dev; -- irq_data[i].type = irq_type; -+ irq_data = devm_kmalloc(tps->dev, sizeof(*irq_data), GFP_KERNEL); -+ if (!irq_data) -+ return -ENOMEM; -+ -+ irq_data->dev = tps->dev; -+ irq_data->type = irq_type; - error = devm_request_threaded_irq(tps->dev, irq, NULL, - tps65219_regulator_irq_handler, - IRQF_ONESHOT, - irq_type->irq_name, -- &irq_data[i]); -+ irq_data); - if (error) -- return dev_err_probe(tps->dev, PTR_ERR(rdev), -- "Failed to request %s IRQ %d: %d\n", -- irq_type->irq_name, irq, error); -+ return dev_err_probe(tps->dev, error, -+ "Failed to request %s IRQ %d\n", -+ irq_type->irq_name, irq); - } - - return 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/remoteproc/imx_rproc.c BPI-Router-Linux-kernel-6.16.12/drivers/remoteproc/imx_rproc.c ---- BPI-Router-Linux-kernel/drivers/remoteproc/imx_rproc.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/remoteproc/imx_rproc.c 2025-10-22 13:53:56.651168486 -0400 -@@ -1029,8 +1029,8 @@ static int imx_rproc_clk_enable(struct i - struct device *dev = priv->dev; - int ret; - -- /* Remote core is not under control of Linux */ -- if (dcfg->method == IMX_RPROC_NONE) -+ /* Remote core is not under control of Linux or it is managed by SCU API */ -+ if (dcfg->method == IMX_RPROC_NONE || dcfg->method == IMX_RPROC_SCU_API) - return 0; - - priv->clk = devm_clk_get(dev, NULL); -diff -purNx .git BPI-Router-Linux-kernel/drivers/remoteproc/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/remoteproc/Kconfig ---- BPI-Router-Linux-kernel/drivers/remoteproc/Kconfig 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/remoteproc/Kconfig 2025-10-22 13:53:56.651168486 -0400 -@@ -214,7 +214,7 @@ config QCOM_Q6V5_MSS - handled by QCOM_Q6V5_PAS driver. - - config QCOM_Q6V5_PAS -- tristate "Qualcomm Hexagon v5 Peripheral Authentication Service support" -+ tristate "Qualcomm Peripheral Authentication Service support" - depends on OF && ARCH_QCOM - depends on QCOM_SMEM - depends on RPMSG_QCOM_SMD || RPMSG_QCOM_SMD=n -@@ -229,11 +229,10 @@ config QCOM_Q6V5_PAS - select QCOM_RPROC_COMMON - select QCOM_SCM - help -- Say y here to support the TrustZone based Peripheral Image Loader -- for the Qualcomm Hexagon v5 based remote processors. This is commonly -- used to control subsystems such as ADSP (Audio DSP), -- CDSP (Compute DSP), MPSS (Modem Peripheral SubSystem), and -- SLPI (Sensor Low Power Island). -+ Say y here to support the TrustZone based Peripheral Image Loader for -+ the Qualcomm remote processors. This is commonly used to control -+ subsystems such as ADSP (Audio DSP), CDSP (Compute DSP), MPSS (Modem -+ Peripheral SubSystem), and SLPI (Sensor Low Power Island). - - config QCOM_Q6V5_WCSS - tristate "Qualcomm Hexagon based WCSS Peripheral Image Loader" -diff -purNx .git BPI-Router-Linux-kernel/drivers/remoteproc/qcom_q6v5_pas.c BPI-Router-Linux-kernel-6.16.12/drivers/remoteproc/qcom_q6v5_pas.c ---- BPI-Router-Linux-kernel/drivers/remoteproc/qcom_q6v5_pas.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/remoteproc/qcom_q6v5_pas.c 2025-10-22 13:53:56.651168486 -0400 -@@ -1,6 +1,6 @@ - // SPDX-License-Identifier: GPL-2.0-only - /* -- * Qualcomm ADSP/SLPI Peripheral Image Loader for MSM8974 and MSM8996 -+ * Qualcomm Peripheral Authentication Service remoteproc driver - * - * Copyright (C) 2016 Linaro Ltd - * Copyright (C) 2014 Sony Mobile Communications AB -@@ -31,11 +31,11 @@ - #include "qcom_q6v5.h" - #include "remoteproc_internal.h" - --#define ADSP_DECRYPT_SHUTDOWN_DELAY_MS 100 -+#define QCOM_PAS_DECRYPT_SHUTDOWN_DELAY_MS 100 - - #define MAX_ASSIGN_COUNT 3 - --struct adsp_data { -+struct qcom_pas_data { - int crash_reason_smem; - const char *firmware_name; - const char *dtb_firmware_name; -@@ -60,7 +60,7 @@ struct adsp_data { - int region_assign_vmid; - }; - --struct qcom_adsp { -+struct qcom_pas { - struct device *dev; - struct rproc *rproc; - -@@ -119,36 +119,37 @@ struct qcom_adsp { - struct qcom_scm_pas_metadata dtb_pas_metadata; - }; - --static void adsp_segment_dump(struct rproc *rproc, struct rproc_dump_segment *segment, -- void *dest, size_t offset, size_t size) -+static void qcom_pas_segment_dump(struct rproc *rproc, -+ struct rproc_dump_segment *segment, -+ void *dest, size_t offset, size_t size) - { -- struct qcom_adsp *adsp = rproc->priv; -+ struct qcom_pas *pas = rproc->priv; - int total_offset; - -- total_offset = segment->da + segment->offset + offset - adsp->mem_phys; -- if (total_offset < 0 || total_offset + size > adsp->mem_size) { -- dev_err(adsp->dev, -+ total_offset = segment->da + segment->offset + offset - pas->mem_phys; -+ if (total_offset < 0 || total_offset + size > pas->mem_size) { -+ dev_err(pas->dev, - "invalid copy request for segment %pad with offset %zu and size %zu)\n", - &segment->da, offset, size); - memset(dest, 0xff, size); - return; - } - -- memcpy_fromio(dest, adsp->mem_region + total_offset, size); -+ memcpy_fromio(dest, pas->mem_region + total_offset, size); - } - --static void adsp_minidump(struct rproc *rproc) -+static void qcom_pas_minidump(struct rproc *rproc) - { -- struct qcom_adsp *adsp = rproc->priv; -+ struct qcom_pas *pas = rproc->priv; - - if (rproc->dump_conf == RPROC_COREDUMP_DISABLED) - return; - -- qcom_minidump(rproc, adsp->minidump_id, adsp_segment_dump); -+ qcom_minidump(rproc, pas->minidump_id, qcom_pas_segment_dump); - } - --static int adsp_pds_enable(struct qcom_adsp *adsp, struct device **pds, -- size_t pd_count) -+static int qcom_pas_pds_enable(struct qcom_pas *pas, struct device **pds, -+ size_t pd_count) - { - int ret; - int i; -@@ -174,8 +175,8 @@ unroll_pd_votes: - return ret; - }; - --static void adsp_pds_disable(struct qcom_adsp *adsp, struct device **pds, -- size_t pd_count) -+static void qcom_pas_pds_disable(struct qcom_pas *pas, struct device **pds, -+ size_t pd_count) - { - int i; - -@@ -185,65 +186,65 @@ static void adsp_pds_disable(struct qcom - } - } - --static int adsp_shutdown_poll_decrypt(struct qcom_adsp *adsp) -+static int qcom_pas_shutdown_poll_decrypt(struct qcom_pas *pas) - { - unsigned int retry_num = 50; - int ret; - - do { -- msleep(ADSP_DECRYPT_SHUTDOWN_DELAY_MS); -- ret = qcom_scm_pas_shutdown(adsp->pas_id); -+ msleep(QCOM_PAS_DECRYPT_SHUTDOWN_DELAY_MS); -+ ret = qcom_scm_pas_shutdown(pas->pas_id); - } while (ret == -EINVAL && --retry_num); - - return ret; - } - --static int adsp_unprepare(struct rproc *rproc) -+static int qcom_pas_unprepare(struct rproc *rproc) - { -- struct qcom_adsp *adsp = rproc->priv; -+ struct qcom_pas *pas = rproc->priv; - - /* -- * adsp_load() did pass pas_metadata to the SCM driver for storing -+ * qcom_pas_load() did pass pas_metadata to the SCM driver for storing - * metadata context. It might have been released already if - * auth_and_reset() was successful, but in other cases clean it up - * here. - */ -- qcom_scm_pas_metadata_release(&adsp->pas_metadata); -- if (adsp->dtb_pas_id) -- qcom_scm_pas_metadata_release(&adsp->dtb_pas_metadata); -+ qcom_scm_pas_metadata_release(&pas->pas_metadata); -+ if (pas->dtb_pas_id) -+ qcom_scm_pas_metadata_release(&pas->dtb_pas_metadata); - - return 0; - } - --static int adsp_load(struct rproc *rproc, const struct firmware *fw) -+static int qcom_pas_load(struct rproc *rproc, const struct firmware *fw) - { -- struct qcom_adsp *adsp = rproc->priv; -+ struct qcom_pas *pas = rproc->priv; - int ret; - -- /* Store firmware handle to be used in adsp_start() */ -- adsp->firmware = fw; -+ /* Store firmware handle to be used in qcom_pas_start() */ -+ pas->firmware = fw; - -- if (adsp->lite_pas_id) -- ret = qcom_scm_pas_shutdown(adsp->lite_pas_id); -+ if (pas->lite_pas_id) -+ ret = qcom_scm_pas_shutdown(pas->lite_pas_id); - -- if (adsp->dtb_pas_id) { -- ret = request_firmware(&adsp->dtb_firmware, adsp->dtb_firmware_name, adsp->dev); -+ if (pas->dtb_pas_id) { -+ ret = request_firmware(&pas->dtb_firmware, pas->dtb_firmware_name, pas->dev); - if (ret) { -- dev_err(adsp->dev, "request_firmware failed for %s: %d\n", -- adsp->dtb_firmware_name, ret); -+ dev_err(pas->dev, "request_firmware failed for %s: %d\n", -+ pas->dtb_firmware_name, ret); - return ret; - } - -- ret = qcom_mdt_pas_init(adsp->dev, adsp->dtb_firmware, adsp->dtb_firmware_name, -- adsp->dtb_pas_id, adsp->dtb_mem_phys, -- &adsp->dtb_pas_metadata); -+ ret = qcom_mdt_pas_init(pas->dev, pas->dtb_firmware, pas->dtb_firmware_name, -+ pas->dtb_pas_id, pas->dtb_mem_phys, -+ &pas->dtb_pas_metadata); - if (ret) - goto release_dtb_firmware; - -- ret = qcom_mdt_load_no_init(adsp->dev, adsp->dtb_firmware, adsp->dtb_firmware_name, -- adsp->dtb_pas_id, adsp->dtb_mem_region, -- adsp->dtb_mem_phys, adsp->dtb_mem_size, -- &adsp->dtb_mem_reloc); -+ ret = qcom_mdt_load_no_init(pas->dev, pas->dtb_firmware, pas->dtb_firmware_name, -+ pas->dtb_pas_id, pas->dtb_mem_region, -+ pas->dtb_mem_phys, pas->dtb_mem_size, -+ &pas->dtb_mem_reloc); - if (ret) - goto release_dtb_metadata; - } -@@ -251,248 +252,246 @@ static int adsp_load(struct rproc *rproc - return 0; - - release_dtb_metadata: -- qcom_scm_pas_metadata_release(&adsp->dtb_pas_metadata); -+ qcom_scm_pas_metadata_release(&pas->dtb_pas_metadata); - - release_dtb_firmware: -- release_firmware(adsp->dtb_firmware); -+ release_firmware(pas->dtb_firmware); - - return ret; - } - --static int adsp_start(struct rproc *rproc) -+static int qcom_pas_start(struct rproc *rproc) - { -- struct qcom_adsp *adsp = rproc->priv; -+ struct qcom_pas *pas = rproc->priv; - int ret; - -- ret = qcom_q6v5_prepare(&adsp->q6v5); -+ ret = qcom_q6v5_prepare(&pas->q6v5); - if (ret) - return ret; - -- ret = adsp_pds_enable(adsp, adsp->proxy_pds, adsp->proxy_pd_count); -+ ret = qcom_pas_pds_enable(pas, pas->proxy_pds, pas->proxy_pd_count); - if (ret < 0) - goto disable_irqs; - -- ret = clk_prepare_enable(adsp->xo); -+ ret = clk_prepare_enable(pas->xo); - if (ret) - goto disable_proxy_pds; - -- ret = clk_prepare_enable(adsp->aggre2_clk); -+ ret = clk_prepare_enable(pas->aggre2_clk); - if (ret) - goto disable_xo_clk; - -- if (adsp->cx_supply) { -- ret = regulator_enable(adsp->cx_supply); -+ if (pas->cx_supply) { -+ ret = regulator_enable(pas->cx_supply); - if (ret) - goto disable_aggre2_clk; - } - -- if (adsp->px_supply) { -- ret = regulator_enable(adsp->px_supply); -+ if (pas->px_supply) { -+ ret = regulator_enable(pas->px_supply); - if (ret) - goto disable_cx_supply; - } - -- if (adsp->dtb_pas_id) { -- ret = qcom_scm_pas_auth_and_reset(adsp->dtb_pas_id); -+ if (pas->dtb_pas_id) { -+ ret = qcom_scm_pas_auth_and_reset(pas->dtb_pas_id); - if (ret) { -- dev_err(adsp->dev, -+ dev_err(pas->dev, - "failed to authenticate dtb image and release reset\n"); - goto disable_px_supply; - } - } - -- ret = qcom_mdt_pas_init(adsp->dev, adsp->firmware, rproc->firmware, adsp->pas_id, -- adsp->mem_phys, &adsp->pas_metadata); -+ ret = qcom_mdt_pas_init(pas->dev, pas->firmware, rproc->firmware, pas->pas_id, -+ pas->mem_phys, &pas->pas_metadata); - if (ret) - goto disable_px_supply; - -- ret = qcom_mdt_load_no_init(adsp->dev, adsp->firmware, rproc->firmware, adsp->pas_id, -- adsp->mem_region, adsp->mem_phys, adsp->mem_size, -- &adsp->mem_reloc); -+ ret = qcom_mdt_load_no_init(pas->dev, pas->firmware, rproc->firmware, pas->pas_id, -+ pas->mem_region, pas->mem_phys, pas->mem_size, -+ &pas->mem_reloc); - if (ret) - goto release_pas_metadata; - -- qcom_pil_info_store(adsp->info_name, adsp->mem_phys, adsp->mem_size); -+ qcom_pil_info_store(pas->info_name, pas->mem_phys, pas->mem_size); - -- ret = qcom_scm_pas_auth_and_reset(adsp->pas_id); -+ ret = qcom_scm_pas_auth_and_reset(pas->pas_id); - if (ret) { -- dev_err(adsp->dev, -+ dev_err(pas->dev, - "failed to authenticate image and release reset\n"); - goto release_pas_metadata; - } - -- ret = qcom_q6v5_wait_for_start(&adsp->q6v5, msecs_to_jiffies(5000)); -+ ret = qcom_q6v5_wait_for_start(&pas->q6v5, msecs_to_jiffies(5000)); - if (ret == -ETIMEDOUT) { -- dev_err(adsp->dev, "start timed out\n"); -- qcom_scm_pas_shutdown(adsp->pas_id); -+ dev_err(pas->dev, "start timed out\n"); -+ qcom_scm_pas_shutdown(pas->pas_id); - goto release_pas_metadata; - } - -- qcom_scm_pas_metadata_release(&adsp->pas_metadata); -- if (adsp->dtb_pas_id) -- qcom_scm_pas_metadata_release(&adsp->dtb_pas_metadata); -+ qcom_scm_pas_metadata_release(&pas->pas_metadata); -+ if (pas->dtb_pas_id) -+ qcom_scm_pas_metadata_release(&pas->dtb_pas_metadata); - -- /* Remove pointer to the loaded firmware, only valid in adsp_load() & adsp_start() */ -- adsp->firmware = NULL; -+ /* firmware is used to pass reference from qcom_pas_start(), drop it now */ -+ pas->firmware = NULL; - - return 0; - - release_pas_metadata: -- qcom_scm_pas_metadata_release(&adsp->pas_metadata); -- if (adsp->dtb_pas_id) -- qcom_scm_pas_metadata_release(&adsp->dtb_pas_metadata); -+ qcom_scm_pas_metadata_release(&pas->pas_metadata); -+ if (pas->dtb_pas_id) -+ qcom_scm_pas_metadata_release(&pas->dtb_pas_metadata); - disable_px_supply: -- if (adsp->px_supply) -- regulator_disable(adsp->px_supply); -+ if (pas->px_supply) -+ regulator_disable(pas->px_supply); - disable_cx_supply: -- if (adsp->cx_supply) -- regulator_disable(adsp->cx_supply); -+ if (pas->cx_supply) -+ regulator_disable(pas->cx_supply); - disable_aggre2_clk: -- clk_disable_unprepare(adsp->aggre2_clk); -+ clk_disable_unprepare(pas->aggre2_clk); - disable_xo_clk: -- clk_disable_unprepare(adsp->xo); -+ clk_disable_unprepare(pas->xo); - disable_proxy_pds: -- adsp_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count); -+ qcom_pas_pds_disable(pas, pas->proxy_pds, pas->proxy_pd_count); - disable_irqs: -- qcom_q6v5_unprepare(&adsp->q6v5); -+ qcom_q6v5_unprepare(&pas->q6v5); - -- /* Remove pointer to the loaded firmware, only valid in adsp_load() & adsp_start() */ -- adsp->firmware = NULL; -+ /* firmware is used to pass reference from qcom_pas_start(), drop it now */ -+ pas->firmware = NULL; - - return ret; - } - - static void qcom_pas_handover(struct qcom_q6v5 *q6v5) - { -- struct qcom_adsp *adsp = container_of(q6v5, struct qcom_adsp, q6v5); -+ struct qcom_pas *pas = container_of(q6v5, struct qcom_pas, q6v5); - -- if (adsp->px_supply) -- regulator_disable(adsp->px_supply); -- if (adsp->cx_supply) -- regulator_disable(adsp->cx_supply); -- clk_disable_unprepare(adsp->aggre2_clk); -- clk_disable_unprepare(adsp->xo); -- adsp_pds_disable(adsp, adsp->proxy_pds, adsp->proxy_pd_count); -+ if (pas->px_supply) -+ regulator_disable(pas->px_supply); -+ if (pas->cx_supply) -+ regulator_disable(pas->cx_supply); -+ clk_disable_unprepare(pas->aggre2_clk); -+ clk_disable_unprepare(pas->xo); -+ qcom_pas_pds_disable(pas, pas->proxy_pds, pas->proxy_pd_count); - } - --static int adsp_stop(struct rproc *rproc) -+static int qcom_pas_stop(struct rproc *rproc) - { -- struct qcom_adsp *adsp = rproc->priv; -+ struct qcom_pas *pas = rproc->priv; - int handover; - int ret; - -- ret = qcom_q6v5_request_stop(&adsp->q6v5, adsp->sysmon); -+ ret = qcom_q6v5_request_stop(&pas->q6v5, pas->sysmon); - if (ret == -ETIMEDOUT) -- dev_err(adsp->dev, "timed out on wait\n"); -+ dev_err(pas->dev, "timed out on wait\n"); - -- ret = qcom_scm_pas_shutdown(adsp->pas_id); -- if (ret && adsp->decrypt_shutdown) -- ret = adsp_shutdown_poll_decrypt(adsp); -+ ret = qcom_scm_pas_shutdown(pas->pas_id); -+ if (ret && pas->decrypt_shutdown) -+ ret = qcom_pas_shutdown_poll_decrypt(pas); - - if (ret) -- dev_err(adsp->dev, "failed to shutdown: %d\n", ret); -+ dev_err(pas->dev, "failed to shutdown: %d\n", ret); - -- if (adsp->dtb_pas_id) { -- ret = qcom_scm_pas_shutdown(adsp->dtb_pas_id); -+ if (pas->dtb_pas_id) { -+ ret = qcom_scm_pas_shutdown(pas->dtb_pas_id); - if (ret) -- dev_err(adsp->dev, "failed to shutdown dtb: %d\n", ret); -+ dev_err(pas->dev, "failed to shutdown dtb: %d\n", ret); - } - -- handover = qcom_q6v5_unprepare(&adsp->q6v5); -+ handover = qcom_q6v5_unprepare(&pas->q6v5); - if (handover) -- qcom_pas_handover(&adsp->q6v5); -+ qcom_pas_handover(&pas->q6v5); - -- if (adsp->smem_host_id) -- ret = qcom_smem_bust_hwspin_lock_by_host(adsp->smem_host_id); -+ if (pas->smem_host_id) -+ ret = qcom_smem_bust_hwspin_lock_by_host(pas->smem_host_id); - - return ret; - } - --static void *adsp_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem) -+static void *qcom_pas_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem) - { -- struct qcom_adsp *adsp = rproc->priv; -+ struct qcom_pas *pas = rproc->priv; - int offset; - -- offset = da - adsp->mem_reloc; -- if (offset < 0 || offset + len > adsp->mem_size) -+ offset = da - pas->mem_reloc; -+ if (offset < 0 || offset + len > pas->mem_size) - return NULL; - - if (is_iomem) - *is_iomem = true; - -- return adsp->mem_region + offset; -+ return pas->mem_region + offset; - } - --static unsigned long adsp_panic(struct rproc *rproc) -+static unsigned long qcom_pas_panic(struct rproc *rproc) - { -- struct qcom_adsp *adsp = rproc->priv; -+ struct qcom_pas *pas = rproc->priv; - -- return qcom_q6v5_panic(&adsp->q6v5); -+ return qcom_q6v5_panic(&pas->q6v5); - } - --static const struct rproc_ops adsp_ops = { -- .unprepare = adsp_unprepare, -- .start = adsp_start, -- .stop = adsp_stop, -- .da_to_va = adsp_da_to_va, -+static const struct rproc_ops qcom_pas_ops = { -+ .unprepare = qcom_pas_unprepare, -+ .start = qcom_pas_start, -+ .stop = qcom_pas_stop, -+ .da_to_va = qcom_pas_da_to_va, - .parse_fw = qcom_register_dump_segments, -- .load = adsp_load, -- .panic = adsp_panic, -+ .load = qcom_pas_load, -+ .panic = qcom_pas_panic, - }; - --static const struct rproc_ops adsp_minidump_ops = { -- .unprepare = adsp_unprepare, -- .start = adsp_start, -- .stop = adsp_stop, -- .da_to_va = adsp_da_to_va, -+static const struct rproc_ops qcom_pas_minidump_ops = { -+ .unprepare = qcom_pas_unprepare, -+ .start = qcom_pas_start, -+ .stop = qcom_pas_stop, -+ .da_to_va = qcom_pas_da_to_va, - .parse_fw = qcom_register_dump_segments, -- .load = adsp_load, -- .panic = adsp_panic, -- .coredump = adsp_minidump, -+ .load = qcom_pas_load, -+ .panic = qcom_pas_panic, -+ .coredump = qcom_pas_minidump, - }; - --static int adsp_init_clock(struct qcom_adsp *adsp) -+static int qcom_pas_init_clock(struct qcom_pas *pas) - { -- adsp->xo = devm_clk_get(adsp->dev, "xo"); -- if (IS_ERR(adsp->xo)) -- return dev_err_probe(adsp->dev, PTR_ERR(adsp->xo), -+ pas->xo = devm_clk_get(pas->dev, "xo"); -+ if (IS_ERR(pas->xo)) -+ return dev_err_probe(pas->dev, PTR_ERR(pas->xo), - "failed to get xo clock"); - -- -- adsp->aggre2_clk = devm_clk_get_optional(adsp->dev, "aggre2"); -- if (IS_ERR(adsp->aggre2_clk)) -- return dev_err_probe(adsp->dev, PTR_ERR(adsp->aggre2_clk), -+ pas->aggre2_clk = devm_clk_get_optional(pas->dev, "aggre2"); -+ if (IS_ERR(pas->aggre2_clk)) -+ return dev_err_probe(pas->dev, PTR_ERR(pas->aggre2_clk), - "failed to get aggre2 clock"); - - return 0; - } - --static int adsp_init_regulator(struct qcom_adsp *adsp) -+static int qcom_pas_init_regulator(struct qcom_pas *pas) - { -- adsp->cx_supply = devm_regulator_get_optional(adsp->dev, "cx"); -- if (IS_ERR(adsp->cx_supply)) { -- if (PTR_ERR(adsp->cx_supply) == -ENODEV) -- adsp->cx_supply = NULL; -+ pas->cx_supply = devm_regulator_get_optional(pas->dev, "cx"); -+ if (IS_ERR(pas->cx_supply)) { -+ if (PTR_ERR(pas->cx_supply) == -ENODEV) -+ pas->cx_supply = NULL; - else -- return PTR_ERR(adsp->cx_supply); -+ return PTR_ERR(pas->cx_supply); - } - -- if (adsp->cx_supply) -- regulator_set_load(adsp->cx_supply, 100000); -+ if (pas->cx_supply) -+ regulator_set_load(pas->cx_supply, 100000); - -- adsp->px_supply = devm_regulator_get_optional(adsp->dev, "px"); -- if (IS_ERR(adsp->px_supply)) { -- if (PTR_ERR(adsp->px_supply) == -ENODEV) -- adsp->px_supply = NULL; -+ pas->px_supply = devm_regulator_get_optional(pas->dev, "px"); -+ if (IS_ERR(pas->px_supply)) { -+ if (PTR_ERR(pas->px_supply) == -ENODEV) -+ pas->px_supply = NULL; - else -- return PTR_ERR(adsp->px_supply); -+ return PTR_ERR(pas->px_supply); - } - - return 0; - } - --static int adsp_pds_attach(struct device *dev, struct device **devs, -- char **pd_names) -+static int qcom_pas_pds_attach(struct device *dev, struct device **devs, char **pd_names) - { - size_t num_pds = 0; - int ret; -@@ -528,10 +527,9 @@ unroll_attach: - return ret; - }; - --static void adsp_pds_detach(struct qcom_adsp *adsp, struct device **pds, -- size_t pd_count) -+static void qcom_pas_pds_detach(struct qcom_pas *pas, struct device **pds, size_t pd_count) - { -- struct device *dev = adsp->dev; -+ struct device *dev = pas->dev; - int i; - - /* Handle single power domain */ -@@ -544,62 +542,62 @@ static void adsp_pds_detach(struct qcom_ - dev_pm_domain_detach(pds[i], false); - } - --static int adsp_alloc_memory_region(struct qcom_adsp *adsp) -+static int qcom_pas_alloc_memory_region(struct qcom_pas *pas) - { - struct reserved_mem *rmem; - struct device_node *node; - -- node = of_parse_phandle(adsp->dev->of_node, "memory-region", 0); -+ node = of_parse_phandle(pas->dev->of_node, "memory-region", 0); - if (!node) { -- dev_err(adsp->dev, "no memory-region specified\n"); -+ dev_err(pas->dev, "no memory-region specified\n"); - return -EINVAL; - } - - rmem = of_reserved_mem_lookup(node); - of_node_put(node); - if (!rmem) { -- dev_err(adsp->dev, "unable to resolve memory-region\n"); -+ dev_err(pas->dev, "unable to resolve memory-region\n"); - return -EINVAL; - } - -- adsp->mem_phys = adsp->mem_reloc = rmem->base; -- adsp->mem_size = rmem->size; -- adsp->mem_region = devm_ioremap_wc(adsp->dev, adsp->mem_phys, adsp->mem_size); -- if (!adsp->mem_region) { -- dev_err(adsp->dev, "unable to map memory region: %pa+%zx\n", -- &rmem->base, adsp->mem_size); -+ pas->mem_phys = pas->mem_reloc = rmem->base; -+ pas->mem_size = rmem->size; -+ pas->mem_region = devm_ioremap_wc(pas->dev, pas->mem_phys, pas->mem_size); -+ if (!pas->mem_region) { -+ dev_err(pas->dev, "unable to map memory region: %pa+%zx\n", -+ &rmem->base, pas->mem_size); - return -EBUSY; - } - -- if (!adsp->dtb_pas_id) -+ if (!pas->dtb_pas_id) - return 0; - -- node = of_parse_phandle(adsp->dev->of_node, "memory-region", 1); -+ node = of_parse_phandle(pas->dev->of_node, "memory-region", 1); - if (!node) { -- dev_err(adsp->dev, "no dtb memory-region specified\n"); -+ dev_err(pas->dev, "no dtb memory-region specified\n"); - return -EINVAL; - } - - rmem = of_reserved_mem_lookup(node); - of_node_put(node); - if (!rmem) { -- dev_err(adsp->dev, "unable to resolve dtb memory-region\n"); -+ dev_err(pas->dev, "unable to resolve dtb memory-region\n"); - return -EINVAL; - } - -- adsp->dtb_mem_phys = adsp->dtb_mem_reloc = rmem->base; -- adsp->dtb_mem_size = rmem->size; -- adsp->dtb_mem_region = devm_ioremap_wc(adsp->dev, adsp->dtb_mem_phys, adsp->dtb_mem_size); -- if (!adsp->dtb_mem_region) { -- dev_err(adsp->dev, "unable to map dtb memory region: %pa+%zx\n", -- &rmem->base, adsp->dtb_mem_size); -+ pas->dtb_mem_phys = pas->dtb_mem_reloc = rmem->base; -+ pas->dtb_mem_size = rmem->size; -+ pas->dtb_mem_region = devm_ioremap_wc(pas->dev, pas->dtb_mem_phys, pas->dtb_mem_size); -+ if (!pas->dtb_mem_region) { -+ dev_err(pas->dev, "unable to map dtb memory region: %pa+%zx\n", -+ &rmem->base, pas->dtb_mem_size); - return -EBUSY; - } - - return 0; - } - --static int adsp_assign_memory_region(struct qcom_adsp *adsp) -+static int qcom_pas_assign_memory_region(struct qcom_pas *pas) - { - struct qcom_scm_vmperm perm[MAX_ASSIGN_COUNT]; - struct device_node *node; -@@ -607,45 +605,45 @@ static int adsp_assign_memory_region(str - int offset; - int ret; - -- if (!adsp->region_assign_idx) -+ if (!pas->region_assign_idx) - return 0; - -- for (offset = 0; offset < adsp->region_assign_count; ++offset) { -+ for (offset = 0; offset < pas->region_assign_count; ++offset) { - struct reserved_mem *rmem = NULL; - -- node = of_parse_phandle(adsp->dev->of_node, "memory-region", -- adsp->region_assign_idx + offset); -+ node = of_parse_phandle(pas->dev->of_node, "memory-region", -+ pas->region_assign_idx + offset); - if (node) - rmem = of_reserved_mem_lookup(node); - of_node_put(node); - if (!rmem) { -- dev_err(adsp->dev, "unable to resolve shareable memory-region index %d\n", -+ dev_err(pas->dev, "unable to resolve shareable memory-region index %d\n", - offset); - return -EINVAL; - } - -- if (adsp->region_assign_shared) { -+ if (pas->region_assign_shared) { - perm[0].vmid = QCOM_SCM_VMID_HLOS; - perm[0].perm = QCOM_SCM_PERM_RW; -- perm[1].vmid = adsp->region_assign_vmid; -+ perm[1].vmid = pas->region_assign_vmid; - perm[1].perm = QCOM_SCM_PERM_RW; - perm_size = 2; - } else { -- perm[0].vmid = adsp->region_assign_vmid; -+ perm[0].vmid = pas->region_assign_vmid; - perm[0].perm = QCOM_SCM_PERM_RW; - perm_size = 1; - } - -- adsp->region_assign_phys[offset] = rmem->base; -- adsp->region_assign_size[offset] = rmem->size; -- adsp->region_assign_owners[offset] = BIT(QCOM_SCM_VMID_HLOS); -- -- ret = qcom_scm_assign_mem(adsp->region_assign_phys[offset], -- adsp->region_assign_size[offset], -- &adsp->region_assign_owners[offset], -+ pas->region_assign_phys[offset] = rmem->base; -+ pas->region_assign_size[offset] = rmem->size; -+ pas->region_assign_owners[offset] = BIT(QCOM_SCM_VMID_HLOS); -+ -+ ret = qcom_scm_assign_mem(pas->region_assign_phys[offset], -+ pas->region_assign_size[offset], -+ &pas->region_assign_owners[offset], - perm, perm_size); - if (ret < 0) { -- dev_err(adsp->dev, "assign memory %d failed\n", offset); -+ dev_err(pas->dev, "assign memory %d failed\n", offset); - return ret; - } - } -@@ -653,35 +651,35 @@ static int adsp_assign_memory_region(str - return 0; - } - --static void adsp_unassign_memory_region(struct qcom_adsp *adsp) -+static void qcom_pas_unassign_memory_region(struct qcom_pas *pas) - { - struct qcom_scm_vmperm perm; - int offset; - int ret; - -- if (!adsp->region_assign_idx || adsp->region_assign_shared) -+ if (!pas->region_assign_idx || pas->region_assign_shared) - return; - -- for (offset = 0; offset < adsp->region_assign_count; ++offset) { -+ for (offset = 0; offset < pas->region_assign_count; ++offset) { - perm.vmid = QCOM_SCM_VMID_HLOS; - perm.perm = QCOM_SCM_PERM_RW; - -- ret = qcom_scm_assign_mem(adsp->region_assign_phys[offset], -- adsp->region_assign_size[offset], -- &adsp->region_assign_owners[offset], -+ ret = qcom_scm_assign_mem(pas->region_assign_phys[offset], -+ pas->region_assign_size[offset], -+ &pas->region_assign_owners[offset], - &perm, 1); - if (ret < 0) -- dev_err(adsp->dev, "unassign memory %d failed\n", offset); -+ dev_err(pas->dev, "unassign memory %d failed\n", offset); - } - } - --static int adsp_probe(struct platform_device *pdev) -+static int qcom_pas_probe(struct platform_device *pdev) - { -- const struct adsp_data *desc; -- struct qcom_adsp *adsp; -+ const struct qcom_pas_data *desc; -+ struct qcom_pas *pas; - struct rproc *rproc; - const char *fw_name, *dtb_fw_name = NULL; -- const struct rproc_ops *ops = &adsp_ops; -+ const struct rproc_ops *ops = &qcom_pas_ops; - int ret; - - desc = of_device_get_match_data(&pdev->dev); -@@ -706,9 +704,9 @@ static int adsp_probe(struct platform_de - } - - if (desc->minidump_id) -- ops = &adsp_minidump_ops; -+ ops = &qcom_pas_minidump_ops; - -- rproc = devm_rproc_alloc(&pdev->dev, desc->sysmon_name, ops, fw_name, sizeof(*adsp)); -+ rproc = devm_rproc_alloc(&pdev->dev, desc->sysmon_name, ops, fw_name, sizeof(*pas)); - - if (!rproc) { - dev_err(&pdev->dev, "unable to allocate remoteproc\n"); -@@ -718,68 +716,65 @@ static int adsp_probe(struct platform_de - rproc->auto_boot = desc->auto_boot; - rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE); - -- adsp = rproc->priv; -- adsp->dev = &pdev->dev; -- adsp->rproc = rproc; -- adsp->minidump_id = desc->minidump_id; -- adsp->pas_id = desc->pas_id; -- adsp->lite_pas_id = desc->lite_pas_id; -- adsp->info_name = desc->sysmon_name; -- adsp->smem_host_id = desc->smem_host_id; -- adsp->decrypt_shutdown = desc->decrypt_shutdown; -- adsp->region_assign_idx = desc->region_assign_idx; -- adsp->region_assign_count = min_t(int, MAX_ASSIGN_COUNT, desc->region_assign_count); -- adsp->region_assign_vmid = desc->region_assign_vmid; -- adsp->region_assign_shared = desc->region_assign_shared; -+ pas = rproc->priv; -+ pas->dev = &pdev->dev; -+ pas->rproc = rproc; -+ pas->minidump_id = desc->minidump_id; -+ pas->pas_id = desc->pas_id; -+ pas->lite_pas_id = desc->lite_pas_id; -+ pas->info_name = desc->sysmon_name; -+ pas->smem_host_id = desc->smem_host_id; -+ pas->decrypt_shutdown = desc->decrypt_shutdown; -+ pas->region_assign_idx = desc->region_assign_idx; -+ pas->region_assign_count = min_t(int, MAX_ASSIGN_COUNT, desc->region_assign_count); -+ pas->region_assign_vmid = desc->region_assign_vmid; -+ pas->region_assign_shared = desc->region_assign_shared; - if (dtb_fw_name) { -- adsp->dtb_firmware_name = dtb_fw_name; -- adsp->dtb_pas_id = desc->dtb_pas_id; -+ pas->dtb_firmware_name = dtb_fw_name; -+ pas->dtb_pas_id = desc->dtb_pas_id; - } -- platform_set_drvdata(pdev, adsp); -+ platform_set_drvdata(pdev, pas); - -- ret = device_init_wakeup(adsp->dev, true); -+ ret = device_init_wakeup(pas->dev, true); - if (ret) - goto free_rproc; - -- ret = adsp_alloc_memory_region(adsp); -+ ret = qcom_pas_alloc_memory_region(pas); - if (ret) - goto free_rproc; - -- ret = adsp_assign_memory_region(adsp); -+ ret = qcom_pas_assign_memory_region(pas); - if (ret) - goto free_rproc; - -- ret = adsp_init_clock(adsp); -+ ret = qcom_pas_init_clock(pas); - if (ret) - goto unassign_mem; - -- ret = adsp_init_regulator(adsp); -+ ret = qcom_pas_init_regulator(pas); - if (ret) - goto unassign_mem; - -- ret = adsp_pds_attach(&pdev->dev, adsp->proxy_pds, -- desc->proxy_pd_names); -+ ret = qcom_pas_pds_attach(&pdev->dev, pas->proxy_pds, desc->proxy_pd_names); - if (ret < 0) - goto unassign_mem; -- adsp->proxy_pd_count = ret; -+ pas->proxy_pd_count = ret; - -- ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem, desc->load_state, -- qcom_pas_handover); -+ ret = qcom_q6v5_init(&pas->q6v5, pdev, rproc, desc->crash_reason_smem, -+ desc->load_state, qcom_pas_handover); - if (ret) - goto detach_proxy_pds; - -- qcom_add_glink_subdev(rproc, &adsp->glink_subdev, desc->ssr_name); -- qcom_add_smd_subdev(rproc, &adsp->smd_subdev); -- qcom_add_pdm_subdev(rproc, &adsp->pdm_subdev); -- adsp->sysmon = qcom_add_sysmon_subdev(rproc, -- desc->sysmon_name, -- desc->ssctl_id); -- if (IS_ERR(adsp->sysmon)) { -- ret = PTR_ERR(adsp->sysmon); -+ qcom_add_glink_subdev(rproc, &pas->glink_subdev, desc->ssr_name); -+ qcom_add_smd_subdev(rproc, &pas->smd_subdev); -+ qcom_add_pdm_subdev(rproc, &pas->pdm_subdev); -+ pas->sysmon = qcom_add_sysmon_subdev(rproc, desc->sysmon_name, desc->ssctl_id); -+ if (IS_ERR(pas->sysmon)) { -+ ret = PTR_ERR(pas->sysmon); - goto deinit_remove_pdm_smd_glink; - } - -- qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name); -+ qcom_add_ssr_subdev(rproc, &pas->ssr_subdev, desc->ssr_name); - ret = rproc_add(rproc); - if (ret) - goto remove_ssr_sysmon; -@@ -787,41 +782,41 @@ static int adsp_probe(struct platform_de - return 0; - - remove_ssr_sysmon: -- qcom_remove_ssr_subdev(rproc, &adsp->ssr_subdev); -- qcom_remove_sysmon_subdev(adsp->sysmon); -+ qcom_remove_ssr_subdev(rproc, &pas->ssr_subdev); -+ qcom_remove_sysmon_subdev(pas->sysmon); - deinit_remove_pdm_smd_glink: -- qcom_remove_pdm_subdev(rproc, &adsp->pdm_subdev); -- qcom_remove_smd_subdev(rproc, &adsp->smd_subdev); -- qcom_remove_glink_subdev(rproc, &adsp->glink_subdev); -- qcom_q6v5_deinit(&adsp->q6v5); -+ qcom_remove_pdm_subdev(rproc, &pas->pdm_subdev); -+ qcom_remove_smd_subdev(rproc, &pas->smd_subdev); -+ qcom_remove_glink_subdev(rproc, &pas->glink_subdev); -+ qcom_q6v5_deinit(&pas->q6v5); - detach_proxy_pds: -- adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count); -+ qcom_pas_pds_detach(pas, pas->proxy_pds, pas->proxy_pd_count); - unassign_mem: -- adsp_unassign_memory_region(adsp); -+ qcom_pas_unassign_memory_region(pas); - free_rproc: -- device_init_wakeup(adsp->dev, false); -+ device_init_wakeup(pas->dev, false); - - return ret; - } - --static void adsp_remove(struct platform_device *pdev) -+static void qcom_pas_remove(struct platform_device *pdev) - { -- struct qcom_adsp *adsp = platform_get_drvdata(pdev); -+ struct qcom_pas *pas = platform_get_drvdata(pdev); - -- rproc_del(adsp->rproc); -+ rproc_del(pas->rproc); - -- qcom_q6v5_deinit(&adsp->q6v5); -- adsp_unassign_memory_region(adsp); -- qcom_remove_glink_subdev(adsp->rproc, &adsp->glink_subdev); -- qcom_remove_sysmon_subdev(adsp->sysmon); -- qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev); -- qcom_remove_pdm_subdev(adsp->rproc, &adsp->pdm_subdev); -- qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev); -- adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count); -- device_init_wakeup(adsp->dev, false); -+ qcom_q6v5_deinit(&pas->q6v5); -+ qcom_pas_unassign_memory_region(pas); -+ qcom_remove_glink_subdev(pas->rproc, &pas->glink_subdev); -+ qcom_remove_sysmon_subdev(pas->sysmon); -+ qcom_remove_smd_subdev(pas->rproc, &pas->smd_subdev); -+ qcom_remove_pdm_subdev(pas->rproc, &pas->pdm_subdev); -+ qcom_remove_ssr_subdev(pas->rproc, &pas->ssr_subdev); -+ qcom_pas_pds_detach(pas, pas->proxy_pds, pas->proxy_pd_count); -+ device_init_wakeup(pas->dev, false); - } - --static const struct adsp_data adsp_resource_init = { -+static const struct qcom_pas_data adsp_resource_init = { - .crash_reason_smem = 423, - .firmware_name = "adsp.mdt", - .pas_id = 1, -@@ -831,7 +826,7 @@ static const struct adsp_data adsp_resou - .ssctl_id = 0x14, - }; - --static const struct adsp_data sa8775p_adsp_resource = { -+static const struct qcom_pas_data sa8775p_adsp_resource = { - .crash_reason_smem = 423, - .firmware_name = "adsp.mbn", - .pas_id = 1, -@@ -848,7 +843,7 @@ static const struct adsp_data sa8775p_ad - .ssctl_id = 0x14, - }; - --static const struct adsp_data sdm845_adsp_resource_init = { -+static const struct qcom_pas_data sdm845_adsp_resource_init = { - .crash_reason_smem = 423, - .firmware_name = "adsp.mdt", - .pas_id = 1, -@@ -859,7 +854,7 @@ static const struct adsp_data sdm845_ads - .ssctl_id = 0x14, - }; - --static const struct adsp_data sm6350_adsp_resource = { -+static const struct qcom_pas_data sm6350_adsp_resource = { - .crash_reason_smem = 423, - .firmware_name = "adsp.mdt", - .pas_id = 1, -@@ -875,7 +870,7 @@ static const struct adsp_data sm6350_ads - .ssctl_id = 0x14, - }; - --static const struct adsp_data sm6375_mpss_resource = { -+static const struct qcom_pas_data sm6375_mpss_resource = { - .crash_reason_smem = 421, - .firmware_name = "modem.mdt", - .pas_id = 4, -@@ -890,7 +885,7 @@ static const struct adsp_data sm6375_mps - .ssctl_id = 0x12, - }; - --static const struct adsp_data sm8150_adsp_resource = { -+static const struct qcom_pas_data sm8150_adsp_resource = { - .crash_reason_smem = 423, - .firmware_name = "adsp.mdt", - .pas_id = 1, -@@ -905,7 +900,7 @@ static const struct adsp_data sm8150_ads - .ssctl_id = 0x14, - }; - --static const struct adsp_data sm8250_adsp_resource = { -+static const struct qcom_pas_data sm8250_adsp_resource = { - .crash_reason_smem = 423, - .firmware_name = "adsp.mdt", - .pas_id = 1, -@@ -922,7 +917,7 @@ static const struct adsp_data sm8250_ads - .ssctl_id = 0x14, - }; - --static const struct adsp_data sm8350_adsp_resource = { -+static const struct qcom_pas_data sm8350_adsp_resource = { - .crash_reason_smem = 423, - .firmware_name = "adsp.mdt", - .pas_id = 1, -@@ -938,7 +933,7 @@ static const struct adsp_data sm8350_ads - .ssctl_id = 0x14, - }; - --static const struct adsp_data msm8996_adsp_resource = { -+static const struct qcom_pas_data msm8996_adsp_resource = { - .crash_reason_smem = 423, - .firmware_name = "adsp.mdt", - .pas_id = 1, -@@ -952,7 +947,7 @@ static const struct adsp_data msm8996_ad - .ssctl_id = 0x14, - }; - --static const struct adsp_data cdsp_resource_init = { -+static const struct qcom_pas_data cdsp_resource_init = { - .crash_reason_smem = 601, - .firmware_name = "cdsp.mdt", - .pas_id = 18, -@@ -962,7 +957,7 @@ static const struct adsp_data cdsp_resou - .ssctl_id = 0x17, - }; - --static const struct adsp_data sa8775p_cdsp0_resource = { -+static const struct qcom_pas_data sa8775p_cdsp0_resource = { - .crash_reason_smem = 601, - .firmware_name = "cdsp0.mbn", - .pas_id = 18, -@@ -980,7 +975,7 @@ static const struct adsp_data sa8775p_cd - .ssctl_id = 0x17, - }; - --static const struct adsp_data sa8775p_cdsp1_resource = { -+static const struct qcom_pas_data sa8775p_cdsp1_resource = { - .crash_reason_smem = 633, - .firmware_name = "cdsp1.mbn", - .pas_id = 30, -@@ -998,7 +993,7 @@ static const struct adsp_data sa8775p_cd - .ssctl_id = 0x20, - }; - --static const struct adsp_data sdm845_cdsp_resource_init = { -+static const struct qcom_pas_data sdm845_cdsp_resource_init = { - .crash_reason_smem = 601, - .firmware_name = "cdsp.mdt", - .pas_id = 18, -@@ -1009,7 +1004,7 @@ static const struct adsp_data sdm845_cds - .ssctl_id = 0x17, - }; - --static const struct adsp_data sm6350_cdsp_resource = { -+static const struct qcom_pas_data sm6350_cdsp_resource = { - .crash_reason_smem = 601, - .firmware_name = "cdsp.mdt", - .pas_id = 18, -@@ -1025,7 +1020,7 @@ static const struct adsp_data sm6350_cds - .ssctl_id = 0x17, - }; - --static const struct adsp_data sm8150_cdsp_resource = { -+static const struct qcom_pas_data sm8150_cdsp_resource = { - .crash_reason_smem = 601, - .firmware_name = "cdsp.mdt", - .pas_id = 18, -@@ -1040,7 +1035,7 @@ static const struct adsp_data sm8150_cds - .ssctl_id = 0x17, - }; - --static const struct adsp_data sm8250_cdsp_resource = { -+static const struct qcom_pas_data sm8250_cdsp_resource = { - .crash_reason_smem = 601, - .firmware_name = "cdsp.mdt", - .pas_id = 18, -@@ -1055,7 +1050,7 @@ static const struct adsp_data sm8250_cds - .ssctl_id = 0x17, - }; - --static const struct adsp_data sc8280xp_nsp0_resource = { -+static const struct qcom_pas_data sc8280xp_nsp0_resource = { - .crash_reason_smem = 601, - .firmware_name = "cdsp.mdt", - .pas_id = 18, -@@ -1069,7 +1064,7 @@ static const struct adsp_data sc8280xp_n - .ssctl_id = 0x17, - }; - --static const struct adsp_data sc8280xp_nsp1_resource = { -+static const struct qcom_pas_data sc8280xp_nsp1_resource = { - .crash_reason_smem = 633, - .firmware_name = "cdsp.mdt", - .pas_id = 30, -@@ -1083,7 +1078,7 @@ static const struct adsp_data sc8280xp_n - .ssctl_id = 0x20, - }; - --static const struct adsp_data x1e80100_adsp_resource = { -+static const struct qcom_pas_data x1e80100_adsp_resource = { - .crash_reason_smem = 423, - .firmware_name = "adsp.mdt", - .dtb_firmware_name = "adsp_dtb.mdt", -@@ -1103,7 +1098,7 @@ static const struct adsp_data x1e80100_a - .ssctl_id = 0x14, - }; - --static const struct adsp_data x1e80100_cdsp_resource = { -+static const struct qcom_pas_data x1e80100_cdsp_resource = { - .crash_reason_smem = 601, - .firmware_name = "cdsp.mdt", - .dtb_firmware_name = "cdsp_dtb.mdt", -@@ -1123,7 +1118,7 @@ static const struct adsp_data x1e80100_c - .ssctl_id = 0x17, - }; - --static const struct adsp_data sm8350_cdsp_resource = { -+static const struct qcom_pas_data sm8350_cdsp_resource = { - .crash_reason_smem = 601, - .firmware_name = "cdsp.mdt", - .pas_id = 18, -@@ -1140,7 +1135,7 @@ static const struct adsp_data sm8350_cds - .ssctl_id = 0x17, - }; - --static const struct adsp_data sa8775p_gpdsp0_resource = { -+static const struct qcom_pas_data sa8775p_gpdsp0_resource = { - .crash_reason_smem = 640, - .firmware_name = "gpdsp0.mbn", - .pas_id = 39, -@@ -1157,7 +1152,7 @@ static const struct adsp_data sa8775p_gp - .ssctl_id = 0x21, - }; - --static const struct adsp_data sa8775p_gpdsp1_resource = { -+static const struct qcom_pas_data sa8775p_gpdsp1_resource = { - .crash_reason_smem = 641, - .firmware_name = "gpdsp1.mbn", - .pas_id = 40, -@@ -1174,7 +1169,7 @@ static const struct adsp_data sa8775p_gp - .ssctl_id = 0x22, - }; - --static const struct adsp_data mpss_resource_init = { -+static const struct qcom_pas_data mpss_resource_init = { - .crash_reason_smem = 421, - .firmware_name = "modem.mdt", - .pas_id = 4, -@@ -1191,7 +1186,7 @@ static const struct adsp_data mpss_resou - .ssctl_id = 0x12, - }; - --static const struct adsp_data sc8180x_mpss_resource = { -+static const struct qcom_pas_data sc8180x_mpss_resource = { - .crash_reason_smem = 421, - .firmware_name = "modem.mdt", - .pas_id = 4, -@@ -1206,7 +1201,7 @@ static const struct adsp_data sc8180x_mp - .ssctl_id = 0x12, - }; - --static const struct adsp_data msm8996_slpi_resource_init = { -+static const struct qcom_pas_data msm8996_slpi_resource_init = { - .crash_reason_smem = 424, - .firmware_name = "slpi.mdt", - .pas_id = 12, -@@ -1220,7 +1215,7 @@ static const struct adsp_data msm8996_sl - .ssctl_id = 0x16, - }; - --static const struct adsp_data sdm845_slpi_resource_init = { -+static const struct qcom_pas_data sdm845_slpi_resource_init = { - .crash_reason_smem = 424, - .firmware_name = "slpi.mdt", - .pas_id = 12, -@@ -1236,7 +1231,7 @@ static const struct adsp_data sdm845_slp - .ssctl_id = 0x16, - }; - --static const struct adsp_data wcss_resource_init = { -+static const struct qcom_pas_data wcss_resource_init = { - .crash_reason_smem = 421, - .firmware_name = "wcnss.mdt", - .pas_id = 6, -@@ -1246,7 +1241,7 @@ static const struct adsp_data wcss_resou - .ssctl_id = 0x12, - }; - --static const struct adsp_data sdx55_mpss_resource = { -+static const struct qcom_pas_data sdx55_mpss_resource = { - .crash_reason_smem = 421, - .firmware_name = "modem.mdt", - .pas_id = 4, -@@ -1261,7 +1256,7 @@ static const struct adsp_data sdx55_mpss - .ssctl_id = 0x22, - }; - --static const struct adsp_data sm8450_mpss_resource = { -+static const struct qcom_pas_data sm8450_mpss_resource = { - .crash_reason_smem = 421, - .firmware_name = "modem.mdt", - .pas_id = 4, -@@ -1279,7 +1274,7 @@ static const struct adsp_data sm8450_mps - .ssctl_id = 0x12, - }; - --static const struct adsp_data sm8550_adsp_resource = { -+static const struct qcom_pas_data sm8550_adsp_resource = { - .crash_reason_smem = 423, - .firmware_name = "adsp.mdt", - .dtb_firmware_name = "adsp_dtb.mdt", -@@ -1299,7 +1294,7 @@ static const struct adsp_data sm8550_ads - .smem_host_id = 2, - }; - --static const struct adsp_data sm8550_cdsp_resource = { -+static const struct qcom_pas_data sm8550_cdsp_resource = { - .crash_reason_smem = 601, - .firmware_name = "cdsp.mdt", - .dtb_firmware_name = "cdsp_dtb.mdt", -@@ -1320,7 +1315,7 @@ static const struct adsp_data sm8550_cds - .smem_host_id = 5, - }; - --static const struct adsp_data sm8550_mpss_resource = { -+static const struct qcom_pas_data sm8550_mpss_resource = { - .crash_reason_smem = 421, - .firmware_name = "modem.mdt", - .dtb_firmware_name = "modem_dtb.mdt", -@@ -1344,7 +1339,7 @@ static const struct adsp_data sm8550_mps - .region_assign_vmid = QCOM_SCM_VMID_MSS_MSA, - }; - --static const struct adsp_data sc7280_wpss_resource = { -+static const struct qcom_pas_data sc7280_wpss_resource = { - .crash_reason_smem = 626, - .firmware_name = "wpss.mdt", - .pas_id = 6, -@@ -1361,7 +1356,7 @@ static const struct adsp_data sc7280_wps - .ssctl_id = 0x19, - }; - --static const struct adsp_data sm8650_cdsp_resource = { -+static const struct qcom_pas_data sm8650_cdsp_resource = { - .crash_reason_smem = 601, - .firmware_name = "cdsp.mdt", - .dtb_firmware_name = "cdsp_dtb.mdt", -@@ -1386,7 +1381,7 @@ static const struct adsp_data sm8650_cds - .region_assign_vmid = QCOM_SCM_VMID_CDSP, - }; - --static const struct adsp_data sm8650_mpss_resource = { -+static const struct qcom_pas_data sm8650_mpss_resource = { - .crash_reason_smem = 421, - .firmware_name = "modem.mdt", - .dtb_firmware_name = "modem_dtb.mdt", -@@ -1410,7 +1405,7 @@ static const struct adsp_data sm8650_mps - .region_assign_vmid = QCOM_SCM_VMID_MSS_MSA, - }; - --static const struct adsp_data sm8750_mpss_resource = { -+static const struct qcom_pas_data sm8750_mpss_resource = { - .crash_reason_smem = 421, - .firmware_name = "modem.mdt", - .dtb_firmware_name = "modem_dtb.mdt", -@@ -1434,7 +1429,7 @@ static const struct adsp_data sm8750_mps - .region_assign_vmid = QCOM_SCM_VMID_MSS_MSA, - }; - --static const struct of_device_id adsp_of_match[] = { -+static const struct of_device_id qcom_pas_of_match[] = { - { .compatible = "qcom,msm8226-adsp-pil", .data = &msm8996_adsp_resource}, - { .compatible = "qcom,msm8953-adsp-pil", .data = &msm8996_adsp_resource}, - { .compatible = "qcom,msm8974-adsp-pil", .data = &adsp_resource_init}, -@@ -1504,17 +1499,17 @@ static const struct of_device_id adsp_of - { .compatible = "qcom,x1e80100-cdsp-pas", .data = &x1e80100_cdsp_resource}, - { }, - }; --MODULE_DEVICE_TABLE(of, adsp_of_match); -+MODULE_DEVICE_TABLE(of, qcom_pas_of_match); - --static struct platform_driver adsp_driver = { -- .probe = adsp_probe, -- .remove = adsp_remove, -+static struct platform_driver qcom_pas_driver = { -+ .probe = qcom_pas_probe, -+ .remove = qcom_pas_remove, - .driver = { - .name = "qcom_q6v5_pas", -- .of_match_table = adsp_of_match, -+ .of_match_table = qcom_pas_of_match, - }, - }; - --module_platform_driver(adsp_driver); --MODULE_DESCRIPTION("Qualcomm Hexagon v5 Peripheral Authentication Service driver"); -+module_platform_driver(qcom_pas_driver); -+MODULE_DESCRIPTION("Qualcomm Peripheral Authentication Service remoteproc driver"); - MODULE_LICENSE("GPL v2"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/remoteproc/xlnx_r5_remoteproc.c BPI-Router-Linux-kernel-6.16.12/drivers/remoteproc/xlnx_r5_remoteproc.c ---- BPI-Router-Linux-kernel/drivers/remoteproc/xlnx_r5_remoteproc.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/remoteproc/xlnx_r5_remoteproc.c 2025-10-22 13:53:56.651168486 -0400 -@@ -938,6 +938,8 @@ static struct zynqmp_r5_core *zynqmp_r5_ - - rproc_coredump_set_elf_info(r5_rproc, ELFCLASS32, EM_ARM); - -+ r5_rproc->recovery_disabled = true; -+ r5_rproc->has_iommu = false; - r5_rproc->auto_boot = false; - r5_core = r5_rproc->priv; - r5_core->dev = cdev; -diff -purNx .git BPI-Router-Linux-kernel/drivers/reset/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/reset/Kconfig ---- BPI-Router-Linux-kernel/drivers/reset/Kconfig 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/reset/Kconfig 2025-10-22 13:53:56.651168486 -0400 -@@ -51,8 +51,8 @@ config RESET_BERLIN - - config RESET_BRCMSTB - tristate "Broadcom STB reset controller" -- depends on ARCH_BRCMSTB || COMPILE_TEST -- default ARCH_BRCMSTB -+ depends on ARCH_BRCMSTB || ARCH_BCM2835 || COMPILE_TEST -+ default ARCH_BRCMSTB || ARCH_BCM2835 - help - This enables the reset controller driver for Broadcom STB SoCs using - a SUN_TOP_CTRL_SW_INIT style controller. -@@ -60,11 +60,11 @@ config RESET_BRCMSTB - config RESET_BRCMSTB_RESCAL - tristate "Broadcom STB RESCAL reset controller" - depends on HAS_IOMEM -- depends on ARCH_BRCMSTB || COMPILE_TEST -- default ARCH_BRCMSTB -+ depends on ARCH_BRCMSTB || ARCH_BCM2835 || COMPILE_TEST -+ default ARCH_BRCMSTB || ARCH_BCM2835 - help - This enables the RESCAL reset controller for SATA, PCIe0, or PCIe1 on -- BCM7216. -+ BCM7216 or the BCM2712. - - config RESET_EYEQ - bool "Mobileye EyeQ reset controller" -diff -purNx .git BPI-Router-Linux-kernel/drivers/rtc/rtc-cmos.c BPI-Router-Linux-kernel-6.16.12/drivers/rtc/rtc-cmos.c ---- BPI-Router-Linux-kernel/drivers/rtc/rtc-cmos.c 2025-10-22 13:53:23.439328053 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/rtc/rtc-cmos.c 2025-10-22 13:53:56.651168486 -0400 -@@ -692,8 +692,12 @@ static irqreturn_t cmos_interrupt(int ir - { - u8 irqstat; - u8 rtc_control; -+ unsigned long flags; - -- spin_lock(&rtc_lock); -+ /* We cannot use spin_lock() here, as cmos_interrupt() is also called -+ * in a non-irq context. -+ */ -+ spin_lock_irqsave(&rtc_lock, flags); - - /* When the HPET interrupt handler calls us, the interrupt - * status is passed as arg1 instead of the irq number. But -@@ -727,7 +731,7 @@ static irqreturn_t cmos_interrupt(int ir - hpet_mask_rtc_irq_bit(RTC_AIE); - CMOS_READ(RTC_INTR_FLAGS); - } -- spin_unlock(&rtc_lock); -+ spin_unlock_irqrestore(&rtc_lock, flags); - - if (is_intr(irqstat)) { - rtc_update_irq(p, 1, irqstat); -@@ -1295,9 +1299,7 @@ static void cmos_check_wkalrm(struct dev - * ACK the rtc irq here - */ - if (t_now >= cmos->alarm_expires && cmos_use_acpi_alarm()) { -- local_irq_disable(); - cmos_interrupt(0, (void *)cmos->rtc); -- local_irq_enable(); - return; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/rtc/rtc-ds1307.c BPI-Router-Linux-kernel-6.16.12/drivers/rtc/rtc-ds1307.c ---- BPI-Router-Linux-kernel/drivers/rtc/rtc-ds1307.c 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/rtc/rtc-ds1307.c 2025-10-22 13:53:56.651168486 -0400 -@@ -279,6 +279,13 @@ static int ds1307_get_time(struct device - if (tmp & DS1340_BIT_OSF) - return -EINVAL; - break; -+ case ds_1341: -+ ret = regmap_read(ds1307->regmap, DS1337_REG_STATUS, &tmp); -+ if (ret) -+ return ret; -+ if (tmp & DS1337_BIT_OSF) -+ return -EINVAL; -+ break; - case ds_1388: - ret = regmap_read(ds1307->regmap, DS1388_REG_FLAG, &tmp); - if (ret) -@@ -377,6 +384,10 @@ static int ds1307_set_time(struct device - regmap_update_bits(ds1307->regmap, DS1340_REG_FLAG, - DS1340_BIT_OSF, 0); - break; -+ case ds_1341: -+ regmap_update_bits(ds1307->regmap, DS1337_REG_STATUS, -+ DS1337_BIT_OSF, 0); -+ break; - case ds_1388: - regmap_update_bits(ds1307->regmap, DS1388_REG_FLAG, - DS1388_BIT_OSF, 0); -@@ -1466,7 +1477,7 @@ static long ds3231_clk_sqw_round_rate(st - return ds3231_clk_sqw_rates[i]; - } - -- return 0; -+ return ds3231_clk_sqw_rates[ARRAY_SIZE(ds3231_clk_sqw_rates) - 1]; - } - - static int ds3231_clk_sqw_set_rate(struct clk_hw *hw, unsigned long rate, -@@ -1813,10 +1824,8 @@ static int ds1307_probe(struct i2c_clien - regmap_write(ds1307->regmap, DS1337_REG_CONTROL, - regs[0]); - -- /* oscillator fault? clear flag, and warn */ -+ /* oscillator fault? warn */ - if (regs[1] & DS1337_BIT_OSF) { -- regmap_write(ds1307->regmap, DS1337_REG_STATUS, -- regs[1] & ~DS1337_BIT_OSF); - dev_warn(ds1307->dev, "SET TIME!\n"); - } - break; -diff -purNx .git BPI-Router-Linux-kernel/drivers/rtc/rtc-hym8563.c BPI-Router-Linux-kernel-6.16.12/drivers/rtc/rtc-hym8563.c ---- BPI-Router-Linux-kernel/drivers/rtc/rtc-hym8563.c 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/rtc/rtc-hym8563.c 2025-10-22 13:53:56.651168486 -0400 -@@ -294,7 +294,7 @@ static long hym8563_clkout_round_rate(st - if (clkout_rates[i] <= rate) - return clkout_rates[i]; - -- return 0; -+ return clkout_rates[0]; - } - - static int hym8563_clkout_set_rate(struct clk_hw *hw, unsigned long rate, -diff -purNx .git BPI-Router-Linux-kernel/drivers/rtc/rtc-nct3018y.c BPI-Router-Linux-kernel-6.16.12/drivers/rtc/rtc-nct3018y.c ---- BPI-Router-Linux-kernel/drivers/rtc/rtc-nct3018y.c 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/rtc/rtc-nct3018y.c 2025-10-22 13:53:56.651168486 -0400 -@@ -376,7 +376,7 @@ static long nct3018y_clkout_round_rate(s - if (clkout_rates[i] <= rate) - return clkout_rates[i]; - -- return 0; -+ return clkout_rates[0]; - } - - static int nct3018y_clkout_set_rate(struct clk_hw *hw, unsigned long rate, -diff -purNx .git BPI-Router-Linux-kernel/drivers/rtc/rtc-pcf2127.c BPI-Router-Linux-kernel-6.16.12/drivers/rtc/rtc-pcf2127.c ---- BPI-Router-Linux-kernel/drivers/rtc/rtc-pcf2127.c 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/rtc/rtc-pcf2127.c 2025-10-22 13:53:56.651168486 -0400 -@@ -1538,7 +1538,12 @@ static int pcf2127_spi_probe(struct spi_ - variant = &pcf21xx_cfg[type]; - } - -- config.max_register = variant->max_register, -+ if (variant->type == PCF2131) { -+ config.read_flag_mask = 0x0; -+ config.write_flag_mask = 0x0; -+ } -+ -+ config.max_register = variant->max_register; - - regmap = devm_regmap_init_spi(spi, &config); - if (IS_ERR(regmap)) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/rtc/rtc-pcf85063.c BPI-Router-Linux-kernel-6.16.12/drivers/rtc/rtc-pcf85063.c ---- BPI-Router-Linux-kernel/drivers/rtc/rtc-pcf85063.c 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/rtc/rtc-pcf85063.c 2025-10-22 13:53:56.651168486 -0400 -@@ -410,7 +410,7 @@ static long pcf85063_clkout_round_rate(s - if (clkout_rates[i] <= rate) - return clkout_rates[i]; - -- return 0; -+ return clkout_rates[0]; - } - - static int pcf85063_clkout_set_rate(struct clk_hw *hw, unsigned long rate, -diff -purNx .git BPI-Router-Linux-kernel/drivers/rtc/rtc-pcf8563.c BPI-Router-Linux-kernel-6.16.12/drivers/rtc/rtc-pcf8563.c ---- BPI-Router-Linux-kernel/drivers/rtc/rtc-pcf8563.c 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/rtc/rtc-pcf8563.c 2025-10-22 13:53:56.651168486 -0400 -@@ -339,7 +339,7 @@ static long pcf8563_clkout_round_rate(st - if (clkout_rates[i] <= rate) - return clkout_rates[i]; - -- return 0; -+ return clkout_rates[0]; - } - - static int pcf8563_clkout_set_rate(struct clk_hw *hw, unsigned long rate, -diff -purNx .git BPI-Router-Linux-kernel/drivers/rtc/rtc-rv3028.c BPI-Router-Linux-kernel-6.16.12/drivers/rtc/rtc-rv3028.c ---- BPI-Router-Linux-kernel/drivers/rtc/rtc-rv3028.c 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/rtc/rtc-rv3028.c 2025-10-22 13:53:56.651168486 -0400 -@@ -740,7 +740,7 @@ static long rv3028_clkout_round_rate(str - if (clkout_rates[i] <= rate) - return clkout_rates[i]; - -- return 0; -+ return clkout_rates[0]; - } - - static int rv3028_clkout_set_rate(struct clk_hw *hw, unsigned long rate, -diff -purNx .git BPI-Router-Linux-kernel/drivers/rtc/rtc-s5m.c BPI-Router-Linux-kernel-6.16.12/drivers/rtc/rtc-s5m.c ---- BPI-Router-Linux-kernel/drivers/rtc/rtc-s5m.c 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/rtc/rtc-s5m.c 2025-10-22 13:53:56.651168486 -0400 -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -53,6 +54,7 @@ enum { - * Device | Write time | Read time | Write alarm - * ================================================= - * S5M8767 | UDR + TIME | | UDR -+ * S2MPG10 | WUDR | RUDR | AUDR - * S2MPS11/14 | WUDR | RUDR | WUDR + RUDR - * S2MPS13 | WUDR | RUDR | WUDR + AUDR - * S2MPS15 | WUDR | RUDR | AUDR -@@ -99,6 +101,20 @@ static const struct s5m_rtc_reg_config s - .write_alarm_udr_mask = S5M_RTC_UDR_MASK, - }; - -+/* Register map for S2MPG10 */ -+static const struct s5m_rtc_reg_config s2mpg10_rtc_regs = { -+ .regs_count = 7, -+ .time = S2MPG10_RTC_SEC, -+ .ctrl = S2MPG10_RTC_CTRL, -+ .alarm0 = S2MPG10_RTC_A0SEC, -+ .alarm1 = S2MPG10_RTC_A1SEC, -+ .udr_update = S2MPG10_RTC_UPDATE, -+ .autoclear_udr_mask = S2MPS15_RTC_WUDR_MASK | S2MPS15_RTC_AUDR_MASK, -+ .read_time_udr_mask = S2MPS_RTC_RUDR_MASK, -+ .write_time_udr_mask = S2MPS15_RTC_WUDR_MASK, -+ .write_alarm_udr_mask = S2MPS15_RTC_AUDR_MASK, -+}; -+ - /* Register map for S2MPS13 */ - static const struct s5m_rtc_reg_config s2mps13_rtc_regs = { - .regs_count = 7, -@@ -227,8 +243,8 @@ static int s5m8767_wait_for_udr_update(s - return ret; - } - --static int s5m_check_peding_alarm_interrupt(struct s5m_rtc_info *info, -- struct rtc_wkalrm *alarm) -+static int s5m_check_pending_alarm_interrupt(struct s5m_rtc_info *info, -+ struct rtc_wkalrm *alarm) - { - int ret; - unsigned int val; -@@ -238,6 +254,7 @@ static int s5m_check_peding_alarm_interr - ret = regmap_read(info->regmap, S5M_RTC_STATUS, &val); - val &= S5M_ALARM0_STATUS; - break; -+ case S2MPG10: - case S2MPS15X: - case S2MPS14X: - case S2MPS13X: -@@ -262,17 +279,9 @@ static int s5m_check_peding_alarm_interr - static int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info) - { - int ret; -- unsigned int data; - -- ret = regmap_read(info->regmap, info->regs->udr_update, &data); -- if (ret < 0) { -- dev_err(info->dev, "failed to read update reg(%d)\n", ret); -- return ret; -- } -- -- data |= info->regs->write_time_udr_mask; -- -- ret = regmap_write(info->regmap, info->regs->udr_update, data); -+ ret = regmap_set_bits(info->regmap, info->regs->udr_update, -+ info->regs->write_time_udr_mask); - if (ret < 0) { - dev_err(info->dev, "failed to write update reg(%d)\n", ret); - return ret; -@@ -286,20 +295,14 @@ static int s5m8767_rtc_set_time_reg(stru - static int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info) - { - int ret; -- unsigned int data; -+ unsigned int udr_mask; - -- ret = regmap_read(info->regmap, info->regs->udr_update, &data); -- if (ret < 0) { -- dev_err(info->dev, "%s: fail to read update reg(%d)\n", -- __func__, ret); -- return ret; -- } -- -- data |= info->regs->write_alarm_udr_mask; -+ udr_mask = info->regs->write_alarm_udr_mask; - switch (info->device_type) { - case S5M8767X: -- data &= ~S5M_RTC_TIME_EN_MASK; -+ udr_mask |= S5M_RTC_TIME_EN_MASK; - break; -+ case S2MPG10: - case S2MPS15X: - case S2MPS14X: - case S2MPS13X: -@@ -309,7 +312,8 @@ static int s5m8767_rtc_set_alarm_reg(str - return -EINVAL; - } - -- ret = regmap_write(info->regmap, info->regs->udr_update, data); -+ ret = regmap_update_bits(info->regmap, info->regs->udr_update, -+ udr_mask, info->regs->write_alarm_udr_mask); - if (ret < 0) { - dev_err(info->dev, "%s: fail to write update reg(%d)\n", - __func__, ret); -@@ -320,8 +324,8 @@ static int s5m8767_rtc_set_alarm_reg(str - - /* On S2MPS13 the AUDR is not auto-cleared */ - if (info->device_type == S2MPS13X) -- regmap_update_bits(info->regmap, info->regs->udr_update, -- S2MPS13_RTC_AUDR_MASK, 0); -+ regmap_clear_bits(info->regmap, info->regs->udr_update, -+ S2MPS13_RTC_AUDR_MASK); - - return ret; - } -@@ -333,10 +337,8 @@ static int s5m_rtc_read_time(struct devi - int ret; - - if (info->regs->read_time_udr_mask) { -- ret = regmap_update_bits(info->regmap, -- info->regs->udr_update, -- info->regs->read_time_udr_mask, -- info->regs->read_time_udr_mask); -+ ret = regmap_set_bits(info->regmap, info->regs->udr_update, -+ info->regs->read_time_udr_mask); - if (ret) { - dev_err(dev, - "Failed to prepare registers for time reading: %d\n", -@@ -351,6 +353,7 @@ static int s5m_rtc_read_time(struct devi - - switch (info->device_type) { - case S5M8767X: -+ case S2MPG10: - case S2MPS15X: - case S2MPS14X: - case S2MPS13X: -@@ -374,6 +377,7 @@ static int s5m_rtc_set_time(struct devic - - switch (info->device_type) { - case S5M8767X: -+ case S2MPG10: - case S2MPS15X: - case S2MPS14X: - case S2MPS13X: -@@ -411,6 +415,7 @@ static int s5m_rtc_read_alarm(struct dev - - switch (info->device_type) { - case S5M8767X: -+ case S2MPG10: - case S2MPS15X: - case S2MPS14X: - case S2MPS13X: -@@ -430,7 +435,7 @@ static int s5m_rtc_read_alarm(struct dev - - dev_dbg(dev, "%s: %ptR(%d)\n", __func__, &alrm->time, alrm->time.tm_wday); - -- return s5m_check_peding_alarm_interrupt(info, alrm); -+ return s5m_check_pending_alarm_interrupt(info, alrm); - } - - static int s5m_rtc_stop_alarm(struct s5m_rtc_info *info) -@@ -449,6 +454,7 @@ static int s5m_rtc_stop_alarm(struct s5m - - switch (info->device_type) { - case S5M8767X: -+ case S2MPG10: - case S2MPS15X: - case S2MPS14X: - case S2MPS13X: -@@ -487,6 +493,7 @@ static int s5m_rtc_start_alarm(struct s5 - - switch (info->device_type) { - case S5M8767X: -+ case S2MPG10: - case S2MPS15X: - case S2MPS14X: - case S2MPS13X: -@@ -524,6 +531,7 @@ static int s5m_rtc_set_alarm(struct devi - - switch (info->device_type) { - case S5M8767X: -+ case S2MPG10: - case S2MPS15X: - case S2MPS14X: - case S2MPS13X: -@@ -604,6 +612,7 @@ static int s5m8767_rtc_init_reg(struct s - ret = regmap_raw_write(info->regmap, S5M_ALARM0_CONF, data, 2); - break; - -+ case S2MPG10: - case S2MPS15X: - case S2MPS14X: - case S2MPS13X: -@@ -634,59 +643,92 @@ static int s5m8767_rtc_init_reg(struct s - return ret; - } - -+static int s5m_rtc_restart_s2mpg10(struct sys_off_data *data) -+{ -+ struct s5m_rtc_info *info = data->cb_data; -+ int ret; -+ -+ if (data->mode != REBOOT_COLD && data->mode != REBOOT_HARD) -+ return NOTIFY_DONE; -+ -+ /* -+ * Arm watchdog with maximum timeout (2 seconds), and perform full reset -+ * on expiry. -+ */ -+ ret = regmap_set_bits(info->regmap, S2MPG10_RTC_WTSR, -+ (S2MPG10_WTSR_COLDTIMER | S2MPG10_WTSR_COLDRST -+ | S2MPG10_WTSR_WTSRT | S2MPG10_WTSR_WTSR_EN)); -+ -+ return ret ? NOTIFY_BAD : NOTIFY_DONE; -+} -+ - static int s5m_rtc_probe(struct platform_device *pdev) - { - struct sec_pmic_dev *s5m87xx = dev_get_drvdata(pdev->dev.parent); -+ enum sec_device_type device_type = -+ platform_get_device_id(pdev)->driver_data; - struct s5m_rtc_info *info; -- struct i2c_client *i2c; -- const struct regmap_config *regmap_cfg; - int ret, alarm_irq; - - info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - -- switch (platform_get_device_id(pdev)->driver_data) { -- case S2MPS15X: -- regmap_cfg = &s2mps14_rtc_regmap_config; -- info->regs = &s2mps15_rtc_regs; -- alarm_irq = S2MPS14_IRQ_RTCA0; -- break; -- case S2MPS14X: -- regmap_cfg = &s2mps14_rtc_regmap_config; -- info->regs = &s2mps14_rtc_regs; -- alarm_irq = S2MPS14_IRQ_RTCA0; -- break; -- case S2MPS13X: -- regmap_cfg = &s2mps14_rtc_regmap_config; -- info->regs = &s2mps13_rtc_regs; -- alarm_irq = S2MPS14_IRQ_RTCA0; -- break; -- case S5M8767X: -- regmap_cfg = &s5m_rtc_regmap_config; -- info->regs = &s5m_rtc_regs; -- alarm_irq = S5M8767_IRQ_RTCA1; -- break; -- default: -+ info->regmap = dev_get_regmap(pdev->dev.parent, "rtc"); -+ if (!info->regmap) { -+ const struct regmap_config *regmap_cfg; -+ struct i2c_client *i2c; -+ -+ switch (device_type) { -+ case S2MPS15X: -+ regmap_cfg = &s2mps14_rtc_regmap_config; -+ info->regs = &s2mps15_rtc_regs; -+ alarm_irq = S2MPS14_IRQ_RTCA0; -+ break; -+ case S2MPS14X: -+ regmap_cfg = &s2mps14_rtc_regmap_config; -+ info->regs = &s2mps14_rtc_regs; -+ alarm_irq = S2MPS14_IRQ_RTCA0; -+ break; -+ case S2MPS13X: -+ regmap_cfg = &s2mps14_rtc_regmap_config; -+ info->regs = &s2mps13_rtc_regs; -+ alarm_irq = S2MPS14_IRQ_RTCA0; -+ break; -+ case S5M8767X: -+ regmap_cfg = &s5m_rtc_regmap_config; -+ info->regs = &s5m_rtc_regs; -+ alarm_irq = S5M8767_IRQ_RTCA1; -+ break; -+ default: -+ return dev_err_probe(&pdev->dev, -ENODEV, -+ "Unsupported device type %d\n", -+ device_type); -+ } -+ -+ i2c = devm_i2c_new_dummy_device(&pdev->dev, -+ s5m87xx->i2c->adapter, -+ RTC_I2C_ADDR); -+ if (IS_ERR(i2c)) -+ return dev_err_probe(&pdev->dev, PTR_ERR(i2c), -+ "Failed to allocate I2C\n"); -+ -+ info->regmap = devm_regmap_init_i2c(i2c, regmap_cfg); -+ if (IS_ERR(info->regmap)) -+ return dev_err_probe(&pdev->dev, PTR_ERR(info->regmap), -+ "Failed to allocate regmap\n"); -+ } else if (device_type == S2MPG10) { -+ info->regs = &s2mpg10_rtc_regs; -+ alarm_irq = S2MPG10_IRQ_RTCA0; -+ } else { - return dev_err_probe(&pdev->dev, -ENODEV, -- "Device type %lu is not supported by RTC driver\n", -- platform_get_device_id(pdev)->driver_data); -+ "Unsupported device type %d\n", -+ device_type); - } - -- i2c = devm_i2c_new_dummy_device(&pdev->dev, s5m87xx->i2c->adapter, -- RTC_I2C_ADDR); -- if (IS_ERR(i2c)) -- return dev_err_probe(&pdev->dev, PTR_ERR(i2c), -- "Failed to allocate I2C for RTC\n"); -- -- info->regmap = devm_regmap_init_i2c(i2c, regmap_cfg); -- if (IS_ERR(info->regmap)) -- return dev_err_probe(&pdev->dev, PTR_ERR(info->regmap), -- "Failed to allocate RTC register map\n"); -- - info->dev = &pdev->dev; - info->s5m87xx = s5m87xx; -- info->device_type = platform_get_device_id(pdev)->driver_data; -+ info->device_type = device_type; - - if (s5m87xx->irq_data) { - info->irq = regmap_irq_get_virq(s5m87xx->irq_data, alarm_irq); -@@ -721,7 +763,23 @@ static int s5m_rtc_probe(struct platform - return dev_err_probe(&pdev->dev, ret, - "Failed to request alarm IRQ %d\n", - info->irq); -- device_init_wakeup(&pdev->dev, true); -+ -+ ret = devm_device_init_wakeup(&pdev->dev); -+ if (ret < 0) -+ return dev_err_probe(&pdev->dev, ret, -+ "Failed to init wakeup\n"); -+ } -+ -+ if (of_device_is_system_power_controller(pdev->dev.parent->of_node) && -+ info->device_type == S2MPG10) { -+ ret = devm_register_sys_off_handler(&pdev->dev, -+ SYS_OFF_MODE_RESTART, -+ SYS_OFF_PRIO_HIGH + 1, -+ s5m_rtc_restart_s2mpg10, -+ info); -+ if (ret) -+ return dev_err_probe(&pdev->dev, ret, -+ "Failed to register restart handler\n"); - } - - return devm_rtc_register_device(info->rtc_dev); -@@ -755,6 +813,7 @@ static SIMPLE_DEV_PM_OPS(s5m_rtc_pm_ops, - - static const struct platform_device_id s5m_rtc_id[] = { - { "s5m-rtc", S5M8767X }, -+ { "s2mpg10-rtc", S2MPG10 }, - { "s2mps13-rtc", S2MPS13X }, - { "s2mps14-rtc", S2MPS14X }, - { "s2mps15-rtc", S2MPS15X }, -diff -purNx .git BPI-Router-Linux-kernel/drivers/s390/char/sclp.c BPI-Router-Linux-kernel-6.16.12/drivers/s390/char/sclp.c ---- BPI-Router-Linux-kernel/drivers/s390/char/sclp.c 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/s390/char/sclp.c 2025-10-22 13:53:56.651168486 -0400 -@@ -76,6 +76,13 @@ unsigned long sclp_console_full; - /* The currently active SCLP command word. */ - static sclp_cmdw_t active_cmd; - -+static inline struct sccb_header *sclpint_to_sccb(u32 sccb_int) -+{ -+ if (sccb_int) -+ return __va(sccb_int); -+ return NULL; -+} -+ - static inline void sclp_trace(int prio, char *id, u32 a, u64 b, bool err) - { - struct sclp_trace_entry e; -@@ -619,7 +626,7 @@ __sclp_find_req(u32 sccb) - - static bool ok_response(u32 sccb_int, sclp_cmdw_t cmd) - { -- struct sccb_header *sccb = (struct sccb_header *)__va(sccb_int); -+ struct sccb_header *sccb = sclpint_to_sccb(sccb_int); - struct evbuf_header *evbuf; - u16 response; - -@@ -658,7 +665,7 @@ static void sclp_interrupt_handler(struc - - /* INT: Interrupt received (a=intparm, b=cmd) */ - sclp_trace_sccb(0, "INT", param32, active_cmd, active_cmd, -- (struct sccb_header *)__va(finished_sccb), -+ sclpint_to_sccb(finished_sccb), - !ok_response(finished_sccb, active_cmd)); - - if (finished_sccb) { -@@ -719,7 +726,7 @@ sclp_sync_wait(void) - timeout = 0; - if (timer_pending(&sclp_request_timer)) { - /* Get timeout TOD value */ -- timeout = get_tod_clock_fast() + -+ timeout = get_tod_clock_monotonic() + - sclp_tod_from_jiffies(sclp_request_timer.expires - - jiffies); - } -@@ -739,7 +746,7 @@ sclp_sync_wait(void) - /* Loop until driver state indicates finished request */ - while (sclp_running_state != sclp_running_state_idle) { - /* Check for expired request timer */ -- if (get_tod_clock_fast() > timeout && timer_delete(&sclp_request_timer)) -+ if (get_tod_clock_monotonic() > timeout && timer_delete(&sclp_request_timer)) - sclp_request_timer.function(&sclp_request_timer); - cpu_relax(); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/s390/crypto/ap_bus.h BPI-Router-Linux-kernel-6.16.12/drivers/s390/crypto/ap_bus.h ---- BPI-Router-Linux-kernel/drivers/s390/crypto/ap_bus.h 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/s390/crypto/ap_bus.h 2025-10-22 13:53:56.651168486 -0400 -@@ -180,7 +180,7 @@ struct ap_card { - atomic64_t total_request_count; /* # requests ever for this AP device.*/ - }; - --#define TAPQ_CARD_HWINFO_MASK 0xFEFF0000FFFF0F0FUL -+#define TAPQ_CARD_HWINFO_MASK 0xFFFF0000FFFF0F0FUL - #define ASSOC_IDX_INVALID 0x10000 - - #define to_ap_card(x) container_of((x), struct ap_card, ap_dev.device) -diff -purNx .git BPI-Router-Linux-kernel/drivers/s390/crypto/pkey_api.c BPI-Router-Linux-kernel-6.16.12/drivers/s390/crypto/pkey_api.c ---- BPI-Router-Linux-kernel/drivers/s390/crypto/pkey_api.c 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/s390/crypto/pkey_api.c 2025-10-22 13:53:56.651168486 -0400 -@@ -86,7 +86,7 @@ static void *_copy_apqns_from_user(void - if (!uapqns || nr_apqns == 0) - return NULL; - -- return memdup_user(uapqns, nr_apqns * sizeof(struct pkey_apqn)); -+ return memdup_array_user(uapqns, nr_apqns, sizeof(struct pkey_apqn)); - } - - static int pkey_ioctl_genseck(struct pkey_genseck __user *ugs) -diff -purNx .git BPI-Router-Linux-kernel/drivers/s390/net/ism_drv.c BPI-Router-Linux-kernel-6.16.12/drivers/s390/net/ism_drv.c ---- BPI-Router-Linux-kernel/drivers/s390/net/ism_drv.c 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/s390/net/ism_drv.c 2025-10-22 13:53:56.651168486 -0400 -@@ -130,6 +130,7 @@ static int ism_cmd(struct ism_dev *ism, - struct ism_req_hdr *req = cmd; - struct ism_resp_hdr *resp = cmd; - -+ spin_lock(&ism->cmd_lock); - __ism_write_cmd(ism, req + 1, sizeof(*req), req->len - sizeof(*req)); - __ism_write_cmd(ism, req, 0, sizeof(*req)); - -@@ -143,6 +144,7 @@ static int ism_cmd(struct ism_dev *ism, - } - __ism_read_cmd(ism, resp + 1, sizeof(*resp), resp->len - sizeof(*resp)); - out: -+ spin_unlock(&ism->cmd_lock); - return resp->ret; - } - -@@ -606,6 +608,7 @@ static int ism_probe(struct pci_dev *pde - return -ENOMEM; - - spin_lock_init(&ism->lock); -+ spin_lock_init(&ism->cmd_lock); - dev_set_drvdata(&pdev->dev, ism); - ism->pdev = pdev; - ism->dev.parent = &pdev->dev; -diff -purNx .git BPI-Router-Linux-kernel/drivers/s390/scsi/zfcp_sysfs.c BPI-Router-Linux-kernel-6.16.12/drivers/s390/scsi/zfcp_sysfs.c ---- BPI-Router-Linux-kernel/drivers/s390/scsi/zfcp_sysfs.c 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/s390/scsi/zfcp_sysfs.c 2025-10-22 13:53:56.651168486 -0400 -@@ -449,6 +449,8 @@ static ssize_t zfcp_sysfs_unit_add_store - if (kstrtoull(buf, 0, (unsigned long long *) &fcp_lun)) - return -EINVAL; - -+ flush_work(&port->rport_work); -+ - retval = zfcp_unit_add(port, fcp_lun); - if (retval) - return retval; -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/aacraid/comminit.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/aacraid/comminit.c ---- BPI-Router-Linux-kernel/drivers/scsi/aacraid/comminit.c 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/aacraid/comminit.c 2025-10-22 13:53:56.651168486 -0400 -@@ -481,8 +481,7 @@ void aac_define_int_mode(struct aac_dev - pci_find_capability(dev->pdev, PCI_CAP_ID_MSIX)) { - min_msix = 2; - i = pci_alloc_irq_vectors(dev->pdev, -- min_msix, msi_count, -- PCI_IRQ_MSIX | PCI_IRQ_AFFINITY); -+ min_msix, msi_count, PCI_IRQ_MSIX); - if (i > 0) { - dev->msi_enabled = 1; - msi_count = i; -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/bfa/bfad_im.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/bfa/bfad_im.c ---- BPI-Router-Linux-kernel/drivers/scsi/bfa/bfad_im.c 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/bfa/bfad_im.c 2025-10-22 13:53:56.651168486 -0400 -@@ -706,6 +706,7 @@ bfad_im_probe(struct bfad_s *bfad) - - if (bfad_thread_workq(bfad) != BFA_STATUS_OK) { - kfree(im); -+ bfad->im = NULL; - return BFA_STATUS_FAILED; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/elx/efct/efct_hw.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/elx/efct/efct_hw.c ---- BPI-Router-Linux-kernel/drivers/scsi/elx/efct/efct_hw.c 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/elx/efct/efct_hw.c 2025-10-22 13:53:56.651168486 -0400 -@@ -1120,7 +1120,7 @@ int - efct_hw_parse_filter(struct efct_hw *hw, void *value) - { - int rc = 0; -- char *p = NULL; -+ char *p = NULL, *pp = NULL; - char *token; - u32 idx = 0; - -@@ -1132,6 +1132,7 @@ efct_hw_parse_filter(struct efct_hw *hw, - efc_log_err(hw->os, "p is NULL\n"); - return -ENOMEM; - } -+ pp = p; - - idx = 0; - while ((token = strsep(&p, ",")) && *token) { -@@ -1144,7 +1145,7 @@ efct_hw_parse_filter(struct efct_hw *hw, - if (idx == ARRAY_SIZE(hw->config.filter_def)) - break; - } -- kfree(p); -+ kfree(pp); - - return rc; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/elx/efct/efct_lio.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/elx/efct/efct_lio.c ---- BPI-Router-Linux-kernel/drivers/scsi/elx/efct/efct_lio.c 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/elx/efct/efct_lio.c 2025-10-22 13:53:56.651168486 -0400 -@@ -382,7 +382,7 @@ efct_lio_sg_unmap(struct efct_io *io) - return; - - dma_unmap_sg(&io->efct->pci->dev, cmd->t_data_sg, -- ocp->seg_map_cnt, cmd->data_direction); -+ cmd->t_data_nents, cmd->data_direction); - ocp->seg_map_cnt = 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/fnic/fdls_disc.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/fnic/fdls_disc.c ---- BPI-Router-Linux-kernel/drivers/scsi/fnic/fdls_disc.c 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/fnic/fdls_disc.c 2025-10-22 13:53:56.651168486 -0400 -@@ -763,50 +763,86 @@ static void fdls_send_fabric_abts(struct - iport->fabric.timer_pending = 1; - } - --static void fdls_send_fdmi_abts(struct fnic_iport_s *iport) -+static uint8_t *fdls_alloc_init_fdmi_abts_frame(struct fnic_iport_s *iport, -+ uint16_t oxid) - { -- uint8_t *frame; -+ struct fc_frame_header *pfdmi_abts; - uint8_t d_id[3]; -+ uint8_t *frame; - struct fnic *fnic = iport->fnic; -- struct fc_frame_header *pfabric_abts; -- unsigned long fdmi_tov; -- uint16_t oxid; -- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET + -- sizeof(struct fc_frame_header); - - frame = fdls_alloc_frame(iport); - if (frame == NULL) { - FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num, - "Failed to allocate frame to send FDMI ABTS"); -- return; -+ return NULL; - } - -- pfabric_abts = (struct fc_frame_header *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET); -+ pfdmi_abts = (struct fc_frame_header *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET); - fdls_init_fabric_abts_frame(frame, iport); - - hton24(d_id, FC_FID_MGMT_SERV); -- FNIC_STD_SET_D_ID(*pfabric_abts, d_id); -+ FNIC_STD_SET_D_ID(*pfdmi_abts, d_id); -+ FNIC_STD_SET_OX_ID(*pfdmi_abts, oxid); -+ -+ return frame; -+} -+ -+static void fdls_send_fdmi_abts(struct fnic_iport_s *iport) -+{ -+ uint8_t *frame; -+ struct fnic *fnic = iport->fnic; -+ unsigned long fdmi_tov; -+ uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET + -+ sizeof(struct fc_frame_header); - - if (iport->fabric.fdmi_pending & FDLS_FDMI_PLOGI_PENDING) { -- oxid = iport->active_oxid_fdmi_plogi; -- FNIC_STD_SET_OX_ID(*pfabric_abts, oxid); -+ frame = fdls_alloc_init_fdmi_abts_frame(iport, -+ iport->active_oxid_fdmi_plogi); -+ if (frame == NULL) -+ return; -+ -+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -+ "0x%x: FDLS send FDMI PLOGI abts. iport->fabric.state: %d oxid: 0x%x", -+ iport->fcid, iport->fabric.state, iport->active_oxid_fdmi_plogi); - fnic_send_fcoe_frame(iport, frame, frame_size); - } else { - if (iport->fabric.fdmi_pending & FDLS_FDMI_REG_HBA_PENDING) { -- oxid = iport->active_oxid_fdmi_rhba; -- FNIC_STD_SET_OX_ID(*pfabric_abts, oxid); -+ frame = fdls_alloc_init_fdmi_abts_frame(iport, -+ iport->active_oxid_fdmi_rhba); -+ if (frame == NULL) -+ return; -+ -+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -+ "0x%x: FDLS send FDMI RHBA abts. iport->fabric.state: %d oxid: 0x%x", -+ iport->fcid, iport->fabric.state, iport->active_oxid_fdmi_rhba); - fnic_send_fcoe_frame(iport, frame, frame_size); - } - if (iport->fabric.fdmi_pending & FDLS_FDMI_RPA_PENDING) { -- oxid = iport->active_oxid_fdmi_rpa; -- FNIC_STD_SET_OX_ID(*pfabric_abts, oxid); -+ frame = fdls_alloc_init_fdmi_abts_frame(iport, -+ iport->active_oxid_fdmi_rpa); -+ if (frame == NULL) { -+ if (iport->fabric.fdmi_pending & FDLS_FDMI_REG_HBA_PENDING) -+ goto arm_timer; -+ else -+ return; -+ } -+ -+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -+ "0x%x: FDLS send FDMI RPA abts. iport->fabric.state: %d oxid: 0x%x", -+ iport->fcid, iport->fabric.state, iport->active_oxid_fdmi_rpa); - fnic_send_fcoe_frame(iport, frame, frame_size); - } - } - -+arm_timer: - fdmi_tov = jiffies + msecs_to_jiffies(2 * iport->e_d_tov); - mod_timer(&iport->fabric.fdmi_timer, round_jiffies(fdmi_tov)); - iport->fabric.fdmi_pending |= FDLS_FDMI_ABORT_PENDING; -+ -+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -+ "0x%x: iport->fabric.fdmi_pending: 0x%x", -+ iport->fcid, iport->fabric.fdmi_pending); - } - - static void fdls_send_fabric_flogi(struct fnic_iport_s *iport) -@@ -2245,6 +2281,21 @@ void fdls_fabric_timer_callback(struct t - spin_unlock_irqrestore(&fnic->fnic_lock, flags); - } - -+void fdls_fdmi_retry_plogi(struct fnic_iport_s *iport) -+{ -+ struct fnic *fnic = iport->fnic; -+ -+ iport->fabric.fdmi_pending = 0; -+ /* If max retries not exhausted, start over from fdmi plogi */ -+ if (iport->fabric.fdmi_retry < FDLS_FDMI_MAX_RETRY) { -+ iport->fabric.fdmi_retry++; -+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -+ "Retry FDMI PLOGI. FDMI retry: %d", -+ iport->fabric.fdmi_retry); -+ fdls_send_fdmi_plogi(iport); -+ } -+} -+ - void fdls_fdmi_timer_callback(struct timer_list *t) - { - struct fnic_fdls_fabric_s *fabric = timer_container_of(fabric, t, -@@ -2257,7 +2308,7 @@ void fdls_fdmi_timer_callback(struct tim - spin_lock_irqsave(&fnic->fnic_lock, flags); - - FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -- "fdmi timer callback : 0x%x\n", iport->fabric.fdmi_pending); -+ "iport->fabric.fdmi_pending: 0x%x\n", iport->fabric.fdmi_pending); - - if (!iport->fabric.fdmi_pending) { - /* timer expired after fdmi responses received. */ -@@ -2265,7 +2316,7 @@ void fdls_fdmi_timer_callback(struct tim - return; - } - FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -- "fdmi timer callback : 0x%x\n", iport->fabric.fdmi_pending); -+ "iport->fabric.fdmi_pending: 0x%x\n", iport->fabric.fdmi_pending); - - /* if not abort pending, send an abort */ - if (!(iport->fabric.fdmi_pending & FDLS_FDMI_ABORT_PENDING)) { -@@ -2274,33 +2325,37 @@ void fdls_fdmi_timer_callback(struct tim - return; - } - FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -- "fdmi timer callback : 0x%x\n", iport->fabric.fdmi_pending); -+ "iport->fabric.fdmi_pending: 0x%x\n", iport->fabric.fdmi_pending); - - /* ABTS pending for an active fdmi request that is pending. - * That means FDMI ABTS timed out - * Schedule to free the OXID after 2*r_a_tov and proceed - */ - if (iport->fabric.fdmi_pending & FDLS_FDMI_PLOGI_PENDING) { -+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -+ "FDMI PLOGI ABTS timed out. Schedule oxid free: 0x%x\n", -+ iport->active_oxid_fdmi_plogi); - fdls_schedule_oxid_free(iport, &iport->active_oxid_fdmi_plogi); - } else { -- if (iport->fabric.fdmi_pending & FDLS_FDMI_REG_HBA_PENDING) -+ if (iport->fabric.fdmi_pending & FDLS_FDMI_REG_HBA_PENDING) { -+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -+ "FDMI RHBA ABTS timed out. Schedule oxid free: 0x%x\n", -+ iport->active_oxid_fdmi_rhba); - fdls_schedule_oxid_free(iport, &iport->active_oxid_fdmi_rhba); -- if (iport->fabric.fdmi_pending & FDLS_FDMI_RPA_PENDING) -+ } -+ if (iport->fabric.fdmi_pending & FDLS_FDMI_RPA_PENDING) { -+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -+ "FDMI RPA ABTS timed out. Schedule oxid free: 0x%x\n", -+ iport->active_oxid_fdmi_rpa); - fdls_schedule_oxid_free(iport, &iport->active_oxid_fdmi_rpa); -+ } - } - FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -- "fdmi timer callback : 0x%x\n", iport->fabric.fdmi_pending); -+ "iport->fabric.fdmi_pending: 0x%x\n", iport->fabric.fdmi_pending); - -- iport->fabric.fdmi_pending = 0; -- /* If max retries not exhaused, start over from fdmi plogi */ -- if (iport->fabric.fdmi_retry < FDLS_FDMI_MAX_RETRY) { -- iport->fabric.fdmi_retry++; -- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -- "retry fdmi timer %d", iport->fabric.fdmi_retry); -- fdls_send_fdmi_plogi(iport); -- } -+ fdls_fdmi_retry_plogi(iport); - FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -- "fdmi timer callback : 0x%x\n", iport->fabric.fdmi_pending); -+ "iport->fabric.fdmi_pending: 0x%x\n", iport->fabric.fdmi_pending); - spin_unlock_irqrestore(&fnic->fnic_lock, flags); - } - -@@ -3715,13 +3770,60 @@ static void fdls_process_fdmi_abts_rsp(s - - switch (FNIC_FRAME_TYPE(oxid)) { - case FNIC_FRAME_TYPE_FDMI_PLOGI: -+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -+ "Received FDMI PLOGI ABTS rsp with oxid: 0x%x", oxid); -+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -+ "0x%x: iport->fabric.fdmi_pending: 0x%x", -+ iport->fcid, iport->fabric.fdmi_pending); - fdls_free_oxid(iport, oxid, &iport->active_oxid_fdmi_plogi); -+ -+ iport->fabric.fdmi_pending &= ~FDLS_FDMI_PLOGI_PENDING; -+ iport->fabric.fdmi_pending &= ~FDLS_FDMI_ABORT_PENDING; -+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -+ "0x%x: iport->fabric.fdmi_pending: 0x%x", -+ iport->fcid, iport->fabric.fdmi_pending); - break; - case FNIC_FRAME_TYPE_FDMI_RHBA: -+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -+ "Received FDMI RHBA ABTS rsp with oxid: 0x%x", oxid); -+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -+ "0x%x: iport->fabric.fdmi_pending: 0x%x", -+ iport->fcid, iport->fabric.fdmi_pending); -+ -+ iport->fabric.fdmi_pending &= ~FDLS_FDMI_REG_HBA_PENDING; -+ -+ /* If RPA is still pending, don't turn off ABORT PENDING. -+ * We count on the timer to detect the ABTS timeout and take -+ * corrective action. -+ */ -+ if (!(iport->fabric.fdmi_pending & FDLS_FDMI_RPA_PENDING)) -+ iport->fabric.fdmi_pending &= ~FDLS_FDMI_ABORT_PENDING; -+ - fdls_free_oxid(iport, oxid, &iport->active_oxid_fdmi_rhba); -+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -+ "0x%x: iport->fabric.fdmi_pending: 0x%x", -+ iport->fcid, iport->fabric.fdmi_pending); - break; - case FNIC_FRAME_TYPE_FDMI_RPA: -+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -+ "Received FDMI RPA ABTS rsp with oxid: 0x%x", oxid); -+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -+ "0x%x: iport->fabric.fdmi_pending: 0x%x", -+ iport->fcid, iport->fabric.fdmi_pending); -+ -+ iport->fabric.fdmi_pending &= ~FDLS_FDMI_RPA_PENDING; -+ -+ /* If RHBA is still pending, don't turn off ABORT PENDING. -+ * We count on the timer to detect the ABTS timeout and take -+ * corrective action. -+ */ -+ if (!(iport->fabric.fdmi_pending & FDLS_FDMI_REG_HBA_PENDING)) -+ iport->fabric.fdmi_pending &= ~FDLS_FDMI_ABORT_PENDING; -+ - fdls_free_oxid(iport, oxid, &iport->active_oxid_fdmi_rpa); -+ FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -+ "0x%x: iport->fabric.fdmi_pending: 0x%x", -+ iport->fcid, iport->fabric.fdmi_pending); - break; - default: - FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -@@ -3730,10 +3832,16 @@ static void fdls_process_fdmi_abts_rsp(s - break; - } - -- timer_delete_sync(&iport->fabric.fdmi_timer); -- iport->fabric.fdmi_pending &= ~FDLS_FDMI_ABORT_PENDING; -- -- fdls_send_fdmi_plogi(iport); -+ /* -+ * Only if ABORT PENDING is off, delete the timer, and if no other -+ * operations are pending, retry FDMI. -+ * Otherwise, let the timer pop and take the appropriate action. -+ */ -+ if (!(iport->fabric.fdmi_pending & FDLS_FDMI_ABORT_PENDING)) { -+ timer_delete_sync(&iport->fabric.fdmi_timer); -+ if (!iport->fabric.fdmi_pending) -+ fdls_fdmi_retry_plogi(iport); -+ } - } - - static void -@@ -4972,9 +5080,12 @@ void fnic_fdls_link_down(struct fnic_ipo - fdls_delete_tport(iport, tport); - } - -- if ((fnic_fdmi_support == 1) && (iport->fabric.fdmi_pending > 0)) { -- timer_delete_sync(&iport->fabric.fdmi_timer); -- iport->fabric.fdmi_pending = 0; -+ if (fnic_fdmi_support == 1) { -+ if (iport->fabric.fdmi_pending > 0) { -+ timer_delete_sync(&iport->fabric.fdmi_timer); -+ iport->fabric.fdmi_pending = 0; -+ } -+ iport->flags &= ~FNIC_FDMI_ACTIVE; - } - - FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/fnic/fnic_fcs.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/fnic/fnic_fcs.c ---- BPI-Router-Linux-kernel/drivers/scsi/fnic/fnic_fcs.c 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/fnic/fnic_fcs.c 2025-10-22 13:53:56.651168486 -0400 -@@ -636,6 +636,8 @@ static int fnic_send_frame(struct fnic * - unsigned long flags; - - pa = dma_map_single(&fnic->pdev->dev, frame, frame_len, DMA_TO_DEVICE); -+ if (dma_mapping_error(&fnic->pdev->dev, pa)) -+ return -ENOMEM; - - if ((fnic_fc_trace_set_data(fnic->fnic_num, - FNIC_FC_SEND | 0x80, (char *) frame, -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/fnic/fnic_fdls.h BPI-Router-Linux-kernel-6.16.12/drivers/scsi/fnic/fnic_fdls.h ---- BPI-Router-Linux-kernel/drivers/scsi/fnic/fnic_fdls.h 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/fnic/fnic_fdls.h 2025-10-22 13:53:56.651168486 -0400 -@@ -394,6 +394,7 @@ void fdls_send_tport_abts(struct fnic_ip - bool fdls_delete_tport(struct fnic_iport_s *iport, - struct fnic_tport_s *tport); - void fdls_fdmi_timer_callback(struct timer_list *t); -+void fdls_fdmi_retry_plogi(struct fnic_iport_s *iport); - - /* fnic_fcs.c */ - void fnic_fdls_init(struct fnic *fnic, int usefip); -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/fnic/fnic.h BPI-Router-Linux-kernel-6.16.12/drivers/scsi/fnic/fnic.h ---- BPI-Router-Linux-kernel/drivers/scsi/fnic/fnic.h 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/fnic/fnic.h 2025-10-22 13:53:56.651168486 -0400 -@@ -30,7 +30,7 @@ - - #define DRV_NAME "fnic" - #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" --#define DRV_VERSION "1.8.0.0" -+#define DRV_VERSION "1.8.0.2" - #define PFX DRV_NAME ": " - #define DFX DRV_NAME "%d: " - -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/fnic/fnic_scsi.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/fnic/fnic_scsi.c ---- BPI-Router-Linux-kernel/drivers/scsi/fnic/fnic_scsi.c 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/fnic/fnic_scsi.c 2025-10-22 13:53:56.651168486 -0400 -@@ -1046,7 +1046,7 @@ static void fnic_fcpio_icmnd_cmpl_handle - if (icmnd_cmpl->scsi_status == SAM_STAT_TASK_SET_FULL) - atomic64_inc(&fnic_stats->misc_stats.queue_fulls); - -- FNIC_SCSI_DBG(KERN_INFO, fnic->host, fnic->fnic_num, -+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num, - "xfer_len: %llu", xfer_len); - break; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/hosts.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/hosts.c ---- BPI-Router-Linux-kernel/drivers/scsi/hosts.c 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/hosts.c 2025-10-22 13:53:56.651168486 -0400 -@@ -473,10 +473,17 @@ struct Scsi_Host *scsi_host_alloc(const - else - shost->max_sectors = SCSI_DEFAULT_MAX_SECTORS; - -- if (sht->max_segment_size) -- shost->max_segment_size = sht->max_segment_size; -- else -- shost->max_segment_size = BLK_MAX_SEGMENT_SIZE; -+ shost->virt_boundary_mask = sht->virt_boundary_mask; -+ if (shost->virt_boundary_mask) { -+ WARN_ON_ONCE(sht->max_segment_size && -+ sht->max_segment_size != UINT_MAX); -+ shost->max_segment_size = UINT_MAX; -+ } else { -+ if (sht->max_segment_size) -+ shost->max_segment_size = sht->max_segment_size; -+ else -+ shost->max_segment_size = BLK_MAX_SEGMENT_SIZE; -+ } - - /* 32-byte (dword) is a common minimum for HBAs. */ - if (sht->dma_alignment) -@@ -492,9 +499,6 @@ struct Scsi_Host *scsi_host_alloc(const - else - shost->dma_boundary = 0xffffffff; - -- if (sht->virt_boundary_mask) -- shost->virt_boundary_mask = sht->virt_boundary_mask; -- - device_initialize(&shost->shost_gendev); - dev_set_name(&shost->shost_gendev, "host%d", shost->host_no); - shost->shost_gendev.bus = &scsi_bus_type; -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/ibmvscsi_tgt/libsrp.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/ibmvscsi_tgt/libsrp.c ---- BPI-Router-Linux-kernel/drivers/scsi/ibmvscsi_tgt/libsrp.c 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/ibmvscsi_tgt/libsrp.c 2025-10-22 13:53:56.651168486 -0400 -@@ -184,7 +184,8 @@ static int srp_direct_data(struct ibmvsc - err = rdma_io(cmd, sg, nsg, md, 1, dir, len); - - if (dma_map) -- dma_unmap_sg(iue->target->dev, sg, nsg, DMA_BIDIRECTIONAL); -+ dma_unmap_sg(iue->target->dev, sg, cmd->se_cmd.t_data_nents, -+ DMA_BIDIRECTIONAL); - - return err; - } -@@ -256,7 +257,8 @@ rdma: - err = rdma_io(cmd, sg, nsg, md, nmd, dir, len); - - if (dma_map) -- dma_unmap_sg(iue->target->dev, sg, nsg, DMA_BIDIRECTIONAL); -+ dma_unmap_sg(iue->target->dev, sg, cmd->se_cmd.t_data_nents, -+ DMA_BIDIRECTIONAL); - - free_mem: - if (token && dma_map) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/isci/request.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/isci/request.c ---- BPI-Router-Linux-kernel/drivers/scsi/isci/request.c 2025-10-22 13:53:23.443328034 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/isci/request.c 2025-10-22 13:53:56.655168467 -0400 -@@ -2904,7 +2904,7 @@ static void isci_request_io_request_comp - task->total_xfer_len, task->data_dir); - else /* unmap the sgl dma addresses */ - dma_unmap_sg(&ihost->pdev->dev, task->scatter, -- request->num_sg_entries, task->data_dir); -+ task->num_scatter, task->data_dir); - break; - case SAS_PROTOCOL_SMP: { - struct scatterlist *sg = &task->smp_task.smp_req; -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/libiscsi.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/libiscsi.c ---- BPI-Router-Linux-kernel/drivers/scsi/libiscsi.c 2025-10-22 13:53:23.447328014 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/libiscsi.c 2025-10-22 13:53:56.655168467 -0400 -@@ -3185,7 +3185,8 @@ iscsi_conn_setup(struct iscsi_cls_sessio - return NULL; - conn = cls_conn->dd_data; - -- conn->dd_data = cls_conn->dd_data + sizeof(*conn); -+ if (dd_size) -+ conn->dd_data = cls_conn->dd_data + sizeof(*conn); - conn->session = session; - conn->cls_conn = cls_conn; - conn->c_stage = ISCSI_CONN_INITIAL_STAGE; -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/lpfc/lpfc_debugfs.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/lpfc/lpfc_debugfs.c ---- BPI-Router-Linux-kernel/drivers/scsi/lpfc/lpfc_debugfs.c 2025-10-22 13:53:23.447328014 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/lpfc/lpfc_debugfs.c 2025-10-22 13:53:56.655168467 -0400 -@@ -6289,7 +6289,6 @@ lpfc_debugfs_initialize(struct lpfc_vpor - } - phba->nvmeio_trc_on = 1; - phba->nvmeio_trc_output_idx = 0; -- phba->nvmeio_trc = NULL; - } else { - nvmeio_off: - phba->nvmeio_trc_size = 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/lpfc/lpfc_hbadisc.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/lpfc/lpfc_hbadisc.c ---- BPI-Router-Linux-kernel/drivers/scsi/lpfc/lpfc_hbadisc.c 2025-10-22 13:53:23.447328014 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/lpfc/lpfc_hbadisc.c 2025-10-22 13:53:56.655168467 -0400 -@@ -183,7 +183,8 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport - - /* Don't schedule a worker thread event if the vport is going down. */ - if (test_bit(FC_UNLOADING, &vport->load_flag) || -- !test_bit(HBA_SETUP, &phba->hba_flag)) { -+ (phba->sli_rev == LPFC_SLI_REV4 && -+ !test_bit(HBA_SETUP, &phba->hba_flag))) { - - spin_lock_irqsave(&ndlp->lock, iflags); - ndlp->rport = NULL; -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/lpfc/lpfc_nvmet.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/lpfc/lpfc_nvmet.c ---- BPI-Router-Linux-kernel/drivers/scsi/lpfc/lpfc_nvmet.c 2025-10-22 13:53:23.447328014 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/lpfc/lpfc_nvmet.c 2025-10-22 13:53:56.655168467 -0400 -@@ -1243,7 +1243,7 @@ lpfc_nvmet_defer_rcv(struct nvmet_fc_tar - struct lpfc_nvmet_tgtport *tgtp; - struct lpfc_async_xchg_ctx *ctxp = - container_of(rsp, struct lpfc_async_xchg_ctx, hdlrctx.fcp_req); -- struct rqb_dmabuf *nvmebuf = ctxp->rqb_buffer; -+ struct rqb_dmabuf *nvmebuf; - struct lpfc_hba *phba = ctxp->phba; - unsigned long iflag; - -@@ -1251,13 +1251,18 @@ lpfc_nvmet_defer_rcv(struct nvmet_fc_tar - lpfc_nvmeio_data(phba, "NVMET DEFERRCV: xri x%x sz %d CPU %02x\n", - ctxp->oxid, ctxp->size, raw_smp_processor_id()); - -+ spin_lock_irqsave(&ctxp->ctxlock, iflag); -+ nvmebuf = ctxp->rqb_buffer; - if (!nvmebuf) { -+ spin_unlock_irqrestore(&ctxp->ctxlock, iflag); - lpfc_printf_log(phba, KERN_INFO, LOG_NVME_IOERR, - "6425 Defer rcv: no buffer oxid x%x: " - "flg %x ste %x\n", - ctxp->oxid, ctxp->flag, ctxp->state); - return; - } -+ ctxp->rqb_buffer = NULL; -+ spin_unlock_irqrestore(&ctxp->ctxlock, iflag); - - tgtp = phba->targetport->private; - if (tgtp) -@@ -1265,9 +1270,6 @@ lpfc_nvmet_defer_rcv(struct nvmet_fc_tar - - /* Free the nvmebuf since a new buffer already replaced it */ - nvmebuf->hrq->rqbp->rqb_free_buffer(phba, nvmebuf); -- spin_lock_irqsave(&ctxp->ctxlock, iflag); -- ctxp->rqb_buffer = NULL; -- spin_unlock_irqrestore(&ctxp->ctxlock, iflag); - } - - /** -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/lpfc/lpfc_scsi.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/lpfc/lpfc_scsi.c ---- BPI-Router-Linux-kernel/drivers/scsi/lpfc/lpfc_scsi.c 2025-10-22 13:53:23.447328014 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/lpfc/lpfc_scsi.c 2025-10-22 13:53:56.655168467 -0400 -@@ -390,6 +390,10 @@ lpfc_sli4_vport_delete_fcp_xri_aborted(s - if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_FCP)) - return; - -+ /* may be called before queues established if hba_setup fails */ -+ if (!phba->sli4_hba.hdwq) -+ return; -+ - spin_lock_irqsave(&phba->hbalock, iflag); - for (idx = 0; idx < phba->cfg_hdw_queue; idx++) { - qp = &phba->sli4_hba.hdwq[idx]; -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/megaraid/megaraid_sas_base.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/megaraid/megaraid_sas_base.c ---- BPI-Router-Linux-kernel/drivers/scsi/megaraid/megaraid_sas_base.c 2025-10-22 13:53:23.451327995 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/megaraid/megaraid_sas_base.c 2025-10-22 13:53:56.659168447 -0400 -@@ -5910,7 +5910,11 @@ megasas_set_high_iops_queue_affinity_and - const struct cpumask *mask; - - if (instance->perf_mode == MR_BALANCED_PERF_MODE) { -- mask = cpumask_of_node(dev_to_node(&instance->pdev->dev)); -+ int nid = dev_to_node(&instance->pdev->dev); -+ -+ if (nid == NUMA_NO_NODE) -+ nid = 0; -+ mask = cpumask_of_node(nid); - - for (i = 0; i < instance->low_latency_index_start; i++) { - irq = pci_irq_vector(instance->pdev, i); -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/mpi3mr/mpi3mr_fw.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/mpi3mr/mpi3mr_fw.c ---- BPI-Router-Linux-kernel/drivers/scsi/mpi3mr/mpi3mr_fw.c 2025-10-22 13:53:23.451327995 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/mpi3mr/mpi3mr_fw.c 2025-10-22 13:53:56.659168447 -0400 -@@ -23,17 +23,22 @@ module_param(poll_queues, int, 0444); - MODULE_PARM_DESC(poll_queues, "Number of queues for io_uring poll mode. (Range 1 - 126)"); - - #if defined(writeq) && defined(CONFIG_64BIT) --static inline void mpi3mr_writeq(__u64 b, volatile void __iomem *addr) -+static inline void mpi3mr_writeq(__u64 b, void __iomem *addr, -+ spinlock_t *write_queue_lock) - { - writeq(b, addr); - } - #else --static inline void mpi3mr_writeq(__u64 b, volatile void __iomem *addr) -+static inline void mpi3mr_writeq(__u64 b, void __iomem *addr, -+ spinlock_t *write_queue_lock) - { - __u64 data_out = b; -+ unsigned long flags; - -+ spin_lock_irqsave(write_queue_lock, flags); - writel((u32)(data_out), addr); - writel((u32)(data_out >> 32), (addr + 4)); -+ spin_unlock_irqrestore(write_queue_lock, flags); - } - #endif - -@@ -428,8 +433,8 @@ static void mpi3mr_process_admin_reply_d - MPI3MR_SENSE_BUF_SZ); - } - if (cmdptr->is_waiting) { -- complete(&cmdptr->done); - cmdptr->is_waiting = 0; -+ complete(&cmdptr->done); - } else if (cmdptr->callback) - cmdptr->callback(mrioc, cmdptr); - } -@@ -2954,9 +2959,11 @@ static int mpi3mr_setup_admin_qpair(stru - (mrioc->num_admin_req); - writel(num_admin_entries, &mrioc->sysif_regs->admin_queue_num_entries); - mpi3mr_writeq(mrioc->admin_req_dma, -- &mrioc->sysif_regs->admin_request_queue_address); -+ &mrioc->sysif_regs->admin_request_queue_address, -+ &mrioc->adm_req_q_bar_writeq_lock); - mpi3mr_writeq(mrioc->admin_reply_dma, -- &mrioc->sysif_regs->admin_reply_queue_address); -+ &mrioc->sysif_regs->admin_reply_queue_address, -+ &mrioc->adm_reply_q_bar_writeq_lock); - writel(mrioc->admin_req_pi, &mrioc->sysif_regs->admin_request_queue_pi); - writel(mrioc->admin_reply_ci, &mrioc->sysif_regs->admin_reply_queue_ci); - return retval; -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/mpi3mr/mpi3mr.h BPI-Router-Linux-kernel-6.16.12/drivers/scsi/mpi3mr/mpi3mr.h ---- BPI-Router-Linux-kernel/drivers/scsi/mpi3mr/mpi3mr.h 2025-10-22 13:53:23.451327995 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/mpi3mr/mpi3mr.h 2025-10-22 13:53:56.659168447 -0400 -@@ -1137,6 +1137,8 @@ struct scmd_priv { - * @logdata_buf: Circular buffer to store log data entries - * @logdata_buf_idx: Index of entry in buffer to store - * @logdata_entry_sz: log data entry size -+ * @adm_req_q_bar_writeq_lock: Admin request queue lock -+ * @adm_reply_q_bar_writeq_lock: Admin reply queue lock - * @pend_large_data_sz: Counter to track pending large data - * @io_throttle_data_length: I/O size to track in 512b blocks - * @io_throttle_high: I/O size to start throttle in 512b blocks -@@ -1185,7 +1187,7 @@ struct mpi3mr_ioc { - char name[MPI3MR_NAME_LENGTH]; - char driver_name[MPI3MR_NAME_LENGTH]; - -- volatile struct mpi3_sysif_registers __iomem *sysif_regs; -+ struct mpi3_sysif_registers __iomem *sysif_regs; - resource_size_t sysif_regs_phys; - int bars; - u64 dma_mask; -@@ -1339,6 +1341,8 @@ struct mpi3mr_ioc { - u8 *logdata_buf; - u16 logdata_buf_idx; - u16 logdata_entry_sz; -+ spinlock_t adm_req_q_bar_writeq_lock; -+ spinlock_t adm_reply_q_bar_writeq_lock; - - atomic_t pend_large_data_sz; - u32 io_throttle_data_length; -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/mpi3mr/mpi3mr_os.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/mpi3mr/mpi3mr_os.c ---- BPI-Router-Linux-kernel/drivers/scsi/mpi3mr/mpi3mr_os.c 2025-10-22 13:53:23.451327995 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/mpi3mr/mpi3mr_os.c 2025-10-22 13:53:56.659168447 -0400 -@@ -49,6 +49,13 @@ static void mpi3mr_send_event_ack(struct - - #define MPI3_EVENT_WAIT_FOR_DEVICES_TO_REFRESH (0xFFFE) - -+/* -+ * SAS Log info code for a NCQ collateral abort after an NCQ error: -+ * IOC_LOGINFO_PREFIX_PL | PL_LOGINFO_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR -+ * See: drivers/message/fusion/lsi/mpi_log_sas.h -+ */ -+#define IOC_LOGINFO_SATA_NCQ_FAIL_AFTER_ERR 0x31080000 -+ - /** - * mpi3mr_host_tag_for_scmd - Get host tag for a scmd - * @mrioc: Adapter instance reference -@@ -3430,7 +3437,18 @@ void mpi3mr_process_op_reply_desc(struct - scmd->result = DID_NO_CONNECT << 16; - break; - case MPI3_IOCSTATUS_SCSI_IOC_TERMINATED: -- scmd->result = DID_SOFT_ERROR << 16; -+ if (ioc_loginfo == IOC_LOGINFO_SATA_NCQ_FAIL_AFTER_ERR) { -+ /* -+ * This is a ATA NCQ command aborted due to another NCQ -+ * command failure. We must retry this command -+ * immediately but without incrementing its retry -+ * counter. -+ */ -+ WARN_ON_ONCE(xfer_count != 0); -+ scmd->result = DID_IMM_RETRY << 16; -+ } else { -+ scmd->result = DID_SOFT_ERROR << 16; -+ } - break; - case MPI3_IOCSTATUS_SCSI_TASK_TERMINATED: - case MPI3_IOCSTATUS_SCSI_EXT_TERMINATED: -@@ -5365,6 +5383,8 @@ mpi3mr_probe(struct pci_dev *pdev, const - spin_lock_init(&mrioc->tgtdev_lock); - spin_lock_init(&mrioc->watchdog_lock); - spin_lock_init(&mrioc->chain_buf_lock); -+ spin_lock_init(&mrioc->adm_req_q_bar_writeq_lock); -+ spin_lock_init(&mrioc->adm_reply_q_bar_writeq_lock); - spin_lock_init(&mrioc->sas_node_lock); - spin_lock_init(&mrioc->trigger_lock); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/mpt3sas/mpt3sas_scsih.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/mpt3sas/mpt3sas_scsih.c ---- BPI-Router-Linux-kernel/drivers/scsi/mpt3sas/mpt3sas_scsih.c 2025-10-22 13:53:23.451327995 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/mpt3sas/mpt3sas_scsih.c 2025-10-22 13:53:56.659168447 -0400 -@@ -195,6 +195,14 @@ struct sense_info { - #define MPT3SAS_PORT_ENABLE_COMPLETE (0xFFFD) - #define MPT3SAS_ABRT_TASK_SET (0xFFFE) - #define MPT3SAS_REMOVE_UNRESPONDING_DEVICES (0xFFFF) -+ -+/* -+ * SAS Log info code for a NCQ collateral abort after an NCQ error: -+ * IOC_LOGINFO_PREFIX_PL | PL_LOGINFO_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR -+ * See: drivers/message/fusion/lsi/mpi_log_sas.h -+ */ -+#define IOC_LOGINFO_SATA_NCQ_FAIL_AFTER_ERR 0x31080000 -+ - /** - * struct fw_event_work - firmware event struct - * @list: link list framework -@@ -5814,6 +5822,17 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *i - scmd->result = DID_TRANSPORT_DISRUPTED << 16; - goto out; - } -+ if (log_info == IOC_LOGINFO_SATA_NCQ_FAIL_AFTER_ERR) { -+ /* -+ * This is a ATA NCQ command aborted due to another NCQ -+ * command failure. We must retry this command -+ * immediately but without incrementing its retry -+ * counter. -+ */ -+ WARN_ON_ONCE(xfer_cnt != 0); -+ scmd->result = DID_IMM_RETRY << 16; -+ break; -+ } - if (log_info == 0x31110630) { - if (scmd->retries > 2) { - scmd->result = DID_NO_CONNECT << 16; -@@ -10790,8 +10809,7 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER - break; - case MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST: - _scsih_pcie_topology_change_event(ioc, fw_event); -- ioc->current_event = NULL; -- return; -+ break; - } - out: - fw_event_work_put(fw_event); -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/mvsas/mv_defs.h BPI-Router-Linux-kernel-6.16.12/drivers/scsi/mvsas/mv_defs.h ---- BPI-Router-Linux-kernel/drivers/scsi/mvsas/mv_defs.h 2025-10-22 13:53:23.451327995 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/mvsas/mv_defs.h 2025-10-22 13:53:56.659168447 -0400 -@@ -215,7 +215,7 @@ enum hw_register_bits { - - /* MVS_Px_INT_STAT, MVS_Px_INT_MASK (per-phy events) */ - PHYEV_DEC_ERR = (1U << 24), /* Phy Decoding Error */ -- PHYEV_DCDR_ERR = (1U << 23), /* STP Deocder Error */ -+ PHYEV_DCDR_ERR = (1U << 23), /* STP Decoder Error */ - PHYEV_CRC_ERR = (1U << 22), /* STP CRC Error */ - PHYEV_UNASSOC_FIS = (1U << 19), /* unassociated FIS rx'd */ - PHYEV_AN = (1U << 18), /* SATA async notification */ -@@ -347,7 +347,7 @@ enum sas_cmd_port_registers { - CMD_SATA_PORT_MEM_CTL0 = 0x158, /* SATA Port Memory Control 0 */ - CMD_SATA_PORT_MEM_CTL1 = 0x15c, /* SATA Port Memory Control 1 */ - CMD_XOR_MEM_BIST_CTL = 0x160, /* XOR Memory BIST Control */ -- CMD_XOR_MEM_BIST_STAT = 0x164, /* XOR Memroy BIST Status */ -+ CMD_XOR_MEM_BIST_STAT = 0x164, /* XOR Memory BIST Status */ - CMD_DMA_MEM_BIST_CTL = 0x168, /* DMA Memory BIST Control */ - CMD_DMA_MEM_BIST_STAT = 0x16c, /* DMA Memory BIST Status */ - CMD_PORT_MEM_BIST_CTL = 0x170, /* Port Memory BIST Control */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/mvsas/mv_sas.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/mvsas/mv_sas.c ---- BPI-Router-Linux-kernel/drivers/scsi/mvsas/mv_sas.c 2025-10-22 13:53:23.451327995 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/mvsas/mv_sas.c 2025-10-22 13:53:56.659168447 -0400 -@@ -818,7 +818,7 @@ err_out: - dev_printk(KERN_ERR, mvi->dev, "mvsas prep failed[%d]!\n", rc); - if (!sas_protocol_ata(task->task_proto)) - if (n_elem) -- dma_unmap_sg(mvi->dev, task->scatter, n_elem, -+ dma_unmap_sg(mvi->dev, task->scatter, task->num_scatter, - task->data_dir); - prep_out: - return rc; -@@ -864,7 +864,7 @@ static void mvs_slot_task_free(struct mv - if (!sas_protocol_ata(task->task_proto)) - if (slot->n_elem) - dma_unmap_sg(mvi->dev, task->scatter, -- slot->n_elem, task->data_dir); -+ task->num_scatter, task->data_dir); - - switch (task->task_proto) { - case SAS_PROTOCOL_SMP: -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/pm8001/pm80xx_hwi.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/pm8001/pm80xx_hwi.c ---- BPI-Router-Linux-kernel/drivers/scsi/pm8001/pm80xx_hwi.c 2025-10-22 13:53:23.451327995 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/pm8001/pm80xx_hwi.c 2025-10-22 13:53:56.659168447 -0400 -@@ -4677,8 +4677,12 @@ pm80xx_chip_phy_start_req(struct pm8001_ - &pm8001_ha->phy[phy_id].dev_sas_addr, SAS_ADDR_SIZE); - payload.sas_identify.phy_id = phy_id; - -- return pm8001_mpi_build_cmd(pm8001_ha, 0, opcode, &payload, -+ ret = pm8001_mpi_build_cmd(pm8001_ha, 0, opcode, &payload, - sizeof(payload), 0); -+ if (ret < 0) -+ pm8001_tag_free(pm8001_ha, tag); -+ -+ return ret; - } - - /** -@@ -4704,8 +4708,12 @@ static int pm80xx_chip_phy_stop_req(stru - payload.tag = cpu_to_le32(tag); - payload.phy_id = cpu_to_le32(phy_id); - -- return pm8001_mpi_build_cmd(pm8001_ha, 0, opcode, &payload, -+ ret = pm8001_mpi_build_cmd(pm8001_ha, 0, opcode, &payload, - sizeof(payload), 0); -+ if (ret < 0) -+ pm8001_tag_free(pm8001_ha, tag); -+ -+ return ret; - } - - /* -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/qla2xxx/qla_mbx.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/qla2xxx/qla_mbx.c ---- BPI-Router-Linux-kernel/drivers/scsi/qla2xxx/qla_mbx.c 2025-10-22 13:53:23.455327976 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/qla2xxx/qla_mbx.c 2025-10-22 13:53:56.659168447 -0400 -@@ -2147,7 +2147,7 @@ qla24xx_get_port_database(scsi_qla_host_ - - pdb_dma = dma_map_single(&vha->hw->pdev->dev, pdb, - sizeof(*pdb), DMA_FROM_DEVICE); -- if (!pdb_dma) { -+ if (dma_mapping_error(&vha->hw->pdev->dev, pdb_dma)) { - ql_log(ql_log_warn, vha, 0x1116, "Failed to map dma buffer.\n"); - return QLA_MEMORY_ALLOC_FAILED; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/qla4xxx/ql4_os.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/qla4xxx/ql4_os.c ---- BPI-Router-Linux-kernel/drivers/scsi/qla4xxx/ql4_os.c 2025-10-22 13:53:23.455327976 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/qla4xxx/ql4_os.c 2025-10-22 13:53:56.663168428 -0400 -@@ -3420,6 +3420,8 @@ static int qla4xxx_alloc_pdu(struct iscs - task_data->data_dma = dma_map_single(&ha->pdev->dev, task->data, - task->data_count, - DMA_TO_DEVICE); -+ if (dma_mapping_error(&ha->pdev->dev, task_data->data_dma)) -+ return -ENOMEM; - } - - DEBUG2(ql4_printk(KERN_INFO, ha, "%s: MaxRecvLen %u, iscsi hrd %d\n", -@@ -6604,6 +6606,8 @@ static struct iscsi_endpoint *qla4xxx_ge - - ep = qla4xxx_ep_connect(ha->host, (struct sockaddr *)dst_addr, 0); - vfree(dst_addr); -+ if (IS_ERR(ep)) -+ return NULL; - return ep; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/scsi.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/scsi.c ---- BPI-Router-Linux-kernel/drivers/scsi/scsi.c 2025-10-22 13:53:23.455327976 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/scsi.c 2025-10-22 13:53:56.663168428 -0400 -@@ -242,9 +242,11 @@ EXPORT_SYMBOL(scsi_change_queue_depth); - * specific SCSI device to determine if and when there is a - * need to adjust the queue depth on the device. - * -- * Returns: 0 - No change needed, >0 - Adjust queue depth to this new depth, -- * -1 - Drop back to untagged operation using host->cmd_per_lun -- * as the untagged command depth -+ * Returns: -+ * * 0 - No change needed -+ * * >0 - Adjust queue depth to this new depth, -+ * * -1 - Drop back to untagged operation using host->cmd_per_lun as the -+ * untagged command depth - * - * Lock Status: None held on entry - * -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/scsi_error.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/scsi_error.c ---- BPI-Router-Linux-kernel/drivers/scsi/scsi_error.c 2025-10-22 13:53:23.455327976 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/scsi_error.c 2025-10-22 13:53:56.663168428 -0400 -@@ -665,7 +665,8 @@ enum scsi_disposition scsi_check_sense(s - * if the device is in the process of becoming ready, we - * should retry. - */ -- if ((sshdr.asc == 0x04) && (sshdr.ascq == 0x01)) -+ if ((sshdr.asc == 0x04) && -+ (sshdr.ascq == 0x01 || sshdr.ascq == 0x0a)) - return NEEDS_RETRY; - /* - * if the device is not started, we need to wake -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/scsi_scan.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/scsi_scan.c ---- BPI-Router-Linux-kernel/drivers/scsi/scsi_scan.c 2025-10-22 13:53:23.455327976 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/scsi_scan.c 2025-10-22 13:53:56.663168428 -0400 -@@ -1899,7 +1899,7 @@ int scsi_scan_host_selected(struct Scsi_ - - return 0; - } -- -+EXPORT_SYMBOL(scsi_scan_host_selected); - static void scsi_sysfs_add_devices(struct Scsi_Host *shost) - { - struct scsi_device *sdev; -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/scsi_sysfs.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/scsi_sysfs.c ---- BPI-Router-Linux-kernel/drivers/scsi/scsi_sysfs.c 2025-10-22 13:53:23.455327976 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/scsi_sysfs.c 2025-10-22 13:53:56.663168428 -0400 -@@ -265,7 +265,7 @@ show_shost_supported_mode(struct device - return show_shost_mode(supported_mode, buf); - } - --static DEVICE_ATTR(supported_mode, S_IRUGO | S_IWUSR, show_shost_supported_mode, NULL); -+static DEVICE_ATTR(supported_mode, S_IRUGO, show_shost_supported_mode, NULL); - - static ssize_t - show_shost_active_mode(struct device *dev, -@@ -279,7 +279,7 @@ show_shost_active_mode(struct device *de - return show_shost_mode(shost->active_mode, buf); - } - --static DEVICE_ATTR(active_mode, S_IRUGO | S_IWUSR, show_shost_active_mode, NULL); -+static DEVICE_ATTR(active_mode, S_IRUGO, show_shost_active_mode, NULL); - - static int check_reset_type(const char *str) - { -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/scsi_transport_iscsi.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/scsi_transport_iscsi.c ---- BPI-Router-Linux-kernel/drivers/scsi/scsi_transport_iscsi.c 2025-10-22 13:53:23.455327976 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/scsi_transport_iscsi.c 2025-10-22 13:53:56.663168428 -0400 -@@ -2143,6 +2143,8 @@ static int iscsi_iter_destroy_conn_fn(st - return 0; - - iscsi_remove_conn(iscsi_dev_to_conn(dev)); -+ iscsi_put_conn(iscsi_dev_to_conn(dev)); -+ - return 0; - } - -@@ -3499,7 +3501,7 @@ static int iscsi_new_flashnode(struct is - pr_err("%s could not find host no %u\n", - __func__, ev->u.new_flashnode.host_no); - err = -ENODEV; -- goto put_host; -+ goto exit_new_fnode; - } - - index = transport->new_flashnode(shost, data, len); -@@ -3509,7 +3511,6 @@ static int iscsi_new_flashnode(struct is - else - err = -EIO; - --put_host: - scsi_host_put(shost); - - exit_new_fnode: -@@ -3534,7 +3535,7 @@ static int iscsi_del_flashnode(struct is - pr_err("%s could not find host no %u\n", - __func__, ev->u.del_flashnode.host_no); - err = -ENODEV; -- goto put_host; -+ goto exit_del_fnode; - } - - idx = ev->u.del_flashnode.flashnode_idx; -@@ -3576,7 +3577,7 @@ static int iscsi_login_flashnode(struct - pr_err("%s could not find host no %u\n", - __func__, ev->u.login_flashnode.host_no); - err = -ENODEV; -- goto put_host; -+ goto exit_login_fnode; - } - - idx = ev->u.login_flashnode.flashnode_idx; -@@ -3628,7 +3629,7 @@ static int iscsi_logout_flashnode(struct - pr_err("%s could not find host no %u\n", - __func__, ev->u.logout_flashnode.host_no); - err = -ENODEV; -- goto put_host; -+ goto exit_logout_fnode; - } - - idx = ev->u.logout_flashnode.flashnode_idx; -@@ -3678,7 +3679,7 @@ static int iscsi_logout_flashnode_sid(st - pr_err("%s could not find host no %u\n", - __func__, ev->u.logout_flashnode.host_no); - err = -ENODEV; -- goto put_host; -+ goto exit_logout_sid; - } - - session = iscsi_session_lookup(ev->u.logout_flashnode_sid.sid); -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/scsi_transport_sas.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/scsi_transport_sas.c ---- BPI-Router-Linux-kernel/drivers/scsi/scsi_transport_sas.c 2025-10-22 13:53:23.455327976 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/scsi_transport_sas.c 2025-10-22 13:53:56.663168428 -0400 -@@ -40,6 +40,8 @@ - #include - - #include "scsi_sas_internal.h" -+#include "scsi_priv.h" -+ - struct sas_host_attrs { - struct list_head rphy_list; - struct mutex lock; -@@ -1683,32 +1685,66 @@ int scsi_is_sas_rphy(const struct device - } - EXPORT_SYMBOL(scsi_is_sas_rphy); - -- --/* -- * SCSI scan helper -- */ -- --static int sas_user_scan(struct Scsi_Host *shost, uint channel, -- uint id, u64 lun) -+static void scan_channel_zero(struct Scsi_Host *shost, uint id, u64 lun) - { - struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); - struct sas_rphy *rphy; - -- mutex_lock(&sas_host->lock); - list_for_each_entry(rphy, &sas_host->rphy_list, list) { - if (rphy->identify.device_type != SAS_END_DEVICE || - rphy->scsi_target_id == -1) - continue; - -- if ((channel == SCAN_WILD_CARD || channel == 0) && -- (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) { -+ if (id == SCAN_WILD_CARD || id == rphy->scsi_target_id) { - scsi_scan_target(&rphy->dev, 0, rphy->scsi_target_id, - lun, SCSI_SCAN_MANUAL); - } - } -- mutex_unlock(&sas_host->lock); -+} - -- return 0; -+/* -+ * SCSI scan helper -+ */ -+ -+static int sas_user_scan(struct Scsi_Host *shost, uint channel, -+ uint id, u64 lun) -+{ -+ struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); -+ int res = 0; -+ int i; -+ -+ switch (channel) { -+ case 0: -+ mutex_lock(&sas_host->lock); -+ scan_channel_zero(shost, id, lun); -+ mutex_unlock(&sas_host->lock); -+ break; -+ -+ case SCAN_WILD_CARD: -+ mutex_lock(&sas_host->lock); -+ scan_channel_zero(shost, id, lun); -+ mutex_unlock(&sas_host->lock); -+ -+ for (i = 1; i <= shost->max_channel; i++) { -+ res = scsi_scan_host_selected(shost, i, id, lun, -+ SCSI_SCAN_MANUAL); -+ if (res) -+ goto exit_scan; -+ } -+ break; -+ -+ default: -+ if (channel < shost->max_channel) { -+ res = scsi_scan_host_selected(shost, channel, id, lun, -+ SCSI_SCAN_MANUAL); -+ } else { -+ res = -EINVAL; -+ } -+ break; -+ } -+ -+exit_scan: -+ return res; - } - - -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/sd.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/sd.c ---- BPI-Router-Linux-kernel/drivers/scsi/sd.c 2025-10-22 13:53:23.455327976 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/sd.c 2025-10-22 13:53:56.663168428 -0400 -@@ -3384,7 +3384,7 @@ static void sd_read_block_limits_ext(str - - rcu_read_lock(); - vpd = rcu_dereference(sdkp->device->vpd_pgb7); -- if (vpd && vpd->len >= 2) -+ if (vpd && vpd->len >= 6) - sdkp->rscs = vpd->data[5] & 1; - rcu_read_unlock(); - } -@@ -4173,7 +4173,9 @@ static void sd_shutdown(struct device *d - if ((system_state != SYSTEM_RESTART && - sdkp->device->manage_system_start_stop) || - (system_state == SYSTEM_POWER_OFF && -- sdkp->device->manage_shutdown)) { -+ sdkp->device->manage_shutdown) || -+ (system_state == SYSTEM_RUNNING && -+ sdkp->device->manage_runtime_start_stop)) { - sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n"); - sd_start_stop_device(sdkp, 0); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/sr.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/sr.c ---- BPI-Router-Linux-kernel/drivers/scsi/sr.c 2025-10-22 13:53:23.455327976 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/sr.c 2025-10-22 13:53:56.663168428 -0400 -@@ -475,13 +475,21 @@ static blk_status_t sr_init_command(stru - - static int sr_revalidate_disk(struct scsi_cd *cd) - { -+ struct request_queue *q = cd->device->request_queue; - struct scsi_sense_hdr sshdr; -+ struct queue_limits lim; -+ int sector_size; - - /* if the unit is not ready, nothing more to do */ - if (scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr)) - return 0; - sr_cd_check(&cd->cdi); -- return get_sectorsize(cd); -+ sector_size = get_sectorsize(cd); -+ -+ lim = queue_limits_start_update(q); -+ lim.logical_block_size = sector_size; -+ lim.features |= BLK_FEAT_ROTATIONAL; -+ return queue_limits_commit_update_frozen(q, &lim); - } - - static int sr_block_open(struct gendisk *disk, blk_mode_t mode) -@@ -721,10 +729,8 @@ fail: - - static int get_sectorsize(struct scsi_cd *cd) - { -- struct request_queue *q = cd->device->request_queue; - static const u8 cmd[10] = { READ_CAPACITY }; - unsigned char buffer[8] = { }; -- struct queue_limits lim; - int err; - int sector_size; - struct scsi_failure failure_defs[] = { -@@ -795,9 +801,7 @@ static int get_sectorsize(struct scsi_cd - set_capacity(cd->disk, cd->capacity); - } - -- lim = queue_limits_start_update(q); -- lim.logical_block_size = sector_size; -- return queue_limits_commit_update_frozen(q, &lim); -+ return sector_size; - } - - static int get_capabilities(struct scsi_cd *cd) -diff -purNx .git BPI-Router-Linux-kernel/drivers/scsi/storvsc_drv.c BPI-Router-Linux-kernel-6.16.12/drivers/scsi/storvsc_drv.c ---- BPI-Router-Linux-kernel/drivers/scsi/storvsc_drv.c 2025-10-22 13:53:23.455327976 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/scsi/storvsc_drv.c 2025-10-22 13:53:56.663168428 -0400 -@@ -362,7 +362,7 @@ MODULE_PARM_DESC(ring_avail_percent_lowa - /* - * Timeout in seconds for all devices managed by this driver. - */ --static int storvsc_timeout = 180; -+static const int storvsc_timeout = 180; - - #if IS_ENABLED(CONFIG_SCSI_FC_ATTRS) - static struct scsi_transport_template *fc_transport_template; -@@ -768,7 +768,7 @@ static void handle_multichannel_storage - return; - } - -- t = wait_for_completion_timeout(&request->wait_event, 10*HZ); -+ t = wait_for_completion_timeout(&request->wait_event, storvsc_timeout * HZ); - if (t == 0) { - dev_err(dev, "Failed to create sub-channel: timed out\n"); - return; -@@ -833,7 +833,7 @@ static int storvsc_execute_vstor_op(stru - if (ret != 0) - return ret; - -- t = wait_for_completion_timeout(&request->wait_event, 5*HZ); -+ t = wait_for_completion_timeout(&request->wait_event, storvsc_timeout * HZ); - if (t == 0) - return -ETIMEDOUT; - -@@ -1350,6 +1350,8 @@ static int storvsc_connect_to_vsp(struct - return ret; - - ret = storvsc_channel_init(device, is_fc); -+ if (ret) -+ vmbus_close(device->channel); - - return ret; - } -@@ -1668,7 +1670,7 @@ static int storvsc_host_reset_handler(st - if (ret != 0) - return FAILED; - -- t = wait_for_completion_timeout(&request->wait_event, 5*HZ); -+ t = wait_for_completion_timeout(&request->wait_event, storvsc_timeout * HZ); - if (t == 0) - return TIMEOUT_ERROR; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/soc/aspeed/aspeed-lpc-snoop.c BPI-Router-Linux-kernel-6.16.12/drivers/soc/aspeed/aspeed-lpc-snoop.c ---- BPI-Router-Linux-kernel/drivers/soc/aspeed/aspeed-lpc-snoop.c 2025-10-22 13:53:23.455327976 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/soc/aspeed/aspeed-lpc-snoop.c 2025-10-22 13:53:56.663168428 -0400 -@@ -58,6 +58,7 @@ struct aspeed_lpc_snoop_model_data { - }; - - struct aspeed_lpc_snoop_channel { -+ bool enabled; - struct kfifo fifo; - wait_queue_head_t wq; - struct miscdevice miscdev; -@@ -190,6 +191,9 @@ static int aspeed_lpc_enable_snoop(struc - const struct aspeed_lpc_snoop_model_data *model_data = - of_device_get_match_data(dev); - -+ if (WARN_ON(lpc_snoop->chan[channel].enabled)) -+ return -EBUSY; -+ - init_waitqueue_head(&lpc_snoop->chan[channel].wq); - /* Create FIFO datastructure */ - rc = kfifo_alloc(&lpc_snoop->chan[channel].fifo, -@@ -236,6 +240,8 @@ static int aspeed_lpc_enable_snoop(struc - regmap_update_bits(lpc_snoop->regmap, HICRB, - hicrb_en, hicrb_en); - -+ lpc_snoop->chan[channel].enabled = true; -+ - return 0; - - err_misc_deregister: -@@ -248,6 +254,9 @@ err_free_fifo: - static void aspeed_lpc_disable_snoop(struct aspeed_lpc_snoop *lpc_snoop, - int channel) - { -+ if (!lpc_snoop->chan[channel].enabled) -+ return; -+ - switch (channel) { - case 0: - regmap_update_bits(lpc_snoop->regmap, HICR5, -@@ -263,8 +272,10 @@ static void aspeed_lpc_disable_snoop(str - return; - } - -- kfifo_free(&lpc_snoop->chan[channel].fifo); -+ lpc_snoop->chan[channel].enabled = false; -+ /* Consider improving safety wrt concurrent reader(s) */ - misc_deregister(&lpc_snoop->chan[channel].miscdev); -+ kfifo_free(&lpc_snoop->chan[channel].fifo); - } - - static int aspeed_lpc_snoop_probe(struct platform_device *pdev) -diff -purNx .git BPI-Router-Linux-kernel/drivers/soc/qcom/mdt_loader.c BPI-Router-Linux-kernel-6.16.12/drivers/soc/qcom/mdt_loader.c ---- BPI-Router-Linux-kernel/drivers/soc/qcom/mdt_loader.c 2025-10-22 13:53:23.455327976 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/soc/qcom/mdt_loader.c 2025-10-22 13:53:56.663168428 -0400 -@@ -18,6 +18,39 @@ - #include - #include - -+static bool mdt_header_valid(const struct firmware *fw) -+{ -+ const struct elf32_hdr *ehdr; -+ size_t phend; -+ size_t shend; -+ -+ if (fw->size < sizeof(*ehdr)) -+ return false; -+ -+ ehdr = (struct elf32_hdr *)fw->data; -+ -+ if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) -+ return false; -+ -+ if (ehdr->e_phentsize != sizeof(struct elf32_phdr)) -+ return false; -+ -+ phend = size_add(size_mul(sizeof(struct elf32_phdr), ehdr->e_phnum), ehdr->e_phoff); -+ if (phend > fw->size) -+ return false; -+ -+ if (ehdr->e_shentsize || ehdr->e_shnum) { -+ if (ehdr->e_shentsize != sizeof(struct elf32_shdr)) -+ return false; -+ -+ shend = size_add(size_mul(sizeof(struct elf32_shdr), ehdr->e_shnum), ehdr->e_shoff); -+ if (shend > fw->size) -+ return false; -+ } -+ -+ return true; -+} -+ - static bool mdt_phdr_valid(const struct elf32_phdr *phdr) - { - if (phdr->p_type != PT_LOAD) -@@ -82,8 +115,11 @@ ssize_t qcom_mdt_get_size(const struct f - phys_addr_t max_addr = 0; - int i; - -+ if (!mdt_header_valid(fw)) -+ return -EINVAL; -+ - ehdr = (struct elf32_hdr *)fw->data; -- phdrs = (struct elf32_phdr *)(ehdr + 1); -+ phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff); - - for (i = 0; i < ehdr->e_phnum; i++) { - phdr = &phdrs[i]; -@@ -134,8 +170,11 @@ void *qcom_mdt_read_metadata(const struc - ssize_t ret; - void *data; - -+ if (!mdt_header_valid(fw)) -+ return ERR_PTR(-EINVAL); -+ - ehdr = (struct elf32_hdr *)fw->data; -- phdrs = (struct elf32_phdr *)(ehdr + 1); -+ phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff); - - if (ehdr->e_phnum < 2) - return ERR_PTR(-EINVAL); -@@ -214,8 +253,11 @@ int qcom_mdt_pas_init(struct device *dev - int ret; - int i; - -+ if (!mdt_header_valid(fw)) -+ return -EINVAL; -+ - ehdr = (struct elf32_hdr *)fw->data; -- phdrs = (struct elf32_phdr *)(ehdr + 1); -+ phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff); - - for (i = 0; i < ehdr->e_phnum; i++) { - phdr = &phdrs[i]; -@@ -270,7 +312,7 @@ static bool qcom_mdt_bins_are_split(cons - int i; - - ehdr = (struct elf32_hdr *)fw->data; -- phdrs = (struct elf32_phdr *)(ehdr + 1); -+ phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff); - - for (i = 0; i < ehdr->e_phnum; i++) { - /* -@@ -310,9 +352,12 @@ static int __qcom_mdt_load(struct device - if (!fw || !mem_region || !mem_phys || !mem_size) - return -EINVAL; - -+ if (!mdt_header_valid(fw)) -+ return -EINVAL; -+ - is_split = qcom_mdt_bins_are_split(fw, fw_name); - ehdr = (struct elf32_hdr *)fw->data; -- phdrs = (struct elf32_phdr *)(ehdr + 1); -+ phdrs = (struct elf32_phdr *)(fw->data + ehdr->e_phoff); - - for (i = 0; i < ehdr->e_phnum; i++) { - phdr = &phdrs[i]; -diff -purNx .git BPI-Router-Linux-kernel/drivers/soc/qcom/pmic_glink.c BPI-Router-Linux-kernel-6.16.12/drivers/soc/qcom/pmic_glink.c ---- BPI-Router-Linux-kernel/drivers/soc/qcom/pmic_glink.c 2025-10-22 13:53:23.455327976 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/soc/qcom/pmic_glink.c 2025-10-22 13:53:56.663168428 -0400 -@@ -167,7 +167,10 @@ static int pmic_glink_rpmsg_callback(str - return 0; - } - --static void pmic_glink_aux_release(struct device *dev) {} -+static void pmic_glink_aux_release(struct device *dev) -+{ -+ of_node_put(dev->of_node); -+} - - static int pmic_glink_add_aux_device(struct pmic_glink *pg, - struct auxiliary_device *aux, -@@ -181,8 +184,10 @@ static int pmic_glink_add_aux_device(str - aux->dev.release = pmic_glink_aux_release; - device_set_of_node_from_dev(&aux->dev, parent); - ret = auxiliary_device_init(aux); -- if (ret) -+ if (ret) { -+ of_node_put(aux->dev.of_node); - return ret; -+ } - - ret = auxiliary_device_add(aux); - if (ret) -diff -purNx .git BPI-Router-Linux-kernel/drivers/soc/qcom/qmi_encdec.c BPI-Router-Linux-kernel-6.16.12/drivers/soc/qcom/qmi_encdec.c ---- BPI-Router-Linux-kernel/drivers/soc/qcom/qmi_encdec.c 2025-10-22 13:53:23.455327976 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/soc/qcom/qmi_encdec.c 2025-10-22 13:53:56.663168428 -0400 -@@ -304,6 +304,8 @@ static int qmi_encode(const struct qmi_e - const void *buf_src; - int encode_tlv = 0; - int rc; -+ u8 val8; -+ u16 val16; - - if (!ei_array) - return 0; -@@ -338,7 +340,6 @@ static int qmi_encode(const struct qmi_e - break; - - case QMI_DATA_LEN: -- memcpy(&data_len_value, buf_src, temp_ei->elem_size); - data_len_sz = temp_ei->elem_size == sizeof(u8) ? - sizeof(u8) : sizeof(u16); - /* Check to avoid out of range buffer access */ -@@ -348,8 +349,17 @@ static int qmi_encode(const struct qmi_e - __func__); - return -ETOOSMALL; - } -- rc = qmi_encode_basic_elem(buf_dst, &data_len_value, -- 1, data_len_sz); -+ if (data_len_sz == sizeof(u8)) { -+ val8 = *(u8 *)buf_src; -+ data_len_value = (u32)val8; -+ rc = qmi_encode_basic_elem(buf_dst, &val8, -+ 1, data_len_sz); -+ } else { -+ val16 = *(u16 *)buf_src; -+ data_len_value = (u32)le16_to_cpu(val16); -+ rc = qmi_encode_basic_elem(buf_dst, &val16, -+ 1, data_len_sz); -+ } - UPDATE_ENCODE_VARIABLES(temp_ei, buf_dst, - encoded_bytes, tlv_len, - encode_tlv, rc); -@@ -523,14 +533,23 @@ static int qmi_decode_string_elem(const - u32 string_len = 0; - u32 string_len_sz = 0; - const struct qmi_elem_info *temp_ei = ei_array; -+ u8 val8; -+ u16 val16; - - if (dec_level == 1) { - string_len = tlv_len; - } else { - string_len_sz = temp_ei->elem_len <= U8_MAX ? - sizeof(u8) : sizeof(u16); -- rc = qmi_decode_basic_elem(&string_len, buf_src, -- 1, string_len_sz); -+ if (string_len_sz == sizeof(u8)) { -+ rc = qmi_decode_basic_elem(&val8, buf_src, -+ 1, string_len_sz); -+ string_len = (u32)val8; -+ } else { -+ rc = qmi_decode_basic_elem(&val16, buf_src, -+ 1, string_len_sz); -+ string_len = (u32)val16; -+ } - decoded_bytes += rc; - } - -@@ -604,6 +623,9 @@ static int qmi_decode(const struct qmi_e - u32 decoded_bytes = 0; - const void *buf_src = in_buf; - int rc; -+ u8 val8; -+ u16 val16; -+ u32 val32; - - while (decoded_bytes < in_buf_len) { - if (dec_level >= 2 && temp_ei->data_type == QMI_EOTI) -@@ -642,9 +664,17 @@ static int qmi_decode(const struct qmi_e - if (temp_ei->data_type == QMI_DATA_LEN) { - data_len_sz = temp_ei->elem_size == sizeof(u8) ? - sizeof(u8) : sizeof(u16); -- rc = qmi_decode_basic_elem(&data_len_value, buf_src, -- 1, data_len_sz); -- memcpy(buf_dst, &data_len_value, sizeof(u32)); -+ if (data_len_sz == sizeof(u8)) { -+ rc = qmi_decode_basic_elem(&val8, buf_src, -+ 1, data_len_sz); -+ data_len_value = (u32)val8; -+ } else { -+ rc = qmi_decode_basic_elem(&val16, buf_src, -+ 1, data_len_sz); -+ data_len_value = (u32)val16; -+ } -+ val32 = cpu_to_le32(data_len_value); -+ memcpy(buf_dst, &val32, sizeof(u32)); - temp_ei = temp_ei + 1; - buf_dst = out_c_struct + temp_ei->offset; - tlv_len -= data_len_sz; -@@ -746,9 +776,9 @@ void *qmi_encode_message(int type, unsig - - hdr = msg; - hdr->type = type; -- hdr->txn_id = txn_id; -- hdr->msg_id = msg_id; -- hdr->msg_len = msglen; -+ hdr->txn_id = cpu_to_le16(txn_id); -+ hdr->msg_id = cpu_to_le16(msg_id); -+ hdr->msg_len = cpu_to_le16(msglen); - - *len = sizeof(*hdr) + msglen; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/soc/qcom/qmi_interface.c BPI-Router-Linux-kernel-6.16.12/drivers/soc/qcom/qmi_interface.c ---- BPI-Router-Linux-kernel/drivers/soc/qcom/qmi_interface.c 2025-10-22 13:53:23.455327976 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/soc/qcom/qmi_interface.c 2025-10-22 13:53:56.663168428 -0400 -@@ -400,7 +400,7 @@ static void qmi_invoke_handler(struct qm - - for (handler = qmi->handlers; handler->fn; handler++) { - if (handler->type == hdr->type && -- handler->msg_id == hdr->msg_id) -+ handler->msg_id == le16_to_cpu(hdr->msg_id)) - break; - } - -@@ -488,7 +488,7 @@ static void qmi_handle_message(struct qm - /* If this is a response, find the matching transaction handle */ - if (hdr->type == QMI_RESPONSE) { - mutex_lock(&qmi->txn_lock); -- txn = idr_find(&qmi->txns, hdr->txn_id); -+ txn = idr_find(&qmi->txns, le16_to_cpu(hdr->txn_id)); - - /* Ignore unexpected responses */ - if (!txn) { -@@ -514,7 +514,7 @@ static void qmi_handle_message(struct qm - } else { - /* Create a txn based on the txn_id of the incoming message */ - memset(&tmp_txn, 0, sizeof(tmp_txn)); -- tmp_txn.id = hdr->txn_id; -+ tmp_txn.id = le16_to_cpu(hdr->txn_id); - - qmi_invoke_handler(qmi, sq, &tmp_txn, buf, len); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/soc/qcom/rpmh-rsc.c BPI-Router-Linux-kernel-6.16.12/drivers/soc/qcom/rpmh-rsc.c ---- BPI-Router-Linux-kernel/drivers/soc/qcom/rpmh-rsc.c 2025-10-22 13:53:23.455327976 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/soc/qcom/rpmh-rsc.c 2025-10-22 13:53:56.663168428 -0400 -@@ -1072,7 +1072,7 @@ static int rpmh_rsc_probe(struct platfor - drv->ver.minor = rsc_id & (MINOR_VER_MASK << MINOR_VER_SHIFT); - drv->ver.minor >>= MINOR_VER_SHIFT; - -- if (drv->ver.major == 3) -+ if (drv->ver.major >= 3) - drv->regs = rpmh_rsc_reg_offset_ver_3_0; - else - drv->regs = rpmh_rsc_reg_offset_ver_2_7; -diff -purNx .git BPI-Router-Linux-kernel/drivers/soc/tegra/cbb/tegra234-cbb.c BPI-Router-Linux-kernel-6.16.12/drivers/soc/tegra/cbb/tegra234-cbb.c ---- BPI-Router-Linux-kernel/drivers/soc/tegra/cbb/tegra234-cbb.c 2025-10-22 13:53:23.455327976 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/soc/tegra/cbb/tegra234-cbb.c 2025-10-22 13:53:56.663168428 -0400 -@@ -185,6 +185,8 @@ static void tegra234_cbb_error_clear(str - { - struct tegra234_cbb *priv = to_tegra234_cbb(cbb); - -+ writel(0, priv->mon + FABRIC_MN_MASTER_ERR_FORCE_0); -+ - writel(0x3f, priv->mon + FABRIC_MN_MASTER_ERR_STATUS_0); - dsb(sy); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/soc/tegra/pmc.c BPI-Router-Linux-kernel-6.16.12/drivers/soc/tegra/pmc.c ---- BPI-Router-Linux-kernel/drivers/soc/tegra/pmc.c 2025-10-22 13:53:23.455327976 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/soc/tegra/pmc.c 2025-10-22 13:53:56.663168428 -0400 -@@ -1234,7 +1234,7 @@ err: - } - - static int tegra_powergate_of_get_resets(struct tegra_powergate *pg, -- struct device_node *np, bool off) -+ struct device_node *np) - { - struct device *dev = pg->pmc->dev; - int err; -@@ -1249,22 +1249,6 @@ static int tegra_powergate_of_get_resets - err = reset_control_acquire(pg->reset); - if (err < 0) { - pr_err("failed to acquire resets: %d\n", err); -- goto out; -- } -- -- if (off) { -- err = reset_control_assert(pg->reset); -- } else { -- err = reset_control_deassert(pg->reset); -- if (err < 0) -- goto out; -- -- reset_control_release(pg->reset); -- } -- --out: -- if (err) { -- reset_control_release(pg->reset); - reset_control_put(pg->reset); - } - -@@ -1309,20 +1293,43 @@ static int tegra_powergate_add(struct te - goto set_available; - } - -- err = tegra_powergate_of_get_resets(pg, np, off); -+ err = tegra_powergate_of_get_resets(pg, np); - if (err < 0) { - dev_err(dev, "failed to get resets for %pOFn: %d\n", np, err); - goto remove_clks; - } - -- if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) { -- if (off) -- WARN_ON(tegra_powergate_power_up(pg, true)); -+ /* -+ * If the power-domain is off, then ensure the resets are asserted. -+ * If the power-domain is on, then power down to ensure that when is -+ * it turned on the power-domain, clocks and resets are all in the -+ * expected state. -+ */ -+ if (off) { -+ err = reset_control_assert(pg->reset); -+ if (err) { -+ pr_err("failed to assert resets: %d\n", err); -+ goto remove_resets; -+ } -+ } else { -+ err = tegra_powergate_power_down(pg); -+ if (err) { -+ dev_err(dev, "failed to turn off PM domain %s: %d\n", -+ pg->genpd.name, err); -+ goto remove_resets; -+ } -+ } - -+ /* -+ * If PM_GENERIC_DOMAINS is not enabled, power-on -+ * the domain and skip the genpd registration. -+ */ -+ if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) { -+ WARN_ON(tegra_powergate_power_up(pg, true)); - goto remove_resets; - } - -- err = pm_genpd_init(&pg->genpd, NULL, off); -+ err = pm_genpd_init(&pg->genpd, NULL, true); - if (err < 0) { - dev_err(dev, "failed to initialise PM domain %pOFn: %d\n", np, - err); -diff -purNx .git BPI-Router-Linux-kernel/drivers/soundwire/amd_manager.c BPI-Router-Linux-kernel-6.16.12/drivers/soundwire/amd_manager.c ---- BPI-Router-Linux-kernel/drivers/soundwire/amd_manager.c 2025-10-22 13:53:23.455327976 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/soundwire/amd_manager.c 2025-10-22 13:53:56.663168428 -0400 -@@ -238,7 +238,7 @@ static u64 amd_sdw_send_cmd_get_resp(str - - if (sts & AMD_SDW_IMM_RES_VALID) { - dev_err(amd_manager->dev, "SDW%x manager is in bad state\n", amd_manager->instance); -- writel(0x00, amd_manager->mmio + ACP_SW_IMM_CMD_STS); -+ writel(AMD_SDW_IMM_RES_VALID, amd_manager->mmio + ACP_SW_IMM_CMD_STS); - } - writel(upper_data, amd_manager->mmio + ACP_SW_IMM_CMD_UPPER_WORD); - writel(lower_data, amd_manager->mmio + ACP_SW_IMM_CMD_LOWER_QWORD); -@@ -1074,6 +1074,7 @@ static void amd_sdw_manager_remove(struc - int ret; - - pm_runtime_disable(&pdev->dev); -+ cancel_work_sync(&amd_manager->amd_sdw_work); - amd_disable_sdw_interrupts(amd_manager); - sdw_bus_master_delete(&amd_manager->bus); - ret = amd_disable_sdw_manager(amd_manager); -@@ -1178,10 +1179,10 @@ static int __maybe_unused amd_pm_prepare - * device is not in runtime suspend state, observed that device alerts are missing - * without pm_prepare on AMD platforms in clockstop mode0. - */ -- if (amd_manager->power_mode_mask & AMD_SDW_CLK_STOP_MODE) { -- ret = pm_request_resume(dev); -+ if (amd_manager->power_mode_mask) { -+ ret = pm_runtime_resume(dev); - if (ret < 0) { -- dev_err(bus->dev, "pm_request_resume failed: %d\n", ret); -+ dev_err(bus->dev, "pm_runtime_resume failed: %d\n", ret); - return 0; - } - } -@@ -1209,6 +1210,7 @@ static int __maybe_unused amd_suspend(st - } - - if (amd_manager->power_mode_mask & AMD_SDW_CLK_STOP_MODE) { -+ cancel_work_sync(&amd_manager->amd_sdw_work); - amd_sdw_wake_enable(amd_manager, false); - if (amd_manager->acp_rev >= ACP70_PCI_REV_ID) { - ret = amd_sdw_host_wake_enable(amd_manager, false); -@@ -1219,6 +1221,7 @@ static int __maybe_unused amd_suspend(st - if (ret) - return ret; - } else if (amd_manager->power_mode_mask & AMD_SDW_POWER_OFF_MODE) { -+ cancel_work_sync(&amd_manager->amd_sdw_work); - amd_sdw_wake_enable(amd_manager, false); - if (amd_manager->acp_rev >= ACP70_PCI_REV_ID) { - ret = amd_sdw_host_wake_enable(amd_manager, false); -diff -purNx .git BPI-Router-Linux-kernel/drivers/soundwire/bus.c BPI-Router-Linux-kernel-6.16.12/drivers/soundwire/bus.c ---- BPI-Router-Linux-kernel/drivers/soundwire/bus.c 2025-10-22 13:53:23.455327976 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/soundwire/bus.c 2025-10-22 13:53:56.663168428 -0400 -@@ -1753,15 +1753,15 @@ static int sdw_handle_slave_alerts(struc - - /* Update the Slave driver */ - if (slave_notify) { -+ if (slave->prop.use_domain_irq && slave->irq) -+ handle_nested_irq(slave->irq); -+ - mutex_lock(&slave->sdw_dev_lock); - - if (slave->probed) { - struct device *dev = &slave->dev; - struct sdw_driver *drv = drv_to_sdw_driver(dev->driver); - -- if (slave->prop.use_domain_irq && slave->irq) -- handle_nested_irq(slave->irq); -- - if (drv->ops && drv->ops->interrupt_callback) { - slave_intr.sdca_cascade = sdca_cascade; - slave_intr.control_port = clear; -diff -purNx .git BPI-Router-Linux-kernel/drivers/soundwire/debugfs.c BPI-Router-Linux-kernel-6.16.12/drivers/soundwire/debugfs.c ---- BPI-Router-Linux-kernel/drivers/soundwire/debugfs.c 2025-10-22 13:53:23.455327976 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/soundwire/debugfs.c 2025-10-22 13:53:56.663168428 -0400 -@@ -291,6 +291,9 @@ static int cmd_go(void *data, u64 value) - - finish_t = ktime_get(); - -+ dev_dbg(&slave->dev, "command completed, num_byte %zu status %d, time %lld ms\n", -+ num_bytes, ret, div_u64(finish_t - start_t, NSEC_PER_MSEC)); -+ - out: - if (fw) - release_firmware(fw); -@@ -298,9 +301,6 @@ out: - pm_runtime_mark_last_busy(&slave->dev); - pm_runtime_put(&slave->dev); - -- dev_dbg(&slave->dev, "command completed, num_byte %zu status %d, time %lld ms\n", -- num_bytes, ret, div_u64(finish_t - start_t, NSEC_PER_MSEC)); -- - return ret; - } - DEFINE_DEBUGFS_ATTRIBUTE(cmd_go_fops, NULL, -diff -purNx .git BPI-Router-Linux-kernel/drivers/soundwire/mipi_disco.c BPI-Router-Linux-kernel-6.16.12/drivers/soundwire/mipi_disco.c ---- BPI-Router-Linux-kernel/drivers/soundwire/mipi_disco.c 2025-10-22 13:53:23.455327976 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/soundwire/mipi_disco.c 2025-10-22 13:53:56.663168428 -0400 -@@ -451,10 +451,10 @@ int sdw_slave_read_prop(struct sdw_slave - "mipi-sdw-highPHY-capable"); - - prop->paging_support = mipi_device_property_read_bool(dev, -- "mipi-sdw-paging-support"); -+ "mipi-sdw-paging-supported"); - - prop->bank_delay_support = mipi_device_property_read_bool(dev, -- "mipi-sdw-bank-delay-support"); -+ "mipi-sdw-bank-delay-supported"); - - device_property_read_u32(dev, - "mipi-sdw-port15-read-behavior", &prop->p15_behave); -diff -purNx .git BPI-Router-Linux-kernel/drivers/soundwire/qcom.c BPI-Router-Linux-kernel-6.16.12/drivers/soundwire/qcom.c ---- BPI-Router-Linux-kernel/drivers/soundwire/qcom.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/soundwire/qcom.c 2025-10-22 13:53:56.663168428 -0400 -@@ -156,7 +156,6 @@ struct qcom_swrm_port_config { - u8 word_length; - u8 blk_group_count; - u8 lane_control; -- u8 ch_mask; - }; - - /* -@@ -1049,13 +1048,9 @@ static int qcom_swrm_port_enable(struct - { - u32 reg = SWRM_DP_PORT_CTRL_BANK(enable_ch->port_num, bank); - struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus); -- struct qcom_swrm_port_config *pcfg; - u32 val; - -- pcfg = &ctrl->pconfig[enable_ch->port_num]; - ctrl->reg_read(ctrl, reg, &val); -- if (pcfg->ch_mask != SWR_INVALID_PARAM && pcfg->ch_mask != 0) -- enable_ch->ch_mask = pcfg->ch_mask; - - if (enable_ch->enable) - val |= (enable_ch->ch_mask << SWRM_DP_PORT_CTRL_EN_CHAN_SHFT); -@@ -1275,26 +1270,6 @@ static void *qcom_swrm_get_sdw_stream(st - return ctrl->sruntime[dai->id]; - } - --static int qcom_swrm_set_channel_map(struct snd_soc_dai *dai, -- unsigned int tx_num, const unsigned int *tx_slot, -- unsigned int rx_num, const unsigned int *rx_slot) --{ -- struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(dai->dev); -- int i; -- -- if (tx_slot) { -- for (i = 0; i < tx_num; i++) -- ctrl->pconfig[i].ch_mask = tx_slot[i]; -- } -- -- if (rx_slot) { -- for (i = 0; i < rx_num; i++) -- ctrl->pconfig[i].ch_mask = rx_slot[i]; -- } -- -- return 0; --} -- - static int qcom_swrm_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) - { -@@ -1331,7 +1306,6 @@ static const struct snd_soc_dai_ops qcom - .shutdown = qcom_swrm_shutdown, - .set_stream = qcom_swrm_set_sdw_stream, - .get_stream = qcom_swrm_get_sdw_stream, -- .set_channel_map = qcom_swrm_set_channel_map, - }; - - static const struct snd_soc_component_driver qcom_swrm_dai_component = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/soundwire/stream.c BPI-Router-Linux-kernel-6.16.12/drivers/soundwire/stream.c ---- BPI-Router-Linux-kernel/drivers/soundwire/stream.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/soundwire/stream.c 2025-10-22 13:53:56.663168428 -0400 -@@ -1510,7 +1510,7 @@ static int _sdw_prepare_stream(struct sd - if (ret < 0) { - dev_err(bus->dev, "Prepare port(s) failed ret = %d\n", - ret); -- return ret; -+ goto restore_params; - } - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/spi/spi.c BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi.c ---- BPI-Router-Linux-kernel/drivers/spi/spi.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi.c 2025-10-22 13:53:56.667168409 -0400 -@@ -4138,10 +4138,13 @@ static int __spi_validate(struct spi_dev - xfer->tx_nbits != SPI_NBITS_OCTAL) - return -EINVAL; - if ((xfer->tx_nbits == SPI_NBITS_DUAL) && -- !(spi->mode & (SPI_TX_DUAL | SPI_TX_QUAD))) -+ !(spi->mode & (SPI_TX_DUAL | SPI_TX_QUAD | SPI_TX_OCTAL))) - return -EINVAL; - if ((xfer->tx_nbits == SPI_NBITS_QUAD) && -- !(spi->mode & SPI_TX_QUAD)) -+ !(spi->mode & (SPI_TX_QUAD | SPI_TX_OCTAL))) -+ return -EINVAL; -+ if ((xfer->tx_nbits == SPI_NBITS_OCTAL) && -+ !(spi->mode & SPI_TX_OCTAL)) - return -EINVAL; - } - /* Check transfer rx_nbits */ -@@ -4154,10 +4157,13 @@ static int __spi_validate(struct spi_dev - xfer->rx_nbits != SPI_NBITS_OCTAL) - return -EINVAL; - if ((xfer->rx_nbits == SPI_NBITS_DUAL) && -- !(spi->mode & (SPI_RX_DUAL | SPI_RX_QUAD))) -+ !(spi->mode & (SPI_RX_DUAL | SPI_RX_QUAD | SPI_RX_OCTAL))) - return -EINVAL; - if ((xfer->rx_nbits == SPI_NBITS_QUAD) && -- !(spi->mode & SPI_RX_QUAD)) -+ !(spi->mode & (SPI_RX_QUAD | SPI_RX_OCTAL))) -+ return -EINVAL; -+ if ((xfer->rx_nbits == SPI_NBITS_OCTAL) && -+ !(spi->mode & SPI_RX_OCTAL)) - return -EINVAL; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/spi/spi-cadence-quadspi.c BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-cadence-quadspi.c ---- BPI-Router-Linux-kernel/drivers/spi/spi-cadence-quadspi.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-cadence-quadspi.c 2025-10-22 13:53:56.663168428 -0400 -@@ -46,6 +46,7 @@ static_assert(CQSPI_MAX_CHIPSELECT <= SP - #define CQSPI_DMA_SET_MASK BIT(7) - #define CQSPI_SUPPORT_DEVICE_RESET BIT(8) - #define CQSPI_DISABLE_STIG_MODE BIT(9) -+#define CQSPI_DISABLE_RUNTIME_PM BIT(10) - - /* Capabilities */ - #define CQSPI_SUPPORTS_OCTAL BIT(0) -@@ -108,6 +109,8 @@ struct cqspi_st { - - bool is_jh7110; /* Flag for StarFive JH7110 SoC */ - bool disable_stig_mode; -+ refcount_t refcount; -+ refcount_t inflight_ops; - - const struct cqspi_driver_platdata *ddata; - }; -@@ -735,6 +738,9 @@ static int cqspi_indirect_read_execute(s - u8 *rxbuf_end = rxbuf + n_rx; - int ret = 0; - -+ if (!refcount_read(&cqspi->refcount)) -+ return -ENODEV; -+ - writel(from_addr, reg_base + CQSPI_REG_INDIRECTRDSTARTADDR); - writel(remaining, reg_base + CQSPI_REG_INDIRECTRDBYTES); - -@@ -1071,6 +1077,9 @@ static int cqspi_indirect_write_execute( - unsigned int write_bytes; - int ret; - -+ if (!refcount_read(&cqspi->refcount)) -+ return -ENODEV; -+ - writel(to_addr, reg_base + CQSPI_REG_INDIRECTWRSTARTADDR); - writel(remaining, reg_base + CQSPI_REG_INDIRECTWRBYTES); - -@@ -1460,21 +1469,43 @@ static int cqspi_exec_mem_op(struct spi_ - int ret; - struct cqspi_st *cqspi = spi_controller_get_devdata(mem->spi->controller); - struct device *dev = &cqspi->pdev->dev; -+ const struct cqspi_driver_platdata *ddata = of_device_get_match_data(dev); - -- ret = pm_runtime_resume_and_get(dev); -- if (ret) { -- dev_err(&mem->spi->dev, "resume failed with %d\n", ret); -- return ret; -+ if (refcount_read(&cqspi->inflight_ops) == 0) -+ return -ENODEV; -+ -+ if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) { -+ ret = pm_runtime_resume_and_get(dev); -+ if (ret) { -+ dev_err(&mem->spi->dev, "resume failed with %d\n", ret); -+ return ret; -+ } -+ } -+ -+ if (!refcount_read(&cqspi->refcount)) -+ return -EBUSY; -+ -+ refcount_inc(&cqspi->inflight_ops); -+ -+ if (!refcount_read(&cqspi->refcount)) { -+ if (refcount_read(&cqspi->inflight_ops)) -+ refcount_dec(&cqspi->inflight_ops); -+ return -EBUSY; - } - - ret = cqspi_mem_process(mem, op); - -- pm_runtime_mark_last_busy(dev); -- pm_runtime_put_autosuspend(dev); -+ if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) { -+ pm_runtime_mark_last_busy(dev); -+ pm_runtime_put_autosuspend(dev); -+ } - - if (ret) - dev_err(&mem->spi->dev, "operation failed with %d\n", ret); - -+ if (refcount_read(&cqspi->inflight_ops) > 1) -+ refcount_dec(&cqspi->inflight_ops); -+ - return ret; - } - -@@ -1926,6 +1957,9 @@ static int cqspi_probe(struct platform_d - } - } - -+ refcount_set(&cqspi->refcount, 1); -+ refcount_set(&cqspi->inflight_ops, 1); -+ - ret = devm_request_irq(dev, irq, cqspi_irq_handler, 0, - pdev->name, cqspi); - if (ret) { -@@ -1958,29 +1992,30 @@ static int cqspi_probe(struct platform_d - goto probe_setup_failed; - } - -- ret = devm_pm_runtime_enable(dev); -- if (ret) { -- if (cqspi->rx_chan) -- dma_release_channel(cqspi->rx_chan); -- goto probe_setup_failed; -+ if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) { -+ pm_runtime_enable(dev); -+ pm_runtime_set_autosuspend_delay(dev, CQSPI_AUTOSUSPEND_TIMEOUT); -+ pm_runtime_use_autosuspend(dev); -+ pm_runtime_get_noresume(dev); - } - -- pm_runtime_set_autosuspend_delay(dev, CQSPI_AUTOSUSPEND_TIMEOUT); -- pm_runtime_use_autosuspend(dev); -- pm_runtime_get_noresume(dev); -- - ret = spi_register_controller(host); - if (ret) { - dev_err(&pdev->dev, "failed to register SPI ctlr %d\n", ret); - goto probe_setup_failed; - } - -- pm_runtime_mark_last_busy(dev); -- pm_runtime_put_autosuspend(dev); -+ if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) { -+ pm_runtime_put_autosuspend(dev); -+ pm_runtime_mark_last_busy(dev); -+ pm_runtime_put_autosuspend(dev); -+ } - - return 0; - probe_setup_failed: - cqspi_controller_enable(cqspi, 0); -+ if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) -+ pm_runtime_disable(dev); - probe_reset_failed: - if (cqspi->is_jh7110) - cqspi_jh7110_disable_clk(pdev, cqspi); -@@ -1991,7 +2026,16 @@ probe_clk_failed: - - static void cqspi_remove(struct platform_device *pdev) - { -+ const struct cqspi_driver_platdata *ddata; - struct cqspi_st *cqspi = platform_get_drvdata(pdev); -+ struct device *dev = &pdev->dev; -+ -+ ddata = of_device_get_match_data(dev); -+ -+ refcount_set(&cqspi->refcount, 0); -+ -+ if (!refcount_dec_and_test(&cqspi->inflight_ops)) -+ cqspi_wait_idle(cqspi); - - spi_unregister_controller(cqspi->host); - cqspi_controller_enable(cqspi, 0); -@@ -1999,13 +2043,17 @@ static void cqspi_remove(struct platform - if (cqspi->rx_chan) - dma_release_channel(cqspi->rx_chan); - -- clk_disable_unprepare(cqspi->clk); -+ if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) -+ if (pm_runtime_get_sync(&pdev->dev) >= 0) -+ clk_disable(cqspi->clk); - - if (cqspi->is_jh7110) - cqspi_jh7110_disable_clk(pdev, cqspi); - -- pm_runtime_put_sync(&pdev->dev); -- pm_runtime_disable(&pdev->dev); -+ if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) { -+ pm_runtime_put_sync(&pdev->dev); -+ pm_runtime_disable(&pdev->dev); -+ } - } - - static int cqspi_runtime_suspend(struct device *dev) -@@ -2084,7 +2132,8 @@ static const struct cqspi_driver_platdat - .quirks = CQSPI_DISABLE_DAC_MODE - | CQSPI_NO_SUPPORT_WR_COMPLETION - | CQSPI_SLOW_SRAM -- | CQSPI_DISABLE_STIG_MODE, -+ | CQSPI_DISABLE_STIG_MODE -+ | CQSPI_DISABLE_RUNTIME_PM, - }; - - static const struct cqspi_driver_platdata versal_ospi = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/spi/spi-cs42l43.c BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-cs42l43.c ---- BPI-Router-Linux-kernel/drivers/spi/spi-cs42l43.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-cs42l43.c 2025-10-22 13:53:56.663168428 -0400 -@@ -295,7 +295,7 @@ static struct spi_board_info *cs42l43_cr - struct spi_board_info *info; - - if (spkid >= 0) { -- props = devm_kmalloc(priv->dev, sizeof(*props), GFP_KERNEL); -+ props = devm_kcalloc(priv->dev, 2, sizeof(*props), GFP_KERNEL); - if (!props) - return NULL; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/spi/spi-fsl-dspi.c BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-fsl-dspi.c ---- BPI-Router-Linux-kernel/drivers/spi/spi-fsl-dspi.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-fsl-dspi.c 2025-10-22 13:53:56.663168428 -0400 -@@ -983,11 +983,20 @@ static int dspi_transfer_one_message(str - if (dspi->devtype_data->trans_mode == DSPI_DMA_MODE) { - status = dspi_dma_xfer(dspi); - } else { -+ /* -+ * Reinitialize the completion before transferring data -+ * to avoid the case where it might remain in the done -+ * state due to a spurious interrupt from a previous -+ * transfer. This could falsely signal that the current -+ * transfer has completed. -+ */ -+ if (dspi->irq) -+ reinit_completion(&dspi->xfer_done); -+ - dspi_fifo_write(dspi); - - if (dspi->irq) { - wait_for_completion(&dspi->xfer_done); -- reinit_completion(&dspi->xfer_done); - } else { - do { - status = dspi_poll(dspi); -diff -purNx .git BPI-Router-Linux-kernel/drivers/spi/spi-fsl-lpspi.c BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-fsl-lpspi.c ---- BPI-Router-Linux-kernel/drivers/spi/spi-fsl-lpspi.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-fsl-lpspi.c 2025-10-22 13:53:56.663168428 -0400 -@@ -3,8 +3,9 @@ - // Freescale i.MX7ULP LPSPI driver - // - // Copyright 2016 Freescale Semiconductor, Inc. --// Copyright 2018 NXP Semiconductors -+// Copyright 2018, 2023, 2025 NXP - -+#include - #include - #include - #include -@@ -70,7 +71,7 @@ - #define DER_TDDE BIT(0) - #define CFGR1_PCSCFG BIT(27) - #define CFGR1_PINCFG (BIT(24)|BIT(25)) --#define CFGR1_PCSPOL BIT(8) -+#define CFGR1_PCSPOL_MASK GENMASK(11, 8) - #define CFGR1_NOSTALL BIT(3) - #define CFGR1_HOST BIT(0) - #define FSR_TXCOUNT (0xFF) -@@ -82,6 +83,8 @@ - #define TCR_RXMSK BIT(19) - #define TCR_TXMSK BIT(18) - -+#define SR_CLEAR_MASK GENMASK(13, 8) -+ - struct fsl_lpspi_devtype_data { - u8 prescale_max; - }; -@@ -331,13 +334,11 @@ static int fsl_lpspi_set_bitrate(struct - } - - if (config.speed_hz > perclk_rate / 2) { -- dev_err(fsl_lpspi->dev, -- "per-clk should be at least two times of transfer speed"); -- return -EINVAL; -+ div = 2; -+ } else { -+ div = DIV_ROUND_UP(perclk_rate, config.speed_hz); - } - -- div = DIV_ROUND_UP(perclk_rate, config.speed_hz); -- - for (prescale = 0; prescale <= prescale_max; prescale++) { - scldiv = div / (1 << prescale) - 2; - if (scldiv >= 0 && scldiv < 256) { -@@ -426,7 +427,9 @@ static int fsl_lpspi_config(struct fsl_l - else - temp = CFGR1_PINCFG; - if (fsl_lpspi->config.mode & SPI_CS_HIGH) -- temp |= CFGR1_PCSPOL; -+ temp |= FIELD_PREP(CFGR1_PCSPOL_MASK, -+ BIT(fsl_lpspi->config.chip_select)); -+ - writel(temp, fsl_lpspi->base + IMX7ULP_CFGR1); - - temp = readl(fsl_lpspi->base + IMX7ULP_CR); -@@ -535,14 +538,13 @@ static int fsl_lpspi_reset(struct fsl_lp - fsl_lpspi_intctrl(fsl_lpspi, 0); - } - -- /* W1C for all flags in SR */ -- temp = 0x3F << 8; -- writel(temp, fsl_lpspi->base + IMX7ULP_SR); -- - /* Clear FIFO and disable module */ - temp = CR_RRF | CR_RTF; - writel(temp, fsl_lpspi->base + IMX7ULP_CR); - -+ /* W1C for all flags in SR */ -+ writel(SR_CLEAR_MASK, fsl_lpspi->base + IMX7ULP_SR); -+ - return 0; - } - -@@ -733,12 +735,10 @@ static int fsl_lpspi_pio_transfer(struct - fsl_lpspi_write_tx_fifo(fsl_lpspi); - - ret = fsl_lpspi_wait_for_completion(controller); -- if (ret) -- return ret; - - fsl_lpspi_reset(fsl_lpspi); - -- return 0; -+ return ret; - } - - static int fsl_lpspi_transfer_one(struct spi_controller *controller, -@@ -788,7 +788,7 @@ static irqreturn_t fsl_lpspi_isr(int irq - if (temp_SR & SR_MBF || - readl(fsl_lpspi->base + IMX7ULP_FSR) & FSR_TXCOUNT) { - writel(SR_FCF, fsl_lpspi->base + IMX7ULP_SR); -- fsl_lpspi_intctrl(fsl_lpspi, IER_FCIE); -+ fsl_lpspi_intctrl(fsl_lpspi, IER_FCIE | (temp_IER & IER_TDIE)); - return IRQ_HANDLED; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/spi/spi-loongson-core.c BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-loongson-core.c ---- BPI-Router-Linux-kernel/drivers/spi/spi-loongson-core.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-loongson-core.c 2025-10-22 13:53:56.663168428 -0400 -@@ -5,6 +5,7 @@ - #include - #include - #include -+#include - #include - #include - #include -diff -purNx .git BPI-Router-Linux-kernel/drivers/spi/spi-microchip-core-qspi.c BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-microchip-core-qspi.c ---- BPI-Router-Linux-kernel/drivers/spi/spi-microchip-core-qspi.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-microchip-core-qspi.c 2025-10-22 13:53:56.663168428 -0400 -@@ -458,10 +458,6 @@ error: - - static bool mchp_coreqspi_supports_op(struct spi_mem *mem, const struct spi_mem_op *op) - { -- struct mchp_coreqspi *qspi = spi_controller_get_devdata(mem->spi->controller); -- unsigned long clk_hz; -- u32 baud_rate_val; -- - if (!spi_mem_default_supports_op(mem, op)) - return false; - -@@ -484,14 +480,6 @@ static bool mchp_coreqspi_supports_op(st - return false; - } - -- clk_hz = clk_get_rate(qspi->clk); -- if (!clk_hz) -- return false; -- -- baud_rate_val = DIV_ROUND_UP(clk_hz, 2 * op->max_freq); -- if (baud_rate_val > MAX_DIVIDER || baud_rate_val < MIN_DIVIDER) -- return false; -- - return true; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/spi/spi-nxp-fspi.c BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-nxp-fspi.c ---- BPI-Router-Linux-kernel/drivers/spi/spi-nxp-fspi.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-nxp-fspi.c 2025-10-22 13:53:56.663168428 -0400 -@@ -1273,7 +1273,9 @@ static int nxp_fspi_probe(struct platfor - if (ret) - return dev_err_probe(dev, ret, "Failed to request irq\n"); - -- devm_mutex_init(dev, &f->lock); -+ ret = devm_mutex_init(dev, &f->lock); -+ if (ret) -+ return dev_err_probe(dev, ret, "Failed to initialize lock\n"); - - ctlr->bus_num = -1; - ctlr->num_chipselect = NXP_FSPI_MAX_CHIPSELECT; -diff -purNx .git BPI-Router-Linux-kernel/drivers/spi/spi-offload.c BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-offload.c ---- BPI-Router-Linux-kernel/drivers/spi/spi-offload.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-offload.c 2025-10-22 13:53:56.667168409 -0400 -@@ -297,7 +297,7 @@ int spi_offload_trigger_enable(struct sp - if (trigger->ops->enable) { - ret = trigger->ops->enable(trigger, config); - if (ret) { -- if (offload->ops->trigger_disable) -+ if (offload->ops && offload->ops->trigger_disable) - offload->ops->trigger_disable(offload); - return ret; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/spi/spi-omap2-mcspi.c BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-omap2-mcspi.c ---- BPI-Router-Linux-kernel/drivers/spi/spi-omap2-mcspi.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-omap2-mcspi.c 2025-10-22 13:53:56.667168409 -0400 -@@ -134,6 +134,7 @@ struct omap2_mcspi { - size_t max_xfer_len; - u32 ref_clk_hz; - bool use_multi_mode; -+ bool last_msg_kept_cs; - }; - - struct omap2_mcspi_cs { -@@ -1269,6 +1270,10 @@ static int omap2_mcspi_prepare_message(s - * multi-mode is applicable. - */ - mcspi->use_multi_mode = true; -+ -+ if (mcspi->last_msg_kept_cs) -+ mcspi->use_multi_mode = false; -+ - list_for_each_entry(tr, &msg->transfers, transfer_list) { - if (!tr->bits_per_word) - bits_per_word = msg->spi->bits_per_word; -@@ -1287,18 +1292,19 @@ static int omap2_mcspi_prepare_message(s - mcspi->use_multi_mode = false; - } - -- /* Check if transfer asks to change the CS status after the transfer */ -- if (!tr->cs_change) -- mcspi->use_multi_mode = false; -- -- /* -- * If at least one message is not compatible, switch back to single mode -- * -- * The bits_per_word of certain transfer can be different, but it will have no -- * impact on the signal itself. -- */ -- if (!mcspi->use_multi_mode) -- break; -+ if (list_is_last(&tr->transfer_list, &msg->transfers)) { -+ /* Check if transfer asks to keep the CS status after the whole message */ -+ if (tr->cs_change) { -+ mcspi->use_multi_mode = false; -+ mcspi->last_msg_kept_cs = true; -+ } else { -+ mcspi->last_msg_kept_cs = false; -+ } -+ } else { -+ /* Check if transfer asks to change the CS status after the transfer */ -+ if (!tr->cs_change) -+ mcspi->use_multi_mode = false; -+ } - } - - omap2_mcspi_set_mode(ctlr); -diff -purNx .git BPI-Router-Linux-kernel/drivers/spi/spi-pci1xxxx.c BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-pci1xxxx.c ---- BPI-Router-Linux-kernel/drivers/spi/spi-pci1xxxx.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-pci1xxxx.c 2025-10-22 13:53:56.667168409 -0400 -@@ -762,10 +762,10 @@ static int pci1xxxx_spi_probe(struct pci - return -EINVAL; - - num_vector = pci_alloc_irq_vectors(pdev, 1, hw_inst_cnt, -- PCI_IRQ_ALL_TYPES); -+ PCI_IRQ_INTX | PCI_IRQ_MSI); - if (num_vector < 0) { - dev_err(&pdev->dev, "Error allocating MSI vectors\n"); -- return ret; -+ return num_vector; - } - - init_completion(&spi_sub_ptr->spi_xfer_done); -diff -purNx .git BPI-Router-Linux-kernel/drivers/spi/spi-qpic-snand.c BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-qpic-snand.c ---- BPI-Router-Linux-kernel/drivers/spi/spi-qpic-snand.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-qpic-snand.c 2025-10-22 13:53:56.667168409 -0400 -@@ -216,13 +216,21 @@ static int qcom_spi_ooblayout_ecc(struct - struct qcom_nand_controller *snandc = nand_to_qcom_snand(nand); - struct qpic_ecc *qecc = snandc->qspi->ecc; - -- if (section > 1) -- return -ERANGE; -- -- oobregion->length = qecc->ecc_bytes_hw + qecc->spare_bytes; -- oobregion->offset = mtd->oobsize - oobregion->length; -+ switch (section) { -+ case 0: -+ oobregion->offset = 0; -+ oobregion->length = qecc->bytes * (qecc->steps - 1) + -+ qecc->bbm_size; -+ return 0; -+ case 1: -+ oobregion->offset = qecc->bytes * (qecc->steps - 1) + -+ qecc->bbm_size + -+ qecc->steps * 4; -+ oobregion->length = mtd->oobsize - oobregion->offset; -+ return 0; -+ } - -- return 0; -+ return -ERANGE; - } - - static int qcom_spi_ooblayout_free(struct mtd_info *mtd, int section, -@@ -308,13 +316,29 @@ static int qcom_spi_ecc_init_ctx_pipelin - ecc_cfg->bch_enabled = true; - ecc_cfg->bytes = ecc_cfg->ecc_bytes_hw + ecc_cfg->spare_bytes + ecc_cfg->bbm_size; - -- ecc_cfg->steps = 4; -+ ecc_cfg->steps = cwperpage; - ecc_cfg->cw_data = 516; - ecc_cfg->cw_size = ecc_cfg->cw_data + ecc_cfg->bytes; - bad_block_byte = mtd->writesize - ecc_cfg->cw_size * (cwperpage - 1) + 1; - - mtd_set_ooblayout(mtd, &qcom_spi_ooblayout); - -+ /* -+ * Free the temporary BAM transaction allocated initially by -+ * qcom_nandc_alloc(), and allocate a new one based on the -+ * updated max_cwperpage value. -+ */ -+ qcom_free_bam_transaction(snandc); -+ -+ snandc->max_cwperpage = cwperpage; -+ -+ snandc->bam_txn = qcom_alloc_bam_transaction(snandc); -+ if (!snandc->bam_txn) { -+ dev_err(snandc->dev, "failed to allocate BAM transaction\n"); -+ ret = -ENOMEM; -+ goto err_free_ecc_cfg; -+ } -+ - ecc_cfg->cfg0 = FIELD_PREP(CW_PER_PAGE_MASK, (cwperpage - 1)) | - FIELD_PREP(UD_SIZE_BYTES_MASK, ecc_cfg->cw_data) | - FIELD_PREP(DISABLE_STATUS_AFTER_WRITE, 1) | -@@ -1169,7 +1193,7 @@ static int qcom_spi_program_oob(struct q - u32 cfg0, cfg1, ecc_bch_cfg, ecc_buf_cfg; - - cfg0 = (ecc_cfg->cfg0 & ~CW_PER_PAGE_MASK) | -- FIELD_PREP(CW_PER_PAGE_MASK, num_cw - 1); -+ FIELD_PREP(CW_PER_PAGE_MASK, 0); - cfg1 = ecc_cfg->cfg1; - ecc_bch_cfg = ecc_cfg->ecc_bch_cfg; - ecc_buf_cfg = ecc_cfg->ecc_buf_cfg; -@@ -1591,11 +1615,13 @@ static int qcom_spi_probe(struct platfor - ret = spi_register_controller(ctlr); - if (ret) { - dev_err(&pdev->dev, "spi_register_controller failed.\n"); -- goto err_spi_init; -+ goto err_register_controller; - } - - return 0; - -+err_register_controller: -+ nand_ecc_unregister_on_host_hw_engine(&snandc->qspi->ecc_eng); - err_spi_init: - qcom_nandc_unalloc(snandc); - err_snand_alloc: -@@ -1617,7 +1643,7 @@ static void qcom_spi_remove(struct platf - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - spi_unregister_controller(ctlr); -- -+ nand_ecc_unregister_on_host_hw_engine(&snandc->qspi->ecc_eng); - qcom_nandc_unalloc(snandc); - - clk_disable_unprepare(snandc->aon_clk); -diff -purNx .git BPI-Router-Linux-kernel/drivers/spi/spi-stm32.c BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-stm32.c ---- BPI-Router-Linux-kernel/drivers/spi/spi-stm32.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-stm32.c 2025-10-22 13:53:56.667168409 -0400 -@@ -2069,9 +2069,15 @@ static int stm32_spi_probe(struct platfo - struct resource *res; - struct reset_control *rst; - struct device_node *np = pdev->dev.of_node; -+ const struct stm32_spi_cfg *cfg; - bool device_mode; - int ret; -- const struct stm32_spi_cfg *cfg = of_device_get_match_data(&pdev->dev); -+ -+ cfg = of_device_get_match_data(&pdev->dev); -+ if (!cfg) { -+ dev_err(&pdev->dev, "Failed to get match data for platform\n"); -+ return -ENODEV; -+ } - - device_mode = of_property_read_bool(np, "spi-slave"); - if (!cfg->has_device_mode && device_mode) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/spi/spi-stm32-ospi.c BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-stm32-ospi.c ---- BPI-Router-Linux-kernel/drivers/spi/spi-stm32-ospi.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-stm32-ospi.c 2025-10-22 13:53:56.667168409 -0400 -@@ -804,7 +804,7 @@ static int stm32_ospi_get_resources(stru - return ret; - } - -- ospi->rstc = devm_reset_control_array_get_exclusive(dev); -+ ospi->rstc = devm_reset_control_array_get_exclusive_released(dev); - if (IS_ERR(ospi->rstc)) - return dev_err_probe(dev, PTR_ERR(ospi->rstc), - "Can't get reset\n"); -@@ -936,12 +936,16 @@ static int stm32_ospi_probe(struct platf - if (ret < 0) - goto err_pm_enable; - -- if (ospi->rstc) { -- reset_control_assert(ospi->rstc); -- udelay(2); -- reset_control_deassert(ospi->rstc); -+ ret = reset_control_acquire(ospi->rstc); -+ if (ret) { -+ dev_err_probe(dev, ret, "Can not acquire reset %d\n", ret); -+ goto err_pm_resume; - } - -+ reset_control_assert(ospi->rstc); -+ udelay(2); -+ reset_control_deassert(ospi->rstc); -+ - ret = spi_register_controller(ctrl); - if (ret) { - /* Disable ospi */ -@@ -987,6 +991,8 @@ static void stm32_ospi_remove(struct pla - if (ospi->dma_chrx) - dma_release_channel(ospi->dma_chrx); - -+ reset_control_release(ospi->rstc); -+ - pm_runtime_put_sync_suspend(ospi->dev); - pm_runtime_force_suspend(ospi->dev); - } -@@ -997,6 +1003,8 @@ static int __maybe_unused stm32_ospi_sus - - pinctrl_pm_select_sleep_state(dev); - -+ reset_control_release(ospi->rstc); -+ - return pm_runtime_force_suspend(ospi->dev); - } - -@@ -1016,6 +1024,12 @@ static int __maybe_unused stm32_ospi_res - if (ret < 0) - return ret; - -+ ret = reset_control_acquire(ospi->rstc); -+ if (ret) { -+ dev_err(dev, "Can not acquire reset\n"); -+ return ret; -+ } -+ - writel_relaxed(ospi->cr_reg, regs_base + OSPI_CR); - writel_relaxed(ospi->dcr_reg, regs_base + OSPI_DCR1); - pm_runtime_mark_last_busy(ospi->dev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/spi/spi-tegra210-quad.c BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-tegra210-quad.c ---- BPI-Router-Linux-kernel/drivers/spi/spi-tegra210-quad.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/spi/spi-tegra210-quad.c 2025-10-22 13:53:56.667168409 -0400 -@@ -407,9 +407,6 @@ tegra_qspi_read_rx_fifo_to_client_rxbuf( - static void - tegra_qspi_copy_client_txbuf_to_qspi_txbuf(struct tegra_qspi *tqspi, struct spi_transfer *t) - { -- dma_sync_single_for_cpu(tqspi->dev, tqspi->tx_dma_phys, -- tqspi->dma_buf_size, DMA_TO_DEVICE); -- - /* - * In packed mode, each word in FIFO may contain multiple packets - * based on bits per word. So all bytes in each FIFO word are valid. -@@ -442,17 +439,11 @@ tegra_qspi_copy_client_txbuf_to_qspi_txb - - tqspi->cur_tx_pos += write_bytes; - } -- -- dma_sync_single_for_device(tqspi->dev, tqspi->tx_dma_phys, -- tqspi->dma_buf_size, DMA_TO_DEVICE); - } - - static void - tegra_qspi_copy_qspi_rxbuf_to_client_rxbuf(struct tegra_qspi *tqspi, struct spi_transfer *t) - { -- dma_sync_single_for_cpu(tqspi->dev, tqspi->rx_dma_phys, -- tqspi->dma_buf_size, DMA_FROM_DEVICE); -- - if (tqspi->is_packed) { - tqspi->cur_rx_pos += tqspi->curr_dma_words * tqspi->bytes_per_word; - } else { -@@ -478,9 +469,6 @@ tegra_qspi_copy_qspi_rxbuf_to_client_rxb - - tqspi->cur_rx_pos += read_bytes; - } -- -- dma_sync_single_for_device(tqspi->dev, tqspi->rx_dma_phys, -- tqspi->dma_buf_size, DMA_FROM_DEVICE); - } - - static void tegra_qspi_dma_complete(void *args) -@@ -701,8 +689,6 @@ static int tegra_qspi_start_dma_based_tr - return ret; - } - -- dma_sync_single_for_device(tqspi->dev, tqspi->rx_dma_phys, -- tqspi->dma_buf_size, DMA_FROM_DEVICE); - ret = tegra_qspi_start_rx_dma(tqspi, t, len); - if (ret < 0) { - dev_err(tqspi->dev, "failed to start RX DMA: %d\n", ret); -diff -purNx .git BPI-Router-Linux-kernel/drivers/staging/axis-fifo/axis-fifo.c BPI-Router-Linux-kernel-6.16.12/drivers/staging/axis-fifo/axis-fifo.c ---- BPI-Router-Linux-kernel/drivers/staging/axis-fifo/axis-fifo.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/staging/axis-fifo/axis-fifo.c 2025-10-22 13:53:56.667168409 -0400 -@@ -42,7 +42,6 @@ - #define DRIVER_NAME "axis_fifo" - - #define READ_BUF_SIZE 128U /* read buffer length in words */ --#define WRITE_BUF_SIZE 128U /* write buffer length in words */ - - /* ---------------------------- - * IP register offsets -@@ -392,6 +391,7 @@ static ssize_t axis_fifo_read(struct fil - } - - bytes_available = ioread32(fifo->base_addr + XLLF_RLR_OFFSET); -+ words_available = bytes_available / sizeof(u32); - if (!bytes_available) { - dev_err(fifo->dt_device, "received a packet of length 0\n"); - ret = -EIO; -@@ -402,7 +402,7 @@ static ssize_t axis_fifo_read(struct fil - dev_err(fifo->dt_device, "user read buffer too small (available bytes=%zu user buffer bytes=%zu)\n", - bytes_available, len); - ret = -EINVAL; -- goto end_unlock; -+ goto err_flush_rx; - } - - if (bytes_available % sizeof(u32)) { -@@ -411,11 +411,9 @@ static ssize_t axis_fifo_read(struct fil - */ - dev_err(fifo->dt_device, "received a packet that isn't word-aligned\n"); - ret = -EIO; -- goto end_unlock; -+ goto err_flush_rx; - } - -- words_available = bytes_available / sizeof(u32); -- - /* read data into an intermediate buffer, copying the contents - * to userspace when the buffer is full - */ -@@ -427,18 +425,23 @@ static ssize_t axis_fifo_read(struct fil - tmp_buf[i] = ioread32(fifo->base_addr + - XLLF_RDFD_OFFSET); - } -+ words_available -= copy; - - if (copy_to_user(buf + copied * sizeof(u32), tmp_buf, - copy * sizeof(u32))) { - ret = -EFAULT; -- goto end_unlock; -+ goto err_flush_rx; - } - - copied += copy; -- words_available -= copy; - } -+ mutex_unlock(&fifo->read_lock); -+ -+ return bytes_available; - -- ret = bytes_available; -+err_flush_rx: -+ while (words_available--) -+ ioread32(fifo->base_addr + XLLF_RDFD_OFFSET); - - end_unlock: - mutex_unlock(&fifo->read_lock); -@@ -466,11 +469,8 @@ static ssize_t axis_fifo_write(struct fi - { - struct axis_fifo *fifo = (struct axis_fifo *)f->private_data; - unsigned int words_to_write; -- unsigned int copied; -- unsigned int copy; -- unsigned int i; -+ u32 *txbuf; - int ret; -- u32 tmp_buf[WRITE_BUF_SIZE]; - - if (len % sizeof(u32)) { - dev_err(fifo->dt_device, -@@ -486,11 +486,17 @@ static ssize_t axis_fifo_write(struct fi - return -EINVAL; - } - -- if (words_to_write > fifo->tx_fifo_depth) { -- dev_err(fifo->dt_device, "tried to write more words [%u] than slots in the fifo buffer [%u]\n", -- words_to_write, fifo->tx_fifo_depth); -+ /* -+ * In 'Store-and-Forward' mode, the maximum packet that can be -+ * transmitted is limited by the size of the FIFO, which is -+ * (C_TX_FIFO_DEPTH–4)*(data interface width/8) bytes. -+ * -+ * Do not attempt to send a packet larger than 'tx_fifo_depth - 4', -+ * otherwise a 'Transmit Packet Overrun Error' interrupt will be -+ * raised, which requires a reset of the TX circuit to recover. -+ */ -+ if (words_to_write > (fifo->tx_fifo_depth - 4)) - return -EINVAL; -- } - - if (fifo->write_flags & O_NONBLOCK) { - /* -@@ -529,32 +535,20 @@ static ssize_t axis_fifo_write(struct fi - } - } - -- /* write data from an intermediate buffer into the fifo IP, refilling -- * the buffer with userspace data as needed -- */ -- copied = 0; -- while (words_to_write > 0) { -- copy = min(words_to_write, WRITE_BUF_SIZE); -- -- if (copy_from_user(tmp_buf, buf + copied * sizeof(u32), -- copy * sizeof(u32))) { -- ret = -EFAULT; -- goto end_unlock; -- } -- -- for (i = 0; i < copy; i++) -- iowrite32(tmp_buf[i], fifo->base_addr + -- XLLF_TDFD_OFFSET); -- -- copied += copy; -- words_to_write -= copy; -+ txbuf = vmemdup_user(buf, len); -+ if (IS_ERR(txbuf)) { -+ ret = PTR_ERR(txbuf); -+ goto end_unlock; - } - -- ret = copied * sizeof(u32); -+ for (int i = 0; i < words_to_write; ++i) -+ iowrite32(txbuf[i], fifo->base_addr + XLLF_TDFD_OFFSET); - - /* write packet size to fifo */ -- iowrite32(ret, fifo->base_addr + XLLF_TLR_OFFSET); -+ iowrite32(len, fifo->base_addr + XLLF_TLR_OFFSET); - -+ ret = len; -+ kvfree(txbuf); - end_unlock: - mutex_unlock(&fifo->write_lock); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/staging/fbtft/fbtft-core.c BPI-Router-Linux-kernel-6.16.12/drivers/staging/fbtft/fbtft-core.c ---- BPI-Router-Linux-kernel/drivers/staging/fbtft/fbtft-core.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/staging/fbtft/fbtft-core.c 2025-10-22 13:53:56.667168409 -0400 -@@ -692,6 +692,7 @@ struct fb_info *fbtft_framebuffer_alloc( - return info; - - release_framebuf: -+ fb_deferred_io_cleanup(info); - framebuffer_release(info); - - alloc_fail: -diff -purNx .git BPI-Router-Linux-kernel/drivers/staging/gpib/cb7210/cb7210.c BPI-Router-Linux-kernel-6.16.12/drivers/staging/gpib/cb7210/cb7210.c ---- BPI-Router-Linux-kernel/drivers/staging/gpib/cb7210/cb7210.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/staging/gpib/cb7210/cb7210.c 2025-10-22 13:53:56.667168409 -0400 -@@ -1184,8 +1184,7 @@ struct local_info { - static int cb_gpib_probe(struct pcmcia_device *link) - { - struct local_info *info; -- --// int ret, i; -+ int ret; - - /* Allocate space for private device-specific data */ - info = kzalloc(sizeof(*info), GFP_KERNEL); -@@ -1211,8 +1210,16 @@ static int cb_gpib_probe(struct pcmcia_d - - /* Register with Card Services */ - curr_dev = link; -- return cb_gpib_config(link); --} /* gpib_attach */ -+ ret = cb_gpib_config(link); -+ if (ret) -+ goto free_info; -+ -+ return 0; -+ -+free_info: -+ kfree(info); -+ return ret; -+} - - /* - * This deletes a driver "instance". The device is de-registered -diff -purNx .git BPI-Router-Linux-kernel/drivers/staging/gpib/common/gpib_os.c BPI-Router-Linux-kernel-6.16.12/drivers/staging/gpib/common/gpib_os.c ---- BPI-Router-Linux-kernel/drivers/staging/gpib/common/gpib_os.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/staging/gpib/common/gpib_os.c 2025-10-22 13:53:56.667168409 -0400 -@@ -831,7 +831,7 @@ static int board_type_ioctl(struct gpib_ - retval = copy_from_user(&cmd, (void __user *)arg, - sizeof(struct gpib_board_type_ioctl)); - if (retval) -- return retval; -+ return -EFAULT; - - for (list_ptr = registered_drivers.next; list_ptr != ®istered_drivers; - list_ptr = list_ptr->next) { -@@ -1774,7 +1774,7 @@ static int query_board_rsv_ioctl(struct - - static int board_info_ioctl(const struct gpib_board *board, unsigned long arg) - { -- struct gpib_board_info_ioctl info; -+ struct gpib_board_info_ioctl info = { }; - int retval; - - info.pad = board->pad; -diff -purNx .git BPI-Router-Linux-kernel/drivers/staging/gpib/ni_usb/ni_usb_gpib.c BPI-Router-Linux-kernel-6.16.12/drivers/staging/gpib/ni_usb/ni_usb_gpib.c ---- BPI-Router-Linux-kernel/drivers/staging/gpib/ni_usb/ni_usb_gpib.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/staging/gpib/ni_usb/ni_usb_gpib.c 2025-10-22 13:53:56.667168409 -0400 -@@ -2079,10 +2079,10 @@ static int ni_usb_hs_wait_for_ready(stru - } - if (buffer[++j] != 0x0) { // [6] - ready = 1; -- // NI-USB-HS+ sends 0xf here -+ // NI-USB-HS+ sends 0xf or 0x19 here - if (buffer[j] != 0x2 && buffer[j] != 0xe && buffer[j] != 0xf && -- buffer[j] != 0x16) { -- dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x2, 0xe, 0xf or 0x16\n", -+ buffer[j] != 0x16 && buffer[j] != 0x19) { -+ dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x2, 0xe, 0xf, 0x16 or 0x19\n", - j, (int)buffer[j]); - unexpected = 1; - } -@@ -2110,11 +2110,11 @@ static int ni_usb_hs_wait_for_ready(stru - j, (int)buffer[j]); - unexpected = 1; - } -- if (buffer[++j] != 0x0) { -+ if (buffer[++j] != 0x0) { // [10] MC usb-488 sends 0x7 here, new HS+ sends 0x59 - ready = 1; -- if (buffer[j] != 0x96 && buffer[j] != 0x7 && buffer[j] != 0x6e) { --// [10] MC usb-488 sends 0x7 here -- dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x96, 0x07 or 0x6e\n", -+ if (buffer[j] != 0x96 && buffer[j] != 0x7 && buffer[j] != 0x6e && -+ buffer[j] != 0x59) { -+ dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x96, 0x07, 0x6e or 0x59\n", - j, (int)buffer[j]); - unexpected = 1; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/staging/greybus/gbphy.c BPI-Router-Linux-kernel-6.16.12/drivers/staging/greybus/gbphy.c ---- BPI-Router-Linux-kernel/drivers/staging/greybus/gbphy.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/staging/greybus/gbphy.c 2025-10-22 13:53:56.667168409 -0400 -@@ -102,8 +102,8 @@ static int gbphy_dev_uevent(const struct - } - - static const struct gbphy_device_id * --gbphy_dev_match_id(struct gbphy_device *gbphy_dev, -- struct gbphy_driver *gbphy_drv) -+gbphy_dev_match_id(const struct gbphy_device *gbphy_dev, -+ const struct gbphy_driver *gbphy_drv) - { - const struct gbphy_device_id *id = gbphy_drv->id_table; - -@@ -119,7 +119,7 @@ gbphy_dev_match_id(struct gbphy_device * - - static int gbphy_dev_match(struct device *dev, const struct device_driver *drv) - { -- struct gbphy_driver *gbphy_drv = to_gbphy_driver(drv); -+ const struct gbphy_driver *gbphy_drv = to_gbphy_driver(drv); - struct gbphy_device *gbphy_dev = to_gbphy_dev(dev); - const struct gbphy_device_id *id; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c BPI-Router-Linux-kernel-6.16.12/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c ---- BPI-Router-Linux-kernel/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c 2025-10-22 13:53:56.667168409 -0400 -@@ -1272,14 +1272,15 @@ static int gmin_get_config_var(struct de - if (efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) - status = efi.get_variable(var16, &GMIN_CFG_VAR_EFI_GUID, NULL, - (unsigned long *)out_len, out); -- if (status == EFI_SUCCESS) -+ if (status == EFI_SUCCESS) { - dev_info(maindev, "found EFI entry for '%s'\n", var8); -- else if (is_gmin) -+ return 0; -+ } -+ if (is_gmin) - dev_info(maindev, "Failed to find EFI gmin variable %s\n", var8); - else - dev_info(maindev, "Failed to find EFI variable %s\n", var8); -- -- return ret; -+ return -ENOENT; - } - - int gmin_get_var_int(struct device *dev, bool is_gmin, const char *var, int def) -diff -purNx .git BPI-Router-Linux-kernel/drivers/staging/media/imx/imx-media-csc-scaler.c BPI-Router-Linux-kernel-6.16.12/drivers/staging/media/imx/imx-media-csc-scaler.c ---- BPI-Router-Linux-kernel/drivers/staging/media/imx/imx-media-csc-scaler.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/staging/media/imx/imx-media-csc-scaler.c 2025-10-22 13:53:56.667168409 -0400 -@@ -912,7 +912,7 @@ imx_media_csc_scaler_device_init(struct - return &priv->vdev; - - err_m2m: -- video_set_drvdata(vfd, NULL); -+ video_device_release(vfd); - err_vfd: - kfree(priv); - return ERR_PTR(ret); -diff -purNx .git BPI-Router-Linux-kernel/drivers/staging/nvec/nvec_power.c BPI-Router-Linux-kernel-6.16.12/drivers/staging/nvec/nvec_power.c ---- BPI-Router-Linux-kernel/drivers/staging/nvec/nvec_power.c 2025-10-22 13:53:23.459327957 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/staging/nvec/nvec_power.c 2025-10-22 13:53:56.667168409 -0400 -@@ -194,7 +194,7 @@ static int nvec_power_bat_notifier(struc - break; - case MANUFACTURER: - memcpy(power->bat_manu, &res->plc, res->length - 2); -- power->bat_model[res->length - 2] = '\0'; -+ power->bat_manu[res->length - 2] = '\0'; - break; - case MODEL: - memcpy(power->bat_model, &res->plc, res->length - 2); -diff -purNx .git BPI-Router-Linux-kernel/drivers/staging/rtl8723bs/core/rtw_security.c BPI-Router-Linux-kernel-6.16.12/drivers/staging/rtl8723bs/core/rtw_security.c ---- BPI-Router-Linux-kernel/drivers/staging/rtl8723bs/core/rtw_security.c 2025-10-22 13:53:23.463327938 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/staging/rtl8723bs/core/rtw_security.c 2025-10-22 13:53:56.667168409 -0400 -@@ -868,29 +868,21 @@ static signed int aes_cipher(u8 *key, ui - num_blocks, payload_index; - - u8 pn_vector[6]; -- u8 mic_iv[16]; -- u8 mic_header1[16]; -- u8 mic_header2[16]; -- u8 ctr_preload[16]; -+ u8 mic_iv[16] = {}; -+ u8 mic_header1[16] = {}; -+ u8 mic_header2[16] = {}; -+ u8 ctr_preload[16] = {}; - - /* Intermediate Buffers */ -- u8 chain_buffer[16]; -- u8 aes_out[16]; -- u8 padded_buffer[16]; -+ u8 chain_buffer[16] = {}; -+ u8 aes_out[16] = {}; -+ u8 padded_buffer[16] = {}; - u8 mic[8]; - uint frtype = GetFrameType(pframe); - uint frsubtype = GetFrameSubType(pframe); - - frsubtype = frsubtype>>4; - -- memset((void *)mic_iv, 0, 16); -- memset((void *)mic_header1, 0, 16); -- memset((void *)mic_header2, 0, 16); -- memset((void *)ctr_preload, 0, 16); -- memset((void *)chain_buffer, 0, 16); -- memset((void *)aes_out, 0, 16); -- memset((void *)padded_buffer, 0, 16); -- - if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen == WLAN_HDR_A3_QOS_LEN)) - a4_exists = 0; - else -@@ -1080,15 +1072,15 @@ static signed int aes_decipher(u8 *key, - num_blocks, payload_index; - signed int res = _SUCCESS; - u8 pn_vector[6]; -- u8 mic_iv[16]; -- u8 mic_header1[16]; -- u8 mic_header2[16]; -- u8 ctr_preload[16]; -+ u8 mic_iv[16] = {}; -+ u8 mic_header1[16] = {}; -+ u8 mic_header2[16] = {}; -+ u8 ctr_preload[16] = {}; - - /* Intermediate Buffers */ -- u8 chain_buffer[16]; -- u8 aes_out[16]; -- u8 padded_buffer[16]; -+ u8 chain_buffer[16] = {}; -+ u8 aes_out[16] = {}; -+ u8 padded_buffer[16] = {}; - u8 mic[8]; - - uint frtype = GetFrameType(pframe); -@@ -1096,14 +1088,6 @@ static signed int aes_decipher(u8 *key, - - frsubtype = frsubtype>>4; - -- memset((void *)mic_iv, 0, 16); -- memset((void *)mic_header1, 0, 16); -- memset((void *)mic_header2, 0, 16); -- memset((void *)ctr_preload, 0, 16); -- memset((void *)chain_buffer, 0, 16); -- memset((void *)aes_out, 0, 16); -- memset((void *)padded_buffer, 0, 16); -- - /* start to decrypt the payload */ - - num_blocks = (plen-8) / 16; /* plen including LLC, payload_length and mic) */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c BPI-Router-Linux-kernel-6.16.12/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c ---- BPI-Router-Linux-kernel/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c 2025-10-22 13:53:23.463327938 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c 2025-10-22 13:53:56.667168409 -0400 -@@ -97,6 +97,13 @@ struct vchiq_arm_state { - * tracked separately with the state. - */ - int peer_use_count; -+ -+ /* -+ * Flag to indicate that the first vchiq connect has made it through. -+ * This means that both sides should be fully ready, and we should -+ * be able to suspend after this point. -+ */ -+ int first_connect; - }; - - static int -@@ -273,6 +280,29 @@ static int vchiq_platform_init(struct pl - return 0; - } - -+int -+vchiq_platform_init_state(struct vchiq_state *state) -+{ -+ struct vchiq_arm_state *platform_state; -+ -+ platform_state = devm_kzalloc(state->dev, sizeof(*platform_state), GFP_KERNEL); -+ if (!platform_state) -+ return -ENOMEM; -+ -+ rwlock_init(&platform_state->susp_res_lock); -+ -+ init_completion(&platform_state->ka_evt); -+ atomic_set(&platform_state->ka_use_count, 0); -+ atomic_set(&platform_state->ka_use_ack_count, 0); -+ atomic_set(&platform_state->ka_release_count, 0); -+ -+ platform_state->state = state; -+ -+ state->platform_state = (struct opaque_platform_state *)platform_state; -+ -+ return 0; -+} -+ - static struct vchiq_arm_state *vchiq_platform_get_arm_state(struct vchiq_state *state) - { - return (struct vchiq_arm_state *)state->platform_state; -@@ -363,8 +393,7 @@ int vchiq_shutdown(struct vchiq_instance - struct vchiq_state *state = instance->state; - int ret = 0; - -- if (mutex_lock_killable(&state->mutex)) -- return -EAGAIN; -+ mutex_lock(&state->mutex); - - /* Remove all services */ - vchiq_shutdown_internal(state, instance); -@@ -982,39 +1011,6 @@ exit: - } - - int --vchiq_platform_init_state(struct vchiq_state *state) --{ -- struct vchiq_arm_state *platform_state; -- char threadname[16]; -- -- platform_state = devm_kzalloc(state->dev, sizeof(*platform_state), GFP_KERNEL); -- if (!platform_state) -- return -ENOMEM; -- -- snprintf(threadname, sizeof(threadname), "vchiq-keep/%d", -- state->id); -- platform_state->ka_thread = kthread_create(&vchiq_keepalive_thread_func, -- (void *)state, threadname); -- if (IS_ERR(platform_state->ka_thread)) { -- dev_err(state->dev, "couldn't create thread %s\n", threadname); -- return PTR_ERR(platform_state->ka_thread); -- } -- -- rwlock_init(&platform_state->susp_res_lock); -- -- init_completion(&platform_state->ka_evt); -- atomic_set(&platform_state->ka_use_count, 0); -- atomic_set(&platform_state->ka_use_ack_count, 0); -- atomic_set(&platform_state->ka_release_count, 0); -- -- platform_state->state = state; -- -- state->platform_state = (struct opaque_platform_state *)platform_state; -- -- return 0; --} -- --int - vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service, - enum USE_TYPE_E use_type) - { -@@ -1329,19 +1325,37 @@ out: - return ret; - } - --void vchiq_platform_connected(struct vchiq_state *state) --{ -- struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); -- -- wake_up_process(arm_state->ka_thread); --} -- - void vchiq_platform_conn_state_changed(struct vchiq_state *state, - enum vchiq_connstate oldstate, - enum vchiq_connstate newstate) - { -+ struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); -+ char threadname[16]; -+ - dev_dbg(state->dev, "suspend: %d: %s->%s\n", - state->id, get_conn_state_name(oldstate), get_conn_state_name(newstate)); -+ if (state->conn_state != VCHIQ_CONNSTATE_CONNECTED) -+ return; -+ -+ write_lock_bh(&arm_state->susp_res_lock); -+ if (arm_state->first_connect) { -+ write_unlock_bh(&arm_state->susp_res_lock); -+ return; -+ } -+ -+ arm_state->first_connect = 1; -+ write_unlock_bh(&arm_state->susp_res_lock); -+ snprintf(threadname, sizeof(threadname), "vchiq-keep/%d", -+ state->id); -+ arm_state->ka_thread = kthread_create(&vchiq_keepalive_thread_func, -+ (void *)state, -+ threadname); -+ if (IS_ERR(arm_state->ka_thread)) { -+ dev_err(state->dev, "suspend: Couldn't create thread %s\n", -+ threadname); -+ } else { -+ wake_up_process(arm_state->ka_thread); -+ } - } - - static const struct of_device_id vchiq_of_match[] = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c BPI-Router-Linux-kernel-6.16.12/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c ---- BPI-Router-Linux-kernel/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c 2025-10-22 13:53:23.463327938 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c 2025-10-22 13:53:56.667168409 -0400 -@@ -3343,7 +3343,6 @@ vchiq_connect_internal(struct vchiq_stat - return -EAGAIN; - - vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED); -- vchiq_platform_connected(state); - complete(&state->connect); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h BPI-Router-Linux-kernel-6.16.12/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h ---- BPI-Router-Linux-kernel/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h 2025-10-22 13:53:23.463327938 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h 2025-10-22 13:53:56.667168409 -0400 -@@ -575,8 +575,6 @@ int vchiq_send_remote_use(struct vchiq_s - - int vchiq_send_remote_use_active(struct vchiq_state *state); - --void vchiq_platform_connected(struct vchiq_state *state); -- - void vchiq_platform_conn_state_changed(struct vchiq_state *state, - enum vchiq_connstate oldstate, - enum vchiq_connstate newstate); -diff -purNx .git BPI-Router-Linux-kernel/drivers/target/target_core_configfs.c BPI-Router-Linux-kernel-6.16.12/drivers/target/target_core_configfs.c ---- BPI-Router-Linux-kernel/drivers/target/target_core_configfs.c 2025-10-22 13:53:23.463327938 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/target/target_core_configfs.c 2025-10-22 13:53:56.667168409 -0400 -@@ -2774,7 +2774,7 @@ static ssize_t target_lu_gp_members_show - config_item_name(&dev->dev_group.cg_item)); - cur_len++; /* Extra byte for NULL terminator */ - -- if ((cur_len + len) > PAGE_SIZE) { -+ if ((cur_len + len) > PAGE_SIZE || cur_len > LU_GROUP_NAME_BUF) { - pr_warn("Ran out of lu_gp_show_attr" - "_members buffer\n"); - break; -diff -purNx .git BPI-Router-Linux-kernel/drivers/target/target_core_fabric_lib.c BPI-Router-Linux-kernel-6.16.12/drivers/target/target_core_fabric_lib.c ---- BPI-Router-Linux-kernel/drivers/target/target_core_fabric_lib.c 2025-10-22 13:53:23.463327938 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/target/target_core_fabric_lib.c 2025-10-22 13:53:56.667168409 -0400 -@@ -257,11 +257,41 @@ static int iscsi_get_pr_transport_id_len - return len; - } - --static char *iscsi_parse_pr_out_transport_id( -+static void sas_parse_pr_out_transport_id(char *buf, char *i_str) -+{ -+ char hex[17] = {}; -+ -+ bin2hex(hex, buf + 4, 8); -+ snprintf(i_str, TRANSPORT_IQN_LEN, "naa.%s", hex); -+} -+ -+static void srp_parse_pr_out_transport_id(char *buf, char *i_str) -+{ -+ char hex[33] = {}; -+ -+ bin2hex(hex, buf + 8, 16); -+ snprintf(i_str, TRANSPORT_IQN_LEN, "0x%s", hex); -+} -+ -+static void fcp_parse_pr_out_transport_id(char *buf, char *i_str) -+{ -+ snprintf(i_str, TRANSPORT_IQN_LEN, "%8phC", buf + 8); -+} -+ -+static void sbp_parse_pr_out_transport_id(char *buf, char *i_str) -+{ -+ char hex[17] = {}; -+ -+ bin2hex(hex, buf + 8, 8); -+ snprintf(i_str, TRANSPORT_IQN_LEN, "%s", hex); -+} -+ -+static bool iscsi_parse_pr_out_transport_id( - struct se_portal_group *se_tpg, - char *buf, - u32 *out_tid_len, -- char **port_nexus_ptr) -+ char **port_nexus_ptr, -+ char *i_str) - { - char *p; - int i; -@@ -282,7 +312,7 @@ static char *iscsi_parse_pr_out_transpor - if ((format_code != 0x00) && (format_code != 0x40)) { - pr_err("Illegal format code: 0x%02x for iSCSI" - " Initiator Transport ID\n", format_code); -- return NULL; -+ return false; - } - /* - * If the caller wants the TransportID Length, we set that value for the -@@ -306,7 +336,7 @@ static char *iscsi_parse_pr_out_transpor - pr_err("Unable to locate \",i,0x\" separator" - " for Initiator port identifier: %s\n", - &buf[4]); -- return NULL; -+ return false; - } - *p = '\0'; /* Terminate iSCSI Name */ - p += 5; /* Skip over ",i,0x" separator */ -@@ -339,7 +369,8 @@ static char *iscsi_parse_pr_out_transpor - } else - *port_nexus_ptr = NULL; - -- return &buf[4]; -+ strscpy(i_str, &buf[4], TRANSPORT_IQN_LEN); -+ return true; - } - - int target_get_pr_transport_id_len(struct se_node_acl *nacl, -@@ -387,33 +418,35 @@ int target_get_pr_transport_id(struct se - } - } - --const char *target_parse_pr_out_transport_id(struct se_portal_group *tpg, -- char *buf, u32 *out_tid_len, char **port_nexus_ptr) -+bool target_parse_pr_out_transport_id(struct se_portal_group *tpg, -+ char *buf, u32 *out_tid_len, char **port_nexus_ptr, char *i_str) - { -- u32 offset; -- - switch (tpg->proto_id) { - case SCSI_PROTOCOL_SAS: - /* - * Assume the FORMAT CODE 00b from spc4r17, 7.5.4.7 TransportID - * for initiator ports using SCSI over SAS Serial SCSI Protocol. - */ -- offset = 4; -+ sas_parse_pr_out_transport_id(buf, i_str); - break; -- case SCSI_PROTOCOL_SBP: - case SCSI_PROTOCOL_SRP: -+ srp_parse_pr_out_transport_id(buf, i_str); -+ break; - case SCSI_PROTOCOL_FCP: -- offset = 8; -+ fcp_parse_pr_out_transport_id(buf, i_str); -+ break; -+ case SCSI_PROTOCOL_SBP: -+ sbp_parse_pr_out_transport_id(buf, i_str); - break; - case SCSI_PROTOCOL_ISCSI: - return iscsi_parse_pr_out_transport_id(tpg, buf, out_tid_len, -- port_nexus_ptr); -+ port_nexus_ptr, i_str); - default: - pr_err("Unknown proto_id: 0x%02x\n", tpg->proto_id); -- return NULL; -+ return false; - } - - *port_nexus_ptr = NULL; - *out_tid_len = 24; -- return buf + offset; -+ return true; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/target/target_core_internal.h BPI-Router-Linux-kernel-6.16.12/drivers/target/target_core_internal.h ---- BPI-Router-Linux-kernel/drivers/target/target_core_internal.h 2025-10-22 13:53:23.463327938 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/target/target_core_internal.h 2025-10-22 13:53:56.667168409 -0400 -@@ -103,8 +103,8 @@ int target_get_pr_transport_id_len(struc - int target_get_pr_transport_id(struct se_node_acl *nacl, - struct t10_pr_registration *pr_reg, int *format_code, - unsigned char *buf); --const char *target_parse_pr_out_transport_id(struct se_portal_group *tpg, -- char *buf, u32 *out_tid_len, char **port_nexus_ptr); -+bool target_parse_pr_out_transport_id(struct se_portal_group *tpg, -+ char *buf, u32 *out_tid_len, char **port_nexus_ptr, char *i_str); - - /* target_core_hba.c */ - struct se_hba *core_alloc_hba(const char *, u32, u32); -diff -purNx .git BPI-Router-Linux-kernel/drivers/target/target_core_pr.c BPI-Router-Linux-kernel-6.16.12/drivers/target/target_core_pr.c ---- BPI-Router-Linux-kernel/drivers/target/target_core_pr.c 2025-10-22 13:53:23.463327938 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/target/target_core_pr.c 2025-10-22 13:53:56.671168389 -0400 -@@ -1478,11 +1478,12 @@ core_scsi3_decode_spec_i_port( - LIST_HEAD(tid_dest_list); - struct pr_transport_id_holder *tidh_new, *tidh, *tidh_tmp; - unsigned char *buf, *ptr, proto_ident; -- const unsigned char *i_str = NULL; -+ unsigned char i_str[TRANSPORT_IQN_LEN]; - char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN]; - sense_reason_t ret; - u32 tpdl, tid_len = 0; - u32 dest_rtpi = 0; -+ bool tid_found; - - /* - * Allocate a struct pr_transport_id_holder and setup the -@@ -1571,9 +1572,9 @@ core_scsi3_decode_spec_i_port( - dest_rtpi = tmp_lun->lun_tpg->tpg_rtpi; - - iport_ptr = NULL; -- i_str = target_parse_pr_out_transport_id(tmp_tpg, -- ptr, &tid_len, &iport_ptr); -- if (!i_str) -+ tid_found = target_parse_pr_out_transport_id(tmp_tpg, -+ ptr, &tid_len, &iport_ptr, i_str); -+ if (!tid_found) - continue; - /* - * Determine if this SCSI device server requires that -@@ -1842,7 +1843,9 @@ out: - } - - kmem_cache_free(t10_pr_reg_cache, dest_pr_reg); -- core_scsi3_lunacl_undepend_item(dest_se_deve); -+ -+ if (dest_se_deve) -+ core_scsi3_lunacl_undepend_item(dest_se_deve); - - if (is_local) - continue; -@@ -3151,13 +3154,14 @@ core_scsi3_emulate_pro_register_and_move - struct t10_pr_registration *pr_reg, *pr_res_holder, *dest_pr_reg; - struct t10_reservation *pr_tmpl = &dev->t10_pr; - unsigned char *buf; -- const unsigned char *initiator_str; -+ unsigned char initiator_str[TRANSPORT_IQN_LEN]; - char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN] = { }; - u32 tid_len, tmp_tid_len; - int new_reg = 0, type, scope, matching_iname; - sense_reason_t ret; - unsigned short rtpi; - unsigned char proto_ident; -+ bool tid_found; - - if (!se_sess || !se_lun) { - pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); -@@ -3276,9 +3280,9 @@ core_scsi3_emulate_pro_register_and_move - ret = TCM_INVALID_PARAMETER_LIST; - goto out; - } -- initiator_str = target_parse_pr_out_transport_id(dest_se_tpg, -- &buf[24], &tmp_tid_len, &iport_ptr); -- if (!initiator_str) { -+ tid_found = target_parse_pr_out_transport_id(dest_se_tpg, -+ &buf[24], &tmp_tid_len, &iport_ptr, initiator_str); -+ if (!tid_found) { - pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate" - " initiator_str from Transport ID\n"); - ret = TCM_INVALID_PARAMETER_LIST; -diff -purNx .git BPI-Router-Linux-kernel/drivers/tee/optee/ffa_abi.c BPI-Router-Linux-kernel-6.16.12/drivers/tee/optee/ffa_abi.c ---- BPI-Router-Linux-kernel/drivers/tee/optee/ffa_abi.c 2025-10-22 13:53:23.463327938 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/tee/optee/ffa_abi.c 2025-10-22 13:53:56.671168389 -0400 -@@ -657,7 +657,7 @@ static int optee_ffa_do_call_with_arg(st - * with a matching configuration. - */ - --static bool optee_ffa_api_is_compatbile(struct ffa_device *ffa_dev, -+static bool optee_ffa_api_is_compatible(struct ffa_device *ffa_dev, - const struct ffa_ops *ops) - { - const struct ffa_msg_ops *msg_ops = ops->msg_ops; -@@ -728,12 +728,21 @@ static bool optee_ffa_exchange_caps(stru - return true; - } - -+static void notif_work_fn(struct work_struct *work) -+{ -+ struct optee_ffa *optee_ffa = container_of(work, struct optee_ffa, -+ notif_work); -+ struct optee *optee = container_of(optee_ffa, struct optee, ffa); -+ -+ optee_do_bottom_half(optee->ctx); -+} -+ - static void notif_callback(int notify_id, void *cb_data) - { - struct optee *optee = cb_data; - - if (notify_id == optee->ffa.bottom_half_value) -- optee_do_bottom_half(optee->ctx); -+ queue_work(optee->ffa.notif_wq, &optee->ffa.notif_work); - else - optee_notif_send(optee, notify_id); - } -@@ -817,9 +826,11 @@ static void optee_ffa_remove(struct ffa_ - struct optee *optee = ffa_dev_get_drvdata(ffa_dev); - u32 bottom_half_id = optee->ffa.bottom_half_value; - -- if (bottom_half_id != U32_MAX) -+ if (bottom_half_id != U32_MAX) { - ffa_dev->ops->notifier_ops->notify_relinquish(ffa_dev, - bottom_half_id); -+ destroy_workqueue(optee->ffa.notif_wq); -+ } - optee_remove_common(optee); - - mutex_destroy(&optee->ffa.mutex); -@@ -835,6 +846,13 @@ static int optee_ffa_async_notif_init(st - u32 notif_id = 0; - int rc; - -+ INIT_WORK(&optee->ffa.notif_work, notif_work_fn); -+ optee->ffa.notif_wq = create_workqueue("optee_notification"); -+ if (!optee->ffa.notif_wq) { -+ rc = -EINVAL; -+ goto err; -+ } -+ - while (true) { - rc = ffa_dev->ops->notifier_ops->notify_request(ffa_dev, - is_per_vcpu, -@@ -851,19 +869,24 @@ static int optee_ffa_async_notif_init(st - * notifications in that case. - */ - if (rc != -EACCES) -- return rc; -+ goto err_wq; - notif_id++; - if (notif_id >= OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE) -- return rc; -+ goto err_wq; - } - optee->ffa.bottom_half_value = notif_id; - - rc = enable_async_notif(optee); -- if (rc < 0) { -- ffa_dev->ops->notifier_ops->notify_relinquish(ffa_dev, -- notif_id); -- optee->ffa.bottom_half_value = U32_MAX; -- } -+ if (rc < 0) -+ goto err_rel; -+ -+ return 0; -+err_rel: -+ ffa_dev->ops->notifier_ops->notify_relinquish(ffa_dev, notif_id); -+err_wq: -+ destroy_workqueue(optee->ffa.notif_wq); -+err: -+ optee->ffa.bottom_half_value = U32_MAX; - - return rc; - } -@@ -885,7 +908,7 @@ static int optee_ffa_probe(struct ffa_de - ffa_ops = ffa_dev->ops; - notif_ops = ffa_ops->notifier_ops; - -- if (!optee_ffa_api_is_compatbile(ffa_dev, ffa_ops)) -+ if (!optee_ffa_api_is_compatible(ffa_dev, ffa_ops)) - return -EINVAL; - - if (!optee_ffa_exchange_caps(ffa_dev, ffa_ops, &sec_caps, -diff -purNx .git BPI-Router-Linux-kernel/drivers/tee/optee/optee_private.h BPI-Router-Linux-kernel-6.16.12/drivers/tee/optee/optee_private.h ---- BPI-Router-Linux-kernel/drivers/tee/optee/optee_private.h 2025-10-22 13:53:23.463327938 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/tee/optee/optee_private.h 2025-10-22 13:53:56.671168389 -0400 -@@ -165,6 +165,8 @@ struct optee_ffa { - /* Serializes access to @global_ids */ - struct mutex mutex; - struct rhashtable global_ids; -+ struct workqueue_struct *notif_wq; -+ struct work_struct notif_work; - }; - - struct optee; -diff -purNx .git BPI-Router-Linux-kernel/drivers/tee/tee_shm.c BPI-Router-Linux-kernel-6.16.12/drivers/tee/tee_shm.c ---- BPI-Router-Linux-kernel/drivers/tee/tee_shm.c 2025-10-22 13:53:23.463327938 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/tee/tee_shm.c 2025-10-22 13:53:56.671168389 -0400 -@@ -230,7 +230,7 @@ int tee_dyn_shm_alloc_helper(struct tee_ - pages = kcalloc(nr_pages, sizeof(*pages), GFP_KERNEL); - if (!pages) { - rc = -ENOMEM; -- goto err; -+ goto err_pages; - } - - for (i = 0; i < nr_pages; i++) -@@ -243,11 +243,13 @@ int tee_dyn_shm_alloc_helper(struct tee_ - rc = shm_register(shm->ctx, shm, pages, nr_pages, - (unsigned long)shm->kaddr); - if (rc) -- goto err; -+ goto err_kfree; - } - - return 0; --err: -+err_kfree: -+ kfree(pages); -+err_pages: - free_pages_exact(shm->kaddr, shm->size); - shm->kaddr = NULL; - return rc; -@@ -560,9 +562,13 @@ EXPORT_SYMBOL_GPL(tee_shm_get_from_id); - */ - void tee_shm_put(struct tee_shm *shm) - { -- struct tee_device *teedev = shm->ctx->teedev; -+ struct tee_device *teedev; - bool do_release = false; - -+ if (!shm || !shm->ctx || !shm->ctx->teedev) -+ return; -+ -+ teedev = shm->ctx->teedev; - mutex_lock(&teedev->mutex); - if (refcount_dec_and_test(&shm->refcount)) { - /* -diff -purNx .git BPI-Router-Linux-kernel/drivers/thermal/qcom/qcom-spmi-temp-alarm.c BPI-Router-Linux-kernel-6.16.12/drivers/thermal/qcom/qcom-spmi-temp-alarm.c ---- BPI-Router-Linux-kernel/drivers/thermal/qcom/qcom-spmi-temp-alarm.c 2025-10-22 13:53:23.463327938 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/thermal/qcom/qcom-spmi-temp-alarm.c 2025-10-22 13:53:56.671168389 -0400 -@@ -1,6 +1,7 @@ - // SPDX-License-Identifier: GPL-2.0-only - /* - * Copyright (c) 2011-2015, 2017, 2020, The Linux Foundation. All rights reserved. -+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. - */ - - #include -@@ -16,6 +17,7 @@ - - #include "../thermal_hwmon.h" - -+#define QPNP_TM_REG_DIG_MINOR 0x00 - #define QPNP_TM_REG_DIG_MAJOR 0x01 - #define QPNP_TM_REG_TYPE 0x04 - #define QPNP_TM_REG_SUBTYPE 0x05 -@@ -31,7 +33,7 @@ - #define STATUS_GEN2_STATE_MASK GENMASK(6, 4) - #define STATUS_GEN2_STATE_SHIFT 4 - --#define SHUTDOWN_CTRL1_OVERRIDE_S2 BIT(6) -+#define SHUTDOWN_CTRL1_OVERRIDE_STAGE2 BIT(6) - #define SHUTDOWN_CTRL1_THRESHOLD_MASK GENMASK(1, 0) - - #define SHUTDOWN_CTRL1_RATE_25HZ BIT(3) -@@ -78,6 +80,7 @@ struct qpnp_tm_chip { - /* protects .thresh, .stage and chip registers */ - struct mutex lock; - bool initialized; -+ bool require_stage2_shutdown; - - struct iio_channel *adc; - const long (*temp_map)[THRESH_COUNT][STAGE_COUNT]; -@@ -220,13 +223,13 @@ static int qpnp_tm_update_critical_trip_ - { - long stage2_threshold_min = (*chip->temp_map)[THRESH_MIN][1]; - long stage2_threshold_max = (*chip->temp_map)[THRESH_MAX][1]; -- bool disable_s2_shutdown = false; -+ bool disable_stage2_shutdown = false; - u8 reg; - - WARN_ON(!mutex_is_locked(&chip->lock)); - - /* -- * Default: S2 and S3 shutdown enabled, thresholds at -+ * Default: Stage 2 and Stage 3 shutdown enabled, thresholds at - * lowest threshold set, monitoring at 25Hz - */ - reg = SHUTDOWN_CTRL1_RATE_25HZ; -@@ -241,12 +244,12 @@ static int qpnp_tm_update_critical_trip_ - chip->thresh = THRESH_MAX - - ((stage2_threshold_max - temp) / - TEMP_THRESH_STEP); -- disable_s2_shutdown = true; -+ disable_stage2_shutdown = true; - } else { - chip->thresh = THRESH_MAX; - - if (chip->adc) -- disable_s2_shutdown = true; -+ disable_stage2_shutdown = true; - else - dev_warn(chip->dev, - "No ADC is configured and critical temperature %d mC is above the maximum stage 2 threshold of %ld mC! Configuring stage 2 shutdown at %ld mC.\n", -@@ -255,8 +258,8 @@ static int qpnp_tm_update_critical_trip_ - - skip: - reg |= chip->thresh; -- if (disable_s2_shutdown) -- reg |= SHUTDOWN_CTRL1_OVERRIDE_S2; -+ if (disable_stage2_shutdown && !chip->require_stage2_shutdown) -+ reg |= SHUTDOWN_CTRL1_OVERRIDE_STAGE2; - - return qpnp_tm_write(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, reg); - } -@@ -350,8 +353,8 @@ static int qpnp_tm_probe(struct platform - { - struct qpnp_tm_chip *chip; - struct device_node *node; -- u8 type, subtype, dig_major; -- u32 res; -+ u8 type, subtype, dig_major, dig_minor; -+ u32 res, dig_revision; - int ret, irq; - - node = pdev->dev.of_node; -@@ -402,6 +405,11 @@ static int qpnp_tm_probe(struct platform - return dev_err_probe(&pdev->dev, ret, - "could not read dig_major\n"); - -+ ret = qpnp_tm_read(chip, QPNP_TM_REG_DIG_MINOR, &dig_minor); -+ if (ret < 0) -+ return dev_err_probe(&pdev->dev, ret, -+ "could not read dig_minor\n"); -+ - if (type != QPNP_TM_TYPE || (subtype != QPNP_TM_SUBTYPE_GEN1 - && subtype != QPNP_TM_SUBTYPE_GEN2)) { - dev_err(&pdev->dev, "invalid type 0x%02x or subtype 0x%02x\n", -@@ -415,6 +423,23 @@ static int qpnp_tm_probe(struct platform - else - chip->temp_map = &temp_map_gen1; - -+ if (chip->subtype == QPNP_TM_SUBTYPE_GEN2) { -+ dig_revision = (dig_major << 8) | dig_minor; -+ /* -+ * Check if stage 2 automatic partial shutdown must remain -+ * enabled to avoid potential repeated faults upon reaching -+ * over-temperature stage 3. -+ */ -+ switch (dig_revision) { -+ case 0x0001: -+ case 0x0002: -+ case 0x0100: -+ case 0x0101: -+ chip->require_stage2_shutdown = true; -+ break; -+ } -+ } -+ - /* - * Register the sensor before initializing the hardware to be able to - * read the trip points. get_temp() returns the default temperature -diff -purNx .git BPI-Router-Linux-kernel/drivers/thermal/thermal_sysfs.c BPI-Router-Linux-kernel-6.16.12/drivers/thermal/thermal_sysfs.c ---- BPI-Router-Linux-kernel/drivers/thermal/thermal_sysfs.c 2025-10-22 13:53:23.463327938 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/thermal/thermal_sysfs.c 2025-10-22 13:53:56.671168389 -0400 -@@ -40,10 +40,13 @@ temp_show(struct device *dev, struct dev - - ret = thermal_zone_get_temp(tz, &temperature); - -- if (ret) -- return ret; -+ if (!ret) -+ return sprintf(buf, "%d\n", temperature); - -- return sprintf(buf, "%d\n", temperature); -+ if (ret == -EAGAIN) -+ return -ENODATA; -+ -+ return ret; - } - - static ssize_t -diff -purNx .git BPI-Router-Linux-kernel/drivers/thunderbolt/domain.c BPI-Router-Linux-kernel-6.16.12/drivers/thunderbolt/domain.c ---- BPI-Router-Linux-kernel/drivers/thunderbolt/domain.c 2025-10-22 13:53:23.463327938 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/thunderbolt/domain.c 2025-10-22 13:53:56.671168389 -0400 -@@ -36,7 +36,7 @@ static bool match_service_id(const struc - return false; - } - -- if (id->match_flags & TBSVC_MATCH_PROTOCOL_VERSION) { -+ if (id->match_flags & TBSVC_MATCH_PROTOCOL_REVISION) { - if (id->protocol_revision != svc->prtcrevs) - return false; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/thunderbolt/switch.c BPI-Router-Linux-kernel-6.16.12/drivers/thunderbolt/switch.c ---- BPI-Router-Linux-kernel/drivers/thunderbolt/switch.c 2025-10-22 13:53:23.463327938 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/thunderbolt/switch.c 2025-10-22 13:53:56.671168389 -0400 -@@ -1450,7 +1450,7 @@ int tb_dp_port_set_hops(struct tb_port * - return ret; - - data[0] &= ~ADP_DP_CS_0_VIDEO_HOPID_MASK; -- data[1] &= ~ADP_DP_CS_1_AUX_RX_HOPID_MASK; -+ data[1] &= ~ADP_DP_CS_1_AUX_TX_HOPID_MASK; - data[1] &= ~ADP_DP_CS_1_AUX_RX_HOPID_MASK; - - data[0] |= (video << ADP_DP_CS_0_VIDEO_HOPID_SHIFT) & -@@ -3437,7 +3437,7 @@ void tb_sw_set_unplugged(struct tb_switc - } - } - --static int tb_switch_set_wake(struct tb_switch *sw, unsigned int flags) -+static int tb_switch_set_wake(struct tb_switch *sw, unsigned int flags, bool runtime) - { - if (flags) - tb_sw_dbg(sw, "enabling wakeup: %#x\n", flags); -@@ -3445,7 +3445,7 @@ static int tb_switch_set_wake(struct tb_ - tb_sw_dbg(sw, "disabling wakeup\n"); - - if (tb_switch_is_usb4(sw)) -- return usb4_switch_set_wake(sw, flags); -+ return usb4_switch_set_wake(sw, flags, runtime); - return tb_lc_set_wake(sw, flags); - } - -@@ -3521,7 +3521,7 @@ int tb_switch_resume(struct tb_switch *s - tb_switch_check_wakes(sw); - - /* Disable wakes */ -- tb_switch_set_wake(sw, 0); -+ tb_switch_set_wake(sw, 0, true); - - err = tb_switch_tmu_init(sw); - if (err) -@@ -3603,7 +3603,7 @@ void tb_switch_suspend(struct tb_switch - flags |= TB_WAKE_ON_USB4 | TB_WAKE_ON_USB3 | TB_WAKE_ON_PCIE; - } - -- tb_switch_set_wake(sw, flags); -+ tb_switch_set_wake(sw, flags, runtime); - - if (tb_switch_is_usb4(sw)) - usb4_switch_set_sleep(sw); -diff -purNx .git BPI-Router-Linux-kernel/drivers/thunderbolt/tb.h BPI-Router-Linux-kernel-6.16.12/drivers/thunderbolt/tb.h ---- BPI-Router-Linux-kernel/drivers/thunderbolt/tb.h 2025-10-22 13:53:23.463327938 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/thunderbolt/tb.h 2025-10-22 13:53:56.671168389 -0400 -@@ -1317,7 +1317,7 @@ int usb4_switch_read_uid(struct tb_switc - int usb4_switch_drom_read(struct tb_switch *sw, unsigned int address, void *buf, - size_t size); - bool usb4_switch_lane_bonding_possible(struct tb_switch *sw); --int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags); -+int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags, bool runtime); - int usb4_switch_set_sleep(struct tb_switch *sw); - int usb4_switch_nvm_sector_size(struct tb_switch *sw); - int usb4_switch_nvm_read(struct tb_switch *sw, unsigned int address, void *buf, -diff -purNx .git BPI-Router-Linux-kernel/drivers/thunderbolt/usb4.c BPI-Router-Linux-kernel-6.16.12/drivers/thunderbolt/usb4.c ---- BPI-Router-Linux-kernel/drivers/thunderbolt/usb4.c 2025-10-22 13:53:23.463327938 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/thunderbolt/usb4.c 2025-10-22 13:53:56.671168389 -0400 -@@ -403,12 +403,12 @@ bool usb4_switch_lane_bonding_possible(s - * usb4_switch_set_wake() - Enabled/disable wake - * @sw: USB4 router - * @flags: Wakeup flags (%0 to disable) -+ * @runtime: Wake is being programmed during system runtime - * - * Enables/disables router to wake up from sleep. - */ --int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags) -+int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags, bool runtime) - { -- struct usb4_port *usb4; - struct tb_port *port; - u64 route = tb_route(sw); - u32 val; -@@ -438,13 +438,11 @@ int usb4_switch_set_wake(struct tb_switc - val |= PORT_CS_19_WOU4; - } else { - bool configured = val & PORT_CS_19_PC; -- usb4 = port->usb4; -+ bool wakeup = runtime || device_may_wakeup(&port->usb4->dev); - -- if (((flags & TB_WAKE_ON_CONNECT) && -- device_may_wakeup(&usb4->dev)) && !configured) -+ if ((flags & TB_WAKE_ON_CONNECT) && wakeup && !configured) - val |= PORT_CS_19_WOC; -- if (((flags & TB_WAKE_ON_DISCONNECT) && -- device_may_wakeup(&usb4->dev)) && configured) -+ if ((flags & TB_WAKE_ON_DISCONNECT) && wakeup && configured) - val |= PORT_CS_19_WOD; - if ((flags & TB_WAKE_ON_USB4) && configured) - val |= PORT_CS_19_WOU4; -diff -purNx .git BPI-Router-Linux-kernel/drivers/tty/hvc/hvc_console.c BPI-Router-Linux-kernel-6.16.12/drivers/tty/hvc/hvc_console.c ---- BPI-Router-Linux-kernel/drivers/tty/hvc/hvc_console.c 2025-10-22 13:53:23.463327938 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/tty/hvc/hvc_console.c 2025-10-22 13:53:56.671168389 -0400 -@@ -543,10 +543,10 @@ static ssize_t hvc_write(struct tty_stru - } - - /* -- * Racy, but harmless, kick thread if there is still pending data. -+ * Kick thread to flush if there's still pending data -+ * or to wakeup the write queue. - */ -- if (hp->n_outbuf) -- hvc_kick(); -+ hvc_kick(); - - return written; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/tty/serial/8250/8250_port.c BPI-Router-Linux-kernel-6.16.12/drivers/tty/serial/8250/8250_port.c ---- BPI-Router-Linux-kernel/drivers/tty/serial/8250/8250_port.c 2025-10-22 13:53:23.463327938 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/tty/serial/8250/8250_port.c 2025-10-22 13:53:56.671168389 -0400 -@@ -2376,9 +2376,8 @@ int serial8250_do_startup(struct uart_po - /* - * Now, initialize the UART - */ -- serial_port_out(port, UART_LCR, UART_LCR_WLEN8); -- - uart_port_lock_irqsave(port, &flags); -+ serial_port_out(port, UART_LCR, UART_LCR_WLEN8); - if (up->port.flags & UPF_FOURPORT) { - if (!up->port.irq) - up->port.mctrl |= TIOCM_OUT1; -diff -purNx .git BPI-Router-Linux-kernel/drivers/tty/serial/imx.c BPI-Router-Linux-kernel-6.16.12/drivers/tty/serial/imx.c ---- BPI-Router-Linux-kernel/drivers/tty/serial/imx.c 2025-10-22 13:53:23.463327938 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/tty/serial/imx.c 2025-10-22 13:53:56.671168389 -0400 -@@ -235,6 +235,7 @@ struct imx_port { - enum imx_tx_state tx_state; - struct hrtimer trigger_start_tx; - struct hrtimer trigger_stop_tx; -+ unsigned int rxtl; - }; - - struct imx_port_ucrs { -@@ -1339,6 +1340,7 @@ static void imx_uart_clear_rx_errors(str - - #define TXTL_DEFAULT 8 - #define RXTL_DEFAULT 8 /* 8 characters or aging timer */ -+#define RXTL_CONSOLE_DEFAULT 1 - #define TXTL_DMA 8 /* DMA burst setting */ - #define RXTL_DMA 9 /* DMA burst setting */ - -@@ -1457,7 +1459,7 @@ static void imx_uart_disable_dma(struct - ucr1 &= ~(UCR1_RXDMAEN | UCR1_TXDMAEN | UCR1_ATDMAEN); - imx_uart_writel(sport, ucr1, UCR1); - -- imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT); -+ imx_uart_setup_ufcr(sport, TXTL_DEFAULT, sport->rxtl); - - sport->dma_is_enabled = 0; - } -@@ -1482,7 +1484,12 @@ static int imx_uart_startup(struct uart_ - return retval; - } - -- imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT); -+ if (uart_console(&sport->port)) -+ sport->rxtl = RXTL_CONSOLE_DEFAULT; -+ else -+ sport->rxtl = RXTL_DEFAULT; -+ -+ imx_uart_setup_ufcr(sport, TXTL_DEFAULT, sport->rxtl); - - /* disable the DREN bit (Data Ready interrupt enable) before - * requesting IRQs -@@ -1948,7 +1955,7 @@ static int imx_uart_poll_init(struct uar - if (retval) - clk_disable_unprepare(sport->clk_ipg); - -- imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT); -+ imx_uart_setup_ufcr(sport, TXTL_DEFAULT, sport->rxtl); - - uart_port_lock_irqsave(&sport->port, &flags); - -@@ -2040,7 +2047,7 @@ static int imx_uart_rs485_config(struct - /* If the receiver trigger is 0, set it to a default value */ - ufcr = imx_uart_readl(sport, UFCR); - if ((ufcr & UFCR_RXTL_MASK) == 0) -- imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT); -+ imx_uart_setup_ufcr(sport, TXTL_DEFAULT, sport->rxtl); - imx_uart_start_rx(port); - } - -@@ -2302,7 +2309,7 @@ imx_uart_console_setup(struct console *c - else - imx_uart_console_get_options(sport, &baud, &parity, &bits); - -- imx_uart_setup_ufcr(sport, TXTL_DEFAULT, RXTL_DEFAULT); -+ imx_uart_setup_ufcr(sport, TXTL_DEFAULT, sport->rxtl); - - retval = uart_set_options(&sport->port, co, baud, parity, bits, flow); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/tty/serial/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/tty/serial/Kconfig ---- BPI-Router-Linux-kernel/drivers/tty/serial/Kconfig 2025-10-22 13:53:23.463327938 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/tty/serial/Kconfig 2025-10-22 13:53:56.671168389 -0400 -@@ -1405,7 +1405,7 @@ config SERIAL_STM32 - - config SERIAL_STM32_CONSOLE - bool "Support for console on STM32" -- depends on SERIAL_STM32=y -+ depends on SERIAL_STM32 - select SERIAL_CORE_CONSOLE - select SERIAL_EARLYCON - -diff -purNx .git BPI-Router-Linux-kernel/drivers/tty/serial/pch_uart.c BPI-Router-Linux-kernel-6.16.12/drivers/tty/serial/pch_uart.c ---- BPI-Router-Linux-kernel/drivers/tty/serial/pch_uart.c 2025-10-22 13:53:23.467327919 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/tty/serial/pch_uart.c 2025-10-22 13:53:56.671168389 -0400 -@@ -954,7 +954,7 @@ static unsigned int dma_handle_tx(struct - __func__); - return 0; - } -- dma_sync_sg_for_device(port->dev, priv->sg_tx_p, nent, DMA_TO_DEVICE); -+ dma_sync_sg_for_device(port->dev, priv->sg_tx_p, num, DMA_TO_DEVICE); - priv->desc_tx = desc; - desc->callback = pch_dma_tx_complete; - desc->callback_param = priv; -diff -purNx .git BPI-Router-Linux-kernel/drivers/tty/serial/sc16is7xx.c BPI-Router-Linux-kernel-6.16.12/drivers/tty/serial/sc16is7xx.c ---- BPI-Router-Linux-kernel/drivers/tty/serial/sc16is7xx.c 2025-10-22 13:53:23.467327919 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/tty/serial/sc16is7xx.c 2025-10-22 13:53:56.671168389 -0400 -@@ -1177,17 +1177,6 @@ static int sc16is7xx_startup(struct uart - sc16is7xx_port_write(port, SC16IS7XX_FCR_REG, - SC16IS7XX_FCR_FIFO_BIT); - -- /* Enable EFR */ -- sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, -- SC16IS7XX_LCR_CONF_MODE_B); -- -- regcache_cache_bypass(one->regmap, true); -- -- /* Enable write access to enhanced features and internal clock div */ -- sc16is7xx_port_update(port, SC16IS7XX_EFR_REG, -- SC16IS7XX_EFR_ENABLE_BIT, -- SC16IS7XX_EFR_ENABLE_BIT); -- - /* Enable TCR/TLR */ - sc16is7xx_port_update(port, SC16IS7XX_MCR_REG, - SC16IS7XX_MCR_TCRTLR_BIT, -@@ -1199,7 +1188,8 @@ static int sc16is7xx_startup(struct uart - SC16IS7XX_TCR_RX_RESUME(24) | - SC16IS7XX_TCR_RX_HALT(48)); - -- regcache_cache_bypass(one->regmap, false); -+ /* Disable TCR/TLR access */ -+ sc16is7xx_port_update(port, SC16IS7XX_MCR_REG, SC16IS7XX_MCR_TCRTLR_BIT, 0); - - /* Now, initialize the UART */ - sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, SC16IS7XX_LCR_WORD_LEN_8); -diff -purNx .git BPI-Router-Linux-kernel/drivers/tty/serial/serial_base_bus.c BPI-Router-Linux-kernel-6.16.12/drivers/tty/serial/serial_base_bus.c ---- BPI-Router-Linux-kernel/drivers/tty/serial/serial_base_bus.c 2025-10-22 13:53:23.467327919 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/tty/serial/serial_base_bus.c 2025-10-22 13:53:56.671168389 -0400 -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -72,6 +73,7 @@ static int serial_base_device_init(struc - dev->parent = parent_dev; - dev->bus = &serial_base_bus_type; - dev->release = release; -+ device_set_of_node_from_dev(dev, parent_dev); - - if (!serial_base_initialized) { - dev_dbg(port->dev, "uart_add_one_port() called before arch_initcall()?\n"); -@@ -92,6 +94,7 @@ static void serial_base_ctrl_release(str - { - struct serial_ctrl_device *ctrl_dev = to_serial_base_ctrl_device(dev); - -+ of_node_put(dev->of_node); - kfree(ctrl_dev); - } - -@@ -139,6 +142,7 @@ static void serial_base_port_release(str - { - struct serial_port_device *port_dev = to_serial_base_port_device(dev); - -+ of_node_put(dev->of_node); - kfree(port_dev); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/tty/serial/serial_core.c BPI-Router-Linux-kernel-6.16.12/drivers/tty/serial/serial_core.c ---- BPI-Router-Linux-kernel/drivers/tty/serial/serial_core.c 2025-10-22 13:53:23.467327919 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/tty/serial/serial_core.c 2025-10-22 13:53:56.671168389 -0400 -@@ -1337,28 +1337,28 @@ static void uart_sanitize_serial_rs485_d - if (!port->rs485_supported.delay_rts_before_send) { - if (rs485->delay_rts_before_send) { - dev_warn_ratelimited(port->dev, -- "%s (%d): RTS delay before sending not supported\n", -+ "%s (%u): RTS delay before sending not supported\n", - port->name, port->line); - } - rs485->delay_rts_before_send = 0; - } else if (rs485->delay_rts_before_send > RS485_MAX_RTS_DELAY) { - rs485->delay_rts_before_send = RS485_MAX_RTS_DELAY; - dev_warn_ratelimited(port->dev, -- "%s (%d): RTS delay before sending clamped to %u ms\n", -+ "%s (%u): RTS delay before sending clamped to %u ms\n", - port->name, port->line, rs485->delay_rts_before_send); - } - - if (!port->rs485_supported.delay_rts_after_send) { - if (rs485->delay_rts_after_send) { - dev_warn_ratelimited(port->dev, -- "%s (%d): RTS delay after sending not supported\n", -+ "%s (%u): RTS delay after sending not supported\n", - port->name, port->line); - } - rs485->delay_rts_after_send = 0; - } else if (rs485->delay_rts_after_send > RS485_MAX_RTS_DELAY) { - rs485->delay_rts_after_send = RS485_MAX_RTS_DELAY; - dev_warn_ratelimited(port->dev, -- "%s (%d): RTS delay after sending clamped to %u ms\n", -+ "%s (%u): RTS delay after sending clamped to %u ms\n", - port->name, port->line, rs485->delay_rts_after_send); - } - } -@@ -1388,14 +1388,14 @@ static void uart_sanitize_serial_rs485(s - rs485->flags &= ~SER_RS485_RTS_AFTER_SEND; - - dev_warn_ratelimited(port->dev, -- "%s (%d): invalid RTS setting, using RTS_ON_SEND instead\n", -+ "%s (%u): invalid RTS setting, using RTS_ON_SEND instead\n", - port->name, port->line); - } else { - rs485->flags |= SER_RS485_RTS_AFTER_SEND; - rs485->flags &= ~SER_RS485_RTS_ON_SEND; - - dev_warn_ratelimited(port->dev, -- "%s (%d): invalid RTS setting, using RTS_AFTER_SEND instead\n", -+ "%s (%u): invalid RTS setting, using RTS_AFTER_SEND instead\n", - port->name, port->line); - } - } -@@ -1834,7 +1834,7 @@ static void uart_wait_until_sent(struct - - expire = jiffies + timeout; - -- pr_debug("uart_wait_until_sent(%d), jiffies=%lu, expire=%lu...\n", -+ pr_debug("uart_wait_until_sent(%u), jiffies=%lu, expire=%lu...\n", - port->line, jiffies, expire); - - /* -@@ -2028,7 +2028,7 @@ static void uart_line_info(struct seq_fi - return; - - mmio = uport->iotype >= UPIO_MEM; -- seq_printf(m, "%d: uart:%s %s%08llX irq:%d", -+ seq_printf(m, "%u: uart:%s %s%08llX irq:%u", - uport->line, uart_type(uport), - mmio ? "mmio:0x" : "port:", - mmio ? (unsigned long long)uport->mapbase -@@ -2050,18 +2050,18 @@ static void uart_line_info(struct seq_fi - if (pm_state != UART_PM_STATE_ON) - uart_change_pm(state, pm_state); - -- seq_printf(m, " tx:%d rx:%d", -+ seq_printf(m, " tx:%u rx:%u", - uport->icount.tx, uport->icount.rx); - if (uport->icount.frame) -- seq_printf(m, " fe:%d", uport->icount.frame); -+ seq_printf(m, " fe:%u", uport->icount.frame); - if (uport->icount.parity) -- seq_printf(m, " pe:%d", uport->icount.parity); -+ seq_printf(m, " pe:%u", uport->icount.parity); - if (uport->icount.brk) -- seq_printf(m, " brk:%d", uport->icount.brk); -+ seq_printf(m, " brk:%u", uport->icount.brk); - if (uport->icount.overrun) -- seq_printf(m, " oe:%d", uport->icount.overrun); -+ seq_printf(m, " oe:%u", uport->icount.overrun); - if (uport->icount.buf_overrun) -- seq_printf(m, " bo:%d", uport->icount.buf_overrun); -+ seq_printf(m, " bo:%u", uport->icount.buf_overrun); - - #define INFOBIT(bit, str) \ - if (uport->mctrl & (bit)) \ -@@ -2553,7 +2553,7 @@ uart_report_port(struct uart_driver *drv - break; - } - -- pr_info("%s%s%s at %s (irq = %d, base_baud = %d) is a %s\n", -+ pr_info("%s%s%s at %s (irq = %u, base_baud = %u) is a %s\n", - port->dev ? dev_name(port->dev) : "", - port->dev ? ": " : "", - port->name, -@@ -2561,7 +2561,7 @@ uart_report_port(struct uart_driver *drv - - /* The magic multiplier feature is a bit obscure, so report it too. */ - if (port->flags & UPF_MAGIC_MULTIPLIER) -- pr_info("%s%s%s extra baud rates supported: %d, %d", -+ pr_info("%s%s%s extra baud rates supported: %u, %u", - port->dev ? dev_name(port->dev) : "", - port->dev ? ": " : "", - port->name, -@@ -2960,7 +2960,7 @@ static ssize_t close_delay_show(struct d - struct tty_port *port = dev_get_drvdata(dev); - - uart_get_info(port, &tmp); -- return sprintf(buf, "%d\n", tmp.close_delay); -+ return sprintf(buf, "%u\n", tmp.close_delay); - } - - static ssize_t closing_wait_show(struct device *dev, -@@ -2970,7 +2970,7 @@ static ssize_t closing_wait_show(struct - struct tty_port *port = dev_get_drvdata(dev); - - uart_get_info(port, &tmp); -- return sprintf(buf, "%d\n", tmp.closing_wait); -+ return sprintf(buf, "%u\n", tmp.closing_wait); - } - - static ssize_t custom_divisor_show(struct device *dev, -@@ -2990,7 +2990,7 @@ static ssize_t io_type_show(struct devic - struct tty_port *port = dev_get_drvdata(dev); - - uart_get_info(port, &tmp); -- return sprintf(buf, "%d\n", tmp.io_type); -+ return sprintf(buf, "%u\n", tmp.io_type); - } - - static ssize_t iomem_base_show(struct device *dev, -@@ -3010,7 +3010,7 @@ static ssize_t iomem_reg_shift_show(stru - struct tty_port *port = dev_get_drvdata(dev); - - uart_get_info(port, &tmp); -- return sprintf(buf, "%d\n", tmp.iomem_reg_shift); -+ return sprintf(buf, "%u\n", tmp.iomem_reg_shift); - } - - static ssize_t console_show(struct device *dev, -@@ -3146,7 +3146,7 @@ static int serial_core_add_one_port(stru - state->pm_state = UART_PM_STATE_UNDEFINED; - uart_port_set_cons(uport, drv->cons); - uport->minor = drv->tty_driver->minor_start + uport->line; -- uport->name = kasprintf(GFP_KERNEL, "%s%d", drv->dev_name, -+ uport->name = kasprintf(GFP_KERNEL, "%s%u", drv->dev_name, - drv->tty_driver->name_base + uport->line); - if (!uport->name) - return -ENOMEM; -@@ -3185,7 +3185,7 @@ static int serial_core_add_one_port(stru - device_set_wakeup_capable(tty_dev, 1); - } else { - uport->flags |= UPF_DEAD; -- dev_err(uport->dev, "Cannot register tty device on line %d\n", -+ dev_err(uport->dev, "Cannot register tty device on line %u\n", - uport->line); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/tty/vt/defkeymap.c_shipped BPI-Router-Linux-kernel-6.16.12/drivers/tty/vt/defkeymap.c_shipped ---- BPI-Router-Linux-kernel/drivers/tty/vt/defkeymap.c_shipped 2025-10-22 13:53:23.467327919 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/tty/vt/defkeymap.c_shipped 2025-10-22 13:53:56.671168389 -0400 -@@ -23,6 +23,22 @@ unsigned short plain_map[NR_KEYS] = { - 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, - 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - }; - - static unsigned short shift_map[NR_KEYS] = { -@@ -42,6 +58,22 @@ static unsigned short shift_map[NR_KEYS] - 0xf20b, 0xf601, 0xf602, 0xf117, 0xf600, 0xf20a, 0xf115, 0xf116, - 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - }; - - static unsigned short altgr_map[NR_KEYS] = { -@@ -61,6 +93,22 @@ static unsigned short altgr_map[NR_KEYS] - 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, - 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - }; - - static unsigned short ctrl_map[NR_KEYS] = { -@@ -80,6 +128,22 @@ static unsigned short ctrl_map[NR_KEYS] - 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, - 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - }; - - static unsigned short shift_ctrl_map[NR_KEYS] = { -@@ -99,6 +163,22 @@ static unsigned short shift_ctrl_map[NR_ - 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, - 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - }; - - static unsigned short alt_map[NR_KEYS] = { -@@ -118,6 +198,22 @@ static unsigned short alt_map[NR_KEYS] = - 0xf118, 0xf210, 0xf211, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, - 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - }; - - static unsigned short ctrl_alt_map[NR_KEYS] = { -@@ -137,6 +233,22 @@ static unsigned short ctrl_alt_map[NR_KE - 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf20c, - 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, -+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - }; - - unsigned short *key_maps[MAX_NR_KEYMAPS] = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/tty/vt/keyboard.c BPI-Router-Linux-kernel-6.16.12/drivers/tty/vt/keyboard.c ---- BPI-Router-Linux-kernel/drivers/tty/vt/keyboard.c 2025-10-22 13:53:23.467327919 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/tty/vt/keyboard.c 2025-10-22 13:53:56.671168389 -0400 -@@ -1487,7 +1487,7 @@ static void kbd_keycode(unsigned int key - rc = atomic_notifier_call_chain(&keyboard_notifier_list, - KBD_UNICODE, ¶m); - if (rc != NOTIFY_STOP) -- if (down && !raw_mode) -+ if (down && !(raw_mode || kbd->kbdmode == VC_OFF)) - k_unicode(vc, keysym, !down); - return; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/tty/vt/ucs.c BPI-Router-Linux-kernel-6.16.12/drivers/tty/vt/ucs.c ---- BPI-Router-Linux-kernel/drivers/tty/vt/ucs.c 2025-10-22 13:53:23.467327919 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/tty/vt/ucs.c 2025-10-22 13:53:56.671168389 -0400 -@@ -206,7 +206,7 @@ static int ucs_page_entry_cmp(const void - - /** - * ucs_get_fallback() - Get a substitution for the provided Unicode character -- * @base: Base Unicode code point (UCS-4) -+ * @cp: Unicode code point (UCS-4) - * - * Get a simpler fallback character for the provided Unicode character. - * This is used for terminal display when corresponding glyph is unavailable. -diff -purNx .git BPI-Router-Linux-kernel/drivers/tty/vt/vt.c BPI-Router-Linux-kernel-6.16.12/drivers/tty/vt/vt.c ---- BPI-Router-Linux-kernel/drivers/tty/vt/vt.c 2025-10-22 13:53:23.467327919 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/tty/vt/vt.c 2025-10-22 13:53:56.671168389 -0400 -@@ -4650,6 +4650,7 @@ void do_unblank_screen(int leaving_gfx) - set_palette(vc); - set_cursor(vc); - vt_event_post(VT_EVENT_UNBLANK, vc->vc_num, vc->vc_num); -+ notify_update(vc); - } - EXPORT_SYMBOL(do_unblank_screen); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/ufs/core/ufshcd.c BPI-Router-Linux-kernel-6.16.12/drivers/ufs/core/ufshcd.c ---- BPI-Router-Linux-kernel/drivers/ufs/core/ufshcd.c 2025-10-22 13:53:23.467327919 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/ufs/core/ufshcd.c 2025-10-22 13:53:56.675168370 -0400 -@@ -4340,7 +4340,7 @@ out: - hba->uic_async_done = NULL; - if (reenable_intr) - ufshcd_enable_intr(hba, UIC_COMMAND_COMPL); -- if (ret) { -+ if (ret && !hba->pm_op_in_progress) { - ufshcd_set_link_broken(hba); - ufshcd_schedule_eh_work(hba); - } -@@ -4348,6 +4348,14 @@ out_unlock: - spin_unlock_irqrestore(hba->host->host_lock, flags); - mutex_unlock(&hba->uic_cmd_mutex); - -+ /* -+ * If the h8 exit fails during the runtime resume process, it becomes -+ * stuck and cannot be recovered through the error handler. To fix -+ * this, use link recovery instead of the error handler. -+ */ -+ if (ret && hba->pm_op_in_progress) -+ ret = ufshcd_link_recovery(hba); -+ - return ret; - } - -@@ -5523,9 +5531,9 @@ static irqreturn_t ufshcd_uic_cmd_compl( - irqreturn_t retval = IRQ_NONE; - struct uic_command *cmd; - -- spin_lock(hba->host->host_lock); -+ guard(spinlock_irqsave)(hba->host->host_lock); - cmd = hba->active_uic_cmd; -- if (WARN_ON_ONCE(!cmd)) -+ if (!cmd) - goto unlock; - - if (ufshcd_is_auto_hibern8_error(hba, intr_status)) -@@ -5550,8 +5558,6 @@ static irqreturn_t ufshcd_uic_cmd_compl( - ufshcd_add_uic_command_trace(hba, cmd, UFS_CMD_COMP); - - unlock: -- spin_unlock(hba->host->host_lock); -- - return retval; - } - -@@ -6623,9 +6629,14 @@ static void ufshcd_err_handler(struct wo - up(&hba->host_sem); - return; - } -- ufshcd_set_eh_in_progress(hba); - spin_unlock_irqrestore(hba->host->host_lock, flags); -+ - ufshcd_err_handling_prepare(hba); -+ -+ spin_lock_irqsave(hba->host->host_lock, flags); -+ ufshcd_set_eh_in_progress(hba); -+ spin_unlock_irqrestore(hba->host->host_lock, flags); -+ - /* Complete requests that have door-bell cleared by h/w */ - ufshcd_complete_requests(hba, false); - spin_lock_irqsave(hba->host->host_lock, flags); -@@ -6879,7 +6890,7 @@ static irqreturn_t ufshcd_check_errors(s - bool queue_eh_work = false; - irqreturn_t retval = IRQ_NONE; - -- spin_lock(hba->host->host_lock); -+ guard(spinlock_irqsave)(hba->host->host_lock); - hba->errors |= UFSHCD_ERROR_MASK & intr_status; - - if (hba->errors & INT_FATAL_ERRORS) { -@@ -6938,7 +6949,7 @@ static irqreturn_t ufshcd_check_errors(s - */ - hba->errors = 0; - hba->uic_error = 0; -- spin_unlock(hba->host->host_lock); -+ - return retval; - } - -@@ -7097,14 +7108,19 @@ static irqreturn_t ufshcd_threaded_intr( - static irqreturn_t ufshcd_intr(int irq, void *__hba) - { - struct ufs_hba *hba = __hba; -+ u32 intr_status, enabled_intr_status; - - /* Move interrupt handling to thread when MCQ & ESI are not enabled */ - if (!hba->mcq_enabled || !hba->mcq_esi_enabled) - return IRQ_WAKE_THREAD; - -+ intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS); -+ enabled_intr_status = intr_status & ufshcd_readl(hba, REG_INTERRUPT_ENABLE); -+ -+ ufshcd_writel(hba, intr_status, REG_INTERRUPT_STATUS); -+ - /* Directly handle interrupts since MCQ ESI handlers does the hard job */ -- return ufshcd_sl_intr(hba, ufshcd_readl(hba, REG_INTERRUPT_STATUS) & -- ufshcd_readl(hba, REG_INTERRUPT_ENABLE)); -+ return ufshcd_sl_intr(hba, enabled_intr_status); - } - - static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag) -@@ -7802,7 +7818,8 @@ static int ufshcd_host_reset_and_restore - hba->silence_err_logs = false; - - /* scale up clocks to max frequency before full reinitialization */ -- ufshcd_scale_clks(hba, ULONG_MAX, true); -+ if (ufshcd_is_clkscaling_supported(hba)) -+ ufshcd_scale_clks(hba, ULONG_MAX, true); - - err = ufshcd_hba_enable(hba); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/ufs/core/ufs-mcq.c BPI-Router-Linux-kernel-6.16.12/drivers/ufs/core/ufs-mcq.c ---- BPI-Router-Linux-kernel/drivers/ufs/core/ufs-mcq.c 2025-10-22 13:53:23.467327919 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/ufs/core/ufs-mcq.c 2025-10-22 13:53:56.675168370 -0400 -@@ -243,7 +243,7 @@ int ufshcd_mcq_memory_alloc(struct ufs_h - hwq->sqe_base_addr = dmam_alloc_coherent(hba->dev, utrdl_size, - &hwq->sqe_dma_addr, - GFP_KERNEL); -- if (!hwq->sqe_dma_addr) { -+ if (!hwq->sqe_base_addr) { - dev_err(hba->dev, "SQE allocation failed\n"); - return -ENOMEM; - } -@@ -252,7 +252,7 @@ int ufshcd_mcq_memory_alloc(struct ufs_h - hwq->cqe_base_addr = dmam_alloc_coherent(hba->dev, cqe_size, - &hwq->cqe_dma_addr, - GFP_KERNEL); -- if (!hwq->cqe_dma_addr) { -+ if (!hwq->cqe_base_addr) { - dev_err(hba->dev, "CQE allocation failed\n"); - return -ENOMEM; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/ufs/core/ufs-sysfs.c BPI-Router-Linux-kernel-6.16.12/drivers/ufs/core/ufs-sysfs.c ---- BPI-Router-Linux-kernel/drivers/ufs/core/ufs-sysfs.c 2025-10-22 13:53:23.467327919 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/ufs/core/ufs-sysfs.c 2025-10-22 13:53:56.675168370 -0400 -@@ -1808,7 +1808,7 @@ UFS_UNIT_DESC_PARAM(logical_block_size, - UFS_UNIT_DESC_PARAM(logical_block_count, _LOGICAL_BLK_COUNT, 8); - UFS_UNIT_DESC_PARAM(erase_block_size, _ERASE_BLK_SIZE, 4); - UFS_UNIT_DESC_PARAM(provisioning_type, _PROVISIONING_TYPE, 1); --UFS_UNIT_DESC_PARAM(physical_memory_resourse_count, _PHY_MEM_RSRC_CNT, 8); -+UFS_UNIT_DESC_PARAM(physical_memory_resource_count, _PHY_MEM_RSRC_CNT, 8); - UFS_UNIT_DESC_PARAM(context_capabilities, _CTX_CAPABILITIES, 2); - UFS_UNIT_DESC_PARAM(large_unit_granularity, _LARGE_UNIT_SIZE_M1, 1); - UFS_UNIT_DESC_PARAM(wb_buf_alloc_units, _WB_BUF_ALLOC_UNITS, 4); -@@ -1825,7 +1825,7 @@ static struct attribute *ufs_sysfs_unit_ - &dev_attr_logical_block_count.attr, - &dev_attr_erase_block_size.attr, - &dev_attr_provisioning_type.attr, -- &dev_attr_physical_memory_resourse_count.attr, -+ &dev_attr_physical_memory_resource_count.attr, - &dev_attr_context_capabilities.attr, - &dev_attr_large_unit_granularity.attr, - &dev_attr_wb_buf_alloc_units.attr, -diff -purNx .git BPI-Router-Linux-kernel/drivers/ufs/host/ufs-exynos.c BPI-Router-Linux-kernel-6.16.12/drivers/ufs/host/ufs-exynos.c ---- BPI-Router-Linux-kernel/drivers/ufs/host/ufs-exynos.c 2025-10-22 13:53:23.467327919 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/ufs/host/ufs-exynos.c 2025-10-22 13:53:56.675168370 -0400 -@@ -1110,8 +1110,8 @@ static int exynos_ufs_post_link(struct u - hci_writel(ufs, val, HCI_TXPRDT_ENTRY_SIZE); - - hci_writel(ufs, ilog2(DATA_UNIT_SIZE), HCI_RXPRDT_ENTRY_SIZE); -- hci_writel(ufs, (1 << hba->nutrs) - 1, HCI_UTRL_NEXUS_TYPE); -- hci_writel(ufs, (1 << hba->nutmrs) - 1, HCI_UTMRL_NEXUS_TYPE); -+ hci_writel(ufs, BIT(hba->nutrs) - 1, HCI_UTRL_NEXUS_TYPE); -+ hci_writel(ufs, BIT(hba->nutmrs) - 1, HCI_UTMRL_NEXUS_TYPE); - hci_writel(ufs, 0xf, HCI_AXIDMA_RWDATA_BURST_LEN); - - if (ufs->opts & EXYNOS_UFS_OPT_SKIP_CONNECTION_ESTAB) -diff -purNx .git BPI-Router-Linux-kernel/drivers/ufs/host/ufshcd-pci.c BPI-Router-Linux-kernel-6.16.12/drivers/ufs/host/ufshcd-pci.c ---- BPI-Router-Linux-kernel/drivers/ufs/host/ufshcd-pci.c 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/ufs/host/ufshcd-pci.c 2025-10-22 13:53:56.675168370 -0400 -@@ -216,6 +216,32 @@ out: - return ret; - } - -+static void ufs_intel_ctrl_uic_compl(struct ufs_hba *hba, bool enable) -+{ -+ u32 set = ufshcd_readl(hba, REG_INTERRUPT_ENABLE); -+ -+ if (enable) -+ set |= UIC_COMMAND_COMPL; -+ else -+ set &= ~UIC_COMMAND_COMPL; -+ ufshcd_writel(hba, set, REG_INTERRUPT_ENABLE); -+} -+ -+static void ufs_intel_mtl_h8_notify(struct ufs_hba *hba, -+ enum uic_cmd_dme cmd, -+ enum ufs_notify_change_status status) -+{ -+ /* -+ * Disable UIC COMPL INTR to prevent access to UFSHCI after -+ * checking HCS.UPMCRS -+ */ -+ if (status == PRE_CHANGE && cmd == UIC_CMD_DME_HIBER_ENTER) -+ ufs_intel_ctrl_uic_compl(hba, false); -+ -+ if (status == POST_CHANGE && cmd == UIC_CMD_DME_HIBER_EXIT) -+ ufs_intel_ctrl_uic_compl(hba, true); -+} -+ - #define INTEL_ACTIVELTR 0x804 - #define INTEL_IDLELTR 0x808 - -@@ -442,10 +468,23 @@ static int ufs_intel_adl_init(struct ufs - return ufs_intel_common_init(hba); - } - -+static void ufs_intel_mtl_late_init(struct ufs_hba *hba) -+{ -+ hba->rpm_lvl = UFS_PM_LVL_2; -+ hba->spm_lvl = UFS_PM_LVL_2; -+} -+ - static int ufs_intel_mtl_init(struct ufs_hba *hba) - { -+ struct ufs_host *ufs_host; -+ int err; -+ - hba->caps |= UFSHCD_CAP_CRYPTO | UFSHCD_CAP_WB_EN; -- return ufs_intel_common_init(hba); -+ err = ufs_intel_common_init(hba); -+ /* Get variant after it is set in ufs_intel_common_init() */ -+ ufs_host = ufshcd_get_variant(hba); -+ ufs_host->late_init = ufs_intel_mtl_late_init; -+ return err; - } - - static int ufs_qemu_get_hba_mac(struct ufs_hba *hba) -@@ -533,6 +572,7 @@ static struct ufs_hba_variant_ops ufs_in - .init = ufs_intel_mtl_init, - .exit = ufs_intel_common_exit, - .hce_enable_notify = ufs_intel_hce_enable_notify, -+ .hibern8_notify = ufs_intel_mtl_h8_notify, - .link_startup_notify = ufs_intel_link_startup_notify, - .resume = ufs_intel_resume, - .device_reset = ufs_intel_device_reset, -diff -purNx .git BPI-Router-Linux-kernel/drivers/ufs/host/ufs-qcom.c BPI-Router-Linux-kernel-6.16.12/drivers/ufs/host/ufs-qcom.c ---- BPI-Router-Linux-kernel/drivers/ufs/host/ufs-qcom.c 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/ufs/host/ufs-qcom.c 2025-10-22 13:53:56.675168370 -0400 -@@ -2053,17 +2053,6 @@ static irqreturn_t ufs_qcom_mcq_esi_hand - return IRQ_HANDLED; - } - --static void ufs_qcom_irq_free(struct ufs_qcom_irq *uqi) --{ -- for (struct ufs_qcom_irq *q = uqi; q->irq; q++) -- devm_free_irq(q->hba->dev, q->irq, q->hba); -- -- platform_device_msi_free_irqs_all(uqi->hba->dev); -- devm_kfree(uqi->hba->dev, uqi); --} -- --DEFINE_FREE(ufs_qcom_irq, struct ufs_qcom_irq *, if (_T) ufs_qcom_irq_free(_T)) -- - static int ufs_qcom_config_esi(struct ufs_hba *hba) - { - struct ufs_qcom_host *host = ufshcd_get_variant(hba); -@@ -2078,18 +2067,18 @@ static int ufs_qcom_config_esi(struct uf - */ - nr_irqs = hba->nr_hw_queues - hba->nr_queues[HCTX_TYPE_POLL]; - -- struct ufs_qcom_irq *qi __free(ufs_qcom_irq) = -- devm_kcalloc(hba->dev, nr_irqs, sizeof(*qi), GFP_KERNEL); -- if (!qi) -- return -ENOMEM; -- /* Preset so __free() has a pointer to hba in all error paths */ -- qi[0].hba = hba; -- - ret = platform_device_msi_init_and_alloc_irqs(hba->dev, nr_irqs, - ufs_qcom_write_msi_msg); - if (ret) { -- dev_err(hba->dev, "Failed to request Platform MSI %d\n", ret); -- return ret; -+ dev_warn(hba->dev, "Platform MSI not supported or failed, continuing without ESI\n"); -+ return ret; /* Continue without ESI */ -+ } -+ -+ struct ufs_qcom_irq *qi = devm_kcalloc(hba->dev, nr_irqs, sizeof(*qi), GFP_KERNEL); -+ -+ if (!qi) { -+ platform_device_msi_free_irqs_all(hba->dev); -+ return -ENOMEM; - } - - for (int idx = 0; idx < nr_irqs; idx++) { -@@ -2100,17 +2089,18 @@ static int ufs_qcom_config_esi(struct uf - ret = devm_request_irq(hba->dev, qi[idx].irq, ufs_qcom_mcq_esi_handler, - IRQF_SHARED, "qcom-mcq-esi", qi + idx); - if (ret) { -- dev_err(hba->dev, "%s: Fail to request IRQ for %d, err = %d\n", -+ dev_err(hba->dev, "%s: Failed to request IRQ for %d, err = %d\n", - __func__, qi[idx].irq, ret); -- qi[idx].irq = 0; -+ /* Free previously allocated IRQs */ -+ for (int j = 0; j < idx; j++) -+ devm_free_irq(hba->dev, qi[j].irq, qi + j); -+ platform_device_msi_free_irqs_all(hba->dev); -+ devm_kfree(hba->dev, qi); - return ret; - } - } - -- retain_and_null_ptr(qi); -- -- if (host->hw_ver.major == 6 && host->hw_ver.minor == 0 && -- host->hw_ver.step == 0) { -+ if (host->hw_ver.major >= 6) { - ufshcd_rmwl(hba, ESI_VEC_MASK, FIELD_PREP(ESI_VEC_MASK, MAX_ESI_VEC - 1), - REG_UFS_CFG3); - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/atm/cxacru.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/atm/cxacru.c ---- BPI-Router-Linux-kernel/drivers/usb/atm/cxacru.c 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/atm/cxacru.c 2025-10-22 13:53:56.675168370 -0400 -@@ -980,25 +980,60 @@ cleanup: - return ret; - } - --static void cxacru_upload_firmware(struct cxacru_data *instance, -- const struct firmware *fw, -- const struct firmware *bp) -+ -+static int cxacru_find_firmware(struct cxacru_data *instance, -+ char *phase, const struct firmware **fw_p) - { -- int ret; -+ struct usbatm_data *usbatm = instance->usbatm; -+ struct device *dev = &usbatm->usb_intf->dev; -+ char buf[16]; -+ -+ sprintf(buf, "cxacru-%s.bin", phase); -+ usb_dbg(usbatm, "cxacru_find_firmware: looking for %s\n", buf); -+ -+ if (request_firmware(fw_p, buf, dev)) { -+ usb_dbg(usbatm, "no stage %s firmware found\n", phase); -+ return -ENOENT; -+ } -+ -+ usb_info(usbatm, "found firmware %s\n", buf); -+ -+ return 0; -+} -+ -+static int cxacru_heavy_init(struct usbatm_data *usbatm_instance, -+ struct usb_interface *usb_intf) -+{ -+ const struct firmware *fw, *bp; -+ struct cxacru_data *instance = usbatm_instance->driver_data; - struct usbatm_data *usbatm = instance->usbatm; - struct usb_device *usb_dev = usbatm->usb_dev; - __le16 signature[] = { usb_dev->descriptor.idVendor, - usb_dev->descriptor.idProduct }; - __le32 val; -+ int ret; -+ -+ ret = cxacru_find_firmware(instance, "fw", &fw); -+ if (ret) { -+ usb_warn(usbatm_instance, "firmware (cxacru-fw.bin) unavailable (system misconfigured?)\n"); -+ return ret; -+ } - -- usb_dbg(usbatm, "%s\n", __func__); -+ if (instance->modem_type->boot_rom_patch) { -+ ret = cxacru_find_firmware(instance, "bp", &bp); -+ if (ret) { -+ usb_warn(usbatm_instance, "boot ROM patch (cxacru-bp.bin) unavailable (system misconfigured?)\n"); -+ release_firmware(fw); -+ return ret; -+ } -+ } - - /* FirmwarePllFClkValue */ - val = cpu_to_le32(instance->modem_type->pll_f_clk); - ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLFCLK_ADDR, (u8 *) &val, 4); - if (ret) { - usb_err(usbatm, "FirmwarePllFClkValue failed: %d\n", ret); -- return; -+ goto done; - } - - /* FirmwarePllBClkValue */ -@@ -1006,7 +1041,7 @@ static void cxacru_upload_firmware(struc - ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, PLLBCLK_ADDR, (u8 *) &val, 4); - if (ret) { - usb_err(usbatm, "FirmwarePllBClkValue failed: %d\n", ret); -- return; -+ goto done; - } - - /* Enable SDRAM */ -@@ -1014,7 +1049,7 @@ static void cxacru_upload_firmware(struc - ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SDRAMEN_ADDR, (u8 *) &val, 4); - if (ret) { - usb_err(usbatm, "Enable SDRAM failed: %d\n", ret); -- return; -+ goto done; - } - - /* Firmware */ -@@ -1022,7 +1057,7 @@ static void cxacru_upload_firmware(struc - ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, FW_ADDR, fw->data, fw->size); - if (ret) { - usb_err(usbatm, "Firmware upload failed: %d\n", ret); -- return; -+ goto done; - } - - /* Boot ROM patch */ -@@ -1031,7 +1066,7 @@ static void cxacru_upload_firmware(struc - ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_ADDR, bp->data, bp->size); - if (ret) { - usb_err(usbatm, "Boot ROM patching failed: %d\n", ret); -- return; -+ goto done; - } - } - -@@ -1039,7 +1074,7 @@ static void cxacru_upload_firmware(struc - ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, SIG_ADDR, (u8 *) signature, 4); - if (ret) { - usb_err(usbatm, "Signature storing failed: %d\n", ret); -- return; -+ goto done; - } - - usb_info(usbatm, "starting device\n"); -@@ -1051,7 +1086,7 @@ static void cxacru_upload_firmware(struc - } - if (ret) { - usb_err(usbatm, "Passing control to firmware failed: %d\n", ret); -- return; -+ goto done; - } - - /* Delay to allow firmware to start up. */ -@@ -1065,53 +1100,10 @@ static void cxacru_upload_firmware(struc - ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0); - if (ret < 0) { - usb_err(usbatm, "modem failed to initialize: %d\n", ret); -- return; -- } --} -- --static int cxacru_find_firmware(struct cxacru_data *instance, -- char *phase, const struct firmware **fw_p) --{ -- struct usbatm_data *usbatm = instance->usbatm; -- struct device *dev = &usbatm->usb_intf->dev; -- char buf[16]; -- -- sprintf(buf, "cxacru-%s.bin", phase); -- usb_dbg(usbatm, "cxacru_find_firmware: looking for %s\n", buf); -- -- if (request_firmware(fw_p, buf, dev)) { -- usb_dbg(usbatm, "no stage %s firmware found\n", phase); -- return -ENOENT; -+ goto done; - } - -- usb_info(usbatm, "found firmware %s\n", buf); -- -- return 0; --} -- --static int cxacru_heavy_init(struct usbatm_data *usbatm_instance, -- struct usb_interface *usb_intf) --{ -- const struct firmware *fw, *bp; -- struct cxacru_data *instance = usbatm_instance->driver_data; -- int ret = cxacru_find_firmware(instance, "fw", &fw); -- -- if (ret) { -- usb_warn(usbatm_instance, "firmware (cxacru-fw.bin) unavailable (system misconfigured?)\n"); -- return ret; -- } -- -- if (instance->modem_type->boot_rom_patch) { -- ret = cxacru_find_firmware(instance, "bp", &bp); -- if (ret) { -- usb_warn(usbatm_instance, "boot ROM patch (cxacru-bp.bin) unavailable (system misconfigured?)\n"); -- release_firmware(fw); -- return ret; -- } -- } -- -- cxacru_upload_firmware(instance, fw, bp); -- -+done: - if (instance->modem_type->boot_rom_patch) - release_firmware(bp); - release_firmware(fw); -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/cdns3/cdnsp-debug.h BPI-Router-Linux-kernel-6.16.12/drivers/usb/cdns3/cdnsp-debug.h ---- BPI-Router-Linux-kernel/drivers/usb/cdns3/cdnsp-debug.h 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/cdns3/cdnsp-debug.h 2025-10-22 13:53:56.675168370 -0400 -@@ -327,12 +327,13 @@ static inline const char *cdnsp_decode_t - case TRB_RESET_EP: - case TRB_HALT_ENDPOINT: - ret = scnprintf(str, size, -- "%s: ep%d%s(%d) ctx %08x%08x slot %ld flags %c", -+ "%s: ep%d%s(%d) ctx %08x%08x slot %ld flags %c %c", - cdnsp_trb_type_string(type), - ep_num, ep_id % 2 ? "out" : "in", - TRB_TO_EP_INDEX(field3), field1, field0, - TRB_TO_SLOT_ID(field3), -- field3 & TRB_CYCLE ? 'C' : 'c'); -+ field3 & TRB_CYCLE ? 'C' : 'c', -+ field3 & TRB_ESP ? 'P' : 'p'); - break; - case TRB_STOP_RING: - ret = scnprintf(str, size, -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/cdns3/cdnsp-ep0.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/cdns3/cdnsp-ep0.c ---- BPI-Router-Linux-kernel/drivers/usb/cdns3/cdnsp-ep0.c 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/cdns3/cdnsp-ep0.c 2025-10-22 13:53:56.675168370 -0400 -@@ -414,6 +414,7 @@ static int cdnsp_ep0_std_request(struct - void cdnsp_setup_analyze(struct cdnsp_device *pdev) - { - struct usb_ctrlrequest *ctrl = &pdev->setup; -+ struct cdnsp_ep *pep; - int ret = -EINVAL; - u16 len; - -@@ -427,10 +428,21 @@ void cdnsp_setup_analyze(struct cdnsp_de - goto out; - } - -+ pep = &pdev->eps[0]; -+ - /* Restore the ep0 to Stopped/Running state. */ -- if (pdev->eps[0].ep_state & EP_HALTED) { -- trace_cdnsp_ep0_halted("Restore to normal state"); -- cdnsp_halt_endpoint(pdev, &pdev->eps[0], 0); -+ if (pep->ep_state & EP_HALTED) { -+ if (GET_EP_CTX_STATE(pep->out_ctx) == EP_STATE_HALTED) -+ cdnsp_halt_endpoint(pdev, pep, 0); -+ -+ /* -+ * Halt Endpoint Command for SSP2 for ep0 preserve current -+ * endpoint state and driver has to synchronize the -+ * software endpoint state with endpoint output context -+ * state. -+ */ -+ pep->ep_state &= ~EP_HALTED; -+ pep->ep_state |= EP_STOPPED; - } - - /* -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/cdns3/cdnsp-gadget.h BPI-Router-Linux-kernel-6.16.12/drivers/usb/cdns3/cdnsp-gadget.h ---- BPI-Router-Linux-kernel/drivers/usb/cdns3/cdnsp-gadget.h 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/cdns3/cdnsp-gadget.h 2025-10-22 13:53:56.675168370 -0400 -@@ -987,6 +987,12 @@ enum cdnsp_setup_dev { - #define STREAM_ID_FOR_TRB(p) ((((p)) << 16) & GENMASK(31, 16)) - #define SCT_FOR_TRB(p) (((p) << 1) & 0x7) - -+/* -+ * Halt Endpoint Command TRB field. -+ * The ESP bit only exists in the SSP2 controller. -+ */ -+#define TRB_ESP BIT(9) -+ - /* Link TRB specific fields. */ - #define TRB_TC BIT(1) - -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/cdns3/cdnsp-ring.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/cdns3/cdnsp-ring.c ---- BPI-Router-Linux-kernel/drivers/usb/cdns3/cdnsp-ring.c 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/cdns3/cdnsp-ring.c 2025-10-22 13:53:56.675168370 -0400 -@@ -772,7 +772,9 @@ static int cdnsp_update_port_id(struct c - } - - if (port_id != old_port) { -- cdnsp_disable_slot(pdev); -+ if (pdev->slot_id) -+ cdnsp_disable_slot(pdev); -+ - pdev->active_port = port; - cdnsp_enable_slot(pdev); - } -@@ -2483,7 +2485,8 @@ void cdnsp_queue_halt_endpoint(struct cd - { - cdnsp_queue_command(pdev, 0, 0, 0, TRB_TYPE(TRB_HALT_ENDPOINT) | - SLOT_ID_FOR_TRB(pdev->slot_id) | -- EP_ID_FOR_TRB(ep_index)); -+ EP_ID_FOR_TRB(ep_index) | -+ (!ep_index ? TRB_ESP : 0)); - } - - void cdnsp_force_header_wakeup(struct cdnsp_device *pdev, int intf_num) -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/chipidea/udc.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/chipidea/udc.c ---- BPI-Router-Linux-kernel/drivers/usb/chipidea/udc.c 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/chipidea/udc.c 2025-10-22 13:53:56.675168370 -0400 -@@ -2374,6 +2374,10 @@ static void udc_suspend(struct ci_hdrc * - */ - if (hw_read(ci, OP_ENDPTLISTADDR, ~0) == 0) - hw_write(ci, OP_ENDPTLISTADDR, ~0, ~0); -+ -+ if (ci->gadget.connected && -+ (!ci->suspended || !device_may_wakeup(ci->dev))) -+ usb_gadget_disconnect(&ci->gadget); - } - - static void udc_resume(struct ci_hdrc *ci, bool power_lost) -@@ -2384,6 +2388,9 @@ static void udc_resume(struct ci_hdrc *c - OTGSC_BSVIS | OTGSC_BSVIE); - if (ci->vbus_active) - usb_gadget_vbus_disconnect(&ci->gadget); -+ } else if (ci->vbus_active && ci->driver && -+ !ci->gadget.connected) { -+ usb_gadget_connect(&ci->gadget); - } - - /* Restore value 0 if it was set for power lost check */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/class/cdc-acm.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/class/cdc-acm.c ---- BPI-Router-Linux-kernel/drivers/usb/class/cdc-acm.c 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/class/cdc-acm.c 2025-10-22 13:53:56.675168370 -0400 -@@ -1520,6 +1520,12 @@ skip_countries: - goto err_remove_files; - } - -+ if (quirks & CLEAR_HALT_CONDITIONS) { -+ /* errors intentionally ignored */ -+ usb_clear_halt(usb_dev, acm->in); -+ usb_clear_halt(usb_dev, acm->out); -+ } -+ - tty_dev = tty_port_register_device(&acm->port, acm_tty_driver, minor, - &control_interface->dev); - if (IS_ERR(tty_dev)) { -@@ -1527,11 +1533,6 @@ skip_countries: - goto err_release_data_interface; - } - -- if (quirks & CLEAR_HALT_CONDITIONS) { -- usb_clear_halt(usb_dev, acm->in); -- usb_clear_halt(usb_dev, acm->out); -- } -- - dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor); - - return 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/core/config.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/core/config.c ---- BPI-Router-Linux-kernel/drivers/usb/core/config.c 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/core/config.c 2025-10-22 13:53:56.675168370 -0400 -@@ -107,8 +107,14 @@ static void usb_parse_ss_endpoint_compan - */ - desc = (struct usb_ss_ep_comp_descriptor *) buffer; - -- if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP || -- size < USB_DT_SS_EP_COMP_SIZE) { -+ if (size < USB_DT_SS_EP_COMP_SIZE) { -+ dev_notice(ddev, -+ "invalid SuperSpeed endpoint companion descriptor " -+ "of length %d, skipping\n", size); -+ return; -+ } -+ -+ if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP) { - dev_notice(ddev, "No SuperSpeed endpoint companion for config %d " - " interface %d altsetting %d ep %d: " - "using minimum values\n", -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/core/hcd.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/core/hcd.c ---- BPI-Router-Linux-kernel/drivers/usb/core/hcd.c 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/core/hcd.c 2025-10-22 13:53:56.675168370 -0400 -@@ -1623,7 +1623,6 @@ static void __usb_hcd_giveback_urb(struc - struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus); - struct usb_anchor *anchor = urb->anchor; - int status = urb->unlinked; -- unsigned long flags; - - urb->hcpriv = NULL; - if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) && -@@ -1641,14 +1640,13 @@ static void __usb_hcd_giveback_urb(struc - /* pass ownership to the completion handler */ - urb->status = status; - /* -- * Only collect coverage in the softirq context and disable interrupts -- * to avoid scenarios with nested remote coverage collection sections -- * that KCOV does not support. -- * See the comment next to kcov_remote_start_usb_softirq() for details. -+ * This function can be called in task context inside another remote -+ * coverage collection section, but kcov doesn't support that kind of -+ * recursion yet. Only collect coverage in softirq context for now. - */ -- flags = kcov_remote_start_usb_softirq((u64)urb->dev->bus->busnum); -+ kcov_remote_start_usb_softirq((u64)urb->dev->bus->busnum); - urb->complete(urb); -- kcov_remote_stop_softirq(flags); -+ kcov_remote_stop_softirq(); - - usb_anchor_resume_wakeups(anchor); - atomic_dec(&urb->use_count); -@@ -2153,7 +2151,7 @@ static struct urb *request_single_step_s - urb->complete = usb_ehset_completion; - urb->status = -EINPROGRESS; - urb->actual_length = 0; -- urb->transfer_flags = URB_DIR_IN; -+ urb->transfer_flags = URB_DIR_IN | URB_NO_TRANSFER_DMA_MAP; - usb_get_urb(urb); - atomic_inc(&urb->use_count); - atomic_inc(&urb->dev->urbnum); -@@ -2217,9 +2215,15 @@ int ehset_single_step_set_feature(struct - - /* Complete remaining DATA and STATUS stages using the same URB */ - urb->status = -EINPROGRESS; -+ urb->transfer_flags &= ~URB_NO_TRANSFER_DMA_MAP; - usb_get_urb(urb); - atomic_inc(&urb->use_count); - atomic_inc(&urb->dev->urbnum); -+ if (map_urb_for_dma(hcd, urb, GFP_KERNEL)) { -+ usb_put_urb(urb); -+ goto out1; -+ } -+ - retval = hcd->driver->submit_single_step_set_feature(hcd, urb, 0); - if (!retval && !wait_for_completion_timeout(&done, - msecs_to_jiffies(2000))) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/core/hub.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/core/hub.c ---- BPI-Router-Linux-kernel/drivers/usb/core/hub.c 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/core/hub.c 2025-10-22 13:53:56.675168370 -0400 -@@ -68,6 +68,12 @@ - */ - #define USB_SHORT_SET_ADDRESS_REQ_TIMEOUT 500 /* ms */ - -+/* -+ * Give SS hubs 200ms time after wake to train downstream links before -+ * assuming no port activity and allowing hub to runtime suspend back. -+ */ -+#define USB_SS_PORT_U0_WAKE_TIME 200 /* ms */ -+ - /* Protect struct usb_device->state and ->children members - * Note: Both are also protected by ->dev.sem, except that ->state can - * change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */ -@@ -1095,6 +1101,7 @@ static void hub_activate(struct usb_hub - goto init2; - goto init3; - } -+ - hub_get(hub); - - /* The superspeed hub except for root hub has to use Hub Depth -@@ -1343,6 +1350,17 @@ static void hub_activate(struct usb_hub - device_unlock(&hdev->dev); - } - -+ if (type == HUB_RESUME && hub_is_superspeed(hub->hdev)) { -+ /* give usb3 downstream links training time after hub resume */ -+ usb_autopm_get_interface_no_resume( -+ to_usb_interface(hub->intfdev)); -+ -+ queue_delayed_work(system_power_efficient_wq, -+ &hub->post_resume_work, -+ msecs_to_jiffies(USB_SS_PORT_U0_WAKE_TIME)); -+ return; -+ } -+ - hub_put(hub); - } - -@@ -1361,6 +1379,14 @@ static void hub_init_func3(struct work_s - hub_activate(hub, HUB_INIT3); - } - -+static void hub_post_resume(struct work_struct *ws) -+{ -+ struct usb_hub *hub = container_of(ws, struct usb_hub, post_resume_work.work); -+ -+ usb_autopm_put_interface_async(to_usb_interface(hub->intfdev)); -+ hub_put(hub); -+} -+ - enum hub_quiescing_type { - HUB_DISCONNECT, HUB_PRE_RESET, HUB_SUSPEND - }; -@@ -1386,6 +1412,7 @@ static void hub_quiesce(struct usb_hub * - - /* Stop hub_wq and related activity */ - timer_delete_sync(&hub->irq_urb_retry); -+ flush_delayed_work(&hub->post_resume_work); - usb_kill_urb(hub->urb); - if (hub->has_indicators) - cancel_delayed_work_sync(&hub->leds); -@@ -1944,6 +1971,7 @@ static int hub_probe(struct usb_interfac - hub->hdev = hdev; - INIT_DELAYED_WORK(&hub->leds, led_work); - INIT_DELAYED_WORK(&hub->init_work, NULL); -+ INIT_DELAYED_WORK(&hub->post_resume_work, hub_post_resume); - INIT_WORK(&hub->events, hub_event); - INIT_LIST_HEAD(&hub->onboard_devs); - spin_lock_init(&hub->irq_urb_lock); -@@ -2337,6 +2365,9 @@ void usb_disconnect(struct usb_device ** - usb_remove_ep_devs(&udev->ep0); - usb_unlock_device(udev); - -+ if (udev->usb4_link) -+ device_link_del(udev->usb4_link); -+ - /* Unregister the device. The device driver is responsible - * for de-configuring the device and invoking the remove-device - * notifier chain (used by usbfs and possibly others). -@@ -5720,6 +5751,7 @@ static void port_event(struct usb_hub *h - struct usb_device *hdev = hub->hdev; - u16 portstatus, portchange; - int i = 0; -+ int err; - - connect_change = test_bit(port1, hub->change_bits); - clear_bit(port1, hub->event_bits); -@@ -5816,8 +5848,11 @@ static void port_event(struct usb_hub *h - } else if (!udev || !(portstatus & USB_PORT_STAT_CONNECTION) - || udev->state == USB_STATE_NOTATTACHED) { - dev_dbg(&port_dev->dev, "do warm reset, port only\n"); -- if (hub_port_reset(hub, port1, NULL, -- HUB_BH_RESET_TIME, true) < 0) -+ err = hub_port_reset(hub, port1, NULL, -+ HUB_BH_RESET_TIME, true); -+ if (!udev && err == -ENOTCONN) -+ connect_change = 0; -+ else if (err < 0) - hub_port_disable(hub, port1, 1); - } else { - dev_dbg(&port_dev->dev, "do warm reset, full device\n"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/core/hub.h BPI-Router-Linux-kernel-6.16.12/drivers/usb/core/hub.h ---- BPI-Router-Linux-kernel/drivers/usb/core/hub.h 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/core/hub.h 2025-10-22 13:53:56.675168370 -0400 -@@ -70,6 +70,7 @@ struct usb_hub { - u8 indicator[USB_MAXCHILDREN]; - struct delayed_work leds; - struct delayed_work init_work; -+ struct delayed_work post_resume_work; - struct work_struct events; - spinlock_t irq_urb_lock; - struct timer_list irq_urb_retry; -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/core/quirks.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/core/quirks.c ---- BPI-Router-Linux-kernel/drivers/usb/core/quirks.c 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/core/quirks.c 2025-10-22 13:53:56.675168370 -0400 -@@ -227,7 +227,8 @@ static const struct usb_device_id usb_qu - { USB_DEVICE(0x046a, 0x0023), .driver_info = USB_QUIRK_RESET_RESUME }, - - /* Logitech HD Webcam C270 */ -- { USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME }, -+ { USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME | -+ USB_QUIRK_NO_LPM}, - - /* Logitech HD Pro Webcams C920, C920-C, C922, C925e and C930e */ - { USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT }, -@@ -370,6 +371,7 @@ static const struct usb_device_id usb_qu - { USB_DEVICE(0x0781, 0x5591), .driver_info = USB_QUIRK_NO_LPM }, - - /* SanDisk Corp. SanDisk 3.2Gen1 */ -+ { USB_DEVICE(0x0781, 0x5596), .driver_info = USB_QUIRK_DELAY_INIT }, - { USB_DEVICE(0x0781, 0x55a3), .driver_info = USB_QUIRK_DELAY_INIT }, - - /* SanDisk Extreme 55AE */ -@@ -735,7 +737,7 @@ void usb_detect_quirks(struct usb_device - udev->quirks ^= usb_detect_dynamic_quirks(udev); - - if (udev->quirks) -- dev_dbg(&udev->dev, "USB quirks for this device: %x\n", -+ dev_dbg(&udev->dev, "USB quirks for this device: 0x%x\n", - udev->quirks); - - #ifdef CONFIG_USB_DEFAULT_PERSIST -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/core/urb.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/core/urb.c ---- BPI-Router-Linux-kernel/drivers/usb/core/urb.c 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/core/urb.c 2025-10-22 13:53:56.675168370 -0400 -@@ -500,7 +500,7 @@ int usb_submit_urb(struct urb *urb, gfp_ - - /* Check that the pipe's type matches the endpoint's type */ - if (usb_pipe_type_check(urb->dev, urb->pipe)) -- dev_WARN(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n", -+ dev_warn_once(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n", - usb_pipetype(urb->pipe), pipetypes[xfertype]); - - /* Check against a simple/standard policy */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/core/usb-acpi.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/core/usb-acpi.c ---- BPI-Router-Linux-kernel/drivers/usb/core/usb-acpi.c 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/core/usb-acpi.c 2025-10-22 13:53:56.675168370 -0400 -@@ -157,7 +157,7 @@ EXPORT_SYMBOL_GPL(usb_acpi_set_power_sta - */ - static int usb_acpi_add_usb4_devlink(struct usb_device *udev) - { -- const struct device_link *link; -+ struct device_link *link; - struct usb_port *port_dev; - struct usb_hub *hub; - -@@ -188,6 +188,8 @@ static int usb_acpi_add_usb4_devlink(str - dev_dbg(&port_dev->dev, "Created device link from %s to %s\n", - dev_name(&port_dev->child->dev), dev_name(nhi_fwnode->dev)); - -+ udev->usb4_link = link; -+ - return 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/dwc2/gadget.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/dwc2/gadget.c ---- BPI-Router-Linux-kernel/drivers/usb/dwc2/gadget.c 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/dwc2/gadget.c 2025-10-22 13:53:56.679168351 -0400 -@@ -5389,20 +5389,34 @@ int dwc2_gadget_enter_hibernation(struct - if (gusbcfg & GUSBCFG_ULPI_UTMI_SEL) { - /* ULPI interface */ - gpwrdn |= GPWRDN_ULPI_LATCH_EN_DURING_HIB_ENTRY; -- } -- dwc2_writel(hsotg, gpwrdn, GPWRDN); -- udelay(10); -+ dwc2_writel(hsotg, gpwrdn, GPWRDN); -+ udelay(10); -+ -+ /* Suspend the Phy Clock */ -+ pcgcctl = dwc2_readl(hsotg, PCGCTL); -+ pcgcctl |= PCGCTL_STOPPCLK; -+ dwc2_writel(hsotg, pcgcctl, PCGCTL); -+ udelay(10); - -- /* Suspend the Phy Clock */ -- pcgcctl = dwc2_readl(hsotg, PCGCTL); -- pcgcctl |= PCGCTL_STOPPCLK; -- dwc2_writel(hsotg, pcgcctl, PCGCTL); -- udelay(10); -+ gpwrdn = dwc2_readl(hsotg, GPWRDN); -+ gpwrdn |= GPWRDN_PMUACTV; -+ dwc2_writel(hsotg, gpwrdn, GPWRDN); -+ udelay(10); -+ } else { -+ /* UTMI+ Interface */ -+ dwc2_writel(hsotg, gpwrdn, GPWRDN); -+ udelay(10); - -- gpwrdn = dwc2_readl(hsotg, GPWRDN); -- gpwrdn |= GPWRDN_PMUACTV; -- dwc2_writel(hsotg, gpwrdn, GPWRDN); -- udelay(10); -+ gpwrdn = dwc2_readl(hsotg, GPWRDN); -+ gpwrdn |= GPWRDN_PMUACTV; -+ dwc2_writel(hsotg, gpwrdn, GPWRDN); -+ udelay(10); -+ -+ pcgcctl = dwc2_readl(hsotg, PCGCTL); -+ pcgcctl |= PCGCTL_STOPPCLK; -+ dwc2_writel(hsotg, pcgcctl, PCGCTL); -+ udelay(10); -+ } - - /* Set flag to indicate that we are in hibernation */ - hsotg->hibernated = 1; -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/dwc3/core.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/dwc3/core.c ---- BPI-Router-Linux-kernel/drivers/usb/dwc3/core.c 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/dwc3/core.c 2025-10-22 13:53:56.679168351 -0400 -@@ -2422,6 +2422,7 @@ static int dwc3_suspend_common(struct dw - { - u32 reg; - int i; -+ int ret; - - if (!pm_runtime_suspended(dwc->dev) && !PMSG_IS_AUTO(msg)) { - dwc->susphy_state = (dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)) & -@@ -2440,7 +2441,9 @@ static int dwc3_suspend_common(struct dw - case DWC3_GCTL_PRTCAP_DEVICE: - if (pm_runtime_suspended(dwc->dev)) - break; -- dwc3_gadget_suspend(dwc); -+ ret = dwc3_gadget_suspend(dwc); -+ if (ret) -+ return ret; - synchronize_irq(dwc->irq_gadget); - dwc3_core_exit(dwc); - break; -@@ -2475,7 +2478,9 @@ static int dwc3_suspend_common(struct dw - break; - - if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) { -- dwc3_gadget_suspend(dwc); -+ ret = dwc3_gadget_suspend(dwc); -+ if (ret) -+ return ret; - synchronize_irq(dwc->irq_gadget); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/dwc3/dwc3-imx8mp.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/dwc3/dwc3-imx8mp.c ---- BPI-Router-Linux-kernel/drivers/usb/dwc3/dwc3-imx8mp.c 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/dwc3/dwc3-imx8mp.c 2025-10-22 13:53:56.679168351 -0400 -@@ -244,7 +244,7 @@ static int dwc3_imx8mp_probe(struct plat - IRQF_ONESHOT, dev_name(dev), dwc3_imx); - if (err) { - dev_err(dev, "failed to request IRQ #%d --> %d\n", irq, err); -- goto depopulate; -+ goto put_dwc3; - } - - device_set_wakeup_capable(dev, true); -@@ -252,6 +252,8 @@ static int dwc3_imx8mp_probe(struct plat - - return 0; - -+put_dwc3: -+ put_device(&dwc3_imx->dwc3->dev); - depopulate: - of_platform_depopulate(dev); - remove_swnode: -@@ -265,8 +267,11 @@ disable_rpm: - - static void dwc3_imx8mp_remove(struct platform_device *pdev) - { -+ struct dwc3_imx8mp *dwc3_imx = platform_get_drvdata(pdev); - struct device *dev = &pdev->dev; - -+ put_device(&dwc3_imx->dwc3->dev); -+ - pm_runtime_get_sync(dev); - of_platform_depopulate(dev); - device_remove_software_node(dev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/dwc3/dwc3-meson-g12a.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/dwc3/dwc3-meson-g12a.c ---- BPI-Router-Linux-kernel/drivers/usb/dwc3/dwc3-meson-g12a.c 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/dwc3/dwc3-meson-g12a.c 2025-10-22 13:53:56.679168351 -0400 -@@ -837,6 +837,9 @@ static void dwc3_meson_g12a_remove(struc - - usb_role_switch_unregister(priv->role_switch); - -+ put_device(priv->switch_desc.udc); -+ put_device(priv->switch_desc.usb2_port); -+ - of_platform_depopulate(dev); - - for (i = 0 ; i < PHY_COUNT ; ++i) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/dwc3/dwc3-pci.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/dwc3/dwc3-pci.c ---- BPI-Router-Linux-kernel/drivers/usb/dwc3/dwc3-pci.c 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/dwc3/dwc3-pci.c 2025-10-22 13:53:56.679168351 -0400 -@@ -41,6 +41,7 @@ - #define PCI_DEVICE_ID_INTEL_TGPLP 0xa0ee - #define PCI_DEVICE_ID_INTEL_TGPH 0x43ee - #define PCI_DEVICE_ID_INTEL_JSP 0x4dee -+#define PCI_DEVICE_ID_INTEL_WCL 0x4d7e - #define PCI_DEVICE_ID_INTEL_ADL 0x460e - #define PCI_DEVICE_ID_INTEL_ADL_PCH 0x51ee - #define PCI_DEVICE_ID_INTEL_ADLN 0x465e -@@ -431,6 +432,7 @@ static const struct pci_device_id dwc3_p - { PCI_DEVICE_DATA(INTEL, TGPLP, &dwc3_pci_intel_swnode) }, - { PCI_DEVICE_DATA(INTEL, TGPH, &dwc3_pci_intel_swnode) }, - { PCI_DEVICE_DATA(INTEL, JSP, &dwc3_pci_intel_swnode) }, -+ { PCI_DEVICE_DATA(INTEL, WCL, &dwc3_pci_intel_swnode) }, - { PCI_DEVICE_DATA(INTEL, ADL, &dwc3_pci_intel_swnode) }, - { PCI_DEVICE_DATA(INTEL, ADL_PCH, &dwc3_pci_intel_swnode) }, - { PCI_DEVICE_DATA(INTEL, ADLN, &dwc3_pci_intel_swnode) }, -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/dwc3/dwc3-qcom.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/dwc3/dwc3-qcom.c ---- BPI-Router-Linux-kernel/drivers/usb/dwc3/dwc3-qcom.c 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/dwc3/dwc3-qcom.c 2025-10-22 13:53:56.679168351 -0400 -@@ -680,12 +680,12 @@ static int dwc3_qcom_probe(struct platfo - ret = reset_control_deassert(qcom->resets); - if (ret) { - dev_err(&pdev->dev, "failed to deassert resets, err=%d\n", ret); -- goto reset_assert; -+ return ret; - } - - ret = clk_bulk_prepare_enable(qcom->num_clocks, qcom->clks); - if (ret < 0) -- goto reset_assert; -+ return ret; - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r) { -@@ -755,8 +755,6 @@ remove_core: - dwc3_core_remove(&qcom->dwc); - clk_disable: - clk_bulk_disable_unprepare(qcom->num_clocks, qcom->clks); --reset_assert: -- reset_control_assert(qcom->resets); - - return ret; - } -@@ -771,7 +769,6 @@ static void dwc3_qcom_remove(struct plat - clk_bulk_disable_unprepare(qcom->num_clocks, qcom->clks); - - dwc3_qcom_interconnect_exit(qcom); -- reset_control_assert(qcom->resets); - } - - static int dwc3_qcom_pm_suspend(struct device *dev) -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/dwc3/dwc3-xilinx.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/dwc3/dwc3-xilinx.c ---- BPI-Router-Linux-kernel/drivers/usb/dwc3/dwc3-xilinx.c 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/dwc3/dwc3-xilinx.c 2025-10-22 13:53:56.679168351 -0400 -@@ -422,6 +422,7 @@ static const struct dev_pm_ops dwc3_xlnx - static struct platform_driver dwc3_xlnx_driver = { - .probe = dwc3_xlnx_probe, - .remove = dwc3_xlnx_remove, -+ .shutdown = dwc3_xlnx_remove, - .driver = { - .name = "dwc3-xilinx", - .of_match_table = dwc3_xlnx_of_match, -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/dwc3/ep0.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/dwc3/ep0.c ---- BPI-Router-Linux-kernel/drivers/usb/dwc3/ep0.c 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/dwc3/ep0.c 2025-10-22 13:53:56.679168351 -0400 -@@ -288,7 +288,9 @@ void dwc3_ep0_out_start(struct dwc3 *dwc - dwc3_ep0_prepare_one_trb(dep, dwc->ep0_trb_addr, 8, - DWC3_TRBCTL_CONTROL_SETUP, false); - ret = dwc3_ep0_start_trans(dep); -- WARN_ON(ret < 0); -+ if (ret < 0) -+ dev_err(dwc->dev, "ep0 out start transfer failed: %d\n", ret); -+ - for (i = 2; i < DWC3_ENDPOINTS_NUM; i++) { - struct dwc3_ep *dwc3_ep; - -@@ -1061,7 +1063,9 @@ static void __dwc3_ep0_do_control_data(s - ret = dwc3_ep0_start_trans(dep); - } - -- WARN_ON(ret < 0); -+ if (ret < 0) -+ dev_err(dwc->dev, -+ "ep0 data phase start transfer failed: %d\n", ret); - } - - static int dwc3_ep0_start_control_status(struct dwc3_ep *dep) -@@ -1078,7 +1082,12 @@ static int dwc3_ep0_start_control_status - - static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep) - { -- WARN_ON(dwc3_ep0_start_control_status(dep)); -+ int ret; -+ -+ ret = dwc3_ep0_start_control_status(dep); -+ if (ret) -+ dev_err(dwc->dev, -+ "ep0 status phase start transfer failed: %d\n", ret); - } - - static void dwc3_ep0_do_control_status(struct dwc3 *dwc, -@@ -1121,7 +1130,10 @@ void dwc3_ep0_end_control_data(struct dw - cmd |= DWC3_DEPCMD_PARAM(dep->resource_index); - memset(¶ms, 0, sizeof(params)); - ret = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); -- WARN_ON_ONCE(ret); -+ if (ret) -+ dev_err_ratelimited(dwc->dev, -+ "ep0 data phase end transfer failed: %d\n", ret); -+ - dep->resource_index = 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/dwc3/gadget.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/dwc3/gadget.c ---- BPI-Router-Linux-kernel/drivers/usb/dwc3/gadget.c 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/dwc3/gadget.c 2025-10-22 13:53:56.679168351 -0400 -@@ -1774,7 +1774,11 @@ static int __dwc3_stop_active_transfer(s - dep->flags |= DWC3_EP_DELAY_STOP; - return 0; - } -- WARN_ON_ONCE(ret); -+ -+ if (ret) -+ dev_err_ratelimited(dep->dwc->dev, -+ "end transfer failed: %d\n", ret); -+ - dep->resource_index = 0; - - if (!interrupt) -@@ -3516,7 +3520,7 @@ static int dwc3_gadget_ep_reclaim_comple - * We're going to do that here to avoid problems of HW trying - * to use bogus TRBs for transfers. - */ -- if (chain && (trb->ctrl & DWC3_TRB_CTRL_HWO)) -+ if (trb->ctrl & DWC3_TRB_CTRL_HWO) - trb->ctrl &= ~DWC3_TRB_CTRL_HWO; - - /* -@@ -3779,6 +3783,15 @@ static void dwc3_gadget_endpoint_transfe - static void dwc3_gadget_endpoint_transfer_not_ready(struct dwc3_ep *dep, - const struct dwc3_event_depevt *event) - { -+ /* -+ * During a device-initiated disconnect, a late xferNotReady event can -+ * be generated after the End Transfer command resets the event filter, -+ * but before the controller is halted. Ignore it to prevent a new -+ * transfer from starting. -+ */ -+ if (!dep->dwc->connected) -+ return; -+ - dwc3_gadget_endpoint_frame_from_event(dep, event); - - /* -@@ -4041,7 +4054,9 @@ static void dwc3_clear_stall_all_ep(stru - dep->flags &= ~DWC3_EP_STALL; - - ret = dwc3_send_clear_stall_ep_cmd(dep); -- WARN_ON_ONCE(ret); -+ if (ret) -+ dev_err_ratelimited(dwc->dev, -+ "failed to clear STALL on %s\n", dep->name); - } - } - -@@ -4821,26 +4836,22 @@ int dwc3_gadget_suspend(struct dwc3 *dwc - int ret; - - ret = dwc3_gadget_soft_disconnect(dwc); -- if (ret) -- goto err; -- -- spin_lock_irqsave(&dwc->lock, flags); -- if (dwc->gadget_driver) -- dwc3_disconnect_gadget(dwc); -- spin_unlock_irqrestore(&dwc->lock, flags); -- -- return 0; -- --err: - /* - * Attempt to reset the controller's state. Likely no - * communication can be established until the host - * performs a port reset. - */ -- if (dwc->softconnect) -+ if (ret && dwc->softconnect) { - dwc3_gadget_soft_connect(dwc); -+ return -EAGAIN; -+ } - -- return ret; -+ spin_lock_irqsave(&dwc->lock, flags); -+ if (dwc->gadget_driver) -+ dwc3_disconnect_gadget(dwc); -+ spin_unlock_irqrestore(&dwc->lock, flags); -+ -+ return 0; - } - - int dwc3_gadget_resume(struct dwc3 *dwc) -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/early/xhci-dbc.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/early/xhci-dbc.c ---- BPI-Router-Linux-kernel/drivers/usb/early/xhci-dbc.c 2025-10-22 13:53:23.471327899 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/early/xhci-dbc.c 2025-10-22 13:53:56.679168351 -0400 -@@ -681,6 +681,10 @@ int __init early_xdbc_setup_hardware(voi - - xdbc.table_base = NULL; - xdbc.out_buf = NULL; -+ -+ early_iounmap(xdbc.xhci_base, xdbc.xhci_length); -+ xdbc.xhci_base = NULL; -+ xdbc.xhci_length = 0; - } - - return ret; -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/gadget/composite.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/gadget/composite.c ---- BPI-Router-Linux-kernel/drivers/usb/gadget/composite.c 2025-10-22 13:53:23.475327880 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/gadget/composite.c 2025-10-22 13:53:56.679168351 -0400 -@@ -2489,6 +2489,11 @@ int composite_os_desc_req_prepare(struct - if (!cdev->os_desc_req->buf) { - ret = -ENOMEM; - usb_ep_free_request(ep0, cdev->os_desc_req); -+ /* -+ * Set os_desc_req to NULL so that composite_dev_cleanup() -+ * will not try to free it again. -+ */ -+ cdev->os_desc_req = NULL; - goto end; - } - cdev->os_desc_req->context = cdev; -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/gadget/configfs.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/gadget/configfs.c ---- BPI-Router-Linux-kernel/drivers/usb/gadget/configfs.c 2025-10-22 13:53:23.475327880 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/gadget/configfs.c 2025-10-22 13:53:56.679168351 -0400 -@@ -1065,6 +1065,8 @@ static ssize_t webusb_landingPage_store( - unsigned int bytes_to_strip = 0; - int l = len; - -+ if (!len) -+ return len; - if (page[l - 1] == '\n') { - --l; - ++bytes_to_strip; -@@ -1188,6 +1190,8 @@ static ssize_t os_desc_qw_sign_store(str - struct gadget_info *gi = os_desc_item_to_gadget_info(item); - int res, l; - -+ if (!len) -+ return len; - l = min_t(int, len, OS_STRING_QW_SIGN_LEN >> 1); - if (page[l - 1] == '\n') - --l; -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/gadget/function/f_hid.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/gadget/function/f_hid.c ---- BPI-Router-Linux-kernel/drivers/usb/gadget/function/f_hid.c 2025-10-22 13:53:23.475327880 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/gadget/function/f_hid.c 2025-10-22 13:53:56.679168351 -0400 -@@ -1278,18 +1278,19 @@ static int hidg_bind(struct usb_configur - - if (!hidg->workqueue) { - status = -ENOMEM; -- goto fail; -+ goto fail_free_descs; - } - - /* create char device */ - cdev_init(&hidg->cdev, &f_hidg_fops); - status = cdev_device_add(&hidg->cdev, &hidg->dev); - if (status) -- goto fail_free_descs; -+ goto fail_free_all; - - return 0; --fail_free_descs: -+fail_free_all: - destroy_workqueue(hidg->workqueue); -+fail_free_descs: - usb_free_all_descriptors(f); - fail: - ERROR(f->config->cdev, "hidg_bind FAILED\n"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/gadget/function/f_midi2.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/gadget/function/f_midi2.c ---- BPI-Router-Linux-kernel/drivers/usb/gadget/function/f_midi2.c 2025-10-22 13:53:23.475327880 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/gadget/function/f_midi2.c 2025-10-22 13:53:56.679168351 -0400 -@@ -1599,6 +1599,7 @@ static int f_midi2_create_card(struct f_ - strscpy(fb->info.name, ump_fb_name(b), - sizeof(fb->info.name)); - } -+ snd_ump_update_group_attrs(ump); - } - - for (i = 0; i < midi2->num_eps; i++) { -@@ -1736,9 +1737,12 @@ static int f_midi2_create_usb_configs(st - case USB_SPEED_HIGH: - midi2_midi1_ep_out_desc.wMaxPacketSize = cpu_to_le16(512); - midi2_midi1_ep_in_desc.wMaxPacketSize = cpu_to_le16(512); -- for (i = 0; i < midi2->num_eps; i++) -+ for (i = 0; i < midi2->num_eps; i++) { - midi2_midi2_ep_out_desc[i].wMaxPacketSize = - cpu_to_le16(512); -+ midi2_midi2_ep_in_desc[i].wMaxPacketSize = -+ cpu_to_le16(512); -+ } - fallthrough; - case USB_SPEED_FULL: - midi1_in_eps = midi2_midi1_ep_in_descs; -@@ -1747,9 +1751,12 @@ static int f_midi2_create_usb_configs(st - case USB_SPEED_SUPER: - midi2_midi1_ep_out_desc.wMaxPacketSize = cpu_to_le16(1024); - midi2_midi1_ep_in_desc.wMaxPacketSize = cpu_to_le16(1024); -- for (i = 0; i < midi2->num_eps; i++) -+ for (i = 0; i < midi2->num_eps; i++) { - midi2_midi2_ep_out_desc[i].wMaxPacketSize = - cpu_to_le16(1024); -+ midi2_midi2_ep_in_desc[i].wMaxPacketSize = -+ cpu_to_le16(1024); -+ } - midi1_in_eps = midi2_midi1_ep_in_ss_descs; - midi1_out_eps = midi2_midi1_ep_out_ss_descs; - break; -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/gadget/function/u_serial.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/gadget/function/u_serial.c ---- BPI-Router-Linux-kernel/drivers/usb/gadget/function/u_serial.c 2025-10-22 13:53:23.475327880 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/gadget/function/u_serial.c 2025-10-22 13:53:56.679168351 -0400 -@@ -295,8 +295,8 @@ __acquires(&port->port_lock) - break; - } - -- if (do_tty_wake && port->port.tty) -- tty_wakeup(port->port.tty); -+ if (do_tty_wake) -+ tty_port_tty_wakeup(&port->port); - return status; - } - -@@ -544,20 +544,16 @@ static int gs_alloc_requests(struct usb_ - static int gs_start_io(struct gs_port *port) - { - struct list_head *head = &port->read_pool; -- struct usb_ep *ep; -+ struct usb_ep *ep = port->port_usb->out; - int status; - unsigned started; - -- if (!port->port_usb || !port->port.tty) -- return -EIO; -- - /* Allocate RX and TX I/O buffers. We can't easily do this much - * earlier (with GFP_KERNEL) because the requests are coupled to - * endpoints, as are the packet sizes we'll be using. Different - * configurations may use different endpoints with a given port; - * and high speed vs full speed changes packet sizes too. - */ -- ep = port->port_usb->out; - status = gs_alloc_requests(ep, head, gs_read_complete, - &port->read_allocated); - if (status) -@@ -578,7 +574,7 @@ static int gs_start_io(struct gs_port *p - gs_start_tx(port); - /* Unblock any pending writes into our circular buffer, in case - * we didn't in gs_start_tx() */ -- tty_wakeup(port->port.tty); -+ tty_port_tty_wakeup(&port->port); - } else { - /* Free reqs only if we are still connected */ - if (port->port_usb) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/gadget/function/uvc_configfs.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/gadget/function/uvc_configfs.c ---- BPI-Router-Linux-kernel/drivers/usb/gadget/function/uvc_configfs.c 2025-10-22 13:53:23.475327880 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/gadget/function/uvc_configfs.c 2025-10-22 13:53:56.679168351 -0400 -@@ -2916,8 +2916,15 @@ static struct config_group *uvcg_frameba - 'H', '2', '6', '4', 0x00, 0x00, 0x10, 0x00, - 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 - }; -+ struct uvcg_color_matching *color_match; -+ struct config_item *streaming; - struct uvcg_framebased *h; - -+ streaming = group->cg_item.ci_parent; -+ color_match = uvcg_format_get_default_color_match(streaming); -+ if (!color_match) -+ return ERR_PTR(-EINVAL); -+ - h = kzalloc(sizeof(*h), GFP_KERNEL); - if (!h) - return ERR_PTR(-ENOMEM); -@@ -2936,6 +2943,9 @@ static struct config_group *uvcg_frameba - - INIT_LIST_HEAD(&h->fmt.frames); - h->fmt.type = UVCG_FRAMEBASED; -+ -+ h->fmt.color_matching = color_match; -+ color_match->refcnt++; - config_group_init_type_name(&h->fmt.group, name, - &uvcg_framebased_type); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/gadget/udc/dummy_hcd.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/gadget/udc/dummy_hcd.c ---- BPI-Router-Linux-kernel/drivers/usb/gadget/udc/dummy_hcd.c 2025-10-22 13:53:23.475327880 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/gadget/udc/dummy_hcd.c 2025-10-22 13:53:56.679168351 -0400 -@@ -765,8 +765,7 @@ static int dummy_dequeue(struct usb_ep * - if (!dum->driver) - return -ESHUTDOWN; - -- local_irq_save(flags); -- spin_lock(&dum->lock); -+ spin_lock_irqsave(&dum->lock, flags); - list_for_each_entry(iter, &ep->queue, queue) { - if (&iter->req != _req) - continue; -@@ -776,15 +775,16 @@ static int dummy_dequeue(struct usb_ep * - retval = 0; - break; - } -- spin_unlock(&dum->lock); - - if (retval == 0) { - dev_dbg(udc_dev(dum), - "dequeued req %p from %s, len %d buf %p\n", - req, _ep->name, _req->length, _req->buf); -+ spin_unlock(&dum->lock); - usb_gadget_giveback_request(_ep, _req); -+ spin_lock(&dum->lock); - } -- local_irq_restore(flags); -+ spin_unlock_irqrestore(&dum->lock, flags); - return retval; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/gadget/udc/renesas_usb3.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/gadget/udc/renesas_usb3.c ---- BPI-Router-Linux-kernel/drivers/usb/gadget/udc/renesas_usb3.c 2025-10-22 13:53:23.475327880 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/gadget/udc/renesas_usb3.c 2025-10-22 13:53:56.679168351 -0400 -@@ -2657,6 +2657,7 @@ static void renesas_usb3_remove(struct p - struct renesas_usb3 *usb3 = platform_get_drvdata(pdev); - - debugfs_remove_recursive(usb3->dentry); -+ put_device(usb3->host_dev); - device_remove_file(&pdev->dev, &dev_attr_role); - - cancel_work_sync(&usb3->role_work); -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/host/xhci.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/host/xhci.c ---- BPI-Router-Linux-kernel/drivers/usb/host/xhci.c 2025-10-22 13:53:23.475327880 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/host/xhci.c 2025-10-22 13:53:56.683168332 -0400 -@@ -85,29 +85,6 @@ int xhci_handshake(void __iomem *ptr, u3 - } - - /* -- * xhci_handshake_check_state - same as xhci_handshake but takes an additional -- * exit_state parameter, and bails out with an error immediately when xhc_state -- * has exit_state flag set. -- */ --int xhci_handshake_check_state(struct xhci_hcd *xhci, void __iomem *ptr, -- u32 mask, u32 done, int usec, unsigned int exit_state) --{ -- u32 result; -- int ret; -- -- ret = readl_poll_timeout_atomic(ptr, result, -- (result & mask) == done || -- result == U32_MAX || -- xhci->xhc_state & exit_state, -- 1, usec); -- -- if (result == U32_MAX || xhci->xhc_state & exit_state) -- return -ENODEV; -- -- return ret; --} -- --/* - * Disable interrupts and begin the xHCI halting process. - */ - void xhci_quiesce(struct xhci_hcd *xhci) -@@ -144,7 +121,8 @@ int xhci_halt(struct xhci_hcd *xhci) - ret = xhci_handshake(&xhci->op_regs->status, - STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC); - if (ret) { -- xhci_warn(xhci, "Host halt failed, %d\n", ret); -+ if (!(xhci->xhc_state & XHCI_STATE_DYING)) -+ xhci_warn(xhci, "Host halt failed, %d\n", ret); - return ret; - } - -@@ -203,7 +181,8 @@ int xhci_reset(struct xhci_hcd *xhci, u6 - state = readl(&xhci->op_regs->status); - - if (state == ~(u32)0) { -- xhci_warn(xhci, "Host not accessible, reset failed.\n"); -+ if (!(xhci->xhc_state & XHCI_STATE_DYING)) -+ xhci_warn(xhci, "Host not accessible, reset failed.\n"); - return -ENODEV; - } - -@@ -227,8 +206,7 @@ int xhci_reset(struct xhci_hcd *xhci, u6 - if (xhci->quirks & XHCI_INTEL_HOST) - udelay(1000); - -- ret = xhci_handshake_check_state(xhci, &xhci->op_regs->command, -- CMD_RESET, 0, timeout_us, XHCI_STATE_REMOVING); -+ ret = xhci_handshake(&xhci->op_regs->command, CMD_RESET, 0, timeout_us); - if (ret) - return ret; - -@@ -331,6 +309,7 @@ int xhci_enable_interrupter(struct xhci_ - return -EINVAL; - - iman = readl(&ir->ir_set->iman); -+ iman &= ~IMAN_IP; - iman |= IMAN_IE; - writel(iman, &ir->ir_set->iman); - -@@ -347,6 +326,7 @@ int xhci_disable_interrupter(struct xhci - return -EINVAL; - - iman = readl(&ir->ir_set->iman); -+ iman &= ~IMAN_IP; - iman &= ~IMAN_IE; - writel(iman, &ir->ir_set->iman); - -@@ -1182,7 +1162,10 @@ int xhci_resume(struct xhci_hcd *xhci, b - xhci_dbg(xhci, "Stop HCD\n"); - xhci_halt(xhci); - xhci_zero_64b_regs(xhci); -- retval = xhci_reset(xhci, XHCI_RESET_LONG_USEC); -+ if (xhci->xhc_state & XHCI_STATE_REMOVING) -+ retval = -ENODEV; -+ else -+ retval = xhci_reset(xhci, XHCI_RESET_LONG_USEC); - spin_unlock_irq(&xhci->lock); - if (retval) - return retval; -@@ -3951,8 +3934,7 @@ static int xhci_discover_or_reset_device - * Obtaining a new device slot to inform the xHCI host that - * the USB device has been reset. - */ -- ret = xhci_disable_slot(xhci, udev->slot_id); -- xhci_free_virt_device(xhci, udev->slot_id); -+ ret = xhci_disable_and_free_slot(xhci, udev->slot_id); - if (!ret) { - ret = xhci_alloc_dev(hcd, udev); - if (ret == 1) -@@ -4109,7 +4091,7 @@ static void xhci_free_dev(struct usb_hcd - xhci_disable_slot(xhci, udev->slot_id); - - spin_lock_irqsave(&xhci->lock, flags); -- xhci_free_virt_device(xhci, udev->slot_id); -+ xhci_free_virt_device(xhci, virt_dev, udev->slot_id); - spin_unlock_irqrestore(&xhci->lock, flags); - - } -@@ -4158,6 +4140,16 @@ int xhci_disable_slot(struct xhci_hcd *x - return 0; - } - -+int xhci_disable_and_free_slot(struct xhci_hcd *xhci, u32 slot_id) -+{ -+ struct xhci_virt_device *vdev = xhci->devs[slot_id]; -+ int ret; -+ -+ ret = xhci_disable_slot(xhci, slot_id); -+ xhci_free_virt_device(xhci, vdev, slot_id); -+ return ret; -+} -+ - /* - * Checks if we have enough host controller resources for the default control - * endpoint. -@@ -4264,8 +4256,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, - return 1; - - disable_slot: -- xhci_disable_slot(xhci, udev->slot_id); -- xhci_free_virt_device(xhci, udev->slot_id); -+ xhci_disable_and_free_slot(xhci, udev->slot_id); - - return 0; - } -@@ -4401,8 +4392,7 @@ static int xhci_setup_device(struct usb_ - dev_warn(&udev->dev, "Device not responding to setup %s.\n", act); - - mutex_unlock(&xhci->mutex); -- ret = xhci_disable_slot(xhci, udev->slot_id); -- xhci_free_virt_device(xhci, udev->slot_id); -+ ret = xhci_disable_and_free_slot(xhci, udev->slot_id); - if (!ret) { - if (xhci_alloc_dev(hcd, udev) == 1) - xhci_setup_addressable_virt_dev(xhci, udev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/host/xhci-dbgcap.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/host/xhci-dbgcap.c ---- BPI-Router-Linux-kernel/drivers/usb/host/xhci-dbgcap.c 2025-10-22 13:53:23.475327880 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/host/xhci-dbgcap.c 2025-10-22 13:53:56.679168351 -0400 -@@ -101,13 +101,34 @@ static u32 xhci_dbc_populate_strings(str - return string_length; - } - -+static void xhci_dbc_init_ep_contexts(struct xhci_dbc *dbc) -+{ -+ struct xhci_ep_ctx *ep_ctx; -+ unsigned int max_burst; -+ dma_addr_t deq; -+ -+ max_burst = DBC_CTRL_MAXBURST(readl(&dbc->regs->control)); -+ -+ /* Populate bulk out endpoint context: */ -+ ep_ctx = dbc_bulkout_ctx(dbc); -+ deq = dbc_bulkout_enq(dbc); -+ ep_ctx->ep_info = 0; -+ ep_ctx->ep_info2 = dbc_epctx_info2(BULK_OUT_EP, 1024, max_burst); -+ ep_ctx->deq = cpu_to_le64(deq | dbc->ring_out->cycle_state); -+ -+ /* Populate bulk in endpoint context: */ -+ ep_ctx = dbc_bulkin_ctx(dbc); -+ deq = dbc_bulkin_enq(dbc); -+ ep_ctx->ep_info = 0; -+ ep_ctx->ep_info2 = dbc_epctx_info2(BULK_IN_EP, 1024, max_burst); -+ ep_ctx->deq = cpu_to_le64(deq | dbc->ring_in->cycle_state); -+} -+ - static void xhci_dbc_init_contexts(struct xhci_dbc *dbc, u32 string_length) - { - struct dbc_info_context *info; -- struct xhci_ep_ctx *ep_ctx; - u32 dev_info; -- dma_addr_t deq, dma; -- unsigned int max_burst; -+ dma_addr_t dma; - - if (!dbc) - return; -@@ -121,20 +142,8 @@ static void xhci_dbc_init_contexts(struc - info->serial = cpu_to_le64(dma + DBC_MAX_STRING_LENGTH * 3); - info->length = cpu_to_le32(string_length); - -- /* Populate bulk out endpoint context: */ -- ep_ctx = dbc_bulkout_ctx(dbc); -- max_burst = DBC_CTRL_MAXBURST(readl(&dbc->regs->control)); -- deq = dbc_bulkout_enq(dbc); -- ep_ctx->ep_info = 0; -- ep_ctx->ep_info2 = dbc_epctx_info2(BULK_OUT_EP, 1024, max_burst); -- ep_ctx->deq = cpu_to_le64(deq | dbc->ring_out->cycle_state); -- -- /* Populate bulk in endpoint context: */ -- ep_ctx = dbc_bulkin_ctx(dbc); -- deq = dbc_bulkin_enq(dbc); -- ep_ctx->ep_info = 0; -- ep_ctx->ep_info2 = dbc_epctx_info2(BULK_IN_EP, 1024, max_burst); -- ep_ctx->deq = cpu_to_le64(deq | dbc->ring_in->cycle_state); -+ /* Populate bulk in and out endpoint contexts: */ -+ xhci_dbc_init_ep_contexts(dbc); - - /* Set DbC context and info registers: */ - lo_hi_writeq(dbc->ctx->dma, &dbc->regs->dccp); -@@ -436,6 +445,42 @@ dbc_alloc_ctx(struct device *dev, gfp_t - return ctx; - } - -+static void xhci_dbc_ring_init(struct xhci_ring *ring) -+{ -+ struct xhci_segment *seg = ring->first_seg; -+ -+ /* clear all trbs on ring in case of old ring */ -+ memset(seg->trbs, 0, TRB_SEGMENT_SIZE); -+ -+ /* Only event ring does not use link TRB */ -+ if (ring->type != TYPE_EVENT) { -+ union xhci_trb *trb = &seg->trbs[TRBS_PER_SEGMENT - 1]; -+ -+ trb->link.segment_ptr = cpu_to_le64(ring->first_seg->dma); -+ trb->link.control = cpu_to_le32(LINK_TOGGLE | TRB_TYPE(TRB_LINK)); -+ } -+ xhci_initialize_ring_info(ring); -+} -+ -+static int xhci_dbc_reinit_ep_rings(struct xhci_dbc *dbc) -+{ -+ struct xhci_ring *in_ring = dbc->eps[BULK_IN].ring; -+ struct xhci_ring *out_ring = dbc->eps[BULK_OUT].ring; -+ -+ if (!in_ring || !out_ring || !dbc->ctx) { -+ dev_warn(dbc->dev, "Can't re-init unallocated endpoints\n"); -+ return -ENODEV; -+ } -+ -+ xhci_dbc_ring_init(in_ring); -+ xhci_dbc_ring_init(out_ring); -+ -+ /* set ep context enqueue, dequeue, and cycle to initial values */ -+ xhci_dbc_init_ep_contexts(dbc); -+ -+ return 0; -+} -+ - static struct xhci_ring * - xhci_dbc_ring_alloc(struct device *dev, enum xhci_ring_type type, gfp_t flags) - { -@@ -464,15 +509,10 @@ xhci_dbc_ring_alloc(struct device *dev, - - seg->dma = dma; - -- /* Only event ring does not use link TRB */ -- if (type != TYPE_EVENT) { -- union xhci_trb *trb = &seg->trbs[TRBS_PER_SEGMENT - 1]; -- -- trb->link.segment_ptr = cpu_to_le64(dma); -- trb->link.control = cpu_to_le32(LINK_TOGGLE | TRB_TYPE(TRB_LINK)); -- } - INIT_LIST_HEAD(&ring->td_list); -- xhci_initialize_ring_info(ring); -+ -+ xhci_dbc_ring_init(ring); -+ - return ring; - dma_fail: - kfree(seg); -@@ -652,6 +692,10 @@ static void xhci_dbc_stop(struct xhci_db - case DS_DISABLED: - return; - case DS_CONFIGURED: -+ spin_lock(&dbc->lock); -+ xhci_dbc_flush_requests(dbc); -+ spin_unlock(&dbc->lock); -+ - if (dbc->driver->disconnect) - dbc->driver->disconnect(dbc); - break; -@@ -860,7 +904,7 @@ static enum evtreturn xhci_dbc_do_handle - dev_info(dbc->dev, "DbC cable unplugged\n"); - dbc->state = DS_ENABLED; - xhci_dbc_flush_requests(dbc); -- -+ xhci_dbc_reinit_ep_rings(dbc); - return EVT_DISC; - } - -@@ -870,7 +914,7 @@ static enum evtreturn xhci_dbc_do_handle - writel(portsc, &dbc->regs->portsc); - dbc->state = DS_ENABLED; - xhci_dbc_flush_requests(dbc); -- -+ xhci_dbc_reinit_ep_rings(dbc); - return EVT_DISC; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/host/xhci-dbgtty.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/host/xhci-dbgtty.c ---- BPI-Router-Linux-kernel/drivers/usb/host/xhci-dbgtty.c 2025-10-22 13:53:23.475327880 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/host/xhci-dbgtty.c 2025-10-22 13:53:56.679168351 -0400 -@@ -617,6 +617,7 @@ int dbc_tty_init(void) - dbc_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; - dbc_tty_driver->subtype = SERIAL_TYPE_NORMAL; - dbc_tty_driver->init_termios = tty_std_termios; -+ dbc_tty_driver->init_termios.c_lflag &= ~ECHO; - dbc_tty_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - dbc_tty_driver->init_termios.c_ispeed = 9600; -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/host/xhci.h BPI-Router-Linux-kernel-6.16.12/drivers/usb/host/xhci.h ---- BPI-Router-Linux-kernel/drivers/usb/host/xhci.h 2025-10-22 13:53:23.475327880 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/host/xhci.h 2025-10-22 13:53:56.683168332 -0400 -@@ -1643,6 +1643,7 @@ struct xhci_hcd { - #define XHCI_WRITE_64_HI_LO BIT_ULL(47) - #define XHCI_CDNS_SCTX_QUIRK BIT_ULL(48) - #define XHCI_ETRON_HOST BIT_ULL(49) -+#define XHCI_LIMIT_ENDPOINT_INTERVAL_9 BIT_ULL(50) - - unsigned int num_active_eps; - unsigned int limit_active_eps; -@@ -1790,7 +1791,7 @@ void xhci_dbg_trace(struct xhci_hcd *xhc - /* xHCI memory management */ - void xhci_mem_cleanup(struct xhci_hcd *xhci); - int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags); --void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id); -+void xhci_free_virt_device(struct xhci_hcd *xhci, struct xhci_virt_device *dev, int slot_id); - int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, struct usb_device *udev, gfp_t flags); - int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udev); - void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci, -@@ -1868,8 +1869,6 @@ void xhci_skip_sec_intr_events(struct xh - /* xHCI host controller glue */ - typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *); - int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, u64 timeout_us); --int xhci_handshake_check_state(struct xhci_hcd *xhci, void __iomem *ptr, -- u32 mask, u32 done, int usec, unsigned int exit_state); - void xhci_quiesce(struct xhci_hcd *xhci); - int xhci_halt(struct xhci_hcd *xhci); - int xhci_start(struct xhci_hcd *xhci); -@@ -1889,6 +1888,7 @@ void xhci_reset_bandwidth(struct usb_hcd - int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, - struct usb_tt *tt, gfp_t mem_flags); - int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id); -+int xhci_disable_and_free_slot(struct xhci_hcd *xhci, u32 slot_id); - int xhci_ext_cap_init(struct xhci_hcd *xhci); - - int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup); -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/host/xhci-hub.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/host/xhci-hub.c ---- BPI-Router-Linux-kernel/drivers/usb/host/xhci-hub.c 2025-10-22 13:53:23.475327880 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/host/xhci-hub.c 2025-10-22 13:53:56.679168351 -0400 -@@ -704,8 +704,7 @@ static int xhci_enter_test_mode(struct x - if (!xhci->devs[i]) - continue; - -- retval = xhci_disable_slot(xhci, i); -- xhci_free_virt_device(xhci, i); -+ retval = xhci_disable_and_free_slot(xhci, i); - if (retval) - xhci_err(xhci, "Failed to disable slot %d, %d. Enter test mode anyway\n", - i, retval); -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/host/xhci-mem.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/host/xhci-mem.c ---- BPI-Router-Linux-kernel/drivers/usb/host/xhci-mem.c 2025-10-22 13:53:23.475327880 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/host/xhci-mem.c 2025-10-22 13:53:56.679168351 -0400 -@@ -865,21 +865,20 @@ free_tts: - * will be manipulated by the configure endpoint, allocate device, or update - * hub functions while this function is removing the TT entries from the list. - */ --void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id) -+void xhci_free_virt_device(struct xhci_hcd *xhci, struct xhci_virt_device *dev, -+ int slot_id) - { -- struct xhci_virt_device *dev; - int i; - int old_active_eps = 0; - - /* Slot ID 0 is reserved */ -- if (slot_id == 0 || !xhci->devs[slot_id]) -+ if (slot_id == 0 || !dev) - return; - -- dev = xhci->devs[slot_id]; -- -- xhci->dcbaa->dev_context_ptrs[slot_id] = 0; -- if (!dev) -- return; -+ /* If device ctx array still points to _this_ device, clear it */ -+ if (dev->out_ctx && -+ xhci->dcbaa->dev_context_ptrs[slot_id] == cpu_to_le64(dev->out_ctx->dma)) -+ xhci->dcbaa->dev_context_ptrs[slot_id] = 0; - - trace_xhci_free_virt_device(dev); - -@@ -920,8 +919,9 @@ void xhci_free_virt_device(struct xhci_h - dev->udev->slot_id = 0; - if (dev->rhub_port && dev->rhub_port->slot_id == slot_id) - dev->rhub_port->slot_id = 0; -- kfree(xhci->devs[slot_id]); -- xhci->devs[slot_id] = NULL; -+ if (xhci->devs[slot_id] == dev) -+ xhci->devs[slot_id] = NULL; -+ kfree(dev); - } - - /* -@@ -962,7 +962,7 @@ static void xhci_free_virt_devices_depth - out: - /* we are now at a leaf device */ - xhci_debugfs_remove_slot(xhci, slot_id); -- xhci_free_virt_device(xhci, slot_id); -+ xhci_free_virt_device(xhci, xhci->devs[slot_id], slot_id); - } - - int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, -@@ -1195,6 +1195,8 @@ int xhci_setup_addressable_virt_dev(stru - ep0_ctx->deq = cpu_to_le64(dev->eps[0].ring->first_seg->dma | - dev->eps[0].ring->cycle_state); - -+ ep0_ctx->tx_info = cpu_to_le32(EP_AVG_TRB_LENGTH(8)); -+ - trace_xhci_setup_addressable_virt_device(dev); - - /* Steps 7 and 8 were done in xhci_alloc_virt_device() */ -@@ -1449,6 +1451,10 @@ int xhci_endpoint_init(struct xhci_hcd * - /* Periodic endpoint bInterval limit quirk */ - if (usb_endpoint_xfer_int(&ep->desc) || - usb_endpoint_xfer_isoc(&ep->desc)) { -+ if ((xhci->quirks & XHCI_LIMIT_ENDPOINT_INTERVAL_9) && -+ interval >= 9) { -+ interval = 8; -+ } - if ((xhci->quirks & XHCI_LIMIT_ENDPOINT_INTERVAL_7) && - udev->speed >= USB_SPEED_HIGH && - interval >= 7) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/host/xhci-pci.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/host/xhci-pci.c ---- BPI-Router-Linux-kernel/drivers/usb/host/xhci-pci.c 2025-10-22 13:53:23.475327880 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/host/xhci-pci.c 2025-10-22 13:53:56.679168351 -0400 -@@ -71,12 +71,22 @@ - #define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_XHCI 0x15ec - #define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_XHCI 0x15f0 - -+#define PCI_DEVICE_ID_AMD_ARIEL_TYPEC_XHCI 0x13ed -+#define PCI_DEVICE_ID_AMD_ARIEL_TYPEA_XHCI 0x13ee -+#define PCI_DEVICE_ID_AMD_STARSHIP_XHCI 0x148c -+#define PCI_DEVICE_ID_AMD_FIREFLIGHT_15D4_XHCI 0x15d4 -+#define PCI_DEVICE_ID_AMD_FIREFLIGHT_15D5_XHCI 0x15d5 -+#define PCI_DEVICE_ID_AMD_RAVEN_15E0_XHCI 0x15e0 -+#define PCI_DEVICE_ID_AMD_RAVEN_15E1_XHCI 0x15e1 -+#define PCI_DEVICE_ID_AMD_RAVEN2_XHCI 0x15e5 - #define PCI_DEVICE_ID_AMD_RENOIR_XHCI 0x1639 - #define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9 - #define PCI_DEVICE_ID_AMD_PROMONTORYA_3 0x43ba - #define PCI_DEVICE_ID_AMD_PROMONTORYA_2 0x43bb - #define PCI_DEVICE_ID_AMD_PROMONTORYA_1 0x43bc - -+#define PCI_DEVICE_ID_ATI_NAVI10_7316_XHCI 0x7316 -+ - #define PCI_DEVICE_ID_ASMEDIA_1042_XHCI 0x1042 - #define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142 - #define PCI_DEVICE_ID_ASMEDIA_1142_XHCI 0x1242 -@@ -280,6 +290,21 @@ static void xhci_pci_quirks(struct devic - if (pdev->vendor == PCI_VENDOR_ID_NEC) - xhci->quirks |= XHCI_NEC_HOST; - -+ if (pdev->vendor == PCI_VENDOR_ID_AMD && -+ (pdev->device == PCI_DEVICE_ID_AMD_ARIEL_TYPEC_XHCI || -+ pdev->device == PCI_DEVICE_ID_AMD_ARIEL_TYPEA_XHCI || -+ pdev->device == PCI_DEVICE_ID_AMD_STARSHIP_XHCI || -+ pdev->device == PCI_DEVICE_ID_AMD_FIREFLIGHT_15D4_XHCI || -+ pdev->device == PCI_DEVICE_ID_AMD_FIREFLIGHT_15D5_XHCI || -+ pdev->device == PCI_DEVICE_ID_AMD_RAVEN_15E0_XHCI || -+ pdev->device == PCI_DEVICE_ID_AMD_RAVEN_15E1_XHCI || -+ pdev->device == PCI_DEVICE_ID_AMD_RAVEN2_XHCI)) -+ xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_9; -+ -+ if (pdev->vendor == PCI_VENDOR_ID_ATI && -+ pdev->device == PCI_DEVICE_ID_ATI_NAVI10_7316_XHCI) -+ xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_9; -+ - if (pdev->vendor == PCI_VENDOR_ID_AMD && xhci->hci_version == 0x96) - xhci->quirks |= XHCI_AMD_0x96_HOST; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/host/xhci-pci-renesas.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/host/xhci-pci-renesas.c ---- BPI-Router-Linux-kernel/drivers/usb/host/xhci-pci-renesas.c 2025-10-22 13:53:23.475327880 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/host/xhci-pci-renesas.c 2025-10-22 13:53:56.679168351 -0400 -@@ -47,8 +47,9 @@ - #define RENESAS_ROM_ERASE_MAGIC 0x5A65726F - #define RENESAS_ROM_WRITE_MAGIC 0x53524F4D - --#define RENESAS_RETRY 10000 --#define RENESAS_DELAY 10 -+#define RENESAS_RETRY 50000 /* 50000 * RENESAS_DELAY ~= 500ms */ -+#define RENESAS_CHIP_ERASE_RETRY 500000 /* 500000 * RENESAS_DELAY ~= 5s */ -+#define RENESAS_DELAY 10 - - #define RENESAS_FW_NAME "renesas_usb_fw.mem" - -@@ -407,7 +408,7 @@ static void renesas_rom_erase(struct pci - /* sleep a bit while ROM is erased */ - msleep(20); - -- for (i = 0; i < RENESAS_RETRY; i++) { -+ for (i = 0; i < RENESAS_CHIP_ERASE_RETRY; i++) { - retval = pci_read_config_byte(pdev, RENESAS_ROM_STATUS, - &status); - status &= RENESAS_ROM_STATUS_ERASE; -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/host/xhci-plat.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/host/xhci-plat.c ---- BPI-Router-Linux-kernel/drivers/usb/host/xhci-plat.c 2025-10-22 13:53:23.475327880 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/host/xhci-plat.c 2025-10-22 13:53:56.679168351 -0400 -@@ -152,7 +152,7 @@ int xhci_plat_probe(struct platform_devi - int ret; - int irq; - struct xhci_plat_priv *priv = NULL; -- bool of_match; -+ const struct of_device_id *of_match; - - if (usb_disabled()) - return -ENODEV; -@@ -328,7 +328,8 @@ int xhci_plat_probe(struct platform_devi - } - - usb3_hcd = xhci_get_usb3_hcd(xhci); -- if (usb3_hcd && HCC_MAX_PSA(xhci->hcc_params) >= 4) -+ if (usb3_hcd && HCC_MAX_PSA(xhci->hcc_params) >= 4 && -+ !(xhci->quirks & XHCI_BROKEN_STREAMS)) - usb3_hcd->can_do_streams = 1; - - if (xhci->shared_hcd) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/host/xhci-ring.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/host/xhci-ring.c ---- BPI-Router-Linux-kernel/drivers/usb/host/xhci-ring.c 2025-10-22 13:53:23.475327880 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/host/xhci-ring.c 2025-10-22 13:53:56.679168351 -0400 -@@ -518,9 +518,8 @@ static int xhci_abort_cmd_ring(struct xh - * In the future we should distinguish between -ENODEV and -ETIMEDOUT - * and try to recover a -ETIMEDOUT with a host controller reset. - */ -- ret = xhci_handshake_check_state(xhci, &xhci->op_regs->cmd_ring, -- CMD_RING_RUNNING, 0, 5 * 1000 * 1000, -- XHCI_STATE_REMOVING); -+ ret = xhci_handshake(&xhci->op_regs->cmd_ring, -+ CMD_RING_RUNNING, 0, 5 * 1000 * 1000); - if (ret < 0) { - xhci_err(xhci, "Abort failed to stop command ring: %d\n", ret); - xhci_halt(xhci); -@@ -1377,12 +1376,15 @@ static void xhci_kill_endpoint_urbs(stru - */ - void xhci_hc_died(struct xhci_hcd *xhci) - { -+ bool notify; - int i, j; - - if (xhci->xhc_state & XHCI_STATE_DYING) - return; - -- xhci_err(xhci, "xHCI host controller not responding, assume dead\n"); -+ notify = !(xhci->xhc_state & XHCI_STATE_REMOVING); -+ if (notify) -+ xhci_err(xhci, "xHCI host controller not responding, assume dead\n"); - xhci->xhc_state |= XHCI_STATE_DYING; - - xhci_cleanup_command_queue(xhci); -@@ -1396,7 +1398,7 @@ void xhci_hc_died(struct xhci_hcd *xhci) - } - - /* inform usb core hc died if PCI remove isn't already handling it */ -- if (!(xhci->xhc_state & XHCI_STATE_REMOVING)) -+ if (notify) - usb_hc_died(xhci_to_hcd(xhci)); - } - -@@ -1590,7 +1592,8 @@ static void xhci_handle_cmd_enable_slot( - command->slot_id = 0; - } - --static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id) -+static void xhci_handle_cmd_disable_slot(struct xhci_hcd *xhci, int slot_id, -+ u32 cmd_comp_code) - { - struct xhci_virt_device *virt_dev; - struct xhci_slot_ctx *slot_ctx; -@@ -1605,6 +1608,10 @@ static void xhci_handle_cmd_disable_slot - if (xhci->quirks & XHCI_EP_LIMIT_QUIRK) - /* Delete default control endpoint resources */ - xhci_free_device_endpoint_resources(xhci, virt_dev, true); -+ if (cmd_comp_code == COMP_SUCCESS) { -+ xhci->dcbaa->dev_context_ptrs[slot_id] = 0; -+ xhci->devs[slot_id] = NULL; -+ } - } - - static void xhci_handle_cmd_config_ep(struct xhci_hcd *xhci, int slot_id) -@@ -1854,7 +1861,7 @@ static void handle_cmd_completion(struct - xhci_handle_cmd_enable_slot(slot_id, cmd, cmd_comp_code); - break; - case TRB_DISABLE_SLOT: -- xhci_handle_cmd_disable_slot(xhci, slot_id); -+ xhci_handle_cmd_disable_slot(xhci, slot_id, cmd_comp_code); - break; - case TRB_CONFIG_EP: - if (!cmd->completion) -@@ -4373,7 +4380,8 @@ static int queue_command(struct xhci_hcd - - if ((xhci->xhc_state & XHCI_STATE_DYING) || - (xhci->xhc_state & XHCI_STATE_HALTED)) { -- xhci_dbg(xhci, "xHCI dying or halted, can't queue_command\n"); -+ xhci_dbg(xhci, "xHCI dying or halted, can't queue_command. state: 0x%x\n", -+ xhci->xhc_state); - return -ESHUTDOWN; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/misc/apple-mfi-fastcharge.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/misc/apple-mfi-fastcharge.c ---- BPI-Router-Linux-kernel/drivers/usb/misc/apple-mfi-fastcharge.c 2025-10-22 13:53:23.475327880 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/misc/apple-mfi-fastcharge.c 2025-10-22 13:53:56.683168332 -0400 -@@ -44,6 +44,7 @@ MODULE_DEVICE_TABLE(usb, mfi_fc_id_table - struct mfi_device { - struct usb_device *udev; - struct power_supply *battery; -+ struct power_supply_desc battery_desc; - int charge_type; - }; - -@@ -178,6 +179,7 @@ static int mfi_fc_probe(struct usb_devic - { - struct power_supply_config battery_cfg = {}; - struct mfi_device *mfi = NULL; -+ char *battery_name; - int err; - - if (!mfi_fc_match(udev)) -@@ -187,23 +189,38 @@ static int mfi_fc_probe(struct usb_devic - if (!mfi) - return -ENOMEM; - -+ battery_name = kasprintf(GFP_KERNEL, "apple_mfi_fastcharge_%d-%d", -+ udev->bus->busnum, udev->devnum); -+ if (!battery_name) { -+ err = -ENOMEM; -+ goto err_free_mfi; -+ } -+ -+ mfi->battery_desc = apple_mfi_fc_desc; -+ mfi->battery_desc.name = battery_name; -+ - battery_cfg.drv_data = mfi; - - mfi->charge_type = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; - mfi->battery = power_supply_register(&udev->dev, -- &apple_mfi_fc_desc, -+ &mfi->battery_desc, - &battery_cfg); - if (IS_ERR(mfi->battery)) { - dev_err(&udev->dev, "Can't register battery\n"); - err = PTR_ERR(mfi->battery); -- kfree(mfi); -- return err; -+ goto err_free_name; - } - - mfi->udev = usb_get_dev(udev); - dev_set_drvdata(&udev->dev, mfi); - - return 0; -+ -+err_free_name: -+ kfree(battery_name); -+err_free_mfi: -+ kfree(mfi); -+ return err; - } - - static void mfi_fc_disconnect(struct usb_device *udev) -@@ -213,6 +230,7 @@ static void mfi_fc_disconnect(struct usb - mfi = dev_get_drvdata(&udev->dev); - if (mfi->battery) - power_supply_unregister(mfi->battery); -+ kfree(mfi->battery_desc.name); - dev_set_drvdata(&udev->dev, NULL); - usb_put_dev(mfi->udev); - kfree(mfi); -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/musb/musb_gadget.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/musb/musb_gadget.c ---- BPI-Router-Linux-kernel/drivers/usb/musb/musb_gadget.c 2025-10-22 13:53:23.475327880 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/musb/musb_gadget.c 2025-10-22 13:53:56.683168332 -0400 -@@ -1913,6 +1913,7 @@ static int musb_gadget_stop(struct usb_g - * gadget driver here and have everything work; - * that currently misbehaves. - */ -+ usb_gadget_set_state(g, USB_STATE_NOTATTACHED); - - /* Force check of devctl register for PM runtime */ - pm_runtime_mark_last_busy(musb->controller); -@@ -2019,6 +2020,7 @@ void musb_g_disconnect(struct musb *musb - case OTG_STATE_B_PERIPHERAL: - case OTG_STATE_B_IDLE: - musb_set_state(musb, OTG_STATE_B_IDLE); -+ usb_gadget_set_state(&musb->g, USB_STATE_NOTATTACHED); - break; - case OTG_STATE_B_SRP_INIT: - break; -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/musb/omap2430.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/musb/omap2430.c ---- BPI-Router-Linux-kernel/drivers/usb/musb/omap2430.c 2025-10-22 13:53:23.475327880 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/musb/omap2430.c 2025-10-22 13:53:56.683168332 -0400 -@@ -400,7 +400,7 @@ static int omap2430_probe(struct platfor - ret = platform_device_add_resources(musb, pdev->resource, pdev->num_resources); - if (ret) { - dev_err(&pdev->dev, "failed to add resources\n"); -- goto err2; -+ goto err_put_control_otghs; - } - - if (populate_irqs) { -@@ -413,7 +413,7 @@ static int omap2430_probe(struct platfor - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - ret = -EINVAL; -- goto err2; -+ goto err_put_control_otghs; - } - - musb_res[i].start = res->start; -@@ -441,14 +441,14 @@ static int omap2430_probe(struct platfor - ret = platform_device_add_resources(musb, musb_res, i); - if (ret) { - dev_err(&pdev->dev, "failed to add IRQ resources\n"); -- goto err2; -+ goto err_put_control_otghs; - } - } - - ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); - if (ret) { - dev_err(&pdev->dev, "failed to add platform_data\n"); -- goto err2; -+ goto err_put_control_otghs; - } - - pm_runtime_enable(glue->dev); -@@ -463,7 +463,9 @@ static int omap2430_probe(struct platfor - - err3: - pm_runtime_disable(glue->dev); -- -+err_put_control_otghs: -+ if (!IS_ERR(glue->control_otghs)) -+ put_device(glue->control_otghs); - err2: - platform_device_put(musb); - -@@ -477,6 +479,8 @@ static void omap2430_remove(struct platf - - platform_device_unregister(glue->musb); - pm_runtime_disable(glue->dev); -+ if (!IS_ERR(glue->control_otghs)) -+ put_device(glue->control_otghs); - } - - #ifdef CONFIG_PM -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/serial/ftdi_sio.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/serial/ftdi_sio.c ---- BPI-Router-Linux-kernel/drivers/usb/serial/ftdi_sio.c 2025-10-22 13:53:23.479327862 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/serial/ftdi_sio.c 2025-10-22 13:53:56.683168332 -0400 -@@ -803,6 +803,8 @@ static const struct usb_device_id id_tab - .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, - { USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID), - .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, -+ { USB_DEVICE(FTDI_NDI_VID, FTDI_NDI_EMGUIDE_GEMINI_PID), -+ .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, - { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, - { USB_DEVICE(NOVITUS_VID, NOVITUS_BONO_E_PID) }, - { USB_DEVICE(FTDI_VID, RTSYSTEMS_USB_VX8_PID) }, -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/serial/ftdi_sio_ids.h BPI-Router-Linux-kernel-6.16.12/drivers/usb/serial/ftdi_sio_ids.h ---- BPI-Router-Linux-kernel/drivers/usb/serial/ftdi_sio_ids.h 2025-10-22 13:53:23.479327862 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/serial/ftdi_sio_ids.h 2025-10-22 13:53:56.683168332 -0400 -@@ -204,6 +204,9 @@ - #define FTDI_NDI_FUTURE_3_PID 0xDA73 /* NDI future device #3 */ - #define FTDI_NDI_AURORA_SCU_PID 0xDA74 /* NDI Aurora SCU */ - -+#define FTDI_NDI_VID 0x23F2 -+#define FTDI_NDI_EMGUIDE_GEMINI_PID 0x0003 /* NDI Emguide Gemini */ -+ - /* - * ChamSys Limited (www.chamsys.co.uk) USB wing/interface product IDs - */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/serial/option.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/serial/option.c ---- BPI-Router-Linux-kernel/drivers/usb/serial/option.c 2025-10-22 13:53:23.479327862 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/serial/option.c 2025-10-22 13:53:56.683168332 -0400 -@@ -1322,7 +1322,18 @@ static const struct usb_device_id option - .driver_info = NCTRL(0) | RSVD(3) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1033, 0xff), /* Telit LE910C1-EUX (ECM) */ - .driver_info = NCTRL(0) }, -+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1034, 0xff), /* Telit LE910C4-WWX (rmnet) */ -+ .driver_info = RSVD(2) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1035, 0xff) }, /* Telit LE910C4-WWX (ECM) */ -+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1036, 0xff) }, /* Telit LE910C4-WWX */ -+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1037, 0xff), /* Telit LE910C4-WWX (rmnet) */ -+ .driver_info = NCTRL(0) | NCTRL(1) | RSVD(4) }, -+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1038, 0xff), /* Telit LE910C4-WWX (rmnet) */ -+ .driver_info = NCTRL(0) | RSVD(3) }, -+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x103b, 0xff), /* Telit LE910C4-WWX */ -+ .driver_info = NCTRL(0) | NCTRL(1) }, -+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x103c, 0xff), /* Telit LE910C4-WWX */ -+ .driver_info = NCTRL(0) }, - { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG0), - .driver_info = RSVD(0) | RSVD(1) | NCTRL(2) | RSVD(3) }, - { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG1), -@@ -1369,6 +1380,12 @@ static const struct usb_device_id option - .driver_info = NCTRL(0) | RSVD(1) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1075, 0xff), /* Telit FN990A (PCIe) */ - .driver_info = RSVD(0) }, -+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1077, 0xff), /* Telit FN990A (rmnet + audio) */ -+ .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, -+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1078, 0xff), /* Telit FN990A (MBIM + audio) */ -+ .driver_info = NCTRL(0) | RSVD(1) }, -+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1079, 0xff), /* Telit FN990A (RNDIS + audio) */ -+ .driver_info = NCTRL(2) | RSVD(3) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1080, 0xff), /* Telit FE990A (rmnet) */ - .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, - { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1081, 0xff), /* Telit FE990A (MBIM) */ -@@ -1415,6 +1432,9 @@ static const struct usb_device_id option - .driver_info = NCTRL(5) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d0, 0xff, 0xff, 0x40) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d0, 0xff, 0xff, 0x60) }, -+ { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10c7, 0xff, 0xff, 0x30), /* Telit FE910C04 (ECM) */ -+ .driver_info = NCTRL(4) }, -+ { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10c7, 0xff, 0xff, 0x40) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d1, 0xff, 0xff, 0x30), /* Telit FN990B (MBIM) */ - .driver_info = NCTRL(6) }, - { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x10d1, 0xff, 0xff, 0x40) }, -@@ -2094,6 +2114,12 @@ static const struct usb_device_id option - { USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x9003, 0xff) }, /* Simcom SIM7500/SIM7600 MBIM mode */ - { USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x9011, 0xff), /* Simcom SIM7500/SIM7600 RNDIS mode */ - .driver_info = RSVD(7) }, -+ { USB_DEVICE(0x1e0e, 0x9071), /* Simcom SIM8230 RMNET mode */ -+ .driver_info = RSVD(3) | RSVD(4) }, -+ { USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x9078, 0xff), /* Simcom SIM8230 ECM mode */ -+ .driver_info = RSVD(5) }, -+ { USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x907b, 0xff), /* Simcom SIM8230 RNDIS mode */ -+ .driver_info = RSVD(5) }, - { USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x9205, 0xff) }, /* Simcom SIM7070/SIM7080/SIM7090 AT+ECM mode */ - { USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x9206, 0xff) }, /* Simcom SIM7070/SIM7080/SIM7090 AT-only mode */ - { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200), -@@ -2343,6 +2369,10 @@ static const struct usb_device_id option - .driver_info = RSVD(3) }, - { USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe145, 0xff), /* Foxconn T99W651 RNDIS */ - .driver_info = RSVD(5) | RSVD(6) }, -+ { USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe15f, 0xff), /* Foxconn T99W709 */ -+ .driver_info = RSVD(5) }, -+ { USB_DEVICE_INTERFACE_CLASS(0x0489, 0xe167, 0xff), /* Foxconn T99W640 MBIM */ -+ .driver_info = RSVD(3) }, - { USB_DEVICE(0x1508, 0x1001), /* Fibocom NL668 (IOT version) */ - .driver_info = RSVD(4) | RSVD(5) | RSVD(6) }, - { USB_DEVICE(0x1782, 0x4d10) }, /* Fibocom L610 (AT mode) */ -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/storage/realtek_cr.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/storage/realtek_cr.c ---- BPI-Router-Linux-kernel/drivers/usb/storage/realtek_cr.c 2025-10-22 13:53:23.479327862 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/storage/realtek_cr.c 2025-10-22 13:53:56.683168332 -0400 -@@ -252,7 +252,7 @@ static int rts51x_bulk_transport(struct - return USB_STOR_TRANSPORT_ERROR; - } - -- residue = bcs->Residue; -+ residue = le32_to_cpu(bcs->Residue); - if (bcs->Tag != us->tag) - return USB_STOR_TRANSPORT_ERROR; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/storage/unusual_devs.h BPI-Router-Linux-kernel-6.16.12/drivers/usb/storage/unusual_devs.h ---- BPI-Router-Linux-kernel/drivers/usb/storage/unusual_devs.h 2025-10-22 13:53:23.479327862 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/storage/unusual_devs.h 2025-10-22 13:53:56.683168332 -0400 -@@ -934,6 +934,13 @@ UNUSUAL_DEV( 0x05e3, 0x0723, 0x9451, 0x - USB_SC_DEVICE, USB_PR_DEVICE, NULL, - US_FL_SANE_SENSE ), - -+/* Added by Maël GUERIN */ -+UNUSUAL_DEV( 0x0603, 0x8611, 0x0000, 0xffff, -+ "Novatek", -+ "NTK96550-based camera", -+ USB_SC_SCSI, USB_PR_BULK, NULL, -+ US_FL_BULK_IGNORE_TAG ), -+ - /* - * Reported by Hanno Boeck - * Taken from the Lycoris Kernel -@@ -1494,6 +1501,28 @@ UNUSUAL_DEV( 0x0bc2, 0x3332, 0x0000, 0x9 - USB_SC_DEVICE, USB_PR_DEVICE, NULL, - US_FL_NO_WP_DETECT ), - -+/* -+ * Reported by Zenm Chen -+ * Ignore driver CD mode, otherwise usb_modeswitch may fail to switch -+ * the device into Wi-Fi mode. -+ */ -+UNUSUAL_DEV( 0x0bda, 0x1a2b, 0x0000, 0xffff, -+ "Realtek", -+ "DISK", -+ USB_SC_DEVICE, USB_PR_DEVICE, NULL, -+ US_FL_IGNORE_DEVICE ), -+ -+/* -+ * Reported by Zenm Chen -+ * Ignore driver CD mode, otherwise usb_modeswitch may fail to switch -+ * the device into Wi-Fi mode. -+ */ -+UNUSUAL_DEV( 0x0bda, 0xa192, 0x0000, 0xffff, -+ "Realtek", -+ "DISK", -+ USB_SC_DEVICE, USB_PR_DEVICE, NULL, -+ US_FL_IGNORE_DEVICE ), -+ - UNUSUAL_DEV( 0x0d49, 0x7310, 0x0000, 0x9999, - "Maxtor", - "USB to SATA", -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/typec/altmodes/displayport.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/altmodes/displayport.c ---- BPI-Router-Linux-kernel/drivers/usb/typec/altmodes/displayport.c 2025-10-22 13:53:23.479327862 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/altmodes/displayport.c 2025-10-22 13:53:56.683168332 -0400 -@@ -394,8 +394,7 @@ static int dp_altmode_vdm(struct typec_a - case CMDT_RSP_NAK: - switch (cmd) { - case DP_CMD_STATUS_UPDATE: -- if (typec_altmode_exit(alt)) -- dev_err(&dp->alt->dev, "Exit Mode Failed!\n"); -+ dp->state = DP_STATE_EXIT; - break; - case DP_CMD_CONFIGURE: - dp->data.conf = 0; -@@ -677,7 +676,7 @@ static ssize_t pin_assignment_show(struc - - assignments = get_current_pin_assignments(dp); - -- for (i = 0; assignments; assignments >>= 1, i++) { -+ for (i = 0; assignments && i < DP_PIN_ASSIGN_MAX; assignments >>= 1, i++) { - if (assignments & 1) { - if (i == cur) - len += sprintf(buf + len, "[%s] ", -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/typec/mux/intel_pmc_mux.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/mux/intel_pmc_mux.c ---- BPI-Router-Linux-kernel/drivers/usb/typec/mux/intel_pmc_mux.c 2025-10-22 13:53:23.479327862 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/mux/intel_pmc_mux.c 2025-10-22 13:53:56.683168332 -0400 -@@ -754,7 +754,7 @@ static int pmc_usb_probe(struct platform - - pmc->ipc = devm_intel_scu_ipc_dev_get(&pdev->dev); - if (!pmc->ipc) -- return -ENODEV; -+ return -EPROBE_DEFER; - - pmc->dev = &pdev->dev; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/typec/tcpm/fusb302.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/tcpm/fusb302.c ---- BPI-Router-Linux-kernel/drivers/usb/typec/tcpm/fusb302.c 2025-10-22 13:53:23.479327862 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/tcpm/fusb302.c 2025-10-22 13:53:56.683168332 -0400 -@@ -104,6 +104,7 @@ struct fusb302_chip { - bool vconn_on; - bool vbus_on; - bool charge_on; -+ bool pd_rx_on; - bool vbus_present; - enum typec_cc_polarity cc_polarity; - enum typec_cc_status cc1; -@@ -841,6 +842,11 @@ static int tcpm_set_pd_rx(struct tcpc_de - int ret = 0; - - mutex_lock(&chip->lock); -+ if (chip->pd_rx_on == on) { -+ fusb302_log(chip, "pd is already %s", str_on_off(on)); -+ goto done; -+ } -+ - ret = fusb302_pd_rx_flush(chip); - if (ret < 0) { - fusb302_log(chip, "cannot flush pd rx buffer, ret=%d", ret); -@@ -863,6 +869,8 @@ static int tcpm_set_pd_rx(struct tcpc_de - str_on_off(on), ret); - goto done; - } -+ -+ chip->pd_rx_on = on; - fusb302_log(chip, "pd := %s", str_on_off(on)); - done: - mutex_unlock(&chip->lock); -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/typec/tcpm/maxim_contaminant.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/tcpm/maxim_contaminant.c ---- BPI-Router-Linux-kernel/drivers/usb/typec/tcpm/maxim_contaminant.c 2025-10-22 13:53:23.479327862 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/tcpm/maxim_contaminant.c 2025-10-22 13:53:56.683168332 -0400 -@@ -188,6 +188,11 @@ static int max_contaminant_read_comparat - if (ret < 0) - return ret; - -+ /* Disable low power mode */ -+ ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL2, CCLPMODESEL, -+ FIELD_PREP(CCLPMODESEL, -+ LOW_POWER_MODE_DISABLE)); -+ - /* Sleep to allow comparators settle */ - usleep_range(5000, 6000); - ret = regmap_update_bits(regmap, TCPC_TCPC_CTRL, TCPC_TCPC_CTRL_ORIENTATION, PLUG_ORNT_CC1); -@@ -324,6 +329,39 @@ static int max_contaminant_enable_dry_de - return 0; - } - -+static int max_contaminant_enable_toggling(struct max_tcpci_chip *chip) -+{ -+ struct regmap *regmap = chip->data.regmap; -+ int ret; -+ -+ /* Disable dry detection if enabled. */ -+ ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL2, CCLPMODESEL, -+ FIELD_PREP(CCLPMODESEL, -+ LOW_POWER_MODE_DISABLE)); -+ if (ret) -+ return ret; -+ -+ ret = regmap_update_bits(regmap, TCPC_VENDOR_CC_CTRL1, CCCONNDRY, 0); -+ if (ret) -+ return ret; -+ -+ ret = max_tcpci_write8(chip, TCPC_ROLE_CTRL, TCPC_ROLE_CTRL_DRP | -+ FIELD_PREP(TCPC_ROLE_CTRL_CC1, -+ TCPC_ROLE_CTRL_CC_RD) | -+ FIELD_PREP(TCPC_ROLE_CTRL_CC2, -+ TCPC_ROLE_CTRL_CC_RD)); -+ if (ret) -+ return ret; -+ -+ ret = regmap_update_bits(regmap, TCPC_TCPC_CTRL, -+ TCPC_TCPC_CTRL_EN_LK4CONN_ALRT, -+ TCPC_TCPC_CTRL_EN_LK4CONN_ALRT); -+ if (ret) -+ return ret; -+ -+ return max_tcpci_write8(chip, TCPC_COMMAND, TCPC_CMD_LOOK4CONNECTION); -+} -+ - bool max_contaminant_is_contaminant(struct max_tcpci_chip *chip, bool disconnect_while_debounce, - bool *cc_handled) - { -@@ -340,6 +378,12 @@ bool max_contaminant_is_contaminant(stru - if (ret < 0) - return false; - -+ if (cc_status & TCPC_CC_STATUS_TOGGLING) { -+ if (chip->contaminant_state == DETECTED) -+ return true; -+ return false; -+ } -+ - if (chip->contaminant_state == NOT_DETECTED || chip->contaminant_state == SINK) { - if (!disconnect_while_debounce) - msleep(100); -@@ -372,6 +416,12 @@ bool max_contaminant_is_contaminant(stru - max_contaminant_enable_dry_detection(chip); - return true; - } -+ -+ ret = max_contaminant_enable_toggling(chip); -+ if (ret) -+ dev_err(chip->dev, -+ "Failed to enable toggling, ret=%d", -+ ret); - } - } else if (chip->contaminant_state == DETECTED) { - if (!(cc_status & TCPC_CC_STATUS_TOGGLING)) { -@@ -379,6 +429,14 @@ bool max_contaminant_is_contaminant(stru - if (chip->contaminant_state == DETECTED) { - max_contaminant_enable_dry_detection(chip); - return true; -+ } else { -+ ret = max_contaminant_enable_toggling(chip); -+ if (ret) { -+ dev_err(chip->dev, -+ "Failed to enable toggling, ret=%d", -+ ret); -+ return true; -+ } - } - } - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/typec/tcpm/tcpci_maxim_core.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/tcpm/tcpci_maxim_core.c ---- BPI-Router-Linux-kernel/drivers/usb/typec/tcpm/tcpci_maxim_core.c 2025-10-22 13:53:23.479327862 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/tcpm/tcpci_maxim_core.c 2025-10-22 13:53:56.683168332 -0400 -@@ -421,21 +421,6 @@ static irqreturn_t max_tcpci_isr(int irq - return IRQ_WAKE_THREAD; - } - --static int max_tcpci_init_alert(struct max_tcpci_chip *chip, struct i2c_client *client) --{ -- int ret; -- -- ret = devm_request_threaded_irq(chip->dev, client->irq, max_tcpci_isr, max_tcpci_irq, -- (IRQF_TRIGGER_LOW | IRQF_ONESHOT), dev_name(chip->dev), -- chip); -- -- if (ret < 0) -- return ret; -- -- enable_irq_wake(client->irq); -- return 0; --} -- - static int max_tcpci_start_toggling(struct tcpci *tcpci, struct tcpci_data *tdata, - enum typec_cc_status cc) - { -@@ -532,7 +517,9 @@ static int max_tcpci_probe(struct i2c_cl - - chip->port = tcpci_get_tcpm_port(chip->tcpci); - -- ret = max_tcpci_init_alert(chip, client); -+ ret = devm_request_threaded_irq(&client->dev, client->irq, max_tcpci_isr, max_tcpci_irq, -+ (IRQF_TRIGGER_LOW | IRQF_ONESHOT), dev_name(chip->dev), -+ chip); - if (ret < 0) - return dev_err_probe(&client->dev, ret, - "IRQ initialization failed\n"); -@@ -544,6 +531,32 @@ static int max_tcpci_probe(struct i2c_cl - return 0; - } - -+#ifdef CONFIG_PM_SLEEP -+static int max_tcpci_resume(struct device *dev) -+{ -+ struct i2c_client *client = to_i2c_client(dev); -+ int ret = 0; -+ -+ if (client->irq && device_may_wakeup(dev)) -+ ret = disable_irq_wake(client->irq); -+ -+ return ret; -+} -+ -+static int max_tcpci_suspend(struct device *dev) -+{ -+ struct i2c_client *client = to_i2c_client(dev); -+ int ret = 0; -+ -+ if (client->irq && device_may_wakeup(dev)) -+ ret = enable_irq_wake(client->irq); -+ -+ return ret; -+} -+#endif /* CONFIG_PM_SLEEP */ -+ -+static SIMPLE_DEV_PM_OPS(max_tcpci_pm_ops, max_tcpci_suspend, max_tcpci_resume); -+ - static const struct i2c_device_id max_tcpci_id[] = { - { "maxtcpc" }, - { } -@@ -562,6 +575,7 @@ static struct i2c_driver max_tcpci_i2c_d - .driver = { - .name = "maxtcpc", - .of_match_table = of_match_ptr(max_tcpci_of_match), -+ .pm = &max_tcpci_pm_ops, - }, - .probe = max_tcpci_probe, - .id_table = max_tcpci_id, -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/typec/tcpm/tcpci_maxim.h BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/tcpm/tcpci_maxim.h ---- BPI-Router-Linux-kernel/drivers/usb/typec/tcpm/tcpci_maxim.h 2025-10-22 13:53:23.479327862 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/tcpm/tcpci_maxim.h 2025-10-22 13:53:56.683168332 -0400 -@@ -21,6 +21,7 @@ - #define CCOVPDIS BIT(6) - #define SBURPCTRL BIT(5) - #define CCLPMODESEL GENMASK(4, 3) -+#define LOW_POWER_MODE_DISABLE 0 - #define ULTRA_LOW_POWER_MODE 1 - #define CCRPCTRL GENMASK(2, 0) - #define UA_1_SRC 1 -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/typec/tcpm/tcpm.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/tcpm/tcpm.c ---- BPI-Router-Linux-kernel/drivers/usb/typec/tcpm/tcpm.c 2025-10-22 13:53:23.479327862 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/tcpm/tcpm.c 2025-10-22 13:53:56.683168332 -0400 -@@ -2426,17 +2426,21 @@ static void tcpm_handle_vdm_request(stru - case ADEV_NONE: - break; - case ADEV_NOTIFY_USB_AND_QUEUE_VDM: -- WARN_ON(typec_altmode_notify(adev, TYPEC_STATE_USB, NULL)); -- typec_altmode_vdm(adev, p[0], &p[1], cnt); -+ if (rx_sop_type == TCPC_TX_SOP_PRIME) { -+ typec_cable_altmode_vdm(adev, TYPEC_PLUG_SOP_P, p[0], &p[1], cnt); -+ } else { -+ WARN_ON(typec_altmode_notify(adev, TYPEC_STATE_USB, NULL)); -+ typec_altmode_vdm(adev, p[0], &p[1], cnt); -+ } - break; - case ADEV_QUEUE_VDM: -- if (response_tx_sop_type == TCPC_TX_SOP_PRIME) -+ if (rx_sop_type == TCPC_TX_SOP_PRIME) - typec_cable_altmode_vdm(adev, TYPEC_PLUG_SOP_P, p[0], &p[1], cnt); - else - typec_altmode_vdm(adev, p[0], &p[1], cnt); - break; - case ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL: -- if (response_tx_sop_type == TCPC_TX_SOP_PRIME) { -+ if (rx_sop_type == TCPC_TX_SOP_PRIME) { - if (typec_cable_altmode_vdm(adev, TYPEC_PLUG_SOP_P, - p[0], &p[1], cnt)) { - int svdm_version = typec_get_cable_svdm_version( -@@ -4410,17 +4414,6 @@ static int tcpm_src_attach(struct tcpm_p - - tcpm_enable_auto_vbus_discharge(port, true); - -- ret = tcpm_set_roles(port, true, TYPEC_STATE_USB, -- TYPEC_SOURCE, tcpm_data_role_for_source(port)); -- if (ret < 0) -- return ret; -- -- if (port->pd_supported) { -- ret = port->tcpc->set_pd_rx(port->tcpc, true); -- if (ret < 0) -- goto out_disable_mux; -- } -- - /* - * USB Type-C specification, version 1.2, - * chapter 4.5.2.2.8.1 (Attached.SRC Requirements) -@@ -4430,13 +4423,24 @@ static int tcpm_src_attach(struct tcpm_p - (polarity == TYPEC_POLARITY_CC2 && port->cc1 == TYPEC_CC_RA)) { - ret = tcpm_set_vconn(port, true); - if (ret < 0) -- goto out_disable_pd; -+ return ret; - } - - ret = tcpm_set_vbus(port, true); - if (ret < 0) - goto out_disable_vconn; - -+ ret = tcpm_set_roles(port, true, TYPEC_STATE_USB, TYPEC_SOURCE, -+ tcpm_data_role_for_source(port)); -+ if (ret < 0) -+ goto out_disable_vbus; -+ -+ if (port->pd_supported) { -+ ret = port->tcpc->set_pd_rx(port->tcpc, true); -+ if (ret < 0) -+ goto out_disable_mux; -+ } -+ - port->pd_capable = false; - - port->partner = NULL; -@@ -4447,14 +4451,14 @@ static int tcpm_src_attach(struct tcpm_p - - return 0; - --out_disable_vconn: -- tcpm_set_vconn(port, false); --out_disable_pd: -- if (port->pd_supported) -- port->tcpc->set_pd_rx(port->tcpc, false); - out_disable_mux: - tcpm_mux_set(port, TYPEC_STATE_SAFE, USB_ROLE_NONE, - TYPEC_ORIENTATION_NONE); -+out_disable_vbus: -+ tcpm_set_vbus(port, false); -+out_disable_vconn: -+ tcpm_set_vconn(port, false); -+ - return ret; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/typec/ucsi/cros_ec_ucsi.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/ucsi/cros_ec_ucsi.c ---- BPI-Router-Linux-kernel/drivers/usb/typec/ucsi/cros_ec_ucsi.c 2025-10-22 13:53:23.479327862 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/ucsi/cros_ec_ucsi.c 2025-10-22 13:53:56.683168332 -0400 -@@ -137,6 +137,7 @@ static int cros_ucsi_sync_control(struct - static const struct ucsi_operations cros_ucsi_ops = { - .read_version = cros_ucsi_read_version, - .read_cci = cros_ucsi_read_cci, -+ .poll_cci = cros_ucsi_read_cci, - .read_message_in = cros_ucsi_read_message_in, - .async_control = cros_ucsi_async_control, - .sync_control = cros_ucsi_sync_control, -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/typec/ucsi/psy.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/ucsi/psy.c ---- BPI-Router-Linux-kernel/drivers/usb/typec/ucsi/psy.c 2025-10-22 13:53:23.479327862 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/ucsi/psy.c 2025-10-22 13:53:56.683168332 -0400 -@@ -164,7 +164,7 @@ static int ucsi_psy_get_current_max(stru - case UCSI_CONSTAT_PWR_OPMODE_DEFAULT: - /* UCSI can't tell b/w DCP/CDP or USB2/3x1/3x2 SDP chargers */ - default: -- val->intval = 0; -+ val->intval = UCSI_TYPEC_DEFAULT_CURRENT * 1000; - break; - } - return 0; -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/typec/ucsi/ucsi.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/ucsi/ucsi.c ---- BPI-Router-Linux-kernel/drivers/usb/typec/ucsi/ucsi.c 2025-10-22 13:53:23.479327862 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/ucsi/ucsi.c 2025-10-22 13:53:56.683168332 -0400 -@@ -1246,6 +1246,7 @@ static void ucsi_handle_connector_change - - if (change & UCSI_CONSTAT_POWER_DIR_CHANGE) { - typec_set_pwr_role(con->port, role); -+ ucsi_port_psy_changed(con); - - /* Complete pending power role swap */ - if (!completion_done(&con->complete)) -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/typec/ucsi/ucsi.h BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/ucsi/ucsi.h ---- BPI-Router-Linux-kernel/drivers/usb/typec/ucsi/ucsi.h 2025-10-22 13:53:23.479327862 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/ucsi/ucsi.h 2025-10-22 13:53:56.683168332 -0400 -@@ -481,9 +481,10 @@ struct ucsi { - #define UCSI_MAX_SVID 5 - #define UCSI_MAX_ALTMODES (UCSI_MAX_SVID * 6) - --#define UCSI_TYPEC_VSAFE5V 5000 --#define UCSI_TYPEC_1_5_CURRENT 1500 --#define UCSI_TYPEC_3_0_CURRENT 3000 -+#define UCSI_TYPEC_VSAFE5V 5000 -+#define UCSI_TYPEC_DEFAULT_CURRENT 100 -+#define UCSI_TYPEC_1_5_CURRENT 1500 -+#define UCSI_TYPEC_3_0_CURRENT 3000 - - struct ucsi_connector { - int num; -diff -purNx .git BPI-Router-Linux-kernel/drivers/usb/typec/ucsi/ucsi_yoga_c630.c BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/ucsi/ucsi_yoga_c630.c ---- BPI-Router-Linux-kernel/drivers/usb/typec/ucsi/ucsi_yoga_c630.c 2025-10-22 13:53:23.479327862 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/usb/typec/ucsi/ucsi_yoga_c630.c 2025-10-22 13:53:56.683168332 -0400 -@@ -133,17 +133,30 @@ static int yoga_c630_ucsi_probe(struct a - - ret = yoga_c630_ec_register_notify(ec, &uec->nb); - if (ret) -- return ret; -+ goto err_destroy; - -- return ucsi_register(uec->ucsi); -+ ret = ucsi_register(uec->ucsi); -+ if (ret) -+ goto err_unregister; -+ -+ return 0; -+ -+err_unregister: -+ yoga_c630_ec_unregister_notify(uec->ec, &uec->nb); -+ -+err_destroy: -+ ucsi_destroy(uec->ucsi); -+ -+ return ret; - } - - static void yoga_c630_ucsi_remove(struct auxiliary_device *adev) - { - struct yoga_c630_ucsi *uec = auxiliary_get_drvdata(adev); - -- yoga_c630_ec_unregister_notify(uec->ec, &uec->nb); - ucsi_unregister(uec->ucsi); -+ yoga_c630_ec_unregister_notify(uec->ec, &uec->nb); -+ ucsi_destroy(uec->ucsi); - } - - static const struct auxiliary_device_id yoga_c630_ucsi_id_table[] = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/vdpa/mlx5/core/mr.c BPI-Router-Linux-kernel-6.16.12/drivers/vdpa/mlx5/core/mr.c ---- BPI-Router-Linux-kernel/drivers/vdpa/mlx5/core/mr.c 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/vdpa/mlx5/core/mr.c 2025-10-22 13:53:56.683168332 -0400 -@@ -908,6 +908,9 @@ void mlx5_vdpa_destroy_mr_resources(stru - { - struct mlx5_vdpa_mr_resources *mres = &mvdev->mres; - -+ if (!mres->wq_gc) -+ return; -+ - atomic_set(&mres->shutdown, 1); - - flush_delayed_work(&mres->gc_dwork_ent); -diff -purNx .git BPI-Router-Linux-kernel/drivers/vdpa/mlx5/net/mlx5_vnet.c BPI-Router-Linux-kernel-6.16.12/drivers/vdpa/mlx5/net/mlx5_vnet.c ---- BPI-Router-Linux-kernel/drivers/vdpa/mlx5/net/mlx5_vnet.c 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/vdpa/mlx5/net/mlx5_vnet.c 2025-10-22 13:53:56.683168332 -0400 -@@ -2491,7 +2491,7 @@ static void mlx5_vdpa_set_vq_num(struct - } - - mvq = &ndev->vqs[idx]; -- ndev->needs_teardown = num != mvq->num_ent; -+ ndev->needs_teardown |= num != mvq->num_ent; - mvq->num_ent = num; - } - -@@ -3432,15 +3432,17 @@ static void mlx5_vdpa_free(struct vdpa_d - - ndev = to_mlx5_vdpa_ndev(mvdev); - -+ /* Functions called here should be able to work with -+ * uninitialized resources. -+ */ - free_fixed_resources(ndev); - mlx5_vdpa_clean_mrs(mvdev); - mlx5_vdpa_destroy_mr_resources(&ndev->mvdev); -- mlx5_cmd_cleanup_async_ctx(&mvdev->async_ctx); -- - if (!is_zero_ether_addr(ndev->config.mac)) { - pfmdev = pci_get_drvdata(pci_physfn(mvdev->mdev->pdev)); - mlx5_mpfs_del_mac(pfmdev, ndev->config.mac); - } -+ mlx5_cmd_cleanup_async_ctx(&mvdev->async_ctx); - mlx5_vdpa_free_resources(&ndev->mvdev); - free_irqs(ndev); - kfree(ndev->event_cbs); -@@ -3888,6 +3890,8 @@ static int mlx5_vdpa_dev_add(struct vdpa - mvdev->actual_features = - (device_features & BIT_ULL(VIRTIO_F_VERSION_1)); - -+ mlx5_cmd_init_async_ctx(mdev, &mvdev->async_ctx); -+ - ndev->vqs = kcalloc(max_vqs, sizeof(*ndev->vqs), GFP_KERNEL); - ndev->event_cbs = kcalloc(max_vqs + 1, sizeof(*ndev->event_cbs), GFP_KERNEL); - if (!ndev->vqs || !ndev->event_cbs) { -@@ -3960,8 +3964,6 @@ static int mlx5_vdpa_dev_add(struct vdpa - ndev->rqt_size = 1; - } - -- mlx5_cmd_init_async_ctx(mdev, &mvdev->async_ctx); -- - ndev->mvdev.mlx_features = device_features; - mvdev->vdev.dma_dev = &mdev->pdev->dev; - err = mlx5_vdpa_alloc_resources(&ndev->mvdev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/vdpa/vdpa_user/vduse_dev.c BPI-Router-Linux-kernel-6.16.12/drivers/vdpa/vdpa_user/vduse_dev.c ---- BPI-Router-Linux-kernel/drivers/vdpa/vdpa_user/vduse_dev.c 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/vdpa/vdpa_user/vduse_dev.c 2025-10-22 13:53:56.683168332 -0400 -@@ -2216,6 +2216,7 @@ static void vduse_exit(void) - cdev_del(&vduse_ctrl_cdev); - unregister_chrdev_region(vduse_major, VDUSE_DEV_MAX); - class_unregister(&vduse_class); -+ idr_destroy(&vduse_idr); - } - module_exit(vduse_exit); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/vfio/device_cdev.c BPI-Router-Linux-kernel-6.16.12/drivers/vfio/device_cdev.c ---- BPI-Router-Linux-kernel/drivers/vfio/device_cdev.c 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/vfio/device_cdev.c 2025-10-22 13:53:56.683168332 -0400 -@@ -60,22 +60,50 @@ static void vfio_df_get_kvm_safe(struct - spin_unlock(&df->kvm_ref_lock); - } - -+static int vfio_df_check_token(struct vfio_device *device, -+ const struct vfio_device_bind_iommufd *bind) -+{ -+ uuid_t uuid; -+ -+ if (!device->ops->match_token_uuid) { -+ if (bind->flags & VFIO_DEVICE_BIND_FLAG_TOKEN) -+ return -EINVAL; -+ return 0; -+ } -+ -+ if (!(bind->flags & VFIO_DEVICE_BIND_FLAG_TOKEN)) -+ return device->ops->match_token_uuid(device, NULL); -+ -+ if (copy_from_user(&uuid, u64_to_user_ptr(bind->token_uuid_ptr), -+ sizeof(uuid))) -+ return -EFAULT; -+ return device->ops->match_token_uuid(device, &uuid); -+} -+ - long vfio_df_ioctl_bind_iommufd(struct vfio_device_file *df, - struct vfio_device_bind_iommufd __user *arg) - { -+ const u32 VALID_FLAGS = VFIO_DEVICE_BIND_FLAG_TOKEN; - struct vfio_device *device = df->device; - struct vfio_device_bind_iommufd bind; - unsigned long minsz; -+ u32 user_size; - int ret; - - static_assert(__same_type(arg->out_devid, df->devid)); - - minsz = offsetofend(struct vfio_device_bind_iommufd, out_devid); - -- if (copy_from_user(&bind, arg, minsz)) -- return -EFAULT; -+ ret = get_user(user_size, &arg->argsz); -+ if (ret) -+ return ret; -+ if (user_size < minsz) -+ return -EINVAL; -+ ret = copy_struct_from_user(&bind, minsz, arg, user_size); -+ if (ret) -+ return ret; - -- if (bind.argsz < minsz || bind.flags || bind.iommufd < 0) -+ if (bind.iommufd < 0 || bind.flags & ~VALID_FLAGS) - return -EINVAL; - - /* BIND_IOMMUFD only allowed for cdev fds */ -@@ -93,6 +121,10 @@ long vfio_df_ioctl_bind_iommufd(struct v - goto out_unlock; - } - -+ ret = vfio_df_check_token(device, &bind); -+ if (ret) -+ goto out_unlock; -+ - df->iommufd = iommufd_ctx_from_fd(bind.iommufd); - if (IS_ERR(df->iommufd)) { - ret = PTR_ERR(df->iommufd); -diff -purNx .git BPI-Router-Linux-kernel/drivers/vfio/group.c BPI-Router-Linux-kernel-6.16.12/drivers/vfio/group.c ---- BPI-Router-Linux-kernel/drivers/vfio/group.c 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/vfio/group.c 2025-10-22 13:53:56.683168332 -0400 -@@ -192,11 +192,10 @@ static int vfio_df_group_open(struct vfi - * implies they expected translation to exist - */ - if (!capable(CAP_SYS_RAWIO) || -- vfio_iommufd_device_has_compat_ioas(device, df->iommufd)) -+ vfio_iommufd_device_has_compat_ioas(device, df->iommufd)) { - ret = -EPERM; -- else -- ret = 0; -- goto out_put_kvm; -+ goto out_put_kvm; -+ } - } - - ret = vfio_df_open(df); -diff -purNx .git BPI-Router-Linux-kernel/drivers/vfio/iommufd.c BPI-Router-Linux-kernel-6.16.12/drivers/vfio/iommufd.c ---- BPI-Router-Linux-kernel/drivers/vfio/iommufd.c 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/vfio/iommufd.c 2025-10-22 13:53:56.683168332 -0400 -@@ -25,6 +25,10 @@ int vfio_df_iommufd_bind(struct vfio_dev - - lockdep_assert_held(&vdev->dev_set->lock); - -+ /* Returns 0 to permit device opening under noiommu mode */ -+ if (vfio_device_is_noiommu(vdev)) -+ return 0; -+ - return vdev->ops->bind_iommufd(vdev, ictx, &df->devid); - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c BPI-Router-Linux-kernel-6.16.12/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c ---- BPI-Router-Linux-kernel/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c 2025-10-22 13:53:56.687168312 -0400 -@@ -1583,6 +1583,7 @@ static const struct vfio_device_ops hisi - .mmap = vfio_pci_core_mmap, - .request = vfio_pci_core_request, - .match = vfio_pci_core_match, -+ .match_token_uuid = vfio_pci_core_match_token_uuid, - .bind_iommufd = vfio_iommufd_physical_bind, - .unbind_iommufd = vfio_iommufd_physical_unbind, - .attach_ioas = vfio_iommufd_physical_attach_ioas, -diff -purNx .git BPI-Router-Linux-kernel/drivers/vfio/pci/mlx5/cmd.c BPI-Router-Linux-kernel-6.16.12/drivers/vfio/pci/mlx5/cmd.c ---- BPI-Router-Linux-kernel/drivers/vfio/pci/mlx5/cmd.c 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/vfio/pci/mlx5/cmd.c 2025-10-22 13:53:56.687168312 -0400 -@@ -1523,8 +1523,8 @@ int mlx5vf_start_page_tracker(struct vfi - log_max_msg_size = MLX5_CAP_ADV_VIRTUALIZATION(mdev, pg_track_log_max_msg_size); - max_msg_size = (1ULL << log_max_msg_size); - /* The RQ must hold at least 4 WQEs/messages for successful QP creation */ -- if (rq_size < 4 * max_msg_size) -- rq_size = 4 * max_msg_size; -+ if (rq_size < 4ULL * max_msg_size) -+ rq_size = 4ULL * max_msg_size; - - memset(tracker, 0, sizeof(*tracker)); - tracker->uar = mlx5_get_uars_page(mdev); -diff -purNx .git BPI-Router-Linux-kernel/drivers/vfio/pci/mlx5/main.c BPI-Router-Linux-kernel-6.16.12/drivers/vfio/pci/mlx5/main.c ---- BPI-Router-Linux-kernel/drivers/vfio/pci/mlx5/main.c 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/vfio/pci/mlx5/main.c 2025-10-22 13:53:56.687168312 -0400 -@@ -1372,6 +1372,7 @@ static const struct vfio_device_ops mlx5 - .mmap = vfio_pci_core_mmap, - .request = vfio_pci_core_request, - .match = vfio_pci_core_match, -+ .match_token_uuid = vfio_pci_core_match_token_uuid, - .bind_iommufd = vfio_iommufd_physical_bind, - .unbind_iommufd = vfio_iommufd_physical_unbind, - .attach_ioas = vfio_iommufd_physical_attach_ioas, -diff -purNx .git BPI-Router-Linux-kernel/drivers/vfio/pci/nvgrace-gpu/main.c BPI-Router-Linux-kernel-6.16.12/drivers/vfio/pci/nvgrace-gpu/main.c ---- BPI-Router-Linux-kernel/drivers/vfio/pci/nvgrace-gpu/main.c 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/vfio/pci/nvgrace-gpu/main.c 2025-10-22 13:53:56.687168312 -0400 -@@ -696,6 +696,7 @@ static const struct vfio_device_ops nvgr - .mmap = nvgrace_gpu_mmap, - .request = vfio_pci_core_request, - .match = vfio_pci_core_match, -+ .match_token_uuid = vfio_pci_core_match_token_uuid, - .bind_iommufd = vfio_iommufd_physical_bind, - .unbind_iommufd = vfio_iommufd_physical_unbind, - .attach_ioas = vfio_iommufd_physical_attach_ioas, -@@ -715,6 +716,7 @@ static const struct vfio_device_ops nvgr - .mmap = vfio_pci_core_mmap, - .request = vfio_pci_core_request, - .match = vfio_pci_core_match, -+ .match_token_uuid = vfio_pci_core_match_token_uuid, - .bind_iommufd = vfio_iommufd_physical_bind, - .unbind_iommufd = vfio_iommufd_physical_unbind, - .attach_ioas = vfio_iommufd_physical_attach_ioas, -diff -purNx .git BPI-Router-Linux-kernel/drivers/vfio/pci/pds/vfio_dev.c BPI-Router-Linux-kernel-6.16.12/drivers/vfio/pci/pds/vfio_dev.c ---- BPI-Router-Linux-kernel/drivers/vfio/pci/pds/vfio_dev.c 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/vfio/pci/pds/vfio_dev.c 2025-10-22 13:53:56.687168312 -0400 -@@ -201,9 +201,11 @@ static const struct vfio_device_ops pds_ - .mmap = vfio_pci_core_mmap, - .request = vfio_pci_core_request, - .match = vfio_pci_core_match, -+ .match_token_uuid = vfio_pci_core_match_token_uuid, - .bind_iommufd = vfio_iommufd_physical_bind, - .unbind_iommufd = vfio_iommufd_physical_unbind, - .attach_ioas = vfio_iommufd_physical_attach_ioas, -+ .detach_ioas = vfio_iommufd_physical_detach_ioas, - }; - - const struct vfio_device_ops *pds_vfio_ops_info(void) -diff -purNx .git BPI-Router-Linux-kernel/drivers/vfio/pci/qat/main.c BPI-Router-Linux-kernel-6.16.12/drivers/vfio/pci/qat/main.c ---- BPI-Router-Linux-kernel/drivers/vfio/pci/qat/main.c 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/vfio/pci/qat/main.c 2025-10-22 13:53:56.687168312 -0400 -@@ -614,6 +614,7 @@ static const struct vfio_device_ops qat_ - .mmap = vfio_pci_core_mmap, - .request = vfio_pci_core_request, - .match = vfio_pci_core_match, -+ .match_token_uuid = vfio_pci_core_match_token_uuid, - .bind_iommufd = vfio_iommufd_physical_bind, - .unbind_iommufd = vfio_iommufd_physical_unbind, - .attach_ioas = vfio_iommufd_physical_attach_ioas, -diff -purNx .git BPI-Router-Linux-kernel/drivers/vfio/pci/vfio_pci.c BPI-Router-Linux-kernel-6.16.12/drivers/vfio/pci/vfio_pci.c ---- BPI-Router-Linux-kernel/drivers/vfio/pci/vfio_pci.c 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/vfio/pci/vfio_pci.c 2025-10-22 13:53:56.687168312 -0400 -@@ -138,6 +138,7 @@ static const struct vfio_device_ops vfio - .mmap = vfio_pci_core_mmap, - .request = vfio_pci_core_request, - .match = vfio_pci_core_match, -+ .match_token_uuid = vfio_pci_core_match_token_uuid, - .bind_iommufd = vfio_iommufd_physical_bind, - .unbind_iommufd = vfio_iommufd_physical_unbind, - .attach_ioas = vfio_iommufd_physical_attach_ioas, -diff -purNx .git BPI-Router-Linux-kernel/drivers/vfio/pci/vfio_pci_core.c BPI-Router-Linux-kernel-6.16.12/drivers/vfio/pci/vfio_pci_core.c ---- BPI-Router-Linux-kernel/drivers/vfio/pci/vfio_pci_core.c 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/vfio/pci/vfio_pci_core.c 2025-10-22 13:53:56.687168312 -0400 -@@ -1821,9 +1821,13 @@ void vfio_pci_core_request(struct vfio_d - } - EXPORT_SYMBOL_GPL(vfio_pci_core_request); - --static int vfio_pci_validate_vf_token(struct vfio_pci_core_device *vdev, -- bool vf_token, uuid_t *uuid) -+int vfio_pci_core_match_token_uuid(struct vfio_device *core_vdev, -+ const uuid_t *uuid) -+ - { -+ struct vfio_pci_core_device *vdev = -+ container_of(core_vdev, struct vfio_pci_core_device, vdev); -+ - /* - * There's always some degree of trust or collaboration between SR-IOV - * PF and VFs, even if just that the PF hosts the SR-IOV capability and -@@ -1854,7 +1858,7 @@ static int vfio_pci_validate_vf_token(st - bool match; - - if (!pf_vdev) { -- if (!vf_token) -+ if (!uuid) - return 0; /* PF is not vfio-pci, no VF token */ - - pci_info_ratelimited(vdev->pdev, -@@ -1862,7 +1866,7 @@ static int vfio_pci_validate_vf_token(st - return -EINVAL; - } - -- if (!vf_token) { -+ if (!uuid) { - pci_info_ratelimited(vdev->pdev, - "VF token required to access device\n"); - return -EACCES; -@@ -1880,7 +1884,7 @@ static int vfio_pci_validate_vf_token(st - } else if (vdev->vf_token) { - mutex_lock(&vdev->vf_token->lock); - if (vdev->vf_token->users) { -- if (!vf_token) { -+ if (!uuid) { - mutex_unlock(&vdev->vf_token->lock); - pci_info_ratelimited(vdev->pdev, - "VF token required to access device\n"); -@@ -1893,12 +1897,12 @@ static int vfio_pci_validate_vf_token(st - "Incorrect VF token provided for device\n"); - return -EACCES; - } -- } else if (vf_token) { -+ } else if (uuid) { - uuid_copy(&vdev->vf_token->uuid, uuid); - } - - mutex_unlock(&vdev->vf_token->lock); -- } else if (vf_token) { -+ } else if (uuid) { - pci_info_ratelimited(vdev->pdev, - "VF token incorrectly provided, not a PF or VF\n"); - return -EINVAL; -@@ -1906,6 +1910,7 @@ static int vfio_pci_validate_vf_token(st - - return 0; - } -+EXPORT_SYMBOL_GPL(vfio_pci_core_match_token_uuid); - - #define VF_TOKEN_ARG "vf_token=" - -@@ -1952,7 +1957,8 @@ int vfio_pci_core_match(struct vfio_devi - } - } - -- ret = vfio_pci_validate_vf_token(vdev, vf_token, &uuid); -+ ret = core_vdev->ops->match_token_uuid(core_vdev, -+ vf_token ? &uuid : NULL); - if (ret) - return ret; - -@@ -2149,7 +2155,7 @@ int vfio_pci_core_register_device(struct - return -EBUSY; - } - -- if (pci_is_root_bus(pdev->bus)) { -+ if (pci_is_root_bus(pdev->bus) || pdev->is_virtfn) { - ret = vfio_assign_device_set(&vdev->vdev, vdev); - } else if (!pci_probe_reset_slot(pdev->slot)) { - ret = vfio_assign_device_set(&vdev->vdev, pdev->slot); -diff -purNx .git BPI-Router-Linux-kernel/drivers/vfio/pci/virtio/main.c BPI-Router-Linux-kernel-6.16.12/drivers/vfio/pci/virtio/main.c ---- BPI-Router-Linux-kernel/drivers/vfio/pci/virtio/main.c 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/vfio/pci/virtio/main.c 2025-10-22 13:53:56.687168312 -0400 -@@ -94,6 +94,7 @@ static const struct vfio_device_ops virt - .mmap = vfio_pci_core_mmap, - .request = vfio_pci_core_request, - .match = vfio_pci_core_match, -+ .match_token_uuid = vfio_pci_core_match_token_uuid, - .bind_iommufd = vfio_iommufd_physical_bind, - .unbind_iommufd = vfio_iommufd_physical_unbind, - .attach_ioas = vfio_iommufd_physical_attach_ioas, -@@ -114,6 +115,7 @@ static const struct vfio_device_ops virt - .mmap = vfio_pci_core_mmap, - .request = vfio_pci_core_request, - .match = vfio_pci_core_match, -+ .match_token_uuid = vfio_pci_core_match_token_uuid, - .bind_iommufd = vfio_iommufd_physical_bind, - .unbind_iommufd = vfio_iommufd_physical_unbind, - .attach_ioas = vfio_iommufd_physical_attach_ioas, -@@ -134,6 +136,7 @@ static const struct vfio_device_ops virt - .mmap = vfio_pci_core_mmap, - .request = vfio_pci_core_request, - .match = vfio_pci_core_match, -+ .match_token_uuid = vfio_pci_core_match_token_uuid, - .bind_iommufd = vfio_iommufd_physical_bind, - .unbind_iommufd = vfio_iommufd_physical_unbind, - .attach_ioas = vfio_iommufd_physical_attach_ioas, -diff -purNx .git BPI-Router-Linux-kernel/drivers/vfio/vfio_iommu_type1.c BPI-Router-Linux-kernel-6.16.12/drivers/vfio/vfio_iommu_type1.c ---- BPI-Router-Linux-kernel/drivers/vfio/vfio_iommu_type1.c 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/vfio/vfio_iommu_type1.c 2025-10-22 13:53:56.687168312 -0400 -@@ -647,6 +647,13 @@ static long vfio_pin_pages_remote(struct - - while (npage) { - if (!batch->size) { -+ /* -+ * Large mappings may take a while to repeatedly refill -+ * the batch, so conditionally relinquish the CPU when -+ * needed to avoid stalls. -+ */ -+ cond_resched(); -+ - /* Empty batch, so refill it. */ - ret = vaddr_get_pfns(mm, vaddr, npage, dma->prot, - &pfn, batch); -diff -purNx .git BPI-Router-Linux-kernel/drivers/vfio/vfio_main.c BPI-Router-Linux-kernel-6.16.12/drivers/vfio/vfio_main.c ---- BPI-Router-Linux-kernel/drivers/vfio/vfio_main.c 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/vfio/vfio_main.c 2025-10-22 13:53:56.687168312 -0400 -@@ -583,7 +583,8 @@ void vfio_df_close(struct vfio_device_fi - - lockdep_assert_held(&device->dev_set->lock); - -- vfio_assert_device_open(device); -+ if (!vfio_assert_device_open(device)) -+ return; - if (device->open_count == 1) - vfio_df_device_last_close(df); - device->open_count--; -diff -purNx .git BPI-Router-Linux-kernel/drivers/vhost/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/vhost/Kconfig ---- BPI-Router-Linux-kernel/drivers/vhost/Kconfig 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/vhost/Kconfig 2025-10-22 13:53:56.687168312 -0400 -@@ -95,4 +95,22 @@ config VHOST_CROSS_ENDIAN_LEGACY - - If unsure, say "N". - -+config VHOST_ENABLE_FORK_OWNER_CONTROL -+ bool "Enable VHOST_ENABLE_FORK_OWNER_CONTROL" -+ default y -+ help -+ This option enables two IOCTLs: VHOST_SET_FORK_FROM_OWNER and -+ VHOST_GET_FORK_FROM_OWNER. These allow userspace applications -+ to modify the vhost worker mode for vhost devices. -+ -+ Also expose module parameter 'fork_from_owner_default' to allow users -+ to configure the default mode for vhost workers. -+ -+ By default, `VHOST_ENABLE_FORK_OWNER_CONTROL` is set to `y`, -+ users can change the worker thread mode as needed. -+ If this config is disabled (n),the related IOCTLs and parameters will -+ be unavailable. -+ -+ If unsure, say "Y". -+ - endif -diff -purNx .git BPI-Router-Linux-kernel/drivers/vhost/net.c BPI-Router-Linux-kernel-6.16.12/drivers/vhost/net.c ---- BPI-Router-Linux-kernel/drivers/vhost/net.c 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/vhost/net.c 2025-10-22 13:53:56.687168312 -0400 -@@ -96,6 +96,7 @@ struct vhost_net_ubuf_ref { - atomic_t refcount; - wait_queue_head_t wait; - struct vhost_virtqueue *vq; -+ struct rcu_head rcu; - }; - - #define VHOST_NET_BATCH 64 -@@ -247,9 +248,13 @@ vhost_net_ubuf_alloc(struct vhost_virtqu - - static int vhost_net_ubuf_put(struct vhost_net_ubuf_ref *ubufs) - { -- int r = atomic_sub_return(1, &ubufs->refcount); -+ int r; -+ -+ rcu_read_lock(); -+ r = atomic_sub_return(1, &ubufs->refcount); - if (unlikely(!r)) - wake_up(&ubufs->wait); -+ rcu_read_unlock(); - return r; - } - -@@ -262,7 +267,7 @@ static void vhost_net_ubuf_put_and_wait( - static void vhost_net_ubuf_put_wait_and_free(struct vhost_net_ubuf_ref *ubufs) - { - vhost_net_ubuf_put_and_wait(ubufs); -- kfree(ubufs); -+ kfree_rcu(ubufs, rcu); - } - - static void vhost_net_clear_ubuf_info(struct vhost_net *n) -@@ -755,10 +760,10 @@ static void handle_tx_copy(struct vhost_ - int err; - int sent_pkts = 0; - bool sock_can_batch = (sock->sk->sk_sndbuf == INT_MAX); -- bool busyloop_intr; - - do { -- busyloop_intr = false; -+ bool busyloop_intr = false; -+ - if (nvq->done_idx == VHOST_NET_BATCH) - vhost_tx_batch(net, nvq, sock, &msg); - -@@ -769,10 +774,18 @@ static void handle_tx_copy(struct vhost_ - break; - /* Nothing new? Wait for eventfd to tell us they refilled. */ - if (head == vq->num) { -- /* Kicks are disabled at this point, break loop and -- * process any remaining batched packets. Queue will -- * be re-enabled afterwards. -+ /* Flush batched packets to handle pending RX -+ * work (if busyloop_intr is set) and to avoid -+ * unnecessary virtqueue kicks. - */ -+ vhost_tx_batch(net, nvq, sock, &msg); -+ if (unlikely(busyloop_intr)) { -+ vhost_poll_queue(&vq->poll); -+ } else if (unlikely(vhost_enable_notify(&net->dev, -+ vq))) { -+ vhost_disable_notify(&net->dev, vq); -+ continue; -+ } - break; - } - -@@ -822,22 +835,7 @@ done: - ++nvq->done_idx; - } while (likely(!vhost_exceeds_weight(vq, ++sent_pkts, total_len))); - -- /* Kicks are still disabled, dispatch any remaining batched msgs. */ - vhost_tx_batch(net, nvq, sock, &msg); -- -- if (unlikely(busyloop_intr)) -- /* If interrupted while doing busy polling, requeue the -- * handler to be fair handle_rx as well as other tasks -- * waiting on cpu. -- */ -- vhost_poll_queue(&vq->poll); -- else -- /* All of our work has been completed; however, before -- * leaving the TX handler, do one last check for work, -- * and requeue handler if necessary. If there is no work, -- * queue will be reenabled. -- */ -- vhost_net_busy_poll_try_queue(net, vq); - } - - static void handle_tx_zerocopy(struct vhost_net *net, struct socket *sock) -diff -purNx .git BPI-Router-Linux-kernel/drivers/vhost/scsi.c BPI-Router-Linux-kernel-6.16.12/drivers/vhost/scsi.c ---- BPI-Router-Linux-kernel/drivers/vhost/scsi.c 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/vhost/scsi.c 2025-10-22 13:53:56.687168312 -0400 -@@ -71,7 +71,7 @@ static int vhost_scsi_set_inline_sg_cnt( - if (ret) - return ret; - -- if (ret > VHOST_SCSI_PREALLOC_SGLS) { -+ if (cnt > VHOST_SCSI_PREALLOC_SGLS) { - pr_err("Max inline_sg_cnt is %u\n", VHOST_SCSI_PREALLOC_SGLS); - return -EINVAL; - } -@@ -1226,10 +1226,8 @@ vhost_scsi_get_req(struct vhost_virtqueu - /* validated at handler entry */ - vs_tpg = vhost_vq_get_backend(vq); - tpg = READ_ONCE(vs_tpg[*vc->target]); -- if (unlikely(!tpg)) { -- vq_err(vq, "Target 0x%x does not exist\n", *vc->target); -+ if (unlikely(!tpg)) - goto out; -- } - } - - if (tpgp) -diff -purNx .git BPI-Router-Linux-kernel/drivers/vhost/vhost.c BPI-Router-Linux-kernel-6.16.12/drivers/vhost/vhost.c ---- BPI-Router-Linux-kernel/drivers/vhost/vhost.c 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/vhost/vhost.c 2025-10-22 13:53:56.687168312 -0400 -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -41,6 +42,13 @@ static int max_iotlb_entries = 2048; - module_param(max_iotlb_entries, int, 0444); - MODULE_PARM_DESC(max_iotlb_entries, - "Maximum number of iotlb entries. (default: 2048)"); -+static bool fork_from_owner_default = VHOST_FORK_OWNER_TASK; -+ -+#ifdef CONFIG_VHOST_ENABLE_FORK_OWNER_CONTROL -+module_param(fork_from_owner_default, bool, 0444); -+MODULE_PARM_DESC(fork_from_owner_default, -+ "Set task mode as the default(default: Y)"); -+#endif - - enum { - VHOST_MEMORY_F_LOG = 0x1, -@@ -242,7 +250,7 @@ static void vhost_worker_queue(struct vh - * test_and_set_bit() implies a memory barrier. - */ - llist_add(&work->node, &worker->work_list); -- vhost_task_wake(worker->vtsk); -+ worker->ops->wakeup(worker); - } - } - -@@ -388,6 +396,44 @@ static void vhost_vq_reset(struct vhost_ - __vhost_vq_meta_reset(vq); - } - -+static int vhost_run_work_kthread_list(void *data) -+{ -+ struct vhost_worker *worker = data; -+ struct vhost_work *work, *work_next; -+ struct vhost_dev *dev = worker->dev; -+ struct llist_node *node; -+ -+ kthread_use_mm(dev->mm); -+ -+ for (;;) { -+ /* mb paired w/ kthread_stop */ -+ set_current_state(TASK_INTERRUPTIBLE); -+ -+ if (kthread_should_stop()) { -+ __set_current_state(TASK_RUNNING); -+ break; -+ } -+ node = llist_del_all(&worker->work_list); -+ if (!node) -+ schedule(); -+ -+ node = llist_reverse_order(node); -+ /* make sure flag is seen after deletion */ -+ smp_wmb(); -+ llist_for_each_entry_safe(work, work_next, node, node) { -+ clear_bit(VHOST_WORK_QUEUED, &work->flags); -+ __set_current_state(TASK_RUNNING); -+ kcov_remote_start_common(worker->kcov_handle); -+ work->fn(work); -+ kcov_remote_stop(); -+ cond_resched(); -+ } -+ } -+ kthread_unuse_mm(dev->mm); -+ -+ return 0; -+} -+ - static bool vhost_run_work_list(void *data) - { - struct vhost_worker *worker = data; -@@ -552,6 +598,7 @@ void vhost_dev_init(struct vhost_dev *de - dev->byte_weight = byte_weight; - dev->use_worker = use_worker; - dev->msg_handler = msg_handler; -+ dev->fork_owner = fork_from_owner_default; - init_waitqueue_head(&dev->wait); - INIT_LIST_HEAD(&dev->read_list); - INIT_LIST_HEAD(&dev->pending_list); -@@ -581,6 +628,46 @@ long vhost_dev_check_owner(struct vhost_ - } - EXPORT_SYMBOL_GPL(vhost_dev_check_owner); - -+struct vhost_attach_cgroups_struct { -+ struct vhost_work work; -+ struct task_struct *owner; -+ int ret; -+}; -+ -+static void vhost_attach_cgroups_work(struct vhost_work *work) -+{ -+ struct vhost_attach_cgroups_struct *s; -+ -+ s = container_of(work, struct vhost_attach_cgroups_struct, work); -+ s->ret = cgroup_attach_task_all(s->owner, current); -+} -+ -+static int vhost_attach_task_to_cgroups(struct vhost_worker *worker) -+{ -+ struct vhost_attach_cgroups_struct attach; -+ int saved_cnt; -+ -+ attach.owner = current; -+ -+ vhost_work_init(&attach.work, vhost_attach_cgroups_work); -+ vhost_worker_queue(worker, &attach.work); -+ -+ mutex_lock(&worker->mutex); -+ -+ /* -+ * Bypass attachment_cnt check in __vhost_worker_flush: -+ * Temporarily change it to INT_MAX to bypass the check -+ */ -+ saved_cnt = worker->attachment_cnt; -+ worker->attachment_cnt = INT_MAX; -+ __vhost_worker_flush(worker); -+ worker->attachment_cnt = saved_cnt; -+ -+ mutex_unlock(&worker->mutex); -+ -+ return attach.ret; -+} -+ - /* Caller should have device mutex */ - bool vhost_dev_has_owner(struct vhost_dev *dev) - { -@@ -626,7 +713,7 @@ static void vhost_worker_destroy(struct - - WARN_ON(!llist_empty(&worker->work_list)); - xa_erase(&dev->worker_xa, worker->id); -- vhost_task_stop(worker->vtsk); -+ worker->ops->stop(worker); - kfree(worker); - } - -@@ -649,42 +736,115 @@ static void vhost_workers_free(struct vh - xa_destroy(&dev->worker_xa); - } - -+static void vhost_task_wakeup(struct vhost_worker *worker) -+{ -+ return vhost_task_wake(worker->vtsk); -+} -+ -+static void vhost_kthread_wakeup(struct vhost_worker *worker) -+{ -+ wake_up_process(worker->kthread_task); -+} -+ -+static void vhost_task_do_stop(struct vhost_worker *worker) -+{ -+ return vhost_task_stop(worker->vtsk); -+} -+ -+static void vhost_kthread_do_stop(struct vhost_worker *worker) -+{ -+ kthread_stop(worker->kthread_task); -+} -+ -+static int vhost_task_worker_create(struct vhost_worker *worker, -+ struct vhost_dev *dev, const char *name) -+{ -+ struct vhost_task *vtsk; -+ u32 id; -+ int ret; -+ -+ vtsk = vhost_task_create(vhost_run_work_list, vhost_worker_killed, -+ worker, name); -+ if (IS_ERR(vtsk)) -+ return PTR_ERR(vtsk); -+ -+ worker->vtsk = vtsk; -+ vhost_task_start(vtsk); -+ ret = xa_alloc(&dev->worker_xa, &id, worker, xa_limit_32b, GFP_KERNEL); -+ if (ret < 0) { -+ vhost_task_do_stop(worker); -+ return ret; -+ } -+ worker->id = id; -+ return 0; -+} -+ -+static int vhost_kthread_worker_create(struct vhost_worker *worker, -+ struct vhost_dev *dev, const char *name) -+{ -+ struct task_struct *task; -+ u32 id; -+ int ret; -+ -+ task = kthread_create(vhost_run_work_kthread_list, worker, "%s", name); -+ if (IS_ERR(task)) -+ return PTR_ERR(task); -+ -+ worker->kthread_task = task; -+ wake_up_process(task); -+ ret = xa_alloc(&dev->worker_xa, &id, worker, xa_limit_32b, GFP_KERNEL); -+ if (ret < 0) -+ goto stop_worker; -+ -+ ret = vhost_attach_task_to_cgroups(worker); -+ if (ret) -+ goto stop_worker; -+ -+ worker->id = id; -+ return 0; -+ -+stop_worker: -+ vhost_kthread_do_stop(worker); -+ return ret; -+} -+ -+static const struct vhost_worker_ops kthread_ops = { -+ .create = vhost_kthread_worker_create, -+ .stop = vhost_kthread_do_stop, -+ .wakeup = vhost_kthread_wakeup, -+}; -+ -+static const struct vhost_worker_ops vhost_task_ops = { -+ .create = vhost_task_worker_create, -+ .stop = vhost_task_do_stop, -+ .wakeup = vhost_task_wakeup, -+}; -+ - static struct vhost_worker *vhost_worker_create(struct vhost_dev *dev) - { - struct vhost_worker *worker; -- struct vhost_task *vtsk; - char name[TASK_COMM_LEN]; - int ret; -- u32 id; -+ const struct vhost_worker_ops *ops = dev->fork_owner ? &vhost_task_ops : -+ &kthread_ops; - - worker = kzalloc(sizeof(*worker), GFP_KERNEL_ACCOUNT); - if (!worker) - return NULL; - - worker->dev = dev; -+ worker->ops = ops; - snprintf(name, sizeof(name), "vhost-%d", current->pid); - -- vtsk = vhost_task_create(vhost_run_work_list, vhost_worker_killed, -- worker, name); -- if (IS_ERR(vtsk)) -- goto free_worker; -- - mutex_init(&worker->mutex); - init_llist_head(&worker->work_list); - worker->kcov_handle = kcov_common_handle(); -- worker->vtsk = vtsk; -- -- vhost_task_start(vtsk); -- -- ret = xa_alloc(&dev->worker_xa, &id, worker, xa_limit_32b, GFP_KERNEL); -+ ret = ops->create(worker, dev, name); - if (ret < 0) -- goto stop_worker; -- worker->id = id; -+ goto free_worker; - - return worker; - --stop_worker: -- vhost_task_stop(vtsk); - free_worker: - kfree(worker); - return NULL; -@@ -865,6 +1025,14 @@ long vhost_worker_ioctl(struct vhost_dev - switch (ioctl) { - /* dev worker ioctls */ - case VHOST_NEW_WORKER: -+ /* -+ * vhost_tasks will account for worker threads under the parent's -+ * NPROC value but kthreads do not. To avoid userspace overflowing -+ * the system with worker threads fork_owner must be true. -+ */ -+ if (!dev->fork_owner) -+ return -EFAULT; -+ - ret = vhost_new_worker(dev, &state); - if (!ret && copy_to_user(argp, &state, sizeof(state))) - ret = -EFAULT; -@@ -982,6 +1150,7 @@ void vhost_dev_reset_owner(struct vhost_ - - vhost_dev_cleanup(dev); - -+ dev->fork_owner = fork_from_owner_default; - dev->umem = umem; - /* We don't need VQ locks below since vhost_dev_cleanup makes sure - * VQs aren't running. -@@ -2135,6 +2304,45 @@ long vhost_dev_ioctl(struct vhost_dev *d - goto done; - } - -+#ifdef CONFIG_VHOST_ENABLE_FORK_OWNER_CONTROL -+ if (ioctl == VHOST_SET_FORK_FROM_OWNER) { -+ /* Only allow modification before owner is set */ -+ if (vhost_dev_has_owner(d)) { -+ r = -EBUSY; -+ goto done; -+ } -+ u8 fork_owner_val; -+ -+ if (get_user(fork_owner_val, (u8 __user *)argp)) { -+ r = -EFAULT; -+ goto done; -+ } -+ if (fork_owner_val != VHOST_FORK_OWNER_TASK && -+ fork_owner_val != VHOST_FORK_OWNER_KTHREAD) { -+ r = -EINVAL; -+ goto done; -+ } -+ d->fork_owner = !!fork_owner_val; -+ r = 0; -+ goto done; -+ } -+ if (ioctl == VHOST_GET_FORK_FROM_OWNER) { -+ u8 fork_owner_val = d->fork_owner; -+ -+ if (fork_owner_val != VHOST_FORK_OWNER_TASK && -+ fork_owner_val != VHOST_FORK_OWNER_KTHREAD) { -+ r = -EINVAL; -+ goto done; -+ } -+ if (put_user(fork_owner_val, (u8 __user *)argp)) { -+ r = -EFAULT; -+ goto done; -+ } -+ r = 0; -+ goto done; -+ } -+#endif -+ - /* You must be the owner to do anything else */ - r = vhost_dev_check_owner(d); - if (r) -@@ -2775,6 +2983,9 @@ int vhost_add_used_n(struct vhost_virtqu - } - r = __vhost_add_used_n(vq, heads, count); - -+ if (r < 0) -+ return r; -+ - /* Make sure buffer is written before we update index. */ - smp_wmb(); - if (vhost_put_used_idx(vq)) { -diff -purNx .git BPI-Router-Linux-kernel/drivers/vhost/vhost.h BPI-Router-Linux-kernel-6.16.12/drivers/vhost/vhost.h ---- BPI-Router-Linux-kernel/drivers/vhost/vhost.h 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/vhost/vhost.h 2025-10-22 13:53:56.687168312 -0400 -@@ -26,7 +26,18 @@ struct vhost_work { - unsigned long flags; - }; - -+struct vhost_worker; -+struct vhost_dev; -+ -+struct vhost_worker_ops { -+ int (*create)(struct vhost_worker *worker, struct vhost_dev *dev, -+ const char *name); -+ void (*stop)(struct vhost_worker *worker); -+ void (*wakeup)(struct vhost_worker *worker); -+}; -+ - struct vhost_worker { -+ struct task_struct *kthread_task; - struct vhost_task *vtsk; - struct vhost_dev *dev; - /* Used to serialize device wide flushing with worker swapping. */ -@@ -36,6 +47,7 @@ struct vhost_worker { - u32 id; - int attachment_cnt; - bool killed; -+ const struct vhost_worker_ops *ops; - }; - - /* Poll a file (eventfd or socket) */ -@@ -176,6 +188,16 @@ struct vhost_dev { - int byte_weight; - struct xarray worker_xa; - bool use_worker; -+ /* -+ * If fork_owner is true we use vhost_tasks to create -+ * the worker so all settings/limits like cgroups, NPROC, -+ * scheduler, etc are inherited from the owner. If false, -+ * we use kthreads and only attach to the same cgroups -+ * as the owner for compat with older kernels. -+ * here we use true as default value. -+ * The default value is set by fork_from_owner_default -+ */ -+ bool fork_owner; - int (*msg_handler)(struct vhost_dev *dev, u32 asid, - struct vhost_iotlb_msg *msg); - }; -diff -purNx .git BPI-Router-Linux-kernel/drivers/vhost/vsock.c BPI-Router-Linux-kernel-6.16.12/drivers/vhost/vsock.c ---- BPI-Router-Linux-kernel/drivers/vhost/vsock.c 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/vhost/vsock.c 2025-10-22 13:53:56.687168312 -0400 -@@ -344,6 +344,9 @@ vhost_vsock_alloc_skb(struct vhost_virtq - - len = iov_length(vq->iov, out); - -+ if (len > VIRTIO_VSOCK_MAX_PKT_BUF_SIZE + VIRTIO_VSOCK_SKB_HEADROOM) -+ return NULL; -+ - /* len contains both payload and hdr */ - skb = virtio_vsock_alloc_skb(len, GFP_KERNEL); - if (!skb) -@@ -367,8 +370,7 @@ vhost_vsock_alloc_skb(struct vhost_virtq - return skb; - - /* The pkt is too big or the length in the header is invalid */ -- if (payload_len > VIRTIO_VSOCK_MAX_PKT_BUF_SIZE || -- payload_len + sizeof(*hdr) > len) { -+ if (payload_len + sizeof(*hdr) > len) { - kfree_skb(skb); - return NULL; - } -diff -purNx .git BPI-Router-Linux-kernel/drivers/video/console/vgacon.c BPI-Router-Linux-kernel-6.16.12/drivers/video/console/vgacon.c ---- BPI-Router-Linux-kernel/drivers/video/console/vgacon.c 2025-10-22 13:53:23.483327842 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/video/console/vgacon.c 2025-10-22 13:53:56.687168312 -0400 -@@ -1168,7 +1168,7 @@ static bool vgacon_scroll(struct vc_data - c->vc_screenbuf_size - delta); - c->vc_origin = vga_vram_end - c->vc_screenbuf_size; - vga_rolled_over = 0; -- } else if (oldo - delta >= (unsigned long)c->vc_screenbuf) -+ } else - c->vc_origin -= delta; - c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size; - scr_memsetw((u16 *) (c->vc_origin), c->vc_video_erase_char, -diff -purNx .git BPI-Router-Linux-kernel/drivers/video/fbdev/core/fbcon.c BPI-Router-Linux-kernel-6.16.12/drivers/video/fbdev/core/fbcon.c ---- BPI-Router-Linux-kernel/drivers/video/fbdev/core/fbcon.c 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/video/fbdev/core/fbcon.c 2025-10-22 13:53:56.687168312 -0400 -@@ -825,7 +825,8 @@ static void con2fb_init_display(struct v - fg_vc->vc_rows); - } - -- update_screen(vc_cons[fg_console].d); -+ if (fg_console != unit) -+ update_screen(vc_cons[fg_console].d); - } - - /** -@@ -952,13 +953,13 @@ static const char *fbcon_startup(void) - int rows, cols; - - /* -- * If num_registered_fb is zero, this is a call for the dummy part. -+ * If fbcon_num_registered_fb is zero, this is a call for the dummy part. - * The frame buffer devices weren't initialized yet. - */ - if (!fbcon_num_registered_fb || info_idx == -1) - return display_desc; - /* -- * Instead of blindly using registered_fb[0], we use info_idx, set by -+ * Instead of blindly using fbcon_registered_fb[0], we use info_idx, set by - * fbcon_fb_registered(); - */ - info = fbcon_registered_fb[info_idx]; -@@ -1362,6 +1363,7 @@ static void fbcon_set_disp(struct fb_inf - struct vc_data *svc; - struct fbcon_ops *ops = info->fbcon_par; - int rows, cols; -+ unsigned long ret = 0; - - p = &fb_display[unit]; - -@@ -1412,11 +1414,10 @@ static void fbcon_set_disp(struct fb_inf - rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); - cols /= vc->vc_font.width; - rows /= vc->vc_font.height; -- vc_resize(vc, cols, rows); -+ ret = vc_resize(vc, cols, rows); - -- if (con_is_visible(vc)) { -+ if (con_is_visible(vc) && !ret) - update_screen(vc); -- } - } - - static __inline__ void ywrap_up(struct vc_data *vc, int count) -@@ -2490,7 +2491,7 @@ static int fbcon_set_font(struct vc_data - unsigned charcount = font->charcount; - int w = font->width; - int h = font->height; -- int size; -+ int size, alloc_size; - int i, csum; - u8 *new_data, *data = font->data; - int pitch = PITCH(font->width); -@@ -2517,9 +2518,16 @@ static int fbcon_set_font(struct vc_data - if (fbcon_invalid_charcount(info, charcount)) - return -EINVAL; - -- size = CALC_FONTSZ(h, pitch, charcount); -+ /* Check for integer overflow in font size calculation */ -+ if (check_mul_overflow(h, pitch, &size) || -+ check_mul_overflow(size, charcount, &size)) -+ return -EINVAL; -+ -+ /* Check for overflow in allocation size calculation */ -+ if (check_add_overflow(FONT_EXTRA_WORDS * sizeof(int), size, &alloc_size)) -+ return -EINVAL; - -- new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, GFP_USER); -+ new_data = kmalloc(alloc_size, GFP_USER); - - if (!new_data) - return -ENOMEM; -diff -purNx .git BPI-Router-Linux-kernel/drivers/video/fbdev/core/fbmem.c BPI-Router-Linux-kernel-6.16.12/drivers/video/fbdev/core/fbmem.c ---- BPI-Router-Linux-kernel/drivers/video/fbdev/core/fbmem.c 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/video/fbdev/core/fbmem.c 2025-10-22 13:53:56.687168312 -0400 -@@ -449,6 +449,9 @@ static int do_register_framebuffer(struc - if (!registered_fb[i]) - break; - -+ if (i >= FB_MAX) -+ return -ENXIO; -+ - if (!fb_info->modelist.prev || !fb_info->modelist.next) - INIT_LIST_HEAD(&fb_info->modelist); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/video/fbdev/imxfb.c BPI-Router-Linux-kernel-6.16.12/drivers/video/fbdev/imxfb.c ---- BPI-Router-Linux-kernel/drivers/video/fbdev/imxfb.c 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/video/fbdev/imxfb.c 2025-10-22 13:53:56.687168312 -0400 -@@ -996,8 +996,13 @@ static int imxfb_probe(struct platform_d - info->fix.smem_start = fbi->map_dma; - - INIT_LIST_HEAD(&info->modelist); -- for (i = 0; i < fbi->num_modes; i++) -- fb_add_videomode(&fbi->mode[i].mode, &info->modelist); -+ for (i = 0; i < fbi->num_modes; i++) { -+ ret = fb_add_videomode(&fbi->mode[i].mode, &info->modelist); -+ if (ret) { -+ dev_err(&pdev->dev, "Failed to add videomode\n"); -+ goto failed_cmap; -+ } -+ } - - /* - * This makes sure that our colour bitfield -diff -purNx .git BPI-Router-Linux-kernel/drivers/video/fbdev/Kconfig BPI-Router-Linux-kernel-6.16.12/drivers/video/fbdev/Kconfig ---- BPI-Router-Linux-kernel/drivers/video/fbdev/Kconfig 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/video/fbdev/Kconfig 2025-10-22 13:53:56.687168312 -0400 -@@ -660,7 +660,7 @@ config FB_ATMEL - - config FB_NVIDIA - tristate "nVidia Framebuffer Support" -- depends on FB && PCI -+ depends on FB && PCI && HAS_IOPORT - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT -diff -purNx .git BPI-Router-Linux-kernel/drivers/virt/coco/efi_secret/efi_secret.c BPI-Router-Linux-kernel-6.16.12/drivers/virt/coco/efi_secret/efi_secret.c ---- BPI-Router-Linux-kernel/drivers/virt/coco/efi_secret/efi_secret.c 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/virt/coco/efi_secret/efi_secret.c 2025-10-22 13:53:56.687168312 -0400 -@@ -136,15 +136,7 @@ static int efi_secret_unlink(struct inod - if (s->fs_files[i] == dentry) - s->fs_files[i] = NULL; - -- /* -- * securityfs_remove tries to lock the directory's inode, but we reach -- * the unlink callback when it's already locked -- */ -- inode_unlock(dir); -- securityfs_remove(dentry); -- inode_lock(dir); -- -- return 0; -+ return simple_unlink(inode, dentry); - } - - static const struct inode_operations efi_secret_dir_inode_operations = { -diff -purNx .git BPI-Router-Linux-kernel/drivers/virtio/virtio_ring.c BPI-Router-Linux-kernel-6.16.12/drivers/virtio/virtio_ring.c ---- BPI-Router-Linux-kernel/drivers/virtio/virtio_ring.c 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/virtio/virtio_ring.c 2025-10-22 13:53:56.687168312 -0400 -@@ -2797,7 +2797,7 @@ int virtqueue_resize(struct virtqueue *_ - void (*recycle_done)(struct virtqueue *vq)) - { - struct vring_virtqueue *vq = to_vvq(_vq); -- int err; -+ int err, err_reset; - - if (num > vq->vq.num_max) - return -E2BIG; -@@ -2819,7 +2819,11 @@ int virtqueue_resize(struct virtqueue *_ - else - err = virtqueue_resize_split(_vq, num); - -- return virtqueue_enable_after_reset(_vq); -+ err_reset = virtqueue_enable_after_reset(_vq); -+ if (err_reset) -+ return err_reset; -+ -+ return err; - } - EXPORT_SYMBOL_GPL(virtqueue_resize); - -diff -purNx .git BPI-Router-Linux-kernel/drivers/watchdog/dw_wdt.c BPI-Router-Linux-kernel-6.16.12/drivers/watchdog/dw_wdt.c ---- BPI-Router-Linux-kernel/drivers/watchdog/dw_wdt.c 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/watchdog/dw_wdt.c 2025-10-22 13:53:56.687168312 -0400 -@@ -644,6 +644,8 @@ static int dw_wdt_drv_probe(struct platf - } else { - wdd->timeout = DW_WDT_DEFAULT_SECONDS; - watchdog_init_timeout(wdd, 0, dev); -+ /* Limit timeout value to hardware constraints. */ -+ dw_wdt_set_timeout(wdd, wdd->timeout); - } - - platform_set_drvdata(pdev, dw_wdt); -diff -purNx .git BPI-Router-Linux-kernel/drivers/watchdog/iTCO_wdt.c BPI-Router-Linux-kernel-6.16.12/drivers/watchdog/iTCO_wdt.c ---- BPI-Router-Linux-kernel/drivers/watchdog/iTCO_wdt.c 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/watchdog/iTCO_wdt.c 2025-10-22 13:53:56.687168312 -0400 -@@ -577,7 +577,11 @@ static int iTCO_wdt_probe(struct platfor - /* Check that the heartbeat value is within it's range; - if not reset to the default */ - if (iTCO_wdt_set_timeout(&p->wddev, heartbeat)) { -- iTCO_wdt_set_timeout(&p->wddev, WATCHDOG_TIMEOUT); -+ ret = iTCO_wdt_set_timeout(&p->wddev, WATCHDOG_TIMEOUT); -+ if (ret != 0) { -+ dev_err(dev, "Failed to set watchdog timeout (%d)\n", WATCHDOG_TIMEOUT); -+ return ret; -+ } - dev_info(dev, "timeout value out of range, using %d\n", - WATCHDOG_TIMEOUT); - heartbeat = WATCHDOG_TIMEOUT; -diff -purNx .git BPI-Router-Linux-kernel/drivers/watchdog/sbsa_gwdt.c BPI-Router-Linux-kernel-6.16.12/drivers/watchdog/sbsa_gwdt.c ---- BPI-Router-Linux-kernel/drivers/watchdog/sbsa_gwdt.c 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/watchdog/sbsa_gwdt.c 2025-10-22 13:53:56.691168293 -0400 -@@ -75,11 +75,17 @@ - #define SBSA_GWDT_VERSION_MASK 0xF - #define SBSA_GWDT_VERSION_SHIFT 16 - -+#define SBSA_GWDT_IMPL_MASK 0x7FF -+#define SBSA_GWDT_IMPL_SHIFT 0 -+#define SBSA_GWDT_IMPL_MEDIATEK 0x426 -+ - /** - * struct sbsa_gwdt - Internal representation of the SBSA GWDT - * @wdd: kernel watchdog_device structure - * @clk: store the System Counter clock frequency, in Hz. - * @version: store the architecture version -+ * @need_ws0_race_workaround: -+ * indicate whether to adjust wdd->timeout to avoid a race with WS0 - * @refresh_base: Virtual address of the watchdog refresh frame - * @control_base: Virtual address of the watchdog control frame - */ -@@ -87,6 +93,7 @@ struct sbsa_gwdt { - struct watchdog_device wdd; - u32 clk; - int version; -+ bool need_ws0_race_workaround; - void __iomem *refresh_base; - void __iomem *control_base; - }; -@@ -161,6 +168,31 @@ static int sbsa_gwdt_set_timeout(struct - */ - sbsa_gwdt_reg_write(((u64)gwdt->clk / 2) * timeout, gwdt); - -+ /* -+ * Some watchdog hardware has a race condition where it will ignore -+ * sbsa_gwdt_keepalive() if it is called at the exact moment that a -+ * timeout occurs and WS0 is being asserted. Unfortunately, the default -+ * behavior of the watchdog core is very likely to trigger this race -+ * when action=0 because it programs WOR to be half of the desired -+ * timeout, and watchdog_next_keepalive() chooses the exact same time to -+ * send keepalive pings. -+ * -+ * This triggers a race where sbsa_gwdt_keepalive() can be called right -+ * as WS0 is being asserted, and affected hardware will ignore that -+ * write and continue to assert WS0. After another (timeout / 2) -+ * seconds, the same race happens again. If the driver wins then the -+ * explicit refresh will reset WS0 to false but if the hardware wins, -+ * then WS1 is asserted and the system resets. -+ * -+ * Avoid the problem by scheduling keepalive heartbeats one second later -+ * than the WOR timeout. -+ * -+ * This workaround might not be needed in a future revision of the -+ * hardware. -+ */ -+ if (gwdt->need_ws0_race_workaround) -+ wdd->min_hw_heartbeat_ms = timeout * 500 + 1000; -+ - return 0; - } - -@@ -202,12 +234,15 @@ static int sbsa_gwdt_keepalive(struct wa - static void sbsa_gwdt_get_version(struct watchdog_device *wdd) - { - struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd); -- int ver; -+ int iidr, ver, impl; - -- ver = readl(gwdt->control_base + SBSA_GWDT_W_IIDR); -- ver = (ver >> SBSA_GWDT_VERSION_SHIFT) & SBSA_GWDT_VERSION_MASK; -+ iidr = readl(gwdt->control_base + SBSA_GWDT_W_IIDR); -+ ver = (iidr >> SBSA_GWDT_VERSION_SHIFT) & SBSA_GWDT_VERSION_MASK; -+ impl = (iidr >> SBSA_GWDT_IMPL_SHIFT) & SBSA_GWDT_IMPL_MASK; - - gwdt->version = ver; -+ gwdt->need_ws0_race_workaround = -+ !action && (impl == SBSA_GWDT_IMPL_MEDIATEK); - } - - static int sbsa_gwdt_start(struct watchdog_device *wdd) -@@ -299,6 +334,15 @@ static int sbsa_gwdt_probe(struct platfo - else - wdd->max_hw_heartbeat_ms = GENMASK_ULL(47, 0) / gwdt->clk * 1000; - -+ if (gwdt->need_ws0_race_workaround) { -+ /* -+ * A timeout of 3 seconds means that WOR will be set to 1.5 -+ * seconds and the heartbeat will be scheduled every 2.5 -+ * seconds. -+ */ -+ wdd->min_timeout = 3; -+ } -+ - status = readl(cf_base + SBSA_GWDT_WCS); - if (status & SBSA_GWDT_WCS_WS1) { - dev_warn(dev, "System reset by WDT.\n"); -diff -purNx .git BPI-Router-Linux-kernel/drivers/watchdog/ziirave_wdt.c BPI-Router-Linux-kernel-6.16.12/drivers/watchdog/ziirave_wdt.c ---- BPI-Router-Linux-kernel/drivers/watchdog/ziirave_wdt.c 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/watchdog/ziirave_wdt.c 2025-10-22 13:53:56.691168293 -0400 -@@ -302,6 +302,9 @@ static int ziirave_firm_verify(struct wa - const u16 len = be16_to_cpu(rec->len); - const u32 addr = be32_to_cpu(rec->addr); - -+ if (len > sizeof(data)) -+ return -EINVAL; -+ - if (ziirave_firm_addr_readonly(addr)) - continue; - -diff -purNx .git BPI-Router-Linux-kernel/drivers/xen/gntdev.c BPI-Router-Linux-kernel-6.16.12/drivers/xen/gntdev.c ---- BPI-Router-Linux-kernel/drivers/xen/gntdev.c 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/xen/gntdev.c 2025-10-22 13:53:56.691168293 -0400 -@@ -56,6 +56,18 @@ MODULE_AUTHOR("Derek G. Murray "); - MODULE_DESCRIPTION("User-space granted page access driver"); - -+#define GNTDEV_COPY_BATCH 16 -+ -+struct gntdev_copy_batch { -+ struct gnttab_copy ops[GNTDEV_COPY_BATCH]; -+ struct page *pages[GNTDEV_COPY_BATCH]; -+ s16 __user *status[GNTDEV_COPY_BATCH]; -+ unsigned int nr_ops; -+ unsigned int nr_pages; -+ bool writeable; -+ struct gntdev_copy_batch *next; -+}; -+ - static unsigned int limit = 64*1024; - module_param(limit, uint, 0644); - MODULE_PARM_DESC(limit, -@@ -584,6 +596,8 @@ static int gntdev_open(struct inode *ino - INIT_LIST_HEAD(&priv->maps); - mutex_init(&priv->lock); - -+ mutex_init(&priv->batch_lock); -+ - #ifdef CONFIG_XEN_GNTDEV_DMABUF - priv->dmabuf_priv = gntdev_dmabuf_init(flip); - if (IS_ERR(priv->dmabuf_priv)) { -@@ -608,6 +622,7 @@ static int gntdev_release(struct inode * - { - struct gntdev_priv *priv = flip->private_data; - struct gntdev_grant_map *map; -+ struct gntdev_copy_batch *batch; - - pr_debug("priv %p\n", priv); - -@@ -620,6 +635,14 @@ static int gntdev_release(struct inode * - } - mutex_unlock(&priv->lock); - -+ mutex_lock(&priv->batch_lock); -+ while (priv->batch) { -+ batch = priv->batch; -+ priv->batch = batch->next; -+ kfree(batch); -+ } -+ mutex_unlock(&priv->batch_lock); -+ - #ifdef CONFIG_XEN_GNTDEV_DMABUF - gntdev_dmabuf_fini(priv->dmabuf_priv); - #endif -@@ -785,17 +808,6 @@ static long gntdev_ioctl_notify(struct g - return rc; - } - --#define GNTDEV_COPY_BATCH 16 -- --struct gntdev_copy_batch { -- struct gnttab_copy ops[GNTDEV_COPY_BATCH]; -- struct page *pages[GNTDEV_COPY_BATCH]; -- s16 __user *status[GNTDEV_COPY_BATCH]; -- unsigned int nr_ops; -- unsigned int nr_pages; -- bool writeable; --}; -- - static int gntdev_get_page(struct gntdev_copy_batch *batch, void __user *virt, - unsigned long *gfn) - { -@@ -953,36 +965,53 @@ static int gntdev_grant_copy_seg(struct - static long gntdev_ioctl_grant_copy(struct gntdev_priv *priv, void __user *u) - { - struct ioctl_gntdev_grant_copy copy; -- struct gntdev_copy_batch batch; -+ struct gntdev_copy_batch *batch; - unsigned int i; - int ret = 0; - - if (copy_from_user(©, u, sizeof(copy))) - return -EFAULT; - -- batch.nr_ops = 0; -- batch.nr_pages = 0; -+ mutex_lock(&priv->batch_lock); -+ if (!priv->batch) { -+ batch = kmalloc(sizeof(*batch), GFP_KERNEL); -+ } else { -+ batch = priv->batch; -+ priv->batch = batch->next; -+ } -+ mutex_unlock(&priv->batch_lock); -+ if (!batch) -+ return -ENOMEM; -+ -+ batch->nr_ops = 0; -+ batch->nr_pages = 0; - - for (i = 0; i < copy.count; i++) { - struct gntdev_grant_copy_segment seg; - - if (copy_from_user(&seg, ©.segments[i], sizeof(seg))) { - ret = -EFAULT; -+ gntdev_put_pages(batch); - goto out; - } - -- ret = gntdev_grant_copy_seg(&batch, &seg, ©.segments[i].status); -- if (ret < 0) -+ ret = gntdev_grant_copy_seg(batch, &seg, ©.segments[i].status); -+ if (ret < 0) { -+ gntdev_put_pages(batch); - goto out; -+ } - - cond_resched(); - } -- if (batch.nr_ops) -- ret = gntdev_copy(&batch); -- return ret; -+ if (batch->nr_ops) -+ ret = gntdev_copy(batch); -+ -+ out: -+ mutex_lock(&priv->batch_lock); -+ batch->next = priv->batch; -+ priv->batch = batch; -+ mutex_unlock(&priv->batch_lock); - -- out: -- gntdev_put_pages(&batch); - return ret; - } - -diff -purNx .git BPI-Router-Linux-kernel/drivers/xen/gntdev-common.h BPI-Router-Linux-kernel-6.16.12/drivers/xen/gntdev-common.h ---- BPI-Router-Linux-kernel/drivers/xen/gntdev-common.h 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/xen/gntdev-common.h 2025-10-22 13:53:56.691168293 -0400 -@@ -26,6 +26,10 @@ struct gntdev_priv { - /* lock protects maps and freeable_maps. */ - struct mutex lock; - -+ /* Free instances of struct gntdev_copy_batch. */ -+ struct gntdev_copy_batch *batch; -+ struct mutex batch_lock; -+ - #ifdef CONFIG_XEN_GRANT_DMA_ALLOC - /* Device for which DMA memory is allocated. */ - struct device *dma_dev; -diff -purNx .git BPI-Router-Linux-kernel/drivers/xen/gntdev-dmabuf.c BPI-Router-Linux-kernel-6.16.12/drivers/xen/gntdev-dmabuf.c ---- BPI-Router-Linux-kernel/drivers/xen/gntdev-dmabuf.c 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/drivers/xen/gntdev-dmabuf.c 2025-10-22 13:53:56.691168293 -0400 -@@ -357,8 +357,11 @@ struct gntdev_dmabuf_export_args { - static int dmabuf_exp_from_pages(struct gntdev_dmabuf_export_args *args) - { - DEFINE_DMA_BUF_EXPORT_INFO(exp_info); -- struct gntdev_dmabuf *gntdev_dmabuf; -- int ret; -+ struct gntdev_dmabuf *gntdev_dmabuf __free(kfree) = NULL; -+ CLASS(get_unused_fd, ret)(O_CLOEXEC); -+ -+ if (ret < 0) -+ return ret; - - gntdev_dmabuf = kzalloc(sizeof(*gntdev_dmabuf), GFP_KERNEL); - if (!gntdev_dmabuf) -@@ -383,32 +386,21 @@ static int dmabuf_exp_from_pages(struct - exp_info.priv = gntdev_dmabuf; - - gntdev_dmabuf->dmabuf = dma_buf_export(&exp_info); -- if (IS_ERR(gntdev_dmabuf->dmabuf)) { -- ret = PTR_ERR(gntdev_dmabuf->dmabuf); -- gntdev_dmabuf->dmabuf = NULL; -- goto fail; -- } -- -- ret = dma_buf_fd(gntdev_dmabuf->dmabuf, O_CLOEXEC); -- if (ret < 0) -- goto fail; -+ if (IS_ERR(gntdev_dmabuf->dmabuf)) -+ return PTR_ERR(gntdev_dmabuf->dmabuf); - - gntdev_dmabuf->fd = ret; - args->fd = ret; - - pr_debug("Exporting DMA buffer with fd %d\n", ret); - -+ get_file(gntdev_dmabuf->priv->filp); - mutex_lock(&args->dmabuf_priv->lock); - list_add(&gntdev_dmabuf->next, &args->dmabuf_priv->exp_list); - mutex_unlock(&args->dmabuf_priv->lock); -- get_file(gntdev_dmabuf->priv->filp); -- return 0; - --fail: -- if (gntdev_dmabuf->dmabuf) -- dma_buf_put(gntdev_dmabuf->dmabuf); -- kfree(gntdev_dmabuf); -- return ret; -+ fd_install(take_fd(ret), no_free_ptr(gntdev_dmabuf)->dmabuf->file); -+ return 0; - } - - static struct gntdev_grant_map * -diff -purNx .git BPI-Router-Linux-kernel/fs/afs/addr_prefs.c BPI-Router-Linux-kernel-6.16.12/fs/afs/addr_prefs.c ---- BPI-Router-Linux-kernel/fs/afs/addr_prefs.c 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/afs/addr_prefs.c 2025-10-22 13:53:56.691168293 -0400 -@@ -48,7 +48,7 @@ static int afs_split_string(char **pbuf, - strv[count++] = p; - - /* Skip over word */ -- while (!isspace(*p)) -+ while (!isspace(*p) && *p) - p++; - if (!*p) - break; -diff -purNx .git BPI-Router-Linux-kernel/fs/afs/cell.c BPI-Router-Linux-kernel-6.16.12/fs/afs/cell.c ---- BPI-Router-Linux-kernel/fs/afs/cell.c 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/afs/cell.c 2025-10-22 13:53:56.691168293 -0400 -@@ -177,6 +177,7 @@ static struct afs_cell *afs_alloc_cell(s - VL_SERVICE, AFS_VL_PORT); - if (IS_ERR(vllist)) { - ret = PTR_ERR(vllist); -+ vllist = NULL; - goto parse_failed; - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/afs/server.c BPI-Router-Linux-kernel-6.16.12/fs/afs/server.c ---- BPI-Router-Linux-kernel/fs/afs/server.c 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/afs/server.c 2025-10-22 13:53:56.691168293 -0400 -@@ -331,13 +331,14 @@ struct afs_server *afs_use_server(struct - void afs_put_server(struct afs_net *net, struct afs_server *server, - enum afs_server_trace reason) - { -- unsigned int a, debug_id = server->debug_id; -+ unsigned int a, debug_id; - bool zero; - int r; - - if (!server) - return; - -+ debug_id = server->debug_id; - a = atomic_read(&server->active); - zero = __refcount_dec_and_test(&server->ref, &r); - trace_afs_server(debug_id, r - 1, a, reason); -diff -purNx .git BPI-Router-Linux-kernel/fs/anon_inodes.c BPI-Router-Linux-kernel-6.16.12/fs/anon_inodes.c ---- BPI-Router-Linux-kernel/fs/anon_inodes.c 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/anon_inodes.c 2025-10-22 13:53:56.691168293 -0400 -@@ -98,14 +98,25 @@ static struct file_system_type anon_inod - .kill_sb = kill_anon_super, - }; - --static struct inode *anon_inode_make_secure_inode( -- const char *name, -- const struct inode *context_inode) -+/** -+ * anon_inode_make_secure_inode - allocate an anonymous inode with security context -+ * @sb: [in] Superblock to allocate from -+ * @name: [in] Name of the class of the newfile (e.g., "secretmem") -+ * @context_inode: -+ * [in] Optional parent inode for security inheritance -+ * -+ * The function ensures proper security initialization through the LSM hook -+ * security_inode_init_security_anon(). -+ * -+ * Return: Pointer to new inode on success, ERR_PTR on failure. -+ */ -+struct inode *anon_inode_make_secure_inode(struct super_block *sb, const char *name, -+ const struct inode *context_inode) - { - struct inode *inode; - int error; - -- inode = alloc_anon_inode(anon_inode_mnt->mnt_sb); -+ inode = alloc_anon_inode(sb); - if (IS_ERR(inode)) - return inode; - inode->i_flags &= ~S_PRIVATE; -@@ -118,6 +129,7 @@ static struct inode *anon_inode_make_sec - } - return inode; - } -+EXPORT_SYMBOL_GPL_FOR_MODULES(anon_inode_make_secure_inode, "kvm"); - - static struct file *__anon_inode_getfile(const char *name, - const struct file_operations *fops, -@@ -132,7 +144,8 @@ static struct file *__anon_inode_getfile - return ERR_PTR(-ENOENT); - - if (make_inode) { -- inode = anon_inode_make_secure_inode(name, context_inode); -+ inode = anon_inode_make_secure_inode(anon_inode_mnt->mnt_sb, -+ name, context_inode); - if (IS_ERR(inode)) { - file = ERR_CAST(inode); - goto err; -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/alloc_background.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/alloc_background.c ---- BPI-Router-Linux-kernel/fs/bcachefs/alloc_background.c 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/alloc_background.c 2025-10-22 13:53:56.691168293 -0400 -@@ -1406,6 +1406,9 @@ int bch2_check_discard_freespace_key(str - : BCH_DATA_free; - struct printbuf buf = PRINTBUF; - -+ unsigned fsck_flags = (async_repair ? FSCK_ERR_NO_LOG : 0)| -+ FSCK_CAN_FIX|FSCK_CAN_IGNORE; -+ - struct bpos bucket = iter->pos; - bucket.offset &= ~(~0ULL << 56); - u64 genbits = iter->pos.offset & (~0ULL << 56); -@@ -1419,9 +1422,10 @@ int bch2_check_discard_freespace_key(str - return ret; - - if (!bch2_dev_bucket_exists(c, bucket)) { -- if (fsck_err(trans, need_discard_freespace_key_to_invalid_dev_bucket, -- "entry in %s btree for nonexistant dev:bucket %llu:%llu", -- bch2_btree_id_str(iter->btree_id), bucket.inode, bucket.offset)) -+ if (__fsck_err(trans, fsck_flags, -+ need_discard_freespace_key_to_invalid_dev_bucket, -+ "entry in %s btree for nonexistant dev:bucket %llu:%llu", -+ bch2_btree_id_str(iter->btree_id), bucket.inode, bucket.offset)) - goto delete; - ret = 1; - goto out; -@@ -1433,7 +1437,8 @@ int bch2_check_discard_freespace_key(str - if (a->data_type != state || - (state == BCH_DATA_free && - genbits != alloc_freespace_genbits(*a))) { -- if (fsck_err(trans, need_discard_freespace_key_bad, -+ if (__fsck_err(trans, fsck_flags, -+ need_discard_freespace_key_bad, - "%s\nincorrectly set at %s:%llu:%llu:0 (free %u, genbits %llu should be %llu)", - (bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf), - bch2_btree_id_str(iter->btree_id), -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/alloc_foreground.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/alloc_foreground.c ---- BPI-Router-Linux-kernel/fs/bcachefs/alloc_foreground.c 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/alloc_foreground.c 2025-10-22 13:53:56.691168293 -0400 -@@ -511,7 +511,8 @@ again: - bch2_dev_usage_read_fast(ca, &req->usage); - avail = dev_buckets_free(ca, req->usage, req->watermark); - -- if (req->usage.buckets[BCH_DATA_need_discard] > avail) -+ if (req->usage.buckets[BCH_DATA_need_discard] > -+ min(avail, ca->mi.nbuckets >> 7)) - bch2_dev_do_discards(ca); - - if (req->usage.buckets[BCH_DATA_need_gc_gens] > avail) -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/backpointers.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/backpointers.c ---- BPI-Router-Linux-kernel/fs/bcachefs/backpointers.c 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/backpointers.c 2025-10-22 13:53:56.691168293 -0400 -@@ -353,7 +353,7 @@ static struct bkey_s_c __bch2_backpointe - return ret ? bkey_s_c_err(ret) : bkey_s_c_null; - } else { - struct btree *b = __bch2_backpointer_get_node(trans, bp, iter, last_flushed, commit); -- if (b == ERR_PTR(bch_err_throw(c, backpointer_to_overwritten_btree_node))) -+ if (b == ERR_PTR(-BCH_ERR_backpointer_to_overwritten_btree_node)) - return bkey_s_c_null; - if (IS_ERR_OR_NULL(b)) - return ((struct bkey_s_c) { .k = ERR_CAST(b) }); -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/bcachefs.h BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/bcachefs.h ---- BPI-Router-Linux-kernel/fs/bcachefs/bcachefs.h 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/bcachefs.h 2025-10-22 13:53:56.691168293 -0400 -@@ -296,7 +296,6 @@ do { \ - #define bch2_fmt(_c, fmt) bch2_log_msg(_c, fmt "\n") - - void bch2_print_str(struct bch_fs *, const char *, const char *); --void bch2_print_str_nonblocking(struct bch_fs *, const char *, const char *); - - __printf(2, 3) - void bch2_print_opts(struct bch_opts *, const char *, ...); -@@ -768,7 +767,8 @@ struct btree_trans_buf { - x(sysfs) \ - x(btree_write_buffer) \ - x(btree_node_scrub) \ -- x(async_recovery_passes) -+ x(async_recovery_passes) \ -+ x(ioctl_data) - - enum bch_write_ref { - #define x(n) BCH_WRITE_REF_##n, -@@ -863,9 +863,7 @@ struct bch_fs { - DARRAY(enum bcachefs_metadata_version) - incompat_versions_requested; - --#ifdef CONFIG_UNICODE - struct unicode_map *cf_encoding; --#endif - - struct bch_sb_handle disk_sb; - -@@ -1285,4 +1283,13 @@ static inline bool bch2_discard_opt_enab - : ca->mi.discard; - } - -+static inline bool bch2_fs_casefold_enabled(struct bch_fs *c) -+{ -+#ifdef CONFIG_UNICODE -+ return !c->opts.casefold_disabled; -+#else -+ return false; -+#endif -+} -+ - #endif /* _BCACHEFS_H */ -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/btree_cache.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_cache.c ---- BPI-Router-Linux-kernel/fs/bcachefs/btree_cache.c 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_cache.c 2025-10-22 13:53:56.691168293 -0400 -@@ -85,7 +85,7 @@ void bch2_btree_node_to_freelist(struct - six_unlock_intent(&b->c.lock); - } - --static void __btree_node_data_free(struct btree_cache *bc, struct btree *b) -+void __btree_node_data_free(struct btree *b) - { - BUG_ON(!list_empty(&b->list)); - BUG_ON(btree_node_hashed(b)); -@@ -112,16 +112,17 @@ static void __btree_node_data_free(struc - munmap(b->aux_data, btree_aux_data_bytes(b)); - #endif - b->aux_data = NULL; -- -- btree_node_to_freedlist(bc, b); - } - - static void btree_node_data_free(struct btree_cache *bc, struct btree *b) - { - BUG_ON(list_empty(&b->list)); - list_del_init(&b->list); -+ -+ __btree_node_data_free(b); -+ - --bc->nr_freeable; -- __btree_node_data_free(bc, b); -+ btree_node_to_freedlist(bc, b); - } - - static int bch2_btree_cache_cmp_fn(struct rhashtable_compare_arg *arg, -@@ -185,10 +186,7 @@ static struct btree *__btree_node_mem_al - - struct btree *__bch2_btree_node_mem_alloc(struct bch_fs *c) - { -- struct btree_cache *bc = &c->btree_cache; -- struct btree *b; -- -- b = __btree_node_mem_alloc(c, GFP_KERNEL); -+ struct btree *b = __btree_node_mem_alloc(c, GFP_KERNEL); - if (!b) - return NULL; - -@@ -198,8 +196,6 @@ struct btree *__bch2_btree_node_mem_allo - } - - bch2_btree_lock_init(&b->c, 0, GFP_KERNEL); -- -- __bch2_btree_node_to_freelist(bc, b); - return b; - } - -@@ -524,7 +520,8 @@ restart: - --touched;; - } else if (!btree_node_reclaim(c, b)) { - __bch2_btree_node_hash_remove(bc, b); -- __btree_node_data_free(bc, b); -+ __btree_node_data_free(b); -+ btree_node_to_freedlist(bc, b); - - freed++; - bc->nr_freed++; -@@ -652,9 +649,12 @@ int bch2_fs_btree_cache_init(struct bch_ - - bch2_recalc_btree_reserve(c); - -- for (i = 0; i < bc->nr_reserve; i++) -- if (!__bch2_btree_node_mem_alloc(c)) -+ for (i = 0; i < bc->nr_reserve; i++) { -+ struct btree *b = __bch2_btree_node_mem_alloc(c); -+ if (!b) - goto err; -+ __bch2_btree_node_to_freelist(bc, b); -+ } - - list_splice_init(&bc->live[0].list, &bc->freeable); - -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/btree_cache.h BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_cache.h ---- BPI-Router-Linux-kernel/fs/bcachefs/btree_cache.h 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_cache.h 2025-10-22 13:53:56.691168293 -0400 -@@ -30,6 +30,7 @@ void bch2_btree_node_update_key_early(st - void bch2_btree_cache_cannibalize_unlock(struct btree_trans *); - int bch2_btree_cache_cannibalize_lock(struct btree_trans *, struct closure *); - -+void __btree_node_data_free(struct btree *); - struct btree *__bch2_btree_node_mem_alloc(struct bch_fs *); - struct btree *bch2_btree_node_mem_alloc(struct btree_trans *, bool); - -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/btree_gc.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_gc.c ---- BPI-Router-Linux-kernel/fs/bcachefs/btree_gc.c 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_gc.c 2025-10-22 13:53:56.691168293 -0400 -@@ -397,7 +397,11 @@ again: - continue; - } - -- ret = btree_check_node_boundaries(trans, b, prev, cur, pulled_from_scan); -+ ret = lockrestart_do(trans, -+ btree_check_node_boundaries(trans, b, prev, cur, pulled_from_scan)); -+ if (ret < 0) -+ goto err; -+ - if (ret == DID_FILL_FROM_SCAN) { - new_pass = true; - ret = 0; -@@ -438,7 +442,8 @@ again: - - if (!ret && !IS_ERR_OR_NULL(prev)) { - BUG_ON(cur); -- ret = btree_repair_node_end(trans, b, prev, pulled_from_scan); -+ ret = lockrestart_do(trans, -+ btree_repair_node_end(trans, b, prev, pulled_from_scan)); - if (ret == DID_FILL_FROM_SCAN) { - new_pass = true; - ret = 0; -@@ -498,8 +503,14 @@ again: - prt_newline(&buf); - bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&b->key)); - -+ /* -+ * XXX: we're not passing the trans object here because we're not set up -+ * to handle a transaction restart - this code needs to be rewritten -+ * when we start doing online topology repair -+ */ -+ bch2_trans_unlock_long(trans); - if (mustfix_fsck_err_on(!have_child, -- trans, btree_node_topology_interior_node_empty, -+ c, btree_node_topology_interior_node_empty, - "empty interior btree node at %s", buf.buf)) - ret = DROP_THIS_NODE; - err: -@@ -519,49 +530,72 @@ fsck_err: - bch2_bkey_buf_exit(&prev_k, c); - bch2_bkey_buf_exit(&cur_k, c); - printbuf_exit(&buf); -+ bch_err_fn(c, ret); - return ret; - } - --int bch2_check_topology(struct bch_fs *c) -+static int bch2_check_root(struct btree_trans *trans, enum btree_id btree, -+ bool *reconstructed_root) - { -- struct btree_trans *trans = bch2_trans_get(c); -- struct bpos pulled_from_scan = POS_MIN; -+ struct bch_fs *c = trans->c; -+ struct btree_root *r = bch2_btree_id_root(c, btree); - struct printbuf buf = PRINTBUF; - int ret = 0; - -- bch2_trans_srcu_unlock(trans); -+ bch2_btree_id_to_text(&buf, btree); - -- for (unsigned i = 0; i < btree_id_nr_alive(c) && !ret; i++) { -- struct btree_root *r = bch2_btree_id_root(c, i); -- bool reconstructed_root = false; -+ if (r->error) { -+ bch_info(c, "btree root %s unreadable, must recover from scan", buf.buf); - -- printbuf_reset(&buf); -- bch2_btree_id_to_text(&buf, i); -+ ret = bch2_btree_has_scanned_nodes(c, btree); -+ if (ret < 0) -+ goto err; - -- if (r->error) { --reconstruct_root: -- bch_info(c, "btree root %s unreadable, must recover from scan", buf.buf); -+ if (!ret) { -+ __fsck_err(trans, -+ FSCK_CAN_FIX|(!btree_id_important(btree) ? FSCK_AUTOFIX : 0), -+ btree_root_unreadable_and_scan_found_nothing, -+ "no nodes found for btree %s, continue?", buf.buf); - - r->alive = false; - r->error = 0; -+ bch2_btree_root_alloc_fake_trans(trans, btree, 0); -+ } else { -+ r->alive = false; -+ r->error = 0; -+ bch2_btree_root_alloc_fake_trans(trans, btree, 1); - -- if (!bch2_btree_has_scanned_nodes(c, i)) { -- __fsck_err(trans, -- FSCK_CAN_FIX|(!btree_id_important(i) ? FSCK_AUTOFIX : 0), -- btree_root_unreadable_and_scan_found_nothing, -- "no nodes found for btree %s, continue?", buf.buf); -- bch2_btree_root_alloc_fake_trans(trans, i, 0); -- } else { -- bch2_btree_root_alloc_fake_trans(trans, i, 1); -- bch2_shoot_down_journal_keys(c, i, 1, BTREE_MAX_DEPTH, POS_MIN, SPOS_MAX); -- ret = bch2_get_scanned_nodes(c, i, 0, POS_MIN, SPOS_MAX); -- if (ret) -- break; -- } -- -- reconstructed_root = true; -+ bch2_shoot_down_journal_keys(c, btree, 1, BTREE_MAX_DEPTH, POS_MIN, SPOS_MAX); -+ ret = bch2_get_scanned_nodes(c, btree, 0, POS_MIN, SPOS_MAX); -+ if (ret) -+ goto err; - } - -+ *reconstructed_root = true; -+ } -+err: -+fsck_err: -+ printbuf_exit(&buf); -+ bch_err_fn(c, ret); -+ return ret; -+} -+ -+int bch2_check_topology(struct bch_fs *c) -+{ -+ struct btree_trans *trans = bch2_trans_get(c); -+ struct bpos pulled_from_scan = POS_MIN; -+ int ret = 0; -+ -+ bch2_trans_srcu_unlock(trans); -+ -+ for (unsigned i = 0; i < btree_id_nr_alive(c) && !ret; i++) { -+ bool reconstructed_root = false; -+recover: -+ ret = lockrestart_do(trans, bch2_check_root(trans, i, &reconstructed_root)); -+ if (ret) -+ break; -+ -+ struct btree_root *r = bch2_btree_id_root(c, i); - struct btree *b = r->b; - - btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_read); -@@ -575,17 +609,21 @@ reconstruct_root: - - r->b = NULL; - -- if (!reconstructed_root) -- goto reconstruct_root; -+ if (!reconstructed_root) { -+ r->error = -EIO; -+ goto recover; -+ } - -+ struct printbuf buf = PRINTBUF; -+ bch2_btree_id_to_text(&buf, i); - bch_err(c, "empty btree root %s", buf.buf); -+ printbuf_exit(&buf); - bch2_btree_root_alloc_fake_trans(trans, i, 0); - r->alive = false; - ret = 0; - } - } --fsck_err: -- printbuf_exit(&buf); -+ - bch2_trans_put(trans); - return ret; - } -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/btree_io.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_io.c ---- BPI-Router-Linux-kernel/fs/bcachefs/btree_io.c 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_io.c 2025-10-22 13:53:56.691168293 -0400 -@@ -557,7 +557,9 @@ static int __btree_err(int ret, - const char *fmt, ...) - { - if (c->recovery.curr_pass == BCH_RECOVERY_PASS_scan_for_btree_nodes) -- return bch_err_throw(c, fsck_fix); -+ return ret == -BCH_ERR_btree_node_read_err_fixable -+ ? bch_err_throw(c, fsck_fix) -+ : ret; - - bool have_retry = false; - int ret2; -@@ -566,9 +568,9 @@ static int __btree_err(int ret, - bch2_mark_btree_validate_failure(failed, ca->dev_idx); - - struct extent_ptr_decoded pick; -- have_retry = !bch2_bkey_pick_read_device(c, -+ have_retry = bch2_bkey_pick_read_device(c, - bkey_i_to_s_c(&b->key), -- failed, &pick, -1); -+ failed, &pick, -1) == 1; - } - - if (!have_retry && ret == -BCH_ERR_btree_node_read_err_want_retry) -@@ -613,7 +615,6 @@ static int __btree_err(int ret, - goto out; - case -BCH_ERR_btree_node_read_err_bad_node: - prt_str(&out, ", "); -- ret = __bch2_topology_error(c, &out); - break; - } - -@@ -642,7 +643,6 @@ static int __btree_err(int ret, - goto out; - case -BCH_ERR_btree_node_read_err_bad_node: - prt_str(&out, ", "); -- ret = __bch2_topology_error(c, &out); - break; - } - print: -@@ -723,12 +723,11 @@ void bch2_btree_node_drop_keys_outside_n - - static int validate_bset(struct bch_fs *c, struct bch_dev *ca, - struct btree *b, struct bset *i, -- unsigned offset, unsigned sectors, int write, -+ unsigned offset, int write, - struct bch_io_failures *failed, - struct printbuf *err_msg) - { - unsigned version = le16_to_cpu(i->version); -- unsigned ptr_written = btree_ptr_sectors_written(bkey_i_to_s_c(&b->key)); - struct printbuf buf1 = PRINTBUF; - struct printbuf buf2 = PRINTBUF; - int ret = 0; -@@ -741,16 +740,22 @@ static int validate_bset(struct bch_fs * - BCH_VERSION_MAJOR(version), - BCH_VERSION_MINOR(version)); - -- if (btree_err_on(version < c->sb.version_min, -+ if (c->recovery.curr_pass != BCH_RECOVERY_PASS_scan_for_btree_nodes && -+ btree_err_on(version < c->sb.version_min, - -BCH_ERR_btree_node_read_err_fixable, - c, NULL, b, i, NULL, - btree_node_bset_older_than_sb_min, - "bset version %u older than superblock version_min %u", - version, c->sb.version_min)) { -- mutex_lock(&c->sb_lock); -- c->disk_sb.sb->version_min = cpu_to_le16(version); -- bch2_write_super(c); -- mutex_unlock(&c->sb_lock); -+ if (bch2_version_compatible(version)) { -+ mutex_lock(&c->sb_lock); -+ c->disk_sb.sb->version_min = cpu_to_le16(version); -+ bch2_write_super(c); -+ mutex_unlock(&c->sb_lock); -+ } else { -+ /* We have no idea what's going on: */ -+ i->version = cpu_to_le16(c->sb.version); -+ } - } - - if (btree_err_on(BCH_VERSION_MAJOR(version) > -@@ -772,15 +777,6 @@ static int validate_bset(struct bch_fs * - btree_node_unsupported_version, - "BSET_SEPARATE_WHITEOUTS no longer supported"); - -- if (!write && -- btree_err_on(offset + sectors > (ptr_written ?: btree_sectors(c)), -- -BCH_ERR_btree_node_read_err_fixable, -- c, ca, b, i, NULL, -- bset_past_end_of_btree_node, -- "bset past end of btree node (offset %u len %u but written %zu)", -- offset, sectors, ptr_written ?: btree_sectors(c))) -- i->u64s = 0; -- - btree_err_on(offset && !i->u64s, - -BCH_ERR_btree_node_read_err_fixable, - c, ca, b, i, NULL, -@@ -1045,6 +1041,7 @@ got_good_key: - le16_add_cpu(&i->u64s, -next_good_key); - memmove_u64s_down(k, (u64 *) k + next_good_key, (u64 *) vstruct_end(i) - (u64 *) k); - set_btree_node_need_rewrite(b); -+ set_btree_node_need_rewrite_error(b); - } - fsck_err: - printbuf_exit(&buf); -@@ -1144,6 +1141,14 @@ int bch2_btree_node_read_done(struct bch - "unknown checksum type %llu", BSET_CSUM_TYPE(i)); - - if (first) { -+ sectors = vstruct_sectors(b->data, c->block_bits); -+ if (btree_err_on(b->written + sectors > (ptr_written ?: btree_sectors(c)), -+ -BCH_ERR_btree_node_read_err_fixable, -+ c, ca, b, i, NULL, -+ bset_past_end_of_btree_node, -+ "bset past end of btree node (offset %u len %u but written %zu)", -+ b->written, sectors, ptr_written ?: btree_sectors(c))) -+ i->u64s = 0; - if (good_csum_type) { - struct bch_csum csum = csum_vstruct(c, BSET_CSUM_TYPE(i), nonce, b->data); - bool csum_bad = bch2_crc_cmp(b->data->csum, csum); -@@ -1171,9 +1176,15 @@ int bch2_btree_node_read_done(struct bch - c, NULL, b, NULL, NULL, - btree_node_unsupported_version, - "btree node does not have NEW_EXTENT_OVERWRITE set"); -- -- sectors = vstruct_sectors(b->data, c->block_bits); - } else { -+ sectors = vstruct_sectors(bne, c->block_bits); -+ if (btree_err_on(b->written + sectors > (ptr_written ?: btree_sectors(c)), -+ -BCH_ERR_btree_node_read_err_fixable, -+ c, ca, b, i, NULL, -+ bset_past_end_of_btree_node, -+ "bset past end of btree node (offset %u len %u but written %zu)", -+ b->written, sectors, ptr_written ?: btree_sectors(c))) -+ i->u64s = 0; - if (good_csum_type) { - struct bch_csum csum = csum_vstruct(c, BSET_CSUM_TYPE(i), nonce, bne); - bool csum_bad = bch2_crc_cmp(bne->csum, csum); -@@ -1194,14 +1205,12 @@ int bch2_btree_node_read_done(struct bch - "decrypting btree node: %s", bch2_err_str(ret))) - goto fsck_err; - } -- -- sectors = vstruct_sectors(bne, c->block_bits); - } - - b->version_ondisk = min(b->version_ondisk, - le16_to_cpu(i->version)); - -- ret = validate_bset(c, ca, b, i, b->written, sectors, READ, failed, err_msg); -+ ret = validate_bset(c, ca, b, i, b->written, READ, failed, err_msg); - if (ret) - goto fsck_err; - -@@ -1286,9 +1295,6 @@ int bch2_btree_node_read_done(struct bch - - btree_bounce_free(c, btree_buf_bytes(b), used_mempool, sorted); - -- if (updated_range) -- bch2_btree_node_drop_keys_outside_node(b); -- - i = &b->data->keys; - for (k = i->start; k != vstruct_last(i);) { - struct bkey tmp; -@@ -1305,6 +1311,7 @@ int bch2_btree_node_read_done(struct bch - (u64 *) vstruct_end(i) - (u64 *) k); - set_btree_bset_end(b, b->set); - set_btree_node_need_rewrite(b); -+ set_btree_node_need_rewrite_error(b); - continue; - } - if (ret) -@@ -1325,16 +1332,50 @@ int bch2_btree_node_read_done(struct bch - - btree_node_reset_sib_u64s(b); - -- scoped_guard(rcu) -- bkey_for_each_ptr(bch2_bkey_ptrs(bkey_i_to_s(&b->key)), ptr) { -- struct bch_dev *ca2 = bch2_dev_rcu(c, ptr->dev); -+ if (updated_range) -+ bch2_btree_node_drop_keys_outside_node(b); - -- if (!ca2 || ca2->mi.state != BCH_MEMBER_STATE_rw) -- set_btree_node_need_rewrite(b); -- } -+ /* -+ * XXX: -+ * -+ * We deadlock if too many btree updates require node rewrites while -+ * we're still in journal replay. -+ * -+ * This is because btree node rewrites generate more updates for the -+ * interior updates (alloc, backpointers), and if those updates touch -+ * new nodes and generate more rewrites - well, you see the problem. -+ * -+ * The biggest cause is that we don't use the btree write buffer (for -+ * the backpointer updates - this needs some real thought on locking in -+ * order to fix. -+ * -+ * The problem with this workaround (not doing the rewrite for degraded -+ * nodes in journal replay) is that those degraded nodes persist, and we -+ * don't want that (this is a real bug when a btree node write completes -+ * with fewer replicas than we wanted and leaves a degraded node due to -+ * device _removal_, i.e. the device went away mid write). -+ * -+ * It's less of a bug here, but still a problem because we don't yet -+ * have a way of tracking degraded data - we another index (all -+ * extents/btree nodes, by replicas entry) in order to fix properly -+ * (re-replicate degraded data at the earliest possible time). -+ */ -+ if (c->recovery.passes_complete & BIT_ULL(BCH_RECOVERY_PASS_journal_replay)) { -+ scoped_guard(rcu) -+ bkey_for_each_ptr(bch2_bkey_ptrs(bkey_i_to_s(&b->key)), ptr) { -+ struct bch_dev *ca2 = bch2_dev_rcu(c, ptr->dev); -+ -+ if (!ca2 || ca2->mi.state != BCH_MEMBER_STATE_rw) { -+ set_btree_node_need_rewrite(b); -+ set_btree_node_need_rewrite_degraded(b); -+ } -+ } -+ } - -- if (!ptr_written) -+ if (!ptr_written) { - set_btree_node_need_rewrite(b); -+ set_btree_node_need_rewrite_ptr_written_zero(b); -+ } - fsck_err: - mempool_free(iter, &c->fill_iter); - printbuf_exit(&buf); -@@ -1365,7 +1406,7 @@ static void btree_node_read_work(struct - ret = bch2_bkey_pick_read_device(c, - bkey_i_to_s_c(&b->key), - &failed, &rb->pick, -1); -- if (ret) { -+ if (ret <= 0) { - set_btree_node_read_error(b); - break; - } -@@ -1970,28 +2011,12 @@ static void btree_node_scrub_work(struct - prt_newline(&err); - - if (!btree_node_scrub_check(c, scrub->buf, scrub->written, &err)) { -- struct btree_trans *trans = bch2_trans_get(c); -- -- struct btree_iter iter; -- bch2_trans_node_iter_init(trans, &iter, scrub->btree, -- scrub->key.k->k.p, 0, scrub->level - 1, 0); -- -- struct btree *b; -- int ret = lockrestart_do(trans, -- PTR_ERR_OR_ZERO(b = bch2_btree_iter_peek_node(trans, &iter))); -- if (ret) -- goto err; -- -- if (bkey_i_to_btree_ptr_v2(&b->key)->v.seq == scrub->seq) { -- bch_err(c, "error validating btree node during scrub on %s at btree %s", -- scrub->ca->name, err.buf); -- -- ret = bch2_btree_node_rewrite(trans, &iter, b, 0, 0); -- } --err: -- bch2_trans_iter_exit(trans, &iter); -- bch2_trans_begin(trans); -- bch2_trans_put(trans); -+ int ret = bch2_trans_do(c, -+ bch2_btree_node_rewrite_key(trans, scrub->btree, scrub->level - 1, -+ scrub->key.k, 0)); -+ if (!bch2_err_matches(ret, ENOENT) && -+ !bch2_err_matches(ret, EROFS)) -+ bch_err_fn_ratelimited(c, ret); - } - - printbuf_exit(&err); -@@ -2255,7 +2280,7 @@ static void btree_node_write_endio(struc - } - - static int validate_bset_for_write(struct bch_fs *c, struct btree *b, -- struct bset *i, unsigned sectors) -+ struct bset *i) - { - int ret = bch2_bkey_validate(c, bkey_i_to_s_c(&b->key), - (struct bkey_validate_context) { -@@ -2270,7 +2295,7 @@ static int validate_bset_for_write(struc - } - - ret = validate_bset_keys(c, b, i, WRITE, NULL, NULL) ?: -- validate_bset(c, NULL, b, i, b->written, sectors, WRITE, NULL, NULL); -+ validate_bset(c, NULL, b, i, b->written, WRITE, NULL, NULL); - if (ret) { - bch2_inconsistent_error(c); - dump_stack(); -@@ -2463,7 +2488,7 @@ do_write: - - /* if we're going to be encrypting, check metadata validity first: */ - if (validate_before_checksum && -- validate_bset_for_write(c, b, i, sectors_to_write)) -+ validate_bset_for_write(c, b, i)) - goto err; - - ret = bset_encrypt(c, i, b->written << 9); -@@ -2480,7 +2505,7 @@ do_write: - - /* if we're not encrypting, check metadata after checksumming: */ - if (!validate_before_checksum && -- validate_bset_for_write(c, b, i, sectors_to_write)) -+ validate_bset_for_write(c, b, i)) - goto err; - - /* -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/btree_iter.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_iter.c ---- BPI-Router-Linux-kernel/fs/bcachefs/btree_iter.c 2025-10-22 13:53:23.487327823 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_iter.c 2025-10-22 13:53:56.691168293 -0400 -@@ -2076,14 +2076,14 @@ inline bool bch2_btree_iter_rewind(struc - - static noinline - void bch2_btree_trans_peek_prev_updates(struct btree_trans *trans, struct btree_iter *iter, -- struct bkey_s_c *k) -+ struct bpos search_key, struct bkey_s_c *k) - { - struct bpos end = path_l(btree_iter_path(trans, iter))->b->data->min_key; - - trans_for_each_update(trans, i) - if (!i->key_cache_already_flushed && - i->btree_id == iter->btree_id && -- bpos_le(i->k->k.p, iter->pos) && -+ bpos_le(i->k->k.p, search_key) && - bpos_ge(i->k->k.p, k->k ? k->k->p : end)) { - iter->k = i->k->k; - *k = bkey_i_to_s_c(i->k); -@@ -2092,6 +2092,7 @@ void bch2_btree_trans_peek_prev_updates( - - static noinline - void bch2_btree_trans_peek_updates(struct btree_trans *trans, struct btree_iter *iter, -+ struct bpos search_key, - struct bkey_s_c *k) - { - struct btree_path *path = btree_iter_path(trans, iter); -@@ -2100,7 +2101,7 @@ void bch2_btree_trans_peek_updates(struc - trans_for_each_update(trans, i) - if (!i->key_cache_already_flushed && - i->btree_id == iter->btree_id && -- bpos_ge(i->k->k.p, path->pos) && -+ bpos_ge(i->k->k.p, search_key) && - bpos_le(i->k->k.p, k->k ? k->k->p : end)) { - iter->k = i->k->k; - *k = bkey_i_to_s_c(i->k); -@@ -2122,13 +2123,14 @@ void bch2_btree_trans_peek_slot_updates( - - static struct bkey_i *bch2_btree_journal_peek(struct btree_trans *trans, - struct btree_iter *iter, -+ struct bpos search_pos, - struct bpos end_pos) - { - struct btree_path *path = btree_iter_path(trans, iter); - - return bch2_journal_keys_peek_max(trans->c, iter->btree_id, - path->level, -- path->pos, -+ search_pos, - end_pos, - &iter->journal_idx); - } -@@ -2138,7 +2140,7 @@ struct bkey_s_c btree_trans_peek_slot_jo - struct btree_iter *iter) - { - struct btree_path *path = btree_iter_path(trans, iter); -- struct bkey_i *k = bch2_btree_journal_peek(trans, iter, path->pos); -+ struct bkey_i *k = bch2_btree_journal_peek(trans, iter, path->pos, path->pos); - - if (k) { - iter->k = k->k; -@@ -2151,11 +2153,12 @@ struct bkey_s_c btree_trans_peek_slot_jo - static noinline - void btree_trans_peek_journal(struct btree_trans *trans, - struct btree_iter *iter, -+ struct bpos search_key, - struct bkey_s_c *k) - { - struct btree_path *path = btree_iter_path(trans, iter); - struct bkey_i *next_journal = -- bch2_btree_journal_peek(trans, iter, -+ bch2_btree_journal_peek(trans, iter, search_key, - k->k ? k->k->p : path_l(path)->b->key.k.p); - if (next_journal) { - iter->k = next_journal->k; -@@ -2165,13 +2168,14 @@ void btree_trans_peek_journal(struct btr - - static struct bkey_i *bch2_btree_journal_peek_prev(struct btree_trans *trans, - struct btree_iter *iter, -+ struct bpos search_key, - struct bpos end_pos) - { - struct btree_path *path = btree_iter_path(trans, iter); - - return bch2_journal_keys_peek_prev_min(trans->c, iter->btree_id, - path->level, -- path->pos, -+ search_key, - end_pos, - &iter->journal_idx); - } -@@ -2179,12 +2183,13 @@ static struct bkey_i *bch2_btree_journal - static noinline - void btree_trans_peek_prev_journal(struct btree_trans *trans, - struct btree_iter *iter, -+ struct bpos search_key, - struct bkey_s_c *k) - { - struct btree_path *path = btree_iter_path(trans, iter); - struct bkey_i *next_journal = -- bch2_btree_journal_peek_prev(trans, iter, -- k->k ? k->k->p : path_l(path)->b->key.k.p); -+ bch2_btree_journal_peek_prev(trans, iter, search_key, -+ k->k ? k->k->p : path_l(path)->b->data->min_key); - - if (next_journal) { - iter->k = next_journal->k; -@@ -2292,11 +2297,11 @@ static struct bkey_s_c __bch2_btree_iter - } - - if (unlikely(iter->flags & BTREE_ITER_with_journal)) -- btree_trans_peek_journal(trans, iter, &k); -+ btree_trans_peek_journal(trans, iter, search_key, &k); - - if (unlikely((iter->flags & BTREE_ITER_with_updates) && - trans->nr_updates)) -- bch2_btree_trans_peek_updates(trans, iter, &k); -+ bch2_btree_trans_peek_updates(trans, iter, search_key, &k); - - if (k.k && bkey_deleted(k.k)) { - /* -@@ -2326,6 +2331,20 @@ static struct bkey_s_c __bch2_btree_iter - } - - bch2_btree_iter_verify(trans, iter); -+ -+ if (trace___btree_iter_peek_enabled()) { -+ CLASS(printbuf, buf)(); -+ -+ int ret = bkey_err(k); -+ if (ret) -+ prt_str(&buf, bch2_err_str(ret)); -+ else if (k.k) -+ bch2_bkey_val_to_text(&buf, trans->c, k); -+ else -+ prt_str(&buf, "(null)"); -+ trace___btree_iter_peek(trans->c, buf.buf); -+ } -+ - return k; - } - -@@ -2484,6 +2503,19 @@ out_no_locked: - - bch2_btree_iter_verify_entry_exit(iter); - -+ if (trace_btree_iter_peek_max_enabled()) { -+ CLASS(printbuf, buf)(); -+ -+ int ret = bkey_err(k); -+ if (ret) -+ prt_str(&buf, bch2_err_str(ret)); -+ else if (k.k) -+ bch2_bkey_val_to_text(&buf, trans->c, k); -+ else -+ prt_str(&buf, "(null)"); -+ trace_btree_iter_peek_max(trans->c, buf.buf); -+ } -+ - return k; - end: - bch2_btree_iter_set_pos(trans, iter, end); -@@ -2557,11 +2589,11 @@ static struct bkey_s_c __bch2_btree_iter - } - - if (unlikely(iter->flags & BTREE_ITER_with_journal)) -- btree_trans_peek_prev_journal(trans, iter, &k); -+ btree_trans_peek_prev_journal(trans, iter, search_key, &k); - - if (unlikely((iter->flags & BTREE_ITER_with_updates) && - trans->nr_updates)) -- bch2_btree_trans_peek_prev_updates(trans, iter, &k); -+ bch2_btree_trans_peek_prev_updates(trans, iter, search_key, &k); - - if (likely(k.k && !bkey_deleted(k.k))) { - break; -@@ -2724,6 +2756,19 @@ out_no_locked: - - bch2_btree_iter_verify_entry_exit(iter); - bch2_btree_iter_verify(trans, iter); -+ -+ if (trace_btree_iter_peek_prev_min_enabled()) { -+ CLASS(printbuf, buf)(); -+ -+ int ret = bkey_err(k); -+ if (ret) -+ prt_str(&buf, bch2_err_str(ret)); -+ else if (k.k) -+ bch2_bkey_val_to_text(&buf, trans->c, k); -+ else -+ prt_str(&buf, "(null)"); -+ trace_btree_iter_peek_prev_min(trans->c, buf.buf); -+ } - return k; - end: - bch2_btree_iter_set_pos(trans, iter, end); -@@ -2767,8 +2812,10 @@ struct bkey_s_c bch2_btree_iter_peek_slo - /* extents can't span inode numbers: */ - if ((iter->flags & BTREE_ITER_is_extents) && - unlikely(iter->pos.offset == KEY_OFFSET_MAX)) { -- if (iter->pos.inode == KEY_INODE_MAX) -- return bkey_s_c_null; -+ if (iter->pos.inode == KEY_INODE_MAX) { -+ k = bkey_s_c_null; -+ goto out2; -+ } - - bch2_btree_iter_set_pos(trans, iter, bpos_nosnap_successor(iter->pos)); - } -@@ -2785,8 +2832,10 @@ struct bkey_s_c bch2_btree_iter_peek_slo - } - - struct btree_path *path = btree_iter_path(trans, iter); -- if (unlikely(!btree_path_node(path, path->level))) -- return bkey_s_c_null; -+ if (unlikely(!btree_path_node(path, path->level))) { -+ k = bkey_s_c_null; -+ goto out2; -+ } - - btree_path_set_should_be_locked(trans, path); - -@@ -2879,7 +2928,20 @@ out: - bch2_btree_iter_verify(trans, iter); - ret = bch2_btree_iter_verify_ret(trans, iter, k); - if (unlikely(ret)) -- return bkey_s_c_err(ret); -+ k = bkey_s_c_err(ret); -+out2: -+ if (trace_btree_iter_peek_slot_enabled()) { -+ CLASS(printbuf, buf)(); -+ -+ int ret = bkey_err(k); -+ if (ret) -+ prt_str(&buf, bch2_err_str(ret)); -+ else if (k.k) -+ bch2_bkey_val_to_text(&buf, trans->c, k); -+ else -+ prt_str(&buf, "(null)"); -+ trace_btree_iter_peek_slot(trans->c, buf.buf); -+ } - - return k; - } -@@ -3132,6 +3194,10 @@ void *__bch2_trans_kmalloc(struct btree_ - if (WARN_ON_ONCE(new_bytes > BTREE_TRANS_MEM_MAX)) { - #ifdef CONFIG_BCACHEFS_TRANS_KMALLOC_TRACE - struct printbuf buf = PRINTBUF; -+ bch2_log_msg_start(c, &buf); -+ prt_printf(&buf, "bump allocator exceeded BTREE_TRANS_MEM_MAX (%u)\n", -+ BTREE_TRANS_MEM_MAX); -+ - bch2_trans_kmalloc_trace_to_text(&buf, &trans->trans_kmalloc_trace); - bch2_print_str(c, KERN_ERR, buf.buf); - printbuf_exit(&buf); -@@ -3159,46 +3225,32 @@ void *__bch2_trans_kmalloc(struct btree_ - mutex_unlock(&s->lock); - } - -- if (trans->used_mempool) { -- if (trans->mem_bytes >= new_bytes) -- goto out_change_top; -- -- /* No more space from mempool item, need malloc new one */ -- new_mem = kmalloc(new_bytes, GFP_NOWAIT|__GFP_NOWARN); -- if (unlikely(!new_mem)) { -- bch2_trans_unlock(trans); -+ if (trans->used_mempool || new_bytes > BTREE_TRANS_MEM_MAX) { -+ EBUG_ON(trans->mem_bytes >= new_bytes); -+ return ERR_PTR(-BCH_ERR_ENOMEM_trans_kmalloc); -+ } - -- new_mem = kmalloc(new_bytes, GFP_KERNEL); -- if (!new_mem) -- return ERR_PTR(-BCH_ERR_ENOMEM_trans_kmalloc); -- -- ret = bch2_trans_relock(trans); -- if (ret) { -- kfree(new_mem); -- return ERR_PTR(ret); -- } -- } -- memcpy(new_mem, trans->mem, trans->mem_top); -- trans->used_mempool = false; -- mempool_free(trans->mem, &c->btree_trans_mem_pool); -- goto out_new_mem; -+ if (old_bytes) { -+ trans->realloc_bytes_required = new_bytes; -+ trace_and_count(c, trans_restart_mem_realloced, trans, _RET_IP_, new_bytes); -+ return ERR_PTR(btree_trans_restart_ip(trans, -+ BCH_ERR_transaction_restart_mem_realloced, _RET_IP_)); - } - -- new_mem = krealloc(trans->mem, new_bytes, GFP_NOWAIT|__GFP_NOWARN); -+ EBUG_ON(trans->mem); -+ -+ new_mem = kmalloc(new_bytes, GFP_NOWAIT|__GFP_NOWARN); - if (unlikely(!new_mem)) { - bch2_trans_unlock(trans); - -- new_mem = krealloc(trans->mem, new_bytes, GFP_KERNEL); -+ new_mem = kmalloc(new_bytes, GFP_KERNEL); - if (!new_mem && new_bytes <= BTREE_TRANS_MEM_MAX) { - new_mem = mempool_alloc(&c->btree_trans_mem_pool, GFP_KERNEL); - new_bytes = BTREE_TRANS_MEM_MAX; -- memcpy(new_mem, trans->mem, trans->mem_top); - trans->used_mempool = true; -- kfree(trans->mem); - } - -- if (!new_mem) -- return ERR_PTR(-BCH_ERR_ENOMEM_trans_kmalloc); -+ EBUG_ON(!new_mem); - - trans->mem = new_mem; - trans->mem_bytes = new_bytes; -@@ -3207,18 +3259,10 @@ void *__bch2_trans_kmalloc(struct btree_ - if (ret) - return ERR_PTR(ret); - } --out_new_mem: -+ - trans->mem = new_mem; - trans->mem_bytes = new_bytes; - -- if (old_bytes) { -- trace_and_count(c, trans_restart_mem_realloced, trans, _RET_IP_, new_bytes); -- return ERR_PTR(btree_trans_restart_ip(trans, -- BCH_ERR_transaction_restart_mem_realloced, _RET_IP_)); -- } --out_change_top: -- bch2_trans_kmalloc_trace(trans, size, ip); -- - p = trans->mem + trans->mem_top; - trans->mem_top += size; - memset(p, 0, size); -@@ -3279,6 +3323,27 @@ u32 bch2_trans_begin(struct btree_trans - trans->restart_count++; - trans->mem_top = 0; - -+ if (trans->restarted == BCH_ERR_transaction_restart_mem_realloced) { -+ EBUG_ON(!trans->mem || !trans->mem_bytes); -+ unsigned new_bytes = trans->realloc_bytes_required; -+ void *new_mem = krealloc(trans->mem, new_bytes, GFP_NOWAIT|__GFP_NOWARN); -+ if (unlikely(!new_mem)) { -+ bch2_trans_unlock(trans); -+ new_mem = krealloc(trans->mem, new_bytes, GFP_KERNEL); -+ -+ EBUG_ON(new_bytes > BTREE_TRANS_MEM_MAX); -+ -+ if (!new_mem) { -+ new_mem = mempool_alloc(&trans->c->btree_trans_mem_pool, GFP_KERNEL); -+ new_bytes = BTREE_TRANS_MEM_MAX; -+ trans->used_mempool = true; -+ kfree(trans->mem); -+ } -+ } -+ trans->mem = new_mem; -+ trans->mem_bytes = new_bytes; -+ } -+ - trans_for_each_path(trans, path, i) { - path->should_be_locked = false; - -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/btree_journal_iter.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_journal_iter.c ---- BPI-Router-Linux-kernel/fs/bcachefs/btree_journal_iter.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_journal_iter.c 2025-10-22 13:53:56.691168293 -0400 -@@ -137,12 +137,15 @@ struct bkey_i *bch2_journal_keys_peek_pr - struct journal_key *k; - - BUG_ON(*idx > keys->nr); -+ -+ if (!keys->nr) -+ return NULL; - search: - if (!*idx) - *idx = __bch2_journal_key_search(keys, btree_id, level, pos); - -- while (*idx && -- __journal_key_cmp(btree_id, level, end_pos, idx_to_key(keys, *idx - 1)) <= 0) { -+ while (*idx < keys->nr && -+ __journal_key_cmp(btree_id, level, end_pos, idx_to_key(keys, *idx)) >= 0) { - (*idx)++; - iters++; - if (iters == 10) { -@@ -151,18 +154,23 @@ search: - } - } - -+ if (*idx == keys->nr) -+ --(*idx); -+ - struct bkey_i *ret = NULL; - rcu_read_lock(); /* for overwritten_ranges */ - -- while ((k = *idx < keys->nr ? idx_to_key(keys, *idx) : NULL)) { -+ while (true) { -+ k = idx_to_key(keys, *idx); - if (__journal_key_cmp(btree_id, level, end_pos, k) > 0) - break; - - if (k->overwritten) { - if (k->overwritten_range) -- *idx = rcu_dereference(k->overwritten_range)->start - 1; -- else -- *idx -= 1; -+ *idx = rcu_dereference(k->overwritten_range)->start; -+ if (!*idx) -+ break; -+ --(*idx); - continue; - } - -@@ -171,6 +179,8 @@ search: - break; - } - -+ if (!*idx) -+ break; - --(*idx); - iters++; - if (iters == 10) { -@@ -641,10 +651,11 @@ static int journal_sort_key_cmp(const vo - { - const struct journal_key *l = _l; - const struct journal_key *r = _r; -+ int rewind = l->rewind && r->rewind ? -1 : 1; - - return journal_key_cmp(l, r) ?: -- cmp_int(l->journal_seq, r->journal_seq) ?: -- cmp_int(l->journal_offset, r->journal_offset); -+ ((cmp_int(l->journal_seq, r->journal_seq) ?: -+ cmp_int(l->journal_offset, r->journal_offset)) * rewind); - } - - void bch2_journal_keys_put(struct bch_fs *c) -@@ -713,6 +724,8 @@ int bch2_journal_keys_sort(struct bch_fs - struct journal_keys *keys = &c->journal_keys; - size_t nr_read = 0; - -+ u64 rewind_seq = c->opts.journal_rewind ?: U64_MAX; -+ - genradix_for_each(&c->journal_entries, iter, _i) { - i = *_i; - -@@ -721,28 +734,43 @@ int bch2_journal_keys_sort(struct bch_fs - - cond_resched(); - -- for_each_jset_key(k, entry, &i->j) { -- struct journal_key n = (struct journal_key) { -- .btree_id = entry->btree_id, -- .level = entry->level, -- .k = k, -- .journal_seq = le64_to_cpu(i->j.seq), -- .journal_offset = k->_data - i->j._data, -- }; -- -- if (darray_push(keys, n)) { -- __journal_keys_sort(keys); -- -- if (keys->nr * 8 > keys->size * 7) { -- bch_err(c, "Too many journal keys for slowpath; have %zu compacted, buf size %zu, processed %zu keys at seq %llu", -- keys->nr, keys->size, nr_read, le64_to_cpu(i->j.seq)); -- return bch_err_throw(c, ENOMEM_journal_keys_sort); -+ vstruct_for_each(&i->j, entry) { -+ bool rewind = !entry->level && -+ !btree_id_is_alloc(entry->btree_id) && -+ le64_to_cpu(i->j.seq) >= rewind_seq; -+ -+ if (entry->type != (rewind -+ ? BCH_JSET_ENTRY_overwrite -+ : BCH_JSET_ENTRY_btree_keys)) -+ continue; -+ -+ if (!rewind && le64_to_cpu(i->j.seq) < c->journal_replay_seq_start) -+ continue; -+ -+ jset_entry_for_each_key(entry, k) { -+ struct journal_key n = (struct journal_key) { -+ .btree_id = entry->btree_id, -+ .level = entry->level, -+ .rewind = rewind, -+ .k = k, -+ .journal_seq = le64_to_cpu(i->j.seq), -+ .journal_offset = k->_data - i->j._data, -+ }; -+ -+ if (darray_push(keys, n)) { -+ __journal_keys_sort(keys); -+ -+ if (keys->nr * 8 > keys->size * 7) { -+ bch_err(c, "Too many journal keys for slowpath; have %zu compacted, buf size %zu, processed %zu keys at seq %llu", -+ keys->nr, keys->size, nr_read, le64_to_cpu(i->j.seq)); -+ return bch_err_throw(c, ENOMEM_journal_keys_sort); -+ } -+ -+ BUG_ON(darray_push(keys, n)); - } - -- BUG_ON(darray_push(keys, n)); -+ nr_read++; - } -- -- nr_read++; - } - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/btree_journal_iter_types.h BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_journal_iter_types.h ---- BPI-Router-Linux-kernel/fs/bcachefs/btree_journal_iter_types.h 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_journal_iter_types.h 2025-10-22 13:53:56.691168293 -0400 -@@ -11,8 +11,9 @@ struct journal_key { - u32 journal_offset; - enum btree_id btree_id:8; - unsigned level:8; -- bool allocated; -- bool overwritten; -+ bool allocated:1; -+ bool overwritten:1; -+ bool rewind:1; - struct journal_key_range_overwritten __rcu * - overwritten_range; - struct bkey_i *k; -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/btree_locking.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_locking.c ---- BPI-Router-Linux-kernel/fs/bcachefs/btree_locking.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_locking.c 2025-10-22 13:53:56.691168293 -0400 -@@ -213,7 +213,7 @@ static noinline __noreturn void break_cy - prt_newline(&buf); - } - -- bch2_print_str_nonblocking(g->g->trans->c, KERN_ERR, buf.buf); -+ bch2_print_str(g->g->trans->c, KERN_ERR, buf.buf); - printbuf_exit(&buf); - BUG(); - } -@@ -771,7 +771,7 @@ static inline void __bch2_trans_unlock(s - } - - static noinline __cold void bch2_trans_relock_fail(struct btree_trans *trans, struct btree_path *path, -- struct get_locks_fail *f, bool trace) -+ struct get_locks_fail *f, bool trace, ulong ip) - { - if (!trace) - goto out; -@@ -796,7 +796,7 @@ static noinline __cold void bch2_trans_r - prt_printf(&buf, " total locked %u.%u.%u", c.n[0], c.n[1], c.n[2]); - } - -- trace_trans_restart_relock(trans, _RET_IP_, buf.buf); -+ trace_trans_restart_relock(trans, ip, buf.buf); - printbuf_exit(&buf); - } - -@@ -806,7 +806,7 @@ out: - bch2_trans_verify_locks(trans); - } - --static inline int __bch2_trans_relock(struct btree_trans *trans, bool trace) -+static inline int __bch2_trans_relock(struct btree_trans *trans, bool trace, ulong ip) - { - bch2_trans_verify_locks(trans); - -@@ -825,7 +825,7 @@ static inline int __bch2_trans_relock(st - if (path->should_be_locked && - (ret = btree_path_get_locks(trans, path, false, &f, - BCH_ERR_transaction_restart_relock))) { -- bch2_trans_relock_fail(trans, path, &f, trace); -+ bch2_trans_relock_fail(trans, path, &f, trace, ip); - return ret; - } - } -@@ -838,12 +838,12 @@ out: - - int bch2_trans_relock(struct btree_trans *trans) - { -- return __bch2_trans_relock(trans, true); -+ return __bch2_trans_relock(trans, true, _RET_IP_); - } - - int bch2_trans_relock_notrace(struct btree_trans *trans) - { -- return __bch2_trans_relock(trans, false); -+ return __bch2_trans_relock(trans, false, _RET_IP_); - } - - void bch2_trans_unlock(struct btree_trans *trans) -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/btree_locking.h BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_locking.h ---- BPI-Router-Linux-kernel/fs/bcachefs/btree_locking.h 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_locking.h 2025-10-22 13:53:56.691168293 -0400 -@@ -417,8 +417,10 @@ static inline void btree_path_set_should - EBUG_ON(!btree_node_locked(path, path->level)); - EBUG_ON(path->uptodate); - -- path->should_be_locked = true; -- trace_btree_path_should_be_locked(trans, path); -+ if (!path->should_be_locked) { -+ path->should_be_locked = true; -+ trace_btree_path_should_be_locked(trans, path); -+ } - } - - static inline void __btree_path_set_level_up(struct btree_trans *trans, -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/btree_node_scan.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_node_scan.c ---- BPI-Router-Linux-kernel/fs/bcachefs/btree_node_scan.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_node_scan.c 2025-10-22 13:53:56.691168293 -0400 -@@ -75,39 +75,6 @@ static inline u64 bkey_journal_seq(struc - } - } - --static bool found_btree_node_is_readable(struct btree_trans *trans, -- struct found_btree_node *f) --{ -- struct { __BKEY_PADDED(k, BKEY_BTREE_PTR_VAL_U64s_MAX); } tmp; -- -- found_btree_node_to_key(&tmp.k, f); -- -- struct btree *b = bch2_btree_node_get_noiter(trans, &tmp.k, f->btree_id, f->level, false); -- bool ret = !IS_ERR_OR_NULL(b); -- if (!ret) -- return ret; -- -- f->sectors_written = b->written; -- f->journal_seq = le64_to_cpu(b->data->keys.journal_seq); -- -- struct bkey_s_c k; -- struct bkey unpacked; -- struct btree_node_iter iter; -- for_each_btree_node_key_unpack(b, k, &iter, &unpacked) -- f->journal_seq = max(f->journal_seq, bkey_journal_seq(k)); -- -- six_unlock_read(&b->c.lock); -- -- /* -- * We might update this node's range; if that happens, we need the node -- * to be re-read so the read path can trim keys that are no longer in -- * this node -- */ -- if (b != btree_node_root(trans->c, b)) -- bch2_btree_node_evict(trans, &tmp.k); -- return ret; --} -- - static int found_btree_node_cmp_cookie(const void *_l, const void *_r) - { - const struct found_btree_node *l = _l; -@@ -159,17 +126,17 @@ static const struct min_heap_callbacks f - }; - - static void try_read_btree_node(struct find_btree_nodes *f, struct bch_dev *ca, -- struct bio *bio, struct btree_node *bn, u64 offset) -+ struct btree *b, struct bio *bio, u64 offset) - { - struct bch_fs *c = container_of(f, struct bch_fs, found_btree_nodes); -+ struct btree_node *bn = b->data; - - bio_reset(bio, ca->disk_sb.bdev, REQ_OP_READ); - bio->bi_iter.bi_sector = offset; -- bch2_bio_map(bio, bn, PAGE_SIZE); -+ bch2_bio_map(bio, b->data, c->opts.block_size); - - u64 submit_time = local_clock(); - submit_bio_wait(bio); -- - bch2_account_io_completion(ca, BCH_MEMBER_ERROR_read, submit_time, !bio->bi_status); - - if (bio->bi_status) { -@@ -217,7 +184,28 @@ static void try_read_btree_node(struct f - }; - rcu_read_unlock(); - -- if (bch2_trans_run(c, found_btree_node_is_readable(trans, &n))) { -+ bio_reset(bio, ca->disk_sb.bdev, REQ_OP_READ); -+ bio->bi_iter.bi_sector = offset; -+ bch2_bio_map(bio, b->data, c->opts.btree_node_size); -+ -+ submit_time = local_clock(); -+ submit_bio_wait(bio); -+ bch2_account_io_completion(ca, BCH_MEMBER_ERROR_read, submit_time, !bio->bi_status); -+ -+ found_btree_node_to_key(&b->key, &n); -+ -+ CLASS(printbuf, buf)(); -+ if (!bch2_btree_node_read_done(c, ca, b, NULL, &buf)) { -+ /* read_done will swap out b->data for another buffer */ -+ bn = b->data; -+ /* -+ * Grab journal_seq here because we want the max journal_seq of -+ * any bset; read_done sorts down to a single set and picks the -+ * max journal_seq -+ */ -+ n.journal_seq = le64_to_cpu(bn->keys.journal_seq), -+ n.sectors_written = b->written; -+ - mutex_lock(&f->lock); - if (BSET_BIG_ENDIAN(&bn->keys) != CPU_BIG_ENDIAN) { - bch_err(c, "try_read_btree_node() can't handle endian conversion"); -@@ -237,12 +225,20 @@ static int read_btree_nodes_worker(void - struct find_btree_nodes_worker *w = p; - struct bch_fs *c = container_of(w->f, struct bch_fs, found_btree_nodes); - struct bch_dev *ca = w->ca; -- void *buf = (void *) __get_free_page(GFP_KERNEL); -- struct bio *bio = bio_alloc(NULL, 1, 0, GFP_KERNEL); - unsigned long last_print = jiffies; -+ struct btree *b = NULL; -+ struct bio *bio = NULL; -+ -+ b = __bch2_btree_node_mem_alloc(c); -+ if (!b) { -+ bch_err(c, "read_btree_nodes_worker: error allocating buf"); -+ w->f->ret = -ENOMEM; -+ goto err; -+ } - -- if (!buf || !bio) { -- bch_err(c, "read_btree_nodes_worker: error allocating bio/buf"); -+ bio = bio_alloc(NULL, buf_pages(b->data, c->opts.btree_node_size), 0, GFP_KERNEL); -+ if (!bio) { -+ bch_err(c, "read_btree_nodes_worker: error allocating bio"); - w->f->ret = -ENOMEM; - goto err; - } -@@ -266,11 +262,13 @@ static int read_btree_nodes_worker(void - !bch2_dev_btree_bitmap_marked_sectors(ca, sector, btree_sectors(c))) - continue; - -- try_read_btree_node(w->f, ca, bio, buf, sector); -+ try_read_btree_node(w->f, ca, b, bio, sector); - } - err: -+ if (b) -+ __btree_node_data_free(b); -+ kfree(b); - bio_put(bio); -- free_page((unsigned long) buf); - enumerated_ref_put(&ca->io_ref[READ], BCH_DEV_READ_REF_btree_node_scan); - closure_put(w->cl); - kfree(w); -@@ -521,8 +519,12 @@ bool bch2_btree_node_is_stale(struct bch - return false; - } - --bool bch2_btree_has_scanned_nodes(struct bch_fs *c, enum btree_id btree) -+int bch2_btree_has_scanned_nodes(struct bch_fs *c, enum btree_id btree) - { -+ int ret = bch2_run_print_explicit_recovery_pass(c, BCH_RECOVERY_PASS_scan_for_btree_nodes); -+ if (ret) -+ return ret; -+ - struct found_btree_node search = { - .btree_id = btree, - .level = 0, -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/btree_node_scan.h BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_node_scan.h ---- BPI-Router-Linux-kernel/fs/bcachefs/btree_node_scan.h 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_node_scan.h 2025-10-22 13:53:56.691168293 -0400 -@@ -4,7 +4,7 @@ - - int bch2_scan_for_btree_nodes(struct bch_fs *); - bool bch2_btree_node_is_stale(struct bch_fs *, struct btree *); --bool bch2_btree_has_scanned_nodes(struct bch_fs *, enum btree_id); -+int bch2_btree_has_scanned_nodes(struct bch_fs *, enum btree_id); - int bch2_get_scanned_nodes(struct bch_fs *, enum btree_id, unsigned, struct bpos, struct bpos); - void bch2_find_btree_nodes_exit(struct find_btree_nodes *); - -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/btree_trans_commit.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_trans_commit.c ---- BPI-Router-Linux-kernel/fs/bcachefs/btree_trans_commit.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_trans_commit.c 2025-10-22 13:53:56.691168293 -0400 -@@ -595,12 +595,13 @@ bch2_trans_commit_write_locked(struct bt - int ret = 0; - - bch2_trans_verify_not_unlocked_or_in_restart(trans); -- -+#if 0 -+ /* todo: bring back dynamic fault injection */ - if (race_fault()) { - trace_and_count(c, trans_restart_fault_inject, trans, trace_ip); - return btree_trans_restart(trans, BCH_ERR_transaction_restart_fault_inject); - } -- -+#endif - /* - * Check if the insert will fit in the leaf node with the write lock - * held, otherwise another thread could write the node changing the -@@ -757,6 +758,8 @@ bch2_trans_commit_write_locked(struct bt - btree_trans_journal_entries_start(trans), - trans->journal_entries.u64s); - -+ EBUG_ON(trans->journal_res.u64s < trans->journal_entries.u64s); -+ - trans->journal_res.offset += trans->journal_entries.u64s; - trans->journal_res.u64s -= trans->journal_entries.u64s; - -@@ -1003,6 +1006,7 @@ int __bch2_trans_commit(struct btree_tra - { - struct btree_insert_entry *errored_at = NULL; - struct bch_fs *c = trans->c; -+ unsigned journal_u64s = 0; - int ret = 0; - - bch2_trans_verify_not_unlocked_or_in_restart(trans); -@@ -1031,10 +1035,10 @@ int __bch2_trans_commit(struct btree_tra - - EBUG_ON(test_bit(BCH_FS_clean_shutdown, &c->flags)); - -- trans->journal_u64s = trans->journal_entries.u64s + jset_u64s(trans->accounting.u64s); -+ journal_u64s = jset_u64s(trans->accounting.u64s); - trans->journal_transaction_names = READ_ONCE(c->opts.journal_transaction_names); - if (trans->journal_transaction_names) -- trans->journal_u64s += jset_u64s(JSET_ENTRY_LOG_U64s); -+ journal_u64s += jset_u64s(JSET_ENTRY_LOG_U64s); - - trans_for_each_update(trans, i) { - struct btree_path *path = trans->paths + i->path; -@@ -1054,11 +1058,11 @@ int __bch2_trans_commit(struct btree_tra - continue; - - /* we're going to journal the key being updated: */ -- trans->journal_u64s += jset_u64s(i->k->k.u64s); -+ journal_u64s += jset_u64s(i->k->k.u64s); - - /* and we're also going to log the overwrite: */ - if (trans->journal_transaction_names) -- trans->journal_u64s += jset_u64s(i->old_k.u64s); -+ journal_u64s += jset_u64s(i->old_k.u64s); - } - - if (trans->extra_disk_res) { -@@ -1076,6 +1080,8 @@ retry: - memset(&trans->journal_res, 0, sizeof(trans->journal_res)); - memset(&trans->fs_usage_delta, 0, sizeof(trans->fs_usage_delta)); - -+ trans->journal_u64s = journal_u64s + trans->journal_entries.u64s; -+ - ret = do_bch2_trans_commit(trans, flags, &errored_at, _RET_IP_); - - /* make sure we didn't drop or screw up locks: */ -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/btree_types.h BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_types.h ---- BPI-Router-Linux-kernel/fs/bcachefs/btree_types.h 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_types.h 2025-10-22 13:53:56.691168293 -0400 -@@ -497,6 +497,7 @@ struct btree_trans { - void *mem; - unsigned mem_top; - unsigned mem_bytes; -+ unsigned realloc_bytes_required; - #ifdef CONFIG_BCACHEFS_TRANS_KMALLOC_TRACE - darray_trans_kmalloc_trace trans_kmalloc_trace; - #endif -@@ -617,6 +618,9 @@ enum btree_write_type { - x(dying) \ - x(fake) \ - x(need_rewrite) \ -+ x(need_rewrite_error) \ -+ x(need_rewrite_degraded) \ -+ x(need_rewrite_ptr_written_zero) \ - x(never_write) \ - x(pinned) - -@@ -641,6 +645,32 @@ static inline void clear_btree_node_ ## - BTREE_FLAGS() - #undef x - -+#define BTREE_NODE_REWRITE_REASON() \ -+ x(none) \ -+ x(unknown) \ -+ x(error) \ -+ x(degraded) \ -+ x(ptr_written_zero) -+ -+enum btree_node_rewrite_reason { -+#define x(n) BTREE_NODE_REWRITE_##n, -+ BTREE_NODE_REWRITE_REASON() -+#undef x -+}; -+ -+static inline enum btree_node_rewrite_reason btree_node_rewrite_reason(struct btree *b) -+{ -+ if (btree_node_need_rewrite_ptr_written_zero(b)) -+ return BTREE_NODE_REWRITE_ptr_written_zero; -+ if (btree_node_need_rewrite_degraded(b)) -+ return BTREE_NODE_REWRITE_degraded; -+ if (btree_node_need_rewrite_error(b)) -+ return BTREE_NODE_REWRITE_error; -+ if (btree_node_need_rewrite(b)) -+ return BTREE_NODE_REWRITE_unknown; -+ return BTREE_NODE_REWRITE_none; -+} -+ - static inline struct btree_write *btree_current_write(struct btree *b) - { - return b->writes + btree_node_write_idx(b); -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/btree_update.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_update.c ---- BPI-Router-Linux-kernel/fs/bcachefs/btree_update.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_update.c 2025-10-22 13:53:56.691168293 -0400 -@@ -549,20 +549,26 @@ void *__bch2_trans_subbuf_alloc(struct b - unsigned u64s) - { - unsigned new_top = buf->u64s + u64s; -- unsigned old_size = buf->size; -+ unsigned new_size = buf->size; - -- if (new_top > buf->size) -- buf->size = roundup_pow_of_two(new_top); -+ BUG_ON(roundup_pow_of_two(new_top) > U16_MAX); - -- void *n = bch2_trans_kmalloc_nomemzero(trans, buf->size * sizeof(u64)); -+ if (new_top > new_size) -+ new_size = roundup_pow_of_two(new_top); -+ -+ void *n = bch2_trans_kmalloc_nomemzero(trans, new_size * sizeof(u64)); - if (IS_ERR(n)) - return n; - -+ unsigned offset = (u64 *) n - (u64 *) trans->mem; -+ BUG_ON(offset > U16_MAX); -+ - if (buf->u64s) - memcpy(n, - btree_trans_subbuf_base(trans, buf), -- old_size * sizeof(u64)); -+ buf->size * sizeof(u64)); - buf->base = (u64 *) n - (u64 *) trans->mem; -+ buf->size = new_size; - - void *p = btree_trans_subbuf_top(trans, buf); - buf->u64s = new_top; -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/btree_update.h BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_update.h ---- BPI-Router-Linux-kernel/fs/bcachefs/btree_update.h 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_update.h 2025-10-22 13:53:56.691168293 -0400 -@@ -170,8 +170,7 @@ bch2_trans_jset_entry_alloc(struct btree - - int bch2_btree_insert_clone_trans(struct btree_trans *, enum btree_id, struct bkey_i *); - --int bch2_btree_write_buffer_insert_err(struct btree_trans *, -- enum btree_id, struct bkey_i *); -+int bch2_btree_write_buffer_insert_err(struct bch_fs *, enum btree_id, struct bkey_i *); - - static inline int __must_check bch2_trans_update_buffered(struct btree_trans *trans, - enum btree_id btree, -@@ -182,7 +181,7 @@ static inline int __must_check bch2_tran - EBUG_ON(k->k.u64s > BTREE_WRITE_BUFERED_U64s_MAX); - - if (unlikely(!btree_type_uses_write_buffer(btree))) { -- int ret = bch2_btree_write_buffer_insert_err(trans, btree, k); -+ int ret = bch2_btree_write_buffer_insert_err(trans->c, btree, k); - dump_stack(); - return ret; - } -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/btree_update_interior.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_update_interior.c ---- BPI-Router-Linux-kernel/fs/bcachefs/btree_update_interior.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_update_interior.c 2025-10-22 13:53:56.691168293 -0400 -@@ -1138,6 +1138,13 @@ static void bch2_btree_update_done(struc - start_time); - } - -+static const char * const btree_node_reawrite_reason_strs[] = { -+#define x(n) #n, -+ BTREE_NODE_REWRITE_REASON() -+#undef x -+ NULL, -+}; -+ - static struct btree_update * - bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path, - unsigned level_start, bool split, -@@ -1232,6 +1239,15 @@ bch2_btree_update_start(struct btree_tra - list_add_tail(&as->list, &c->btree_interior_update_list); - mutex_unlock(&c->btree_interior_update_lock); - -+ struct btree *b = btree_path_node(path, path->level); -+ as->node_start = b->data->min_key; -+ as->node_end = b->data->max_key; -+ as->node_needed_rewrite = btree_node_rewrite_reason(b); -+ as->node_written = b->written; -+ as->node_sectors = btree_buf_bytes(b) >> 9; -+ as->node_remaining = __bch2_btree_u64s_remaining(b, -+ btree_bkey_last(b, bset_tree_last(b))); -+ - /* - * We don't want to allocate if we're in an error state, that can cause - * deadlock on emergency shutdown due to open buckets getting stuck in -@@ -1271,10 +1287,11 @@ bch2_btree_update_start(struct btree_tra - - do { - ret = bch2_btree_reserve_get(trans, as, nr_nodes, target, flags, &cl); -- -+ if (!bch2_err_matches(ret, BCH_ERR_operation_blocked)) -+ break; - bch2_trans_unlock(trans); - bch2_wait_on_allocator(c, &cl); -- } while (bch2_err_matches(ret, BCH_ERR_operation_blocked)); -+ } while (1); - } - - if (ret) { -@@ -2108,6 +2125,9 @@ int __bch2_foreground_maybe_merge(struct - if (ret) - goto err; - -+ as->node_start = prev->data->min_key; -+ as->node_end = next->data->max_key; -+ - trace_and_count(c, btree_node_merge, trans, b); - - n = bch2_btree_node_alloc(as, trans, b->c.level); -@@ -2274,9 +2294,9 @@ err: - goto out; - } - --static int bch2_btree_node_rewrite_key(struct btree_trans *trans, -- enum btree_id btree, unsigned level, -- struct bkey_i *k, unsigned flags) -+int bch2_btree_node_rewrite_key(struct btree_trans *trans, -+ enum btree_id btree, unsigned level, -+ struct bkey_i *k, unsigned flags) - { - struct btree_iter iter; - bch2_trans_node_iter_init(trans, &iter, -@@ -2348,9 +2368,8 @@ static void async_btree_node_rewrite_wor - - int ret = bch2_trans_do(c, bch2_btree_node_rewrite_key(trans, - a->btree_id, a->level, a->key.k, 0)); -- if (ret != -ENOENT && -- !bch2_err_matches(ret, EROFS) && -- ret != -BCH_ERR_journal_shutdown) -+ if (!bch2_err_matches(ret, ENOENT) && -+ !bch2_err_matches(ret, EROFS)) - bch_err_fn_ratelimited(c, ret); - - spin_lock(&c->btree_node_rewrites_lock); -@@ -2681,9 +2700,19 @@ static void bch2_btree_update_to_text(st - - prt_str(out, " "); - bch2_btree_id_to_text(out, as->btree_id); -- prt_printf(out, " l=%u-%u mode=%s nodes_written=%u cl.remaining=%u journal_seq=%llu\n", -+ prt_printf(out, " l=%u-%u ", - as->update_level_start, -- as->update_level_end, -+ as->update_level_end); -+ bch2_bpos_to_text(out, as->node_start); -+ prt_char(out, ' '); -+ bch2_bpos_to_text(out, as->node_end); -+ prt_printf(out, "\nwritten %u/%u u64s_remaining %u need_rewrite %s", -+ as->node_written, -+ as->node_sectors, -+ as->node_remaining, -+ btree_node_reawrite_reason_strs[as->node_needed_rewrite]); -+ -+ prt_printf(out, "\nmode=%s nodes_written=%u cl.remaining=%u journal_seq=%llu\n", - bch2_btree_update_modes[as->mode], - as->nodes_written, - closure_nr_remaining(&as->cl), -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/btree_update_interior.h BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_update_interior.h ---- BPI-Router-Linux-kernel/fs/bcachefs/btree_update_interior.h 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_update_interior.h 2025-10-22 13:53:56.691168293 -0400 -@@ -57,6 +57,13 @@ struct btree_update { - unsigned took_gc_lock:1; - - enum btree_id btree_id; -+ struct bpos node_start; -+ struct bpos node_end; -+ enum btree_node_rewrite_reason node_needed_rewrite; -+ u16 node_written; -+ u16 node_sectors; -+ u16 node_remaining; -+ - unsigned update_level_start; - unsigned update_level_end; - -@@ -169,6 +176,9 @@ static inline int bch2_foreground_maybe_ - - int bch2_btree_node_rewrite(struct btree_trans *, struct btree_iter *, - struct btree *, unsigned, unsigned); -+int bch2_btree_node_rewrite_key(struct btree_trans *, -+ enum btree_id, unsigned, -+ struct bkey_i *, unsigned); - int bch2_btree_node_rewrite_pos(struct btree_trans *, - enum btree_id, unsigned, - struct bpos, unsigned, unsigned); -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/btree_write_buffer.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_write_buffer.c ---- BPI-Router-Linux-kernel/fs/bcachefs/btree_write_buffer.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_write_buffer.c 2025-10-22 13:53:56.691168293 -0400 -@@ -267,10 +267,9 @@ out: - BUG_ON(wb->sorted.size < wb->flushing.keys.nr); - } - --int bch2_btree_write_buffer_insert_err(struct btree_trans *trans, -+int bch2_btree_write_buffer_insert_err(struct bch_fs *c, - enum btree_id btree, struct bkey_i *k) - { -- struct bch_fs *c = trans->c; - struct printbuf buf = PRINTBUF; - - prt_printf(&buf, "attempting to do write buffer update on non wb btree="); -@@ -332,7 +331,7 @@ static int bch2_btree_write_buffer_flush - struct btree_write_buffered_key *k = &wb->flushing.keys.data[i->idx]; - - if (unlikely(!btree_type_uses_write_buffer(k->btree))) { -- ret = bch2_btree_write_buffer_insert_err(trans, k->btree, &k->k); -+ ret = bch2_btree_write_buffer_insert_err(trans->c, k->btree, &k->k); - goto err; - } - -@@ -676,6 +675,9 @@ int bch2_btree_write_buffer_maybe_flush( - goto err; - - bch2_bkey_buf_copy(last_flushed, c, tmp.k); -+ -+ /* can we avoid the unconditional restart? */ -+ trace_and_count(c, trans_restart_write_buffer_flush, trans, _RET_IP_); - ret = bch_err_throw(c, transaction_restart_write_buffer_flush); - } - err: -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/btree_write_buffer.h BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_write_buffer.h ---- BPI-Router-Linux-kernel/fs/bcachefs/btree_write_buffer.h 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/btree_write_buffer.h 2025-10-22 13:53:56.691168293 -0400 -@@ -89,6 +89,12 @@ static inline int bch2_journal_key_to_wb - struct journal_keys_to_wb *dst, - enum btree_id btree, struct bkey_i *k) - { -+ if (unlikely(!btree_type_uses_write_buffer(btree))) { -+ int ret = bch2_btree_write_buffer_insert_err(c, btree, k); -+ dump_stack(); -+ return ret; -+ } -+ - EBUG_ON(!dst->seq); - - return k->k.type == KEY_TYPE_accounting -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/chardev.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/chardev.c ---- BPI-Router-Linux-kernel/fs/bcachefs/chardev.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/chardev.c 2025-10-22 13:53:56.691168293 -0400 -@@ -319,6 +319,7 @@ static int bch2_data_thread(void *arg) - ctx->stats.ret = BCH_IOCTL_DATA_EVENT_RET_done; - ctx->stats.data_type = (int) DATA_PROGRESS_DATA_TYPE_done; - } -+ enumerated_ref_put(&ctx->c->writes, BCH_WRITE_REF_ioctl_data); - return 0; - } - -@@ -378,15 +379,24 @@ static long bch2_ioctl_data(struct bch_f - struct bch_data_ctx *ctx; - int ret; - -- if (!capable(CAP_SYS_ADMIN)) -- return -EPERM; -+ if (!enumerated_ref_tryget(&c->writes, BCH_WRITE_REF_ioctl_data)) -+ return -EROFS; - -- if (arg.op >= BCH_DATA_OP_NR || arg.flags) -- return -EINVAL; -+ if (!capable(CAP_SYS_ADMIN)) { -+ ret = -EPERM; -+ goto put_ref; -+ } -+ -+ if (arg.op >= BCH_DATA_OP_NR || arg.flags) { -+ ret = -EINVAL; -+ goto put_ref; -+ } - - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); -- if (!ctx) -- return -ENOMEM; -+ if (!ctx) { -+ ret = -ENOMEM; -+ goto put_ref; -+ } - - ctx->c = c; - ctx->arg = arg; -@@ -395,11 +405,16 @@ static long bch2_ioctl_data(struct bch_f - &bcachefs_data_ops, - bch2_data_thread); - if (ret < 0) -- kfree(ctx); -+ goto cleanup; -+ return ret; -+cleanup: -+ kfree(ctx); -+put_ref: -+ enumerated_ref_put(&c->writes, BCH_WRITE_REF_ioctl_data); - return ret; - } - --static long bch2_ioctl_fs_usage(struct bch_fs *c, -+static noinline_for_stack long bch2_ioctl_fs_usage(struct bch_fs *c, - struct bch_ioctl_fs_usage __user *user_arg) - { - struct bch_ioctl_fs_usage arg = {}; -@@ -469,7 +484,7 @@ err: - } - - /* obsolete, didn't allow for new data types: */ --static long bch2_ioctl_dev_usage(struct bch_fs *c, -+static noinline_for_stack long bch2_ioctl_dev_usage(struct bch_fs *c, - struct bch_ioctl_dev_usage __user *user_arg) - { - struct bch_ioctl_dev_usage arg; -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/data_update.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/data_update.c ---- BPI-Router-Linux-kernel/fs/bcachefs/data_update.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/data_update.c 2025-10-22 13:53:56.691168293 -0400 -@@ -249,6 +249,7 @@ static int data_update_invalid_bkey(stru - bch2_bkey_val_to_text(&buf, c, k); - prt_str(&buf, "\nnew: "); - bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(insert)); -+ prt_newline(&buf); - - bch2_fs_emergency_read_only2(c, &buf); - -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/debug.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/debug.c ---- BPI-Router-Linux-kernel/fs/bcachefs/debug.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/debug.c 2025-10-22 13:53:56.691168293 -0400 -@@ -153,8 +153,6 @@ void __bch2_btree_verify(struct bch_fs * - c->verify_data = __bch2_btree_node_mem_alloc(c); - if (!c->verify_data) - goto out; -- -- list_del_init(&c->verify_data->list); - } - - BUG_ON(b->nsets != 1); -@@ -586,6 +584,8 @@ static ssize_t bch2_btree_transactions_r - i->ubuf = buf; - i->size = size; - i->ret = 0; -+ -+ int srcu_idx = srcu_read_lock(&c->btree_trans_barrier); - restart: - seqmutex_lock(&c->btree_trans_lock); - list_sort(&c->btree_trans_list, list_ptr_order_cmp); -@@ -599,6 +599,11 @@ restart: - if (!closure_get_not_zero(&trans->ref)) - continue; - -+ if (!trans->srcu_held) { -+ closure_put(&trans->ref); -+ continue; -+ } -+ - u32 seq = seqmutex_unlock(&c->btree_trans_lock); - - bch2_btree_trans_to_text(&i->buf, trans); -@@ -620,6 +625,8 @@ restart: - } - seqmutex_unlock(&c->btree_trans_lock); - unlocked: -+ srcu_read_unlock(&c->btree_trans_barrier, srcu_idx); -+ - if (i->buf.allocation_failure) - ret = -ENOMEM; - -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/dirent.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/dirent.c ---- BPI-Router-Linux-kernel/fs/bcachefs/dirent.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/dirent.c 2025-10-22 13:53:56.691168293 -0400 -@@ -13,12 +13,15 @@ - - #include - -+#ifdef CONFIG_UNICODE - int bch2_casefold(struct btree_trans *trans, const struct bch_hash_info *info, - const struct qstr *str, struct qstr *out_cf) - { - *out_cf = (struct qstr) QSTR_INIT(NULL, 0); - --#ifdef CONFIG_UNICODE -+ if (!bch2_fs_casefold_enabled(trans->c)) -+ return -EOPNOTSUPP; -+ - unsigned char *buf = bch2_trans_kmalloc(trans, BCH_NAME_MAX + 1); - int ret = PTR_ERR_OR_ZERO(buf); - if (ret) -@@ -30,10 +33,8 @@ int bch2_casefold(struct btree_trans *tr - - *out_cf = (struct qstr) QSTR_INIT(buf, ret); - return 0; --#else -- return -EOPNOTSUPP; --#endif - } -+#endif - - static unsigned bch2_dirent_name_bytes(struct bkey_s_c_dirent d) - { -@@ -231,7 +232,8 @@ void bch2_dirent_to_text(struct printbuf - prt_printf(out, " type %s", bch2_d_type_str(d.v->d_type)); - } - --int bch2_dirent_init_name(struct bkey_i_dirent *dirent, -+int bch2_dirent_init_name(struct bch_fs *c, -+ struct bkey_i_dirent *dirent, - const struct bch_hash_info *hash_info, - const struct qstr *name, - const struct qstr *cf_name) -@@ -251,6 +253,9 @@ int bch2_dirent_init_name(struct bkey_i_ - offsetof(struct bch_dirent, d_name) - - name->len); - } else { -+ if (!bch2_fs_casefold_enabled(c)) -+ return -EOPNOTSUPP; -+ - #ifdef CONFIG_UNICODE - memcpy(&dirent->v.d_cf_name_block.d_names[0], name->name, name->len); - -@@ -277,8 +282,6 @@ int bch2_dirent_init_name(struct bkey_i_ - dirent->v.d_cf_name_block.d_cf_name_len = cpu_to_le16(cf_len); - - EBUG_ON(bch2_dirent_get_casefold_name(dirent_i_to_s_c(dirent)).len != cf_len); --#else -- return -EOPNOTSUPP; - #endif - } - -@@ -313,7 +316,7 @@ struct bkey_i_dirent *bch2_dirent_create - dirent->v.d_type = type; - dirent->v.d_unused = 0; - -- int ret = bch2_dirent_init_name(dirent, hash_info, name, cf_name); -+ int ret = bch2_dirent_init_name(trans->c, dirent, hash_info, name, cf_name); - if (ret) - return ERR_PTR(ret); - -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/dirent.h BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/dirent.h ---- BPI-Router-Linux-kernel/fs/bcachefs/dirent.h 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/dirent.h 2025-10-22 13:53:56.691168293 -0400 -@@ -23,8 +23,16 @@ struct bch_fs; - struct bch_hash_info; - struct bch_inode_info; - -+#ifdef CONFIG_UNICODE - int bch2_casefold(struct btree_trans *, const struct bch_hash_info *, - const struct qstr *, struct qstr *); -+#else -+static inline int bch2_casefold(struct btree_trans *trans, const struct bch_hash_info *info, -+ const struct qstr *str, struct qstr *out_cf) -+{ -+ return -EOPNOTSUPP; -+} -+#endif - - static inline int bch2_maybe_casefold(struct btree_trans *trans, - const struct bch_hash_info *info, -@@ -59,7 +67,8 @@ static inline void dirent_copy_target(st - dst->v.d_type = src.v->d_type; - } - --int bch2_dirent_init_name(struct bkey_i_dirent *, -+int bch2_dirent_init_name(struct bch_fs *, -+ struct bkey_i_dirent *, - const struct bch_hash_info *, - const struct qstr *, - const struct qstr *); -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/disk_accounting.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/disk_accounting.c ---- BPI-Router-Linux-kernel/fs/bcachefs/disk_accounting.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/disk_accounting.c 2025-10-22 13:53:56.691168293 -0400 -@@ -618,7 +618,9 @@ int bch2_gc_accounting_done(struct bch_f - for (unsigned j = 0; j < nr; j++) - src_v[j] -= dst_v[j]; - -- if (fsck_err(trans, accounting_mismatch, "%s", buf.buf)) { -+ bch2_trans_unlock_long(trans); -+ -+ if (fsck_err(c, accounting_mismatch, "%s", buf.buf)) { - percpu_up_write(&c->mark_lock); - ret = commit_do(trans, NULL, NULL, 0, - bch2_disk_accounting_mod(trans, &acc_k, src_v, nr, false)); -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/errcode.h BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/errcode.h ---- BPI-Router-Linux-kernel/fs/bcachefs/errcode.h 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/errcode.h 2025-10-22 13:53:56.691168293 -0400 -@@ -137,7 +137,6 @@ - x(BCH_ERR_transaction_restart, transaction_restart_relock) \ - x(BCH_ERR_transaction_restart, transaction_restart_relock_path) \ - x(BCH_ERR_transaction_restart, transaction_restart_relock_path_intent) \ -- x(BCH_ERR_transaction_restart, transaction_restart_relock_after_fill) \ - x(BCH_ERR_transaction_restart, transaction_restart_too_many_iters) \ - x(BCH_ERR_transaction_restart, transaction_restart_lock_node_reused) \ - x(BCH_ERR_transaction_restart, transaction_restart_fill_relock) \ -@@ -148,11 +147,8 @@ - x(BCH_ERR_transaction_restart, transaction_restart_would_deadlock_write)\ - x(BCH_ERR_transaction_restart, transaction_restart_deadlock_recursion_limit)\ - x(BCH_ERR_transaction_restart, transaction_restart_upgrade) \ -- x(BCH_ERR_transaction_restart, transaction_restart_key_cache_upgrade) \ - x(BCH_ERR_transaction_restart, transaction_restart_key_cache_fill) \ - x(BCH_ERR_transaction_restart, transaction_restart_key_cache_raced) \ -- x(BCH_ERR_transaction_restart, transaction_restart_key_cache_realloced)\ -- x(BCH_ERR_transaction_restart, transaction_restart_journal_preres_get) \ - x(BCH_ERR_transaction_restart, transaction_restart_split_race) \ - x(BCH_ERR_transaction_restart, transaction_restart_write_buffer_flush) \ - x(BCH_ERR_transaction_restart, transaction_restart_nested) \ -@@ -241,7 +237,6 @@ - x(BCH_ERR_journal_res_blocked, journal_buf_enomem) \ - x(BCH_ERR_journal_res_blocked, journal_stuck) \ - x(BCH_ERR_journal_res_blocked, journal_retry_open) \ -- x(BCH_ERR_journal_res_blocked, journal_preres_get_blocked) \ - x(BCH_ERR_journal_res_blocked, bucket_alloc_blocked) \ - x(BCH_ERR_journal_res_blocked, stripe_alloc_blocked) \ - x(BCH_ERR_invalid, invalid_sb) \ -@@ -287,7 +282,6 @@ - x(EIO, sb_not_downgraded) \ - x(EIO, btree_node_write_all_failed) \ - x(EIO, btree_node_read_error) \ -- x(EIO, btree_node_read_validate_error) \ - x(EIO, btree_need_topology_repair) \ - x(EIO, bucket_ref_update) \ - x(EIO, trigger_alloc) \ -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/error.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/error.c ---- BPI-Router-Linux-kernel/fs/bcachefs/error.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/error.c 2025-10-22 13:53:56.691168293 -0400 -@@ -69,7 +69,7 @@ static bool bch2_fs_trans_inconsistent(s - if (trans) - bch2_trans_updates_to_text(&buf, trans); - bool ret = __bch2_inconsistent_error(c, &buf); -- bch2_print_str_nonblocking(c, KERN_ERR, buf.buf); -+ bch2_print_str(c, KERN_ERR, buf.buf); - - printbuf_exit(&buf); - return ret; -@@ -103,7 +103,7 @@ int __bch2_topology_error(struct bch_fs - return bch_err_throw(c, btree_need_topology_repair); - } else { - return bch2_run_explicit_recovery_pass(c, out, BCH_RECOVERY_PASS_check_topology, 0) ?: -- bch_err_throw(c, btree_node_read_validate_error); -+ bch_err_throw(c, btree_need_topology_repair); - } - } - -@@ -620,6 +620,11 @@ print: - - if (s) - s->ret = ret; -+ -+ if (trans && -+ !(flags & FSCK_ERR_NO_LOG) && -+ ret == -BCH_ERR_fsck_fix) -+ ret = bch2_trans_log_str(trans, bch2_sb_error_strs[err]) ?: ret; - err_unlock: - mutex_unlock(&c->fsck_error_msgs_lock); - err: -@@ -628,7 +633,9 @@ err: - * log_fsck_err()s: that would require us to track for every error type - * which recovery pass corrects it, to get the fsck exit status correct: - */ -- if (bch2_err_matches(ret, BCH_ERR_fsck_fix)) { -+ if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) { -+ /* nothing */ -+ } else if (bch2_err_matches(ret, BCH_ERR_fsck_fix)) { - set_bit(BCH_FS_errors_fixed, &c->flags); - } else { - set_bit(BCH_FS_errors_not_fixed, &c->flags); -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/extents.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/extents.c ---- BPI-Router-Linux-kernel/fs/bcachefs/extents.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/extents.c 2025-10-22 13:53:56.691168293 -0400 -@@ -50,19 +50,17 @@ void bch2_io_failures_to_text(struct pri - struct bch_io_failures *failed) - { - static const char * const error_types[] = { -- "io", "checksum", "ec reconstruct", NULL -+ "btree validate", "io", "checksum", "ec reconstruct", NULL - }; - - for (struct bch_dev_io_failures *f = failed->devs; - f < failed->devs + failed->nr; - f++) { - unsigned errflags = -- ((!!f->failed_io) << 0) | -- ((!!f->failed_csum_nr) << 1) | -- ((!!f->failed_ec) << 2); -- -- if (!errflags) -- continue; -+ ((!!f->failed_btree_validate) << 0) | -+ ((!!f->failed_io) << 1) | -+ ((!!f->failed_csum_nr) << 2) | -+ ((!!f->failed_ec) << 3); - - bch2_printbuf_make_room(out, 1024); - out->atomic++; -@@ -77,7 +75,9 @@ void bch2_io_failures_to_text(struct pri - - prt_char(out, ' '); - -- if (is_power_of_2(errflags)) { -+ if (!errflags) { -+ prt_str(out, "no error - confused"); -+ } else if (is_power_of_2(errflags)) { - prt_bitflags(out, error_types, errflags); - prt_str(out, " error"); - } else { -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/extent_update.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/extent_update.c ---- BPI-Router-Linux-kernel/fs/bcachefs/extent_update.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/extent_update.c 2025-10-22 13:53:56.691168293 -0400 -@@ -139,6 +139,17 @@ int bch2_extent_trim_atomic(struct btree - if (ret) - return ret; - -- bch2_cut_back(end, k); -+ /* tracepoint */ -+ -+ if (bpos_lt(end, k->k.p)) { -+ if (trace_extent_trim_atomic_enabled()) { -+ CLASS(printbuf, buf)(); -+ bch2_bpos_to_text(&buf, end); -+ prt_newline(&buf); -+ bch2_bkey_val_to_text(&buf, trans->c, bkey_i_to_s_c(k)); -+ trace_extent_trim_atomic(trans->c, buf.buf); -+ } -+ bch2_cut_back(end, k); -+ } - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/fs.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/fs.c ---- BPI-Router-Linux-kernel/fs/bcachefs/fs.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/fs.c 2025-10-22 13:53:56.695168274 -0400 -@@ -722,7 +722,6 @@ static struct dentry *bch2_lookup(struct - if (IS_ERR(inode)) - inode = NULL; - --#ifdef CONFIG_UNICODE - if (!inode && IS_CASEFOLDED(vdir)) { - /* - * Do not cache a negative dentry in casefolded directories -@@ -737,7 +736,6 @@ static struct dentry *bch2_lookup(struct - */ - return NULL; - } --#endif - - return d_splice_alias(&inode->v, dentry); - } -@@ -1732,7 +1730,8 @@ static int bch2_fileattr_set(struct mnt_ - bch2_write_inode(c, inode, fssetxattr_inode_update_fn, &s, - ATTR_CTIME); - mutex_unlock(&inode->ei_update_lock); -- return ret; -+ -+ return bch2_err_class(ret); - } - - static const struct file_operations bch_file_operations = { -@@ -2490,6 +2489,14 @@ static int bch2_fs_get_tree(struct fs_co - if (ret) - goto err_stop_fs; - -+ /* -+ * We might be doing a RO mount because other options required it, or we -+ * have no alloc info and it's a small image with no room to regenerate -+ * it -+ */ -+ if (c->opts.read_only) -+ fc->sb_flags |= SB_RDONLY; -+ - sb = sget(fc->fs_type, NULL, bch2_set_super, fc->sb_flags|SB_NOSEC, c); - ret = PTR_ERR_OR_ZERO(sb); - if (ret) -@@ -2557,9 +2564,10 @@ got_sb: - sb->s_shrink->seeks = 0; - - #ifdef CONFIG_UNICODE -- sb->s_encoding = c->cf_encoding; --#endif -+ if (bch2_fs_casefold_enabled(c)) -+ sb->s_encoding = c->cf_encoding; - generic_set_sb_d_ops(sb); -+#endif - - vinode = bch2_vfs_inode_get(c, BCACHEFS_ROOT_SUBVOL_INUM); - ret = PTR_ERR_OR_ZERO(vinode); -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/fsck.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/fsck.c ---- BPI-Router-Linux-kernel/fs/bcachefs/fsck.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/fsck.c 2025-10-22 13:53:56.695168274 -0400 -@@ -12,6 +12,7 @@ - #include "fs.h" - #include "fsck.h" - #include "inode.h" -+#include "io_misc.h" - #include "keylist.h" - #include "namei.h" - #include "recovery_passes.h" -@@ -327,7 +328,8 @@ static inline bool inode_should_reattach - (inode->bi_flags & BCH_INODE_has_child_snapshot)) - return false; - -- return !inode->bi_dir && !(inode->bi_flags & BCH_INODE_unlinked); -+ return !bch2_inode_has_backpointer(inode) && -+ !(inode->bi_flags & BCH_INODE_unlinked); - } - - static int maybe_delete_dirent(struct btree_trans *trans, struct bpos d_pos, u32 snapshot) -@@ -372,6 +374,18 @@ static int reattach_inode(struct btree_t - if (inode->bi_subvol) { - inode->bi_parent_subvol = BCACHEFS_ROOT_SUBVOL; - -+ struct btree_iter subvol_iter; -+ struct bkey_i_subvolume *subvol = -+ bch2_bkey_get_mut_typed(trans, &subvol_iter, -+ BTREE_ID_subvolumes, POS(0, inode->bi_subvol), -+ 0, subvolume); -+ ret = PTR_ERR_OR_ZERO(subvol); -+ if (ret) -+ return ret; -+ -+ subvol->v.fs_path_parent = BCACHEFS_ROOT_SUBVOL; -+ bch2_trans_iter_exit(trans, &subvol_iter); -+ - u64 root_inum; - ret = subvol_lookup(trans, inode->bi_parent_subvol, - &dirent_snapshot, &root_inum); -@@ -387,6 +401,8 @@ static int reattach_inode(struct btree_t - if (ret) - return ret; - -+ bch_verbose(c, "got lostfound inum %llu", lostfound.bi_inum); -+ - lostfound.bi_nlink += S_ISDIR(inode->bi_mode); - - /* ensure lost+found inode is also present in inode snapshot */ -@@ -423,6 +439,16 @@ static int reattach_inode(struct btree_t - if (ret) - return ret; - -+ { -+ CLASS(printbuf, buf)(); -+ ret = bch2_inum_snapshot_to_path(trans, inode->bi_inum, -+ inode->bi_snapshot, NULL, &buf); -+ if (ret) -+ return ret; -+ -+ bch_info(c, "reattached at %s", buf.buf); -+ } -+ - /* - * Fix up inodes in child snapshots: if they should also be reattached - * update the backpointer field, if they should not be we need to emit -@@ -490,13 +516,21 @@ static struct bkey_s_c_dirent dirent_get - static int remove_backpointer(struct btree_trans *trans, - struct bch_inode_unpacked *inode) - { -- if (!inode->bi_dir) -+ if (!bch2_inode_has_backpointer(inode)) - return 0; - -+ u32 snapshot = inode->bi_snapshot; -+ -+ if (inode->bi_parent_subvol) { -+ int ret = bch2_subvolume_get_snapshot(trans, inode->bi_parent_subvol, &snapshot); -+ if (ret) -+ return ret; -+ } -+ - struct bch_fs *c = trans->c; - struct btree_iter iter; - struct bkey_s_c_dirent d = dirent_get_by_pos(trans, &iter, -- SPOS(inode->bi_dir, inode->bi_dir_offset, inode->bi_snapshot)); -+ SPOS(inode->bi_dir, inode->bi_dir_offset, snapshot)); - int ret = bkey_err(d) ?: - dirent_points_to_inode(c, d, inode) ?: - bch2_fsck_remove_dirent(trans, d.k->p); -@@ -695,14 +729,8 @@ static int snapshots_seen_update(struct - static bool key_visible_in_snapshot(struct bch_fs *c, struct snapshots_seen *seen, - u32 id, u32 ancestor) - { -- ssize_t i; -- - EBUG_ON(id > ancestor); - -- /* @ancestor should be the snapshot most recently added to @seen */ -- EBUG_ON(ancestor != seen->pos.snapshot); -- EBUG_ON(ancestor != darray_last(seen->ids)); -- - if (id == ancestor) - return true; - -@@ -718,11 +746,8 @@ static bool key_visible_in_snapshot(stru - * numerically, since snapshot ID lists are kept sorted, so if we find - * an id that's an ancestor of @id we're done: - */ -- -- for (i = seen->ids.nr - 2; -- i >= 0 && seen->ids.data[i] >= id; -- --i) -- if (bch2_snapshot_is_ancestor(c, id, seen->ids.data[i])) -+ darray_for_each_reverse(seen->ids, i) -+ if (*i != ancestor && bch2_snapshot_is_ancestor(c, id, *i)) - return false; - - return true; -@@ -806,7 +831,7 @@ static int add_inode(struct bch_fs *c, s - if (!n->whiteout) { - return bch2_inode_unpack(inode, &n->inode); - } else { -- n->inode.bi_inum = inode.k->p.inode; -+ n->inode.bi_inum = inode.k->p.offset; - n->inode.bi_snapshot = inode.k->p.snapshot; - return 0; - } -@@ -903,17 +928,15 @@ lookup_inode_for_snapshot(struct btree_t - w->last_pos.inode, k.k->p.snapshot, i->inode.bi_snapshot, - (bch2_bkey_val_to_text(&buf, c, k), - buf.buf))) { -- struct bch_inode_unpacked new = i->inode; -- struct bkey_i whiteout; -- -- new.bi_snapshot = k.k->p.snapshot; -- - if (!i->whiteout) { -+ struct bch_inode_unpacked new = i->inode; -+ new.bi_snapshot = k.k->p.snapshot; - ret = __bch2_fsck_write_inode(trans, &new); - } else { -+ struct bkey_i whiteout; - bkey_init(&whiteout.k); - whiteout.k.type = KEY_TYPE_whiteout; -- whiteout.k.p = SPOS(0, i->inode.bi_inum, i->inode.bi_snapshot); -+ whiteout.k.p = SPOS(0, i->inode.bi_inum, k.k->p.snapshot); - ret = bch2_btree_insert_nonextent(trans, BTREE_ID_inodes, - &whiteout, - BTREE_UPDATE_internal_snapshot_node); -@@ -1135,13 +1158,14 @@ static int check_inode(struct btree_tran - if (ret) - goto err; - -- if (u.bi_dir || u.bi_dir_offset) { -+ if (bch2_inode_has_backpointer(&u)) { - ret = check_inode_dirent_inode(trans, &u, &do_update); - if (ret) - goto err; - } - -- if (fsck_err_on(u.bi_dir && (u.bi_flags & BCH_INODE_unlinked), -+ if (fsck_err_on(bch2_inode_has_backpointer(&u) && -+ (u.bi_flags & BCH_INODE_unlinked), - trans, inode_unlinked_but_has_dirent, - "inode unlinked but has dirent\n%s", - (printbuf_reset(&buf), -@@ -1438,6 +1462,7 @@ static int check_key_has_inode(struct bt - { - struct bch_fs *c = trans->c; - struct printbuf buf = PRINTBUF; -+ struct btree_iter iter2 = {}; - int ret = PTR_ERR_OR_ZERO(i); - if (ret) - return ret; -@@ -1447,40 +1472,105 @@ static int check_key_has_inode(struct bt - - bool have_inode = i && !i->whiteout; - -- if (!have_inode && (c->sb.btrees_lost_data & BIT_ULL(BTREE_ID_inodes))) { -- ret = reconstruct_inode(trans, iter->btree_id, k.k->p.snapshot, k.k->p.inode) ?: -- bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc); -- if (ret) -- goto err; -+ if (!have_inode && (c->sb.btrees_lost_data & BIT_ULL(BTREE_ID_inodes))) -+ goto reconstruct; - -- inode->last_pos.inode--; -- ret = bch_err_throw(c, transaction_restart_nested); -- goto err; -+ if (have_inode && btree_matches_i_mode(iter->btree_id, i->inode.bi_mode)) -+ goto out; -+ -+ prt_printf(&buf, ", "); -+ -+ bool have_old_inode = false; -+ darray_for_each(inode->inodes, i2) -+ if (!i2->whiteout && -+ bch2_snapshot_is_ancestor(c, k.k->p.snapshot, i2->inode.bi_snapshot) && -+ btree_matches_i_mode(iter->btree_id, i2->inode.bi_mode)) { -+ prt_printf(&buf, "but found good inode in older snapshot\n"); -+ bch2_inode_unpacked_to_text(&buf, &i2->inode); -+ prt_newline(&buf); -+ have_old_inode = true; -+ break; -+ } -+ -+ struct bkey_s_c k2; -+ unsigned nr_keys = 0; -+ -+ prt_printf(&buf, "found keys:\n"); -+ -+ for_each_btree_key_max_norestart(trans, iter2, iter->btree_id, -+ SPOS(k.k->p.inode, 0, k.k->p.snapshot), -+ POS(k.k->p.inode, U64_MAX), -+ 0, k2, ret) { -+ nr_keys++; -+ if (nr_keys <= 10) { -+ bch2_bkey_val_to_text(&buf, c, k2); -+ prt_newline(&buf); -+ } -+ if (nr_keys >= 100) -+ break; - } - -- if (fsck_err_on(!have_inode, -- trans, key_in_missing_inode, -- "key in missing inode:\n%s", -- (printbuf_reset(&buf), -- bch2_bkey_val_to_text(&buf, c, k), buf.buf))) -- goto delete; -+ if (ret) -+ goto err; - -- if (fsck_err_on(have_inode && !btree_matches_i_mode(iter->btree_id, i->inode.bi_mode), -- trans, key_in_wrong_inode_type, -- "key for wrong inode mode %o:\n%s", -- i->inode.bi_mode, -- (printbuf_reset(&buf), -- bch2_bkey_val_to_text(&buf, c, k), buf.buf))) -- goto delete; -+ if (nr_keys > 100) -+ prt_printf(&buf, "found > %u keys for this missing inode\n", nr_keys); -+ else if (nr_keys > 10) -+ prt_printf(&buf, "found %u keys for this missing inode\n", nr_keys); -+ -+ if (!have_inode) { -+ if (fsck_err_on(!have_inode, -+ trans, key_in_missing_inode, -+ "key in missing inode%s", buf.buf)) { -+ /* -+ * Maybe a deletion that raced with data move, or something -+ * weird like that? But if we know the inode was deleted, or -+ * it's just a few keys, we can safely delete them. -+ * -+ * If it's many keys, we should probably recreate the inode -+ */ -+ if (have_old_inode || nr_keys <= 2) -+ goto delete; -+ else -+ goto reconstruct; -+ } -+ } else { -+ /* -+ * not autofix, this one would be a giant wtf - bit error in the -+ * inode corrupting i_mode? -+ * -+ * may want to try repairing inode instead of deleting -+ */ -+ if (fsck_err_on(!btree_matches_i_mode(iter->btree_id, i->inode.bi_mode), -+ trans, key_in_wrong_inode_type, -+ "key for wrong inode mode %o%s", -+ i->inode.bi_mode, buf.buf)) -+ goto delete; -+ } - out: - err: - fsck_err: -+ bch2_trans_iter_exit(trans, &iter2); - printbuf_exit(&buf); - bch_err_fn(c, ret); - return ret; - delete: -+ /* -+ * XXX: print out more info -+ * count up extents for this inode, check if we have different inode in -+ * an older snapshot version, perhaps decide if we want to reconstitute -+ */ - ret = bch2_btree_delete_at(trans, iter, BTREE_UPDATE_internal_snapshot_node); - goto out; -+reconstruct: -+ ret = reconstruct_inode(trans, iter->btree_id, k.k->p.snapshot, k.k->p.inode) ?: -+ bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc); -+ if (ret) -+ goto err; -+ -+ inode->last_pos.inode--; -+ ret = bch_err_throw(c, transaction_restart_nested); -+ goto out; - } - - static int check_i_sectors_notnested(struct btree_trans *trans, struct inode_walker *w) -@@ -1822,20 +1912,20 @@ static int check_extent(struct btree_tra - !key_visible_in_snapshot(c, s, i->inode.bi_snapshot, k.k->p.snapshot)) - continue; - -- if (fsck_err_on(k.k->p.offset > round_up(i->inode.bi_size, block_bytes(c)) >> 9 && -+ u64 last_block = round_up(i->inode.bi_size, block_bytes(c)) >> 9; -+ -+ if (fsck_err_on(k.k->p.offset > last_block && - !bkey_extent_is_reservation(k), - trans, extent_past_end_of_inode, - "extent type past end of inode %llu:%u, i_size %llu\n%s", - i->inode.bi_inum, i->inode.bi_snapshot, i->inode.bi_size, - (bch2_bkey_val_to_text(&buf, c, k), buf.buf))) { -- struct btree_iter iter2; -- -- bch2_trans_copy_iter(trans, &iter2, iter); -- bch2_btree_iter_set_snapshot(trans, &iter2, i->inode.bi_snapshot); -- ret = bch2_btree_iter_traverse(trans, &iter2) ?: -- bch2_btree_delete_at(trans, &iter2, -- BTREE_UPDATE_internal_snapshot_node); -- bch2_trans_iter_exit(trans, &iter2); -+ ret = snapshots_seen_add_inorder(c, s, i->inode.bi_snapshot) ?: -+ bch2_fpunch_snapshot(trans, -+ SPOS(i->inode.bi_inum, -+ last_block, -+ i->inode.bi_snapshot), -+ POS(i->inode.bi_inum, U64_MAX)); - if (ret) - goto err; - -@@ -1949,14 +2039,22 @@ static int check_subdir_count_notnested( - continue; - } - -- if (fsck_err_on(i->inode.bi_nlink != i->count, -- trans, inode_dir_wrong_nlink, -- "directory %llu:%u with wrong i_nlink: got %u, should be %llu", -- w->last_pos.inode, i->inode.bi_snapshot, i->inode.bi_nlink, i->count)) { -- i->inode.bi_nlink = i->count; -- ret = bch2_fsck_write_inode(trans, &i->inode); -- if (ret) -- break; -+ if (i->inode.bi_nlink != i->count) { -+ CLASS(printbuf, buf)(); -+ -+ lockrestart_do(trans, -+ bch2_inum_snapshot_to_path(trans, w->last_pos.inode, -+ i->inode.bi_snapshot, NULL, &buf)); -+ -+ if (fsck_err_on(i->inode.bi_nlink != i->count, -+ trans, inode_dir_wrong_nlink, -+ "directory with wrong i_nlink: got %u, should be %llu\n%s", -+ i->inode.bi_nlink, i->count, buf.buf)) { -+ i->inode.bi_nlink = i->count; -+ ret = bch2_fsck_write_inode(trans, &i->inode); -+ if (ret) -+ break; -+ } - } - } - fsck_err: -@@ -2184,9 +2282,7 @@ static int check_dirent(struct btree_tra - *hash_info = bch2_hash_info_init(c, &i->inode); - dir->first_this_inode = false; - --#ifdef CONFIG_UNICODE - hash_info->cf_encoding = bch2_inode_casefold(c, &i->inode) ? c->cf_encoding : NULL; --#endif - - ret = bch2_str_hash_check_key(trans, s, &bch2_dirent_hash_desc, hash_info, - iter, k, need_second_pass); -@@ -2493,6 +2589,11 @@ static int check_subvol_path(struct btre - if (k.k->type != KEY_TYPE_subvolume) - return 0; - -+ subvol_inum start = { -+ .subvol = k.k->p.offset, -+ .inum = le64_to_cpu(bkey_s_c_to_subvolume(k).v->inode), -+ }; -+ - while (k.k->p.offset != BCACHEFS_ROOT_SUBVOL) { - ret = darray_push(&subvol_path, k.k->p.offset); - if (ret) -@@ -2511,11 +2612,11 @@ static int check_subvol_path(struct btre - - if (darray_u32_has(&subvol_path, parent)) { - printbuf_reset(&buf); -- prt_printf(&buf, "subvolume loop:\n"); -+ prt_printf(&buf, "subvolume loop: "); - -- darray_for_each_reverse(subvol_path, i) -- prt_printf(&buf, "%u ", *i); -- prt_printf(&buf, "%u", parent); -+ ret = bch2_inum_to_path(trans, start, &buf); -+ if (ret) -+ goto err; - - if (fsck_err(trans, subvol_loop, "%s", buf.buf)) - ret = reattach_subvol(trans, s); -@@ -2559,19 +2660,13 @@ int bch2_check_subvolume_structure(struc - return ret; - } - --struct pathbuf_entry { -- u64 inum; -- u32 snapshot; --}; -- --typedef DARRAY(struct pathbuf_entry) pathbuf; -- --static int bch2_bi_depth_renumber_one(struct btree_trans *trans, struct pathbuf_entry *p, -+static int bch2_bi_depth_renumber_one(struct btree_trans *trans, -+ u64 inum, u32 snapshot, - u32 new_depth) - { - struct btree_iter iter; - struct bkey_s_c k = bch2_bkey_get_iter(trans, &iter, BTREE_ID_inodes, -- SPOS(0, p->inum, p->snapshot), 0); -+ SPOS(0, inum, snapshot), 0); - - struct bch_inode_unpacked inode; - int ret = bkey_err(k) ?: -@@ -2590,14 +2685,15 @@ err: - return ret; - } - --static int bch2_bi_depth_renumber(struct btree_trans *trans, pathbuf *path, u32 new_bi_depth) -+static int bch2_bi_depth_renumber(struct btree_trans *trans, darray_u64 *path, -+ u32 snapshot, u32 new_bi_depth) - { - u32 restart_count = trans->restart_count; - int ret = 0; - - darray_for_each_reverse(*path, i) { - ret = nested_lockrestart_do(trans, -- bch2_bi_depth_renumber_one(trans, i, new_bi_depth)); -+ bch2_bi_depth_renumber_one(trans, *i, snapshot, new_bi_depth)); - bch_err_fn(trans->c, ret); - if (ret) - break; -@@ -2608,37 +2704,36 @@ static int bch2_bi_depth_renumber(struct - return ret ?: trans_was_restarted(trans, restart_count); - } - --static bool path_is_dup(pathbuf *p, u64 inum, u32 snapshot) --{ -- darray_for_each(*p, i) -- if (i->inum == inum && -- i->snapshot == snapshot) -- return true; -- return false; --} -- - static int check_path_loop(struct btree_trans *trans, struct bkey_s_c inode_k) - { - struct bch_fs *c = trans->c; - struct btree_iter inode_iter = {}; -- pathbuf path = {}; -+ darray_u64 path = {}; - struct printbuf buf = PRINTBUF; - u32 snapshot = inode_k.k->p.snapshot; - bool redo_bi_depth = false; - u32 min_bi_depth = U32_MAX; - int ret = 0; - -+ struct bpos start = inode_k.k->p; -+ - struct bch_inode_unpacked inode; - ret = bch2_inode_unpack(inode_k, &inode); - if (ret) - return ret; - -- while (!inode.bi_subvol) { -+ /* -+ * If we're running full fsck, check_dirents() will have already ran, -+ * and we shouldn't see any missing backpointers here - otherwise that's -+ * handled separately, by check_unreachable_inodes -+ */ -+ while (!inode.bi_subvol && -+ bch2_inode_has_backpointer(&inode)) { - struct btree_iter dirent_iter; - struct bkey_s_c_dirent d; -- u32 parent_snapshot = snapshot; - -- d = inode_get_dirent(trans, &dirent_iter, &inode, &parent_snapshot); -+ d = dirent_get_by_pos(trans, &dirent_iter, -+ SPOS(inode.bi_dir, inode.bi_dir_offset, snapshot)); - ret = bkey_err(d.s_c); - if (ret && !bch2_err_matches(ret, ENOENT)) - goto out; -@@ -2656,15 +2751,10 @@ static int check_path_loop(struct btree_ - - bch2_trans_iter_exit(trans, &dirent_iter); - -- ret = darray_push(&path, ((struct pathbuf_entry) { -- .inum = inode.bi_inum, -- .snapshot = snapshot, -- })); -+ ret = darray_push(&path, inode.bi_inum); - if (ret) - return ret; - -- snapshot = parent_snapshot; -- - bch2_trans_iter_exit(trans, &inode_iter); - inode_k = bch2_bkey_get_iter(trans, &inode_iter, BTREE_ID_inodes, - SPOS(0, inode.bi_dir, snapshot), 0); -@@ -2686,21 +2776,28 @@ static int check_path_loop(struct btree_ - break; - - inode = parent_inode; -- snapshot = inode_k.k->p.snapshot; - redo_bi_depth = true; - -- if (path_is_dup(&path, inode.bi_inum, snapshot)) { -+ if (darray_find(path, inode.bi_inum)) { - printbuf_reset(&buf); -- prt_printf(&buf, "directory structure loop:\n"); -- darray_for_each_reverse(path, i) -- prt_printf(&buf, "%llu:%u ", i->inum, i->snapshot); -- prt_printf(&buf, "%llu:%u", inode.bi_inum, snapshot); -+ prt_printf(&buf, "directory structure loop in snapshot %u: ", -+ snapshot); -+ -+ ret = bch2_inum_snapshot_to_path(trans, start.offset, start.snapshot, NULL, &buf); -+ if (ret) -+ goto out; -+ -+ if (c->opts.verbose) { -+ prt_newline(&buf); -+ darray_for_each(path, i) -+ prt_printf(&buf, "%llu ", *i); -+ } - - if (fsck_err(trans, dir_loop, "%s", buf.buf)) { - ret = remove_backpointer(trans, &inode); - bch_err_msg(c, ret, "removing dirent"); - if (ret) -- break; -+ goto out; - - ret = reattach_inode(trans, &inode); - bch_err_msg(c, ret, "reattaching inode %llu", inode.bi_inum); -@@ -2714,7 +2811,7 @@ static int check_path_loop(struct btree_ - min_bi_depth = 0; - - if (redo_bi_depth) -- ret = bch2_bi_depth_renumber(trans, &path, min_bi_depth); -+ ret = bch2_bi_depth_renumber(trans, &path, snapshot, min_bi_depth); - out: - fsck_err: - bch2_trans_iter_exit(trans, &inode_iter); -@@ -2731,7 +2828,7 @@ fsck_err: - int bch2_check_directory_structure(struct bch_fs *c) - { - int ret = bch2_trans_run(c, -- for_each_btree_key_commit(trans, iter, BTREE_ID_inodes, POS_MIN, -+ for_each_btree_key_reverse_commit(trans, iter, BTREE_ID_inodes, POS_MIN, - BTREE_ITER_intent| - BTREE_ITER_prefetch| - BTREE_ITER_all_snapshots, k, -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/inode.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/inode.c ---- BPI-Router-Linux-kernel/fs/bcachefs/inode.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/inode.c 2025-10-22 13:53:56.695168274 -0400 -@@ -1265,7 +1265,14 @@ int bch2_inode_set_casefold(struct btree - { - struct bch_fs *c = trans->c; - --#ifdef CONFIG_UNICODE -+#ifndef CONFIG_UNICODE -+ bch_err(c, "Cannot use casefolding on a kernel without CONFIG_UNICODE"); -+ return -EOPNOTSUPP; -+#endif -+ -+ if (c->opts.casefold_disabled) -+ return -EOPNOTSUPP; -+ - int ret = 0; - /* Not supported on individual files. */ - if (!S_ISDIR(bi->bi_mode)) -@@ -1289,10 +1296,6 @@ int bch2_inode_set_casefold(struct btree - bi->bi_fields_set |= BIT(Inode_opt_casefold); - - return bch2_maybe_propagate_has_case_insensitive(trans, inum, bi); --#else -- bch_err(c, "Cannot use casefolding on a kernel without CONFIG_UNICODE"); -- return -EOPNOTSUPP; --#endif - } - - static noinline int __bch2_inode_rm_snapshot(struct btree_trans *trans, u64 inum, u32 snapshot) -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/inode.h BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/inode.h ---- BPI-Router-Linux-kernel/fs/bcachefs/inode.h 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/inode.h 2025-10-22 13:53:56.695168274 -0400 -@@ -254,6 +254,11 @@ static inline bool bch2_inode_casefold(s - : c->opts.casefold; - } - -+static inline bool bch2_inode_has_backpointer(const struct bch_inode_unpacked *bi) -+{ -+ return bi->bi_dir || bi->bi_dir_offset; -+} -+ - /* i_nlink: */ - - static inline unsigned nlink_bias(umode_t mode) -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/io_misc.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/io_misc.c ---- BPI-Router-Linux-kernel/fs/bcachefs/io_misc.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/io_misc.c 2025-10-22 13:53:56.695168274 -0400 -@@ -135,6 +135,33 @@ err_noprint: - return ret; - } - -+/* For fsck */ -+int bch2_fpunch_snapshot(struct btree_trans *trans, struct bpos start, struct bpos end) -+{ -+ u32 restart_count = trans->restart_count; -+ struct bch_fs *c = trans->c; -+ struct disk_reservation disk_res = bch2_disk_reservation_init(c, 0); -+ unsigned max_sectors = KEY_SIZE_MAX & (~0 << c->block_bits); -+ struct bkey_i delete; -+ -+ int ret = for_each_btree_key_max_commit(trans, iter, BTREE_ID_extents, -+ start, end, 0, k, -+ &disk_res, NULL, BCH_TRANS_COMMIT_no_enospc, ({ -+ bkey_init(&delete.k); -+ delete.k.p = iter.pos; -+ -+ /* create the biggest key we can */ -+ bch2_key_resize(&delete.k, max_sectors); -+ bch2_cut_back(end, &delete); -+ -+ bch2_extent_trim_atomic(trans, &iter, &delete) ?: -+ bch2_trans_update(trans, &iter, &delete, 0); -+ })); -+ -+ bch2_disk_reservation_put(c, &disk_res); -+ return ret ?: trans_was_restarted(trans, restart_count); -+} -+ - /* - * Returns -BCH_ERR_transacton_restart if we had to drop locks: - */ -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/io_misc.h BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/io_misc.h ---- BPI-Router-Linux-kernel/fs/bcachefs/io_misc.h 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/io_misc.h 2025-10-22 13:53:56.695168274 -0400 -@@ -5,6 +5,8 @@ - int bch2_extent_fallocate(struct btree_trans *, subvol_inum, struct btree_iter *, - u64, struct bch_io_opts, s64 *, - struct write_point_specifier); -+ -+int bch2_fpunch_snapshot(struct btree_trans *, struct bpos, struct bpos); - int bch2_fpunch_at(struct btree_trans *, struct btree_iter *, - subvol_inum, u64, s64 *); - int bch2_fpunch(struct bch_fs *c, subvol_inum, u64, u64, s64 *); -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/io_read.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/io_read.c ---- BPI-Router-Linux-kernel/fs/bcachefs/io_read.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/io_read.c 2025-10-22 13:53:56.695168274 -0400 -@@ -166,6 +166,7 @@ static noinline void promote_free(struct - BUG_ON(ret); - - async_object_list_del(c, promote, op->list_idx); -+ async_object_list_del(c, rbio, rbio->list_idx); - - bch2_data_update_exit(&op->write); - -@@ -343,6 +344,10 @@ static struct bch_read_bio *promote_allo - - *bounce = true; - *read_full = promote_full; -+ -+ if (have_io_error(failed)) -+ orig->self_healing = true; -+ - return promote; - nopromote: - trace_io_read_nopromote(c, ret); -@@ -452,6 +457,10 @@ static void bch2_rbio_done(struct bch_re - if (rbio->start_time) - bch2_time_stats_update(&rbio->c->times[BCH_TIME_data_read], - rbio->start_time); -+#ifdef CONFIG_BCACHEFS_ASYNC_OBJECT_LISTS -+ if (rbio->list_idx) -+ async_object_list_del(rbio->c, rbio, rbio->list_idx); -+#endif - bio_endio(&rbio->bio); - } - -@@ -635,12 +644,15 @@ static void bch2_rbio_retry(struct work_ - prt_str(&buf, "(internal move) "); - - prt_str(&buf, "data read error, "); -- if (!ret) -+ if (!ret) { - prt_str(&buf, "successful retry"); -- else -+ if (rbio->self_healing) -+ prt_str(&buf, ", self healing"); -+ } else - prt_str(&buf, bch2_err_str(ret)); - prt_newline(&buf); - -+ - if (!bkey_deleted(&sk.k->k)) { - bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(sk.k)); - prt_newline(&buf); -@@ -1484,7 +1496,12 @@ void bch2_read_bio_to_text(struct printb - prt_printf(out, "have_ioref:\t%u\n", rbio->have_ioref); - prt_printf(out, "narrow_crcs:\t%u\n", rbio->narrow_crcs); - prt_printf(out, "context:\t%u\n", rbio->context); -- prt_printf(out, "ret:\t%s\n", bch2_err_str(rbio->ret)); -+ -+ int ret = READ_ONCE(rbio->ret); -+ if (ret < 0) -+ prt_printf(out, "ret:\t%s\n", bch2_err_str(ret)); -+ else -+ prt_printf(out, "ret:\t%i\n", ret); - - prt_printf(out, "flags:\t"); - bch2_prt_bitflags(out, bch2_read_bio_flags, rbio->flags); -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/io_read.h BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/io_read.h ---- BPI-Router-Linux-kernel/fs/bcachefs/io_read.h 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/io_read.h 2025-10-22 13:53:56.695168274 -0400 -@@ -44,6 +44,7 @@ struct bch_read_bio { - have_ioref:1, - narrow_crcs:1, - saw_error:1, -+ self_healing:1, - context:2; - }; - u16 _state; -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/journal.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/journal.c ---- BPI-Router-Linux-kernel/fs/bcachefs/journal.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/journal.c 2025-10-22 13:53:56.695168274 -0400 -@@ -1082,6 +1082,7 @@ static struct journal_buf *__bch2_next_w - - if (open && !*blocked) { - __bch2_journal_block(j); -+ s.v = atomic64_read_acquire(&j->reservations.counter); - *blocked = true; - } - -@@ -1283,7 +1284,7 @@ static int bch2_set_nr_journal_buckets_l - ret = 0; /* wait and retry */ - - bch2_disk_reservation_put(c, &disk_res); -- closure_sync(&cl); -+ bch2_wait_on_allocator(c, &cl); - } - - return ret; -@@ -1474,14 +1475,13 @@ void bch2_fs_journal_stop(struct journal - clear_bit(JOURNAL_running, &j->flags); - } - --int bch2_fs_journal_start(struct journal *j, u64 cur_seq) -+int bch2_fs_journal_start(struct journal *j, u64 last_seq, u64 cur_seq) - { - struct bch_fs *c = container_of(j, struct bch_fs, journal); - struct journal_entry_pin_list *p; - struct journal_replay *i, **_i; - struct genradix_iter iter; - bool had_entries = false; -- u64 last_seq = cur_seq, nr, seq; - - /* - * -@@ -1495,17 +1495,11 @@ int bch2_fs_journal_start(struct journal - return -EINVAL; - } - -- genradix_for_each_reverse(&c->journal_entries, iter, _i) { -- i = *_i; -+ /* Clean filesystem? */ -+ if (!last_seq) -+ last_seq = cur_seq; - -- if (journal_replay_ignore(i)) -- continue; -- -- last_seq = le64_to_cpu(i->j.last_seq); -- break; -- } -- -- nr = cur_seq - last_seq; -+ u64 nr = cur_seq - last_seq; - - /* - * Extra fudge factor, in case we crashed when the journal pin fifo was -@@ -1532,6 +1526,7 @@ int bch2_fs_journal_start(struct journal - j->pin.back = cur_seq; - atomic64_set(&j->seq, cur_seq - 1); - -+ u64 seq; - fifo_for_each_entry_ptr(p, &j->pin, seq) - journal_pin_list_init(p, 1); - -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/journal.h BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/journal.h ---- BPI-Router-Linux-kernel/fs/bcachefs/journal.h 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/journal.h 2025-10-22 13:53:56.695168274 -0400 -@@ -453,7 +453,7 @@ int bch2_fs_journal_alloc(struct bch_fs - void bch2_dev_journal_stop(struct journal *, struct bch_dev *); - - void bch2_fs_journal_stop(struct journal *); --int bch2_fs_journal_start(struct journal *, u64); -+int bch2_fs_journal_start(struct journal *, u64, u64); - void bch2_journal_set_replay_done(struct journal *); - - void bch2_dev_journal_exit(struct bch_dev *); -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/journal_io.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/journal_io.c ---- BPI-Router-Linux-kernel/fs/bcachefs/journal_io.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/journal_io.c 2025-10-22 13:53:56.695168274 -0400 -@@ -160,6 +160,9 @@ static int journal_entry_add(struct bch_ - struct printbuf buf = PRINTBUF; - int ret = JOURNAL_ENTRY_ADD_OK; - -+ if (last_seq && c->opts.journal_rewind) -+ last_seq = min(last_seq, c->opts.journal_rewind); -+ - if (!c->journal.oldest_seq_found_ondisk || - le64_to_cpu(j->seq) < c->journal.oldest_seq_found_ondisk) - c->journal.oldest_seq_found_ondisk = le64_to_cpu(j->seq); -@@ -1430,11 +1433,21 @@ int bch2_journal_read(struct bch_fs *c, - printbuf_reset(&buf); - prt_printf(&buf, "journal read done, replaying entries %llu-%llu", - *last_seq, *blacklist_seq - 1); -+ -+ /* -+ * Drop blacklisted entries and entries older than last_seq (or start of -+ * journal rewind: -+ */ -+ u64 drop_before = *last_seq; -+ if (c->opts.journal_rewind) { -+ drop_before = min(drop_before, c->opts.journal_rewind); -+ prt_printf(&buf, " (rewinding from %llu)", c->opts.journal_rewind); -+ } -+ -+ *last_seq = drop_before; - if (*start_seq != *blacklist_seq) - prt_printf(&buf, " (unflushed %llu-%llu)", *blacklist_seq, *start_seq - 1); - bch_info(c, "%s", buf.buf); -- -- /* Drop blacklisted entries and entries older than last_seq: */ - genradix_for_each(&c->journal_entries, radix_iter, _i) { - i = *_i; - -@@ -1442,7 +1455,7 @@ int bch2_journal_read(struct bch_fs *c, - continue; - - seq = le64_to_cpu(i->j.seq); -- if (seq < *last_seq) { -+ if (seq < drop_before) { - journal_replay_free(c, i, false); - continue; - } -@@ -1455,7 +1468,7 @@ int bch2_journal_read(struct bch_fs *c, - } - } - -- ret = bch2_journal_check_for_missing(c, *last_seq, *blacklist_seq - 1); -+ ret = bch2_journal_check_for_missing(c, drop_before, *blacklist_seq - 1); - if (ret) - goto err; - -@@ -1703,9 +1716,10 @@ static CLOSURE_CALLBACK(journal_write_do - bch2_log_msg_start(c, &buf); - - if (err == -BCH_ERR_journal_write_err) -- prt_printf(&buf, "unable to write journal to sufficient devices"); -+ prt_printf(&buf, "unable to write journal to sufficient devices\n"); - else -- prt_printf(&buf, "journal write error marking replicas: %s", bch2_err_str(err)); -+ prt_printf(&buf, "journal write error marking replicas: %s\n", -+ bch2_err_str(err)); - - bch2_fs_emergency_read_only2(c, &buf); - -@@ -1753,6 +1767,7 @@ static CLOSURE_CALLBACK(journal_write_do - - closure_wake_up(&c->freelist_wait); - bch2_reset_alloc_cursors(c); -+ do_discards = true; - } - - j->seq_ondisk = seq; -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/journal_reclaim.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/journal_reclaim.c ---- BPI-Router-Linux-kernel/fs/bcachefs/journal_reclaim.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/journal_reclaim.c 2025-10-22 13:53:56.695168274 -0400 -@@ -170,6 +170,12 @@ static struct journal_space __journal_sp - return (struct journal_space) { 0, 0 }; - - /* -+ * It's possible for bucket size to be misaligned w.r.t. the filesystem -+ * block size: -+ */ -+ min_bucket_size = round_down(min_bucket_size, block_sectors(c)); -+ -+ /* - * We sorted largest to smallest, and we want the smallest out of the - * @nr_devs_want largest devices: - */ -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/movinggc.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/movinggc.c ---- BPI-Router-Linux-kernel/fs/bcachefs/movinggc.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/movinggc.c 2025-10-22 13:53:56.695168274 -0400 -@@ -28,7 +28,7 @@ - #include - - struct buckets_in_flight { -- struct rhashtable table; -+ struct rhashtable *table; - struct move_bucket *first; - struct move_bucket *last; - size_t nr; -@@ -71,7 +71,7 @@ static int bch2_bucket_is_movable(struct - if (ret) - return ret; - -- struct bch_dev *ca = bch2_dev_tryget(c, k.k->p.inode); -+ struct bch_dev *ca = bch2_dev_bucket_tryget(c, k.k->p); - if (!ca) - goto out; - -@@ -98,7 +98,7 @@ out: - static void move_bucket_free(struct buckets_in_flight *list, - struct move_bucket *b) - { -- int ret = rhashtable_remove_fast(&list->table, &b->hash, -+ int ret = rhashtable_remove_fast(list->table, &b->hash, - bch_move_bucket_params); - BUG_ON(ret); - kfree(b); -@@ -133,7 +133,7 @@ static void move_buckets_wait(struct mov - static bool bucket_in_flight(struct buckets_in_flight *list, - struct move_bucket_key k) - { -- return rhashtable_lookup_fast(&list->table, &k, bch_move_bucket_params); -+ return rhashtable_lookup_fast(list->table, &k, bch_move_bucket_params); - } - - static int bch2_copygc_get_buckets(struct moving_context *ctxt, -@@ -185,7 +185,7 @@ static int bch2_copygc_get_buckets(struc - goto err; - } - -- ret2 = rhashtable_lookup_insert_fast(&buckets_in_flight->table, &b_i->hash, -+ ret2 = rhashtable_lookup_insert_fast(buckets_in_flight->table, &b_i->hash, - bch_move_bucket_params); - BUG_ON(ret2); - -@@ -350,10 +350,13 @@ static int bch2_copygc_thread(void *arg) - struct buckets_in_flight buckets = {}; - u64 last, wait; - -- int ret = rhashtable_init(&buckets.table, &bch_move_bucket_params); -+ buckets.table = kzalloc(sizeof(*buckets.table), GFP_KERNEL); -+ int ret = !buckets.table -+ ? -ENOMEM -+ : rhashtable_init(buckets.table, &bch_move_bucket_params); - bch_err_msg(c, ret, "allocating copygc buckets in flight"); - if (ret) -- return ret; -+ goto err; - - set_freezable(); - -@@ -421,11 +424,12 @@ static int bch2_copygc_thread(void *arg) - } - - move_buckets_wait(&ctxt, &buckets, true); -- rhashtable_destroy(&buckets.table); -+ rhashtable_destroy(buckets.table); - bch2_moving_ctxt_exit(&ctxt); - bch2_move_stats_exit(&move_stats, c); -- -- return 0; -+err: -+ kfree(buckets.table); -+ return ret; - } - - void bch2_copygc_stop(struct bch_fs *c) -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/namei.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/namei.c ---- BPI-Router-Linux-kernel/fs/bcachefs/namei.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/namei.c 2025-10-22 13:53:56.695168274 -0400 -@@ -175,6 +175,16 @@ int bch2_create_trans(struct btree_trans - new_inode->bi_dir_offset = dir_offset; - } - -+ if (S_ISDIR(mode)) { -+ ret = bch2_maybe_propagate_has_case_insensitive(trans, -+ (subvol_inum) { -+ new_inode->bi_subvol ?: dir.subvol, -+ new_inode->bi_inum }, -+ new_inode); -+ if (ret) -+ goto err; -+ } -+ - if (S_ISDIR(mode) && - !new_inode->bi_subvol) - new_inode->bi_depth = dir_u->bi_depth + 1; -@@ -615,14 +625,26 @@ static int __bch2_inum_to_path(struct bt - { - unsigned orig_pos = path->pos; - int ret = 0; -+ DARRAY(subvol_inum) inums = {}; -+ -+ if (!snapshot) { -+ ret = bch2_subvolume_get_snapshot(trans, subvol, &snapshot); -+ if (ret) -+ goto disconnected; -+ } - - while (true) { -- if (!snapshot) { -- ret = bch2_subvolume_get_snapshot(trans, subvol, &snapshot); -- if (ret) -- goto disconnected; -+ subvol_inum n = (subvol_inum) { subvol ?: snapshot, inum }; -+ -+ if (darray_find_p(inums, i, i->subvol == n.subvol && i->inum == n.inum)) { -+ prt_str_reversed(path, "(loop)"); -+ break; - } - -+ ret = darray_push(&inums, n); -+ if (ret) -+ goto err; -+ - struct bch_inode_unpacked inode; - ret = bch2_inode_find_by_inum_snapshot(trans, inum, snapshot, &inode, 0); - if (ret) -@@ -640,7 +662,9 @@ static int __bch2_inum_to_path(struct bt - inum = inode.bi_dir; - if (inode.bi_parent_subvol) { - subvol = inode.bi_parent_subvol; -- snapshot = 0; -+ ret = bch2_subvolume_get_snapshot(trans, inode.bi_parent_subvol, &snapshot); -+ if (ret) -+ goto disconnected; - } - - struct btree_iter d_iter; -@@ -652,6 +676,7 @@ static int __bch2_inum_to_path(struct bt - goto disconnected; - - struct qstr dirent_name = bch2_dirent_get_name(d); -+ - prt_bytes_reversed(path, dirent_name.name, dirent_name.len); - - prt_char(path, '/'); -@@ -667,8 +692,10 @@ out: - goto err; - - reverse_bytes(path->buf + orig_pos, path->pos - orig_pos); -+ darray_exit(&inums); - return 0; - err: -+ darray_exit(&inums); - return ret; - disconnected: - if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) -@@ -707,8 +734,7 @@ static int bch2_check_dirent_inode_diren - if (inode_points_to_dirent(target, d)) - return 0; - -- if (!target->bi_dir && -- !target->bi_dir_offset) { -+ if (!bch2_inode_has_backpointer(target)) { - fsck_err_on(S_ISDIR(target->bi_mode), - trans, inode_dir_missing_backpointer, - "directory with missing backpointer\n%s", -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/opts.h BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/opts.h ---- BPI-Router-Linux-kernel/fs/bcachefs/opts.h 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/opts.h 2025-10-22 13:53:56.695168274 -0400 -@@ -234,6 +234,11 @@ enum fsck_err_opts { - OPT_BOOL(), \ - BCH_SB_CASEFOLD, false, \ - NULL, "Dirent lookups are casefolded") \ -+ x(casefold_disabled, u8, \ -+ OPT_FS|OPT_MOUNT, \ -+ OPT_BOOL(), \ -+ BCH2_NO_SB_OPT, false, \ -+ NULL, "Disable casefolding filesystem wide") \ - x(inodes_32bit, u8, \ - OPT_FS|OPT_INODE|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \ - OPT_BOOL(), \ -@@ -379,6 +384,11 @@ enum fsck_err_opts { - OPT_BOOL(), \ - BCH2_NO_SB_OPT, false, \ - NULL, "Exit recovery immediately prior to journal replay")\ -+ x(journal_rewind, u64, \ -+ OPT_FS|OPT_MOUNT, \ -+ OPT_UINT(0, U64_MAX), \ -+ BCH2_NO_SB_OPT, 0, \ -+ NULL, "Rewind journal") \ - x(recovery_passes, u64, \ - OPT_FS|OPT_MOUNT, \ - OPT_BITFIELD(bch2_recovery_passes), \ -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/rcu_pending.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/rcu_pending.c ---- BPI-Router-Linux-kernel/fs/bcachefs/rcu_pending.c 2025-10-22 13:53:23.491327804 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/rcu_pending.c 2025-10-22 13:53:56.695168274 -0400 -@@ -182,11 +182,6 @@ static inline void kfree_bulk(size_t nr, - while (nr--) - kfree(*p); - } -- --#define local_irq_save(flags) \ --do { \ -- flags = 0; \ --} while (0) - #endif - - static noinline void __process_finished_items(struct rcu_pending *pending, -@@ -429,9 +424,15 @@ __rcu_pending_enqueue(struct rcu_pending - - BUG_ON((ptr != NULL) != (pending->process == RCU_PENDING_KVFREE_FN)); - -- local_irq_save(flags); -- p = this_cpu_ptr(pending->p); -- spin_lock(&p->lock); -+ /* We could technically be scheduled before taking the lock and end up -+ * using a different cpu's rcu_pending_pcpu: that's ok, it needs a lock -+ * anyways -+ * -+ * And we have to do it this way to avoid breaking PREEMPT_RT, which -+ * redefines how spinlocks work: -+ */ -+ p = raw_cpu_ptr(pending->p); -+ spin_lock_irqsave(&p->lock, flags); - rcu_gp_poll_state_t seq = __get_state_synchronize_rcu(pending->srcu); - restart: - if (may_sleep && -@@ -520,9 +521,8 @@ check_expired: - goto free_node; - } - -- local_irq_save(flags); -- p = this_cpu_ptr(pending->p); -- spin_lock(&p->lock); -+ p = raw_cpu_ptr(pending->p); -+ spin_lock_irqsave(&p->lock, flags); - goto restart; - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/recovery.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/recovery.c ---- BPI-Router-Linux-kernel/fs/bcachefs/recovery.c 2025-10-22 13:53:23.495327784 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/recovery.c 2025-10-22 13:53:56.695168274 -0400 -@@ -99,9 +99,11 @@ int bch2_btree_lost_data(struct bch_fs * - goto out; - case BTREE_ID_snapshots: - ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_reconstruct_snapshots, 0) ?: ret; -+ ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_check_topology, 0) ?: ret; - ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_scan_for_btree_nodes, 0) ?: ret; - goto out; - default: -+ ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_check_topology, 0) ?: ret; - ret = __bch2_run_explicit_recovery_pass(c, msg, BCH_RECOVERY_PASS_scan_for_btree_nodes, 0) ?: ret; - goto out; - } -@@ -272,6 +274,28 @@ static int bch2_journal_replay_key(struc - - struct btree_path *path = btree_iter_path(trans, &iter); - if (unlikely(!btree_path_node(path, k->level))) { -+ struct bch_fs *c = trans->c; -+ -+ CLASS(printbuf, buf)(); -+ prt_str(&buf, "btree="); -+ bch2_btree_id_to_text(&buf, k->btree_id); -+ prt_printf(&buf, " level=%u ", k->level); -+ bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(k->k)); -+ -+ if (!(c->recovery.passes_complete & (BIT_ULL(BCH_RECOVERY_PASS_scan_for_btree_nodes)| -+ BIT_ULL(BCH_RECOVERY_PASS_check_topology)))) { -+ bch_err(c, "have key in journal replay for btree depth that does not exist, confused\n%s", -+ buf.buf); -+ ret = -EINVAL; -+ } -+ -+ if (!k->allocated) { -+ bch_notice(c, "dropping key in journal replay for depth that does not exist because we're recovering from scan\n%s", -+ buf.buf); -+ k->overwritten = true; -+ goto out; -+ } -+ - bch2_trans_iter_exit(trans, &iter); - bch2_trans_node_iter_init(trans, &iter, k->btree_id, k->k->k.p, - BTREE_MAX_DEPTH, 0, iter_flags); -@@ -594,6 +618,7 @@ static int read_btree_roots(struct bch_f - buf.buf, bch2_err_str(ret))) { - if (btree_id_is_alloc(i)) - r->error = 0; -+ ret = 0; - } - } - -@@ -679,7 +704,7 @@ static bool check_version_upgrade(struct - ret = true; - } - -- if (new_version > c->sb.version_incompat && -+ if (new_version > c->sb.version_incompat_allowed && - c->opts.version_upgrade == BCH_VERSION_UPGRADE_incompatible) { - struct printbuf buf = PRINTBUF; - -@@ -739,7 +764,24 @@ int bch2_fs_recovery(struct bch_fs *c) - ? min(c->opts.recovery_pass_last, BCH_RECOVERY_PASS_snapshots_read) - : BCH_RECOVERY_PASS_snapshots_read; - c->opts.nochanges = true; -+ } -+ -+ if (c->opts.nochanges) - c->opts.read_only = true; -+ -+ if (c->opts.journal_rewind) { -+ bch_info(c, "rewinding journal, fsck required"); -+ c->opts.fsck = true; -+ } -+ -+ if (go_rw_in_recovery(c)) { -+ /* -+ * start workqueues/kworkers early - kthread creation checks for -+ * pending signals, which is _very_ annoying -+ */ -+ ret = bch2_fs_init_rw(c); -+ if (ret) -+ goto err; - } - - mutex_lock(&c->sb_lock); -@@ -950,7 +992,7 @@ use_clean: - - ret = bch2_journal_log_msg(c, "starting journal at entry %llu, replaying %llu-%llu", - journal_seq, last_seq, blacklist_seq - 1) ?: -- bch2_fs_journal_start(&c->journal, journal_seq); -+ bch2_fs_journal_start(&c->journal, last_seq, journal_seq); - if (ret) - goto err; - -@@ -1093,9 +1135,6 @@ use_clean: - out: - bch2_flush_fsck_errs(c); - -- if (!IS_ERR(clean)) -- kfree(clean); -- - if (!ret && - test_bit(BCH_FS_need_delete_dead_snapshots, &c->flags) && - !c->opts.nochanges) { -@@ -1104,6 +1143,9 @@ out: - } - - bch_err_fn(c, ret); -+final_out: -+ if (!IS_ERR(clean)) -+ kfree(clean); - return ret; - err: - fsck_err: -@@ -1111,13 +1153,13 @@ fsck_err: - struct printbuf buf = PRINTBUF; - bch2_log_msg_start(c, &buf); - -- prt_printf(&buf, "error in recovery: %s", bch2_err_str(ret)); -+ prt_printf(&buf, "error in recovery: %s\n", bch2_err_str(ret)); - bch2_fs_emergency_read_only2(c, &buf); - - bch2_print_str(c, KERN_ERR, buf.buf); - printbuf_exit(&buf); - } -- return ret; -+ goto final_out; - } - - int bch2_fs_initialize(struct bch_fs *c) -@@ -1166,7 +1208,7 @@ int bch2_fs_initialize(struct bch_fs *c) - * journal_res_get() will crash if called before this has - * set up the journal.pin FIFO and journal.cur pointer: - */ -- ret = bch2_fs_journal_start(&c->journal, 1); -+ ret = bch2_fs_journal_start(&c->journal, 1, 1); - if (ret) - goto err; - -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/recovery_passes.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/recovery_passes.c ---- BPI-Router-Linux-kernel/fs/bcachefs/recovery_passes.c 2025-10-22 13:53:23.495327784 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/recovery_passes.c 2025-10-22 13:53:56.695168274 -0400 -@@ -217,11 +217,7 @@ static int bch2_set_may_go_rw(struct bch - - set_bit(BCH_FS_may_go_rw, &c->flags); - -- if (keys->nr || -- !c->opts.read_only || -- !c->sb.clean || -- c->opts.recovery_passes || -- (c->opts.fsck && !(c->sb.features & BIT_ULL(BCH_FEATURE_no_alloc_info)))) { -+ if (go_rw_in_recovery(c)) { - if (c->sb.features & BIT_ULL(BCH_FEATURE_no_alloc_info)) { - bch_info(c, "mounting a filesystem with no alloc info read-write; will recreate"); - bch2_reconstruct_alloc(c); -@@ -294,8 +290,13 @@ static bool recovery_pass_needs_set(stru - enum bch_run_recovery_pass_flags *flags) - { - struct bch_fs_recovery *r = &c->recovery; -- bool in_recovery = test_bit(BCH_FS_in_recovery, &c->flags); -- bool persistent = !in_recovery || !(*flags & RUN_RECOVERY_PASS_nopersistent); -+ -+ /* -+ * Never run scan_for_btree_nodes persistently: check_topology will run -+ * it if required -+ */ -+ if (pass == BCH_RECOVERY_PASS_scan_for_btree_nodes) -+ *flags |= RUN_RECOVERY_PASS_nopersistent; - - if ((*flags & RUN_RECOVERY_PASS_ratelimit) && - !bch2_recovery_pass_want_ratelimit(c, pass)) -@@ -310,6 +311,11 @@ static bool recovery_pass_needs_set(stru - * Otherwise, we run run_explicit_recovery_pass when we find damage, so - * it should run again even if it's already run: - */ -+ bool in_recovery = test_bit(BCH_FS_in_recovery, &c->flags); -+ bool persistent = !in_recovery || !(*flags & RUN_RECOVERY_PASS_nopersistent); -+ bool rewind = in_recovery && -+ r->curr_pass > pass && -+ !(r->passes_complete & BIT_ULL(pass)); - - if (persistent - ? !(c->sb.recovery_passes_required & BIT_ULL(pass)) -@@ -320,6 +326,9 @@ static bool recovery_pass_needs_set(stru - (r->passes_ratelimiting & BIT_ULL(pass))) - return true; - -+ if (rewind) -+ return true; -+ - return false; - } - -@@ -351,7 +360,7 @@ int __bch2_run_explicit_recovery_pass(st - !(r->passes_complete & BIT_ULL(pass)); - bool ratelimit = flags & RUN_RECOVERY_PASS_ratelimit; - -- if (!(in_recovery && (flags & RUN_RECOVERY_PASS_nopersistent))) { -+ if (!(flags & RUN_RECOVERY_PASS_nopersistent)) { - struct bch_sb_field_ext *ext = bch2_sb_field_get(c->disk_sb.sb, ext); - __set_bit_le64(bch2_recovery_pass_to_stable(pass), ext->recovery_passes_required); - } -@@ -404,10 +413,8 @@ int bch2_run_explicit_recovery_pass(stru - { - int ret = 0; - -- scoped_guard(mutex, &c->sb_lock) { -- if (!recovery_pass_needs_set(c, pass, &flags)) -- return 0; -- -+ if (recovery_pass_needs_set(c, pass, &flags)) { -+ guard(mutex)(&c->sb_lock); - ret = __bch2_run_explicit_recovery_pass(c, out, pass, flags); - bch2_write_super(c); - } -@@ -446,7 +453,7 @@ int bch2_require_recovery_pass(struct bc - - int bch2_run_print_explicit_recovery_pass(struct bch_fs *c, enum bch_recovery_pass pass) - { -- enum bch_run_recovery_pass_flags flags = RUN_RECOVERY_PASS_nopersistent; -+ enum bch_run_recovery_pass_flags flags = 0; - - if (!recovery_pass_needs_set(c, pass, &flags)) - return 0; -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/recovery_passes.h BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/recovery_passes.h ---- BPI-Router-Linux-kernel/fs/bcachefs/recovery_passes.h 2025-10-22 13:53:23.495327784 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/recovery_passes.h 2025-10-22 13:53:56.695168274 -0400 -@@ -17,6 +17,15 @@ enum bch_run_recovery_pass_flags { - RUN_RECOVERY_PASS_ratelimit = BIT(1), - }; - -+static inline bool go_rw_in_recovery(struct bch_fs *c) -+{ -+ return (c->journal_keys.nr || -+ !c->opts.read_only || -+ !c->sb.clean || -+ c->opts.recovery_passes || -+ (c->opts.fsck && !(c->sb.features & BIT_ULL(BCH_FEATURE_no_alloc_info)))); -+} -+ - int bch2_run_print_explicit_recovery_pass(struct bch_fs *, enum bch_recovery_pass); - - int __bch2_run_explicit_recovery_pass(struct bch_fs *, struct printbuf *, -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/reflink.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/reflink.c ---- BPI-Router-Linux-kernel/fs/bcachefs/reflink.c 2025-10-22 13:53:23.495327784 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/reflink.c 2025-10-22 13:53:56.695168274 -0400 -@@ -64,6 +64,9 @@ void bch2_reflink_p_to_text(struct print - REFLINK_P_IDX(p.v), - le32_to_cpu(p.v->front_pad), - le32_to_cpu(p.v->back_pad)); -+ -+ if (REFLINK_P_ERROR(p.v)) -+ prt_str(out, " error"); - } - - bool bch2_reflink_p_merge(struct bch_fs *c, struct bkey_s _l, struct bkey_s_c _r) -@@ -269,13 +272,12 @@ struct bkey_s_c bch2_lookup_indirect_ext - return k; - - if (unlikely(!bkey_extent_is_reflink_data(k.k))) { -- unsigned size = min((u64) k.k->size, -- REFLINK_P_IDX(p.v) + p.k->size + le32_to_cpu(p.v->back_pad) - -- reflink_offset); -- bch2_key_resize(&iter->k, size); -+ u64 missing_end = min(k.k->p.offset, -+ REFLINK_P_IDX(p.v) + p.k->size + le32_to_cpu(p.v->back_pad)); -+ BUG_ON(reflink_offset == missing_end); - - int ret = bch2_indirect_extent_missing_error(trans, p, reflink_offset, -- k.k->p.offset, should_commit); -+ missing_end, should_commit); - if (ret) { - bch2_trans_iter_exit(trans, iter); - return bkey_s_c_err(ret); -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/sb-downgrade.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/sb-downgrade.c ---- BPI-Router-Linux-kernel/fs/bcachefs/sb-downgrade.c 2025-10-22 13:53:23.495327784 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/sb-downgrade.c 2025-10-22 13:53:56.695168274 -0400 -@@ -253,6 +253,7 @@ DOWNGRADE_TABLE() - - static int downgrade_table_extra(struct bch_fs *c, darray_char *table) - { -+ unsigned dst_offset = table->nr; - struct bch_sb_field_downgrade_entry *dst = (void *) &darray_top(*table); - unsigned bytes = sizeof(*dst) + sizeof(dst->errors[0]) * le16_to_cpu(dst->nr_errors); - int ret = 0; -@@ -268,6 +269,9 @@ static int downgrade_table_extra(struct - if (ret) - return ret; - -+ dst = (void *) &table->data[dst_offset]; -+ dst->nr_errors = cpu_to_le16(nr_errors + 1); -+ - /* open coded __set_bit_le64, as dst is packed and - * dst->recovery_passes is misaligned */ - unsigned b = BCH_RECOVERY_PASS_STABLE_check_allocations; -@@ -278,7 +282,6 @@ static int downgrade_table_extra(struct - break; - } - -- dst->nr_errors = cpu_to_le16(nr_errors); - return ret; - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/sb-errors_format.h BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/sb-errors_format.h ---- BPI-Router-Linux-kernel/fs/bcachefs/sb-errors_format.h 2025-10-22 13:53:23.495327784 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/sb-errors_format.h 2025-10-22 13:53:56.695168274 -0400 -@@ -3,9 +3,10 @@ - #define _BCACHEFS_SB_ERRORS_FORMAT_H - - enum bch_fsck_flags { -- FSCK_CAN_FIX = 1 << 0, -- FSCK_CAN_IGNORE = 1 << 1, -- FSCK_AUTOFIX = 1 << 2, -+ FSCK_CAN_FIX = BIT(0), -+ FSCK_CAN_IGNORE = BIT(1), -+ FSCK_AUTOFIX = BIT(2), -+ FSCK_ERR_NO_LOG = BIT(3), - }; - - #define BCH_SB_ERRS() \ -@@ -134,7 +135,7 @@ enum bch_fsck_flags { - x(bucket_gens_to_invalid_buckets, 121, FSCK_AUTOFIX) \ - x(bucket_gens_nonzero_for_invalid_buckets, 122, FSCK_AUTOFIX) \ - x(need_discard_freespace_key_to_invalid_dev_bucket, 123, 0) \ -- x(need_discard_freespace_key_bad, 124, 0) \ -+ x(need_discard_freespace_key_bad, 124, FSCK_AUTOFIX) \ - x(discarding_bucket_not_in_need_discard_btree, 291, 0) \ - x(backpointer_bucket_offset_wrong, 125, 0) \ - x(backpointer_level_bad, 294, 0) \ -@@ -165,7 +166,7 @@ enum bch_fsck_flags { - x(ptr_to_missing_replicas_entry, 149, FSCK_AUTOFIX) \ - x(ptr_to_missing_stripe, 150, 0) \ - x(ptr_to_incorrect_stripe, 151, 0) \ -- x(ptr_gen_newer_than_bucket_gen, 152, 0) \ -+ x(ptr_gen_newer_than_bucket_gen, 152, FSCK_AUTOFIX) \ - x(ptr_too_stale, 153, 0) \ - x(stale_dirty_ptr, 154, FSCK_AUTOFIX) \ - x(ptr_bucket_data_type_mismatch, 155, 0) \ -@@ -217,7 +218,7 @@ enum bch_fsck_flags { - x(inode_str_hash_invalid, 194, 0) \ - x(inode_v3_fields_start_bad, 195, 0) \ - x(inode_snapshot_mismatch, 196, 0) \ -- x(snapshot_key_missing_inode_snapshot, 314, 0) \ -+ x(snapshot_key_missing_inode_snapshot, 314, FSCK_AUTOFIX) \ - x(inode_unlinked_but_clean, 197, 0) \ - x(inode_unlinked_but_nlink_nonzero, 198, 0) \ - x(inode_unlinked_and_not_open, 281, 0) \ -@@ -236,7 +237,7 @@ enum bch_fsck_flags { - x(inode_multiple_links_but_nlink_0, 207, FSCK_AUTOFIX) \ - x(inode_wrong_backpointer, 208, FSCK_AUTOFIX) \ - x(inode_wrong_nlink, 209, FSCK_AUTOFIX) \ -- x(inode_has_child_snapshots_wrong, 287, 0) \ -+ x(inode_has_child_snapshots_wrong, 287, FSCK_AUTOFIX) \ - x(inode_unreachable, 210, FSCK_AUTOFIX) \ - x(inode_journal_seq_in_future, 299, FSCK_AUTOFIX) \ - x(inode_i_sectors_underflow, 312, FSCK_AUTOFIX) \ -@@ -251,20 +252,20 @@ enum bch_fsck_flags { - x(deleted_inode_not_unlinked, 214, FSCK_AUTOFIX) \ - x(deleted_inode_has_child_snapshots, 288, FSCK_AUTOFIX) \ - x(extent_overlapping, 215, 0) \ -- x(key_in_missing_inode, 216, 0) \ -+ x(key_in_missing_inode, 216, FSCK_AUTOFIX) \ - x(key_in_wrong_inode_type, 217, 0) \ -- x(extent_past_end_of_inode, 218, 0) \ -+ x(extent_past_end_of_inode, 218, FSCK_AUTOFIX) \ - x(dirent_empty_name, 219, 0) \ - x(dirent_val_too_big, 220, 0) \ - x(dirent_name_too_long, 221, 0) \ - x(dirent_name_embedded_nul, 222, 0) \ - x(dirent_name_dot_or_dotdot, 223, 0) \ - x(dirent_name_has_slash, 224, 0) \ -- x(dirent_d_type_wrong, 225, 0) \ -+ x(dirent_d_type_wrong, 225, FSCK_AUTOFIX) \ - x(inode_bi_parent_wrong, 226, 0) \ - x(dirent_in_missing_dir_inode, 227, 0) \ - x(dirent_in_non_dir_inode, 228, 0) \ -- x(dirent_to_missing_inode, 229, 0) \ -+ x(dirent_to_missing_inode, 229, FSCK_AUTOFIX) \ - x(dirent_to_overwritten_inode, 302, 0) \ - x(dirent_to_missing_subvol, 230, 0) \ - x(dirent_to_itself, 231, 0) \ -@@ -279,8 +280,8 @@ enum bch_fsck_flags { - x(root_dir_missing, 239, 0) \ - x(root_inode_not_dir, 240, 0) \ - x(dir_loop, 241, 0) \ -- x(hash_table_key_duplicate, 242, 0) \ -- x(hash_table_key_wrong_offset, 243, 0) \ -+ x(hash_table_key_duplicate, 242, FSCK_AUTOFIX) \ -+ x(hash_table_key_wrong_offset, 243, FSCK_AUTOFIX) \ - x(unlinked_inode_not_on_deleted_list, 244, FSCK_AUTOFIX) \ - x(reflink_p_front_pad_bad, 245, 0) \ - x(journal_entry_dup_same_device, 246, 0) \ -@@ -300,7 +301,7 @@ enum bch_fsck_flags { - x(btree_node_bkey_bad_u64s, 260, 0) \ - x(btree_node_topology_empty_interior_node, 261, 0) \ - x(btree_ptr_v2_min_key_bad, 262, 0) \ -- x(btree_root_unreadable_and_scan_found_nothing, 263, FSCK_AUTOFIX) \ -+ x(btree_root_unreadable_and_scan_found_nothing, 263, 0) \ - x(snapshot_node_missing, 264, FSCK_AUTOFIX) \ - x(dup_backpointer_to_bad_csum_extent, 265, 0) \ - x(btree_bitmap_not_marked, 266, FSCK_AUTOFIX) \ -@@ -313,7 +314,7 @@ enum bch_fsck_flags { - x(accounting_mismatch, 272, FSCK_AUTOFIX) \ - x(accounting_replicas_not_marked, 273, 0) \ - x(accounting_to_invalid_device, 289, 0) \ -- x(invalid_btree_id, 274, 0) \ -+ x(invalid_btree_id, 274, FSCK_AUTOFIX) \ - x(alloc_key_io_time_bad, 275, 0) \ - x(alloc_key_fragmentation_lru_wrong, 276, FSCK_AUTOFIX) \ - x(accounting_key_junk_at_end, 277, FSCK_AUTOFIX) \ -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/sb-members.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/sb-members.c ---- BPI-Router-Linux-kernel/fs/bcachefs/sb-members.c 2025-10-22 13:53:23.495327784 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/sb-members.c 2025-10-22 13:53:56.695168274 -0400 -@@ -325,9 +325,17 @@ static void bch2_sb_members_v1_to_text(s - { - struct bch_sb_field_members_v1 *mi = field_to_type(f, members_v1); - struct bch_sb_field_disk_groups *gi = bch2_sb_field_get(sb, disk_groups); -- unsigned i; - -- for (i = 0; i < sb->nr_devices; i++) -+ if (vstruct_end(&mi->field) <= (void *) &mi->_members[0]) { -+ prt_printf(out, "field ends before start of entries"); -+ return; -+ } -+ -+ unsigned nr = (vstruct_end(&mi->field) - (void *) &mi->_members[0]) / sizeof(mi->_members[0]); -+ if (nr != sb->nr_devices) -+ prt_printf(out, "nr_devices mismatch: have %i entries, should be %u", nr, sb->nr_devices); -+ -+ for (unsigned i = 0; i < min(sb->nr_devices, nr); i++) - member_to_text(out, members_v1_get(mi, i), gi, sb, i); - } - -@@ -341,9 +349,27 @@ static void bch2_sb_members_v2_to_text(s - { - struct bch_sb_field_members_v2 *mi = field_to_type(f, members_v2); - struct bch_sb_field_disk_groups *gi = bch2_sb_field_get(sb, disk_groups); -- unsigned i; - -- for (i = 0; i < sb->nr_devices; i++) -+ if (vstruct_end(&mi->field) <= (void *) &mi->_members[0]) { -+ prt_printf(out, "field ends before start of entries"); -+ return; -+ } -+ -+ if (!le16_to_cpu(mi->member_bytes)) { -+ prt_printf(out, "member_bytes 0"); -+ return; -+ } -+ -+ unsigned nr = (vstruct_end(&mi->field) - (void *) &mi->_members[0]) / le16_to_cpu(mi->member_bytes); -+ if (nr != sb->nr_devices) -+ prt_printf(out, "nr_devices mismatch: have %i entries, should be %u", nr, sb->nr_devices); -+ -+ /* -+ * We call to_text() on superblock sections that haven't passed -+ * validate, so we can't trust sb->nr_devices. -+ */ -+ -+ for (unsigned i = 0; i < min(sb->nr_devices, nr); i++) - member_to_text(out, members_v2_get(mi, i), gi, sb, i); - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/snapshot.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/snapshot.c ---- BPI-Router-Linux-kernel/fs/bcachefs/snapshot.c 2025-10-22 13:53:23.495327784 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/snapshot.c 2025-10-22 13:53:56.695168274 -0400 -@@ -135,7 +135,9 @@ static bool test_ancestor_bitmap(struct - - bool __bch2_snapshot_is_ancestor(struct bch_fs *c, u32 id, u32 ancestor) - { -- bool ret; -+#ifdef CONFIG_BCACHEFS_DEBUG -+ u32 orig_id = id; -+#endif - - guard(rcu)(); - struct snapshot_table *t = rcu_dereference(c->snapshots); -@@ -147,11 +149,11 @@ bool __bch2_snapshot_is_ancestor(struct - while (id && id < ancestor - IS_ANCESTOR_BITMAP) - id = get_ancestor_below(t, id, ancestor); - -- ret = id && id < ancestor -+ bool ret = id && id < ancestor - ? test_ancestor_bitmap(t, id, ancestor) - : id == ancestor; - -- EBUG_ON(ret != __bch2_snapshot_is_ancestor_early(t, id, ancestor)); -+ EBUG_ON(ret != __bch2_snapshot_is_ancestor_early(t, orig_id, ancestor)); - return ret; - } - -@@ -869,7 +871,8 @@ static int check_snapshot_exists(struct - - for_each_btree_key_norestart(trans, iter, BTREE_ID_snapshot_trees, POS_MIN, - 0, k, ret) { -- if (le32_to_cpu(bkey_s_c_to_snapshot_tree(k).v->root_snapshot) == id) { -+ if (k.k->type == KEY_TYPE_snapshot_tree && -+ le32_to_cpu(bkey_s_c_to_snapshot_tree(k).v->root_snapshot) == id) { - tree_id = k.k->p.offset; - break; - } -@@ -897,7 +900,8 @@ static int check_snapshot_exists(struct - - for_each_btree_key_norestart(trans, iter, BTREE_ID_subvolumes, POS_MIN, - 0, k, ret) { -- if (le32_to_cpu(bkey_s_c_to_subvolume(k).v->snapshot) == id) { -+ if (k.k->type == KEY_TYPE_subvolume && -+ le32_to_cpu(bkey_s_c_to_subvolume(k).v->snapshot) == id) { - snapshot->v.subvol = cpu_to_le32(k.k->p.offset); - SET_BCH_SNAPSHOT_SUBVOL(&snapshot->v, true); - break; -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/str_hash.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/str_hash.c ---- BPI-Router-Linux-kernel/fs/bcachefs/str_hash.c 2025-10-22 13:53:23.495327784 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/str_hash.c 2025-10-22 13:53:56.695168274 -0400 -@@ -38,6 +38,7 @@ static int bch2_fsck_rename_dirent(struc - struct bkey_s_c_dirent old, - bool *updated_before_k_pos) - { -+ struct bch_fs *c = trans->c; - struct qstr old_name = bch2_dirent_get_name(old); - struct bkey_i_dirent *new = bch2_trans_kmalloc(trans, BKEY_U64s_MAX * sizeof(u64)); - int ret = PTR_ERR_OR_ZERO(new); -@@ -60,7 +61,7 @@ static int bch2_fsck_rename_dirent(struc - sprintf(renamed_buf, "%.*s.fsck_renamed-%u", - old_name.len, old_name.name, i)); - -- ret = bch2_dirent_init_name(new, hash_info, &renamed_name, NULL); -+ ret = bch2_dirent_init_name(c, new, hash_info, &renamed_name, NULL); - if (ret) - return ret; - -@@ -79,7 +80,7 @@ static int bch2_fsck_rename_dirent(struc - } - - ret = ret ?: bch2_fsck_update_backpointers(trans, s, desc, hash_info, &new->k_i); -- bch_err_fn(trans->c, ret); -+ bch_err_fn(c, ret); - return ret; - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/str_hash.h BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/str_hash.h ---- BPI-Router-Linux-kernel/fs/bcachefs/str_hash.h 2025-10-22 13:53:23.495327784 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/str_hash.h 2025-10-22 13:53:56.695168274 -0400 -@@ -48,9 +48,7 @@ bch2_hash_info_init(struct bch_fs *c, co - struct bch_hash_info info = { - .inum_snapshot = bi->bi_snapshot, - .type = INODE_STR_HASH(bi), --#ifdef CONFIG_UNICODE - .cf_encoding = bch2_inode_casefold(c, bi) ? c->cf_encoding : NULL, --#endif - .siphash_key = { .k0 = bi->bi_hash_seed } - }; - -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/super.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/super.c ---- BPI-Router-Linux-kernel/fs/bcachefs/super.c 2025-10-22 13:53:23.495327784 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/super.c 2025-10-22 13:53:56.695168274 -0400 -@@ -104,7 +104,7 @@ const char * const bch2_dev_write_refs[] - #undef x - - static void __bch2_print_str(struct bch_fs *c, const char *prefix, -- const char *str, bool nonblocking) -+ const char *str) - { - #ifdef __KERNEL__ - struct stdio_redirect *stdio = bch2_fs_stdio_redirect(c); -@@ -114,17 +114,12 @@ static void __bch2_print_str(struct bch_ - return; - } - #endif -- bch2_print_string_as_lines(KERN_ERR, str, nonblocking); -+ bch2_print_string_as_lines(KERN_ERR, str); - } - - void bch2_print_str(struct bch_fs *c, const char *prefix, const char *str) - { -- __bch2_print_str(c, prefix, str, false); --} -- --void bch2_print_str_nonblocking(struct bch_fs *c, const char *prefix, const char *str) --{ -- __bch2_print_str(c, prefix, str, true); -+ __bch2_print_str(c, prefix, str); - } - - __printf(2, 0) -@@ -215,7 +210,6 @@ static int bch2_dev_alloc(struct bch_fs - static int bch2_dev_sysfs_online(struct bch_fs *, struct bch_dev *); - static void bch2_dev_io_ref_stop(struct bch_dev *, int); - static void __bch2_dev_read_only(struct bch_fs *, struct bch_dev *); --static int bch2_fs_init_rw(struct bch_fs *); - - struct bch_fs *bch2_dev_to_fs(dev_t dev) - { -@@ -799,7 +793,7 @@ err: - return ret; - } - --static int bch2_fs_init_rw(struct bch_fs *c) -+int bch2_fs_init_rw(struct bch_fs *c) - { - if (test_bit(BCH_FS_rw_init_done, &c->flags)) - return 0; -@@ -1020,16 +1014,28 @@ static struct bch_fs *bch2_fs_alloc(stru - if (ret) - goto err; - -+ if (go_rw_in_recovery(c)) { -+ /* -+ * start workqueues/kworkers early - kthread creation checks for -+ * pending signals, which is _very_ annoying -+ */ -+ ret = bch2_fs_init_rw(c); -+ if (ret) -+ goto err; -+ } -+ - #ifdef CONFIG_UNICODE -- /* Default encoding until we can potentially have more as an option. */ -- c->cf_encoding = utf8_load(BCH_FS_DEFAULT_UTF8_ENCODING); -- if (IS_ERR(c->cf_encoding)) { -- printk(KERN_ERR "Cannot load UTF-8 encoding for filesystem. Version: %u.%u.%u", -- unicode_major(BCH_FS_DEFAULT_UTF8_ENCODING), -- unicode_minor(BCH_FS_DEFAULT_UTF8_ENCODING), -- unicode_rev(BCH_FS_DEFAULT_UTF8_ENCODING)); -- ret = -EINVAL; -- goto err; -+ if (bch2_fs_casefold_enabled(c)) { -+ /* Default encoding until we can potentially have more as an option. */ -+ c->cf_encoding = utf8_load(BCH_FS_DEFAULT_UTF8_ENCODING); -+ if (IS_ERR(c->cf_encoding)) { -+ printk(KERN_ERR "Cannot load UTF-8 encoding for filesystem. Version: %u.%u.%u", -+ unicode_major(BCH_FS_DEFAULT_UTF8_ENCODING), -+ unicode_minor(BCH_FS_DEFAULT_UTF8_ENCODING), -+ unicode_rev(BCH_FS_DEFAULT_UTF8_ENCODING)); -+ ret = -EINVAL; -+ goto err; -+ } - } - #else - if (c->sb.features & BIT_ULL(BCH_FEATURE_casefolding)) { -@@ -1072,12 +1078,13 @@ noinline_for_stack - static void print_mount_opts(struct bch_fs *c) - { - enum bch_opt_id i; -- struct printbuf p = PRINTBUF; -- bool first = true; -+ CLASS(printbuf, p)(); -+ bch2_log_msg_start(c, &p); - - prt_str(&p, "starting version "); - bch2_version_to_text(&p, c->sb.version); - -+ bool first = true; - for (i = 0; i < bch2_opts_nr; i++) { - const struct bch_option *opt = &bch2_opt_table[i]; - u64 v = bch2_opt_get_by_id(&c->opts, i); -@@ -1094,17 +1101,24 @@ static void print_mount_opts(struct bch_ - } - - if (c->sb.version_incompat_allowed != c->sb.version) { -- prt_printf(&p, "\n allowing incompatible features above "); -+ prt_printf(&p, "\nallowing incompatible features above "); - bch2_version_to_text(&p, c->sb.version_incompat_allowed); - } - - if (c->opts.verbose) { -- prt_printf(&p, "\n features: "); -+ prt_printf(&p, "\nfeatures: "); - prt_bitflags(&p, bch2_sb_features, c->sb.features); - } - -- bch_info(c, "%s", p.buf); -- printbuf_exit(&p); -+ if (c->sb.multi_device) { -+ prt_printf(&p, "\nwith devices"); -+ for_each_online_member(c, ca, BCH_DEV_READ_REF_bch2_online_devs) { -+ prt_char(&p, ' '); -+ prt_str(&p, ca->name); -+ } -+ } -+ -+ bch2_print_str(c, KERN_INFO, p.buf); - } - - static bool bch2_fs_may_start(struct bch_fs *c) -@@ -1148,12 +1162,11 @@ int bch2_fs_start(struct bch_fs *c) - - print_mount_opts(c); - --#ifdef CONFIG_UNICODE -- bch_info(c, "Using encoding defined by superblock: utf8-%u.%u.%u", -- unicode_major(BCH_FS_DEFAULT_UTF8_ENCODING), -- unicode_minor(BCH_FS_DEFAULT_UTF8_ENCODING), -- unicode_rev(BCH_FS_DEFAULT_UTF8_ENCODING)); --#endif -+ if (c->cf_encoding) -+ bch_info(c, "Using encoding defined by superblock: utf8-%u.%u.%u", -+ unicode_major(BCH_FS_DEFAULT_UTF8_ENCODING), -+ unicode_minor(BCH_FS_DEFAULT_UTF8_ENCODING), -+ unicode_rev(BCH_FS_DEFAULT_UTF8_ENCODING)); - - if (!bch2_fs_may_start(c)) - return bch_err_throw(c, insufficient_devices_to_start); -@@ -1995,6 +2008,22 @@ int bch2_dev_add(struct bch_fs *c, const - goto err_late; - } - -+ /* -+ * We just changed the superblock UUID, invalidate cache and send a -+ * uevent to update /dev/disk/by-uuid -+ */ -+ invalidate_bdev(ca->disk_sb.bdev); -+ -+ char uuid_str[37]; -+ snprintf(uuid_str, sizeof(uuid_str), "UUID=%pUb", &c->sb.uuid); -+ -+ char *envp[] = { -+ "CHANGE=uuid", -+ uuid_str, -+ NULL, -+ }; -+ kobject_uevent_env(&ca->disk_sb.bdev->bd_device.kobj, KOBJ_CHANGE, envp); -+ - up_write(&c->state_lock); - out: - printbuf_exit(&label); -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/super.h BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/super.h ---- BPI-Router-Linux-kernel/fs/bcachefs/super.h 2025-10-22 13:53:23.495327784 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/super.h 2025-10-22 13:53:56.695168274 -0400 -@@ -46,6 +46,7 @@ void __bch2_fs_stop(struct bch_fs *); - void bch2_fs_free(struct bch_fs *); - void bch2_fs_stop(struct bch_fs *); - -+int bch2_fs_init_rw(struct bch_fs *); - int bch2_fs_start(struct bch_fs *); - struct bch_fs *bch2_fs_open(darray_const_str *, struct bch_opts *); - -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/trace.h BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/trace.h ---- BPI-Router-Linux-kernel/fs/bcachefs/trace.h 2025-10-22 13:53:23.495327784 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/trace.h 2025-10-22 13:53:56.695168274 -0400 -@@ -1080,34 +1080,14 @@ TRACE_EVENT(trans_blocked_journal_reclai - __entry->must_wait) - ); - --TRACE_EVENT(trans_restart_journal_preres_get, -- TP_PROTO(struct btree_trans *trans, -- unsigned long caller_ip, -- unsigned flags), -- TP_ARGS(trans, caller_ip, flags), -- -- TP_STRUCT__entry( -- __array(char, trans_fn, 32 ) -- __field(unsigned long, caller_ip ) -- __field(unsigned, flags ) -- ), -- -- TP_fast_assign( -- strscpy(__entry->trans_fn, trans->fn, sizeof(__entry->trans_fn)); -- __entry->caller_ip = caller_ip; -- __entry->flags = flags; -- ), -- -- TP_printk("%s %pS %x", __entry->trans_fn, -- (void *) __entry->caller_ip, -- __entry->flags) --); -- -+#if 0 -+/* todo: bring back dynamic fault injection */ - DEFINE_EVENT(transaction_event, trans_restart_fault_inject, - TP_PROTO(struct btree_trans *trans, - unsigned long caller_ip), - TP_ARGS(trans, caller_ip) - ); -+#endif - - DEFINE_EVENT(transaction_event, trans_traverse_all, - TP_PROTO(struct btree_trans *trans, -@@ -1195,19 +1175,6 @@ DEFINE_EVENT(transaction_restart_iter, t - TP_ARGS(trans, caller_ip, path) - ); - --DEFINE_EVENT(transaction_restart_iter, trans_restart_relock_after_fill, -- TP_PROTO(struct btree_trans *trans, -- unsigned long caller_ip, -- struct btree_path *path), -- TP_ARGS(trans, caller_ip, path) --); -- --DEFINE_EVENT(transaction_event, trans_restart_key_cache_upgrade, -- TP_PROTO(struct btree_trans *trans, -- unsigned long caller_ip), -- TP_ARGS(trans, caller_ip) --); -- - DEFINE_EVENT(transaction_restart_iter, trans_restart_relock_key_cache_fill, - TP_PROTO(struct btree_trans *trans, - unsigned long caller_ip, -@@ -1229,13 +1196,6 @@ DEFINE_EVENT(transaction_restart_iter, t - TP_ARGS(trans, caller_ip, path) - ); - --DEFINE_EVENT(transaction_restart_iter, trans_restart_traverse, -- TP_PROTO(struct btree_trans *trans, -- unsigned long caller_ip, -- struct btree_path *path), -- TP_ARGS(trans, caller_ip, path) --); -- - DEFINE_EVENT(transaction_restart_iter, trans_restart_memory_allocation_failure, - TP_PROTO(struct btree_trans *trans, - unsigned long caller_ip, -@@ -1294,44 +1254,6 @@ TRACE_EVENT(trans_restart_mem_realloced, - __entry->bytes) - ); - --TRACE_EVENT(trans_restart_key_cache_key_realloced, -- TP_PROTO(struct btree_trans *trans, -- unsigned long caller_ip, -- struct btree_path *path, -- unsigned old_u64s, -- unsigned new_u64s), -- TP_ARGS(trans, caller_ip, path, old_u64s, new_u64s), -- -- TP_STRUCT__entry( -- __array(char, trans_fn, 32 ) -- __field(unsigned long, caller_ip ) -- __field(enum btree_id, btree_id ) -- TRACE_BPOS_entries(pos) -- __field(u32, old_u64s ) -- __field(u32, new_u64s ) -- ), -- -- TP_fast_assign( -- strscpy(__entry->trans_fn, trans->fn, sizeof(__entry->trans_fn)); -- __entry->caller_ip = caller_ip; -- -- __entry->btree_id = path->btree_id; -- TRACE_BPOS_assign(pos, path->pos); -- __entry->old_u64s = old_u64s; -- __entry->new_u64s = new_u64s; -- ), -- -- TP_printk("%s %pS btree %s pos %llu:%llu:%u old_u64s %u new_u64s %u", -- __entry->trans_fn, -- (void *) __entry->caller_ip, -- bch2_btree_id_str(__entry->btree_id), -- __entry->pos_inode, -- __entry->pos_offset, -- __entry->pos_snapshot, -- __entry->old_u64s, -- __entry->new_u64s) --); -- - DEFINE_EVENT(transaction_event, trans_restart_write_buffer_flush, - TP_PROTO(struct btree_trans *trans, - unsigned long caller_ip), -@@ -1490,6 +1412,31 @@ DEFINE_EVENT(fs_str, io_move_evacuate_bu - TP_ARGS(c, str) - ); - -+DEFINE_EVENT(fs_str, extent_trim_atomic, -+ TP_PROTO(struct bch_fs *c, const char *str), -+ TP_ARGS(c, str) -+); -+ -+DEFINE_EVENT(fs_str, btree_iter_peek_slot, -+ TP_PROTO(struct bch_fs *c, const char *str), -+ TP_ARGS(c, str) -+); -+ -+DEFINE_EVENT(fs_str, __btree_iter_peek, -+ TP_PROTO(struct bch_fs *c, const char *str), -+ TP_ARGS(c, str) -+); -+ -+DEFINE_EVENT(fs_str, btree_iter_peek_max, -+ TP_PROTO(struct bch_fs *c, const char *str), -+ TP_ARGS(c, str) -+); -+ -+DEFINE_EVENT(fs_str, btree_iter_peek_prev_min, -+ TP_PROTO(struct bch_fs *c, const char *str), -+ TP_ARGS(c, str) -+); -+ - #ifdef CONFIG_BCACHEFS_PATH_TRACEPOINTS - - TRACE_EVENT(update_by_path, -@@ -1902,21 +1849,6 @@ TRACE_EVENT(btree_path_free, - __entry->dup_locked) - ); - --TRACE_EVENT(btree_path_free_trans_begin, -- TP_PROTO(btree_path_idx_t path), -- TP_ARGS(path), -- -- TP_STRUCT__entry( -- __field(btree_path_idx_t, idx ) -- ), -- -- TP_fast_assign( -- __entry->idx = path; -- ), -- -- TP_printk(" path %3u", __entry->idx) --); -- - #else /* CONFIG_BCACHEFS_PATH_TRACEPOINTS */ - #ifndef _TRACE_BCACHEFS_H - -@@ -1934,7 +1866,6 @@ static inline void trace_btree_path_trav - static inline void trace_btree_path_traverse_end(struct btree_trans *trans, struct btree_path *path) {} - static inline void trace_btree_path_set_pos(struct btree_trans *trans, struct btree_path *path, struct bpos *new_pos) {} - static inline void trace_btree_path_free(struct btree_trans *trans, btree_path_idx_t path, struct btree_path *dup) {} --static inline void trace_btree_path_free_trans_begin(btree_path_idx_t path) {} - - #endif - #endif /* CONFIG_BCACHEFS_PATH_TRACEPOINTS */ -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/util.c BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/util.c ---- BPI-Router-Linux-kernel/fs/bcachefs/util.c 2025-10-22 13:53:23.495327784 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/util.c 2025-10-22 13:53:56.695168274 -0400 -@@ -262,8 +262,7 @@ static bool string_is_spaces(const char - return true; - } - --void bch2_print_string_as_lines(const char *prefix, const char *lines, -- bool nonblocking) -+void bch2_print_string_as_lines(const char *prefix, const char *lines) - { - bool locked = false; - const char *p; -@@ -273,12 +272,7 @@ void bch2_print_string_as_lines(const ch - return; - } - -- if (!nonblocking) { -- console_lock(); -- locked = true; -- } else { -- locked = console_trylock(); -- } -+ locked = console_trylock(); - - while (*lines) { - p = strchrnul(lines, '\n'); -diff -purNx .git BPI-Router-Linux-kernel/fs/bcachefs/util.h BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/util.h ---- BPI-Router-Linux-kernel/fs/bcachefs/util.h 2025-10-22 13:53:23.495327784 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/bcachefs/util.h 2025-10-22 13:53:56.695168274 -0400 -@@ -214,7 +214,7 @@ u64 bch2_read_flag_list(const char *, co - void bch2_prt_u64_base2_nbits(struct printbuf *, u64, unsigned); - void bch2_prt_u64_base2(struct printbuf *, u64); - --void bch2_print_string_as_lines(const char *, const char *, bool); -+void bch2_print_string_as_lines(const char *, const char *); - - typedef DARRAY(unsigned long) bch_stacktrace; - int bch2_save_backtrace(bch_stacktrace *stack, struct task_struct *, unsigned, gfp_t); -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/block-group.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/block-group.c ---- BPI-Router-Linux-kernel/fs/btrfs/block-group.c 2025-10-22 13:53:23.495327784 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/block-group.c 2025-10-22 13:53:56.695168274 -0400 -@@ -34,6 +34,19 @@ int btrfs_should_fragment_free_space(con - } - #endif - -+static inline bool has_unwritten_metadata(struct btrfs_block_group *block_group) -+{ -+ /* The meta_write_pointer is available only on the zoned setup. */ -+ if (!btrfs_is_zoned(block_group->fs_info)) -+ return false; -+ -+ if (block_group->flags & BTRFS_BLOCK_GROUP_DATA) -+ return false; -+ -+ return block_group->start + block_group->alloc_offset > -+ block_group->meta_write_pointer; -+} -+ - /* - * Return target flags in extended format or 0 if restripe for this chunk_type - * is not in progress -@@ -1244,6 +1257,15 @@ int btrfs_remove_block_group(struct btrf - goto out; - - spin_lock(&block_group->lock); -+ /* -+ * Hitting this WARN means we removed a block group with an unwritten -+ * region. It will cause "unable to find chunk map for logical" errors. -+ */ -+ if (WARN_ON(has_unwritten_metadata(block_group))) -+ btrfs_warn(fs_info, -+ "block group %llu is removed before metadata write out", -+ block_group->start); -+ - set_bit(BLOCK_GROUP_FLAG_REMOVED, &block_group->runtime_flags); - - /* -@@ -1586,8 +1608,9 @@ void btrfs_delete_unused_bgs(struct btrf - * needing to allocate extents from the block group. - */ - used = btrfs_space_info_used(space_info, true); -- if (space_info->total_bytes - block_group->length < used && -- block_group->zone_unusable < block_group->length) { -+ if ((space_info->total_bytes - block_group->length < used && -+ block_group->zone_unusable < block_group->length) || -+ has_unwritten_metadata(block_group)) { - /* - * Add a reference for the list, compensate for the ref - * drop under the "next" label for the -@@ -1616,8 +1639,10 @@ void btrfs_delete_unused_bgs(struct btrf - ret = btrfs_zone_finish(block_group); - if (ret < 0) { - btrfs_dec_block_group_ro(block_group); -- if (ret == -EAGAIN) -+ if (ret == -EAGAIN) { -+ btrfs_link_bg_list(block_group, &retry_list); - ret = 0; -+ } - goto next; - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/block-group.h BPI-Router-Linux-kernel-6.16.12/fs/btrfs/block-group.h ---- BPI-Router-Linux-kernel/fs/btrfs/block-group.h 2025-10-22 13:53:23.495327784 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/block-group.h 2025-10-22 13:53:56.695168274 -0400 -@@ -83,6 +83,8 @@ enum btrfs_block_group_flags { - BLOCK_GROUP_FLAG_ZONED_DATA_RELOC, - /* Does the block group need to be added to the free space tree? */ - BLOCK_GROUP_FLAG_NEEDS_FREE_SPACE, -+ /* Set after we add a new block group to the free space tree. */ -+ BLOCK_GROUP_FLAG_FREE_SPACE_ADDED, - /* Indicate that the block group is placed on a sequential zone */ - BLOCK_GROUP_FLAG_SEQUENTIAL_ZONE, - /* -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/btrfs_inode.h BPI-Router-Linux-kernel-6.16.12/fs/btrfs/btrfs_inode.h ---- BPI-Router-Linux-kernel/fs/btrfs/btrfs_inode.h 2025-10-22 13:53:23.495327784 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/btrfs_inode.h 2025-10-22 13:53:56.695168274 -0400 -@@ -248,7 +248,7 @@ struct btrfs_inode { - u64 new_delalloc_bytes; - /* - * The offset of the last dir index key that was logged. -- * This is used only for directories. -+ * This is used only for directories. Protected by 'log_mutex'. - */ - u64 last_dir_index_offset; - }; -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/ctree.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/ctree.c ---- BPI-Router-Linux-kernel/fs/btrfs/ctree.c 2025-10-22 13:53:23.495327784 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/ctree.c 2025-10-22 13:53:56.695168274 -0400 -@@ -198,7 +198,7 @@ struct extent_buffer *btrfs_root_node(st - * the inc_not_zero dance and if it doesn't work then - * synchronize_rcu and try again. - */ -- if (atomic_inc_not_zero(&eb->refs)) { -+ if (refcount_inc_not_zero(&eb->refs)) { - rcu_read_unlock(); - break; - } -@@ -283,7 +283,14 @@ int btrfs_copy_root(struct btrfs_trans_h - - write_extent_buffer_fsid(cow, fs_info->fs_devices->metadata_uuid); - -- WARN_ON(btrfs_header_generation(buf) > trans->transid); -+ if (unlikely(btrfs_header_generation(buf) > trans->transid)) { -+ btrfs_tree_unlock(cow); -+ free_extent_buffer(cow); -+ ret = -EUCLEAN; -+ btrfs_abort_transaction(trans, ret); -+ return ret; -+ } -+ - if (new_root_objectid == BTRFS_TREE_RELOC_OBJECTID) - ret = btrfs_inc_ref(trans, root, cow, 1); - else -@@ -549,7 +556,7 @@ int btrfs_force_cow_block(struct btrfs_t - btrfs_abort_transaction(trans, ret); - goto error_unlock_cow; - } -- atomic_inc(&cow->refs); -+ refcount_inc(&cow->refs); - rcu_assign_pointer(root->node, cow); - - ret = btrfs_free_tree_block(trans, btrfs_root_id(root), buf, -@@ -1081,7 +1088,7 @@ static noinline int balance_level(struct - /* update the path */ - if (left) { - if (btrfs_header_nritems(left) > orig_slot) { -- atomic_inc(&left->refs); -+ refcount_inc(&left->refs); - /* left was locked after cow */ - path->nodes[level] = left; - path->slots[level + 1] -= 1; -@@ -1685,7 +1692,7 @@ static struct extent_buffer *btrfs_searc - - if (p->search_commit_root) { - b = root->commit_root; -- atomic_inc(&b->refs); -+ refcount_inc(&b->refs); - level = btrfs_header_level(b); - /* - * Ensure that all callers have set skip_locking when -@@ -2872,6 +2879,7 @@ static noinline int insert_new_root(stru - if (ret < 0) { - int ret2; - -+ btrfs_clear_buffer_dirty(trans, c); - ret2 = btrfs_free_tree_block(trans, btrfs_root_id(root), c, 0, 1); - if (ret2 < 0) - btrfs_abort_transaction(trans, ret2); -@@ -2885,7 +2893,7 @@ static noinline int insert_new_root(stru - free_extent_buffer(old); - - add_root_to_dirty_list(root); -- atomic_inc(&c->refs); -+ refcount_inc(&c->refs); - path->nodes[level] = c; - path->locks[level] = BTRFS_WRITE_LOCK; - path->slots[level] = 0; -@@ -4442,7 +4450,7 @@ static noinline int btrfs_del_leaf(struc - - root_sub_used_bytes(root); - -- atomic_inc(&leaf->refs); -+ refcount_inc(&leaf->refs); - ret = btrfs_free_tree_block(trans, btrfs_root_id(root), leaf, 0, 1); - free_extent_buffer_stale(leaf); - if (ret < 0) -@@ -4527,7 +4535,7 @@ int btrfs_del_items(struct btrfs_trans_h - * for possible call to btrfs_del_ptr below - */ - slot = path->slots[1]; -- atomic_inc(&leaf->refs); -+ refcount_inc(&leaf->refs); - /* - * We want to be able to at least push one item to the - * left neighbour leaf, and that's the first item. -@@ -4585,16 +4593,13 @@ int btrfs_del_items(struct btrfs_trans_h - - /* - * A helper function to walk down the tree starting at min_key, and looking -- * for nodes or leaves that are have a minimum transaction id. -+ * for leaves that have a minimum transaction id. - * This is used by the btree defrag code, and tree logging - * - * This does not cow, but it does stuff the starting key it finds back - * into min_key, so you can call btrfs_search_slot with cow=1 on the - * key and get a writable path. - * -- * This honors path->lowest_level to prevent descent past a given level -- * of the tree. -- * - * min_trans indicates the oldest transaction that you are interested - * in walking through. Any nodes or leaves older than min_trans are - * skipped over (without reading them). -@@ -4615,6 +4620,7 @@ int btrfs_search_forward(struct btrfs_ro - int keep_locks = path->keep_locks; - - ASSERT(!path->nowait); -+ ASSERT(path->lowest_level == 0); - path->keep_locks = 1; - again: - cur = btrfs_read_lock_root_node(root); -@@ -4636,8 +4642,8 @@ again: - goto out; - } - -- /* at the lowest level, we're done, setup the path and exit */ -- if (level == path->lowest_level) { -+ /* At level 0 we're done, setup the path and exit. */ -+ if (level == 0) { - if (slot >= nritems) - goto find_next_key; - ret = 0; -@@ -4678,12 +4684,6 @@ find_next_key: - goto out; - } - } -- if (level == path->lowest_level) { -- ret = 0; -- /* Save our key for returning back. */ -- btrfs_node_key_to_cpu(cur, min_key, slot); -- goto out; -- } - cur = btrfs_read_node_slot(cur, slot); - if (IS_ERR(cur)) { - ret = PTR_ERR(cur); -@@ -4699,7 +4699,7 @@ find_next_key: - out: - path->keep_locks = keep_locks; - if (ret == 0) -- btrfs_unlock_up_safe(path, path->lowest_level + 1); -+ btrfs_unlock_up_safe(path, 1); - return ret; - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/delayed-inode.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/delayed-inode.c ---- BPI-Router-Linux-kernel/fs/btrfs/delayed-inode.c 2025-10-22 13:53:23.495327784 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/delayed-inode.c 2025-10-22 13:53:56.695168274 -0400 -@@ -1377,7 +1377,10 @@ static int btrfs_wq_run_delayed_node(str - - void btrfs_assert_delayed_root_empty(struct btrfs_fs_info *fs_info) - { -- WARN_ON(btrfs_first_delayed_node(fs_info->delayed_root)); -+ struct btrfs_delayed_node *node = btrfs_first_delayed_node(fs_info->delayed_root); -+ -+ if (WARN_ON(node)) -+ refcount_dec(&node->refs); - } - - static bool could_end_wait(struct btrfs_delayed_root *delayed_root, int seq) -@@ -1840,7 +1843,6 @@ static void fill_stack_inode_item(struct - - int btrfs_fill_inode(struct btrfs_inode *inode, u32 *rdev) - { -- struct btrfs_fs_info *fs_info = inode->root->fs_info; - struct btrfs_delayed_node *delayed_node; - struct btrfs_inode_item *inode_item; - struct inode *vfs_inode = &inode->vfs_inode; -@@ -1861,8 +1863,6 @@ int btrfs_fill_inode(struct btrfs_inode - i_uid_write(vfs_inode, btrfs_stack_inode_uid(inode_item)); - i_gid_write(vfs_inode, btrfs_stack_inode_gid(inode_item)); - btrfs_i_size_write(inode, btrfs_stack_inode_size(inode_item)); -- btrfs_inode_set_file_extent_range(inode, 0, -- round_up(i_size_read(vfs_inode), fs_info->sectorsize)); - vfs_inode->i_mode = btrfs_stack_inode_mode(inode_item); - set_nlink(vfs_inode, btrfs_stack_inode_nlink(inode_item)); - inode_set_bytes(vfs_inode, btrfs_stack_inode_nbytes(inode_item)); -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/disk-io.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/disk-io.c ---- BPI-Router-Linux-kernel/fs/btrfs/disk-io.c 2025-10-22 13:53:23.495327784 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/disk-io.c 2025-10-22 13:53:56.699168255 -0400 -@@ -1835,6 +1835,8 @@ void btrfs_put_root(struct btrfs_root *r - if (refcount_dec_and_test(&root->refs)) { - if (WARN_ON(!xa_empty(&root->inodes))) - xa_destroy(&root->inodes); -+ if (WARN_ON(!xa_empty(&root->delayed_nodes))) -+ xa_destroy(&root->delayed_nodes); - WARN_ON(test_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state)); - if (root->anon_dev) - free_anon_bdev(root->anon_dev); -@@ -2156,8 +2158,7 @@ static int load_global_roots_objectid(st - found = true; - root = read_tree_root_path(tree_root, path, &key); - if (IS_ERR(root)) { -- if (!btrfs_test_opt(fs_info, IGNOREBADROOTS)) -- ret = PTR_ERR(root); -+ ret = PTR_ERR(root); - break; - } - set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state); -@@ -3560,6 +3561,7 @@ int __cold open_ctree(struct super_block - goto fail_sysfs; - } - -+ btrfs_zoned_reserve_data_reloc_bg(fs_info); - btrfs_free_zone_cache(fs_info); - - btrfs_check_active_zone_reservation(fs_info); -@@ -4310,8 +4312,8 @@ void __cold close_ctree(struct btrfs_fs_ - * - * So wait for all ongoing ordered extents to complete and then run - * delayed iputs. This works because once we reach this point no one -- * can either create new ordered extents nor create delayed iputs -- * through some other means. -+ * can create new ordered extents, but delayed iputs can still be added -+ * by a reclaim worker (see comments further below). - * - * Also note that btrfs_wait_ordered_roots() is not safe here, because - * it waits for BTRFS_ORDERED_COMPLETE to be set on an ordered extent, -@@ -4322,15 +4324,29 @@ void __cold close_ctree(struct btrfs_fs_ - btrfs_flush_workqueue(fs_info->endio_write_workers); - /* Ordered extents for free space inodes. */ - btrfs_flush_workqueue(fs_info->endio_freespace_worker); -+ /* -+ * Run delayed iputs in case an async reclaim worker is waiting for them -+ * to be run as mentioned above. -+ */ - btrfs_run_delayed_iputs(fs_info); -- /* There should be no more workload to generate new delayed iputs. */ -- set_bit(BTRFS_FS_STATE_NO_DELAYED_IPUT, &fs_info->fs_state); - - cancel_work_sync(&fs_info->async_reclaim_work); - cancel_work_sync(&fs_info->async_data_reclaim_work); - cancel_work_sync(&fs_info->preempt_reclaim_work); - cancel_work_sync(&fs_info->em_shrinker_work); - -+ /* -+ * Run delayed iputs again because an async reclaim worker may have -+ * added new ones if it was flushing delalloc: -+ * -+ * shrink_delalloc() -> btrfs_start_delalloc_roots() -> -+ * start_delalloc_inodes() -> btrfs_add_delayed_iput() -+ */ -+ btrfs_run_delayed_iputs(fs_info); -+ -+ /* There should be no more workload to generate new delayed iputs. */ -+ set_bit(BTRFS_FS_STATE_NO_DELAYED_IPUT, &fs_info->fs_state); -+ - /* Cancel or finish ongoing discard work */ - btrfs_discard_cleanup(fs_info); - -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/extent_io.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/extent_io.c ---- BPI-Router-Linux-kernel/fs/btrfs/extent_io.c 2025-10-22 13:53:23.499327765 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/extent_io.c 2025-10-22 13:53:56.699168255 -0400 -@@ -77,7 +77,7 @@ void btrfs_extent_buffer_leak_debug_chec - struct extent_buffer, leak_list); - pr_err( - "BTRFS: buffer leak start %llu len %u refs %d bflags %lu owner %llu\n", -- eb->start, eb->len, atomic_read(&eb->refs), eb->bflags, -+ eb->start, eb->len, refcount_read(&eb->refs), eb->bflags, - btrfs_header_owner(eb)); - list_del(&eb->leak_list); - WARN_ON_ONCE(1); -@@ -110,6 +110,25 @@ struct btrfs_bio_ctrl { - * This is to avoid touching ranges covered by compression/inline. - */ - unsigned long submit_bitmap; -+ struct readahead_control *ractl; -+ -+ /* -+ * The start offset of the last used extent map by a read operation. -+ * -+ * This is for proper compressed read merge. -+ * U64_MAX means we are starting the read and have made no progress yet. -+ * -+ * The current btrfs_bio_is_contig() only uses disk_bytenr as -+ * the condition to check if the read can be merged with previous -+ * bio, which is not correct. E.g. two file extents pointing to the -+ * same extent but with different offset. -+ * -+ * So here we need to do extra checks to only merge reads that are -+ * covered by the same extent map. -+ * Just extent_map::start will be enough, as they are unique -+ * inside the same inode. -+ */ -+ u64 last_em_start; - }; - - static void submit_one_bio(struct btrfs_bio_ctrl *bio_ctrl) -@@ -782,7 +801,7 @@ static void submit_extent_folio(struct b - - static int attach_extent_buffer_folio(struct extent_buffer *eb, - struct folio *folio, -- struct btrfs_subpage *prealloc) -+ struct btrfs_folio_state *prealloc) - { - struct btrfs_fs_info *fs_info = eb->fs_info; - int ret = 0; -@@ -806,7 +825,7 @@ static int attach_extent_buffer_folio(st - - /* Already mapped, just free prealloc */ - if (folio_test_private(folio)) { -- btrfs_free_subpage(prealloc); -+ btrfs_free_folio_state(prealloc); - return 0; - } - -@@ -815,7 +834,7 @@ static int attach_extent_buffer_folio(st - folio_attach_private(folio, prealloc); - else - /* Do new allocation to attach subpage */ -- ret = btrfs_attach_subpage(fs_info, folio, BTRFS_SUBPAGE_METADATA); -+ ret = btrfs_attach_folio_state(fs_info, folio, BTRFS_SUBPAGE_METADATA); - return ret; - } - -@@ -831,7 +850,7 @@ int set_folio_extent_mapped(struct folio - fs_info = folio_to_fs_info(folio); - - if (btrfs_is_subpage(fs_info, folio)) -- return btrfs_attach_subpage(fs_info, folio, BTRFS_SUBPAGE_DATA); -+ return btrfs_attach_folio_state(fs_info, folio, BTRFS_SUBPAGE_DATA); - - folio_attach_private(folio, (void *)EXTENT_FOLIO_PRIVATE); - return 0; -@@ -848,7 +867,7 @@ void clear_folio_extent_mapped(struct fo - - fs_info = folio_to_fs_info(folio); - if (btrfs_is_subpage(fs_info, folio)) -- return btrfs_detach_subpage(fs_info, folio, BTRFS_SUBPAGE_DATA); -+ return btrfs_detach_folio_state(fs_info, folio, BTRFS_SUBPAGE_DATA); - - folio_detach_private(folio); - } -@@ -882,6 +901,25 @@ static struct extent_map *get_extent_map - - return em; - } -+ -+static void btrfs_readahead_expand(struct readahead_control *ractl, -+ const struct extent_map *em) -+{ -+ const u64 ra_pos = readahead_pos(ractl); -+ const u64 ra_end = ra_pos + readahead_length(ractl); -+ const u64 em_end = em->start + em->ram_bytes; -+ -+ /* No expansion for holes and inline extents. */ -+ if (em->disk_bytenr > EXTENT_MAP_LAST_BYTE) -+ return; -+ -+ ASSERT(em_end >= ra_pos, -+ "extent_map %llu %llu ends before current readahead position %llu", -+ em->start, em->len, ra_pos); -+ if (em_end > ra_end) -+ readahead_expand(ractl, ra_pos, em_end - ra_pos); -+} -+ - /* - * basic readpage implementation. Locked extent state structs are inserted - * into the tree that are removed when the IO is done (by the end_io -@@ -890,7 +928,7 @@ static struct extent_map *get_extent_map - * return 0 on success, otherwise return error - */ - static int btrfs_do_readpage(struct folio *folio, struct extent_map **em_cached, -- struct btrfs_bio_ctrl *bio_ctrl, u64 *prev_em_start) -+ struct btrfs_bio_ctrl *bio_ctrl) - { - struct inode *inode = folio->mapping->host; - struct btrfs_fs_info *fs_info = inode_to_fs_info(inode); -@@ -945,6 +983,16 @@ static int btrfs_do_readpage(struct foli - - compress_type = btrfs_extent_map_compression(em); - -+ /* -+ * Only expand readahead for extents which are already creating -+ * the pages anyway in add_ra_bio_pages, which is compressed -+ * extents in the non subpage case. -+ */ -+ if (bio_ctrl->ractl && -+ !btrfs_is_subpage(fs_info, folio) && -+ compress_type != BTRFS_COMPRESS_NONE) -+ btrfs_readahead_expand(bio_ctrl->ractl, em); -+ - if (compress_type != BTRFS_COMPRESS_NONE) - disk_bytenr = em->disk_bytenr; - else -@@ -990,12 +1038,11 @@ static int btrfs_do_readpage(struct foli - * non-optimal behavior (submitting 2 bios for the same extent). - */ - if (compress_type != BTRFS_COMPRESS_NONE && -- prev_em_start && *prev_em_start != (u64)-1 && -- *prev_em_start != em->start) -+ bio_ctrl->last_em_start != U64_MAX && -+ bio_ctrl->last_em_start != em->start) - force_bio_submit = true; - -- if (prev_em_start) -- *prev_em_start = em->start; -+ bio_ctrl->last_em_start = em->start; - - btrfs_free_extent_map(em); - em = NULL; -@@ -1209,12 +1256,15 @@ int btrfs_read_folio(struct file *file, - const u64 start = folio_pos(folio); - const u64 end = start + folio_size(folio) - 1; - struct extent_state *cached_state = NULL; -- struct btrfs_bio_ctrl bio_ctrl = { .opf = REQ_OP_READ }; -+ struct btrfs_bio_ctrl bio_ctrl = { -+ .opf = REQ_OP_READ, -+ .last_em_start = U64_MAX, -+ }; - struct extent_map *em_cached = NULL; - int ret; - - lock_extents_for_read(inode, start, end, &cached_state); -- ret = btrfs_do_readpage(folio, &em_cached, &bio_ctrl, NULL); -+ ret = btrfs_do_readpage(folio, &em_cached, &bio_ctrl); - btrfs_unlock_extent(&inode->io_tree, start, end, &cached_state); - - btrfs_free_extent_map(em_cached); -@@ -1483,7 +1533,7 @@ out: - - /* - * Return 0 if we have submitted or queued the sector for submission. -- * Return <0 for critical errors. -+ * Return <0 for critical errors, and the sector will have its dirty flag cleared. - * - * Caller should make sure filepos < i_size and handle filepos >= i_size case. - */ -@@ -1506,8 +1556,17 @@ static int submit_one_sector(struct btrf - ASSERT(filepos < i_size); - - em = btrfs_get_extent(inode, NULL, filepos, sectorsize); -- if (IS_ERR(em)) -+ if (IS_ERR(em)) { -+ /* -+ * When submission failed, we should still clear the folio dirty. -+ * Or the folio will be written back again but without any -+ * ordered extent. -+ */ -+ btrfs_folio_clear_dirty(fs_info, folio, filepos, sectorsize); -+ btrfs_folio_set_writeback(fs_info, folio, filepos, sectorsize); -+ btrfs_folio_clear_writeback(fs_info, folio, filepos, sectorsize); - return PTR_ERR(em); -+ } - - extent_offset = filepos - em->start; - em_end = btrfs_extent_map_end(em); -@@ -1637,8 +1696,8 @@ static noinline_for_stack int extent_wri - * Here we set writeback and clear for the range. If the full folio - * is no longer dirty then we clear the PAGECACHE_TAG_DIRTY tag. - * -- * If we hit any error, the corresponding sector will still be dirty -- * thus no need to clear PAGECACHE_TAG_DIRTY. -+ * If we hit any error, the corresponding sector will have its dirty -+ * flag cleared and writeback finished, thus no need to handle the error case. - */ - if (!submitted_io && !error) { - btrfs_folio_set_writeback(fs_info, folio, start, len); -@@ -1961,7 +2020,7 @@ retry: - if (!eb) - return NULL; - -- if (!atomic_inc_not_zero(&eb->refs)) { -+ if (!refcount_inc_not_zero(&eb->refs)) { - xas_reset(xas); - goto retry; - } -@@ -2012,7 +2071,7 @@ static struct extent_buffer *find_extent - - rcu_read_lock(); - eb = xa_load(&fs_info->buffer_tree, index); -- if (eb && !atomic_inc_not_zero(&eb->refs)) -+ if (eb && !refcount_inc_not_zero(&eb->refs)) - eb = NULL; - rcu_read_unlock(); - return eb; -@@ -2541,19 +2600,22 @@ int btrfs_writepages(struct address_spac - - void btrfs_readahead(struct readahead_control *rac) - { -- struct btrfs_bio_ctrl bio_ctrl = { .opf = REQ_OP_READ | REQ_RAHEAD }; -+ struct btrfs_bio_ctrl bio_ctrl = { -+ .opf = REQ_OP_READ | REQ_RAHEAD, -+ .ractl = rac, -+ .last_em_start = U64_MAX, -+ }; - struct folio *folio; - struct btrfs_inode *inode = BTRFS_I(rac->mapping->host); - const u64 start = readahead_pos(rac); - const u64 end = start + readahead_length(rac) - 1; - struct extent_state *cached_state = NULL; - struct extent_map *em_cached = NULL; -- u64 prev_em_start = (u64)-1; - - lock_extents_for_read(inode, start, end, &cached_state); - - while ((folio = readahead_folio(rac)) != NULL) -- btrfs_do_readpage(folio, &em_cached, &bio_ctrl, &prev_em_start); -+ btrfs_do_readpage(folio, &em_cached, &bio_ctrl); - - btrfs_unlock_extent(&inode->io_tree, start, end, &cached_state); - -@@ -2731,13 +2793,13 @@ static int extent_buffer_under_io(const - - static bool folio_range_has_eb(struct folio *folio) - { -- struct btrfs_subpage *subpage; -+ struct btrfs_folio_state *bfs; - - lockdep_assert_held(&folio->mapping->i_private_lock); - - if (folio_test_private(folio)) { -- subpage = folio_get_private(folio); -- if (atomic_read(&subpage->eb_refs)) -+ bfs = folio_get_private(folio); -+ if (atomic_read(&bfs->eb_refs)) - return true; - } - return false; -@@ -2787,7 +2849,7 @@ static void detach_extent_buffer_folio(c - * attached to one dummy eb, no sharing. - */ - if (!mapped) { -- btrfs_detach_subpage(fs_info, folio, BTRFS_SUBPAGE_METADATA); -+ btrfs_detach_folio_state(fs_info, folio, BTRFS_SUBPAGE_METADATA); - return; - } - -@@ -2798,7 +2860,7 @@ static void detach_extent_buffer_folio(c - * page range and no unfinished IO. - */ - if (!folio_range_has_eb(folio)) -- btrfs_detach_subpage(fs_info, folio, BTRFS_SUBPAGE_METADATA); -+ btrfs_detach_folio_state(fs_info, folio, BTRFS_SUBPAGE_METADATA); - - spin_unlock(&mapping->i_private_lock); - } -@@ -2842,7 +2904,7 @@ static struct extent_buffer *__alloc_ext - btrfs_leak_debug_add_eb(eb); - - spin_lock_init(&eb->refs_lock); -- atomic_set(&eb->refs, 1); -+ refcount_set(&eb->refs, 1); - - ASSERT(eb->len <= BTRFS_MAX_METADATA_BLOCKSIZE); - -@@ -2975,13 +3037,13 @@ static void check_buffer_tree_ref(struct - * once io is initiated, TREE_REF can no longer be cleared, so that is - * the moment at which any such race is best fixed. - */ -- refs = atomic_read(&eb->refs); -+ refs = refcount_read(&eb->refs); - if (refs >= 2 && test_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags)) - return; - - spin_lock(&eb->refs_lock); - if (!test_and_set_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags)) -- atomic_inc(&eb->refs); -+ refcount_inc(&eb->refs); - spin_unlock(&eb->refs_lock); - } - -@@ -3047,7 +3109,7 @@ again: - return ERR_PTR(ret); - } - if (exists) { -- if (!atomic_inc_not_zero(&exists->refs)) { -+ if (!refcount_inc_not_zero(&exists->refs)) { - /* The extent buffer is being freed, retry. */ - xa_unlock_irq(&fs_info->buffer_tree); - goto again; -@@ -3092,7 +3154,7 @@ static struct extent_buffer *grab_extent - * just overwrite folio private. - */ - exists = folio_get_private(folio); -- if (atomic_inc_not_zero(&exists->refs)) -+ if (refcount_inc_not_zero(&exists->refs)) - return exists; - - WARN_ON(folio_test_dirty(folio)); -@@ -3141,7 +3203,7 @@ static bool check_eb_alignment(struct bt - * The caller needs to free the existing folios and retry using the same order. - */ - static int attach_eb_folio_to_filemap(struct extent_buffer *eb, int i, -- struct btrfs_subpage *prealloc, -+ struct btrfs_folio_state *prealloc, - struct extent_buffer **found_eb_ret) - { - -@@ -3224,7 +3286,7 @@ struct extent_buffer *alloc_extent_buffe - int attached = 0; - struct extent_buffer *eb; - struct extent_buffer *existing_eb = NULL; -- struct btrfs_subpage *prealloc = NULL; -+ struct btrfs_folio_state *prealloc = NULL; - u64 lockdep_owner = owner_root; - bool page_contig = true; - int uptodate = 1; -@@ -3269,7 +3331,7 @@ struct extent_buffer *alloc_extent_buffe - * manually if we exit earlier. - */ - if (btrfs_meta_is_subpage(fs_info)) { -- prealloc = btrfs_alloc_subpage(fs_info, PAGE_SIZE, BTRFS_SUBPAGE_METADATA); -+ prealloc = btrfs_alloc_folio_state(fs_info, PAGE_SIZE, BTRFS_SUBPAGE_METADATA); - if (IS_ERR(prealloc)) { - ret = PTR_ERR(prealloc); - goto out; -@@ -3280,7 +3342,7 @@ reallocate: - /* Allocate all pages first. */ - ret = alloc_eb_folio_array(eb, true); - if (ret < 0) { -- btrfs_free_subpage(prealloc); -+ btrfs_free_folio_state(prealloc); - goto out; - } - -@@ -3362,7 +3424,7 @@ again: - goto out; - } - if (existing_eb) { -- if (!atomic_inc_not_zero(&existing_eb->refs)) { -+ if (!refcount_inc_not_zero(&existing_eb->refs)) { - xa_unlock_irq(&fs_info->buffer_tree); - goto again; - } -@@ -3391,7 +3453,7 @@ again: - return eb; - - out: -- WARN_ON(!atomic_dec_and_test(&eb->refs)); -+ WARN_ON(!refcount_dec_and_test(&eb->refs)); - - /* - * Any attached folios need to be detached before we unlock them. This -@@ -3437,8 +3499,7 @@ static int release_extent_buffer(struct - { - lockdep_assert_held(&eb->refs_lock); - -- WARN_ON(atomic_read(&eb->refs) == 0); -- if (atomic_dec_and_test(&eb->refs)) { -+ if (refcount_dec_and_test(&eb->refs)) { - struct btrfs_fs_info *fs_info = eb->fs_info; - - spin_unlock(&eb->refs_lock); -@@ -3484,22 +3545,26 @@ void free_extent_buffer(struct extent_bu - if (!eb) - return; - -- refs = atomic_read(&eb->refs); -+ refs = refcount_read(&eb->refs); - while (1) { -- if ((!test_bit(EXTENT_BUFFER_UNMAPPED, &eb->bflags) && refs <= 3) -- || (test_bit(EXTENT_BUFFER_UNMAPPED, &eb->bflags) && -- refs == 1)) -+ if (test_bit(EXTENT_BUFFER_UNMAPPED, &eb->bflags)) { -+ if (refs == 1) -+ break; -+ } else if (refs <= 3) { - break; -- if (atomic_try_cmpxchg(&eb->refs, &refs, refs - 1)) -+ } -+ -+ /* Optimization to avoid locking eb->refs_lock. */ -+ if (atomic_try_cmpxchg(&eb->refs.refs, &refs, refs - 1)) - return; - } - - spin_lock(&eb->refs_lock); -- if (atomic_read(&eb->refs) == 2 && -+ if (refcount_read(&eb->refs) == 2 && - test_bit(EXTENT_BUFFER_STALE, &eb->bflags) && - !extent_buffer_under_io(eb) && - test_and_clear_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags)) -- atomic_dec(&eb->refs); -+ refcount_dec(&eb->refs); - - /* - * I know this is terrible, but it's temporary until we stop tracking -@@ -3516,9 +3581,9 @@ void free_extent_buffer_stale(struct ext - spin_lock(&eb->refs_lock); - set_bit(EXTENT_BUFFER_STALE, &eb->bflags); - -- if (atomic_read(&eb->refs) == 2 && !extent_buffer_under_io(eb) && -+ if (refcount_read(&eb->refs) == 2 && !extent_buffer_under_io(eb) && - test_and_clear_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags)) -- atomic_dec(&eb->refs); -+ refcount_dec(&eb->refs); - release_extent_buffer(eb); - } - -@@ -3576,7 +3641,7 @@ void btrfs_clear_buffer_dirty(struct btr - btree_clear_folio_dirty_tag(folio); - folio_unlock(folio); - } -- WARN_ON(atomic_read(&eb->refs) == 0); -+ WARN_ON(refcount_read(&eb->refs) == 0); - } - - void set_extent_buffer_dirty(struct extent_buffer *eb) -@@ -3587,7 +3652,7 @@ void set_extent_buffer_dirty(struct exte - - was_dirty = test_and_set_bit(EXTENT_BUFFER_DIRTY, &eb->bflags); - -- WARN_ON(atomic_read(&eb->refs) == 0); -+ WARN_ON(refcount_read(&eb->refs) == 0); - WARN_ON(!test_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags)); - WARN_ON(test_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags)); - -@@ -3713,7 +3778,7 @@ int read_extent_buffer_pages_nowait(stru - - eb->read_mirror = 0; - check_buffer_tree_ref(eb); -- atomic_inc(&eb->refs); -+ refcount_inc(&eb->refs); - - bbio = btrfs_bio_alloc(INLINE_EXTENT_BUFFER_PAGES, - REQ_OP_READ | REQ_META, eb->fs_info, -@@ -4301,18 +4366,20 @@ static int try_release_subpage_extent_bu - unsigned long end = index + (PAGE_SIZE >> fs_info->sectorsize_bits) - 1; - int ret; - -- xa_lock_irq(&fs_info->buffer_tree); -+ rcu_read_lock(); - xa_for_each_range(&fs_info->buffer_tree, index, eb, start, end) { - /* - * The same as try_release_extent_buffer(), to ensure the eb - * won't disappear out from under us. - */ - spin_lock(&eb->refs_lock); -- if (atomic_read(&eb->refs) != 1 || extent_buffer_under_io(eb)) { -+ rcu_read_unlock(); -+ -+ if (refcount_read(&eb->refs) != 1 || extent_buffer_under_io(eb)) { - spin_unlock(&eb->refs_lock); -+ rcu_read_lock(); - continue; - } -- xa_unlock_irq(&fs_info->buffer_tree); - - /* - * If tree ref isn't set then we know the ref on this eb is a -@@ -4330,9 +4397,9 @@ static int try_release_subpage_extent_bu - * release_extent_buffer() will release the refs_lock. - */ - release_extent_buffer(eb); -- xa_lock_irq(&fs_info->buffer_tree); -+ rcu_read_lock(); - } -- xa_unlock_irq(&fs_info->buffer_tree); -+ rcu_read_unlock(); - - /* - * Finally to check if we have cleared folio private, as if we have -@@ -4345,7 +4412,6 @@ static int try_release_subpage_extent_bu - ret = 0; - spin_unlock(&folio->mapping->i_private_lock); - return ret; -- - } - - int try_release_extent_buffer(struct folio *folio) -@@ -4374,7 +4440,7 @@ int try_release_extent_buffer(struct fol - * this page. - */ - spin_lock(&eb->refs_lock); -- if (atomic_read(&eb->refs) != 1 || extent_buffer_under_io(eb)) { -+ if (refcount_read(&eb->refs) != 1 || extent_buffer_under_io(eb)) { - spin_unlock(&eb->refs_lock); - spin_unlock(&folio->mapping->i_private_lock); - return 0; -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/extent_io.h BPI-Router-Linux-kernel-6.16.12/fs/btrfs/extent_io.h ---- BPI-Router-Linux-kernel/fs/btrfs/extent_io.h 2025-10-22 13:53:23.499327765 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/extent_io.h 2025-10-22 13:53:56.699168255 -0400 -@@ -98,7 +98,7 @@ struct extent_buffer { - void *addr; - - spinlock_t refs_lock; -- atomic_t refs; -+ refcount_t refs; - int read_mirror; - /* >= 0 if eb belongs to a log tree, -1 otherwise */ - s8 log_index; -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/extent-tree.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/extent-tree.c ---- BPI-Router-Linux-kernel/fs/btrfs/extent-tree.c 2025-10-22 13:53:23.499327765 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/extent-tree.c 2025-10-22 13:53:56.699168255 -0400 -@@ -3649,6 +3649,21 @@ btrfs_release_block_group(struct btrfs_b - btrfs_put_block_group(cache); - } - -+static bool find_free_extent_check_size_class(const struct find_free_extent_ctl *ffe_ctl, -+ const struct btrfs_block_group *bg) -+{ -+ if (ffe_ctl->policy == BTRFS_EXTENT_ALLOC_ZONED) -+ return true; -+ if (!btrfs_block_group_should_use_size_class(bg)) -+ return true; -+ if (ffe_ctl->loop >= LOOP_WRONG_SIZE_CLASS) -+ return true; -+ if (ffe_ctl->loop >= LOOP_UNSET_SIZE_CLASS && -+ bg->size_class == BTRFS_BG_SZ_NONE) -+ return true; -+ return ffe_ctl->size_class == bg->size_class; -+} -+ - /* - * Helper function for find_free_extent(). - * -@@ -3670,7 +3685,8 @@ static int find_free_extent_clustered(st - if (!cluster_bg) - goto refill_cluster; - if (cluster_bg != bg && (cluster_bg->ro || -- !block_group_bits(cluster_bg, ffe_ctl->flags))) -+ !block_group_bits(cluster_bg, ffe_ctl->flags) || -+ !find_free_extent_check_size_class(ffe_ctl, cluster_bg))) - goto release_cluster; - - offset = btrfs_alloc_from_cluster(cluster_bg, last_ptr, -@@ -4227,21 +4243,6 @@ static int find_free_extent_update_loop( - return -ENOSPC; - } - --static bool find_free_extent_check_size_class(struct find_free_extent_ctl *ffe_ctl, -- struct btrfs_block_group *bg) --{ -- if (ffe_ctl->policy == BTRFS_EXTENT_ALLOC_ZONED) -- return true; -- if (!btrfs_block_group_should_use_size_class(bg)) -- return true; -- if (ffe_ctl->loop >= LOOP_WRONG_SIZE_CLASS) -- return true; -- if (ffe_ctl->loop >= LOOP_UNSET_SIZE_CLASS && -- bg->size_class == BTRFS_BG_SZ_NONE) -- return true; -- return ffe_ctl->size_class == bg->size_class; --} -- - static int prepare_allocation_clustered(struct btrfs_fs_info *fs_info, - struct find_free_extent_ctl *ffe_ctl, - struct btrfs_space_info *space_info, -@@ -6341,7 +6342,7 @@ int btrfs_drop_subtree(struct btrfs_tran - - btrfs_assert_tree_write_locked(parent); - parent_level = btrfs_header_level(parent); -- atomic_inc(&parent->refs); -+ refcount_inc(&parent->refs); - path->nodes[parent_level] = parent; - path->slots[parent_level] = btrfs_header_nritems(parent); - -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/fiemap.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/fiemap.c ---- BPI-Router-Linux-kernel/fs/btrfs/fiemap.c 2025-10-22 13:53:23.499327765 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/fiemap.c 2025-10-22 13:53:56.699168255 -0400 -@@ -320,7 +320,7 @@ static int fiemap_next_leaf_item(struct - * the cost of allocating a new one. - */ - ASSERT(test_bit(EXTENT_BUFFER_UNMAPPED, &clone->bflags)); -- atomic_inc(&clone->refs); -+ refcount_inc(&clone->refs); - - ret = btrfs_next_leaf(inode->root, path); - if (ret != 0) -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/file.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/file.c ---- BPI-Router-Linux-kernel/fs/btrfs/file.c 2025-10-22 13:53:23.499327765 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/file.c 2025-10-22 13:53:56.699168255 -0400 -@@ -1842,6 +1842,7 @@ static vm_fault_t btrfs_page_mkwrite(str - loff_t size; - size_t fsize = folio_size(folio); - int ret; -+ bool only_release_metadata = false; - u64 reserved_space; - u64 page_start; - u64 page_end; -@@ -1862,10 +1863,34 @@ static vm_fault_t btrfs_page_mkwrite(str - * end up waiting indefinitely to get a lock on the page currently - * being processed by btrfs_page_mkwrite() function. - */ -- ret = btrfs_delalloc_reserve_space(BTRFS_I(inode), &data_reserved, -- page_start, reserved_space); -- if (ret < 0) -+ ret = btrfs_check_data_free_space(BTRFS_I(inode), &data_reserved, -+ page_start, reserved_space, false); -+ if (ret < 0) { -+ size_t write_bytes = reserved_space; -+ -+ if (btrfs_check_nocow_lock(BTRFS_I(inode), page_start, -+ &write_bytes, false) <= 0) -+ goto out_noreserve; -+ -+ only_release_metadata = true; -+ -+ /* -+ * Can't write the whole range, there may be shared extents or -+ * holes in the range, bail out with @only_release_metadata set -+ * to true so that we unlock the nocow lock before returning the -+ * error. -+ */ -+ if (write_bytes < reserved_space) -+ goto out_noreserve; -+ } -+ ret = btrfs_delalloc_reserve_metadata(BTRFS_I(inode), reserved_space, -+ reserved_space, false); -+ if (ret < 0) { -+ if (!only_release_metadata) -+ btrfs_free_reserved_data_space(BTRFS_I(inode), data_reserved, -+ page_start, reserved_space); - goto out_noreserve; -+ } - - ret = file_update_time(vmf->vma->vm_file); - if (ret < 0) -@@ -1906,10 +1931,16 @@ again: - if (folio_contains(folio, (size - 1) >> PAGE_SHIFT)) { - reserved_space = round_up(size - page_start, fs_info->sectorsize); - if (reserved_space < fsize) { -+ const u64 to_free = fsize - reserved_space; -+ - end = page_start + reserved_space - 1; -- btrfs_delalloc_release_space(BTRFS_I(inode), -- data_reserved, end + 1, -- fsize - reserved_space, true); -+ if (only_release_metadata) -+ btrfs_delalloc_release_metadata(BTRFS_I(inode), -+ to_free, true); -+ else -+ btrfs_delalloc_release_space(BTRFS_I(inode), -+ data_reserved, end + 1, -+ to_free, true); - } - } - -@@ -1946,10 +1977,16 @@ again: - - btrfs_set_inode_last_sub_trans(BTRFS_I(inode)); - -+ if (only_release_metadata) -+ btrfs_set_extent_bit(io_tree, page_start, end, EXTENT_NORESERVE, -+ &cached_state); -+ - btrfs_unlock_extent(io_tree, page_start, page_end, &cached_state); - up_read(&BTRFS_I(inode)->i_mmap_lock); - - btrfs_delalloc_release_extents(BTRFS_I(inode), fsize); -+ if (only_release_metadata) -+ btrfs_check_nocow_unlock(BTRFS_I(inode)); - sb_end_pagefault(inode->i_sb); - extent_changeset_free(data_reserved); - return VM_FAULT_LOCKED; -@@ -1959,10 +1996,16 @@ out_unlock: - up_read(&BTRFS_I(inode)->i_mmap_lock); - out: - btrfs_delalloc_release_extents(BTRFS_I(inode), fsize); -- btrfs_delalloc_release_space(BTRFS_I(inode), data_reserved, page_start, -- reserved_space, true); -+ if (only_release_metadata) -+ btrfs_delalloc_release_metadata(BTRFS_I(inode), reserved_space, true); -+ else -+ btrfs_delalloc_release_space(BTRFS_I(inode), data_reserved, -+ page_start, reserved_space, true); - extent_changeset_free(data_reserved); - out_noreserve: -+ if (only_release_metadata) -+ btrfs_check_nocow_unlock(BTRFS_I(inode)); -+ - sb_end_pagefault(inode->i_sb); - - if (ret < 0) -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/free-space-tree.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/free-space-tree.c ---- BPI-Router-Linux-kernel/fs/btrfs/free-space-tree.c 2025-10-22 13:53:23.499327765 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/free-space-tree.c 2025-10-22 13:53:56.699168255 -0400 -@@ -1115,11 +1115,21 @@ static int populate_free_space_tree(stru - ret = btrfs_search_slot_for_read(extent_root, &key, path, 1, 0); - if (ret < 0) - goto out_locked; -- ASSERT(ret == 0); -+ /* -+ * If ret is 1 (no key found), it means this is an empty block group, -+ * without any extents allocated from it and there's no block group -+ * item (key BTRFS_BLOCK_GROUP_ITEM_KEY) located in the extent tree -+ * because we are using the block group tree feature, so block group -+ * items are stored in the block group tree. It also means there are no -+ * extents allocated for block groups with a start offset beyond this -+ * block group's end offset (this is the last, highest, block group). -+ */ -+ if (!btrfs_fs_compat_ro(trans->fs_info, BLOCK_GROUP_TREE)) -+ ASSERT(ret == 0); - - start = block_group->start; - end = block_group->start + block_group->length; -- while (1) { -+ while (ret == 0) { - btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); - - if (key.type == BTRFS_EXTENT_ITEM_KEY || -@@ -1149,8 +1159,6 @@ static int populate_free_space_tree(stru - ret = btrfs_next_item(extent_root, path); - if (ret < 0) - goto out_locked; -- if (ret) -- break; - } - if (start < end) { - ret = __add_to_free_space_tree(trans, block_group, path2, -@@ -1233,6 +1241,7 @@ static int clear_free_space_tree(struct - { - BTRFS_PATH_AUTO_FREE(path); - struct btrfs_key key; -+ struct rb_node *node; - int nr; - int ret; - -@@ -1261,6 +1270,16 @@ static int clear_free_space_tree(struct - btrfs_release_path(path); - } - -+ node = rb_first_cached(&trans->fs_info->block_group_cache_tree); -+ while (node) { -+ struct btrfs_block_group *bg; -+ -+ bg = rb_entry(node, struct btrfs_block_group, cache_node); -+ clear_bit(BLOCK_GROUP_FLAG_FREE_SPACE_ADDED, &bg->runtime_flags); -+ node = rb_next(node); -+ cond_resched(); -+ } -+ - return 0; - } - -@@ -1350,12 +1369,18 @@ int btrfs_rebuild_free_space_tree(struct - - block_group = rb_entry(node, struct btrfs_block_group, - cache_node); -+ -+ if (test_bit(BLOCK_GROUP_FLAG_FREE_SPACE_ADDED, -+ &block_group->runtime_flags)) -+ goto next; -+ - ret = populate_free_space_tree(trans, block_group); - if (ret) { - btrfs_abort_transaction(trans, ret); - btrfs_end_transaction(trans); - return ret; - } -+next: - if (btrfs_should_end_transaction(trans)) { - btrfs_end_transaction(trans); - trans = btrfs_start_transaction(free_space_root, 1); -@@ -1382,13 +1407,41 @@ static int __add_block_group_free_space( - - clear_bit(BLOCK_GROUP_FLAG_NEEDS_FREE_SPACE, &block_group->runtime_flags); - -+ /* -+ * While rebuilding the free space tree we may allocate new metadata -+ * block groups while modifying the free space tree. -+ * -+ * Because during the rebuild (at btrfs_rebuild_free_space_tree()) we -+ * can use multiple transactions, every time btrfs_end_transaction() is -+ * called at btrfs_rebuild_free_space_tree() we finish the creation of -+ * new block groups by calling btrfs_create_pending_block_groups(), and -+ * that in turn calls us, through add_block_group_free_space(), to add -+ * a free space info item and a free space extent item for the block -+ * group. -+ * -+ * Then later btrfs_rebuild_free_space_tree() may find such new block -+ * groups and processes them with populate_free_space_tree(), which can -+ * fail with EEXIST since there are already items for the block group in -+ * the free space tree. Notice that we say "may find" because a new -+ * block group may be added to the block groups rbtree in a node before -+ * or after the block group currently being processed by the rebuild -+ * process. So signal the rebuild process to skip such new block groups -+ * if it finds them. -+ */ -+ set_bit(BLOCK_GROUP_FLAG_FREE_SPACE_ADDED, &block_group->runtime_flags); -+ - ret = add_new_free_space_info(trans, block_group, path); -- if (ret) -+ if (ret) { -+ btrfs_abort_transaction(trans, ret); - return ret; -+ } -+ -+ ret = __add_to_free_space_tree(trans, block_group, path, -+ block_group->start, block_group->length); -+ if (ret) -+ btrfs_abort_transaction(trans, ret); - -- return __add_to_free_space_tree(trans, block_group, path, -- block_group->start, -- block_group->length); -+ return 0; - } - - int add_block_group_free_space(struct btrfs_trans_handle *trans, -@@ -1408,16 +1461,14 @@ int add_block_group_free_space(struct bt - path = btrfs_alloc_path(); - if (!path) { - ret = -ENOMEM; -+ btrfs_abort_transaction(trans, ret); - goto out; - } - - ret = __add_block_group_free_space(trans, block_group, path); -- - out: - btrfs_free_path(path); - mutex_unlock(&block_group->free_space_lock); -- if (ret) -- btrfs_abort_transaction(trans, ret); - return ret; - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/inode.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/inode.c ---- BPI-Router-Linux-kernel/fs/btrfs/inode.c 2025-10-22 13:53:23.499327765 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/inode.c 2025-10-22 13:53:56.699168255 -0400 -@@ -2010,7 +2010,7 @@ static int nocow_one_range(struct btrfs_ - * cleaered by the caller. - */ - if (ret < 0) -- btrfs_cleanup_ordered_extents(inode, file_pos, end); -+ btrfs_cleanup_ordered_extents(inode, file_pos, len); - return ret; - } - -@@ -3881,10 +3881,6 @@ static int btrfs_read_locked_inode(struc - bool filled = false; - int first_xattr_slot; - -- ret = btrfs_init_file_extent_tree(inode); -- if (ret) -- goto out; -- - ret = btrfs_fill_inode(inode, &rdev); - if (!ret) - filled = true; -@@ -3916,8 +3912,6 @@ static int btrfs_read_locked_inode(struc - i_uid_write(vfs_inode, btrfs_inode_uid(leaf, inode_item)); - i_gid_write(vfs_inode, btrfs_inode_gid(leaf, inode_item)); - btrfs_i_size_write(inode, btrfs_inode_size(leaf, inode_item)); -- btrfs_inode_set_file_extent_range(inode, 0, -- round_up(i_size_read(vfs_inode), fs_info->sectorsize)); - - inode_set_atime(vfs_inode, btrfs_timespec_sec(leaf, &inode_item->atime), - btrfs_timespec_nsec(leaf, &inode_item->atime)); -@@ -3948,6 +3942,11 @@ static int btrfs_read_locked_inode(struc - btrfs_update_inode_mapping_flags(inode); - - cache_index: -+ ret = btrfs_init_file_extent_tree(inode); -+ if (ret) -+ goto out; -+ btrfs_inode_set_file_extent_range(inode, 0, -+ round_up(i_size_read(vfs_inode), fs_info->sectorsize)); - /* - * If we were modified in the current generation and evicted from memory - * and then re-read we need to do a full sync since we don't have any -@@ -4250,9 +4249,9 @@ static int __btrfs_unlink_inode(struct b - - ret = btrfs_del_inode_ref(trans, root, name, ino, dir_ino, &index); - if (ret) { -- btrfs_info(fs_info, -- "failed to delete reference to %.*s, inode %llu parent %llu", -- name->len, name->name, ino, dir_ino); -+ btrfs_crit(fs_info, -+ "failed to delete reference to %.*s, root %llu inode %llu parent %llu", -+ name->len, name->name, btrfs_root_id(root), ino, dir_ino); - btrfs_abort_transaction(trans, ret); - goto err; - } -@@ -4710,7 +4709,6 @@ static int btrfs_rmdir(struct inode *dir - struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info; - int ret = 0; - struct btrfs_trans_handle *trans; -- u64 last_unlink_trans; - struct fscrypt_name fname; - - if (inode->i_size > BTRFS_EMPTY_DIR_SIZE) -@@ -4736,6 +4734,23 @@ static int btrfs_rmdir(struct inode *dir - goto out_notrans; - } - -+ /* -+ * Propagate the last_unlink_trans value of the deleted dir to its -+ * parent directory. This is to prevent an unrecoverable log tree in the -+ * case we do something like this: -+ * 1) create dir foo -+ * 2) create snapshot under dir foo -+ * 3) delete the snapshot -+ * 4) rmdir foo -+ * 5) mkdir foo -+ * 6) fsync foo or some file inside foo -+ * -+ * This is because we can't unlink other roots when replaying the dir -+ * deletes for directory foo. -+ */ -+ if (BTRFS_I(inode)->last_unlink_trans >= trans->transid) -+ btrfs_record_snapshot_destroy(trans, BTRFS_I(dir)); -+ - if (unlikely(btrfs_ino(BTRFS_I(inode)) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) { - ret = btrfs_unlink_subvol(trans, BTRFS_I(dir), dentry); - goto out; -@@ -4745,27 +4760,11 @@ static int btrfs_rmdir(struct inode *dir - if (ret) - goto out; - -- last_unlink_trans = BTRFS_I(inode)->last_unlink_trans; -- - /* now the directory is empty */ - ret = btrfs_unlink_inode(trans, BTRFS_I(dir), BTRFS_I(d_inode(dentry)), - &fname.disk_name); -- if (!ret) { -+ if (!ret) - btrfs_i_size_write(BTRFS_I(inode), 0); -- /* -- * Propagate the last_unlink_trans value of the deleted dir to -- * its parent directory. This is to prevent an unrecoverable -- * log tree in the case we do something like this: -- * 1) create dir foo -- * 2) create snapshot under dir foo -- * 3) delete the snapshot -- * 4) rmdir foo -- * 5) mkdir foo -- * 6) fsync foo or some file inside foo -- */ -- if (last_unlink_trans >= trans->transid) -- BTRFS_I(dir)->last_unlink_trans = last_unlink_trans; -- } - out: - btrfs_end_transaction(trans); - out_notrans: -@@ -5685,7 +5684,17 @@ static void btrfs_del_inode_from_root(st - bool empty = false; - - xa_lock(&root->inodes); -- entry = __xa_erase(&root->inodes, btrfs_ino(inode)); -+ /* -+ * This btrfs_inode is being freed and has already been unhashed at this -+ * point. It's possible that another btrfs_inode has already been -+ * allocated for the same inode and inserted itself into the root, so -+ * don't delete it in that case. -+ * -+ * Note that this shouldn't need to allocate memory, so the gfp flags -+ * don't really matter. -+ */ -+ entry = __xa_cmpxchg(&root->inodes, btrfs_ino(inode), inode, NULL, -+ GFP_ATOMIC); - if (entry == inode) - empty = xa_empty(&root->inodes); - xa_unlock(&root->inodes); -@@ -7364,13 +7373,13 @@ struct extent_map *btrfs_create_io_em(st - static void wait_subpage_spinlock(struct folio *folio) - { - struct btrfs_fs_info *fs_info = folio_to_fs_info(folio); -- struct btrfs_subpage *subpage; -+ struct btrfs_folio_state *bfs; - - if (!btrfs_is_subpage(fs_info, folio)) - return; - - ASSERT(folio_test_private(folio) && folio_get_private(folio)); -- subpage = folio_get_private(folio); -+ bfs = folio_get_private(folio); - - /* - * This may look insane as we just acquire the spinlock and release it, -@@ -7383,8 +7392,8 @@ static void wait_subpage_spinlock(struct - * Here we just acquire the spinlock so that all existing callers - * should exit and we're safe to release/invalidate the page. - */ -- spin_lock_irq(&subpage->lock); -- spin_unlock_irq(&subpage->lock); -+ spin_lock_irq(&bfs->lock); -+ spin_unlock_irq(&bfs->lock); - } - - static int btrfs_launder_folio(struct folio *folio) -@@ -7827,6 +7836,7 @@ struct inode *btrfs_alloc_inode(struct s - ei->last_sub_trans = 0; - ei->logged_trans = 0; - ei->delalloc_bytes = 0; -+ /* new_delalloc_bytes and last_dir_index_offset are in a union. */ - ei->new_delalloc_bytes = 0; - ei->defrag_bytes = 0; - ei->disk_i_size = 0; -@@ -8059,6 +8069,7 @@ static int btrfs_rename_exchange(struct - int ret; - int ret2; - bool need_abort = false; -+ bool logs_pinned = false; - struct fscrypt_name old_fname, new_fname; - struct fscrypt_str *old_name, *new_name; - -@@ -8182,6 +8193,31 @@ static int btrfs_rename_exchange(struct - inode_inc_iversion(new_inode); - simple_rename_timestamp(old_dir, old_dentry, new_dir, new_dentry); - -+ if (old_ino != BTRFS_FIRST_FREE_OBJECTID && -+ new_ino != BTRFS_FIRST_FREE_OBJECTID) { -+ /* -+ * If we are renaming in the same directory (and it's not for -+ * root entries) pin the log early to prevent any concurrent -+ * task from logging the directory after we removed the old -+ * entries and before we add the new entries, otherwise that -+ * task can sync a log without any entry for the inodes we are -+ * renaming and therefore replaying that log, if a power failure -+ * happens after syncing the log, would result in deleting the -+ * inodes. -+ * -+ * If the rename affects two different directories, we want to -+ * make sure the that there's no log commit that contains -+ * updates for only one of the directories but not for the -+ * other. -+ * -+ * If we are renaming an entry for a root, we don't care about -+ * log updates since we called btrfs_set_log_full_commit(). -+ */ -+ btrfs_pin_log_trans(root); -+ btrfs_pin_log_trans(dest); -+ logs_pinned = true; -+ } -+ - if (old_dentry->d_parent != new_dentry->d_parent) { - btrfs_record_unlink_dir(trans, BTRFS_I(old_dir), - BTRFS_I(old_inode), true); -@@ -8253,30 +8289,23 @@ static int btrfs_rename_exchange(struct - BTRFS_I(new_inode)->dir_index = new_idx; - - /* -- * Now pin the logs of the roots. We do it to ensure that no other task -- * can sync the logs while we are in progress with the rename, because -- * that could result in an inconsistency in case any of the inodes that -- * are part of this rename operation were logged before. -+ * Do the log updates for all inodes. -+ * -+ * If either entry is for a root we don't need to update the logs since -+ * we've called btrfs_set_log_full_commit() before. - */ -- if (old_ino != BTRFS_FIRST_FREE_OBJECTID) -- btrfs_pin_log_trans(root); -- if (new_ino != BTRFS_FIRST_FREE_OBJECTID) -- btrfs_pin_log_trans(dest); -- -- /* Do the log updates for all inodes. */ -- if (old_ino != BTRFS_FIRST_FREE_OBJECTID) -+ if (logs_pinned) { - btrfs_log_new_name(trans, old_dentry, BTRFS_I(old_dir), - old_rename_ctx.index, new_dentry->d_parent); -- if (new_ino != BTRFS_FIRST_FREE_OBJECTID) - btrfs_log_new_name(trans, new_dentry, BTRFS_I(new_dir), - new_rename_ctx.index, old_dentry->d_parent); -+ } - -- /* Now unpin the logs. */ -- if (old_ino != BTRFS_FIRST_FREE_OBJECTID) -+out_fail: -+ if (logs_pinned) { - btrfs_end_log_trans(root); -- if (new_ino != BTRFS_FIRST_FREE_OBJECTID) - btrfs_end_log_trans(dest); --out_fail: -+ } - ret2 = btrfs_end_transaction(trans); - ret = ret ? ret : ret2; - out_notrans: -@@ -8326,6 +8355,7 @@ static int btrfs_rename(struct mnt_idmap - int ret2; - u64 old_ino = btrfs_ino(BTRFS_I(old_inode)); - struct fscrypt_name old_fname, new_fname; -+ bool logs_pinned = false; - - if (btrfs_ino(BTRFS_I(new_dir)) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID) - return -EPERM; -@@ -8460,6 +8490,29 @@ static int btrfs_rename(struct mnt_idmap - inode_inc_iversion(old_inode); - simple_rename_timestamp(old_dir, old_dentry, new_dir, new_dentry); - -+ if (old_ino != BTRFS_FIRST_FREE_OBJECTID) { -+ /* -+ * If we are renaming in the same directory (and it's not a -+ * root entry) pin the log to prevent any concurrent task from -+ * logging the directory after we removed the old entry and -+ * before we add the new entry, otherwise that task can sync -+ * a log without any entry for the inode we are renaming and -+ * therefore replaying that log, if a power failure happens -+ * after syncing the log, would result in deleting the inode. -+ * -+ * If the rename affects two different directories, we want to -+ * make sure the that there's no log commit that contains -+ * updates for only one of the directories but not for the -+ * other. -+ * -+ * If we are renaming an entry for a root, we don't care about -+ * log updates since we called btrfs_set_log_full_commit(). -+ */ -+ btrfs_pin_log_trans(root); -+ btrfs_pin_log_trans(dest); -+ logs_pinned = true; -+ } -+ - if (old_dentry->d_parent != new_dentry->d_parent) - btrfs_record_unlink_dir(trans, BTRFS_I(old_dir), - BTRFS_I(old_inode), true); -@@ -8524,7 +8577,7 @@ static int btrfs_rename(struct mnt_idmap - if (old_inode->i_nlink == 1) - BTRFS_I(old_inode)->dir_index = index; - -- if (old_ino != BTRFS_FIRST_FREE_OBJECTID) -+ if (logs_pinned) - btrfs_log_new_name(trans, old_dentry, BTRFS_I(old_dir), - rename_ctx.index, new_dentry->d_parent); - -@@ -8540,6 +8593,10 @@ static int btrfs_rename(struct mnt_idmap - } - } - out_fail: -+ if (logs_pinned) { -+ btrfs_end_log_trans(root); -+ btrfs_end_log_trans(dest); -+ } - ret2 = btrfs_end_transaction(trans); - ret = ret ? ret : ret2; - out_notrans: -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/ioctl.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/ioctl.c ---- BPI-Router-Linux-kernel/fs/btrfs/ioctl.c 2025-10-22 13:53:23.503327747 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/ioctl.c 2025-10-22 13:53:56.699168255 -0400 -@@ -666,14 +666,14 @@ static noinline int create_subvol(struct - goto out; - } - -+ btrfs_record_new_subvolume(trans, BTRFS_I(dir)); -+ - ret = btrfs_create_new_inode(trans, &new_inode_args); - if (ret) { - btrfs_abort_transaction(trans, ret); - goto out; - } - -- btrfs_record_new_subvolume(trans, BTRFS_I(dir)); -- - d_instantiate_new(dentry, new_inode_args.inode); - new_inode_args.inode = NULL; - -@@ -3139,7 +3139,7 @@ static long btrfs_ioctl_scrub(struct fil - return -EPERM; - - if (btrfs_fs_incompat(fs_info, EXTENT_TREE_V2)) { -- btrfs_err(fs_info, "scrub is not supported on extent tree v2 yet"); -+ btrfs_err(fs_info, "scrub: extent tree v2 not yet supported"); - return -EINVAL; - } - -@@ -4829,7 +4829,8 @@ static int btrfs_uring_encoded_read(stru - #if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT) - copy_end = offsetofend(struct btrfs_ioctl_encoded_io_args_32, flags); - #else -- return -ENOTTY; -+ ret = -ENOTTY; -+ goto out_acct; - #endif - } else { - copy_end = copy_end_kernel; -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/print-tree.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/print-tree.c ---- BPI-Router-Linux-kernel/fs/btrfs/print-tree.c 2025-10-22 13:53:23.503327747 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/print-tree.c 2025-10-22 13:53:56.699168255 -0400 -@@ -223,7 +223,7 @@ static void print_eb_refs_lock(const str - { - #ifdef CONFIG_BTRFS_DEBUG - btrfs_info(eb->fs_info, "refs %u lock_owner %u current %u", -- atomic_read(&eb->refs), eb->lock_owner, current->pid); -+ refcount_read(&eb->refs), eb->lock_owner, current->pid); - #endif - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/qgroup.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/qgroup.c ---- BPI-Router-Linux-kernel/fs/btrfs/qgroup.c 2025-10-22 13:53:23.503327747 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/qgroup.c 2025-10-22 13:53:56.699168255 -0400 -@@ -630,22 +630,30 @@ bool btrfs_check_quota_leak(const struct - - /* - * This is called from close_ctree() or open_ctree() or btrfs_quota_disable(), -- * first two are in single-threaded paths.And for the third one, we have set -- * quota_root to be null with qgroup_lock held before, so it is safe to clean -- * up the in-memory structures without qgroup_lock held. -+ * first two are in single-threaded paths. - */ - void btrfs_free_qgroup_config(struct btrfs_fs_info *fs_info) - { - struct rb_node *n; - struct btrfs_qgroup *qgroup; - -+ /* -+ * btrfs_quota_disable() can be called concurrently with -+ * btrfs_qgroup_rescan() -> qgroup_rescan_zero_tracking(), so take the -+ * lock. -+ */ -+ spin_lock(&fs_info->qgroup_lock); - while ((n = rb_first(&fs_info->qgroup_tree))) { - qgroup = rb_entry(n, struct btrfs_qgroup, node); - rb_erase(n, &fs_info->qgroup_tree); - __del_qgroup_rb(qgroup); -+ spin_unlock(&fs_info->qgroup_lock); - btrfs_sysfs_del_one_qgroup(fs_info, qgroup); - kfree(qgroup); -+ spin_lock(&fs_info->qgroup_lock); - } -+ spin_unlock(&fs_info->qgroup_lock); -+ - /* - * We call btrfs_free_qgroup_config() when unmounting - * filesystem and disabling quota, so we set qgroup_ulist -@@ -1354,11 +1362,14 @@ int btrfs_quota_disable(struct btrfs_fs_ - - /* - * We have nothing held here and no trans handle, just return the error -- * if there is one. -+ * if there is one and set back the quota enabled bit since we didn't -+ * actually disable quotas. - */ - ret = flush_reservations(fs_info); -- if (ret) -+ if (ret) { -+ set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags); - return ret; -+ } - - /* - * 1 For the root item -@@ -1470,9 +1481,9 @@ static int __qgroup_excl_accounting(stru - struct btrfs_qgroup *src, int sign) - { - struct btrfs_qgroup *qgroup; -- struct btrfs_qgroup *cur; - LIST_HEAD(qgroup_list); - u64 num_bytes = src->excl; -+ u64 num_bytes_cmpr = src->excl_cmpr; - int ret = 0; - - qgroup = find_qgroup_rb(fs_info, ref_root); -@@ -1480,15 +1491,16 @@ static int __qgroup_excl_accounting(stru - goto out; - - qgroup_iterator_add(&qgroup_list, qgroup); -- list_for_each_entry(cur, &qgroup_list, iterator) { -+ list_for_each_entry(qgroup, &qgroup_list, iterator) { - struct btrfs_qgroup_list *glist; - - qgroup->rfer += sign * num_bytes; -- qgroup->rfer_cmpr += sign * num_bytes; -+ qgroup->rfer_cmpr += sign * num_bytes_cmpr; - - WARN_ON(sign < 0 && qgroup->excl < num_bytes); -+ WARN_ON(sign < 0 && qgroup->excl_cmpr < num_bytes_cmpr); - qgroup->excl += sign * num_bytes; -- qgroup->excl_cmpr += sign * num_bytes; -+ qgroup->excl_cmpr += sign * num_bytes_cmpr; - - if (sign > 0) - qgroup_rsv_add_by_qgroup(fs_info, qgroup, src); -@@ -1679,9 +1691,6 @@ int btrfs_create_qgroup(struct btrfs_tra - struct btrfs_qgroup *prealloc = NULL; - int ret = 0; - -- if (btrfs_qgroup_mode(fs_info) == BTRFS_QGROUP_MODE_DISABLED) -- return 0; -- - mutex_lock(&fs_info->qgroup_ioctl_lock); - if (!fs_info->quota_root) { - ret = -ENOTCONN; -@@ -2341,7 +2350,7 @@ static int qgroup_trace_extent_swap(stru - btrfs_item_key_to_cpu(dst_path->nodes[dst_level], &key, 0); - - /* For src_path */ -- atomic_inc(&src_eb->refs); -+ refcount_inc(&src_eb->refs); - src_path->nodes[root_level] = src_eb; - src_path->slots[root_level] = dst_path->slots[root_level]; - src_path->locks[root_level] = 0; -@@ -2574,7 +2583,7 @@ static int qgroup_trace_subtree_swap(str - goto out; - } - /* For dst_path */ -- atomic_inc(&dst_eb->refs); -+ refcount_inc(&dst_eb->refs); - dst_path->nodes[level] = dst_eb; - dst_path->slots[level] = 0; - dst_path->locks[level] = 0; -@@ -2666,7 +2675,7 @@ int btrfs_qgroup_trace_subtree(struct bt - * walk back up the tree (adjusting slot pointers as we go) - * and restart the search process. - */ -- atomic_inc(&root_eb->refs); /* For path */ -+ refcount_inc(&root_eb->refs); /* For path */ - path->nodes[root_level] = root_eb; - path->slots[root_level] = 0; - path->locks[root_level] = 0; /* so release_path doesn't try to unlock */ -@@ -4036,12 +4045,21 @@ btrfs_qgroup_rescan(struct btrfs_fs_info - qgroup_rescan_zero_tracking(fs_info); - - mutex_lock(&fs_info->qgroup_rescan_lock); -- fs_info->qgroup_rescan_running = true; -- btrfs_queue_work(fs_info->qgroup_rescan_workers, -- &fs_info->qgroup_rescan_work); -+ /* -+ * The rescan worker is only for full accounting qgroups, check if it's -+ * enabled as it is pointless to queue it otherwise. A concurrent quota -+ * disable may also have just cleared BTRFS_FS_QUOTA_ENABLED. -+ */ -+ if (btrfs_qgroup_full_accounting(fs_info)) { -+ fs_info->qgroup_rescan_running = true; -+ btrfs_queue_work(fs_info->qgroup_rescan_workers, -+ &fs_info->qgroup_rescan_work); -+ } else { -+ ret = -ENOTCONN; -+ } - mutex_unlock(&fs_info->qgroup_rescan_lock); - -- return 0; -+ return ret; - } - - int btrfs_qgroup_wait_for_completion(struct btrfs_fs_info *fs_info, -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/ref-verify.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/ref-verify.c ---- BPI-Router-Linux-kernel/fs/btrfs/ref-verify.c 2025-10-22 13:53:23.503327747 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/ref-verify.c 2025-10-22 13:53:56.699168255 -0400 -@@ -998,11 +998,18 @@ int btrfs_build_ref_tree(struct btrfs_fs - if (!btrfs_test_opt(fs_info, REF_VERIFY)) - return 0; - -+ extent_root = btrfs_extent_root(fs_info, 0); -+ /* If the extent tree is damaged we cannot ignore it (IGNOREBADROOTS). */ -+ if (IS_ERR(extent_root)) { -+ btrfs_warn(fs_info, "ref-verify: extent tree not available, disabling"); -+ btrfs_clear_opt(fs_info->mount_opt, REF_VERIFY); -+ return 0; -+ } -+ - path = btrfs_alloc_path(); - if (!path) - return -ENOMEM; - -- extent_root = btrfs_extent_root(fs_info, 0); - eb = btrfs_read_lock_root_node(extent_root); - level = btrfs_header_level(eb); - path->nodes[level] = eb; -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/relocation.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/relocation.c ---- BPI-Router-Linux-kernel/fs/btrfs/relocation.c 2025-10-22 13:53:23.503327747 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/relocation.c 2025-10-22 13:53:56.703168235 -0400 -@@ -594,6 +594,25 @@ static struct btrfs_root *create_reloc_r - if (btrfs_root_id(root) == objectid) { - u64 commit_root_gen; - -+ /* -+ * Relocation will wait for cleaner thread, and any half-dropped -+ * subvolume will be fully cleaned up at mount time. -+ * So here we shouldn't hit a subvolume with non-zero drop_progress. -+ * -+ * If this isn't the case, error out since it can make us attempt to -+ * drop references for extents that were already dropped before. -+ */ -+ if (unlikely(btrfs_disk_key_objectid(&root->root_item.drop_progress))) { -+ struct btrfs_key cpu_key; -+ -+ btrfs_disk_key_to_cpu(&cpu_key, &root->root_item.drop_progress); -+ btrfs_err(fs_info, -+ "cannot relocate partially dropped subvolume %llu, drop progress key (%llu %u %llu)", -+ objectid, cpu_key.objectid, cpu_key.type, cpu_key.offset); -+ ret = -EUCLEAN; -+ goto fail; -+ } -+ - /* called by btrfs_init_reloc_root */ - ret = btrfs_copy_root(trans, root, root->commit_root, &eb, - BTRFS_TREE_RELOC_OBJECTID); -@@ -1516,7 +1535,7 @@ static noinline_for_stack int merge_relo - - if (btrfs_disk_key_objectid(&root_item->drop_progress) == 0) { - level = btrfs_root_level(root_item); -- atomic_inc(&reloc_root->node->refs); -+ refcount_inc(&reloc_root->node->refs); - path->nodes[level] = reloc_root->node; - path->slots[level] = 0; - } else { -@@ -4339,7 +4358,7 @@ int btrfs_reloc_cow_block(struct btrfs_t - } - - btrfs_backref_drop_node_buffer(node); -- atomic_inc(&cow->refs); -+ refcount_inc(&cow->refs); - node->eb = cow; - node->new_bytenr = cow->start; - -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/scrub.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/scrub.c ---- BPI-Router-Linux-kernel/fs/btrfs/scrub.c 2025-10-22 13:53:23.503327747 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/scrub.c 2025-10-22 13:53:56.703168235 -0400 -@@ -557,7 +557,7 @@ static int scrub_print_warning_inode(u64 - */ - for (i = 0; i < ipath->fspath->elem_cnt; ++i) - btrfs_warn_in_rcu(fs_info, --"%s at logical %llu on dev %s, physical %llu, root %llu, inode %llu, offset %llu, length %u, links %u (path: %s)", -+"scrub: %s at logical %llu on dev %s, physical %llu root %llu inode %llu offset %llu length %u links %u (path: %s)", - swarn->errstr, swarn->logical, - btrfs_dev_name(swarn->dev), - swarn->physical, -@@ -571,7 +571,7 @@ static int scrub_print_warning_inode(u64 - - err: - btrfs_warn_in_rcu(fs_info, -- "%s at logical %llu on dev %s, physical %llu, root %llu, inode %llu, offset %llu: path resolving failed with ret=%d", -+ "scrub: %s at logical %llu on dev %s, physical %llu root %llu inode %llu offset %llu: path resolving failed with ret=%d", - swarn->errstr, swarn->logical, - btrfs_dev_name(swarn->dev), - swarn->physical, -@@ -596,7 +596,7 @@ static void scrub_print_common_warning(c - - /* Super block error, no need to search extent tree. */ - if (is_super) { -- btrfs_warn_in_rcu(fs_info, "%s on device %s, physical %llu", -+ btrfs_warn_in_rcu(fs_info, "scrub: %s on device %s, physical %llu", - errstr, btrfs_dev_name(dev), physical); - return; - } -@@ -631,14 +631,14 @@ static void scrub_print_common_warning(c - &ref_level); - if (ret < 0) { - btrfs_warn(fs_info, -- "failed to resolve tree backref for logical %llu: %d", -- swarn.logical, ret); -+ "scrub: failed to resolve tree backref for logical %llu: %d", -+ swarn.logical, ret); - break; - } - if (ret > 0) - break; - btrfs_warn_in_rcu(fs_info, --"%s at logical %llu on dev %s, physical %llu: metadata %s (level %d) in tree %llu", -+"scrub: %s at logical %llu on dev %s, physical %llu: metadata %s (level %d) in tree %llu", - errstr, swarn.logical, btrfs_dev_name(dev), - swarn.physical, (ref_level ? "node" : "leaf"), - ref_level, ref_root); -@@ -718,7 +718,7 @@ static void scrub_verify_one_metadata(st - scrub_bitmap_set_meta_error(stripe, sector_nr, sectors_per_tree); - scrub_bitmap_set_error(stripe, sector_nr, sectors_per_tree); - btrfs_warn_rl(fs_info, -- "tree block %llu mirror %u has bad bytenr, has %llu want %llu", -+ "scrub: tree block %llu mirror %u has bad bytenr, has %llu want %llu", - logical, stripe->mirror_num, - btrfs_stack_header_bytenr(header), logical); - return; -@@ -728,7 +728,7 @@ static void scrub_verify_one_metadata(st - scrub_bitmap_set_meta_error(stripe, sector_nr, sectors_per_tree); - scrub_bitmap_set_error(stripe, sector_nr, sectors_per_tree); - btrfs_warn_rl(fs_info, -- "tree block %llu mirror %u has bad fsid, has %pU want %pU", -+ "scrub: tree block %llu mirror %u has bad fsid, has %pU want %pU", - logical, stripe->mirror_num, - header->fsid, fs_info->fs_devices->fsid); - return; -@@ -738,7 +738,7 @@ static void scrub_verify_one_metadata(st - scrub_bitmap_set_meta_error(stripe, sector_nr, sectors_per_tree); - scrub_bitmap_set_error(stripe, sector_nr, sectors_per_tree); - btrfs_warn_rl(fs_info, -- "tree block %llu mirror %u has bad chunk tree uuid, has %pU want %pU", -+ "scrub: tree block %llu mirror %u has bad chunk tree uuid, has %pU want %pU", - logical, stripe->mirror_num, - header->chunk_tree_uuid, fs_info->chunk_tree_uuid); - return; -@@ -760,7 +760,7 @@ static void scrub_verify_one_metadata(st - scrub_bitmap_set_meta_error(stripe, sector_nr, sectors_per_tree); - scrub_bitmap_set_error(stripe, sector_nr, sectors_per_tree); - btrfs_warn_rl(fs_info, -- "tree block %llu mirror %u has bad csum, has " CSUM_FMT " want " CSUM_FMT, -+"scrub: tree block %llu mirror %u has bad csum, has " CSUM_FMT " want " CSUM_FMT, - logical, stripe->mirror_num, - CSUM_FMT_VALUE(fs_info->csum_size, on_disk_csum), - CSUM_FMT_VALUE(fs_info->csum_size, calculated_csum)); -@@ -771,7 +771,7 @@ static void scrub_verify_one_metadata(st - scrub_bitmap_set_meta_gen_error(stripe, sector_nr, sectors_per_tree); - scrub_bitmap_set_error(stripe, sector_nr, sectors_per_tree); - btrfs_warn_rl(fs_info, -- "tree block %llu mirror %u has bad generation, has %llu want %llu", -+ "scrub: tree block %llu mirror %u has bad generation, has %llu want %llu", - logical, stripe->mirror_num, - btrfs_stack_header_generation(header), - stripe->sectors[sector_nr].generation); -@@ -814,7 +814,7 @@ static void scrub_verify_one_sector(stru - */ - if (unlikely(sector_nr + sectors_per_tree > stripe->nr_sectors)) { - btrfs_warn_rl(fs_info, -- "tree block at %llu crosses stripe boundary %llu", -+ "scrub: tree block at %llu crosses stripe boundary %llu", - stripe->logical + - (sector_nr << fs_info->sectorsize_bits), - stripe->logical); -@@ -1046,12 +1046,12 @@ skip: - if (repaired) { - if (dev) { - btrfs_err_rl_in_rcu(fs_info, -- "fixed up error at logical %llu on dev %s physical %llu", -+ "scrub: fixed up error at logical %llu on dev %s physical %llu", - stripe->logical, btrfs_dev_name(dev), - physical); - } else { - btrfs_err_rl_in_rcu(fs_info, -- "fixed up error at logical %llu on mirror %u", -+ "scrub: fixed up error at logical %llu on mirror %u", - stripe->logical, stripe->mirror_num); - } - continue; -@@ -1060,12 +1060,12 @@ skip: - /* The remaining are all for unrepaired. */ - if (dev) { - btrfs_err_rl_in_rcu(fs_info, -- "unable to fixup (regular) error at logical %llu on dev %s physical %llu", -+"scrub: unable to fixup (regular) error at logical %llu on dev %s physical %llu", - stripe->logical, btrfs_dev_name(dev), - physical); - } else { - btrfs_err_rl_in_rcu(fs_info, -- "unable to fixup (regular) error at logical %llu on mirror %u", -+ "scrub: unable to fixup (regular) error at logical %llu on mirror %u", - stripe->logical, stripe->mirror_num); - } - -@@ -1593,8 +1593,7 @@ static int sync_write_pointer_for_zoned( - physical, - sctx->write_pointer); - if (ret) -- btrfs_err(fs_info, -- "zoned: failed to recover write pointer"); -+ btrfs_err(fs_info, "scrub: zoned: failed to recover write pointer"); - } - mutex_unlock(&sctx->wr_lock); - btrfs_dev_clear_zone_empty(sctx->wr_tgtdev, physical); -@@ -1658,7 +1657,7 @@ static int scrub_find_fill_first_stripe( - int ret; - - if (unlikely(!extent_root || !csum_root)) { -- btrfs_err(fs_info, "no valid extent or csum root for scrub"); -+ btrfs_err(fs_info, "scrub: no valid extent or csum root found"); - return -EUCLEAN; - } - memset(stripe->sectors, 0, sizeof(struct scrub_sector_verification) * -@@ -1907,7 +1906,7 @@ static bool stripe_has_metadata_error(st - struct btrfs_fs_info *fs_info = stripe->bg->fs_info; - - btrfs_err(fs_info, -- "stripe %llu has unrepaired metadata sector at %llu", -+ "scrub: stripe %llu has unrepaired metadata sector at logical %llu", - stripe->logical, - stripe->logical + (i << fs_info->sectorsize_bits)); - return true; -@@ -2167,7 +2166,7 @@ static int scrub_raid56_parity_stripe(st - bitmap_and(&error, &error, &has_extent, stripe->nr_sectors); - if (!bitmap_empty(&error, stripe->nr_sectors)) { - btrfs_err(fs_info, --"unrepaired sectors detected, full stripe %llu data stripe %u errors %*pbl", -+"scrub: unrepaired sectors detected, full stripe %llu data stripe %u errors %*pbl", - full_stripe_start, i, stripe->nr_sectors, - &error); - ret = -EIO; -@@ -2789,14 +2788,14 @@ int scrub_enumerate_chunks(struct scrub_ - ro_set = 0; - } else if (ret == -ETXTBSY) { - btrfs_warn(fs_info, -- "skipping scrub of block group %llu due to active swapfile", -+ "scrub: skipping scrub of block group %llu due to active swapfile", - cache->start); - scrub_pause_off(fs_info); - ret = 0; - goto skip_unfreeze; - } else { -- btrfs_warn(fs_info, -- "failed setting block group ro: %d", ret); -+ btrfs_warn(fs_info, "scrub: failed setting block group ro: %d", -+ ret); - btrfs_unfreeze_block_group(cache); - btrfs_put_block_group(cache); - scrub_pause_off(fs_info); -@@ -2892,13 +2891,13 @@ static int scrub_one_super(struct scrub_ - ret = btrfs_check_super_csum(fs_info, sb); - if (ret != 0) { - btrfs_err_rl(fs_info, -- "super block at physical %llu devid %llu has bad csum", -+ "scrub: super block at physical %llu devid %llu has bad csum", - physical, dev->devid); - return -EIO; - } - if (btrfs_super_generation(sb) != generation) { - btrfs_err_rl(fs_info, --"super block at physical %llu devid %llu has bad generation %llu expect %llu", -+"scrub: super block at physical %llu devid %llu has bad generation %llu expect %llu", - physical, dev->devid, - btrfs_super_generation(sb), generation); - return -EUCLEAN; -@@ -3059,7 +3058,7 @@ int btrfs_scrub_dev(struct btrfs_fs_info - !test_bit(BTRFS_DEV_STATE_WRITEABLE, &dev->dev_state)) { - mutex_unlock(&fs_info->fs_devices->device_list_mutex); - btrfs_err_in_rcu(fs_info, -- "scrub on devid %llu: filesystem on %s is not writable", -+ "scrub: devid %llu: filesystem on %s is not writable", - devid, btrfs_dev_name(dev)); - ret = -EROFS; - goto out; -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/send.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/send.c ---- BPI-Router-Linux-kernel/fs/btrfs/send.c 2025-10-22 13:53:23.503327747 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/send.c 2025-10-22 13:53:56.703168235 -0400 -@@ -4,6 +4,7 @@ - */ - - #include -+#include - #include - #include - #include -@@ -5411,6 +5412,30 @@ tlv_put_failure: - return ret; - } - -+static int send_fallocate(struct send_ctx *sctx, u32 mode, u64 offset, u64 len) -+{ -+ struct fs_path *path; -+ int ret; -+ -+ path = get_cur_inode_path(sctx); -+ if (IS_ERR(path)) -+ return PTR_ERR(path); -+ -+ ret = begin_cmd(sctx, BTRFS_SEND_C_FALLOCATE); -+ if (ret < 0) -+ return ret; -+ -+ TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, path); -+ TLV_PUT_U32(sctx, BTRFS_SEND_A_FALLOCATE_MODE, mode); -+ TLV_PUT_U64(sctx, BTRFS_SEND_A_FILE_OFFSET, offset); -+ TLV_PUT_U64(sctx, BTRFS_SEND_A_SIZE, len); -+ -+ ret = send_cmd(sctx); -+ -+tlv_put_failure: -+ return ret; -+} -+ - static int send_hole(struct send_ctx *sctx, u64 end) - { - struct fs_path *p = NULL; -@@ -5419,6 +5444,14 @@ static int send_hole(struct send_ctx *sc - int ret = 0; - - /* -+ * Starting with send stream v2 we have fallocate and can use it to -+ * punch holes instead of sending writes full of zeroes. -+ */ -+ if (proto_cmd_ok(sctx, BTRFS_SEND_C_FALLOCATE)) -+ return send_fallocate(sctx, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, -+ offset, end - offset); -+ -+ /* - * A hole that starts at EOF or beyond it. Since we do not yet support - * fallocate (for extent preallocation and hole punching), sending a - * write of zeroes starting at EOF or beyond would later require issuing -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/subpage.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/subpage.c ---- BPI-Router-Linux-kernel/fs/btrfs/subpage.c 2025-10-22 13:53:23.503327747 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/subpage.c 2025-10-22 13:53:56.703168235 -0400 -@@ -49,7 +49,7 @@ - * Implementation: - * - * - Common -- * Both metadata and data will use a new structure, btrfs_subpage, to -+ * Both metadata and data will use a new structure, btrfs_folio_state, to - * record the status of each sector inside a page. This provides the extra - * granularity needed. - * -@@ -63,10 +63,10 @@ - * This means a slightly higher tree locking latency. - */ - --int btrfs_attach_subpage(const struct btrfs_fs_info *fs_info, -- struct folio *folio, enum btrfs_subpage_type type) -+int btrfs_attach_folio_state(const struct btrfs_fs_info *fs_info, -+ struct folio *folio, enum btrfs_folio_type type) - { -- struct btrfs_subpage *subpage; -+ struct btrfs_folio_state *bfs; - - /* For metadata we don't support large folio yet. */ - if (type == BTRFS_SUBPAGE_METADATA) -@@ -87,18 +87,18 @@ int btrfs_attach_subpage(const struct bt - if (type == BTRFS_SUBPAGE_DATA && !btrfs_is_subpage(fs_info, folio)) - return 0; - -- subpage = btrfs_alloc_subpage(fs_info, folio_size(folio), type); -- if (IS_ERR(subpage)) -- return PTR_ERR(subpage); -+ bfs = btrfs_alloc_folio_state(fs_info, folio_size(folio), type); -+ if (IS_ERR(bfs)) -+ return PTR_ERR(bfs); - -- folio_attach_private(folio, subpage); -+ folio_attach_private(folio, bfs); - return 0; - } - --void btrfs_detach_subpage(const struct btrfs_fs_info *fs_info, struct folio *folio, -- enum btrfs_subpage_type type) -+void btrfs_detach_folio_state(const struct btrfs_fs_info *fs_info, struct folio *folio, -+ enum btrfs_folio_type type) - { -- struct btrfs_subpage *subpage; -+ struct btrfs_folio_state *bfs; - - /* Either not subpage, or the folio already has private attached. */ - if (!folio_test_private(folio)) -@@ -108,15 +108,15 @@ void btrfs_detach_subpage(const struct b - if (type == BTRFS_SUBPAGE_DATA && !btrfs_is_subpage(fs_info, folio)) - return; - -- subpage = folio_detach_private(folio); -- ASSERT(subpage); -- btrfs_free_subpage(subpage); -+ bfs = folio_detach_private(folio); -+ ASSERT(bfs); -+ btrfs_free_folio_state(bfs); - } - --struct btrfs_subpage *btrfs_alloc_subpage(const struct btrfs_fs_info *fs_info, -- size_t fsize, enum btrfs_subpage_type type) -+struct btrfs_folio_state *btrfs_alloc_folio_state(const struct btrfs_fs_info *fs_info, -+ size_t fsize, enum btrfs_folio_type type) - { -- struct btrfs_subpage *ret; -+ struct btrfs_folio_state *ret; - unsigned int real_size; - - ASSERT(fs_info->sectorsize < fsize); -@@ -136,11 +136,6 @@ struct btrfs_subpage *btrfs_alloc_subpag - return ret; - } - --void btrfs_free_subpage(struct btrfs_subpage *subpage) --{ -- kfree(subpage); --} -- - /* - * Increase the eb_refs of current subpage. - * -@@ -152,7 +147,7 @@ void btrfs_free_subpage(struct btrfs_sub - */ - void btrfs_folio_inc_eb_refs(const struct btrfs_fs_info *fs_info, struct folio *folio) - { -- struct btrfs_subpage *subpage; -+ struct btrfs_folio_state *bfs; - - if (!btrfs_meta_is_subpage(fs_info)) - return; -@@ -160,13 +155,13 @@ void btrfs_folio_inc_eb_refs(const struc - ASSERT(folio_test_private(folio) && folio->mapping); - lockdep_assert_held(&folio->mapping->i_private_lock); - -- subpage = folio_get_private(folio); -- atomic_inc(&subpage->eb_refs); -+ bfs = folio_get_private(folio); -+ atomic_inc(&bfs->eb_refs); - } - - void btrfs_folio_dec_eb_refs(const struct btrfs_fs_info *fs_info, struct folio *folio) - { -- struct btrfs_subpage *subpage; -+ struct btrfs_folio_state *bfs; - - if (!btrfs_meta_is_subpage(fs_info)) - return; -@@ -174,9 +169,9 @@ void btrfs_folio_dec_eb_refs(const struc - ASSERT(folio_test_private(folio) && folio->mapping); - lockdep_assert_held(&folio->mapping->i_private_lock); - -- subpage = folio_get_private(folio); -- ASSERT(atomic_read(&subpage->eb_refs)); -- atomic_dec(&subpage->eb_refs); -+ bfs = folio_get_private(folio); -+ ASSERT(atomic_read(&bfs->eb_refs)); -+ atomic_dec(&bfs->eb_refs); - } - - static void btrfs_subpage_assert(const struct btrfs_fs_info *fs_info, -@@ -228,7 +223,7 @@ static void btrfs_subpage_clamp_range(st - static bool btrfs_subpage_end_and_test_lock(const struct btrfs_fs_info *fs_info, - struct folio *folio, u64 start, u32 len) - { -- struct btrfs_subpage *subpage = folio_get_private(folio); -+ struct btrfs_folio_state *bfs = folio_get_private(folio); - const int start_bit = subpage_calc_start_bit(fs_info, folio, locked, start, len); - const int nbits = (len >> fs_info->sectorsize_bits); - unsigned long flags; -@@ -238,7 +233,7 @@ static bool btrfs_subpage_end_and_test_l - - btrfs_subpage_assert(fs_info, folio, start, len); - -- spin_lock_irqsave(&subpage->lock, flags); -+ spin_lock_irqsave(&bfs->lock, flags); - /* - * We have call sites passing @lock_page into - * extent_clear_unlock_delalloc() for compression path. -@@ -246,18 +241,18 @@ static bool btrfs_subpage_end_and_test_l - * This @locked_page is locked by plain lock_page(), thus its - * subpage::locked is 0. Handle them in a special way. - */ -- if (atomic_read(&subpage->nr_locked) == 0) { -- spin_unlock_irqrestore(&subpage->lock, flags); -+ if (atomic_read(&bfs->nr_locked) == 0) { -+ spin_unlock_irqrestore(&bfs->lock, flags); - return true; - } - -- for_each_set_bit_from(bit, subpage->bitmaps, start_bit + nbits) { -- clear_bit(bit, subpage->bitmaps); -+ for_each_set_bit_from(bit, bfs->bitmaps, start_bit + nbits) { -+ clear_bit(bit, bfs->bitmaps); - cleared++; - } -- ASSERT(atomic_read(&subpage->nr_locked) >= cleared); -- last = atomic_sub_and_test(cleared, &subpage->nr_locked); -- spin_unlock_irqrestore(&subpage->lock, flags); -+ ASSERT(atomic_read(&bfs->nr_locked) >= cleared); -+ last = atomic_sub_and_test(cleared, &bfs->nr_locked); -+ spin_unlock_irqrestore(&bfs->lock, flags); - return last; - } - -@@ -280,7 +275,7 @@ static bool btrfs_subpage_end_and_test_l - void btrfs_folio_end_lock(const struct btrfs_fs_info *fs_info, - struct folio *folio, u64 start, u32 len) - { -- struct btrfs_subpage *subpage = folio_get_private(folio); -+ struct btrfs_folio_state *bfs = folio_get_private(folio); - - ASSERT(folio_test_locked(folio)); - -@@ -296,7 +291,7 @@ void btrfs_folio_end_lock(const struct b - * Since we own the page lock, no one else could touch subpage::locked - * and we are safe to do several atomic operations without spinlock. - */ -- if (atomic_read(&subpage->nr_locked) == 0) { -+ if (atomic_read(&bfs->nr_locked) == 0) { - /* No subpage lock, locked by plain lock_page(). */ - folio_unlock(folio); - return; -@@ -310,7 +305,7 @@ void btrfs_folio_end_lock(const struct b - void btrfs_folio_end_lock_bitmap(const struct btrfs_fs_info *fs_info, - struct folio *folio, unsigned long bitmap) - { -- struct btrfs_subpage *subpage = folio_get_private(folio); -+ struct btrfs_folio_state *bfs = folio_get_private(folio); - const unsigned int blocks_per_folio = btrfs_blocks_per_folio(fs_info, folio); - const int start_bit = blocks_per_folio * btrfs_bitmap_nr_locked; - unsigned long flags; -@@ -323,42 +318,42 @@ void btrfs_folio_end_lock_bitmap(const s - return; - } - -- if (atomic_read(&subpage->nr_locked) == 0) { -+ if (atomic_read(&bfs->nr_locked) == 0) { - /* No subpage lock, locked by plain lock_page(). */ - folio_unlock(folio); - return; - } - -- spin_lock_irqsave(&subpage->lock, flags); -+ spin_lock_irqsave(&bfs->lock, flags); - for_each_set_bit(bit, &bitmap, blocks_per_folio) { -- if (test_and_clear_bit(bit + start_bit, subpage->bitmaps)) -+ if (test_and_clear_bit(bit + start_bit, bfs->bitmaps)) - cleared++; - } -- ASSERT(atomic_read(&subpage->nr_locked) >= cleared); -- last = atomic_sub_and_test(cleared, &subpage->nr_locked); -- spin_unlock_irqrestore(&subpage->lock, flags); -+ ASSERT(atomic_read(&bfs->nr_locked) >= cleared); -+ last = atomic_sub_and_test(cleared, &bfs->nr_locked); -+ spin_unlock_irqrestore(&bfs->lock, flags); - if (last) - folio_unlock(folio); - } - - #define subpage_test_bitmap_all_set(fs_info, folio, name) \ - ({ \ -- struct btrfs_subpage *subpage = folio_get_private(folio); \ -+ struct btrfs_folio_state *bfs = folio_get_private(folio); \ - const unsigned int blocks_per_folio = \ - btrfs_blocks_per_folio(fs_info, folio); \ - \ -- bitmap_test_range_all_set(subpage->bitmaps, \ -+ bitmap_test_range_all_set(bfs->bitmaps, \ - blocks_per_folio * btrfs_bitmap_nr_##name, \ - blocks_per_folio); \ - }) - - #define subpage_test_bitmap_all_zero(fs_info, folio, name) \ - ({ \ -- struct btrfs_subpage *subpage = folio_get_private(folio); \ -+ struct btrfs_folio_state *bfs = folio_get_private(folio); \ - const unsigned int blocks_per_folio = \ - btrfs_blocks_per_folio(fs_info, folio); \ - \ -- bitmap_test_range_all_zero(subpage->bitmaps, \ -+ bitmap_test_range_all_zero(bfs->bitmaps, \ - blocks_per_folio * btrfs_bitmap_nr_##name, \ - blocks_per_folio); \ - }) -@@ -366,43 +361,43 @@ void btrfs_folio_end_lock_bitmap(const s - void btrfs_subpage_set_uptodate(const struct btrfs_fs_info *fs_info, - struct folio *folio, u64 start, u32 len) - { -- struct btrfs_subpage *subpage = folio_get_private(folio); -+ struct btrfs_folio_state *bfs = folio_get_private(folio); - unsigned int start_bit = subpage_calc_start_bit(fs_info, folio, - uptodate, start, len); - unsigned long flags; - -- spin_lock_irqsave(&subpage->lock, flags); -- bitmap_set(subpage->bitmaps, start_bit, len >> fs_info->sectorsize_bits); -+ spin_lock_irqsave(&bfs->lock, flags); -+ bitmap_set(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits); - if (subpage_test_bitmap_all_set(fs_info, folio, uptodate)) - folio_mark_uptodate(folio); -- spin_unlock_irqrestore(&subpage->lock, flags); -+ spin_unlock_irqrestore(&bfs->lock, flags); - } - - void btrfs_subpage_clear_uptodate(const struct btrfs_fs_info *fs_info, - struct folio *folio, u64 start, u32 len) - { -- struct btrfs_subpage *subpage = folio_get_private(folio); -+ struct btrfs_folio_state *bfs = folio_get_private(folio); - unsigned int start_bit = subpage_calc_start_bit(fs_info, folio, - uptodate, start, len); - unsigned long flags; - -- spin_lock_irqsave(&subpage->lock, flags); -- bitmap_clear(subpage->bitmaps, start_bit, len >> fs_info->sectorsize_bits); -+ spin_lock_irqsave(&bfs->lock, flags); -+ bitmap_clear(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits); - folio_clear_uptodate(folio); -- spin_unlock_irqrestore(&subpage->lock, flags); -+ spin_unlock_irqrestore(&bfs->lock, flags); - } - - void btrfs_subpage_set_dirty(const struct btrfs_fs_info *fs_info, - struct folio *folio, u64 start, u32 len) - { -- struct btrfs_subpage *subpage = folio_get_private(folio); -+ struct btrfs_folio_state *bfs = folio_get_private(folio); - unsigned int start_bit = subpage_calc_start_bit(fs_info, folio, - dirty, start, len); - unsigned long flags; - -- spin_lock_irqsave(&subpage->lock, flags); -- bitmap_set(subpage->bitmaps, start_bit, len >> fs_info->sectorsize_bits); -- spin_unlock_irqrestore(&subpage->lock, flags); -+ spin_lock_irqsave(&bfs->lock, flags); -+ bitmap_set(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits); -+ spin_unlock_irqrestore(&bfs->lock, flags); - folio_mark_dirty(folio); - } - -@@ -419,17 +414,17 @@ void btrfs_subpage_set_dirty(const struc - bool btrfs_subpage_clear_and_test_dirty(const struct btrfs_fs_info *fs_info, - struct folio *folio, u64 start, u32 len) - { -- struct btrfs_subpage *subpage = folio_get_private(folio); -+ struct btrfs_folio_state *bfs = folio_get_private(folio); - unsigned int start_bit = subpage_calc_start_bit(fs_info, folio, - dirty, start, len); - unsigned long flags; - bool last = false; - -- spin_lock_irqsave(&subpage->lock, flags); -- bitmap_clear(subpage->bitmaps, start_bit, len >> fs_info->sectorsize_bits); -+ spin_lock_irqsave(&bfs->lock, flags); -+ bitmap_clear(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits); - if (subpage_test_bitmap_all_zero(fs_info, folio, dirty)) - last = true; -- spin_unlock_irqrestore(&subpage->lock, flags); -+ spin_unlock_irqrestore(&bfs->lock, flags); - return last; - } - -@@ -446,91 +441,108 @@ void btrfs_subpage_clear_dirty(const str - void btrfs_subpage_set_writeback(const struct btrfs_fs_info *fs_info, - struct folio *folio, u64 start, u32 len) - { -- struct btrfs_subpage *subpage = folio_get_private(folio); -+ struct btrfs_folio_state *bfs = folio_get_private(folio); - unsigned int start_bit = subpage_calc_start_bit(fs_info, folio, - writeback, start, len); - unsigned long flags; - -- spin_lock_irqsave(&subpage->lock, flags); -- bitmap_set(subpage->bitmaps, start_bit, len >> fs_info->sectorsize_bits); -+ spin_lock_irqsave(&bfs->lock, flags); -+ bitmap_set(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits); -+ -+ /* -+ * Don't clear the TOWRITE tag when starting writeback on a still-dirty -+ * folio. Doing so can cause WB_SYNC_ALL writepages() to overlook it, -+ * assume writeback is complete, and exit too early — violating sync -+ * ordering guarantees. -+ */ - if (!folio_test_writeback(folio)) -- folio_start_writeback(folio); -- spin_unlock_irqrestore(&subpage->lock, flags); -+ __folio_start_writeback(folio, true); -+ if (!folio_test_dirty(folio)) { -+ struct address_space *mapping = folio_mapping(folio); -+ XA_STATE(xas, &mapping->i_pages, folio->index); -+ unsigned long flags; -+ -+ xas_lock_irqsave(&xas, flags); -+ xas_load(&xas); -+ xas_clear_mark(&xas, PAGECACHE_TAG_TOWRITE); -+ xas_unlock_irqrestore(&xas, flags); -+ } -+ spin_unlock_irqrestore(&bfs->lock, flags); - } - - void btrfs_subpage_clear_writeback(const struct btrfs_fs_info *fs_info, - struct folio *folio, u64 start, u32 len) - { -- struct btrfs_subpage *subpage = folio_get_private(folio); -+ struct btrfs_folio_state *bfs = folio_get_private(folio); - unsigned int start_bit = subpage_calc_start_bit(fs_info, folio, - writeback, start, len); - unsigned long flags; - -- spin_lock_irqsave(&subpage->lock, flags); -- bitmap_clear(subpage->bitmaps, start_bit, len >> fs_info->sectorsize_bits); -+ spin_lock_irqsave(&bfs->lock, flags); -+ bitmap_clear(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits); - if (subpage_test_bitmap_all_zero(fs_info, folio, writeback)) { - ASSERT(folio_test_writeback(folio)); - folio_end_writeback(folio); - } -- spin_unlock_irqrestore(&subpage->lock, flags); -+ spin_unlock_irqrestore(&bfs->lock, flags); - } - - void btrfs_subpage_set_ordered(const struct btrfs_fs_info *fs_info, - struct folio *folio, u64 start, u32 len) - { -- struct btrfs_subpage *subpage = folio_get_private(folio); -+ struct btrfs_folio_state *bfs = folio_get_private(folio); - unsigned int start_bit = subpage_calc_start_bit(fs_info, folio, - ordered, start, len); - unsigned long flags; - -- spin_lock_irqsave(&subpage->lock, flags); -- bitmap_set(subpage->bitmaps, start_bit, len >> fs_info->sectorsize_bits); -+ spin_lock_irqsave(&bfs->lock, flags); -+ bitmap_set(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits); - folio_set_ordered(folio); -- spin_unlock_irqrestore(&subpage->lock, flags); -+ spin_unlock_irqrestore(&bfs->lock, flags); - } - - void btrfs_subpage_clear_ordered(const struct btrfs_fs_info *fs_info, - struct folio *folio, u64 start, u32 len) - { -- struct btrfs_subpage *subpage = folio_get_private(folio); -+ struct btrfs_folio_state *bfs = folio_get_private(folio); - unsigned int start_bit = subpage_calc_start_bit(fs_info, folio, - ordered, start, len); - unsigned long flags; - -- spin_lock_irqsave(&subpage->lock, flags); -- bitmap_clear(subpage->bitmaps, start_bit, len >> fs_info->sectorsize_bits); -+ spin_lock_irqsave(&bfs->lock, flags); -+ bitmap_clear(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits); - if (subpage_test_bitmap_all_zero(fs_info, folio, ordered)) - folio_clear_ordered(folio); -- spin_unlock_irqrestore(&subpage->lock, flags); -+ spin_unlock_irqrestore(&bfs->lock, flags); - } - - void btrfs_subpage_set_checked(const struct btrfs_fs_info *fs_info, - struct folio *folio, u64 start, u32 len) - { -- struct btrfs_subpage *subpage = folio_get_private(folio); -+ struct btrfs_folio_state *bfs = folio_get_private(folio); - unsigned int start_bit = subpage_calc_start_bit(fs_info, folio, - checked, start, len); - unsigned long flags; - -- spin_lock_irqsave(&subpage->lock, flags); -- bitmap_set(subpage->bitmaps, start_bit, len >> fs_info->sectorsize_bits); -+ spin_lock_irqsave(&bfs->lock, flags); -+ bitmap_set(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits); - if (subpage_test_bitmap_all_set(fs_info, folio, checked)) - folio_set_checked(folio); -- spin_unlock_irqrestore(&subpage->lock, flags); -+ spin_unlock_irqrestore(&bfs->lock, flags); - } - - void btrfs_subpage_clear_checked(const struct btrfs_fs_info *fs_info, - struct folio *folio, u64 start, u32 len) - { -- struct btrfs_subpage *subpage = folio_get_private(folio); -+ struct btrfs_folio_state *bfs = folio_get_private(folio); - unsigned int start_bit = subpage_calc_start_bit(fs_info, folio, - checked, start, len); - unsigned long flags; - -- spin_lock_irqsave(&subpage->lock, flags); -- bitmap_clear(subpage->bitmaps, start_bit, len >> fs_info->sectorsize_bits); -+ spin_lock_irqsave(&bfs->lock, flags); -+ bitmap_clear(bfs->bitmaps, start_bit, len >> fs_info->sectorsize_bits); - folio_clear_checked(folio); -- spin_unlock_irqrestore(&subpage->lock, flags); -+ spin_unlock_irqrestore(&bfs->lock, flags); - } - - /* -@@ -541,16 +553,16 @@ void btrfs_subpage_clear_checked(const s - bool btrfs_subpage_test_##name(const struct btrfs_fs_info *fs_info, \ - struct folio *folio, u64 start, u32 len) \ - { \ -- struct btrfs_subpage *subpage = folio_get_private(folio); \ -+ struct btrfs_folio_state *bfs = folio_get_private(folio); \ - unsigned int start_bit = subpage_calc_start_bit(fs_info, folio, \ - name, start, len); \ - unsigned long flags; \ - bool ret; \ - \ -- spin_lock_irqsave(&subpage->lock, flags); \ -- ret = bitmap_test_range_all_set(subpage->bitmaps, start_bit, \ -+ spin_lock_irqsave(&bfs->lock, flags); \ -+ ret = bitmap_test_range_all_set(bfs->bitmaps, start_bit, \ - len >> fs_info->sectorsize_bits); \ -- spin_unlock_irqrestore(&subpage->lock, flags); \ -+ spin_unlock_irqrestore(&bfs->lock, flags); \ - return ret; \ - } - IMPLEMENT_BTRFS_SUBPAGE_TEST_OP(uptodate); -@@ -662,10 +674,10 @@ IMPLEMENT_BTRFS_PAGE_OPS(checked, folio_ - { \ - const unsigned int blocks_per_folio = \ - btrfs_blocks_per_folio(fs_info, folio); \ -- const struct btrfs_subpage *subpage = folio_get_private(folio); \ -+ const struct btrfs_folio_state *bfs = folio_get_private(folio); \ - \ - ASSERT(blocks_per_folio <= BITS_PER_LONG); \ -- *dst = bitmap_read(subpage->bitmaps, \ -+ *dst = bitmap_read(bfs->bitmaps, \ - blocks_per_folio * btrfs_bitmap_nr_##name, \ - blocks_per_folio); \ - } -@@ -690,7 +702,7 @@ IMPLEMENT_BTRFS_PAGE_OPS(checked, folio_ - void btrfs_folio_assert_not_dirty(const struct btrfs_fs_info *fs_info, - struct folio *folio, u64 start, u32 len) - { -- struct btrfs_subpage *subpage; -+ struct btrfs_folio_state *bfs; - unsigned int start_bit; - unsigned int nbits; - unsigned long flags; -@@ -705,15 +717,15 @@ void btrfs_folio_assert_not_dirty(const - - start_bit = subpage_calc_start_bit(fs_info, folio, dirty, start, len); - nbits = len >> fs_info->sectorsize_bits; -- subpage = folio_get_private(folio); -- ASSERT(subpage); -- spin_lock_irqsave(&subpage->lock, flags); -- if (unlikely(!bitmap_test_range_all_zero(subpage->bitmaps, start_bit, nbits))) { -+ bfs = folio_get_private(folio); -+ ASSERT(bfs); -+ spin_lock_irqsave(&bfs->lock, flags); -+ if (unlikely(!bitmap_test_range_all_zero(bfs->bitmaps, start_bit, nbits))) { - SUBPAGE_DUMP_BITMAP(fs_info, folio, dirty, start, len); -- ASSERT(bitmap_test_range_all_zero(subpage->bitmaps, start_bit, nbits)); -+ ASSERT(bitmap_test_range_all_zero(bfs->bitmaps, start_bit, nbits)); - } -- ASSERT(bitmap_test_range_all_zero(subpage->bitmaps, start_bit, nbits)); -- spin_unlock_irqrestore(&subpage->lock, flags); -+ ASSERT(bitmap_test_range_all_zero(bfs->bitmaps, start_bit, nbits)); -+ spin_unlock_irqrestore(&bfs->lock, flags); - } - - /* -@@ -726,7 +738,7 @@ void btrfs_folio_assert_not_dirty(const - void btrfs_folio_set_lock(const struct btrfs_fs_info *fs_info, - struct folio *folio, u64 start, u32 len) - { -- struct btrfs_subpage *subpage; -+ struct btrfs_folio_state *bfs; - unsigned long flags; - unsigned int start_bit; - unsigned int nbits; -@@ -736,19 +748,19 @@ void btrfs_folio_set_lock(const struct b - if (unlikely(!fs_info) || !btrfs_is_subpage(fs_info, folio)) - return; - -- subpage = folio_get_private(folio); -+ bfs = folio_get_private(folio); - start_bit = subpage_calc_start_bit(fs_info, folio, locked, start, len); - nbits = len >> fs_info->sectorsize_bits; -- spin_lock_irqsave(&subpage->lock, flags); -+ spin_lock_irqsave(&bfs->lock, flags); - /* Target range should not yet be locked. */ -- if (unlikely(!bitmap_test_range_all_zero(subpage->bitmaps, start_bit, nbits))) { -+ if (unlikely(!bitmap_test_range_all_zero(bfs->bitmaps, start_bit, nbits))) { - SUBPAGE_DUMP_BITMAP(fs_info, folio, locked, start, len); -- ASSERT(bitmap_test_range_all_zero(subpage->bitmaps, start_bit, nbits)); -+ ASSERT(bitmap_test_range_all_zero(bfs->bitmaps, start_bit, nbits)); - } -- bitmap_set(subpage->bitmaps, start_bit, nbits); -- ret = atomic_add_return(nbits, &subpage->nr_locked); -+ bitmap_set(bfs->bitmaps, start_bit, nbits); -+ ret = atomic_add_return(nbits, &bfs->nr_locked); - ASSERT(ret <= btrfs_blocks_per_folio(fs_info, folio)); -- spin_unlock_irqrestore(&subpage->lock, flags); -+ spin_unlock_irqrestore(&bfs->lock, flags); - } - - /* -@@ -776,7 +788,7 @@ bool btrfs_meta_folio_clear_and_test_dir - void __cold btrfs_subpage_dump_bitmap(const struct btrfs_fs_info *fs_info, - struct folio *folio, u64 start, u32 len) - { -- struct btrfs_subpage *subpage; -+ struct btrfs_folio_state *bfs; - const unsigned int blocks_per_folio = btrfs_blocks_per_folio(fs_info, folio); - unsigned long uptodate_bitmap; - unsigned long dirty_bitmap; -@@ -788,18 +800,18 @@ void __cold btrfs_subpage_dump_bitmap(co - - ASSERT(folio_test_private(folio) && folio_get_private(folio)); - ASSERT(blocks_per_folio > 1); -- subpage = folio_get_private(folio); -+ bfs = folio_get_private(folio); - -- spin_lock_irqsave(&subpage->lock, flags); -+ spin_lock_irqsave(&bfs->lock, flags); - GET_SUBPAGE_BITMAP(fs_info, folio, uptodate, &uptodate_bitmap); - GET_SUBPAGE_BITMAP(fs_info, folio, dirty, &dirty_bitmap); - GET_SUBPAGE_BITMAP(fs_info, folio, writeback, &writeback_bitmap); - GET_SUBPAGE_BITMAP(fs_info, folio, ordered, &ordered_bitmap); - GET_SUBPAGE_BITMAP(fs_info, folio, checked, &checked_bitmap); - GET_SUBPAGE_BITMAP(fs_info, folio, locked, &locked_bitmap); -- spin_unlock_irqrestore(&subpage->lock, flags); -+ spin_unlock_irqrestore(&bfs->lock, flags); - -- dump_page(folio_page(folio, 0), "btrfs subpage dump"); -+ dump_page(folio_page(folio, 0), "btrfs folio state dump"); - btrfs_warn(fs_info, - "start=%llu len=%u page=%llu, bitmaps uptodate=%*pbl dirty=%*pbl locked=%*pbl writeback=%*pbl ordered=%*pbl checked=%*pbl", - start, len, folio_pos(folio), -@@ -815,14 +827,14 @@ void btrfs_get_subpage_dirty_bitmap(stru - struct folio *folio, - unsigned long *ret_bitmap) - { -- struct btrfs_subpage *subpage; -+ struct btrfs_folio_state *bfs; - unsigned long flags; - - ASSERT(folio_test_private(folio) && folio_get_private(folio)); - ASSERT(btrfs_blocks_per_folio(fs_info, folio) > 1); -- subpage = folio_get_private(folio); -+ bfs = folio_get_private(folio); - -- spin_lock_irqsave(&subpage->lock, flags); -+ spin_lock_irqsave(&bfs->lock, flags); - GET_SUBPAGE_BITMAP(fs_info, folio, dirty, ret_bitmap); -- spin_unlock_irqrestore(&subpage->lock, flags); -+ spin_unlock_irqrestore(&bfs->lock, flags); - } -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/subpage.h BPI-Router-Linux-kernel-6.16.12/fs/btrfs/subpage.h ---- BPI-Router-Linux-kernel/fs/btrfs/subpage.h 2025-10-22 13:53:23.503327747 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/subpage.h 2025-10-22 13:53:56.703168235 -0400 -@@ -32,9 +32,31 @@ struct folio; - enum { - btrfs_bitmap_nr_uptodate = 0, - btrfs_bitmap_nr_dirty, -+ -+ /* -+ * This can be changed to atomic eventually. But this change will rely -+ * on the async delalloc range rework for locked bitmap. As async -+ * delalloc can unlock its range and mark blocks writeback at random -+ * timing. -+ */ - btrfs_bitmap_nr_writeback, -+ -+ /* -+ * The ordered and checked flags are for COW fixup, already marked -+ * deprecated, and will be removed eventually. -+ */ - btrfs_bitmap_nr_ordered, - btrfs_bitmap_nr_checked, -+ -+ /* -+ * The locked bit is for async delalloc range (compression), currently -+ * async extent is queued with the range locked, until the compression -+ * is done. -+ * So an async extent can unlock the range at any random timing. -+ * -+ * This will need a rework on the async extent lifespan (mark writeback -+ * and do compression) before deprecating this flag. -+ */ - btrfs_bitmap_nr_locked, - btrfs_bitmap_nr_max - }; -@@ -43,7 +65,7 @@ enum { - * Structure to trace status of each sector inside a page, attached to - * page::private for both data and metadata inodes. - */ --struct btrfs_subpage { -+struct btrfs_folio_state { - /* Common members for both data and metadata pages */ - spinlock_t lock; - union { -@@ -51,7 +73,7 @@ struct btrfs_subpage { - * Structures only used by metadata - * - * @eb_refs should only be operated under private_lock, as it -- * manages whether the subpage can be detached. -+ * manages whether the btrfs_folio_state can be detached. - */ - atomic_t eb_refs; - -@@ -65,7 +87,7 @@ struct btrfs_subpage { - unsigned long bitmaps[]; - }; - --enum btrfs_subpage_type { -+enum btrfs_folio_type { - BTRFS_SUBPAGE_METADATA, - BTRFS_SUBPAGE_DATA, - }; -@@ -105,15 +127,18 @@ static inline bool btrfs_is_subpage(cons - } - #endif - --int btrfs_attach_subpage(const struct btrfs_fs_info *fs_info, -- struct folio *folio, enum btrfs_subpage_type type); --void btrfs_detach_subpage(const struct btrfs_fs_info *fs_info, struct folio *folio, -- enum btrfs_subpage_type type); -+int btrfs_attach_folio_state(const struct btrfs_fs_info *fs_info, -+ struct folio *folio, enum btrfs_folio_type type); -+void btrfs_detach_folio_state(const struct btrfs_fs_info *fs_info, struct folio *folio, -+ enum btrfs_folio_type type); - - /* Allocate additional data where page represents more than one sector */ --struct btrfs_subpage *btrfs_alloc_subpage(const struct btrfs_fs_info *fs_info, -- size_t fsize, enum btrfs_subpage_type type); --void btrfs_free_subpage(struct btrfs_subpage *subpage); -+struct btrfs_folio_state *btrfs_alloc_folio_state(const struct btrfs_fs_info *fs_info, -+ size_t fsize, enum btrfs_folio_type type); -+static inline void btrfs_free_folio_state(struct btrfs_folio_state *bfs) -+{ -+ kfree(bfs); -+} - - void btrfs_folio_inc_eb_refs(const struct btrfs_fs_info *fs_info, struct folio *folio); - void btrfs_folio_dec_eb_refs(const struct btrfs_fs_info *fs_info, struct folio *folio); -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/super.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/super.c ---- BPI-Router-Linux-kernel/fs/btrfs/super.c 2025-10-22 13:53:23.503327747 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/super.c 2025-10-22 13:53:56.703168235 -0400 -@@ -88,6 +88,9 @@ struct btrfs_fs_context { - refcount_t refs; - }; - -+static void btrfs_emit_options(struct btrfs_fs_info *info, -+ struct btrfs_fs_context *old); -+ - enum { - Opt_acl, - Opt_clear_cache, -@@ -689,12 +692,9 @@ bool btrfs_check_options(const struct bt - - if (!test_bit(BTRFS_FS_STATE_REMOUNTING, &info->fs_state)) { - if (btrfs_raw_test_opt(*mount_opt, SPACE_CACHE)) { -- btrfs_info(info, "disk space caching is enabled"); - btrfs_warn(info, - "space cache v1 is being deprecated and will be removed in a future release, please use -o space_cache=v2"); - } -- if (btrfs_raw_test_opt(*mount_opt, FREE_SPACE_TREE)) -- btrfs_info(info, "using free-space-tree"); - } - - return ret; -@@ -971,6 +971,8 @@ static int btrfs_fill_super(struct super - return err; - } - -+ btrfs_emit_options(fs_info, NULL); -+ - inode = btrfs_iget(BTRFS_FIRST_FREE_OBJECTID, fs_info->fs_root); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); -@@ -1428,7 +1430,7 @@ static void btrfs_emit_options(struct bt - { - btrfs_info_if_set(info, old, NODATASUM, "setting nodatasum"); - btrfs_info_if_set(info, old, DEGRADED, "allowing degraded mounts"); -- btrfs_info_if_set(info, old, NODATASUM, "setting nodatasum"); -+ btrfs_info_if_set(info, old, NODATACOW, "setting nodatacow"); - btrfs_info_if_set(info, old, SSD, "enabling ssd optimizations"); - btrfs_info_if_set(info, old, SSD_SPREAD, "using spread ssd allocation scheme"); - btrfs_info_if_set(info, old, NOBARRIER, "turning off barriers"); -@@ -1450,10 +1452,11 @@ static void btrfs_emit_options(struct bt - btrfs_info_if_set(info, old, IGNOREMETACSUMS, "ignoring meta csums"); - btrfs_info_if_set(info, old, IGNORESUPERFLAGS, "ignoring unknown super block flags"); - -+ btrfs_info_if_unset(info, old, NODATASUM, "setting datasum"); - btrfs_info_if_unset(info, old, NODATACOW, "setting datacow"); - btrfs_info_if_unset(info, old, SSD, "not using ssd optimizations"); - btrfs_info_if_unset(info, old, SSD_SPREAD, "not using spread ssd allocation scheme"); -- btrfs_info_if_unset(info, old, NOBARRIER, "turning off barriers"); -+ btrfs_info_if_unset(info, old, NOBARRIER, "turning on barriers"); - btrfs_info_if_unset(info, old, NOTREELOG, "enabling tree log"); - btrfs_info_if_unset(info, old, SPACE_CACHE, "disabling disk space caching"); - btrfs_info_if_unset(info, old, FREE_SPACE_TREE, "disabling free space tree"); -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/transaction.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/transaction.c ---- BPI-Router-Linux-kernel/fs/btrfs/transaction.c 2025-10-22 13:53:23.503327747 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/transaction.c 2025-10-22 13:53:56.703168235 -0400 -@@ -1735,8 +1735,10 @@ static noinline int create_pending_snaps - - ret = btrfs_create_qgroup(trans, objectid); - if (ret && ret != -EEXIST) { -- btrfs_abort_transaction(trans, ret); -- goto fail; -+ if (ret != -ENOTCONN || btrfs_qgroup_enabled(fs_info)) { -+ btrfs_abort_transaction(trans, ret); -+ goto fail; -+ } - } - - /* -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/tree-checker.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/tree-checker.c ---- BPI-Router-Linux-kernel/fs/btrfs/tree-checker.c 2025-10-22 13:53:23.503327747 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/tree-checker.c 2025-10-22 13:53:56.703168235 -0400 -@@ -1756,10 +1756,10 @@ static int check_inode_ref(struct extent - while (ptr < end) { - u16 namelen; - -- if (unlikely(ptr + sizeof(iref) > end)) { -+ if (unlikely(ptr + sizeof(*iref) > end)) { - inode_ref_err(leaf, slot, - "inode ref overflow, ptr %lu end %lu inode_ref_size %zu", -- ptr, end, sizeof(iref)); -+ ptr, end, sizeof(*iref)); - return -EUCLEAN; - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/tree-log.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/tree-log.c ---- BPI-Router-Linux-kernel/fs/btrfs/tree-log.c 2025-10-22 13:53:23.507327727 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/tree-log.c 2025-10-22 13:53:56.703168235 -0400 -@@ -143,6 +143,9 @@ static struct btrfs_inode *btrfs_iget_lo - unsigned int nofs_flag; - struct btrfs_inode *inode; - -+ /* Only meant to be called for subvolume roots and not for log roots. */ -+ ASSERT(is_fstree(btrfs_root_id(root))); -+ - /* - * We're holding a transaction handle whether we are logging or - * replaying a log tree, so we must make sure NOFS semantics apply -@@ -318,8 +321,7 @@ struct walk_control { - - /* - * Ignore any items from the inode currently being processed. Needs -- * to be set every time we find a BTRFS_INODE_ITEM_KEY and we are in -- * the LOG_WALK_REPLAY_INODES stage. -+ * to be set every time we find a BTRFS_INODE_ITEM_KEY. - */ - bool ignore_cur_inode; - -@@ -604,21 +606,6 @@ static int read_alloc_one_name(struct ex - return 0; - } - --/* -- * simple helper to read an inode off the disk from a given root -- * This can only be called for subvolume roots and not for the log -- */ --static noinline struct btrfs_inode *read_one_inode(struct btrfs_root *root, -- u64 objectid) --{ -- struct btrfs_inode *inode; -- -- inode = btrfs_iget_logging(objectid, root); -- if (IS_ERR(inode)) -- return NULL; -- return inode; --} -- - /* replays a single extent in 'eb' at 'slot' with 'key' into the - * subvolume 'root'. path is released on entry and should be released - * on exit. -@@ -668,15 +655,15 @@ static noinline int replay_one_extent(st - extent_end = ALIGN(start + size, - fs_info->sectorsize); - } else { -- ret = 0; -- goto out; -+ btrfs_err(fs_info, -+ "unexpected extent type=%d root=%llu inode=%llu offset=%llu", -+ found_type, btrfs_root_id(root), key->objectid, key->offset); -+ return -EUCLEAN; - } - -- inode = read_one_inode(root, key->objectid); -- if (!inode) { -- ret = -EIO; -- goto out; -- } -+ inode = btrfs_iget_logging(key->objectid, root); -+ if (IS_ERR(inode)) -+ return PTR_ERR(inode); - - /* - * first check to see if we already have this extent in the -@@ -948,9 +935,10 @@ static noinline int drop_one_dir_item(st - - btrfs_release_path(path); - -- inode = read_one_inode(root, location.objectid); -- if (!inode) { -- ret = -EIO; -+ inode = btrfs_iget_logging(location.objectid, root); -+ if (IS_ERR(inode)) { -+ ret = PTR_ERR(inode); -+ inode = NULL; - goto out; - } - -@@ -961,7 +949,8 @@ static noinline int drop_one_dir_item(st - ret = unlink_inode_for_log_replay(trans, dir, inode, &name); - out: - kfree(name.name); -- iput(&inode->vfs_inode); -+ if (inode) -+ iput(&inode->vfs_inode); - return ret; - } - -@@ -1072,7 +1061,9 @@ again: - search_key.type = BTRFS_INODE_REF_KEY; - search_key.offset = parent_objectid; - ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0); -- if (ret == 0) { -+ if (ret < 0) { -+ return ret; -+ } else if (ret == 0) { - struct btrfs_inode_ref *victim_ref; - unsigned long ptr; - unsigned long ptr_end; -@@ -1145,13 +1136,13 @@ again: - struct fscrypt_str victim_name; - - extref = (struct btrfs_inode_extref *)(base + cur_offset); -+ victim_name.len = btrfs_inode_extref_name_len(leaf, extref); - - if (btrfs_inode_extref_parent(leaf, extref) != parent_objectid) - goto next; - - ret = read_alloc_one_name(leaf, &extref->name, -- btrfs_inode_extref_name_len(leaf, extref), -- &victim_name); -+ victim_name.len, &victim_name); - if (ret) - return ret; - -@@ -1166,18 +1157,18 @@ again: - kfree(victim_name.name); - return ret; - } else if (!ret) { -- ret = -ENOENT; -- victim_parent = read_one_inode(root, -- parent_objectid); -- if (victim_parent) { -+ victim_parent = btrfs_iget_logging(parent_objectid, root); -+ if (IS_ERR(victim_parent)) { -+ ret = PTR_ERR(victim_parent); -+ } else { - inc_nlink(&inode->vfs_inode); - btrfs_release_path(path); - - ret = unlink_inode_for_log_replay(trans, - victim_parent, - inode, &victim_name); -+ iput(&victim_parent->vfs_inode); - } -- iput(&victim_parent->vfs_inode); - kfree(victim_name.name); - if (ret) - return ret; -@@ -1314,9 +1305,9 @@ again: - struct btrfs_inode *dir; - - btrfs_release_path(path); -- dir = read_one_inode(root, parent_id); -- if (!dir) { -- ret = -ENOENT; -+ dir = btrfs_iget_logging(parent_id, root); -+ if (IS_ERR(dir)) { -+ ret = PTR_ERR(dir); - kfree(name.name); - goto out; - } -@@ -1388,15 +1379,19 @@ static noinline int add_inode_ref(struct - * copy the back ref in. The link count fixup code will take - * care of the rest - */ -- dir = read_one_inode(root, parent_objectid); -- if (!dir) { -- ret = -ENOENT; -+ dir = btrfs_iget_logging(parent_objectid, root); -+ if (IS_ERR(dir)) { -+ ret = PTR_ERR(dir); -+ if (ret == -ENOENT) -+ ret = 0; -+ dir = NULL; - goto out; - } - -- inode = read_one_inode(root, inode_objectid); -- if (!inode) { -- ret = -EIO; -+ inode = btrfs_iget_logging(inode_objectid, root); -+ if (IS_ERR(inode)) { -+ ret = PTR_ERR(inode); -+ inode = NULL; - goto out; - } - -@@ -1404,21 +1399,41 @@ static noinline int add_inode_ref(struct - if (log_ref_ver) { - ret = extref_get_fields(eb, ref_ptr, &name, - &ref_index, &parent_objectid); -+ if (ret) -+ goto out; - /* - * parent object can change from one array - * item to another. - */ -- if (!dir) -- dir = read_one_inode(root, parent_objectid); - if (!dir) { -- ret = -ENOENT; -- goto out; -+ dir = btrfs_iget_logging(parent_objectid, root); -+ if (IS_ERR(dir)) { -+ ret = PTR_ERR(dir); -+ dir = NULL; -+ /* -+ * A new parent dir may have not been -+ * logged and not exist in the subvolume -+ * tree, see the comment above before -+ * the loop when getting the first -+ * parent dir. -+ */ -+ if (ret == -ENOENT) { -+ /* -+ * The next extref may refer to -+ * another parent dir that -+ * exists, so continue. -+ */ -+ ret = 0; -+ goto next; -+ } -+ goto out; -+ } - } - } else { - ret = ref_get_fields(eb, ref_ptr, &name, &ref_index); -+ if (ret) -+ goto out; - } -- if (ret) -- goto out; - - ret = inode_in_dir(root, path, btrfs_ino(dir), btrfs_ino(inode), - ref_index, &name); -@@ -1452,10 +1467,11 @@ static noinline int add_inode_ref(struct - } - /* Else, ret == 1, we already have a perfect match, we're done. */ - -+next: - ref_ptr = (unsigned long)(ref_ptr + ref_struct_size) + name.len; - kfree(name.name); - name.name = NULL; -- if (log_ref_ver) { -+ if (log_ref_ver && dir) { - iput(&dir->vfs_inode); - dir = NULL; - } -@@ -1681,9 +1697,9 @@ static noinline int fixup_inode_link_cou - break; - - btrfs_release_path(path); -- inode = read_one_inode(root, key.offset); -- if (!inode) { -- ret = -EIO; -+ inode = btrfs_iget_logging(key.offset, root); -+ if (IS_ERR(inode)) { -+ ret = PTR_ERR(inode); - break; - } - -@@ -1719,9 +1735,9 @@ static noinline int link_to_fixup_dir(st - struct btrfs_inode *inode; - struct inode *vfs_inode; - -- inode = read_one_inode(root, objectid); -- if (!inode) -- return -EIO; -+ inode = btrfs_iget_logging(objectid, root); -+ if (IS_ERR(inode)) -+ return PTR_ERR(inode); - - vfs_inode = &inode->vfs_inode; - key.objectid = BTRFS_TREE_LOG_FIXUP_OBJECTID; -@@ -1760,14 +1776,14 @@ static noinline int insert_one_name(stru - struct btrfs_inode *dir; - int ret; - -- inode = read_one_inode(root, location->objectid); -- if (!inode) -- return -ENOENT; -+ inode = btrfs_iget_logging(location->objectid, root); -+ if (IS_ERR(inode)) -+ return PTR_ERR(inode); - -- dir = read_one_inode(root, dirid); -- if (!dir) { -+ dir = btrfs_iget_logging(dirid, root); -+ if (IS_ERR(dir)) { - iput(&inode->vfs_inode); -- return -EIO; -+ return PTR_ERR(dir); - } - - ret = btrfs_add_link(trans, dir, inode, name, 1, index); -@@ -1844,9 +1860,9 @@ static noinline int replay_one_name(stru - bool update_size = true; - bool name_added = false; - -- dir = read_one_inode(root, key->objectid); -- if (!dir) -- return -EIO; -+ dir = btrfs_iget_logging(key->objectid, root); -+ if (IS_ERR(dir)) -+ return PTR_ERR(dir); - - ret = read_alloc_one_name(eb, di + 1, btrfs_dir_name_len(eb, di), &name); - if (ret) -@@ -1917,7 +1933,7 @@ static noinline int replay_one_name(stru - - search_key.objectid = log_key.objectid; - search_key.type = BTRFS_INODE_EXTREF_KEY; -- search_key.offset = key->objectid; -+ search_key.offset = btrfs_extref_hash(key->objectid, name.name, name.len); - ret = backref_in_log(root->log_root, &search_key, key->objectid, &name); - if (ret < 0) { - goto out; -@@ -2146,9 +2162,10 @@ static noinline int check_item_in_log(st - btrfs_dir_item_key_to_cpu(eb, di, &location); - btrfs_release_path(path); - btrfs_release_path(log_path); -- inode = read_one_inode(root, location.objectid); -- if (!inode) { -- ret = -EIO; -+ inode = btrfs_iget_logging(location.objectid, root); -+ if (IS_ERR(inode)) { -+ ret = PTR_ERR(inode); -+ inode = NULL; - goto out; - } - -@@ -2300,14 +2317,17 @@ static noinline int replay_dir_deletes(s - if (!log_path) - return -ENOMEM; - -- dir = read_one_inode(root, dirid); -- /* it isn't an error if the inode isn't there, that can happen -- * because we replay the deletes before we copy in the inode item -- * from the log -+ dir = btrfs_iget_logging(dirid, root); -+ /* -+ * It isn't an error if the inode isn't there, that can happen because -+ * we replay the deletes before we copy in the inode item from the log. - */ -- if (!dir) { -+ if (IS_ERR(dir)) { - btrfs_free_path(log_path); -- return 0; -+ ret = PTR_ERR(dir); -+ if (ret == -ENOENT) -+ ret = 0; -+ return ret; - } - - range_start = 0; -@@ -2413,23 +2433,30 @@ static int replay_one_buffer(struct btrf - - nritems = btrfs_header_nritems(eb); - for (i = 0; i < nritems; i++) { -- btrfs_item_key_to_cpu(eb, &key, i); -+ struct btrfs_inode_item *inode_item; - -- /* inode keys are done during the first stage */ -- if (key.type == BTRFS_INODE_ITEM_KEY && -- wc->stage == LOG_WALK_REPLAY_INODES) { -- struct btrfs_inode_item *inode_item; -- u32 mode; -+ btrfs_item_key_to_cpu(eb, &key, i); - -- inode_item = btrfs_item_ptr(eb, i, -- struct btrfs_inode_item); -+ if (key.type == BTRFS_INODE_ITEM_KEY) { -+ inode_item = btrfs_item_ptr(eb, i, struct btrfs_inode_item); - /* -- * If we have a tmpfile (O_TMPFILE) that got fsync'ed -- * and never got linked before the fsync, skip it, as -- * replaying it is pointless since it would be deleted -- * later. We skip logging tmpfiles, but it's always -- * possible we are replaying a log created with a kernel -- * that used to log tmpfiles. -+ * An inode with no links is either: -+ * -+ * 1) A tmpfile (O_TMPFILE) that got fsync'ed and never -+ * got linked before the fsync, skip it, as replaying -+ * it is pointless since it would be deleted later. -+ * We skip logging tmpfiles, but it's always possible -+ * we are replaying a log created with a kernel that -+ * used to log tmpfiles; -+ * -+ * 2) A non-tmpfile which got its last link deleted -+ * while holding an open fd on it and later got -+ * fsynced through that fd. We always log the -+ * parent inodes when inode->last_unlink_trans is -+ * set to the current transaction, so ignore all the -+ * inode items for this inode. We will delete the -+ * inode when processing the parent directory with -+ * replay_dir_deletes(). - */ - if (btrfs_inode_nlink(eb, inode_item) == 0) { - wc->ignore_cur_inode = true; -@@ -2437,8 +2464,14 @@ static int replay_one_buffer(struct btrf - } else { - wc->ignore_cur_inode = false; - } -- ret = replay_xattr_deletes(wc->trans, root, log, -- path, key.objectid); -+ } -+ -+ /* Inode keys are done during the first stage. */ -+ if (key.type == BTRFS_INODE_ITEM_KEY && -+ wc->stage == LOG_WALK_REPLAY_INODES) { -+ u32 mode; -+ -+ ret = replay_xattr_deletes(wc->trans, root, log, path, key.objectid); - if (ret) - break; - mode = btrfs_inode_mode(eb, inode_item); -@@ -2466,9 +2499,9 @@ static int replay_one_buffer(struct btrf - struct btrfs_inode *inode; - u64 from; - -- inode = read_one_inode(root, key.objectid); -- if (!inode) { -- ret = -EIO; -+ inode = btrfs_iget_logging(key.objectid, root); -+ if (IS_ERR(inode)) { -+ ret = PTR_ERR(inode); - break; - } - from = ALIGN(i_size_read(&inode->vfs_inode), -@@ -2519,9 +2552,8 @@ static int replay_one_buffer(struct btrf - key.type == BTRFS_INODE_EXTREF_KEY) { - ret = add_inode_ref(wc->trans, root, log, path, - eb, i, &key); -- if (ret && ret != -ENOENT) -+ if (ret) - break; -- ret = 0; - } else if (key.type == BTRFS_EXTENT_DATA_KEY) { - ret = replay_one_extent(wc->trans, root, path, - eb, i, &key); -@@ -2542,14 +2574,14 @@ static int replay_one_buffer(struct btrf - /* - * Correctly adjust the reserved bytes occupied by a log tree extent buffer - */ --static void unaccount_log_buffer(struct btrfs_fs_info *fs_info, u64 start) -+static int unaccount_log_buffer(struct btrfs_fs_info *fs_info, u64 start) - { - struct btrfs_block_group *cache; - - cache = btrfs_lookup_block_group(fs_info, start); - if (!cache) { - btrfs_err(fs_info, "unable to find block group for %llu", start); -- return; -+ return -ENOENT; - } - - spin_lock(&cache->space_info->lock); -@@ -2560,27 +2592,22 @@ static void unaccount_log_buffer(struct - spin_unlock(&cache->space_info->lock); - - btrfs_put_block_group(cache); -+ -+ return 0; - } - - static int clean_log_buffer(struct btrfs_trans_handle *trans, - struct extent_buffer *eb) - { -- int ret; -- - btrfs_tree_lock(eb); - btrfs_clear_buffer_dirty(trans, eb); - wait_on_extent_buffer_writeback(eb); - btrfs_tree_unlock(eb); - -- if (trans) { -- ret = btrfs_pin_reserved_extent(trans, eb); -- if (ret) -- return ret; -- } else { -- unaccount_log_buffer(eb->fs_info, eb->start); -- } -+ if (trans) -+ return btrfs_pin_reserved_extent(trans, eb); - -- return 0; -+ return unaccount_log_buffer(eb->fs_info, eb->start); - } - - static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans, -@@ -2720,7 +2747,7 @@ static int walk_log_tree(struct btrfs_tr - level = btrfs_header_level(log->node); - orig_level = level; - path->nodes[level] = log->node; -- atomic_inc(&log->node->refs); -+ refcount_inc(&log->node->refs); - path->slots[level] = 0; - - while (1) { -@@ -3282,6 +3309,31 @@ int btrfs_free_log_root_tree(struct btrf - return 0; - } - -+static bool mark_inode_as_not_logged(const struct btrfs_trans_handle *trans, -+ struct btrfs_inode *inode) -+{ -+ bool ret = false; -+ -+ /* -+ * Do this only if ->logged_trans is still 0 to prevent races with -+ * concurrent logging as we may see the inode not logged when -+ * inode_logged() is called but it gets logged after inode_logged() did -+ * not find it in the log tree and we end up setting ->logged_trans to a -+ * value less than trans->transid after the concurrent logging task has -+ * set it to trans->transid. As a consequence, subsequent rename, unlink -+ * and link operations may end up not logging new names and removing old -+ * names from the log. -+ */ -+ spin_lock(&inode->lock); -+ if (inode->logged_trans == 0) -+ inode->logged_trans = trans->transid - 1; -+ else if (inode->logged_trans == trans->transid) -+ ret = true; -+ spin_unlock(&inode->lock); -+ -+ return ret; -+} -+ - /* - * Check if an inode was logged in the current transaction. This correctly deals - * with the case where the inode was logged but has a logged_trans of 0, which -@@ -3299,15 +3351,32 @@ static int inode_logged(const struct btr - struct btrfs_key key; - int ret; - -- if (inode->logged_trans == trans->transid) -+ /* -+ * Quick lockless call, since once ->logged_trans is set to the current -+ * transaction, we never set it to a lower value anywhere else. -+ */ -+ if (data_race(inode->logged_trans) == trans->transid) - return 1; - - /* -- * If logged_trans is not 0, then we know the inode logged was not logged -- * in this transaction, so we can return false right away. -+ * If logged_trans is not 0 and not trans->transid, then we know the -+ * inode was not logged in this transaction, so we can return false -+ * right away. We take the lock to avoid a race caused by load/store -+ * tearing with a concurrent btrfs_log_inode() call or a concurrent task -+ * in this function further below - an update to trans->transid can be -+ * teared into two 32 bits updates for example, in which case we could -+ * see a positive value that is not trans->transid and assume the inode -+ * was not logged when it was. - */ -- if (inode->logged_trans > 0) -+ spin_lock(&inode->lock); -+ if (inode->logged_trans == trans->transid) { -+ spin_unlock(&inode->lock); -+ return 1; -+ } else if (inode->logged_trans > 0) { -+ spin_unlock(&inode->lock); - return 0; -+ } -+ spin_unlock(&inode->lock); - - /* - * If no log tree was created for this root in this transaction, then -@@ -3316,10 +3385,8 @@ static int inode_logged(const struct btr - * transaction's ID, to avoid the search below in a future call in case - * a log tree gets created after this. - */ -- if (!test_bit(BTRFS_ROOT_HAS_LOG_TREE, &inode->root->state)) { -- inode->logged_trans = trans->transid - 1; -- return 0; -- } -+ if (!test_bit(BTRFS_ROOT_HAS_LOG_TREE, &inode->root->state)) -+ return mark_inode_as_not_logged(trans, inode); - - /* - * We have a log tree and the inode's logged_trans is 0. We can't tell -@@ -3373,8 +3440,7 @@ static int inode_logged(const struct btr - * Set logged_trans to a value greater than 0 and less then the - * current transaction to avoid doing the search in future calls. - */ -- inode->logged_trans = trans->transid - 1; -- return 0; -+ return mark_inode_as_not_logged(trans, inode); - } - - /* -@@ -3382,20 +3448,9 @@ static int inode_logged(const struct btr - * the current transacion's ID, to avoid future tree searches as long as - * the inode is not evicted again. - */ -+ spin_lock(&inode->lock); - inode->logged_trans = trans->transid; -- -- /* -- * If it's a directory, then we must set last_dir_index_offset to the -- * maximum possible value, so that the next attempt to log the inode does -- * not skip checking if dir index keys found in modified subvolume tree -- * leaves have been logged before, otherwise it would result in attempts -- * to insert duplicate dir index keys in the log tree. This must be done -- * because last_dir_index_offset is an in-memory only field, not persisted -- * in the inode item or any other on-disk structure, so its value is lost -- * once the inode is evicted. -- */ -- if (S_ISDIR(inode->vfs_inode.i_mode)) -- inode->last_dir_index_offset = (u64)-1; -+ spin_unlock(&inode->lock); - - return 1; - } -@@ -3684,7 +3739,7 @@ static int clone_leaf(struct btrfs_path - * Add extra ref to scratch eb so that it is not freed when callers - * release the path, so we can reuse it later if needed. - */ -- atomic_inc(&ctx->scratch_eb->refs); -+ refcount_inc(&ctx->scratch_eb->refs); - - return 0; - } -@@ -3987,7 +4042,7 @@ done: - - /* - * If the inode was logged before and it was evicted, then its -- * last_dir_index_offset is (u64)-1, so we don't the value of the last index -+ * last_dir_index_offset is 0, so we don't know the value of the last index - * key offset. If that's the case, search for it and update the inode. This - * is to avoid lookups in the log tree every time we try to insert a dir index - * key from a leaf changed in the current transaction, and to allow us to always -@@ -4003,7 +4058,7 @@ static int update_last_dir_index_offset( - - lockdep_assert_held(&inode->log_mutex); - -- if (inode->last_dir_index_offset != (u64)-1) -+ if (inode->last_dir_index_offset != 0) - return 0; - - if (!ctx->logged_before) { -@@ -4211,6 +4266,9 @@ static void fill_inode_item(struct btrfs - btrfs_set_token_timespec_nsec(&token, &item->ctime, - inode_get_ctime_nsec(inode)); - -+ btrfs_set_timespec_sec(leaf, &item->otime, BTRFS_I(inode)->i_otime_sec); -+ btrfs_set_timespec_nsec(leaf, &item->otime, BTRFS_I(inode)->i_otime_nsec); -+ - /* - * We do not need to set the nbytes field, in fact during a fast fsync - * its value may not even be correct, since a fast fsync does not wait -@@ -7279,11 +7337,14 @@ again: - - wc.replay_dest->log_root = log; - ret = btrfs_record_root_in_trans(trans, wc.replay_dest); -- if (ret) -+ if (ret) { - /* The loop needs to continue due to the root refs */ - btrfs_abort_transaction(trans, ret); -- else -+ } else { - ret = walk_log_tree(trans, log, &wc); -+ if (ret) -+ btrfs_abort_transaction(trans, ret); -+ } - - if (!ret && wc.stage == LOG_WALK_REPLAY_ALL) { - ret = fixup_inode_link_counts(trans, wc.replay_dest, -@@ -7447,6 +7508,8 @@ void btrfs_record_snapshot_destroy(struc - * full log sync. - * Also we don't need to worry with renames, since btrfs_rename() marks the log - * for full commit when renaming a subvolume. -+ * -+ * Must be called before creating the subvolume entry in its parent directory. - */ - void btrfs_record_new_subvolume(const struct btrfs_trans_handle *trans, - struct btrfs_inode *dir) -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/volumes.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/volumes.c ---- BPI-Router-Linux-kernel/fs/btrfs/volumes.c 2025-10-22 13:53:23.507327727 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/volumes.c 2025-10-22 13:53:56.703168235 -0400 -@@ -2714,6 +2714,11 @@ int btrfs_init_new_device(struct btrfs_f - goto error; - } - -+ if (bdev_nr_bytes(file_bdev(bdev_file)) <= BTRFS_DEVICE_RANGE_RESERVED) { -+ ret = -EINVAL; -+ goto error; -+ } -+ - if (fs_devices->seeding) { - seeding_dev = true; - down_write(&sb->s_umount); -@@ -3282,6 +3287,12 @@ int btrfs_remove_chunk(struct btrfs_tran - device->bytes_used - dev_extent_len); - atomic64_add(dev_extent_len, &fs_info->free_chunk_space); - btrfs_clear_space_info_full(fs_info); -+ -+ if (list_empty(&device->post_commit_list)) { -+ list_add_tail(&device->post_commit_list, -+ &trans->transaction->dev_update_list); -+ } -+ - mutex_unlock(&fs_info->chunk_mutex); - } - } -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/zoned.c BPI-Router-Linux-kernel-6.16.12/fs/btrfs/zoned.c ---- BPI-Router-Linux-kernel/fs/btrfs/zoned.c 2025-10-22 13:53:23.507327727 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/zoned.c 2025-10-22 13:53:56.703168235 -0400 -@@ -17,6 +17,8 @@ - #include "fs.h" - #include "accessors.h" - #include "bio.h" -+#include "transaction.h" -+#include "sysfs.h" - - /* Maximum number of zones to report per blkdev_report_zones() call */ - #define BTRFS_REPORT_NR_ZONES 4096 -@@ -1403,7 +1405,8 @@ static int btrfs_load_block_group_single - static int btrfs_load_block_group_dup(struct btrfs_block_group *bg, - struct btrfs_chunk_map *map, - struct zone_info *zone_info, -- unsigned long *active) -+ unsigned long *active, -+ u64 last_alloc) - { - struct btrfs_fs_info *fs_info = bg->fs_info; - -@@ -1426,6 +1429,13 @@ static int btrfs_load_block_group_dup(st - zone_info[1].physical); - return -EIO; - } -+ -+ if (zone_info[0].alloc_offset == WP_CONVENTIONAL) -+ zone_info[0].alloc_offset = last_alloc; -+ -+ if (zone_info[1].alloc_offset == WP_CONVENTIONAL) -+ zone_info[1].alloc_offset = last_alloc; -+ - if (zone_info[0].alloc_offset != zone_info[1].alloc_offset) { - btrfs_err(bg->fs_info, - "zoned: write pointer offset mismatch of zones in DUP profile"); -@@ -1446,7 +1456,8 @@ static int btrfs_load_block_group_dup(st - static int btrfs_load_block_group_raid1(struct btrfs_block_group *bg, - struct btrfs_chunk_map *map, - struct zone_info *zone_info, -- unsigned long *active) -+ unsigned long *active, -+ u64 last_alloc) - { - struct btrfs_fs_info *fs_info = bg->fs_info; - int i; -@@ -1461,10 +1472,12 @@ static int btrfs_load_block_group_raid1( - bg->zone_capacity = min_not_zero(zone_info[0].capacity, zone_info[1].capacity); - - for (i = 0; i < map->num_stripes; i++) { -- if (zone_info[i].alloc_offset == WP_MISSING_DEV || -- zone_info[i].alloc_offset == WP_CONVENTIONAL) -+ if (zone_info[i].alloc_offset == WP_MISSING_DEV) - continue; - -+ if (zone_info[i].alloc_offset == WP_CONVENTIONAL) -+ zone_info[i].alloc_offset = last_alloc; -+ - if ((zone_info[0].alloc_offset != zone_info[i].alloc_offset) && - !btrfs_test_opt(fs_info, DEGRADED)) { - btrfs_err(fs_info, -@@ -1494,7 +1507,8 @@ static int btrfs_load_block_group_raid1( - static int btrfs_load_block_group_raid0(struct btrfs_block_group *bg, - struct btrfs_chunk_map *map, - struct zone_info *zone_info, -- unsigned long *active) -+ unsigned long *active, -+ u64 last_alloc) - { - struct btrfs_fs_info *fs_info = bg->fs_info; - -@@ -1505,10 +1519,29 @@ static int btrfs_load_block_group_raid0( - } - - for (int i = 0; i < map->num_stripes; i++) { -- if (zone_info[i].alloc_offset == WP_MISSING_DEV || -- zone_info[i].alloc_offset == WP_CONVENTIONAL) -+ if (zone_info[i].alloc_offset == WP_MISSING_DEV) - continue; - -+ if (zone_info[i].alloc_offset == WP_CONVENTIONAL) { -+ u64 stripe_nr, full_stripe_nr; -+ u64 stripe_offset; -+ int stripe_index; -+ -+ stripe_nr = div64_u64(last_alloc, map->stripe_size); -+ stripe_offset = stripe_nr * map->stripe_size; -+ full_stripe_nr = div_u64(stripe_nr, map->num_stripes); -+ div_u64_rem(stripe_nr, map->num_stripes, &stripe_index); -+ -+ zone_info[i].alloc_offset = -+ full_stripe_nr * map->stripe_size; -+ -+ if (stripe_index > i) -+ zone_info[i].alloc_offset += map->stripe_size; -+ else if (stripe_index == i) -+ zone_info[i].alloc_offset += -+ (last_alloc - stripe_offset); -+ } -+ - if (test_bit(0, active) != test_bit(i, active)) { - if (!btrfs_zone_activate(bg)) - return -EIO; -@@ -1526,7 +1559,8 @@ static int btrfs_load_block_group_raid0( - static int btrfs_load_block_group_raid10(struct btrfs_block_group *bg, - struct btrfs_chunk_map *map, - struct zone_info *zone_info, -- unsigned long *active) -+ unsigned long *active, -+ u64 last_alloc) - { - struct btrfs_fs_info *fs_info = bg->fs_info; - -@@ -1537,8 +1571,7 @@ static int btrfs_load_block_group_raid10 - } - - for (int i = 0; i < map->num_stripes; i++) { -- if (zone_info[i].alloc_offset == WP_MISSING_DEV || -- zone_info[i].alloc_offset == WP_CONVENTIONAL) -+ if (zone_info[i].alloc_offset == WP_MISSING_DEV) - continue; - - if (test_bit(0, active) != test_bit(i, active)) { -@@ -1549,6 +1582,29 @@ static int btrfs_load_block_group_raid10 - set_bit(BLOCK_GROUP_FLAG_ZONE_IS_ACTIVE, &bg->runtime_flags); - } - -+ if (zone_info[i].alloc_offset == WP_CONVENTIONAL) { -+ u64 stripe_nr, full_stripe_nr; -+ u64 stripe_offset; -+ int stripe_index; -+ -+ stripe_nr = div64_u64(last_alloc, map->stripe_size); -+ stripe_offset = stripe_nr * map->stripe_size; -+ full_stripe_nr = div_u64(stripe_nr, -+ map->num_stripes / map->sub_stripes); -+ div_u64_rem(stripe_nr, -+ (map->num_stripes / map->sub_stripes), -+ &stripe_index); -+ -+ zone_info[i].alloc_offset = -+ full_stripe_nr * map->stripe_size; -+ -+ if (stripe_index > (i / map->sub_stripes)) -+ zone_info[i].alloc_offset += map->stripe_size; -+ else if (stripe_index == (i / map->sub_stripes)) -+ zone_info[i].alloc_offset += -+ (last_alloc - stripe_offset); -+ } -+ - if ((i % map->sub_stripes) == 0) { - bg->zone_capacity += zone_info[i].capacity; - bg->alloc_offset += zone_info[i].alloc_offset; -@@ -1637,18 +1693,22 @@ int btrfs_load_block_group_zone_info(str - ret = btrfs_load_block_group_single(cache, &zone_info[0], active); - break; - case BTRFS_BLOCK_GROUP_DUP: -- ret = btrfs_load_block_group_dup(cache, map, zone_info, active); -+ ret = btrfs_load_block_group_dup(cache, map, zone_info, active, -+ last_alloc); - break; - case BTRFS_BLOCK_GROUP_RAID1: - case BTRFS_BLOCK_GROUP_RAID1C3: - case BTRFS_BLOCK_GROUP_RAID1C4: -- ret = btrfs_load_block_group_raid1(cache, map, zone_info, active); -+ ret = btrfs_load_block_group_raid1(cache, map, zone_info, -+ active, last_alloc); - break; - case BTRFS_BLOCK_GROUP_RAID0: -- ret = btrfs_load_block_group_raid0(cache, map, zone_info, active); -+ ret = btrfs_load_block_group_raid0(cache, map, zone_info, -+ active, last_alloc); - break; - case BTRFS_BLOCK_GROUP_RAID10: -- ret = btrfs_load_block_group_raid10(cache, map, zone_info, active); -+ ret = btrfs_load_block_group_raid10(cache, map, zone_info, -+ active, last_alloc); - break; - case BTRFS_BLOCK_GROUP_RAID5: - case BTRFS_BLOCK_GROUP_RAID6: -@@ -2110,10 +2170,15 @@ bool btrfs_zone_activate(struct btrfs_bl - goto out_unlock; - } - -- /* No space left */ -- if (btrfs_zoned_bg_is_full(block_group)) { -- ret = false; -- goto out_unlock; -+ if (block_group->flags & BTRFS_BLOCK_GROUP_DATA) { -+ /* The caller should check if the block group is full. */ -+ if (WARN_ON_ONCE(btrfs_zoned_bg_is_full(block_group))) { -+ ret = false; -+ goto out_unlock; -+ } -+ } else { -+ /* Since it is already written, it should have been active. */ -+ WARN_ON_ONCE(block_group->meta_write_pointer != block_group->start); - } - - for (i = 0; i < map->num_stripes; i++) { -@@ -2187,6 +2252,40 @@ static void wait_eb_writebacks(struct bt - rcu_read_unlock(); - } - -+static int call_zone_finish(struct btrfs_block_group *block_group, -+ struct btrfs_io_stripe *stripe) -+{ -+ struct btrfs_device *device = stripe->dev; -+ const u64 physical = stripe->physical; -+ struct btrfs_zoned_device_info *zinfo = device->zone_info; -+ int ret; -+ -+ if (!device->bdev) -+ return 0; -+ -+ if (zinfo->max_active_zones == 0) -+ return 0; -+ -+ if (btrfs_dev_is_sequential(device, physical)) { -+ unsigned int nofs_flags; -+ -+ nofs_flags = memalloc_nofs_save(); -+ ret = blkdev_zone_mgmt(device->bdev, REQ_OP_ZONE_FINISH, -+ physical >> SECTOR_SHIFT, -+ zinfo->zone_size >> SECTOR_SHIFT); -+ memalloc_nofs_restore(nofs_flags); -+ -+ if (ret) -+ return ret; -+ } -+ -+ if (!(block_group->flags & BTRFS_BLOCK_GROUP_DATA)) -+ zinfo->reserved_active_zones++; -+ btrfs_dev_clear_active_zone(device, physical); -+ -+ return 0; -+} -+ - static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_written) - { - struct btrfs_fs_info *fs_info = block_group->fs_info; -@@ -2271,31 +2370,12 @@ static int do_zone_finish(struct btrfs_b - down_read(&dev_replace->rwsem); - map = block_group->physical_map; - for (i = 0; i < map->num_stripes; i++) { -- struct btrfs_device *device = map->stripes[i].dev; -- const u64 physical = map->stripes[i].physical; -- struct btrfs_zoned_device_info *zinfo = device->zone_info; -- unsigned int nofs_flags; -- -- if (!device->bdev) -- continue; -- -- if (zinfo->max_active_zones == 0) -- continue; -- -- nofs_flags = memalloc_nofs_save(); -- ret = blkdev_zone_mgmt(device->bdev, REQ_OP_ZONE_FINISH, -- physical >> SECTOR_SHIFT, -- zinfo->zone_size >> SECTOR_SHIFT); -- memalloc_nofs_restore(nofs_flags); - -+ ret = call_zone_finish(block_group, &map->stripes[i]); - if (ret) { - up_read(&dev_replace->rwsem); - return ret; - } -- -- if (!(block_group->flags & BTRFS_BLOCK_GROUP_DATA)) -- zinfo->reserved_active_zones++; -- btrfs_dev_clear_active_zone(device, physical); - } - up_read(&dev_replace->rwsem); - -@@ -2427,7 +2507,7 @@ void btrfs_schedule_zone_finish_bg(struc - - /* For the work */ - btrfs_get_block_group(bg); -- atomic_inc(&eb->refs); -+ refcount_inc(&eb->refs); - bg->last_eb = eb; - INIT_WORK(&bg->zone_finish_work, btrfs_zone_finish_endio_workfn); - queue_work(system_unbound_wq, &bg->zone_finish_work); -@@ -2443,6 +2523,104 @@ void btrfs_clear_data_reloc_bg(struct bt - spin_unlock(&fs_info->relocation_bg_lock); - } - -+void btrfs_zoned_reserve_data_reloc_bg(struct btrfs_fs_info *fs_info) -+{ -+ struct btrfs_space_info *data_sinfo = fs_info->data_sinfo; -+ struct btrfs_space_info *space_info = data_sinfo; -+ struct btrfs_trans_handle *trans; -+ struct btrfs_block_group *bg; -+ struct list_head *bg_list; -+ u64 alloc_flags; -+ bool first = true; -+ bool did_chunk_alloc = false; -+ int index; -+ int ret; -+ -+ if (!btrfs_is_zoned(fs_info)) -+ return; -+ -+ if (fs_info->data_reloc_bg) -+ return; -+ -+ if (sb_rdonly(fs_info->sb)) -+ return; -+ -+ alloc_flags = btrfs_get_alloc_profile(fs_info, space_info->flags); -+ index = btrfs_bg_flags_to_raid_index(alloc_flags); -+ -+ /* Scan the data space_info to find empty block groups. Take the second one. */ -+again: -+ bg_list = &space_info->block_groups[index]; -+ list_for_each_entry(bg, bg_list, list) { -+ if (bg->alloc_offset != 0) -+ continue; -+ -+ if (first) { -+ first = false; -+ continue; -+ } -+ -+ if (space_info == data_sinfo) { -+ /* Migrate the block group to the data relocation space_info. */ -+ struct btrfs_space_info *reloc_sinfo = data_sinfo->sub_group[0]; -+ int factor; -+ -+ ASSERT(reloc_sinfo->subgroup_id == BTRFS_SUB_GROUP_DATA_RELOC); -+ factor = btrfs_bg_type_to_factor(bg->flags); -+ -+ down_write(&space_info->groups_sem); -+ list_del_init(&bg->list); -+ /* We can assume this as we choose the second empty one. */ -+ ASSERT(!list_empty(&space_info->block_groups[index])); -+ up_write(&space_info->groups_sem); -+ -+ spin_lock(&space_info->lock); -+ space_info->total_bytes -= bg->length; -+ space_info->disk_total -= bg->length * factor; -+ space_info->disk_total -= bg->zone_unusable; -+ /* There is no allocation ever happened. */ -+ ASSERT(bg->used == 0); -+ /* No super block in a block group on the zoned setup. */ -+ ASSERT(bg->bytes_super == 0); -+ spin_unlock(&space_info->lock); -+ -+ bg->space_info = reloc_sinfo; -+ if (reloc_sinfo->block_group_kobjs[index] == NULL) -+ btrfs_sysfs_add_block_group_type(bg); -+ -+ btrfs_add_bg_to_space_info(fs_info, bg); -+ } -+ -+ fs_info->data_reloc_bg = bg->start; -+ set_bit(BLOCK_GROUP_FLAG_ZONED_DATA_RELOC, &bg->runtime_flags); -+ btrfs_zone_activate(bg); -+ -+ return; -+ } -+ -+ if (did_chunk_alloc) -+ return; -+ -+ trans = btrfs_join_transaction(fs_info->tree_root); -+ if (IS_ERR(trans)) -+ return; -+ -+ /* Allocate new BG in the data relocation space_info. */ -+ space_info = data_sinfo->sub_group[0]; -+ ASSERT(space_info->subgroup_id == BTRFS_SUB_GROUP_DATA_RELOC); -+ ret = btrfs_chunk_alloc(trans, space_info, alloc_flags, CHUNK_ALLOC_FORCE); -+ btrfs_end_transaction(trans); -+ if (ret == 1) { -+ /* -+ * We allocated a new block group in the data relocation space_info. We -+ * can take that one. -+ */ -+ first = false; -+ did_chunk_alloc = true; -+ goto again; -+ } -+} -+ - void btrfs_free_zone_cache(struct btrfs_fs_info *fs_info) - { - struct btrfs_fs_devices *fs_devices = fs_info->fs_devices; -@@ -2465,8 +2643,8 @@ bool btrfs_zoned_should_reclaim(const st - { - struct btrfs_fs_devices *fs_devices = fs_info->fs_devices; - struct btrfs_device *device; -+ u64 total = btrfs_super_total_bytes(fs_info->super_copy); - u64 used = 0; -- u64 total = 0; - u64 factor; - - ASSERT(btrfs_is_zoned(fs_info)); -@@ -2479,7 +2657,6 @@ bool btrfs_zoned_should_reclaim(const st - if (!device->bdev) - continue; - -- total += device->disk_total_bytes; - used += device->bytes_used; - } - mutex_unlock(&fs_devices->device_list_mutex); -@@ -2533,7 +2710,7 @@ int btrfs_zone_finish_one_bg(struct btrf - - spin_lock(&block_group->lock); - if (block_group->reserved || block_group->alloc_offset == 0 || -- (block_group->flags & BTRFS_BLOCK_GROUP_SYSTEM) || -+ !(block_group->flags & BTRFS_BLOCK_GROUP_DATA) || - test_bit(BLOCK_GROUP_FLAG_ZONED_DATA_RELOC, &block_group->runtime_flags)) { - spin_unlock(&block_group->lock); - continue; -diff -purNx .git BPI-Router-Linux-kernel/fs/btrfs/zoned.h BPI-Router-Linux-kernel-6.16.12/fs/btrfs/zoned.h ---- BPI-Router-Linux-kernel/fs/btrfs/zoned.h 2025-10-22 13:53:23.507327727 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/btrfs/zoned.h 2025-10-22 13:53:56.703168235 -0400 -@@ -88,6 +88,7 @@ void btrfs_zone_finish_endio(struct btrf - void btrfs_schedule_zone_finish_bg(struct btrfs_block_group *bg, - struct extent_buffer *eb); - void btrfs_clear_data_reloc_bg(struct btrfs_block_group *bg); -+void btrfs_zoned_reserve_data_reloc_bg(struct btrfs_fs_info *fs_info); - void btrfs_free_zone_cache(struct btrfs_fs_info *fs_info); - bool btrfs_zoned_should_reclaim(const struct btrfs_fs_info *fs_info); - void btrfs_zoned_release_data_reloc_bg(struct btrfs_fs_info *fs_info, u64 logical, -@@ -241,6 +242,8 @@ static inline void btrfs_schedule_zone_f - - static inline void btrfs_clear_data_reloc_bg(struct btrfs_block_group *bg) { } - -+static inline void btrfs_zoned_reserve_data_reloc_bg(struct btrfs_fs_info *fs_info) { } -+ - static inline void btrfs_free_zone_cache(struct btrfs_fs_info *fs_info) { } - - static inline bool btrfs_zoned_should_reclaim(const struct btrfs_fs_info *fs_info) -diff -purNx .git BPI-Router-Linux-kernel/fs/buffer.c BPI-Router-Linux-kernel-6.16.12/fs/buffer.c ---- BPI-Router-Linux-kernel/fs/buffer.c 2025-10-22 13:53:23.507327727 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/buffer.c 2025-10-22 13:53:56.707168215 -0400 -@@ -157,8 +157,8 @@ static void __end_buffer_read_notouch(st - */ - void end_buffer_read_sync(struct buffer_head *bh, int uptodate) - { -- __end_buffer_read_notouch(bh, uptodate); - put_bh(bh); -+ __end_buffer_read_notouch(bh, uptodate); - } - EXPORT_SYMBOL(end_buffer_read_sync); - -diff -purNx .git BPI-Router-Linux-kernel/fs/cachefiles/io.c BPI-Router-Linux-kernel-6.16.12/fs/cachefiles/io.c ---- BPI-Router-Linux-kernel/fs/cachefiles/io.c 2025-10-22 13:53:23.507327727 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/cachefiles/io.c 2025-10-22 13:53:56.707168215 -0400 -@@ -347,8 +347,6 @@ int __cachefiles_write(struct cachefiles - default: - ki->was_async = false; - cachefiles_write_complete(&ki->iocb, ret); -- if (ret > 0) -- ret = 0; - break; - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/cachefiles/ondemand.c BPI-Router-Linux-kernel-6.16.12/fs/cachefiles/ondemand.c ---- BPI-Router-Linux-kernel/fs/cachefiles/ondemand.c 2025-10-22 13:53:23.507327727 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/cachefiles/ondemand.c 2025-10-22 13:53:56.707168215 -0400 -@@ -83,10 +83,8 @@ static ssize_t cachefiles_ondemand_fd_wr - - trace_cachefiles_ondemand_fd_write(object, file_inode(file), pos, len); - ret = __cachefiles_write(object, file, pos, iter, NULL, NULL); -- if (!ret) { -- ret = len; -+ if (ret > 0) - kiocb->ki_pos += ret; -- } - - out: - fput(file); -diff -purNx .git BPI-Router-Linux-kernel/fs/ceph/addr.c BPI-Router-Linux-kernel-6.16.12/fs/ceph/addr.c ---- BPI-Router-Linux-kernel/fs/ceph/addr.c 2025-10-22 13:53:23.507327727 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ceph/addr.c 2025-10-22 13:53:56.707168215 -0400 -@@ -1264,7 +1264,9 @@ static inline int move_dirty_folio_in_pa - 0, - gfp_flags); - if (IS_ERR(pages[index])) { -- if (PTR_ERR(pages[index]) == -EINVAL) { -+ int err = PTR_ERR(pages[index]); -+ -+ if (err == -EINVAL) { - pr_err_client(cl, "inode->i_blkbits=%hhu\n", - inode->i_blkbits); - } -@@ -1273,7 +1275,7 @@ static inline int move_dirty_folio_in_pa - BUG_ON(ceph_wbc->locked_pages == 0); - - pages[index] = NULL; -- return PTR_ERR(pages[index]); -+ return err; - } - } else { - pages[index] = &folio->page; -@@ -1687,6 +1689,7 @@ get_more_pages: - - process_folio_batch: - rc = ceph_process_folio_batch(mapping, wbc, &ceph_wbc); -+ ceph_shift_unused_folios_left(&ceph_wbc.fbatch); - if (rc) - goto release_folios; - -@@ -1695,8 +1698,6 @@ process_folio_batch: - goto release_folios; - - if (ceph_wbc.processed_in_fbatch) { -- ceph_shift_unused_folios_left(&ceph_wbc.fbatch); -- - if (folio_batch_count(&ceph_wbc.fbatch) == 0 && - ceph_wbc.locked_pages < ceph_wbc.max_pages) { - doutc(cl, "reached end fbatch, trying for more\n"); -diff -purNx .git BPI-Router-Linux-kernel/fs/ceph/crypto.c BPI-Router-Linux-kernel-6.16.12/fs/ceph/crypto.c ---- BPI-Router-Linux-kernel/fs/ceph/crypto.c 2025-10-22 13:53:23.507327727 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ceph/crypto.c 2025-10-22 13:53:56.707168215 -0400 -@@ -215,35 +215,31 @@ static struct inode *parse_longname(cons - struct ceph_client *cl = ceph_inode_to_client(parent); - struct inode *dir = NULL; - struct ceph_vino vino = { .snap = CEPH_NOSNAP }; -- char *inode_number; -- char *name_end; -- int orig_len = *name_len; -+ char *name_end, *inode_number; - int ret = -EIO; -- -+ /* NUL-terminate */ -+ char *str __free(kfree) = kmemdup_nul(name, *name_len, GFP_KERNEL); -+ if (!str) -+ return ERR_PTR(-ENOMEM); - /* Skip initial '_' */ -- name++; -- name_end = strrchr(name, '_'); -+ str++; -+ name_end = strrchr(str, '_'); - if (!name_end) { -- doutc(cl, "failed to parse long snapshot name: %s\n", name); -+ doutc(cl, "failed to parse long snapshot name: %s\n", str); - return ERR_PTR(-EIO); - } -- *name_len = (name_end - name); -+ *name_len = (name_end - str); - if (*name_len <= 0) { - pr_err_client(cl, "failed to parse long snapshot name\n"); - return ERR_PTR(-EIO); - } - - /* Get the inode number */ -- inode_number = kmemdup_nul(name_end + 1, -- orig_len - *name_len - 2, -- GFP_KERNEL); -- if (!inode_number) -- return ERR_PTR(-ENOMEM); -+ inode_number = name_end + 1; - ret = kstrtou64(inode_number, 10, &vino.ino); - if (ret) { -- doutc(cl, "failed to parse inode number: %s\n", name); -- dir = ERR_PTR(ret); -- goto out; -+ doutc(cl, "failed to parse inode number: %s\n", str); -+ return ERR_PTR(ret); - } - - /* And finally the inode */ -@@ -254,9 +250,6 @@ static struct inode *parse_longname(cons - if (IS_ERR(dir)) - doutc(cl, "can't find inode %s (%s)\n", inode_number, name); - } -- --out: -- kfree(inode_number); - return dir; - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/ceph/debugfs.c BPI-Router-Linux-kernel-6.16.12/fs/ceph/debugfs.c ---- BPI-Router-Linux-kernel/fs/ceph/debugfs.c 2025-10-22 13:53:23.507327727 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ceph/debugfs.c 2025-10-22 13:53:56.707168215 -0400 -@@ -55,8 +55,6 @@ static int mdsc_show(struct seq_file *s, - struct ceph_mds_client *mdsc = fsc->mdsc; - struct ceph_mds_request *req; - struct rb_node *rp; -- int pathlen = 0; -- u64 pathbase; - char *path; - - mutex_lock(&mdsc->mutex); -@@ -81,8 +79,8 @@ static int mdsc_show(struct seq_file *s, - if (req->r_inode) { - seq_printf(s, " #%llx", ceph_ino(req->r_inode)); - } else if (req->r_dentry) { -- path = ceph_mdsc_build_path(mdsc, req->r_dentry, &pathlen, -- &pathbase, 0); -+ struct ceph_path_info path_info; -+ path = ceph_mdsc_build_path(mdsc, req->r_dentry, &path_info, 0); - if (IS_ERR(path)) - path = NULL; - spin_lock(&req->r_dentry->d_lock); -@@ -91,7 +89,7 @@ static int mdsc_show(struct seq_file *s, - req->r_dentry, - path ? path : ""); - spin_unlock(&req->r_dentry->d_lock); -- ceph_mdsc_free_path(path, pathlen); -+ ceph_mdsc_free_path_info(&path_info); - } else if (req->r_path1) { - seq_printf(s, " #%llx/%s", req->r_ino1.ino, - req->r_path1); -@@ -100,8 +98,8 @@ static int mdsc_show(struct seq_file *s, - } - - if (req->r_old_dentry) { -- path = ceph_mdsc_build_path(mdsc, req->r_old_dentry, &pathlen, -- &pathbase, 0); -+ struct ceph_path_info path_info; -+ path = ceph_mdsc_build_path(mdsc, req->r_old_dentry, &path_info, 0); - if (IS_ERR(path)) - path = NULL; - spin_lock(&req->r_old_dentry->d_lock); -@@ -111,7 +109,7 @@ static int mdsc_show(struct seq_file *s, - req->r_old_dentry, - path ? path : ""); - spin_unlock(&req->r_old_dentry->d_lock); -- ceph_mdsc_free_path(path, pathlen); -+ ceph_mdsc_free_path_info(&path_info); - } else if (req->r_path2 && req->r_op != CEPH_MDS_OP_SYMLINK) { - if (req->r_ino2.ino) - seq_printf(s, " #%llx/%s", req->r_ino2.ino, -diff -purNx .git BPI-Router-Linux-kernel/fs/ceph/dir.c BPI-Router-Linux-kernel-6.16.12/fs/ceph/dir.c ---- BPI-Router-Linux-kernel/fs/ceph/dir.c 2025-10-22 13:53:23.507327727 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ceph/dir.c 2025-10-22 13:53:56.707168215 -0400 -@@ -1272,10 +1272,8 @@ static void ceph_async_unlink_cb(struct - - /* If op failed, mark everyone involved for errors */ - if (result) { -- int pathlen = 0; -- u64 base = 0; -- char *path = ceph_mdsc_build_path(mdsc, dentry, &pathlen, -- &base, 0); -+ struct ceph_path_info path_info = {0}; -+ char *path = ceph_mdsc_build_path(mdsc, dentry, &path_info, 0); - - /* mark error on parent + clear complete */ - mapping_set_error(req->r_parent->i_mapping, result); -@@ -1289,8 +1287,8 @@ static void ceph_async_unlink_cb(struct - mapping_set_error(req->r_old_inode->i_mapping, result); - - pr_warn_client(cl, "failure path=(%llx)%s result=%d!\n", -- base, IS_ERR(path) ? "<>" : path, result); -- ceph_mdsc_free_path(path, pathlen); -+ path_info.vino.ino, IS_ERR(path) ? "<>" : path, result); -+ ceph_mdsc_free_path_info(&path_info); - } - out: - iput(req->r_old_inode); -@@ -1348,8 +1346,6 @@ static int ceph_unlink(struct inode *dir - int err = -EROFS; - int op; - char *path; -- int pathlen; -- u64 pathbase; - - if (ceph_snap(dir) == CEPH_SNAPDIR) { - /* rmdir .snap/foo is RMSNAP */ -@@ -1368,14 +1364,15 @@ static int ceph_unlink(struct inode *dir - if (!dn) { - try_async = false; - } else { -- path = ceph_mdsc_build_path(mdsc, dn, &pathlen, &pathbase, 0); -+ struct ceph_path_info path_info; -+ path = ceph_mdsc_build_path(mdsc, dn, &path_info, 0); - if (IS_ERR(path)) { - try_async = false; - err = 0; - } else { - err = ceph_mds_check_access(mdsc, path, MAY_WRITE); - } -- ceph_mdsc_free_path(path, pathlen); -+ ceph_mdsc_free_path_info(&path_info); - dput(dn); - - /* For none EACCES cases will let the MDS do the mds auth check */ -diff -purNx .git BPI-Router-Linux-kernel/fs/ceph/file.c BPI-Router-Linux-kernel-6.16.12/fs/ceph/file.c ---- BPI-Router-Linux-kernel/fs/ceph/file.c 2025-10-22 13:53:23.507327727 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ceph/file.c 2025-10-22 13:53:56.707168215 -0400 -@@ -368,8 +368,6 @@ int ceph_open(struct inode *inode, struc - int flags, fmode, wanted; - struct dentry *dentry; - char *path; -- int pathlen; -- u64 pathbase; - bool do_sync = false; - int mask = MAY_READ; - -@@ -399,14 +397,15 @@ int ceph_open(struct inode *inode, struc - if (!dentry) { - do_sync = true; - } else { -- path = ceph_mdsc_build_path(mdsc, dentry, &pathlen, &pathbase, 0); -+ struct ceph_path_info path_info; -+ path = ceph_mdsc_build_path(mdsc, dentry, &path_info, 0); - if (IS_ERR(path)) { - do_sync = true; - err = 0; - } else { - err = ceph_mds_check_access(mdsc, path, mask); - } -- ceph_mdsc_free_path(path, pathlen); -+ ceph_mdsc_free_path_info(&path_info); - dput(dentry); - - /* For none EACCES cases will let the MDS do the mds auth check */ -@@ -614,15 +613,13 @@ static void ceph_async_create_cb(struct - mapping_set_error(req->r_parent->i_mapping, result); - - if (result) { -- int pathlen = 0; -- u64 base = 0; -- char *path = ceph_mdsc_build_path(mdsc, req->r_dentry, &pathlen, -- &base, 0); -+ struct ceph_path_info path_info = {0}; -+ char *path = ceph_mdsc_build_path(mdsc, req->r_dentry, &path_info, 0); - - pr_warn_client(cl, - "async create failure path=(%llx)%s result=%d!\n", -- base, IS_ERR(path) ? "<>" : path, result); -- ceph_mdsc_free_path(path, pathlen); -+ path_info.vino.ino, IS_ERR(path) ? "<>" : path, result); -+ ceph_mdsc_free_path_info(&path_info); - - ceph_dir_clear_complete(req->r_parent); - if (!d_unhashed(dentry)) -@@ -791,8 +788,6 @@ int ceph_atomic_open(struct inode *dir, - int mask; - int err; - char *path; -- int pathlen; -- u64 pathbase; - - doutc(cl, "%p %llx.%llx dentry %p '%pd' %s flags %d mode 0%o\n", - dir, ceph_vinop(dir), dentry, dentry, -@@ -814,7 +809,8 @@ int ceph_atomic_open(struct inode *dir, - if (!dn) { - try_async = false; - } else { -- path = ceph_mdsc_build_path(mdsc, dn, &pathlen, &pathbase, 0); -+ struct ceph_path_info path_info; -+ path = ceph_mdsc_build_path(mdsc, dn, &path_info, 0); - if (IS_ERR(path)) { - try_async = false; - err = 0; -@@ -826,7 +822,7 @@ int ceph_atomic_open(struct inode *dir, - mask |= MAY_WRITE; - err = ceph_mds_check_access(mdsc, path, mask); - } -- ceph_mdsc_free_path(path, pathlen); -+ ceph_mdsc_free_path_info(&path_info); - dput(dn); - - /* For none EACCES cases will let the MDS do the mds auth check */ -diff -purNx .git BPI-Router-Linux-kernel/fs/ceph/inode.c BPI-Router-Linux-kernel-6.16.12/fs/ceph/inode.c ---- BPI-Router-Linux-kernel/fs/ceph/inode.c 2025-10-22 13:53:23.507327727 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ceph/inode.c 2025-10-22 13:53:56.707168215 -0400 -@@ -55,6 +55,52 @@ static int ceph_set_ino_cb(struct inode - return 0; - } - -+/* -+ * Check if the parent inode matches the vino from directory reply info -+ */ -+static inline bool ceph_vino_matches_parent(struct inode *parent, -+ struct ceph_vino vino) -+{ -+ return ceph_ino(parent) == vino.ino && ceph_snap(parent) == vino.snap; -+} -+ -+/* -+ * Validate that the directory inode referenced by @req->r_parent matches the -+ * inode number and snapshot id contained in the reply's directory record. If -+ * they do not match – which can theoretically happen if the parent dentry was -+ * moved between the time the request was issued and the reply arrived – fall -+ * back to looking up the correct inode in the inode cache. -+ * -+ * A reference is *always* returned. Callers that receive a different inode -+ * than the original @parent are responsible for dropping the extra reference -+ * once the reply has been processed. -+ */ -+static struct inode *ceph_get_reply_dir(struct super_block *sb, -+ struct inode *parent, -+ struct ceph_mds_reply_info_parsed *rinfo) -+{ -+ struct ceph_vino vino; -+ -+ if (unlikely(!rinfo->diri.in)) -+ return parent; /* nothing to compare against */ -+ -+ /* If we didn't have a cached parent inode to begin with, just bail out. */ -+ if (!parent) -+ return NULL; -+ -+ vino.ino = le64_to_cpu(rinfo->diri.in->ino); -+ vino.snap = le64_to_cpu(rinfo->diri.in->snapid); -+ -+ if (likely(ceph_vino_matches_parent(parent, vino))) -+ return parent; /* matches – use the original reference */ -+ -+ /* Mismatch – this should be rare. Emit a WARN and obtain the correct inode. */ -+ WARN_ONCE(1, "ceph: reply dir mismatch (parent valid %llx.%llx reply %llx.%llx)\n", -+ ceph_ino(parent), ceph_snap(parent), vino.ino, vino.snap); -+ -+ return ceph_get_inode(sb, vino, NULL); -+} -+ - /** - * ceph_new_inode - allocate a new inode in advance of an expected create - * @dir: parent directory for new inode -@@ -1523,6 +1569,7 @@ int ceph_fill_trace(struct super_block * - struct ceph_vino tvino, dvino; - struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb); - struct ceph_client *cl = fsc->client; -+ struct inode *parent_dir = NULL; - int err = 0; - - doutc(cl, "%p is_dentry %d is_target %d\n", req, -@@ -1536,10 +1583,17 @@ int ceph_fill_trace(struct super_block * - } - - if (rinfo->head->is_dentry) { -- struct inode *dir = req->r_parent; -- -- if (dir) { -- err = ceph_fill_inode(dir, NULL, &rinfo->diri, -+ /* -+ * r_parent may be stale, in cases when R_PARENT_LOCKED is not set, -+ * so we need to get the correct inode -+ */ -+ parent_dir = ceph_get_reply_dir(sb, req->r_parent, rinfo); -+ if (unlikely(IS_ERR(parent_dir))) { -+ err = PTR_ERR(parent_dir); -+ goto done; -+ } -+ if (parent_dir) { -+ err = ceph_fill_inode(parent_dir, NULL, &rinfo->diri, - rinfo->dirfrag, session, -1, - &req->r_caps_reservation); - if (err < 0) -@@ -1548,14 +1602,14 @@ int ceph_fill_trace(struct super_block * - WARN_ON_ONCE(1); - } - -- if (dir && req->r_op == CEPH_MDS_OP_LOOKUPNAME && -+ if (parent_dir && req->r_op == CEPH_MDS_OP_LOOKUPNAME && - test_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags) && - !test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags)) { - bool is_nokey = false; - struct qstr dname; - struct dentry *dn, *parent; - struct fscrypt_str oname = FSTR_INIT(NULL, 0); -- struct ceph_fname fname = { .dir = dir, -+ struct ceph_fname fname = { .dir = parent_dir, - .name = rinfo->dname, - .ctext = rinfo->altname, - .name_len = rinfo->dname_len, -@@ -1564,10 +1618,10 @@ int ceph_fill_trace(struct super_block * - BUG_ON(!rinfo->head->is_target); - BUG_ON(req->r_dentry); - -- parent = d_find_any_alias(dir); -+ parent = d_find_any_alias(parent_dir); - BUG_ON(!parent); - -- err = ceph_fname_alloc_buffer(dir, &oname); -+ err = ceph_fname_alloc_buffer(parent_dir, &oname); - if (err < 0) { - dput(parent); - goto done; -@@ -1576,7 +1630,7 @@ int ceph_fill_trace(struct super_block * - err = ceph_fname_to_usr(&fname, NULL, &oname, &is_nokey); - if (err < 0) { - dput(parent); -- ceph_fname_free_buffer(dir, &oname); -+ ceph_fname_free_buffer(parent_dir, &oname); - goto done; - } - dname.name = oname.name; -@@ -1595,7 +1649,7 @@ retry_lookup: - dname.len, dname.name, dn); - if (!dn) { - dput(parent); -- ceph_fname_free_buffer(dir, &oname); -+ ceph_fname_free_buffer(parent_dir, &oname); - err = -ENOMEM; - goto done; - } -@@ -1610,12 +1664,12 @@ retry_lookup: - ceph_snap(d_inode(dn)) != tvino.snap)) { - doutc(cl, " dn %p points to wrong inode %p\n", - dn, d_inode(dn)); -- ceph_dir_clear_ordered(dir); -+ ceph_dir_clear_ordered(parent_dir); - d_delete(dn); - dput(dn); - goto retry_lookup; - } -- ceph_fname_free_buffer(dir, &oname); -+ ceph_fname_free_buffer(parent_dir, &oname); - - req->r_dentry = dn; - dput(parent); -@@ -1794,6 +1848,9 @@ retry_lookup: - &dvino, ptvino); - } - done: -+ /* Drop extra ref from ceph_get_reply_dir() if it returned a new inode */ -+ if (unlikely(!IS_ERR_OR_NULL(parent_dir) && parent_dir != req->r_parent)) -+ iput(parent_dir); - doutc(cl, "done err=%d\n", err); - return err; - } -@@ -2488,22 +2545,21 @@ int __ceph_setattr(struct mnt_idmap *idm - int truncate_retry = 20; /* The RMW will take around 50ms */ - struct dentry *dentry; - char *path; -- int pathlen; -- u64 pathbase; - bool do_sync = false; - - dentry = d_find_alias(inode); - if (!dentry) { - do_sync = true; - } else { -- path = ceph_mdsc_build_path(mdsc, dentry, &pathlen, &pathbase, 0); -+ struct ceph_path_info path_info; -+ path = ceph_mdsc_build_path(mdsc, dentry, &path_info, 0); - if (IS_ERR(path)) { - do_sync = true; - err = 0; - } else { - err = ceph_mds_check_access(mdsc, path, MAY_WRITE); - } -- ceph_mdsc_free_path(path, pathlen); -+ ceph_mdsc_free_path_info(&path_info); - dput(dentry); - - /* For none EACCES cases will let the MDS do the mds auth check */ -diff -purNx .git BPI-Router-Linux-kernel/fs/ceph/mds_client.c BPI-Router-Linux-kernel-6.16.12/fs/ceph/mds_client.c ---- BPI-Router-Linux-kernel/fs/ceph/mds_client.c 2025-10-22 13:53:23.507327727 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ceph/mds_client.c 2025-10-22 13:53:56.707168215 -0400 -@@ -2681,8 +2681,7 @@ static u8 *get_fscrypt_altname(const str - * ceph_mdsc_build_path - build a path string to a given dentry - * @mdsc: mds client - * @dentry: dentry to which path should be built -- * @plen: returned length of string -- * @pbase: returned base inode number -+ * @path_info: output path, length, base ino+snap, and freepath ownership flag - * @for_wire: is this path going to be sent to the MDS? - * - * Build a string that represents the path to the dentry. This is mostly called -@@ -2700,7 +2699,7 @@ static u8 *get_fscrypt_altname(const str - * foo/.snap/bar -> foo//bar - */ - char *ceph_mdsc_build_path(struct ceph_mds_client *mdsc, struct dentry *dentry, -- int *plen, u64 *pbase, int for_wire) -+ struct ceph_path_info *path_info, int for_wire) - { - struct ceph_client *cl = mdsc->fsc->client; - struct dentry *cur; -@@ -2810,16 +2809,28 @@ retry: - return ERR_PTR(-ENAMETOOLONG); - } - -- *pbase = base; -- *plen = PATH_MAX - 1 - pos; -+ /* Initialize the output structure */ -+ memset(path_info, 0, sizeof(*path_info)); -+ -+ path_info->vino.ino = base; -+ path_info->pathlen = PATH_MAX - 1 - pos; -+ path_info->path = path + pos; -+ path_info->freepath = true; -+ -+ /* Set snap from dentry if available */ -+ if (d_inode(dentry)) -+ path_info->vino.snap = ceph_snap(d_inode(dentry)); -+ else -+ path_info->vino.snap = CEPH_NOSNAP; -+ - doutc(cl, "on %p %d built %llx '%.*s'\n", dentry, d_count(dentry), -- base, *plen, path + pos); -+ base, PATH_MAX - 1 - pos, path + pos); - return path + pos; - } - - static int build_dentry_path(struct ceph_mds_client *mdsc, struct dentry *dentry, -- struct inode *dir, const char **ppath, int *ppathlen, -- u64 *pino, bool *pfreepath, bool parent_locked) -+ struct inode *dir, struct ceph_path_info *path_info, -+ bool parent_locked) - { - char *path; - -@@ -2828,41 +2839,47 @@ static int build_dentry_path(struct ceph - dir = d_inode_rcu(dentry->d_parent); - if (dir && parent_locked && ceph_snap(dir) == CEPH_NOSNAP && - !IS_ENCRYPTED(dir)) { -- *pino = ceph_ino(dir); -+ path_info->vino.ino = ceph_ino(dir); -+ path_info->vino.snap = ceph_snap(dir); - rcu_read_unlock(); -- *ppath = dentry->d_name.name; -- *ppathlen = dentry->d_name.len; -+ path_info->path = dentry->d_name.name; -+ path_info->pathlen = dentry->d_name.len; -+ path_info->freepath = false; - return 0; - } - rcu_read_unlock(); -- path = ceph_mdsc_build_path(mdsc, dentry, ppathlen, pino, 1); -+ path = ceph_mdsc_build_path(mdsc, dentry, path_info, 1); - if (IS_ERR(path)) - return PTR_ERR(path); -- *ppath = path; -- *pfreepath = true; -+ /* -+ * ceph_mdsc_build_path already fills path_info, including snap handling. -+ */ - return 0; - } - --static int build_inode_path(struct inode *inode, -- const char **ppath, int *ppathlen, u64 *pino, -- bool *pfreepath) -+static int build_inode_path(struct inode *inode, struct ceph_path_info *path_info) - { - struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb); - struct dentry *dentry; - char *path; - - if (ceph_snap(inode) == CEPH_NOSNAP) { -- *pino = ceph_ino(inode); -- *ppathlen = 0; -+ path_info->vino.ino = ceph_ino(inode); -+ path_info->vino.snap = ceph_snap(inode); -+ path_info->pathlen = 0; -+ path_info->freepath = false; - return 0; - } - dentry = d_find_alias(inode); -- path = ceph_mdsc_build_path(mdsc, dentry, ppathlen, pino, 1); -+ path = ceph_mdsc_build_path(mdsc, dentry, path_info, 1); - dput(dentry); - if (IS_ERR(path)) - return PTR_ERR(path); -- *ppath = path; -- *pfreepath = true; -+ /* -+ * ceph_mdsc_build_path already fills path_info, including snap from dentry. -+ * Override with inode's snap since that's what this function is for. -+ */ -+ path_info->vino.snap = ceph_snap(inode); - return 0; - } - -@@ -2872,26 +2889,32 @@ static int build_inode_path(struct inode - */ - static int set_request_path_attr(struct ceph_mds_client *mdsc, struct inode *rinode, - struct dentry *rdentry, struct inode *rdiri, -- const char *rpath, u64 rino, const char **ppath, -- int *pathlen, u64 *ino, bool *freepath, -+ const char *rpath, u64 rino, -+ struct ceph_path_info *path_info, - bool parent_locked) - { - struct ceph_client *cl = mdsc->fsc->client; - int r = 0; - -+ /* Initialize the output structure */ -+ memset(path_info, 0, sizeof(*path_info)); -+ - if (rinode) { -- r = build_inode_path(rinode, ppath, pathlen, ino, freepath); -+ r = build_inode_path(rinode, path_info); - doutc(cl, " inode %p %llx.%llx\n", rinode, ceph_ino(rinode), - ceph_snap(rinode)); - } else if (rdentry) { -- r = build_dentry_path(mdsc, rdentry, rdiri, ppath, pathlen, ino, -- freepath, parent_locked); -- doutc(cl, " dentry %p %llx/%.*s\n", rdentry, *ino, *pathlen, *ppath); -+ r = build_dentry_path(mdsc, rdentry, rdiri, path_info, parent_locked); -+ doutc(cl, " dentry %p %llx/%.*s\n", rdentry, path_info->vino.ino, -+ path_info->pathlen, path_info->path); - } else if (rpath || rino) { -- *ino = rino; -- *ppath = rpath; -- *pathlen = rpath ? strlen(rpath) : 0; -- doutc(cl, " path %.*s\n", *pathlen, rpath); -+ path_info->vino.ino = rino; -+ path_info->vino.snap = CEPH_NOSNAP; -+ path_info->path = rpath; -+ path_info->pathlen = rpath ? strlen(rpath) : 0; -+ path_info->freepath = false; -+ -+ doutc(cl, " path %.*s\n", path_info->pathlen, rpath); - } - - return r; -@@ -2968,11 +2991,8 @@ static struct ceph_msg *create_request_m - struct ceph_client *cl = mdsc->fsc->client; - struct ceph_msg *msg; - struct ceph_mds_request_head_legacy *lhead; -- const char *path1 = NULL; -- const char *path2 = NULL; -- u64 ino1 = 0, ino2 = 0; -- int pathlen1 = 0, pathlen2 = 0; -- bool freepath1 = false, freepath2 = false; -+ struct ceph_path_info path_info1 = {0}; -+ struct ceph_path_info path_info2 = {0}; - struct dentry *old_dentry = NULL; - int len; - u16 releases; -@@ -2982,25 +3002,49 @@ static struct ceph_msg *create_request_m - u16 request_head_version = mds_supported_head_version(session); - kuid_t caller_fsuid = req->r_cred->fsuid; - kgid_t caller_fsgid = req->r_cred->fsgid; -+ bool parent_locked = test_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags); - - ret = set_request_path_attr(mdsc, req->r_inode, req->r_dentry, -- req->r_parent, req->r_path1, req->r_ino1.ino, -- &path1, &pathlen1, &ino1, &freepath1, -- test_bit(CEPH_MDS_R_PARENT_LOCKED, -- &req->r_req_flags)); -+ req->r_parent, req->r_path1, req->r_ino1.ino, -+ &path_info1, parent_locked); - if (ret < 0) { - msg = ERR_PTR(ret); - goto out; - } - -+ /* -+ * When the parent directory's i_rwsem is *not* locked, req->r_parent may -+ * have become stale (e.g. after a concurrent rename) between the time the -+ * dentry was looked up and now. If we detect that the stored r_parent -+ * does not match the inode number we just encoded for the request, switch -+ * to the correct inode so that the MDS receives a valid parent reference. -+ */ -+ if (!parent_locked && req->r_parent && path_info1.vino.ino && -+ ceph_ino(req->r_parent) != path_info1.vino.ino) { -+ struct inode *old_parent = req->r_parent; -+ struct inode *correct_dir = ceph_get_inode(mdsc->fsc->sb, path_info1.vino, NULL); -+ if (!IS_ERR(correct_dir)) { -+ WARN_ONCE(1, "ceph: r_parent mismatch (had %llx wanted %llx) - updating\n", -+ ceph_ino(old_parent), path_info1.vino.ino); -+ /* -+ * Transfer CEPH_CAP_PIN from the old parent to the new one. -+ * The pin was taken earlier in ceph_mdsc_submit_request(). -+ */ -+ ceph_put_cap_refs(ceph_inode(old_parent), CEPH_CAP_PIN); -+ iput(old_parent); -+ req->r_parent = correct_dir; -+ ceph_get_cap_refs(ceph_inode(req->r_parent), CEPH_CAP_PIN); -+ } -+ } -+ - /* If r_old_dentry is set, then assume that its parent is locked */ - if (req->r_old_dentry && - !(req->r_old_dentry->d_flags & DCACHE_DISCONNECTED)) - old_dentry = req->r_old_dentry; - ret = set_request_path_attr(mdsc, NULL, old_dentry, -- req->r_old_dentry_dir, -- req->r_path2, req->r_ino2.ino, -- &path2, &pathlen2, &ino2, &freepath2, true); -+ req->r_old_dentry_dir, -+ req->r_path2, req->r_ino2.ino, -+ &path_info2, true); - if (ret < 0) { - msg = ERR_PTR(ret); - goto out_free1; -@@ -3031,7 +3075,7 @@ static struct ceph_msg *create_request_m - - /* filepaths */ - len += 2 * (1 + sizeof(u32) + sizeof(u64)); -- len += pathlen1 + pathlen2; -+ len += path_info1.pathlen + path_info2.pathlen; - - /* cap releases */ - len += sizeof(struct ceph_mds_request_release) * -@@ -3039,9 +3083,9 @@ static struct ceph_msg *create_request_m - !!req->r_old_inode_drop + !!req->r_old_dentry_drop); - - if (req->r_dentry_drop) -- len += pathlen1; -+ len += path_info1.pathlen; - if (req->r_old_dentry_drop) -- len += pathlen2; -+ len += path_info2.pathlen; - - /* MClientRequest tail */ - -@@ -3154,8 +3198,8 @@ static struct ceph_msg *create_request_m - lhead->ino = cpu_to_le64(req->r_deleg_ino); - lhead->args = req->r_args; - -- ceph_encode_filepath(&p, end, ino1, path1); -- ceph_encode_filepath(&p, end, ino2, path2); -+ ceph_encode_filepath(&p, end, path_info1.vino.ino, path_info1.path); -+ ceph_encode_filepath(&p, end, path_info2.vino.ino, path_info2.path); - - /* make note of release offset, in case we need to replay */ - req->r_request_release_offset = p - msg->front.iov_base; -@@ -3218,11 +3262,9 @@ static struct ceph_msg *create_request_m - msg->hdr.data_off = cpu_to_le16(0); - - out_free2: -- if (freepath2) -- ceph_mdsc_free_path((char *)path2, pathlen2); -+ ceph_mdsc_free_path_info(&path_info2); - out_free1: -- if (freepath1) -- ceph_mdsc_free_path((char *)path1, pathlen1); -+ ceph_mdsc_free_path_info(&path_info1); - out: - return msg; - out_err: -@@ -4579,24 +4621,20 @@ static int reconnect_caps_cb(struct inod - struct ceph_pagelist *pagelist = recon_state->pagelist; - struct dentry *dentry; - struct ceph_cap *cap; -- char *path; -- int pathlen = 0, err; -- u64 pathbase; -+ struct ceph_path_info path_info = {0}; -+ int err; - u64 snap_follows; - - dentry = d_find_primary(inode); - if (dentry) { - /* set pathbase to parent dir when msg_version >= 2 */ -- path = ceph_mdsc_build_path(mdsc, dentry, &pathlen, &pathbase, -+ char *path = ceph_mdsc_build_path(mdsc, dentry, &path_info, - recon_state->msg_version >= 2); - dput(dentry); - if (IS_ERR(path)) { - err = PTR_ERR(path); - goto out_err; - } -- } else { -- path = NULL; -- pathbase = 0; - } - - spin_lock(&ci->i_ceph_lock); -@@ -4629,7 +4667,7 @@ static int reconnect_caps_cb(struct inod - rec.v2.wanted = cpu_to_le32(__ceph_caps_wanted(ci)); - rec.v2.issued = cpu_to_le32(cap->issued); - rec.v2.snaprealm = cpu_to_le64(ci->i_snap_realm->ino); -- rec.v2.pathbase = cpu_to_le64(pathbase); -+ rec.v2.pathbase = cpu_to_le64(path_info.vino.ino); - rec.v2.flock_len = (__force __le32) - ((ci->i_ceph_flags & CEPH_I_ERROR_FILELOCK) ? 0 : 1); - } else { -@@ -4644,7 +4682,7 @@ static int reconnect_caps_cb(struct inod - ts = inode_get_atime(inode); - ceph_encode_timespec64(&rec.v1.atime, &ts); - rec.v1.snaprealm = cpu_to_le64(ci->i_snap_realm->ino); -- rec.v1.pathbase = cpu_to_le64(pathbase); -+ rec.v1.pathbase = cpu_to_le64(path_info.vino.ino); - } - - if (list_empty(&ci->i_cap_snaps)) { -@@ -4706,7 +4744,7 @@ encode_again: - sizeof(struct ceph_filelock); - rec.v2.flock_len = cpu_to_le32(struct_len); - -- struct_len += sizeof(u32) + pathlen + sizeof(rec.v2); -+ struct_len += sizeof(u32) + path_info.pathlen + sizeof(rec.v2); - - if (struct_v >= 2) - struct_len += sizeof(u64); /* snap_follows */ -@@ -4730,7 +4768,7 @@ encode_again: - ceph_pagelist_encode_8(pagelist, 1); - ceph_pagelist_encode_32(pagelist, struct_len); - } -- ceph_pagelist_encode_string(pagelist, path, pathlen); -+ ceph_pagelist_encode_string(pagelist, (char *)path_info.path, path_info.pathlen); - ceph_pagelist_append(pagelist, &rec, sizeof(rec.v2)); - ceph_locks_to_pagelist(flocks, pagelist, - num_fcntl_locks, num_flock_locks); -@@ -4741,17 +4779,17 @@ out_freeflocks: - } else { - err = ceph_pagelist_reserve(pagelist, - sizeof(u64) + sizeof(u32) + -- pathlen + sizeof(rec.v1)); -+ path_info.pathlen + sizeof(rec.v1)); - if (err) - goto out_err; - - ceph_pagelist_encode_64(pagelist, ceph_ino(inode)); -- ceph_pagelist_encode_string(pagelist, path, pathlen); -+ ceph_pagelist_encode_string(pagelist, (char *)path_info.path, path_info.pathlen); - ceph_pagelist_append(pagelist, &rec, sizeof(rec.v1)); - } - - out_err: -- ceph_mdsc_free_path(path, pathlen); -+ ceph_mdsc_free_path_info(&path_info); - if (!err) - recon_state->nr_caps++; - return err; -diff -purNx .git BPI-Router-Linux-kernel/fs/ceph/mds_client.h BPI-Router-Linux-kernel-6.16.12/fs/ceph/mds_client.h ---- BPI-Router-Linux-kernel/fs/ceph/mds_client.h 2025-10-22 13:53:23.507327727 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ceph/mds_client.h 2025-10-22 13:53:56.707168215 -0400 -@@ -617,14 +617,24 @@ extern int ceph_mds_check_access(struct - - extern void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc); - --static inline void ceph_mdsc_free_path(char *path, int len) -+/* -+ * Structure to group path-related output parameters for build_*_path functions -+ */ -+struct ceph_path_info { -+ const char *path; -+ int pathlen; -+ struct ceph_vino vino; -+ bool freepath; -+}; -+ -+static inline void ceph_mdsc_free_path_info(const struct ceph_path_info *path_info) - { -- if (!IS_ERR_OR_NULL(path)) -- __putname(path - (PATH_MAX - 1 - len)); -+ if (path_info && path_info->freepath && !IS_ERR_OR_NULL(path_info->path)) -+ __putname((char *)path_info->path - (PATH_MAX - 1 - path_info->pathlen)); - } - - extern char *ceph_mdsc_build_path(struct ceph_mds_client *mdsc, -- struct dentry *dentry, int *plen, u64 *base, -+ struct dentry *dentry, struct ceph_path_info *path_info, - int for_wire); - - extern void __ceph_mdsc_drop_dentry_lease(struct dentry *dentry); -diff -purNx .git BPI-Router-Linux-kernel/fs/coredump.c BPI-Router-Linux-kernel-6.16.12/fs/coredump.c ---- BPI-Router-Linux-kernel/fs/coredump.c 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/coredump.c 2025-10-22 13:53:56.707168215 -0400 -@@ -1263,11 +1263,15 @@ static int proc_dostring_coredump(const - ssize_t retval; - char old_core_pattern[CORENAME_MAX_SIZE]; - -+ if (write) -+ return proc_dostring(table, write, buffer, lenp, ppos); -+ - retval = strscpy(old_core_pattern, core_pattern, CORENAME_MAX_SIZE); - - error = proc_dostring(table, write, buffer, lenp, ppos); - if (error) - return error; -+ - if (!check_coredump_socket()) { - strscpy(core_pattern, old_core_pattern, retval + 1); - return -EINVAL; -diff -purNx .git BPI-Router-Linux-kernel/fs/crypto/fscrypt_private.h BPI-Router-Linux-kernel-6.16.12/fs/crypto/fscrypt_private.h ---- BPI-Router-Linux-kernel/fs/crypto/fscrypt_private.h 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/crypto/fscrypt_private.h 2025-10-22 13:53:56.707168215 -0400 -@@ -45,6 +45,23 @@ - */ - #undef FSCRYPT_MAX_KEY_SIZE - -+/* -+ * This mask is passed as the third argument to the crypto_alloc_*() functions -+ * to prevent fscrypt from using the Crypto API drivers for non-inline crypto -+ * engines. Those drivers have been problematic for fscrypt. fscrypt users -+ * have reported hangs and even incorrect en/decryption with these drivers. -+ * Since going to the driver, off CPU, and back again is really slow, such -+ * drivers can be over 50 times slower than the CPU-based code for fscrypt's -+ * workload. Even on platforms that lack AES instructions on the CPU, using the -+ * offloads has been shown to be slower, even staying with AES. (Of course, -+ * Adiantum is faster still, and is the recommended option on such platforms...) -+ * -+ * Note that fscrypt also supports inline crypto engines. Those don't use the -+ * Crypto API and work much better than the old-style (non-inline) engines. -+ */ -+#define FSCRYPT_CRYPTOAPI_MASK \ -+ (CRYPTO_ALG_ALLOCATES_MEMORY | CRYPTO_ALG_KERN_DRIVER_ONLY) -+ - #define FSCRYPT_CONTEXT_V1 1 - #define FSCRYPT_CONTEXT_V2 2 - -diff -purNx .git BPI-Router-Linux-kernel/fs/crypto/hkdf.c BPI-Router-Linux-kernel-6.16.12/fs/crypto/hkdf.c ---- BPI-Router-Linux-kernel/fs/crypto/hkdf.c 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/crypto/hkdf.c 2025-10-22 13:53:56.707168215 -0400 -@@ -58,7 +58,7 @@ int fscrypt_init_hkdf(struct fscrypt_hkd - u8 prk[HKDF_HASHLEN]; - int err; - -- hmac_tfm = crypto_alloc_shash(HKDF_HMAC_ALG, 0, 0); -+ hmac_tfm = crypto_alloc_shash(HKDF_HMAC_ALG, 0, FSCRYPT_CRYPTOAPI_MASK); - if (IS_ERR(hmac_tfm)) { - fscrypt_err(NULL, "Error allocating " HKDF_HMAC_ALG ": %ld", - PTR_ERR(hmac_tfm)); -diff -purNx .git BPI-Router-Linux-kernel/fs/crypto/keysetup.c BPI-Router-Linux-kernel-6.16.12/fs/crypto/keysetup.c ---- BPI-Router-Linux-kernel/fs/crypto/keysetup.c 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/crypto/keysetup.c 2025-10-22 13:53:56.707168215 -0400 -@@ -103,7 +103,8 @@ fscrypt_allocate_skcipher(struct fscrypt - struct crypto_skcipher *tfm; - int err; - -- tfm = crypto_alloc_skcipher(mode->cipher_str, 0, 0); -+ tfm = crypto_alloc_skcipher(mode->cipher_str, 0, -+ FSCRYPT_CRYPTOAPI_MASK); - if (IS_ERR(tfm)) { - if (PTR_ERR(tfm) == -ENOENT) { - fscrypt_warn(inode, -diff -purNx .git BPI-Router-Linux-kernel/fs/crypto/keysetup_v1.c BPI-Router-Linux-kernel-6.16.12/fs/crypto/keysetup_v1.c ---- BPI-Router-Linux-kernel/fs/crypto/keysetup_v1.c 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/crypto/keysetup_v1.c 2025-10-22 13:53:56.707168215 -0400 -@@ -52,7 +52,8 @@ static int derive_key_aes(const u8 *mast - struct skcipher_request *req = NULL; - DECLARE_CRYPTO_WAIT(wait); - struct scatterlist src_sg, dst_sg; -- struct crypto_skcipher *tfm = crypto_alloc_skcipher("ecb(aes)", 0, 0); -+ struct crypto_skcipher *tfm = -+ crypto_alloc_skcipher("ecb(aes)", 0, FSCRYPT_CRYPTOAPI_MASK); - - if (IS_ERR(tfm)) { - res = PTR_ERR(tfm); -diff -purNx .git BPI-Router-Linux-kernel/fs/debugfs/inode.c BPI-Router-Linux-kernel-6.16.12/fs/debugfs/inode.c ---- BPI-Router-Linux-kernel/fs/debugfs/inode.c 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/debugfs/inode.c 2025-10-22 13:53:56.707168215 -0400 -@@ -183,6 +183,9 @@ static int debugfs_reconfigure(struct fs - struct debugfs_fs_info *sb_opts = sb->s_fs_info; - struct debugfs_fs_info *new_opts = fc->s_fs_info; - -+ if (!new_opts) -+ return 0; -+ - sync_filesystem(sb); - - /* structure copy of new mount options to sb */ -@@ -282,10 +285,16 @@ static int debugfs_fill_super(struct sup - - static int debugfs_get_tree(struct fs_context *fc) - { -+ int err; -+ - if (!(debugfs_allow & DEBUGFS_ALLOW_API)) - return -EPERM; - -- return get_tree_single(fc, debugfs_fill_super); -+ err = get_tree_single(fc, debugfs_fill_super); -+ if (err) -+ return err; -+ -+ return debugfs_reconfigure(fc); - } - - static void debugfs_free_fc(struct fs_context *fc) -diff -purNx .git BPI-Router-Linux-kernel/fs/efivarfs/super.c BPI-Router-Linux-kernel-6.16.12/fs/efivarfs/super.c ---- BPI-Router-Linux-kernel/fs/efivarfs/super.c 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/efivarfs/super.c 2025-10-22 13:53:56.707168215 -0400 -@@ -152,6 +152,10 @@ static int efivarfs_d_compare(const stru - { - int guid = len - EFI_VARIABLE_GUID_LEN; - -+ /* Parallel lookups may produce a temporary invalid filename */ -+ if (guid <= 0) -+ return 1; -+ - if (name->len != len) - return 1; - -@@ -390,10 +394,16 @@ static int efivarfs_reconfigure(struct f - return 0; - } - -+static void efivarfs_free(struct fs_context *fc) -+{ -+ kfree(fc->s_fs_info); -+} -+ - static const struct fs_context_operations efivarfs_context_ops = { - .get_tree = efivarfs_get_tree, - .parse_param = efivarfs_parse_param, - .reconfigure = efivarfs_reconfigure, -+ .free = efivarfs_free, - }; - - static int efivarfs_check_missing(efi_char16_t *name16, efi_guid_t vendor, -diff -purNx .git BPI-Router-Linux-kernel/fs/erofs/data.c BPI-Router-Linux-kernel-6.16.12/fs/erofs/data.c ---- BPI-Router-Linux-kernel/fs/erofs/data.c 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/erofs/data.c 2025-10-22 13:53:56.707168215 -0400 -@@ -65,10 +65,10 @@ void erofs_init_metabuf(struct erofs_buf - } - - void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb, -- erofs_off_t offset, bool need_kmap) -+ erofs_off_t offset) - { - erofs_init_metabuf(buf, sb); -- return erofs_bread(buf, offset, need_kmap); -+ return erofs_bread(buf, offset, true); - } - - int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map) -@@ -118,7 +118,7 @@ int erofs_map_blocks(struct inode *inode - pos = ALIGN(erofs_iloc(inode) + vi->inode_isize + - vi->xattr_isize, unit) + unit * chunknr; - -- idx = erofs_read_metabuf(&buf, sb, pos, true); -+ idx = erofs_read_metabuf(&buf, sb, pos); - if (IS_ERR(idx)) { - err = PTR_ERR(idx); - goto out; -@@ -214,9 +214,11 @@ int erofs_map_dev(struct super_block *sb - - /* - * bit 30: I/O error occurred on this folio -+ * bit 29: CPU has dirty data in D-cache (needs aliasing handling); - * bit 0 - 29: remaining parts to complete this folio - */ --#define EROFS_ONLINEFOLIO_EIO (1 << 30) -+#define EROFS_ONLINEFOLIO_EIO 30 -+#define EROFS_ONLINEFOLIO_DIRTY 29 - - void erofs_onlinefolio_init(struct folio *folio) - { -@@ -233,19 +235,23 @@ void erofs_onlinefolio_split(struct foli - atomic_inc((atomic_t *)&folio->private); - } - --void erofs_onlinefolio_end(struct folio *folio, int err) -+void erofs_onlinefolio_end(struct folio *folio, int err, bool dirty) - { - int orig, v; - - do { - orig = atomic_read((atomic_t *)&folio->private); -- v = (orig - 1) | (err ? EROFS_ONLINEFOLIO_EIO : 0); -+ DBG_BUGON(orig <= 0); -+ v = dirty << EROFS_ONLINEFOLIO_DIRTY; -+ v |= (orig - 1) | (!!err << EROFS_ONLINEFOLIO_EIO); - } while (atomic_cmpxchg((atomic_t *)&folio->private, orig, v) != orig); - -- if (v & ~EROFS_ONLINEFOLIO_EIO) -+ if (v & (BIT(EROFS_ONLINEFOLIO_DIRTY) - 1)) - return; - folio->private = 0; -- folio_end_read(folio, !(v & EROFS_ONLINEFOLIO_EIO)); -+ if (v & BIT(EROFS_ONLINEFOLIO_DIRTY)) -+ flush_dcache_folio(folio); -+ folio_end_read(folio, !(v & BIT(EROFS_ONLINEFOLIO_EIO))); - } - - static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length, -@@ -293,7 +299,7 @@ static int erofs_iomap_begin(struct inod - struct erofs_buf buf = __EROFS_BUF_INITIALIZER; - - iomap->type = IOMAP_INLINE; -- ptr = erofs_read_metabuf(&buf, sb, mdev.m_pa, true); -+ ptr = erofs_read_metabuf(&buf, sb, mdev.m_pa); - if (IS_ERR(ptr)) - return PTR_ERR(ptr); - iomap->inline_data = ptr; -@@ -351,11 +357,16 @@ int erofs_fiemap(struct inode *inode, st - */ - static int erofs_read_folio(struct file *file, struct folio *folio) - { -+ trace_erofs_read_folio(folio, true); -+ - return iomap_read_folio(folio, &erofs_iomap_ops); - } - - static void erofs_readahead(struct readahead_control *rac) - { -+ trace_erofs_readahead(rac->mapping->host, readahead_index(rac), -+ readahead_count(rac), true); -+ - return iomap_readahead(rac, &erofs_iomap_ops); - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/erofs/decompressor.c BPI-Router-Linux-kernel-6.16.12/fs/erofs/decompressor.c ---- BPI-Router-Linux-kernel/fs/erofs/decompressor.c 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/erofs/decompressor.c 2025-10-22 13:53:56.707168215 -0400 -@@ -301,13 +301,11 @@ static int z_erofs_transform_plain(struc - cur = min(cur, rq->outputsize); - if (cur && rq->out[0]) { - kin = kmap_local_page(rq->in[nrpages_in - 1]); -- if (rq->out[0] == rq->in[nrpages_in - 1]) { -+ if (rq->out[0] == rq->in[nrpages_in - 1]) - memmove(kin + rq->pageofs_out, kin + pi, cur); -- flush_dcache_page(rq->out[0]); -- } else { -+ else - memcpy_to_page(rq->out[0], rq->pageofs_out, - kin + pi, cur); -- } - kunmap_local(kin); - } - rq->outputsize -= cur; -@@ -325,14 +323,12 @@ static int z_erofs_transform_plain(struc - po = (rq->pageofs_out + cur + pi) & ~PAGE_MASK; - DBG_BUGON(no >= nrpages_out); - cnt = min(insz - pi, PAGE_SIZE - po); -- if (rq->out[no] == rq->in[ni]) { -+ if (rq->out[no] == rq->in[ni]) - memmove(kin + po, - kin + rq->pageofs_in + pi, cnt); -- flush_dcache_page(rq->out[no]); -- } else if (rq->out[no]) { -+ else if (rq->out[no]) - memcpy_to_page(rq->out[no], po, - kin + rq->pageofs_in + pi, cnt); -- } - pi += cnt; - } while (pi < insz); - kunmap_local(kin); -diff -purNx .git BPI-Router-Linux-kernel/fs/erofs/dir.c BPI-Router-Linux-kernel-6.16.12/fs/erofs/dir.c ---- BPI-Router-Linux-kernel/fs/erofs/dir.c 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/erofs/dir.c 2025-10-22 13:53:56.707168215 -0400 -@@ -58,6 +58,11 @@ static int erofs_readdir(struct file *f, - struct erofs_dirent *de; - unsigned int nameoff, maxsize; - -+ if (fatal_signal_pending(current)) { -+ err = -ERESTARTSYS; -+ break; -+ } -+ - de = erofs_bread(&buf, dbstart, true); - if (IS_ERR(de)) { - erofs_err(sb, "failed to readdir of logical block %llu of nid %llu", -@@ -88,6 +93,7 @@ static int erofs_readdir(struct file *f, - break; - ctx->pos = dbstart + maxsize; - ofs = 0; -+ cond_resched(); - } - erofs_put_metabuf(&buf); - if (EROFS_I(dir)->dot_omitted && ctx->pos == dir->i_size) { -diff -purNx .git BPI-Router-Linux-kernel/fs/erofs/fileio.c BPI-Router-Linux-kernel-6.16.12/fs/erofs/fileio.c ---- BPI-Router-Linux-kernel/fs/erofs/fileio.c 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/erofs/fileio.c 2025-10-22 13:53:56.707168215 -0400 -@@ -38,7 +38,7 @@ static void erofs_fileio_ki_complete(str - } else { - bio_for_each_folio_all(fi, &rq->bio) { - DBG_BUGON(folio_test_uptodate(fi.folio)); -- erofs_onlinefolio_end(fi.folio, ret); -+ erofs_onlinefolio_end(fi.folio, ret, false); - } - } - bio_uninit(&rq->bio); -@@ -47,6 +47,7 @@ static void erofs_fileio_ki_complete(str - - static void erofs_fileio_rq_submit(struct erofs_fileio_rq *rq) - { -+ const struct cred *old_cred; - struct iov_iter iter; - int ret; - -@@ -60,7 +61,9 @@ static void erofs_fileio_rq_submit(struc - rq->iocb.ki_flags = IOCB_DIRECT; - iov_iter_bvec(&iter, ITER_DEST, rq->bvecs, rq->bio.bi_vcnt, - rq->bio.bi_iter.bi_size); -+ old_cred = override_creds(rq->iocb.ki_filp->f_cred); - ret = vfs_iocb_iter_read(rq->iocb.ki_filp, &rq->iocb, &iter); -+ revert_creds(old_cred); - if (ret != -EIOCBQUEUED) - erofs_fileio_ki_complete(&rq->iocb, ret); - } -@@ -93,8 +96,6 @@ static int erofs_fileio_scan_folio(struc - struct erofs_map_blocks *map = &io->map; - unsigned int cur = 0, end = folio_size(folio), len, attached = 0; - loff_t pos = folio_pos(folio), ofs; -- struct iov_iter iter; -- struct bio_vec bv; - int err = 0; - - erofs_onlinefolio_init(folio); -@@ -114,18 +115,12 @@ static int erofs_fileio_scan_folio(struc - void *src; - - src = erofs_read_metabuf(&buf, inode->i_sb, -- map->m_pa + ofs, true); -+ map->m_pa + ofs); - if (IS_ERR(src)) { - err = PTR_ERR(src); - break; - } -- bvec_set_folio(&bv, folio, len, cur); -- iov_iter_bvec(&iter, ITER_DEST, &bv, 1, len); -- if (copy_to_iter(src, len, &iter) != len) { -- erofs_put_metabuf(&buf); -- err = -EIO; -- break; -- } -+ memcpy_to_folio(folio, cur, src, len); - erofs_put_metabuf(&buf); - } else if (!(map->m_flags & EROFS_MAP_MAPPED)) { - folio_zero_segment(folio, cur, cur + len); -@@ -159,7 +154,7 @@ io_retry: - } - cur += len; - } -- erofs_onlinefolio_end(folio, err); -+ erofs_onlinefolio_end(folio, err, false); - return err; - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/erofs/fscache.c BPI-Router-Linux-kernel-6.16.12/fs/erofs/fscache.c ---- BPI-Router-Linux-kernel/fs/erofs/fscache.c 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/erofs/fscache.c 2025-10-22 13:53:56.707168215 -0400 -@@ -274,7 +274,7 @@ static int erofs_fscache_data_read_slice - size_t size = map.m_llen; - void *src; - -- src = erofs_read_metabuf(&buf, sb, map.m_pa, true); -+ src = erofs_read_metabuf(&buf, sb, map.m_pa); - if (IS_ERR(src)) - return PTR_ERR(src); - -diff -purNx .git BPI-Router-Linux-kernel/fs/erofs/inode.c BPI-Router-Linux-kernel-6.16.12/fs/erofs/inode.c ---- BPI-Router-Linux-kernel/fs/erofs/inode.c 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/erofs/inode.c 2025-10-22 13:53:56.707168215 -0400 -@@ -39,10 +39,10 @@ static int erofs_read_inode(struct inode - void *ptr; - int err = 0; - -- ptr = erofs_read_metabuf(&buf, sb, erofs_pos(sb, blkaddr), true); -+ ptr = erofs_read_metabuf(&buf, sb, erofs_pos(sb, blkaddr)); - if (IS_ERR(ptr)) { - err = PTR_ERR(ptr); -- erofs_err(sb, "failed to get inode (nid: %llu) page, err %d", -+ erofs_err(sb, "failed to read inode meta block (nid: %llu): %d", - vi->nid, err); - goto err_out; - } -@@ -78,10 +78,10 @@ static int erofs_read_inode(struct inode - - memcpy(&copied, dic, gotten); - ptr = erofs_read_metabuf(&buf, sb, -- erofs_pos(sb, blkaddr + 1), true); -+ erofs_pos(sb, blkaddr + 1)); - if (IS_ERR(ptr)) { - err = PTR_ERR(ptr); -- erofs_err(sb, "failed to get inode payload block (nid: %llu), err %d", -+ erofs_err(sb, "failed to read inode payload block (nid: %llu): %d", - vi->nid, err); - goto err_out; - } -diff -purNx .git BPI-Router-Linux-kernel/fs/erofs/internal.h BPI-Router-Linux-kernel-6.16.12/fs/erofs/internal.h ---- BPI-Router-Linux-kernel/fs/erofs/internal.h 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/erofs/internal.h 2025-10-22 13:53:56.707168215 -0400 -@@ -315,10 +315,12 @@ static inline struct folio *erofs_grab_f - /* The length of extent is full */ - #define EROFS_MAP_FULL_MAPPED 0x0008 - /* Located in the special packed inode */ --#define EROFS_MAP_FRAGMENT 0x0010 -+#define __EROFS_MAP_FRAGMENT 0x0010 - /* The extent refers to partial decompressed data */ - #define EROFS_MAP_PARTIAL_REF 0x0020 - -+#define EROFS_MAP_FRAGMENT (EROFS_MAP_MAPPED | __EROFS_MAP_FRAGMENT) -+ - struct erofs_map_blocks { - struct erofs_buf buf; - -@@ -383,14 +385,14 @@ void erofs_put_metabuf(struct erofs_buf - void *erofs_bread(struct erofs_buf *buf, erofs_off_t offset, bool need_kmap); - void erofs_init_metabuf(struct erofs_buf *buf, struct super_block *sb); - void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb, -- erofs_off_t offset, bool need_kmap); -+ erofs_off_t offset); - int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *dev); - int erofs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, - u64 start, u64 len); - int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map); - void erofs_onlinefolio_init(struct folio *folio); - void erofs_onlinefolio_split(struct folio *folio); --void erofs_onlinefolio_end(struct folio *folio, int err); -+void erofs_onlinefolio_end(struct folio *folio, int err, bool dirty); - struct inode *erofs_iget(struct super_block *sb, erofs_nid_t nid); - int erofs_getattr(struct mnt_idmap *idmap, const struct path *path, - struct kstat *stat, u32 request_mask, -diff -purNx .git BPI-Router-Linux-kernel/fs/erofs/Kconfig BPI-Router-Linux-kernel-6.16.12/fs/erofs/Kconfig ---- BPI-Router-Linux-kernel/fs/erofs/Kconfig 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/erofs/Kconfig 2025-10-22 13:53:56.707168215 -0400 -@@ -3,8 +3,18 @@ - config EROFS_FS - tristate "EROFS filesystem support" - depends on BLOCK -+ select CACHEFILES if EROFS_FS_ONDEMAND - select CRC32 -+ select CRYPTO if EROFS_FS_ZIP_ACCEL -+ select CRYPTO_DEFLATE if EROFS_FS_ZIP_ACCEL - select FS_IOMAP -+ select LZ4_DECOMPRESS if EROFS_FS_ZIP -+ select NETFS_SUPPORT if EROFS_FS_ONDEMAND -+ select XXHASH if EROFS_FS_XATTR -+ select XZ_DEC if EROFS_FS_ZIP_LZMA -+ select XZ_DEC_MICROLZMA if EROFS_FS_ZIP_LZMA -+ select ZLIB_INFLATE if EROFS_FS_ZIP_DEFLATE -+ select ZSTD_DECOMPRESS if EROFS_FS_ZIP_ZSTD - help - EROFS (Enhanced Read-Only File System) is a lightweight read-only - file system with modern designs (e.g. no buffer heads, inline -@@ -38,7 +48,6 @@ config EROFS_FS_DEBUG - config EROFS_FS_XATTR - bool "EROFS extended attributes" - depends on EROFS_FS -- select XXHASH - default y - help - Extended attributes are name:value pairs associated with inodes by -@@ -94,7 +103,6 @@ config EROFS_FS_BACKED_BY_FILE - config EROFS_FS_ZIP - bool "EROFS Data Compression Support" - depends on EROFS_FS -- select LZ4_DECOMPRESS - default y - help - Enable transparent compression support for EROFS file systems. -@@ -104,8 +112,6 @@ config EROFS_FS_ZIP - config EROFS_FS_ZIP_LZMA - bool "EROFS LZMA compressed data support" - depends on EROFS_FS_ZIP -- select XZ_DEC -- select XZ_DEC_MICROLZMA - help - Saying Y here includes support for reading EROFS file systems - containing LZMA compressed data, specifically called microLZMA. It -@@ -117,7 +123,6 @@ config EROFS_FS_ZIP_LZMA - config EROFS_FS_ZIP_DEFLATE - bool "EROFS DEFLATE compressed data support" - depends on EROFS_FS_ZIP -- select ZLIB_INFLATE - help - Saying Y here includes support for reading EROFS file systems - containing DEFLATE compressed data. It gives better compression -@@ -132,7 +137,6 @@ config EROFS_FS_ZIP_DEFLATE - config EROFS_FS_ZIP_ZSTD - bool "EROFS Zstandard compressed data support" - depends on EROFS_FS_ZIP -- select ZSTD_DECOMPRESS - help - Saying Y here includes support for reading EROFS file systems - containing Zstandard compressed data. It gives better compression -@@ -161,9 +165,7 @@ config EROFS_FS_ZIP_ACCEL - config EROFS_FS_ONDEMAND - bool "EROFS fscache-based on-demand read support (deprecated)" - depends on EROFS_FS -- select NETFS_SUPPORT - select FSCACHE -- select CACHEFILES - select CACHEFILES_ONDEMAND - help - This permits EROFS to use fscache-backed data blobs with on-demand -diff -purNx .git BPI-Router-Linux-kernel/fs/erofs/super.c BPI-Router-Linux-kernel-6.16.12/fs/erofs/super.c ---- BPI-Router-Linux-kernel/fs/erofs/super.c 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/erofs/super.c 2025-10-22 13:53:56.707168215 -0400 -@@ -141,7 +141,7 @@ static int erofs_init_device(struct erof - struct erofs_deviceslot *dis; - struct file *file; - -- dis = erofs_read_metabuf(buf, sb, *pos, true); -+ dis = erofs_read_metabuf(buf, sb, *pos); - if (IS_ERR(dis)) - return PTR_ERR(dis); - -@@ -174,6 +174,11 @@ static int erofs_init_device(struct erof - if (!erofs_is_fileio_mode(sbi)) { - dif->dax_dev = fs_dax_get_by_bdev(file_bdev(file), - &dif->dax_part_off, NULL, NULL); -+ if (!dif->dax_dev && test_opt(&sbi->opt, DAX_ALWAYS)) { -+ erofs_info(sb, "DAX unsupported by %s. Turning off DAX.", -+ dif->path); -+ clear_opt(&sbi->opt, DAX_ALWAYS); -+ } - } else if (!S_ISREG(file_inode(file)->i_mode)) { - fput(file); - return -EINVAL; -@@ -210,8 +215,13 @@ static int erofs_scan_devices(struct sup - ondisk_extradevs, sbi->devs->extra_devices); - return -EINVAL; - } -- if (!ondisk_extradevs) -+ if (!ondisk_extradevs) { -+ if (test_opt(&sbi->opt, DAX_ALWAYS) && !sbi->dif0.dax_dev) { -+ erofs_info(sb, "DAX unsupported by block device. Turning off DAX."); -+ clear_opt(&sbi->opt, DAX_ALWAYS); -+ } - return 0; -+ } - - if (!sbi->devs->extra_devices && !erofs_is_fscache_mode(sb)) - sbi->devs->flatdev = true; -@@ -258,7 +268,7 @@ static int erofs_read_superblock(struct - void *data; - int ret; - -- data = erofs_read_metabuf(&buf, sb, 0, true); -+ data = erofs_read_metabuf(&buf, sb, 0); - if (IS_ERR(data)) { - erofs_err(sb, "cannot read erofs superblock"); - return PTR_ERR(data); -@@ -313,8 +323,8 @@ static int erofs_read_superblock(struct - sbi->islotbits = ilog2(sizeof(struct erofs_inode_compact)); - if (erofs_sb_has_48bit(sbi) && dsb->rootnid_8b) { - sbi->root_nid = le64_to_cpu(dsb->rootnid_8b); -- sbi->dif0.blocks = (sbi->dif0.blocks << 32) | -- le16_to_cpu(dsb->rb.blocks_hi); -+ sbi->dif0.blocks = sbi->dif0.blocks | -+ ((u64)le16_to_cpu(dsb->rb.blocks_hi) << 32); - } else { - sbi->root_nid = le16_to_cpu(dsb->rb.rootnid_2b); - } -@@ -330,7 +340,6 @@ static int erofs_read_superblock(struct - if (ret < 0) - goto out; - -- /* handle multiple devices */ - ret = erofs_scan_devices(sb, dsb); - - if (erofs_sb_has_48bit(sbi)) -@@ -661,14 +670,9 @@ static int erofs_fc_fill_super(struct su - return invalfc(fc, "cannot use fsoffset in fscache mode"); - } - -- if (test_opt(&sbi->opt, DAX_ALWAYS)) { -- if (!sbi->dif0.dax_dev) { -- errorfc(fc, "DAX unsupported by block device. Turning off DAX."); -- clear_opt(&sbi->opt, DAX_ALWAYS); -- } else if (sbi->blkszbits != PAGE_SHIFT) { -- errorfc(fc, "unsupported blocksize for DAX"); -- clear_opt(&sbi->opt, DAX_ALWAYS); -- } -+ if (test_opt(&sbi->opt, DAX_ALWAYS) && sbi->blkszbits != PAGE_SHIFT) { -+ erofs_info(sb, "unsupported blocksize for DAX"); -+ clear_opt(&sbi->opt, DAX_ALWAYS); - } - - sb->s_time_gran = 1; -@@ -995,10 +999,22 @@ static int erofs_show_options(struct seq - return 0; - } - -+static void erofs_evict_inode(struct inode *inode) -+{ -+#ifdef CONFIG_FS_DAX -+ if (IS_DAX(inode)) -+ dax_break_layout_final(inode); -+#endif -+ -+ truncate_inode_pages_final(&inode->i_data); -+ clear_inode(inode); -+} -+ - const struct super_operations erofs_sops = { - .put_super = erofs_put_super, - .alloc_inode = erofs_alloc_inode, - .free_inode = erofs_free_inode, -+ .evict_inode = erofs_evict_inode, - .statfs = erofs_statfs, - .show_options = erofs_show_options, - }; -diff -purNx .git BPI-Router-Linux-kernel/fs/erofs/zdata.c BPI-Router-Linux-kernel-6.16.12/fs/erofs/zdata.c ---- BPI-Router-Linux-kernel/fs/erofs/zdata.c 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/erofs/zdata.c 2025-10-22 13:53:56.707168215 -0400 -@@ -805,6 +805,7 @@ static int z_erofs_pcluster_begin(struct - struct erofs_map_blocks *map = &fe->map; - struct super_block *sb = fe->inode->i_sb; - struct z_erofs_pcluster *pcl = NULL; -+ void *ptr; - int ret; - - DBG_BUGON(fe->pcl); -@@ -854,15 +855,14 @@ static int z_erofs_pcluster_begin(struct - /* bind cache first when cached decompression is preferred */ - z_erofs_bind_cache(fe); - } else { -- void *mptr; -- -- mptr = erofs_read_metabuf(&map->buf, sb, map->m_pa, false); -- if (IS_ERR(mptr)) { -- ret = PTR_ERR(mptr); -- erofs_err(sb, "failed to get inline data %d", ret); -+ erofs_init_metabuf(&map->buf, sb); -+ ptr = erofs_bread(&map->buf, map->m_pa, false); -+ if (IS_ERR(ptr)) { -+ ret = PTR_ERR(ptr); -+ erofs_err(sb, "failed to get inline folio %d", ret); - return ret; - } -- get_page(map->buf.page); -+ folio_get(page_folio(map->buf.page)); - WRITE_ONCE(fe->pcl->compressed_bvecs[0].page, map->buf.page); - fe->pcl->pageofs_in = map->m_pa & ~PAGE_MASK; - fe->mode = Z_EROFS_PCLUSTER_FOLLOWED_NOINPLACE; -@@ -1034,7 +1034,7 @@ static int z_erofs_scan_folio(struct z_e - if (!(map->m_flags & EROFS_MAP_MAPPED)) { - folio_zero_segment(folio, cur, end); - tight = false; -- } else if (map->m_flags & EROFS_MAP_FRAGMENT) { -+ } else if (map->m_flags & __EROFS_MAP_FRAGMENT) { - erofs_off_t fpos = offset + cur - map->m_la; - - err = z_erofs_read_fragment(inode->i_sb, folio, cur, -@@ -1091,7 +1091,7 @@ static int z_erofs_scan_folio(struct z_e - tight = (bs == PAGE_SIZE); - } - } while ((end = cur) > 0); -- erofs_onlinefolio_end(folio, err); -+ erofs_onlinefolio_end(folio, err, false); - return err; - } - -@@ -1196,7 +1196,7 @@ static void z_erofs_fill_other_copies(st - cur += len; - } - kunmap_local(dst); -- erofs_onlinefolio_end(page_folio(bvi->bvec.page), err); -+ erofs_onlinefolio_end(page_folio(bvi->bvec.page), err, true); - list_del(p); - kfree(bvi); - } -@@ -1325,9 +1325,8 @@ static int z_erofs_decompress_pcluster(s - - /* must handle all compressed pages before actual file pages */ - if (pcl->from_meta) { -- page = pcl->compressed_bvecs[0].page; -+ folio_put(page_folio(pcl->compressed_bvecs[0].page)); - WRITE_ONCE(pcl->compressed_bvecs[0].page, NULL); -- put_page(page); - } else { - /* managed folios are still left in compressed_bvecs[] */ - for (i = 0; i < pclusterpages; ++i) { -@@ -1355,7 +1354,7 @@ static int z_erofs_decompress_pcluster(s - - DBG_BUGON(z_erofs_page_is_invalidated(page)); - if (!z_erofs_is_shortlived_page(page)) { -- erofs_onlinefolio_end(page_folio(page), err); -+ erofs_onlinefolio_end(page_folio(page), err, true); - continue; - } - if (pcl->algorithmformat != Z_EROFS_COMPRESSION_LZ4) { -@@ -1430,6 +1429,16 @@ static void z_erofs_decompressqueue_kthr - } - #endif - -+/* Use (kthread_)work in atomic contexts to minimize scheduling overhead */ -+static inline bool z_erofs_in_atomic(void) -+{ -+ if (IS_ENABLED(CONFIG_PREEMPTION) && rcu_preempt_depth()) -+ return true; -+ if (!IS_ENABLED(CONFIG_PREEMPT_COUNT)) -+ return true; -+ return !preemptible(); -+} -+ - static void z_erofs_decompress_kickoff(struct z_erofs_decompressqueue *io, - int bios) - { -@@ -1444,8 +1453,7 @@ static void z_erofs_decompress_kickoff(s - - if (atomic_add_return(bios, &io->pending_bios)) - return; -- /* Use (kthread_)work and sync decompression for atomic contexts only */ -- if (!in_task() || irqs_disabled() || rcu_read_lock_any_held()) { -+ if (z_erofs_in_atomic()) { - #ifdef CONFIG_EROFS_FS_PCPU_KTHREAD - struct kthread_worker *worker; - -diff -purNx .git BPI-Router-Linux-kernel/fs/erofs/zmap.c BPI-Router-Linux-kernel-6.16.12/fs/erofs/zmap.c ---- BPI-Router-Linux-kernel/fs/erofs/zmap.c 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/erofs/zmap.c 2025-10-22 13:53:56.707168215 -0400 -@@ -31,7 +31,7 @@ static int z_erofs_load_full_lcluster(st - struct z_erofs_lcluster_index *di; - unsigned int advise; - -- di = erofs_read_metabuf(&m->map->buf, inode->i_sb, pos, true); -+ di = erofs_read_metabuf(&m->map->buf, inode->i_sb, pos); - if (IS_ERR(di)) - return PTR_ERR(di); - m->lcn = lcn; -@@ -146,7 +146,7 @@ static int z_erofs_load_compact_lcluster - else - return -EOPNOTSUPP; - -- in = erofs_read_metabuf(&m->map->buf, m->inode->i_sb, pos, true); -+ in = erofs_read_metabuf(&m->map->buf, m->inode->i_sb, pos); - if (IS_ERR(in)) - return PTR_ERR(in); - -@@ -403,18 +403,17 @@ static int z_erofs_map_blocks_fo(struct - .inode = inode, - .map = map, - }; -- int err = 0; -- unsigned int endoff, afmt; -+ unsigned int endoff; - unsigned long initial_lcn; - unsigned long long ofs, end; -+ int err; - - ofs = flags & EROFS_GET_BLOCKS_FINDTAIL ? inode->i_size - 1 : map->m_la; - if (fragment && !(flags & EROFS_GET_BLOCKS_FINDTAIL) && - !vi->z_tailextent_headlcn) { - map->m_la = 0; - map->m_llen = inode->i_size; -- map->m_flags = EROFS_MAP_MAPPED | -- EROFS_MAP_FULL_MAPPED | EROFS_MAP_FRAGMENT; -+ map->m_flags = EROFS_MAP_FRAGMENT; - return 0; - } - initial_lcn = ofs >> lclusterbits; -@@ -489,7 +488,7 @@ static int z_erofs_map_blocks_fo(struct - goto unmap_out; - } - } else if (fragment && m.lcn == vi->z_tailextent_headlcn) { -- map->m_flags |= EROFS_MAP_FRAGMENT; -+ map->m_flags = EROFS_MAP_FRAGMENT; - } else { - map->m_pa = erofs_pos(sb, m.pblk); - err = z_erofs_get_extent_compressedlen(&m, initial_lcn); -@@ -503,20 +502,15 @@ static int z_erofs_map_blocks_fo(struct - err = -EFSCORRUPTED; - goto unmap_out; - } -- afmt = vi->z_advise & Z_EROFS_ADVISE_INTERLACED_PCLUSTER ? -- Z_EROFS_COMPRESSION_INTERLACED : -- Z_EROFS_COMPRESSION_SHIFTED; -+ if (vi->z_advise & Z_EROFS_ADVISE_INTERLACED_PCLUSTER) -+ map->m_algorithmformat = Z_EROFS_COMPRESSION_INTERLACED; -+ else -+ map->m_algorithmformat = Z_EROFS_COMPRESSION_SHIFTED; -+ } else if (m.headtype == Z_EROFS_LCLUSTER_TYPE_HEAD2) { -+ map->m_algorithmformat = vi->z_algorithmtype[1]; - } else { -- afmt = m.headtype == Z_EROFS_LCLUSTER_TYPE_HEAD2 ? -- vi->z_algorithmtype[1] : vi->z_algorithmtype[0]; -- if (!(EROFS_I_SB(inode)->available_compr_algs & (1 << afmt))) { -- erofs_err(sb, "inconsistent algorithmtype %u for nid %llu", -- afmt, vi->nid); -- err = -EFSCORRUPTED; -- goto unmap_out; -- } -+ map->m_algorithmformat = vi->z_algorithmtype[0]; - } -- map->m_algorithmformat = afmt; - - if ((flags & EROFS_GET_BLOCKS_FIEMAP) || - ((flags & EROFS_GET_BLOCKS_READMORE) && -@@ -552,7 +546,7 @@ static int z_erofs_map_blocks_ext(struct - map->m_flags = 0; - if (recsz <= offsetof(struct z_erofs_extent, pstart_hi)) { - if (recsz <= offsetof(struct z_erofs_extent, pstart_lo)) { -- ext = erofs_read_metabuf(&map->buf, sb, pos, true); -+ ext = erofs_read_metabuf(&map->buf, sb, pos); - if (IS_ERR(ext)) - return PTR_ERR(ext); - pa = le64_to_cpu(*(__le64 *)ext); -@@ -565,7 +559,7 @@ static int z_erofs_map_blocks_ext(struct - } - - for (; lstart <= map->m_la; lstart += 1 << vi->z_lclusterbits) { -- ext = erofs_read_metabuf(&map->buf, sb, pos, true); -+ ext = erofs_read_metabuf(&map->buf, sb, pos); - if (IS_ERR(ext)) - return PTR_ERR(ext); - map->m_plen = le32_to_cpu(ext->plen); -@@ -585,7 +579,7 @@ static int z_erofs_map_blocks_ext(struct - for (l = 0, r = vi->z_extents; l < r; ) { - mid = l + (r - l) / 2; - ext = erofs_read_metabuf(&map->buf, sb, -- pos + mid * recsz, true); -+ pos + mid * recsz); - if (IS_ERR(ext)) - return PTR_ERR(ext); - -@@ -597,6 +591,10 @@ static int z_erofs_map_blocks_ext(struct - - if (la > map->m_la) { - r = mid; -+ if (la > lend) { -+ DBG_BUGON(1); -+ return -EFSCORRUPTED; -+ } - lend = la; - } else { - l = mid + 1; -@@ -613,7 +611,7 @@ static int z_erofs_map_blocks_ext(struct - if (lstart < lend) { - map->m_la = lstart; - if (last && (vi->z_advise & Z_EROFS_ADVISE_FRAGMENT_PCLUSTER)) { -- map->m_flags |= EROFS_MAP_MAPPED | EROFS_MAP_FRAGMENT; -+ map->m_flags = EROFS_MAP_FRAGMENT; - vi->z_fragmentoff = map->m_plen; - if (recsz > offsetof(struct z_erofs_extent, pstart_lo)) - vi->z_fragmentoff |= map->m_pa << 32; -@@ -635,23 +633,16 @@ static int z_erofs_map_blocks_ext(struct - } - } - map->m_llen = lend - map->m_la; -- if (!last && map->m_llen < sb->s_blocksize) { -- erofs_err(sb, "extent too small %llu @ offset %llu of nid %llu", -- map->m_llen, map->m_la, vi->nid); -- DBG_BUGON(1); -- return -EFSCORRUPTED; -- } - return 0; - } - --static int z_erofs_fill_inode_lazy(struct inode *inode) -+static int z_erofs_fill_inode(struct inode *inode, struct erofs_map_blocks *map) - { - struct erofs_inode *const vi = EROFS_I(inode); - struct super_block *const sb = inode->i_sb; -- int err, headnr; -- erofs_off_t pos; -- struct erofs_buf buf = __EROFS_BUF_INITIALIZER; - struct z_erofs_map_header *h; -+ erofs_off_t pos; -+ int err = 0; - - if (test_bit(EROFS_I_Z_INITED_BIT, &vi->flags)) { - /* -@@ -665,12 +656,11 @@ static int z_erofs_fill_inode_lazy(struc - if (wait_on_bit_lock(&vi->flags, EROFS_I_BL_Z_BIT, TASK_KILLABLE)) - return -ERESTARTSYS; - -- err = 0; - if (test_bit(EROFS_I_Z_INITED_BIT, &vi->flags)) - goto out_unlock; - - pos = ALIGN(erofs_iloc(inode) + vi->inode_isize + vi->xattr_isize, 8); -- h = erofs_read_metabuf(&buf, sb, pos, true); -+ h = erofs_read_metabuf(&map->buf, sb, pos); - if (IS_ERR(h)) { - err = PTR_ERR(h); - goto out_unlock; -@@ -702,22 +692,13 @@ static int z_erofs_fill_inode_lazy(struc - else if (vi->z_advise & Z_EROFS_ADVISE_INLINE_PCLUSTER) - vi->z_idata_size = le16_to_cpu(h->h_idata_size); - -- headnr = 0; -- if (vi->z_algorithmtype[0] >= Z_EROFS_COMPRESSION_MAX || -- vi->z_algorithmtype[++headnr] >= Z_EROFS_COMPRESSION_MAX) { -- erofs_err(sb, "unknown HEAD%u format %u for nid %llu, please upgrade kernel", -- headnr + 1, vi->z_algorithmtype[headnr], vi->nid); -- err = -EOPNOTSUPP; -- goto out_put_metabuf; -- } -- - if (!erofs_sb_has_big_pcluster(EROFS_SB(sb)) && - vi->z_advise & (Z_EROFS_ADVISE_BIG_PCLUSTER_1 | - Z_EROFS_ADVISE_BIG_PCLUSTER_2)) { - erofs_err(sb, "per-inode big pcluster without sb feature for nid %llu", - vi->nid); - err = -EFSCORRUPTED; -- goto out_put_metabuf; -+ goto out_unlock; - } - if (vi->datalayout == EROFS_INODE_COMPRESSED_COMPACT && - !(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1) ^ -@@ -725,32 +706,54 @@ static int z_erofs_fill_inode_lazy(struc - erofs_err(sb, "big pcluster head1/2 of compact indexes should be consistent for nid %llu", - vi->nid); - err = -EFSCORRUPTED; -- goto out_put_metabuf; -+ goto out_unlock; - } - - if (vi->z_idata_size || - (vi->z_advise & Z_EROFS_ADVISE_FRAGMENT_PCLUSTER)) { -- struct erofs_map_blocks map = { -+ struct erofs_map_blocks tm = { - .buf = __EROFS_BUF_INITIALIZER - }; - -- err = z_erofs_map_blocks_fo(inode, &map, -+ err = z_erofs_map_blocks_fo(inode, &tm, - EROFS_GET_BLOCKS_FINDTAIL); -- erofs_put_metabuf(&map.buf); -+ erofs_put_metabuf(&tm.buf); - if (err < 0) -- goto out_put_metabuf; -+ goto out_unlock; - } - done: - /* paired with smp_mb() at the beginning of the function */ - smp_mb(); - set_bit(EROFS_I_Z_INITED_BIT, &vi->flags); --out_put_metabuf: -- erofs_put_metabuf(&buf); - out_unlock: - clear_and_wake_up_bit(EROFS_I_BL_Z_BIT, &vi->flags); - return err; - } - -+static int z_erofs_map_sanity_check(struct inode *inode, -+ struct erofs_map_blocks *map) -+{ -+ struct erofs_sb_info *sbi = EROFS_I_SB(inode); -+ -+ if (!(map->m_flags & EROFS_MAP_ENCODED)) -+ return 0; -+ if (unlikely(map->m_algorithmformat >= Z_EROFS_COMPRESSION_RUNTIME_MAX)) { -+ erofs_err(inode->i_sb, "unknown algorithm %d @ pos %llu for nid %llu, please upgrade kernel", -+ map->m_algorithmformat, map->m_la, EROFS_I(inode)->nid); -+ return -EOPNOTSUPP; -+ } -+ if (unlikely(map->m_algorithmformat < Z_EROFS_COMPRESSION_MAX && -+ !(sbi->available_compr_algs & (1 << map->m_algorithmformat)))) { -+ erofs_err(inode->i_sb, "inconsistent algorithmtype %u for nid %llu", -+ map->m_algorithmformat, EROFS_I(inode)->nid); -+ return -EFSCORRUPTED; -+ } -+ if (unlikely(map->m_plen > Z_EROFS_PCLUSTER_MAX_SIZE || -+ map->m_llen > Z_EROFS_PCLUSTER_MAX_DSIZE)) -+ return -EOPNOTSUPP; -+ return 0; -+} -+ - int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map, - int flags) - { -@@ -763,7 +766,7 @@ int z_erofs_map_blocks_iter(struct inode - map->m_la = inode->i_size; - map->m_flags = 0; - } else { -- err = z_erofs_fill_inode_lazy(inode); -+ err = z_erofs_fill_inode(inode, map); - if (!err) { - if (vi->datalayout == EROFS_INODE_COMPRESSED_FULL && - (vi->z_advise & Z_EROFS_ADVISE_EXTENTS)) -@@ -771,10 +774,8 @@ int z_erofs_map_blocks_iter(struct inode - else - err = z_erofs_map_blocks_fo(inode, map, flags); - } -- if (!err && (map->m_flags & EROFS_MAP_ENCODED) && -- unlikely(map->m_plen > Z_EROFS_PCLUSTER_MAX_SIZE || -- map->m_llen > Z_EROFS_PCLUSTER_MAX_DSIZE)) -- err = -EOPNOTSUPP; -+ if (!err) -+ err = z_erofs_map_sanity_check(inode, map); - if (err) - map->m_llen = 0; - } -@@ -799,7 +800,7 @@ static int z_erofs_iomap_begin_report(st - iomap->length = map.m_llen; - if (map.m_flags & EROFS_MAP_MAPPED) { - iomap->type = IOMAP_MAPPED; -- iomap->addr = map.m_flags & EROFS_MAP_FRAGMENT ? -+ iomap->addr = map.m_flags & __EROFS_MAP_FRAGMENT ? - IOMAP_NULL_ADDR : map.m_pa; - } else { - iomap->type = IOMAP_HOLE; -diff -purNx .git BPI-Router-Linux-kernel/fs/eventpoll.c BPI-Router-Linux-kernel-6.16.12/fs/eventpoll.c ---- BPI-Router-Linux-kernel/fs/eventpoll.c 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/eventpoll.c 2025-10-22 13:53:56.707168215 -0400 -@@ -218,6 +218,7 @@ struct eventpoll { - /* used to optimize loop detection check */ - u64 gen; - struct hlist_head refs; -+ u8 loop_check_depth; - - /* - * usage count, used together with epitem->dying to -@@ -883,7 +884,7 @@ static bool __ep_remove(struct eventpoll - kfree_rcu(epi, rcu); - - percpu_counter_dec(&ep->user->epoll_watches); -- return ep_refcount_dec_and_test(ep); -+ return true; - } - - /* -@@ -891,14 +892,14 @@ static bool __ep_remove(struct eventpoll - */ - static void ep_remove_safe(struct eventpoll *ep, struct epitem *epi) - { -- WARN_ON_ONCE(__ep_remove(ep, epi, false)); -+ if (__ep_remove(ep, epi, false)) -+ WARN_ON_ONCE(ep_refcount_dec_and_test(ep)); - } - - static void ep_clear_and_put(struct eventpoll *ep) - { - struct rb_node *rbp, *next; - struct epitem *epi; -- bool dispose; - - /* We need to release all tasks waiting for these file */ - if (waitqueue_active(&ep->poll_wait)) -@@ -931,10 +932,8 @@ static void ep_clear_and_put(struct even - cond_resched(); - } - -- dispose = ep_refcount_dec_and_test(ep); - mutex_unlock(&ep->mtx); -- -- if (dispose) -+ if (ep_refcount_dec_and_test(ep)) - ep_free(ep); - } - -@@ -1137,7 +1136,7 @@ again: - dispose = __ep_remove(ep, epi, true); - mutex_unlock(&ep->mtx); - -- if (dispose) -+ if (dispose && ep_refcount_dec_and_test(ep)) - ep_free(ep); - goto again; - } -@@ -2142,23 +2141,24 @@ static int ep_poll(struct eventpoll *ep, - } - - /** -- * ep_loop_check_proc - verify that adding an epoll file inside another -- * epoll structure does not violate the constraints, in -- * terms of closed loops, or too deep chains (which can -- * result in excessive stack usage). -+ * ep_loop_check_proc - verify that adding an epoll file @ep inside another -+ * epoll file does not create closed loops, and -+ * determine the depth of the subtree starting at @ep - * - * @ep: the &struct eventpoll to be currently checked. - * @depth: Current depth of the path being checked. - * -- * Return: %zero if adding the epoll @file inside current epoll -- * structure @ep does not violate the constraints, or %-1 otherwise. -+ * Return: depth of the subtree, or INT_MAX if we found a loop or went too deep. - */ - static int ep_loop_check_proc(struct eventpoll *ep, int depth) - { -- int error = 0; -+ int result = 0; - struct rb_node *rbp; - struct epitem *epi; - -+ if (ep->gen == loop_check_gen) -+ return ep->loop_check_depth; -+ - mutex_lock_nested(&ep->mtx, depth + 1); - ep->gen = loop_check_gen; - for (rbp = rb_first_cached(&ep->rbr); rbp; rbp = rb_next(rbp)) { -@@ -2166,13 +2166,11 @@ static int ep_loop_check_proc(struct eve - if (unlikely(is_file_epoll(epi->ffd.file))) { - struct eventpoll *ep_tovisit; - ep_tovisit = epi->ffd.file->private_data; -- if (ep_tovisit->gen == loop_check_gen) -- continue; - if (ep_tovisit == inserting_into || depth > EP_MAX_NESTS) -- error = -1; -+ result = INT_MAX; - else -- error = ep_loop_check_proc(ep_tovisit, depth + 1); -- if (error != 0) -+ result = max(result, ep_loop_check_proc(ep_tovisit, depth + 1) + 1); -+ if (result > EP_MAX_NESTS) - break; - } else { - /* -@@ -2186,9 +2184,25 @@ static int ep_loop_check_proc(struct eve - list_file(epi->ffd.file); - } - } -+ ep->loop_check_depth = result; - mutex_unlock(&ep->mtx); - -- return error; -+ return result; -+} -+ -+/* ep_get_upwards_depth_proc - determine depth of @ep when traversed upwards */ -+static int ep_get_upwards_depth_proc(struct eventpoll *ep, int depth) -+{ -+ int result = 0; -+ struct epitem *epi; -+ -+ if (ep->gen == loop_check_gen) -+ return ep->loop_check_depth; -+ hlist_for_each_entry_rcu(epi, &ep->refs, fllink) -+ result = max(result, ep_get_upwards_depth_proc(epi->ep, depth + 1) + 1); -+ ep->gen = loop_check_gen; -+ ep->loop_check_depth = result; -+ return result; - } - - /** -@@ -2204,8 +2218,22 @@ static int ep_loop_check_proc(struct eve - */ - static int ep_loop_check(struct eventpoll *ep, struct eventpoll *to) - { -+ int depth, upwards_depth; -+ - inserting_into = ep; -- return ep_loop_check_proc(to, 0); -+ /* -+ * Check how deep down we can get from @to, and whether it is possible -+ * to loop up to @ep. -+ */ -+ depth = ep_loop_check_proc(to, 0); -+ if (depth > EP_MAX_NESTS) -+ return -1; -+ /* Check how far up we can go from @ep. */ -+ rcu_read_lock(); -+ upwards_depth = ep_get_upwards_depth_proc(ep, 0); -+ rcu_read_unlock(); -+ -+ return (depth+1+upwards_depth > EP_MAX_NESTS) ? -1 : 0; - } - - static void clear_tfile_check_list(void) -diff -purNx .git BPI-Router-Linux-kernel/fs/exec.c BPI-Router-Linux-kernel-6.16.12/fs/exec.c ---- BPI-Router-Linux-kernel/fs/exec.c 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/exec.c 2025-10-22 13:53:56.707168215 -0400 -@@ -114,6 +114,9 @@ static inline void put_binfmt(struct lin - - bool path_noexec(const struct path *path) - { -+ /* If it's an anonymous inode make sure that we catch any shenanigans. */ -+ VFS_WARN_ON_ONCE(IS_ANON_FILE(d_inode(path->dentry)) && -+ !(path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC)); - return (path->mnt->mnt_flags & MNT_NOEXEC) || - (path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC); - } -@@ -781,13 +784,15 @@ static struct file *do_open_execat(int f - if (IS_ERR(file)) - return file; - -+ if (path_noexec(&file->f_path)) -+ return ERR_PTR(-EACCES); -+ - /* - * In the past the regular type check was here. It moved to may_open() in - * 633fb6ac3980 ("exec: move S_ISREG() check earlier"). Since then it is - * an invariant that all non-regular files error out before we get here. - */ -- if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode)) || -- path_noexec(&file->f_path)) -+ if (WARN_ON_ONCE(!S_ISREG(file_inode(file)->i_mode))) - return ERR_PTR(-EACCES); - - err = exe_file_deny_write_access(file); -@@ -2043,7 +2048,7 @@ static int proc_dointvec_minmax_coredump - { - int error = proc_dointvec_minmax(table, write, buffer, lenp, ppos); - -- if (!error) -+ if (!error && !write) - validate_coredump_safety(); - return error; - } -diff -purNx .git BPI-Router-Linux-kernel/fs/exfat/dir.c BPI-Router-Linux-kernel-6.16.12/fs/exfat/dir.c ---- BPI-Router-Linux-kernel/fs/exfat/dir.c 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/exfat/dir.c 2025-10-22 13:53:56.707168215 -0400 -@@ -996,6 +996,7 @@ int exfat_find_dir_entry(struct super_bl - struct exfat_hint_femp candi_empty; - struct exfat_sb_info *sbi = EXFAT_SB(sb); - int num_entries = exfat_calc_num_entries(p_uniname); -+ unsigned int clu_count = 0; - - if (num_entries < 0) - return num_entries; -@@ -1133,6 +1134,10 @@ rewind: - } else { - if (exfat_get_next_cluster(sb, &clu.dir)) - return -EIO; -+ -+ /* break if the cluster chain includes a loop */ -+ if (unlikely(++clu_count > EXFAT_DATA_CLUSTER_COUNT(sbi))) -+ goto not_found; - } - } - -@@ -1195,6 +1200,7 @@ int exfat_count_dir_entries(struct super - int i, count = 0; - int dentries_per_clu; - unsigned int entry_type; -+ unsigned int clu_count = 0; - struct exfat_chain clu; - struct exfat_dentry *ep; - struct exfat_sb_info *sbi = EXFAT_SB(sb); -@@ -1227,6 +1233,12 @@ int exfat_count_dir_entries(struct super - } else { - if (exfat_get_next_cluster(sb, &(clu.dir))) - return -EIO; -+ -+ if (unlikely(++clu_count > sbi->used_clusters)) { -+ exfat_fs_error(sb, "FAT or bitmap is corrupted"); -+ return -EIO; -+ } -+ - } - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/exfat/fatent.c BPI-Router-Linux-kernel-6.16.12/fs/exfat/fatent.c ---- BPI-Router-Linux-kernel/fs/exfat/fatent.c 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/exfat/fatent.c 2025-10-22 13:53:56.707168215 -0400 -@@ -490,5 +490,15 @@ int exfat_count_num_clusters(struct supe - } - - *ret_count = count; -+ -+ /* -+ * since exfat_count_used_clusters() is not called, sbi->used_clusters -+ * cannot be used here. -+ */ -+ if (unlikely(i == sbi->num_clusters && clu != EXFAT_EOF_CLUSTER)) { -+ exfat_fs_error(sb, "The cluster chain has a loop"); -+ return -EIO; -+ } -+ - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/fs/exfat/file.c BPI-Router-Linux-kernel-6.16.12/fs/exfat/file.c ---- BPI-Router-Linux-kernel/fs/exfat/file.c 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/exfat/file.c 2025-10-22 13:53:56.707168215 -0400 -@@ -623,9 +623,8 @@ static ssize_t exfat_file_write_iter(str - if (pos > valid_size) - pos = valid_size; - -- if (iocb_is_dsync(iocb) && iocb->ki_pos > pos) { -- ssize_t err = vfs_fsync_range(file, pos, iocb->ki_pos - 1, -- iocb->ki_flags & IOCB_SYNC); -+ if (iocb->ki_pos > pos) { -+ ssize_t err = generic_write_sync(iocb, iocb->ki_pos - pos); - if (err < 0) - return err; - } -diff -purNx .git BPI-Router-Linux-kernel/fs/exfat/namei.c BPI-Router-Linux-kernel-6.16.12/fs/exfat/namei.c ---- BPI-Router-Linux-kernel/fs/exfat/namei.c 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/exfat/namei.c 2025-10-22 13:53:56.707168215 -0400 -@@ -890,6 +890,7 @@ static int exfat_check_dir_empty(struct - { - int i, dentries_per_clu; - unsigned int type; -+ unsigned int clu_count = 0; - struct exfat_chain clu; - struct exfat_dentry *ep; - struct exfat_sb_info *sbi = EXFAT_SB(sb); -@@ -926,6 +927,10 @@ static int exfat_check_dir_empty(struct - } else { - if (exfat_get_next_cluster(sb, &(clu.dir))) - return -EIO; -+ -+ /* break if the cluster chain includes a loop */ -+ if (unlikely(++clu_count > EXFAT_DATA_CLUSTER_COUNT(sbi))) -+ break; - } - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/exfat/super.c BPI-Router-Linux-kernel-6.16.12/fs/exfat/super.c ---- BPI-Router-Linux-kernel/fs/exfat/super.c 2025-10-22 13:53:23.511327708 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/exfat/super.c 2025-10-22 13:53:56.711168196 -0400 -@@ -341,13 +341,12 @@ static void exfat_hash_init(struct super - INIT_HLIST_HEAD(&sbi->inode_hashtable[i]); - } - --static int exfat_read_root(struct inode *inode) -+static int exfat_read_root(struct inode *inode, struct exfat_chain *root_clu) - { - struct super_block *sb = inode->i_sb; - struct exfat_sb_info *sbi = EXFAT_SB(sb); - struct exfat_inode_info *ei = EXFAT_I(inode); -- struct exfat_chain cdir; -- int num_subdirs, num_clu = 0; -+ int num_subdirs; - - exfat_chain_set(&ei->dir, sbi->root_dir, 0, ALLOC_FAT_CHAIN); - ei->entry = -1; -@@ -360,12 +359,9 @@ static int exfat_read_root(struct inode - ei->hint_stat.clu = sbi->root_dir; - ei->hint_femp.eidx = EXFAT_HINT_NONE; - -- exfat_chain_set(&cdir, sbi->root_dir, 0, ALLOC_FAT_CHAIN); -- if (exfat_count_num_clusters(sb, &cdir, &num_clu)) -- return -EIO; -- i_size_write(inode, num_clu << sbi->cluster_size_bits); -+ i_size_write(inode, EXFAT_CLU_TO_B(root_clu->size, sbi)); - -- num_subdirs = exfat_count_dir_entries(sb, &cdir); -+ num_subdirs = exfat_count_dir_entries(sb, root_clu); - if (num_subdirs < 0) - return -EIO; - set_nlink(inode, num_subdirs + EXFAT_MIN_SUBDIR); -@@ -578,7 +574,8 @@ static int exfat_verify_boot_region(stru - } - - /* mount the file system volume */ --static int __exfat_fill_super(struct super_block *sb) -+static int __exfat_fill_super(struct super_block *sb, -+ struct exfat_chain *root_clu) - { - int ret; - struct exfat_sb_info *sbi = EXFAT_SB(sb); -@@ -595,6 +592,18 @@ static int __exfat_fill_super(struct sup - goto free_bh; - } - -+ /* -+ * Call exfat_count_num_cluster() before searching for up-case and -+ * bitmap directory entries to avoid infinite loop if they are missing -+ * and the cluster chain includes a loop. -+ */ -+ exfat_chain_set(root_clu, sbi->root_dir, 0, ALLOC_FAT_CHAIN); -+ ret = exfat_count_num_clusters(sb, root_clu, &root_clu->size); -+ if (ret) { -+ exfat_err(sb, "failed to count the number of clusters in root"); -+ goto free_bh; -+ } -+ - ret = exfat_create_upcase_table(sb); - if (ret) { - exfat_err(sb, "failed to load upcase table"); -@@ -627,6 +636,7 @@ static int exfat_fill_super(struct super - struct exfat_sb_info *sbi = sb->s_fs_info; - struct exfat_mount_options *opts = &sbi->options; - struct inode *root_inode; -+ struct exfat_chain root_clu; - int err; - - if (opts->allow_utime == (unsigned short)-1) -@@ -645,7 +655,7 @@ static int exfat_fill_super(struct super - sb->s_time_min = EXFAT_MIN_TIMESTAMP_SECS; - sb->s_time_max = EXFAT_MAX_TIMESTAMP_SECS; - -- err = __exfat_fill_super(sb); -+ err = __exfat_fill_super(sb, &root_clu); - if (err) { - exfat_err(sb, "failed to recognize exfat type"); - goto check_nls_io; -@@ -680,7 +690,7 @@ static int exfat_fill_super(struct super - - root_inode->i_ino = EXFAT_ROOT_INO; - inode_set_iversion(root_inode, 1); -- err = exfat_read_root(root_inode); -+ err = exfat_read_root(root_inode, &root_clu); - if (err) { - exfat_err(sb, "failed to initialize root inode"); - goto put_inode; -diff -purNx .git BPI-Router-Linux-kernel/fs/ext2/inode.c BPI-Router-Linux-kernel-6.16.12/fs/ext2/inode.c ---- BPI-Router-Linux-kernel/fs/ext2/inode.c 2025-10-22 13:53:23.515327689 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ext2/inode.c 2025-10-22 13:53:56.711168196 -0400 -@@ -895,9 +895,19 @@ int ext2_fiemap(struct inode *inode, str - u64 start, u64 len) - { - int ret; -+ loff_t i_size; - - inode_lock(inode); -- len = min_t(u64, len, i_size_read(inode)); -+ i_size = i_size_read(inode); -+ /* -+ * iomap_fiemap() returns EINVAL for 0 length. Make sure we don't trim -+ * length to 0 but still trim the range as much as possible since -+ * ext2_get_blocks() iterates unmapped space block by block which is -+ * slow. -+ */ -+ if (i_size == 0) -+ i_size = 1; -+ len = min_t(u64, len, i_size); - ret = iomap_fiemap(inode, fieinfo, start, len, &ext2_iomap_ops); - inode_unlock(inode); - -diff -purNx .git BPI-Router-Linux-kernel/fs/ext4/ext4.h BPI-Router-Linux-kernel-6.16.12/fs/ext4/ext4.h ---- BPI-Router-Linux-kernel/fs/ext4/ext4.h 2025-10-22 13:53:23.515327689 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ext4/ext4.h 2025-10-22 13:53:56.711168196 -0400 -@@ -3020,7 +3020,7 @@ int ext4_walk_page_buffers(handle_t *han - struct buffer_head *bh)); - int do_journal_get_write_access(handle_t *handle, struct inode *inode, - struct buffer_head *bh); --bool ext4_should_enable_large_folio(struct inode *inode); -+void ext4_set_inode_mapping_order(struct inode *inode); - #define FALL_BACK_TO_NONDELALLOC 1 - #define CONVERT_INLINE_DATA 2 - -@@ -3064,9 +3064,9 @@ extern int ext4_punch_hole(struct file * - extern void ext4_set_inode_flags(struct inode *, bool init); - extern int ext4_alloc_da_blocks(struct inode *inode); - extern void ext4_set_aops(struct inode *inode); --extern int ext4_writepage_trans_blocks(struct inode *); - extern int ext4_normal_submit_inode_data_buffers(struct jbd2_inode *jinode); - extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks); -+extern int ext4_chunk_trans_extent(struct inode *inode, int nrblocks); - extern int ext4_meta_trans_blocks(struct inode *inode, int lblocks, - int pextents); - extern int ext4_zero_partial_blocks(handle_t *handle, struct inode *inode, -diff -purNx .git BPI-Router-Linux-kernel/fs/ext4/extents.c BPI-Router-Linux-kernel-6.16.12/fs/ext4/extents.c ---- BPI-Router-Linux-kernel/fs/ext4/extents.c 2025-10-22 13:53:23.515327689 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ext4/extents.c 2025-10-22 13:53:56.711168196 -0400 -@@ -5171,7 +5171,7 @@ ext4_ext_shift_path_extents(struct ext4_ - credits = depth + 2; - } - -- restart_credits = ext4_writepage_trans_blocks(inode); -+ restart_credits = ext4_chunk_trans_extent(inode, 0); - err = ext4_datasem_ensure_credits(handle, inode, credits, - restart_credits, 0); - if (err) { -@@ -5431,7 +5431,7 @@ static int ext4_collapse_range(struct fi - - truncate_pagecache(inode, start); - -- credits = ext4_writepage_trans_blocks(inode); -+ credits = ext4_chunk_trans_extent(inode, 0); - handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits); - if (IS_ERR(handle)) - return PTR_ERR(handle); -@@ -5527,7 +5527,7 @@ static int ext4_insert_range(struct file - - truncate_pagecache(inode, start); - -- credits = ext4_writepage_trans_blocks(inode); -+ credits = ext4_chunk_trans_extent(inode, 0); - handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits); - if (IS_ERR(handle)) - return PTR_ERR(handle); -diff -purNx .git BPI-Router-Linux-kernel/fs/ext4/fsmap.c BPI-Router-Linux-kernel-6.16.12/fs/ext4/fsmap.c ---- BPI-Router-Linux-kernel/fs/ext4/fsmap.c 2025-10-22 13:53:23.515327689 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ext4/fsmap.c 2025-10-22 13:53:56.711168196 -0400 -@@ -393,6 +393,14 @@ static unsigned int ext4_getfsmap_find_s - /* Reserved GDT blocks */ - if (!ext4_has_feature_meta_bg(sb) || metagroup < first_meta_bg) { - len = le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks); -+ -+ /* -+ * mkfs.ext4 can set s_reserved_gdt_blocks as 0 in some cases, -+ * check for that. -+ */ -+ if (!len) -+ return 0; -+ - error = ext4_getfsmap_fill(meta_list, fsb, len, - EXT4_FMR_OWN_RESV_GDT); - if (error) -@@ -526,6 +534,7 @@ static int ext4_getfsmap_datadev(struct - ext4_group_t end_ag; - ext4_grpblk_t first_cluster; - ext4_grpblk_t last_cluster; -+ struct ext4_fsmap irec; - int error = 0; - - bofs = le32_to_cpu(sbi->s_es->s_first_data_block); -@@ -609,10 +618,18 @@ static int ext4_getfsmap_datadev(struct - goto err; - } - -- /* Report any gaps at the end of the bg */ -+ /* -+ * The dummy record below will cause ext4_getfsmap_helper() to report -+ * any allocated blocks at the end of the range. -+ */ -+ irec.fmr_device = 0; -+ irec.fmr_physical = end_fsb + 1; -+ irec.fmr_length = 0; -+ irec.fmr_owner = EXT4_FMR_OWN_FREE; -+ irec.fmr_flags = 0; -+ - info->gfi_last = true; -- error = ext4_getfsmap_datadev_helper(sb, end_ag, last_cluster + 1, -- 0, info); -+ error = ext4_getfsmap_helper(sb, info, &irec); - if (error) - goto err; - -diff -purNx .git BPI-Router-Linux-kernel/fs/ext4/ialloc.c BPI-Router-Linux-kernel-6.16.12/fs/ext4/ialloc.c ---- BPI-Router-Linux-kernel/fs/ext4/ialloc.c 2025-10-22 13:53:23.515327689 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ext4/ialloc.c 2025-10-22 13:53:56.711168196 -0400 -@@ -1335,8 +1335,7 @@ got: - } - } - -- if (ext4_should_enable_large_folio(inode)) -- mapping_set_large_folios(inode->i_mapping); -+ ext4_set_inode_mapping_order(inode); - - ext4_update_inode_fsync_trans(handle, inode, 1); - -diff -purNx .git BPI-Router-Linux-kernel/fs/ext4/indirect.c BPI-Router-Linux-kernel-6.16.12/fs/ext4/indirect.c ---- BPI-Router-Linux-kernel/fs/ext4/indirect.c 2025-10-22 13:53:23.515327689 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ext4/indirect.c 2025-10-22 13:53:56.711168196 -0400 -@@ -539,7 +539,7 @@ int ext4_ind_map_blocks(handle_t *handle - int indirect_blks; - int blocks_to_boundary = 0; - int depth; -- int count = 0; -+ u64 count = 0; - ext4_fsblk_t first_block = 0; - - trace_ext4_ind_map_blocks_enter(inode, map->m_lblk, map->m_len, flags); -@@ -588,7 +588,7 @@ int ext4_ind_map_blocks(handle_t *handle - count++; - /* Fill in size of a hole we found */ - map->m_pblk = 0; -- map->m_len = min_t(unsigned int, map->m_len, count); -+ map->m_len = umin(map->m_len, count); - goto cleanup; - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/ext4/inline.c BPI-Router-Linux-kernel-6.16.12/fs/ext4/inline.c ---- BPI-Router-Linux-kernel/fs/ext4/inline.c 2025-10-22 13:53:23.515327689 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ext4/inline.c 2025-10-22 13:53:56.711168196 -0400 -@@ -303,7 +303,11 @@ static int ext4_create_inline_data(handl - if (error) - goto out; - -- BUG_ON(!is.s.not_found); -+ if (!is.s.not_found) { -+ EXT4_ERROR_INODE(inode, "unexpected inline data xattr"); -+ error = -EFSCORRUPTED; -+ goto out; -+ } - - error = ext4_xattr_ibody_set(handle, inode, &i, &is); - if (error) { -@@ -354,7 +358,11 @@ static int ext4_update_inline_data(handl - if (error) - goto out; - -- BUG_ON(is.s.not_found); -+ if (is.s.not_found) { -+ EXT4_ERROR_INODE(inode, "missing inline data xattr"); -+ error = -EFSCORRUPTED; -+ goto out; -+ } - - len -= EXT4_MIN_INLINE_DATA_SIZE; - value = kzalloc(len, GFP_NOFS); -@@ -562,7 +570,7 @@ static int ext4_convert_inline_data_to_e - return 0; - } - -- needed_blocks = ext4_writepage_trans_blocks(inode); -+ needed_blocks = ext4_chunk_trans_extent(inode, 1); - - ret = ext4_get_inode_loc(inode, &iloc); - if (ret) -@@ -612,6 +620,7 @@ retry: - } else - ret = ext4_block_write_begin(handle, folio, from, to, - ext4_get_block); -+ clear_buffer_new(folio_buffers(folio)); - - if (!ret && ext4_should_journal_data(inode)) { - ret = ext4_walk_page_buffers(handle, inode, -@@ -891,6 +900,7 @@ static int ext4_da_convert_inline_data_t - return ret; - } - -+ clear_buffer_new(folio_buffers(folio)); - folio_mark_dirty(folio); - folio_mark_uptodate(folio); - ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA); -@@ -1864,7 +1874,7 @@ int ext4_inline_data_truncate(struct ino - }; - - -- needed_blocks = ext4_writepage_trans_blocks(inode); -+ needed_blocks = ext4_chunk_trans_extent(inode, 1); - handle = ext4_journal_start(inode, EXT4_HT_INODE, needed_blocks); - if (IS_ERR(handle)) - return PTR_ERR(handle); -@@ -1903,7 +1913,12 @@ int ext4_inline_data_truncate(struct ino - if ((err = ext4_xattr_ibody_find(inode, &i, &is)) != 0) - goto out_error; - -- BUG_ON(is.s.not_found); -+ if (is.s.not_found) { -+ EXT4_ERROR_INODE(inode, -+ "missing inline data xattr"); -+ err = -EFSCORRUPTED; -+ goto out_error; -+ } - - value_len = le32_to_cpu(is.s.here->e_value_size); - value = kmalloc(value_len, GFP_NOFS); -@@ -1979,7 +1994,7 @@ int ext4_convert_inline_data(struct inod - return 0; - } - -- needed_blocks = ext4_writepage_trans_blocks(inode); -+ needed_blocks = ext4_chunk_trans_extent(inode, 1); - - iloc.bh = NULL; - error = ext4_get_inode_loc(inode, &iloc); -diff -purNx .git BPI-Router-Linux-kernel/fs/ext4/inode.c BPI-Router-Linux-kernel-6.16.12/fs/ext4/inode.c ---- BPI-Router-Linux-kernel/fs/ext4/inode.c 2025-10-22 13:53:23.515327689 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ext4/inode.c 2025-10-22 13:53:56.711168196 -0400 -@@ -146,7 +146,7 @@ static inline int ext4_begin_ordered_tru - */ - int ext4_inode_is_fast_symlink(struct inode *inode) - { -- if (!(EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)) { -+ if (!ext4_has_feature_ea_inode(inode->i_sb)) { - int ea_blocks = EXT4_I(inode)->i_file_acl ? - EXT4_CLUSTER_SIZE(inode->i_sb) >> 9 : 0; - -@@ -877,6 +877,26 @@ static void ext4_update_bh_state(struct - } while (unlikely(!try_cmpxchg(&bh->b_state, &old_state, new_state))); - } - -+/* -+ * Make sure that the current journal transaction has enough credits to map -+ * one extent. Return -EAGAIN if it cannot extend the current running -+ * transaction. -+ */ -+static inline int ext4_journal_ensure_extent_credits(handle_t *handle, -+ struct inode *inode) -+{ -+ int credits; -+ int ret; -+ -+ /* Called from ext4_da_write_begin() which has no handle started? */ -+ if (!handle) -+ return 0; -+ -+ credits = ext4_chunk_trans_blocks(inode, 1); -+ ret = __ext4_journal_ensure_credits(handle, credits, credits, 0); -+ return ret <= 0 ? ret : -EAGAIN; -+} -+ - static int _ext4_get_block(struct inode *inode, sector_t iblock, - struct buffer_head *bh, int flags) - { -@@ -1171,11 +1191,13 @@ int ext4_block_write_begin(handle_t *han - } - continue; - } -- if (buffer_new(bh)) -+ if (WARN_ON_ONCE(buffer_new(bh))) - clear_buffer_new(bh); - if (!buffer_mapped(bh)) { - WARN_ON(bh->b_size != blocksize); -- err = get_block(inode, block, bh, 1); -+ err = ext4_journal_ensure_extent_credits(handle, inode); -+ if (!err) -+ err = get_block(inode, block, bh, 1); - if (err) - break; - if (buffer_new(bh)) { -@@ -1274,7 +1296,8 @@ static int ext4_write_begin(struct file - * Reserve one block more for addition to orphan list in case - * we allocate blocks but write fails for some reason - */ -- needed_blocks = ext4_writepage_trans_blocks(inode) + 1; -+ needed_blocks = ext4_chunk_trans_extent(inode, -+ ext4_journal_blocks_per_folio(inode)) + 1; - index = pos >> PAGE_SHIFT; - - if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) { -@@ -1374,8 +1397,9 @@ retry_journal: - ext4_orphan_del(NULL, inode); - } - -- if (ret == -ENOSPC && -- ext4_should_retry_alloc(inode->i_sb, &retries)) -+ if (ret == -EAGAIN || -+ (ret == -ENOSPC && -+ ext4_should_retry_alloc(inode->i_sb, &retries))) - goto retry_journal; - folio_put(folio); - return ret; -@@ -1395,6 +1419,7 @@ static int write_end_fn(handle_t *handle - ret = ext4_dirty_journalled_data(handle, bh); - clear_buffer_meta(bh); - clear_buffer_prio(bh); -+ clear_buffer_new(bh); - return ret; - } - -@@ -1667,11 +1692,12 @@ struct mpage_da_data { - unsigned int can_map:1; /* Can writepages call map blocks? */ - - /* These are internal state of ext4_do_writepages() */ -- pgoff_t first_page; /* The first page to write */ -- pgoff_t next_page; /* Current page to examine */ -- pgoff_t last_page; /* Last page to examine */ -+ loff_t start_pos; /* The start pos to write */ -+ loff_t next_pos; /* Current pos to examine */ -+ loff_t end_pos; /* Last pos to examine */ -+ - /* -- * Extent to map - this can be after first_page because that can be -+ * Extent to map - this can be after start_pos because that can be - * fully mapped. We somewhat abuse m_flags to store whether the extent - * is delalloc or unwritten. - */ -@@ -1691,38 +1717,38 @@ static void mpage_release_unused_pages(s - struct inode *inode = mpd->inode; - struct address_space *mapping = inode->i_mapping; - -- /* This is necessary when next_page == 0. */ -- if (mpd->first_page >= mpd->next_page) -+ /* This is necessary when next_pos == 0. */ -+ if (mpd->start_pos >= mpd->next_pos) - return; - - mpd->scanned_until_end = 0; -- index = mpd->first_page; -- end = mpd->next_page - 1; - if (invalidate) { - ext4_lblk_t start, last; -- start = index << (PAGE_SHIFT - inode->i_blkbits); -- last = end << (PAGE_SHIFT - inode->i_blkbits); -+ start = EXT4_B_TO_LBLK(inode, mpd->start_pos); -+ last = mpd->next_pos >> inode->i_blkbits; - - /* - * avoid racing with extent status tree scans made by - * ext4_insert_delayed_block() - */ - down_write(&EXT4_I(inode)->i_data_sem); -- ext4_es_remove_extent(inode, start, last - start + 1); -+ ext4_es_remove_extent(inode, start, last - start); - up_write(&EXT4_I(inode)->i_data_sem); - } - - folio_batch_init(&fbatch); -- while (index <= end) { -- nr = filemap_get_folios(mapping, &index, end, &fbatch); -+ index = mpd->start_pos >> PAGE_SHIFT; -+ end = mpd->next_pos >> PAGE_SHIFT; -+ while (index < end) { -+ nr = filemap_get_folios(mapping, &index, end - 1, &fbatch); - if (nr == 0) - break; - for (i = 0; i < nr; i++) { - struct folio *folio = fbatch.folios[i]; - -- if (folio->index < mpd->first_page) -+ if (folio_pos(folio) < mpd->start_pos) - continue; -- if (folio_next_index(folio) - 1 > end) -+ if (folio_next_index(folio) > end) - continue; - BUG_ON(!folio_test_locked(folio)); - BUG_ON(folio_test_writeback(folio)); -@@ -2024,7 +2050,8 @@ int ext4_da_get_block_prep(struct inode - - static void mpage_folio_done(struct mpage_da_data *mpd, struct folio *folio) - { -- mpd->first_page += folio_nr_pages(folio); -+ mpd->start_pos += folio_size(folio); -+ mpd->wbc->nr_to_write -= folio_nr_pages(folio); - folio_unlock(folio); - } - -@@ -2034,7 +2061,7 @@ static int mpage_submit_folio(struct mpa - loff_t size; - int err; - -- BUG_ON(folio->index != mpd->first_page); -+ WARN_ON_ONCE(folio_pos(folio) != mpd->start_pos); - folio_clear_dirty_for_io(folio); - /* - * We have to be very careful here! Nothing protects writeback path -@@ -2055,8 +2082,6 @@ static int mpage_submit_folio(struct mpa - !ext4_verity_in_progress(mpd->inode)) - len = size & (len - 1); - err = ext4_bio_write_folio(&mpd->io_submit, folio, len); -- if (!err) -- mpd->wbc->nr_to_write -= folio_nr_pages(folio); - - return err; - } -@@ -2323,6 +2348,11 @@ static int mpage_map_one_extent(handle_t - int get_blocks_flags; - int err, dioread_nolock; - -+ /* Make sure transaction has enough credits for this extent */ -+ err = ext4_journal_ensure_extent_credits(handle, inode); -+ if (err < 0) -+ return err; -+ - trace_ext4_da_write_pages_extent(inode, map); - /* - * Call ext4_map_blocks() to allocate any delayed allocation blocks, or -@@ -2362,6 +2392,47 @@ static int mpage_map_one_extent(handle_t - } - - /* -+ * This is used to submit mapped buffers in a single folio that is not fully -+ * mapped for various reasons, such as insufficient space or journal credits. -+ */ -+static int mpage_submit_partial_folio(struct mpage_da_data *mpd) -+{ -+ struct inode *inode = mpd->inode; -+ struct folio *folio; -+ loff_t pos; -+ int ret; -+ -+ folio = filemap_get_folio(inode->i_mapping, -+ mpd->start_pos >> PAGE_SHIFT); -+ if (IS_ERR(folio)) -+ return PTR_ERR(folio); -+ /* -+ * The mapped position should be within the current processing folio -+ * but must not be the folio start position. -+ */ -+ pos = ((loff_t)mpd->map.m_lblk) << inode->i_blkbits; -+ if (WARN_ON_ONCE((folio_pos(folio) == pos) || -+ !folio_contains(folio, pos >> PAGE_SHIFT))) -+ return -EINVAL; -+ -+ ret = mpage_submit_folio(mpd, folio); -+ if (ret) -+ goto out; -+ /* -+ * Update start_pos to prevent this folio from being released in -+ * mpage_release_unused_pages(), it will be reset to the aligned folio -+ * pos when this folio is written again in the next round. Additionally, -+ * do not update wbc->nr_to_write here, as it will be updated once the -+ * entire folio has finished processing. -+ */ -+ mpd->start_pos = pos; -+out: -+ folio_unlock(folio); -+ folio_put(folio); -+ return ret; -+} -+ -+/* - * mpage_map_and_submit_extent - map extent starting at mpd->lblk of length - * mpd->len and submit pages underlying it for IO - * -@@ -2409,10 +2480,18 @@ static int mpage_map_and_submit_extent(h - * In the case of ENOSPC, if ext4_count_free_blocks() - * is non-zero, a commit should free up blocks. - */ -- if ((err == -ENOMEM) || -+ if ((err == -ENOMEM) || (err == -EAGAIN) || - (err == -ENOSPC && ext4_count_free_clusters(sb))) { -- if (progress) -+ /* -+ * We may have already allocated extents for -+ * some bhs inside the folio, issue the -+ * corresponding data to prevent stale data. -+ */ -+ if (progress) { -+ if (mpage_submit_partial_folio(mpd)) -+ goto invalidate_dirty_pages; - goto update_disksize; -+ } - return err; - } - ext4_msg(sb, KERN_CRIT, -@@ -2446,7 +2525,7 @@ update_disksize: - * Update on-disk size after IO is submitted. Races with - * truncate are avoided by checking i_size under i_data_sem. - */ -- disksize = ((loff_t)mpd->first_page) << PAGE_SHIFT; -+ disksize = mpd->start_pos; - if (disksize > READ_ONCE(EXT4_I(inode)->i_disksize)) { - int err2; - loff_t i_size; -@@ -2470,21 +2549,6 @@ update_disksize: - return err; - } - --/* -- * Calculate the total number of credits to reserve for one writepages -- * iteration. This is called from ext4_writepages(). We map an extent of -- * up to MAX_WRITEPAGES_EXTENT_LEN blocks and then we go on and finish mapping -- * the last partial page. So in total we can map MAX_WRITEPAGES_EXTENT_LEN + -- * bpp - 1 blocks in bpp different extents. -- */ --static int ext4_da_writepages_trans_blocks(struct inode *inode) --{ -- int bpp = ext4_journal_blocks_per_folio(inode); -- -- return ext4_meta_trans_blocks(inode, -- MAX_WRITEPAGES_EXTENT_LEN + bpp - 1, bpp); --} -- - static int ext4_journal_folio_buffers(handle_t *handle, struct folio *folio, - size_t len) - { -@@ -2549,8 +2613,8 @@ static int mpage_prepare_extent_to_map(s - struct address_space *mapping = mpd->inode->i_mapping; - struct folio_batch fbatch; - unsigned int nr_folios; -- pgoff_t index = mpd->first_page; -- pgoff_t end = mpd->last_page; -+ pgoff_t index = mpd->start_pos >> PAGE_SHIFT; -+ pgoff_t end = mpd->end_pos >> PAGE_SHIFT; - xa_mark_t tag; - int i, err = 0; - int blkbits = mpd->inode->i_blkbits; -@@ -2565,7 +2629,7 @@ static int mpage_prepare_extent_to_map(s - tag = PAGECACHE_TAG_DIRTY; - - mpd->map.m_len = 0; -- mpd->next_page = index; -+ mpd->next_pos = mpd->start_pos; - if (ext4_should_journal_data(mpd->inode)) { - handle = ext4_journal_start(mpd->inode, EXT4_HT_WRITE_PAGE, - bpp); -@@ -2596,7 +2660,8 @@ static int mpage_prepare_extent_to_map(s - goto out; - - /* If we can't merge this page, we are done. */ -- if (mpd->map.m_len > 0 && mpd->next_page != folio->index) -+ if (mpd->map.m_len > 0 && -+ mpd->next_pos != folio_pos(folio)) - goto out; - - if (handle) { -@@ -2642,8 +2707,8 @@ static int mpage_prepare_extent_to_map(s - } - - if (mpd->map.m_len == 0) -- mpd->first_page = folio->index; -- mpd->next_page = folio_next_index(folio); -+ mpd->start_pos = folio_pos(folio); -+ mpd->next_pos = folio_pos(folio) + folio_size(folio); - /* - * Writeout when we cannot modify metadata is simple. - * Just submit the page. For data=journal mode we -@@ -2771,12 +2836,12 @@ static int ext4_do_writepages(struct mpa - mpd->journalled_more_data = 0; - - if (ext4_should_dioread_nolock(inode)) { -+ int bpf = ext4_journal_blocks_per_folio(inode); - /* - * We may need to convert up to one extent per block in -- * the page and we may dirty the inode. -+ * the folio and we may dirty the inode. - */ -- rsv_blocks = 1 + ext4_chunk_trans_blocks(inode, -- PAGE_SIZE >> inode->i_blkbits); -+ rsv_blocks = 1 + ext4_ext_index_trans_blocks(inode, bpf); - } - - if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) -@@ -2786,18 +2851,18 @@ static int ext4_do_writepages(struct mpa - writeback_index = mapping->writeback_index; - if (writeback_index) - cycled = 0; -- mpd->first_page = writeback_index; -- mpd->last_page = -1; -+ mpd->start_pos = writeback_index << PAGE_SHIFT; -+ mpd->end_pos = LLONG_MAX; - } else { -- mpd->first_page = wbc->range_start >> PAGE_SHIFT; -- mpd->last_page = wbc->range_end >> PAGE_SHIFT; -+ mpd->start_pos = wbc->range_start; -+ mpd->end_pos = wbc->range_end; - } - - ext4_io_submit_init(&mpd->io_submit, wbc); - retry: - if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages) -- tag_pages_for_writeback(mapping, mpd->first_page, -- mpd->last_page); -+ tag_pages_for_writeback(mapping, mpd->start_pos >> PAGE_SHIFT, -+ mpd->end_pos >> PAGE_SHIFT); - blk_start_plug(&plug); - - /* -@@ -2840,8 +2905,14 @@ retry: - * not supported by delalloc. - */ - BUG_ON(ext4_should_journal_data(inode)); -- needed_blocks = ext4_da_writepages_trans_blocks(inode); -- -+ /* -+ * Calculate the number of credits needed to reserve for one -+ * extent of up to MAX_WRITEPAGES_EXTENT_LEN blocks. It will -+ * attempt to extend the transaction or start a new iteration -+ * if the reserved credits are insufficient. -+ */ -+ needed_blocks = ext4_chunk_trans_blocks(inode, -+ MAX_WRITEPAGES_EXTENT_LEN); - /* start a new transaction */ - handle = ext4_journal_start_with_reserve(inode, - EXT4_HT_WRITE_PAGE, needed_blocks, rsv_blocks); -@@ -2857,7 +2928,8 @@ retry: - } - mpd->do_map = 1; - -- trace_ext4_da_write_pages(inode, mpd->first_page, wbc); -+ trace_ext4_da_write_folios_start(inode, mpd->start_pos, -+ mpd->next_pos, wbc); - ret = mpage_prepare_extent_to_map(mpd); - if (!ret && mpd->map.m_len) - ret = mpage_map_and_submit_extent(handle, mpd, -@@ -2895,6 +2967,8 @@ retry: - } else - ext4_put_io_end(mpd->io_submit.io_end); - mpd->io_submit.io_end = NULL; -+ trace_ext4_da_write_folios_end(inode, mpd->start_pos, -+ mpd->next_pos, wbc, ret); - - if (ret == -ENOSPC && sbi->s_journal) { - /* -@@ -2906,6 +2980,8 @@ retry: - ret = 0; - continue; - } -+ if (ret == -EAGAIN) -+ ret = 0; - /* Fatal error - ENOMEM, EIO... */ - if (ret) - break; -@@ -2914,8 +2990,8 @@ unplug: - blk_finish_plug(&plug); - if (!ret && !cycled && wbc->nr_to_write > 0) { - cycled = 1; -- mpd->last_page = writeback_index - 1; -- mpd->first_page = 0; -+ mpd->end_pos = (writeback_index << PAGE_SHIFT) - 1; -+ mpd->start_pos = 0; - goto retry; - } - -@@ -2925,7 +3001,7 @@ unplug: - * Set the writeback_index so that range_cyclic - * mode will write it back later - */ -- mapping->writeback_index = mpd->first_page; -+ mapping->writeback_index = mpd->start_pos >> PAGE_SHIFT; - - out_writepages: - trace_ext4_writepages_result(inode, wbc, ret, -@@ -4389,7 +4465,7 @@ int ext4_punch_hole(struct file *file, l - return ret; - - if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) -- credits = ext4_writepage_trans_blocks(inode); -+ credits = ext4_chunk_trans_extent(inode, 2); - else - credits = ext4_blocks_for_truncate(inode); - handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits); -@@ -4538,7 +4614,7 @@ int ext4_truncate(struct inode *inode) - } - - if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) -- credits = ext4_writepage_trans_blocks(inode); -+ credits = ext4_chunk_trans_extent(inode, 1); - else - credits = ext4_blocks_for_truncate(inode); - -@@ -5106,7 +5182,7 @@ error: - return -EFSCORRUPTED; - } - --bool ext4_should_enable_large_folio(struct inode *inode) -+static bool ext4_should_enable_large_folio(struct inode *inode) - { - struct super_block *sb = inode->i_sb; - -@@ -5123,6 +5199,22 @@ bool ext4_should_enable_large_folio(stru - return true; - } - -+/* -+ * Limit the maximum folio order to 2048 blocks to prevent overestimation -+ * of reserve handle credits during the folio writeback in environments -+ * where the PAGE_SIZE exceeds 4KB. -+ */ -+#define EXT4_MAX_PAGECACHE_ORDER(i) \ -+ umin(MAX_PAGECACHE_ORDER, (11 + (i)->i_blkbits - PAGE_SHIFT)) -+void ext4_set_inode_mapping_order(struct inode *inode) -+{ -+ if (!ext4_should_enable_large_folio(inode)) -+ return; -+ -+ mapping_set_folio_order_range(inode->i_mapping, 0, -+ EXT4_MAX_PAGECACHE_ORDER(inode)); -+} -+ - struct inode *__ext4_iget(struct super_block *sb, unsigned long ino, - ext4_iget_flags flags, const char *function, - unsigned int line) -@@ -5440,8 +5532,8 @@ struct inode *__ext4_iget(struct super_b - ret = -EFSCORRUPTED; - goto bad_inode; - } -- if (ext4_should_enable_large_folio(inode)) -- mapping_set_large_folios(inode->i_mapping); -+ -+ ext4_set_inode_mapping_order(inode); - - ret = check_igot_inode(inode, flags, function, line); - /* -@@ -6139,7 +6231,7 @@ int ext4_meta_trans_blocks(struct inode - int ret; - - /* -- * How many index and lead blocks need to touch to map @lblocks -+ * How many index and leaf blocks need to touch to map @lblocks - * logical blocks to @pextents physical extents? - */ - idxblocks = ext4_index_trans_blocks(inode, lblocks, pextents); -@@ -6148,7 +6240,7 @@ int ext4_meta_trans_blocks(struct inode - * Now let's see how many group bitmaps and group descriptors need - * to account - */ -- groups = idxblocks; -+ groups = idxblocks + pextents; - gdpblocks = groups; - if (groups > ngroups) - groups = ngroups; -@@ -6165,25 +6257,19 @@ int ext4_meta_trans_blocks(struct inode - } - - /* -- * Calculate the total number of credits to reserve to fit -- * the modification of a single pages into a single transaction, -- * which may include multiple chunks of block allocations. -- * -- * This could be called via ext4_write_begin() -- * -- * We need to consider the worse case, when -- * one new block per extent. -+ * Calculate the journal credits for modifying the number of blocks -+ * in a single extent within one transaction. 'nrblocks' is used only -+ * for non-extent inodes. For extent type inodes, 'nrblocks' can be -+ * zero if the exact number of blocks is unknown. - */ --int ext4_writepage_trans_blocks(struct inode *inode) -+int ext4_chunk_trans_extent(struct inode *inode, int nrblocks) - { -- int bpp = ext4_journal_blocks_per_folio(inode); - int ret; - -- ret = ext4_meta_trans_blocks(inode, bpp, bpp); -- -+ ret = ext4_meta_trans_blocks(inode, nrblocks, 1); - /* Account for data blocks for journalled mode */ - if (ext4_should_journal_data(inode)) -- ret += bpp; -+ ret += nrblocks; - return ret; - } - -@@ -6555,6 +6641,55 @@ static int ext4_bh_unmapped(handle_t *ha - return !buffer_mapped(bh); - } - -+static int ext4_block_page_mkwrite(struct inode *inode, struct folio *folio, -+ get_block_t get_block) -+{ -+ handle_t *handle; -+ loff_t size; -+ unsigned long len; -+ int credits; -+ int ret; -+ -+ credits = ext4_chunk_trans_extent(inode, -+ ext4_journal_blocks_per_folio(inode)); -+ handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, credits); -+ if (IS_ERR(handle)) -+ return PTR_ERR(handle); -+ -+ folio_lock(folio); -+ size = i_size_read(inode); -+ /* Page got truncated from under us? */ -+ if (folio->mapping != inode->i_mapping || folio_pos(folio) > size) { -+ ret = -EFAULT; -+ goto out_error; -+ } -+ -+ len = folio_size(folio); -+ if (folio_pos(folio) + len > size) -+ len = size - folio_pos(folio); -+ -+ ret = ext4_block_write_begin(handle, folio, 0, len, get_block); -+ if (ret) -+ goto out_error; -+ -+ if (!ext4_should_journal_data(inode)) { -+ block_commit_write(folio, 0, len); -+ folio_mark_dirty(folio); -+ } else { -+ ret = ext4_journal_folio_buffers(handle, folio, len); -+ if (ret) -+ goto out_error; -+ } -+ ext4_journal_stop(handle); -+ folio_wait_stable(folio); -+ return ret; -+ -+out_error: -+ folio_unlock(folio); -+ ext4_journal_stop(handle); -+ return ret; -+} -+ - vm_fault_t ext4_page_mkwrite(struct vm_fault *vmf) - { - struct vm_area_struct *vma = vmf->vma; -@@ -6566,8 +6701,7 @@ vm_fault_t ext4_page_mkwrite(struct vm_f - struct file *file = vma->vm_file; - struct inode *inode = file_inode(file); - struct address_space *mapping = inode->i_mapping; -- handle_t *handle; -- get_block_t *get_block; -+ get_block_t *get_block = ext4_get_block; - int retries = 0; - - if (unlikely(IS_IMMUTABLE(inode))) -@@ -6635,47 +6769,11 @@ vm_fault_t ext4_page_mkwrite(struct vm_f - /* OK, we need to fill the hole... */ - if (ext4_should_dioread_nolock(inode)) - get_block = ext4_get_block_unwritten; -- else -- get_block = ext4_get_block; - retry_alloc: -- handle = ext4_journal_start(inode, EXT4_HT_WRITE_PAGE, -- ext4_writepage_trans_blocks(inode)); -- if (IS_ERR(handle)) { -- ret = VM_FAULT_SIGBUS; -- goto out; -- } -- /* -- * Data journalling can't use block_page_mkwrite() because it -- * will set_buffer_dirty() before do_journal_get_write_access() -- * thus might hit warning messages for dirty metadata buffers. -- */ -- if (!ext4_should_journal_data(inode)) { -- err = block_page_mkwrite(vma, vmf, get_block); -- } else { -- folio_lock(folio); -- size = i_size_read(inode); -- /* Page got truncated from under us? */ -- if (folio->mapping != mapping || folio_pos(folio) > size) { -- ret = VM_FAULT_NOPAGE; -- goto out_error; -- } -- -- len = folio_size(folio); -- if (folio_pos(folio) + len > size) -- len = size - folio_pos(folio); -- -- err = ext4_block_write_begin(handle, folio, 0, len, -- ext4_get_block); -- if (!err) { -- ret = VM_FAULT_SIGBUS; -- if (ext4_journal_folio_buffers(handle, folio, len)) -- goto out_error; -- } else { -- folio_unlock(folio); -- } -- } -- ext4_journal_stop(handle); -- if (err == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) -+ /* Start journal and allocate blocks */ -+ err = ext4_block_page_mkwrite(inode, folio, get_block); -+ if (err == -EAGAIN || -+ (err == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))) - goto retry_alloc; - out_ret: - ret = vmf_fs_error(err); -@@ -6683,8 +6781,4 @@ out: - filemap_invalidate_unlock_shared(mapping); - sb_end_pagefault(inode->i_sb); - return ret; --out_error: -- folio_unlock(folio); -- ext4_journal_stop(handle); -- goto out; - } -diff -purNx .git BPI-Router-Linux-kernel/fs/ext4/mballoc.c BPI-Router-Linux-kernel-6.16.12/fs/ext4/mballoc.c ---- BPI-Router-Linux-kernel/fs/ext4/mballoc.c 2025-10-22 13:53:23.515327689 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ext4/mballoc.c 2025-10-22 13:53:56.715168177 -0400 -@@ -841,30 +841,30 @@ static void - mb_update_avg_fragment_size(struct super_block *sb, struct ext4_group_info *grp) - { - struct ext4_sb_info *sbi = EXT4_SB(sb); -- int new_order; -+ int new, old; - -- if (!test_opt2(sb, MB_OPTIMIZE_SCAN) || grp->bb_fragments == 0) -+ if (!test_opt2(sb, MB_OPTIMIZE_SCAN)) - return; - -- new_order = mb_avg_fragment_size_order(sb, -- grp->bb_free / grp->bb_fragments); -- if (new_order == grp->bb_avg_fragment_size_order) -+ old = grp->bb_avg_fragment_size_order; -+ new = grp->bb_fragments == 0 ? -1 : -+ mb_avg_fragment_size_order(sb, grp->bb_free / grp->bb_fragments); -+ if (new == old) - return; - -- if (grp->bb_avg_fragment_size_order != -1) { -- write_lock(&sbi->s_mb_avg_fragment_size_locks[ -- grp->bb_avg_fragment_size_order]); -+ if (old >= 0) { -+ write_lock(&sbi->s_mb_avg_fragment_size_locks[old]); - list_del(&grp->bb_avg_fragment_size_node); -- write_unlock(&sbi->s_mb_avg_fragment_size_locks[ -- grp->bb_avg_fragment_size_order]); -+ write_unlock(&sbi->s_mb_avg_fragment_size_locks[old]); -+ } -+ -+ grp->bb_avg_fragment_size_order = new; -+ if (new >= 0) { -+ write_lock(&sbi->s_mb_avg_fragment_size_locks[new]); -+ list_add_tail(&grp->bb_avg_fragment_size_node, -+ &sbi->s_mb_avg_fragment_size[new]); -+ write_unlock(&sbi->s_mb_avg_fragment_size_locks[new]); - } -- grp->bb_avg_fragment_size_order = new_order; -- write_lock(&sbi->s_mb_avg_fragment_size_locks[ -- grp->bb_avg_fragment_size_order]); -- list_add_tail(&grp->bb_avg_fragment_size_node, -- &sbi->s_mb_avg_fragment_size[grp->bb_avg_fragment_size_order]); -- write_unlock(&sbi->s_mb_avg_fragment_size_locks[ -- grp->bb_avg_fragment_size_order]); - } - - /* -@@ -1150,33 +1150,28 @@ static void - mb_set_largest_free_order(struct super_block *sb, struct ext4_group_info *grp) - { - struct ext4_sb_info *sbi = EXT4_SB(sb); -- int i; -+ int new, old = grp->bb_largest_free_order; - -- for (i = MB_NUM_ORDERS(sb) - 1; i >= 0; i--) -- if (grp->bb_counters[i] > 0) -+ for (new = MB_NUM_ORDERS(sb) - 1; new >= 0; new--) -+ if (grp->bb_counters[new] > 0) - break; -+ - /* No need to move between order lists? */ -- if (!test_opt2(sb, MB_OPTIMIZE_SCAN) || -- i == grp->bb_largest_free_order) { -- grp->bb_largest_free_order = i; -+ if (new == old) - return; -- } - -- if (grp->bb_largest_free_order >= 0) { -- write_lock(&sbi->s_mb_largest_free_orders_locks[ -- grp->bb_largest_free_order]); -+ if (old >= 0 && !list_empty(&grp->bb_largest_free_order_node)) { -+ write_lock(&sbi->s_mb_largest_free_orders_locks[old]); - list_del_init(&grp->bb_largest_free_order_node); -- write_unlock(&sbi->s_mb_largest_free_orders_locks[ -- grp->bb_largest_free_order]); -+ write_unlock(&sbi->s_mb_largest_free_orders_locks[old]); - } -- grp->bb_largest_free_order = i; -- if (grp->bb_largest_free_order >= 0 && grp->bb_free) { -- write_lock(&sbi->s_mb_largest_free_orders_locks[ -- grp->bb_largest_free_order]); -+ -+ grp->bb_largest_free_order = new; -+ if (test_opt2(sb, MB_OPTIMIZE_SCAN) && new >= 0 && grp->bb_free) { -+ write_lock(&sbi->s_mb_largest_free_orders_locks[new]); - list_add_tail(&grp->bb_largest_free_order_node, -- &sbi->s_mb_largest_free_orders[grp->bb_largest_free_order]); -- write_unlock(&sbi->s_mb_largest_free_orders_locks[ -- grp->bb_largest_free_order]); -+ &sbi->s_mb_largest_free_orders[new]); -+ write_unlock(&sbi->s_mb_largest_free_orders_locks[new]); - } - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/ext4/mballoc-test.c BPI-Router-Linux-kernel-6.16.12/fs/ext4/mballoc-test.c ---- BPI-Router-Linux-kernel/fs/ext4/mballoc-test.c 2025-10-22 13:53:23.515327689 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ext4/mballoc-test.c 2025-10-22 13:53:56.711168196 -0400 -@@ -155,6 +155,7 @@ static struct super_block *mbt_ext4_allo - bgl_lock_init(sbi->s_blockgroup_lock); - - sbi->s_es = &fsb->es; -+ sbi->s_sb = sb; - sb->s_fs_info = sbi; - - up_write(&sb->s_umount); -@@ -802,6 +803,10 @@ static void test_mb_mark_used(struct kun - KUNIT_ASSERT_EQ(test, ret, 0); - - grp->bb_free = EXT4_CLUSTERS_PER_GROUP(sb); -+ grp->bb_largest_free_order = -1; -+ grp->bb_avg_fragment_size_order = -1; -+ INIT_LIST_HEAD(&grp->bb_largest_free_order_node); -+ INIT_LIST_HEAD(&grp->bb_avg_fragment_size_node); - mbt_generate_test_ranges(sb, ranges, TEST_RANGE_COUNT); - for (i = 0; i < TEST_RANGE_COUNT; i++) - test_mb_mark_used_range(test, &e4b, ranges[i].start, -@@ -875,6 +880,10 @@ static void test_mb_free_blocks(struct k - ext4_unlock_group(sb, TEST_GOAL_GROUP); - - grp->bb_free = 0; -+ grp->bb_largest_free_order = -1; -+ grp->bb_avg_fragment_size_order = -1; -+ INIT_LIST_HEAD(&grp->bb_largest_free_order_node); -+ INIT_LIST_HEAD(&grp->bb_avg_fragment_size_node); - memset(bitmap, 0xff, sb->s_blocksize); - - mbt_generate_test_ranges(sb, ranges, TEST_RANGE_COUNT); -diff -purNx .git BPI-Router-Linux-kernel/fs/ext4/move_extent.c BPI-Router-Linux-kernel-6.16.12/fs/ext4/move_extent.c ---- BPI-Router-Linux-kernel/fs/ext4/move_extent.c 2025-10-22 13:53:23.515327689 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ext4/move_extent.c 2025-10-22 13:53:56.715168177 -0400 -@@ -280,7 +280,8 @@ move_extent_per_page(struct file *o_filp - */ - again: - *err = 0; -- jblocks = ext4_writepage_trans_blocks(orig_inode) * 2; -+ jblocks = ext4_meta_trans_blocks(orig_inode, block_len_in_page, -+ block_len_in_page) * 2; - handle = ext4_journal_start(orig_inode, EXT4_HT_MOVE_EXTENTS, jblocks); - if (IS_ERR(handle)) { - *err = PTR_ERR(handle); -diff -purNx .git BPI-Router-Linux-kernel/fs/ext4/orphan.c BPI-Router-Linux-kernel-6.16.12/fs/ext4/orphan.c ---- BPI-Router-Linux-kernel/fs/ext4/orphan.c 2025-10-22 13:53:23.515327689 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ext4/orphan.c 2025-10-22 13:53:56.715168177 -0400 -@@ -589,8 +589,9 @@ int ext4_init_orphan_info(struct super_b - } - oi->of_blocks = inode->i_size >> sb->s_blocksize_bits; - oi->of_csum_seed = EXT4_I(inode)->i_csum_seed; -- oi->of_binfo = kmalloc(oi->of_blocks*sizeof(struct ext4_orphan_block), -- GFP_KERNEL); -+ oi->of_binfo = kmalloc_array(oi->of_blocks, -+ sizeof(struct ext4_orphan_block), -+ GFP_KERNEL); - if (!oi->of_binfo) { - ret = -ENOMEM; - goto out_put; -diff -purNx .git BPI-Router-Linux-kernel/fs/ext4/page-io.c BPI-Router-Linux-kernel-6.16.12/fs/ext4/page-io.c ---- BPI-Router-Linux-kernel/fs/ext4/page-io.c 2025-10-22 13:53:23.519327670 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ext4/page-io.c 2025-10-22 13:53:56.715168177 -0400 -@@ -236,10 +236,12 @@ static void dump_completed_IO(struct ino - - static bool ext4_io_end_defer_completion(ext4_io_end_t *io_end) - { -- if (io_end->flag & EXT4_IO_END_UNWRITTEN) -+ if (io_end->flag & EXT4_IO_END_UNWRITTEN && -+ !list_empty(&io_end->list_vec)) - return true; - if (test_opt(io_end->inode->i_sb, DATA_ERR_ABORT) && -- io_end->flag & EXT4_IO_END_FAILED) -+ io_end->flag & EXT4_IO_END_FAILED && -+ !ext4_emergency_state(io_end->inode->i_sb)) - return true; - return false; - } -@@ -256,6 +258,7 @@ static void ext4_add_complete_io(ext4_io - WARN_ON(!(io_end->flag & EXT4_IO_END_DEFER_COMPLETION)); - WARN_ON(io_end->flag & EXT4_IO_END_UNWRITTEN && - !io_end->handle && sbi->s_journal); -+ WARN_ON(!io_end->bio); - - spin_lock_irqsave(&ei->i_completed_io_lock, flags); - wq = sbi->rsv_conversion_wq; -@@ -318,12 +321,9 @@ ext4_io_end_t *ext4_init_io_end(struct i - void ext4_put_io_end_defer(ext4_io_end_t *io_end) - { - if (refcount_dec_and_test(&io_end->count)) { -- if (io_end->flag & EXT4_IO_END_FAILED || -- (io_end->flag & EXT4_IO_END_UNWRITTEN && -- !list_empty(&io_end->list_vec))) { -- ext4_add_complete_io(io_end); -- return; -- } -+ if (ext4_io_end_defer_completion(io_end)) -+ return ext4_add_complete_io(io_end); -+ - ext4_release_io_end(io_end); - } - } -diff -purNx .git BPI-Router-Linux-kernel/fs/ext4/super.c BPI-Router-Linux-kernel-6.16.12/fs/ext4/super.c ---- BPI-Router-Linux-kernel/fs/ext4/super.c 2025-10-22 13:53:23.519327670 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ext4/super.c 2025-10-22 13:53:56.715168177 -0400 -@@ -1998,6 +1998,9 @@ int ext4_init_fs_context(struct fs_conte - fc->fs_private = ctx; - fc->ops = &ext4_context_ops; - -+ /* i_version is always enabled now */ -+ fc->sb_flags |= SB_I_VERSION; -+ - return 0; - } - -@@ -5314,9 +5317,6 @@ static int __ext4_fill_super(struct fs_c - sb->s_flags = (sb->s_flags & ~SB_POSIXACL) | - (test_opt(sb, POSIX_ACL) ? SB_POSIXACL : 0); - -- /* i_version is always enabled now */ -- sb->s_flags |= SB_I_VERSION; -- - /* HSM events are allowed by default. */ - sb->s_iflags |= SB_I_ALLOW_HSM; - -@@ -5414,6 +5414,8 @@ static int __ext4_fill_super(struct fs_c - err = ext4_load_and_init_journal(sb, es, ctx); - if (err) - goto failed_mount3a; -+ if (bdev_read_only(sb->s_bdev)) -+ needs_recovery = 0; - } else if (test_opt(sb, NOLOAD) && !sb_rdonly(sb) && - ext4_has_feature_journal_needs_recovery(sb)) { - ext4_msg(sb, KERN_ERR, "required journal recovery " -diff -purNx .git BPI-Router-Linux-kernel/fs/ext4/xattr.c BPI-Router-Linux-kernel-6.16.12/fs/ext4/xattr.c ---- BPI-Router-Linux-kernel/fs/ext4/xattr.c 2025-10-22 13:53:23.519327670 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ext4/xattr.c 2025-10-22 13:53:56.715168177 -0400 -@@ -962,7 +962,7 @@ int __ext4_xattr_set_credits(struct supe - * so we need to reserve credits for this eventuality - */ - if (inode && ext4_has_inline_data(inode)) -- credits += ext4_writepage_trans_blocks(inode) + 1; -+ credits += ext4_chunk_trans_extent(inode, 1) + 1; - - /* We are done if ea_inode feature is not enabled. */ - if (!ext4_has_feature_ea_inode(sb)) -diff -purNx .git BPI-Router-Linux-kernel/fs/f2fs/compress.c BPI-Router-Linux-kernel-6.16.12/fs/f2fs/compress.c ---- BPI-Router-Linux-kernel/fs/f2fs/compress.c 2025-10-22 13:53:23.519327670 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/f2fs/compress.c 2025-10-22 13:53:56.715168177 -0400 -@@ -23,20 +23,18 @@ - static struct kmem_cache *cic_entry_slab; - static struct kmem_cache *dic_entry_slab; - --static void *page_array_alloc(struct inode *inode, int nr) -+static void *page_array_alloc(struct f2fs_sb_info *sbi, int nr) - { -- struct f2fs_sb_info *sbi = F2FS_I_SB(inode); - unsigned int size = sizeof(struct page *) * nr; - - if (likely(size <= sbi->page_array_slab_size)) - return f2fs_kmem_cache_alloc(sbi->page_array_slab, -- GFP_F2FS_ZERO, false, F2FS_I_SB(inode)); -+ GFP_F2FS_ZERO, false, sbi); - return f2fs_kzalloc(sbi, size, GFP_NOFS); - } - --static void page_array_free(struct inode *inode, void *pages, int nr) -+static void page_array_free(struct f2fs_sb_info *sbi, void *pages, int nr) - { -- struct f2fs_sb_info *sbi = F2FS_I_SB(inode); - unsigned int size = sizeof(struct page *) * nr; - - if (!pages) -@@ -149,13 +147,13 @@ int f2fs_init_compress_ctx(struct compre - if (cc->rpages) - return 0; - -- cc->rpages = page_array_alloc(cc->inode, cc->cluster_size); -+ cc->rpages = page_array_alloc(F2FS_I_SB(cc->inode), cc->cluster_size); - return cc->rpages ? 0 : -ENOMEM; - } - - void f2fs_destroy_compress_ctx(struct compress_ctx *cc, bool reuse) - { -- page_array_free(cc->inode, cc->rpages, cc->cluster_size); -+ page_array_free(F2FS_I_SB(cc->inode), cc->rpages, cc->cluster_size); - cc->rpages = NULL; - cc->nr_rpages = 0; - cc->nr_cpages = 0; -@@ -216,13 +214,13 @@ static int lzo_decompress_pages(struct d - ret = lzo1x_decompress_safe(dic->cbuf->cdata, dic->clen, - dic->rbuf, &dic->rlen); - if (ret != LZO_E_OK) { -- f2fs_err_ratelimited(F2FS_I_SB(dic->inode), -+ f2fs_err_ratelimited(dic->sbi, - "lzo decompress failed, ret:%d", ret); - return -EIO; - } - - if (dic->rlen != PAGE_SIZE << dic->log_cluster_size) { -- f2fs_err_ratelimited(F2FS_I_SB(dic->inode), -+ f2fs_err_ratelimited(dic->sbi, - "lzo invalid rlen:%zu, expected:%lu", - dic->rlen, PAGE_SIZE << dic->log_cluster_size); - return -EIO; -@@ -296,13 +294,13 @@ static int lz4_decompress_pages(struct d - ret = LZ4_decompress_safe(dic->cbuf->cdata, dic->rbuf, - dic->clen, dic->rlen); - if (ret < 0) { -- f2fs_err_ratelimited(F2FS_I_SB(dic->inode), -+ f2fs_err_ratelimited(dic->sbi, - "lz4 decompress failed, ret:%d", ret); - return -EIO; - } - - if (ret != PAGE_SIZE << dic->log_cluster_size) { -- f2fs_err_ratelimited(F2FS_I_SB(dic->inode), -+ f2fs_err_ratelimited(dic->sbi, - "lz4 invalid ret:%d, expected:%lu", - ret, PAGE_SIZE << dic->log_cluster_size); - return -EIO; -@@ -424,13 +422,13 @@ static int zstd_init_decompress_ctx(stru - - workspace_size = zstd_dstream_workspace_bound(max_window_size); - -- workspace = f2fs_vmalloc(F2FS_I_SB(dic->inode), workspace_size); -+ workspace = f2fs_vmalloc(dic->sbi, workspace_size); - if (!workspace) - return -ENOMEM; - - stream = zstd_init_dstream(max_window_size, workspace, workspace_size); - if (!stream) { -- f2fs_err_ratelimited(F2FS_I_SB(dic->inode), -+ f2fs_err_ratelimited(dic->sbi, - "%s zstd_init_dstream failed", __func__); - vfree(workspace); - return -EIO; -@@ -466,14 +464,14 @@ static int zstd_decompress_pages(struct - - ret = zstd_decompress_stream(stream, &outbuf, &inbuf); - if (zstd_is_error(ret)) { -- f2fs_err_ratelimited(F2FS_I_SB(dic->inode), -+ f2fs_err_ratelimited(dic->sbi, - "%s zstd_decompress_stream failed, ret: %d", - __func__, zstd_get_error_code(ret)); - return -EIO; - } - - if (dic->rlen != outbuf.pos) { -- f2fs_err_ratelimited(F2FS_I_SB(dic->inode), -+ f2fs_err_ratelimited(dic->sbi, - "%s ZSTD invalid rlen:%zu, expected:%lu", - __func__, dic->rlen, - PAGE_SIZE << dic->log_cluster_size); -@@ -622,6 +620,7 @@ static void *f2fs_vmap(struct page **pag - - static int f2fs_compress_pages(struct compress_ctx *cc) - { -+ struct f2fs_sb_info *sbi = F2FS_I_SB(cc->inode); - struct f2fs_inode_info *fi = F2FS_I(cc->inode); - const struct f2fs_compress_ops *cops = - f2fs_cops[fi->i_compress_algorithm]; -@@ -642,7 +641,7 @@ static int f2fs_compress_pages(struct co - cc->nr_cpages = DIV_ROUND_UP(max_len, PAGE_SIZE); - cc->valid_nr_cpages = cc->nr_cpages; - -- cc->cpages = page_array_alloc(cc->inode, cc->nr_cpages); -+ cc->cpages = page_array_alloc(sbi, cc->nr_cpages); - if (!cc->cpages) { - ret = -ENOMEM; - goto destroy_compress_ctx; -@@ -716,7 +715,7 @@ out_free_cpages: - if (cc->cpages[i]) - f2fs_compress_free_page(cc->cpages[i]); - } -- page_array_free(cc->inode, cc->cpages, cc->nr_cpages); -+ page_array_free(sbi, cc->cpages, cc->nr_cpages); - cc->cpages = NULL; - destroy_compress_ctx: - if (cops->destroy_compress_ctx) -@@ -734,7 +733,7 @@ static void f2fs_release_decomp_mem(stru - - void f2fs_decompress_cluster(struct decompress_io_ctx *dic, bool in_task) - { -- struct f2fs_sb_info *sbi = F2FS_I_SB(dic->inode); -+ struct f2fs_sb_info *sbi = dic->sbi; - struct f2fs_inode_info *fi = F2FS_I(dic->inode); - const struct f2fs_compress_ops *cops = - f2fs_cops[fi->i_compress_algorithm]; -@@ -807,7 +806,7 @@ void f2fs_end_read_compressed_page(struc - { - struct decompress_io_ctx *dic = - (struct decompress_io_ctx *)page_private(page); -- struct f2fs_sb_info *sbi = F2FS_I_SB(dic->inode); -+ struct f2fs_sb_info *sbi = dic->sbi; - - dec_page_count(sbi, F2FS_RD_DATA); - -@@ -1340,7 +1339,7 @@ static int f2fs_write_compressed_pages(s - cic->magic = F2FS_COMPRESSED_PAGE_MAGIC; - cic->inode = inode; - atomic_set(&cic->pending_pages, cc->valid_nr_cpages); -- cic->rpages = page_array_alloc(cc->inode, cc->cluster_size); -+ cic->rpages = page_array_alloc(sbi, cc->cluster_size); - if (!cic->rpages) - goto out_put_cic; - -@@ -1442,13 +1441,13 @@ unlock_continue: - spin_unlock(&fi->i_size_lock); - - f2fs_put_rpages(cc); -- page_array_free(cc->inode, cc->cpages, cc->nr_cpages); -+ page_array_free(sbi, cc->cpages, cc->nr_cpages); - cc->cpages = NULL; - f2fs_destroy_compress_ctx(cc, false); - return 0; - - out_destroy_crypt: -- page_array_free(cc->inode, cic->rpages, cc->cluster_size); -+ page_array_free(sbi, cic->rpages, cc->cluster_size); - - for (--i; i >= 0; i--) { - if (!cc->cpages[i]) -@@ -1469,7 +1468,7 @@ out_free: - f2fs_compress_free_page(cc->cpages[i]); - cc->cpages[i] = NULL; - } -- page_array_free(cc->inode, cc->cpages, cc->nr_cpages); -+ page_array_free(sbi, cc->cpages, cc->nr_cpages); - cc->cpages = NULL; - return -EAGAIN; - } -@@ -1499,7 +1498,7 @@ void f2fs_compress_write_end_io(struct b - end_page_writeback(cic->rpages[i]); - } - -- page_array_free(cic->inode, cic->rpages, cic->nr_rpages); -+ page_array_free(sbi, cic->rpages, cic->nr_rpages); - kmem_cache_free(cic_entry_slab, cic); - } - -@@ -1633,14 +1632,13 @@ static inline bool allow_memalloc_for_de - static int f2fs_prepare_decomp_mem(struct decompress_io_ctx *dic, - bool pre_alloc) - { -- const struct f2fs_compress_ops *cops = -- f2fs_cops[F2FS_I(dic->inode)->i_compress_algorithm]; -+ const struct f2fs_compress_ops *cops = f2fs_cops[dic->compress_algorithm]; - int i; - -- if (!allow_memalloc_for_decomp(F2FS_I_SB(dic->inode), pre_alloc)) -+ if (!allow_memalloc_for_decomp(dic->sbi, pre_alloc)) - return 0; - -- dic->tpages = page_array_alloc(dic->inode, dic->cluster_size); -+ dic->tpages = page_array_alloc(dic->sbi, dic->cluster_size); - if (!dic->tpages) - return -ENOMEM; - -@@ -1670,10 +1668,9 @@ static int f2fs_prepare_decomp_mem(struc - static void f2fs_release_decomp_mem(struct decompress_io_ctx *dic, - bool bypass_destroy_callback, bool pre_alloc) - { -- const struct f2fs_compress_ops *cops = -- f2fs_cops[F2FS_I(dic->inode)->i_compress_algorithm]; -+ const struct f2fs_compress_ops *cops = f2fs_cops[dic->compress_algorithm]; - -- if (!allow_memalloc_for_decomp(F2FS_I_SB(dic->inode), pre_alloc)) -+ if (!allow_memalloc_for_decomp(dic->sbi, pre_alloc)) - return; - - if (!bypass_destroy_callback && cops->destroy_decompress_ctx) -@@ -1700,7 +1697,7 @@ struct decompress_io_ctx *f2fs_alloc_dic - if (!dic) - return ERR_PTR(-ENOMEM); - -- dic->rpages = page_array_alloc(cc->inode, cc->cluster_size); -+ dic->rpages = page_array_alloc(sbi, cc->cluster_size); - if (!dic->rpages) { - kmem_cache_free(dic_entry_slab, dic); - return ERR_PTR(-ENOMEM); -@@ -1708,6 +1705,8 @@ struct decompress_io_ctx *f2fs_alloc_dic - - dic->magic = F2FS_COMPRESSED_PAGE_MAGIC; - dic->inode = cc->inode; -+ dic->sbi = sbi; -+ dic->compress_algorithm = F2FS_I(cc->inode)->i_compress_algorithm; - atomic_set(&dic->remaining_pages, cc->nr_cpages); - dic->cluster_idx = cc->cluster_idx; - dic->cluster_size = cc->cluster_size; -@@ -1721,7 +1720,7 @@ struct decompress_io_ctx *f2fs_alloc_dic - dic->rpages[i] = cc->rpages[i]; - dic->nr_rpages = cc->cluster_size; - -- dic->cpages = page_array_alloc(dic->inode, dic->nr_cpages); -+ dic->cpages = page_array_alloc(sbi, dic->nr_cpages); - if (!dic->cpages) { - ret = -ENOMEM; - goto out_free; -@@ -1751,6 +1750,8 @@ static void f2fs_free_dic(struct decompr - bool bypass_destroy_callback) - { - int i; -+ /* use sbi in dic to avoid UFA of dic->inode*/ -+ struct f2fs_sb_info *sbi = dic->sbi; - - f2fs_release_decomp_mem(dic, bypass_destroy_callback, true); - -@@ -1762,7 +1763,7 @@ static void f2fs_free_dic(struct decompr - continue; - f2fs_compress_free_page(dic->tpages[i]); - } -- page_array_free(dic->inode, dic->tpages, dic->cluster_size); -+ page_array_free(sbi, dic->tpages, dic->cluster_size); - } - - if (dic->cpages) { -@@ -1771,10 +1772,10 @@ static void f2fs_free_dic(struct decompr - continue; - f2fs_compress_free_page(dic->cpages[i]); - } -- page_array_free(dic->inode, dic->cpages, dic->nr_cpages); -+ page_array_free(sbi, dic->cpages, dic->nr_cpages); - } - -- page_array_free(dic->inode, dic->rpages, dic->nr_rpages); -+ page_array_free(sbi, dic->rpages, dic->nr_rpages); - kmem_cache_free(dic_entry_slab, dic); - } - -@@ -1793,8 +1794,7 @@ static void f2fs_put_dic(struct decompre - f2fs_free_dic(dic, false); - } else { - INIT_WORK(&dic->free_work, f2fs_late_free_dic); -- queue_work(F2FS_I_SB(dic->inode)->post_read_wq, -- &dic->free_work); -+ queue_work(dic->sbi->post_read_wq, &dic->free_work); - } - } - } -diff -purNx .git BPI-Router-Linux-kernel/fs/f2fs/data.c BPI-Router-Linux-kernel-6.16.12/fs/f2fs/data.c ---- BPI-Router-Linux-kernel/fs/f2fs/data.c 2025-10-22 13:53:23.519327670 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/f2fs/data.c 2025-10-22 13:53:56.715168177 -0400 -@@ -282,7 +282,7 @@ static void f2fs_read_end_io(struct bio - { - struct f2fs_sb_info *sbi = F2FS_P_SB(bio_first_page_all(bio)); - struct bio_post_read_ctx *ctx; -- bool intask = in_task(); -+ bool intask = in_task() && !irqs_disabled(); - - iostat_update_and_unbind_ctx(bio); - ctx = bio->bi_private; -@@ -1572,8 +1572,11 @@ int f2fs_map_blocks(struct inode *inode, - end = pgofs + maxblocks; - - next_dnode: -- if (map->m_may_create) -+ if (map->m_may_create) { -+ if (f2fs_lfs_mode(sbi)) -+ f2fs_balance_fs(sbi, true); - f2fs_map_lock(sbi, flag); -+ } - - /* When reading holes, we need its node page */ - set_new_dnode(&dn, inode, NULL, NULL, 0); -diff -purNx .git BPI-Router-Linux-kernel/fs/f2fs/debug.c BPI-Router-Linux-kernel-6.16.12/fs/f2fs/debug.c ---- BPI-Router-Linux-kernel/fs/f2fs/debug.c 2025-10-22 13:53:23.519327670 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/f2fs/debug.c 2025-10-22 13:53:56.715168177 -0400 -@@ -21,7 +21,7 @@ - #include "gc.h" - - static LIST_HEAD(f2fs_stat_list); --static DEFINE_RAW_SPINLOCK(f2fs_stat_lock); -+static DEFINE_SPINLOCK(f2fs_stat_lock); - #ifdef CONFIG_DEBUG_FS - static struct dentry *f2fs_debugfs_root; - #endif -@@ -439,9 +439,8 @@ static int stat_show(struct seq_file *s, - { - struct f2fs_stat_info *si; - int i = 0, j = 0; -- unsigned long flags; - -- raw_spin_lock_irqsave(&f2fs_stat_lock, flags); -+ spin_lock(&f2fs_stat_lock); - list_for_each_entry(si, &f2fs_stat_list, stat_list) { - struct f2fs_sb_info *sbi = si->sbi; - -@@ -753,7 +752,7 @@ static int stat_show(struct seq_file *s, - seq_printf(s, " - paged : %llu KB\n", - si->page_mem >> 10); - } -- raw_spin_unlock_irqrestore(&f2fs_stat_lock, flags); -+ spin_unlock(&f2fs_stat_lock); - return 0; - } - -@@ -765,7 +764,6 @@ int f2fs_build_stats(struct f2fs_sb_info - struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); - struct f2fs_stat_info *si; - struct f2fs_dev_stats *dev_stats; -- unsigned long flags; - int i; - - si = f2fs_kzalloc(sbi, sizeof(struct f2fs_stat_info), GFP_KERNEL); -@@ -817,9 +815,9 @@ int f2fs_build_stats(struct f2fs_sb_info - - atomic_set(&sbi->max_aw_cnt, 0); - -- raw_spin_lock_irqsave(&f2fs_stat_lock, flags); -+ spin_lock(&f2fs_stat_lock); - list_add_tail(&si->stat_list, &f2fs_stat_list); -- raw_spin_unlock_irqrestore(&f2fs_stat_lock, flags); -+ spin_unlock(&f2fs_stat_lock); - - return 0; - } -@@ -827,11 +825,10 @@ int f2fs_build_stats(struct f2fs_sb_info - void f2fs_destroy_stats(struct f2fs_sb_info *sbi) - { - struct f2fs_stat_info *si = F2FS_STAT(sbi); -- unsigned long flags; - -- raw_spin_lock_irqsave(&f2fs_stat_lock, flags); -+ spin_lock(&f2fs_stat_lock); - list_del(&si->stat_list); -- raw_spin_unlock_irqrestore(&f2fs_stat_lock, flags); -+ spin_unlock(&f2fs_stat_lock); - - kfree(si->dev_stats); - kfree(si); -diff -purNx .git BPI-Router-Linux-kernel/fs/f2fs/extent_cache.c BPI-Router-Linux-kernel-6.16.12/fs/f2fs/extent_cache.c ---- BPI-Router-Linux-kernel/fs/f2fs/extent_cache.c 2025-10-22 13:53:23.519327670 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/f2fs/extent_cache.c 2025-10-22 13:53:56.715168177 -0400 -@@ -414,7 +414,7 @@ void f2fs_init_read_extent_tree(struct i - struct f2fs_extent *i_ext = &F2FS_INODE(&ifolio->page)->i_ext; - struct extent_tree *et; - struct extent_node *en; -- struct extent_info ei; -+ struct extent_info ei = {0}; - - if (!__may_extent_tree(inode, EX_READ)) { - /* drop largest read extent */ -diff -purNx .git BPI-Router-Linux-kernel/fs/f2fs/f2fs.h BPI-Router-Linux-kernel-6.16.12/fs/f2fs/f2fs.h ---- BPI-Router-Linux-kernel/fs/f2fs/f2fs.h 2025-10-22 13:53:23.519327670 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/f2fs/f2fs.h 2025-10-22 13:53:56.715168177 -0400 -@@ -1286,7 +1286,7 @@ struct f2fs_bio_info { - struct f2fs_dev_info { - struct file *bdev_file; - struct block_device *bdev; -- char path[MAX_PATH_LEN]; -+ char path[MAX_PATH_LEN + 1]; - unsigned int total_segments; - block_t start_blk; - block_t end_blk; -@@ -1536,6 +1536,7 @@ struct compress_io_ctx { - struct decompress_io_ctx { - u32 magic; /* magic number to indicate page is compressed */ - struct inode *inode; /* inode the context belong to */ -+ struct f2fs_sb_info *sbi; /* f2fs_sb_info pointer */ - pgoff_t cluster_idx; /* cluster index number */ - unsigned int cluster_size; /* page count in cluster */ - unsigned int log_cluster_size; /* log of cluster size */ -@@ -1576,6 +1577,7 @@ struct decompress_io_ctx { - - bool failed; /* IO error occurred before decompression? */ - bool need_verity; /* need fs-verity verification after decompression? */ -+ unsigned char compress_algorithm; /* backup algorithm type */ - void *private; /* payload buffer for specified decompression algorithm */ - void *private2; /* extra payload buffer */ - struct work_struct verity_work; /* work to verify the decompressed pages */ -diff -purNx .git BPI-Router-Linux-kernel/fs/f2fs/file.c BPI-Router-Linux-kernel-6.16.12/fs/f2fs/file.c ---- BPI-Router-Linux-kernel/fs/f2fs/file.c 2025-10-22 13:53:23.519327670 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/f2fs/file.c 2025-10-22 13:53:56.715168177 -0400 -@@ -35,6 +35,17 @@ - #include - #include - -+static void f2fs_zero_post_eof_page(struct inode *inode, loff_t new_size) -+{ -+ loff_t old_size = i_size_read(inode); -+ -+ if (old_size >= new_size) -+ return; -+ -+ /* zero or drop pages only in range of [old_size, new_size] */ -+ truncate_pagecache(inode, old_size); -+} -+ - static vm_fault_t f2fs_filemap_fault(struct vm_fault *vmf) - { - struct inode *inode = file_inode(vmf->vma->vm_file); -@@ -103,8 +114,13 @@ static vm_fault_t f2fs_vm_page_mkwrite(s - - f2fs_bug_on(sbi, f2fs_has_inline_data(inode)); - -+ filemap_invalidate_lock(inode->i_mapping); -+ f2fs_zero_post_eof_page(inode, (folio->index + 1) << PAGE_SHIFT); -+ filemap_invalidate_unlock(inode->i_mapping); -+ - file_update_time(vmf->vma->vm_file); - filemap_invalidate_lock_shared(inode->i_mapping); -+ - folio_lock(folio); - if (unlikely(folio->mapping != inode->i_mapping || - folio_pos(folio) > i_size_read(inode) || -@@ -1031,6 +1047,18 @@ int f2fs_setattr(struct mnt_idmap *idmap - if (unlikely(f2fs_cp_error(F2FS_I_SB(inode)))) - return -EIO; - -+ err = setattr_prepare(idmap, dentry, attr); -+ if (err) -+ return err; -+ -+ err = fscrypt_prepare_setattr(dentry, attr); -+ if (err) -+ return err; -+ -+ err = fsverity_prepare_setattr(dentry, attr); -+ if (err) -+ return err; -+ - if (unlikely(IS_IMMUTABLE(inode))) - return -EPERM; - -@@ -1049,18 +1077,6 @@ int f2fs_setattr(struct mnt_idmap *idmap - return -EINVAL; - } - -- err = setattr_prepare(idmap, dentry, attr); -- if (err) -- return err; -- -- err = fscrypt_prepare_setattr(dentry, attr); -- if (err) -- return err; -- -- err = fsverity_prepare_setattr(dentry, attr); -- if (err) -- return err; -- - if (is_quota_modification(idmap, inode, attr)) { - err = f2fs_dquot_initialize(inode); - if (err) -@@ -1109,6 +1125,8 @@ int f2fs_setattr(struct mnt_idmap *idmap - f2fs_down_write(&fi->i_gc_rwsem[WRITE]); - filemap_invalidate_lock(inode->i_mapping); - -+ if (attr->ia_size > old_size) -+ f2fs_zero_post_eof_page(inode, attr->ia_size); - truncate_setsize(inode, attr->ia_size); - - if (attr->ia_size <= old_size) -@@ -1227,6 +1245,10 @@ static int f2fs_punch_hole(struct inode - if (ret) - return ret; - -+ filemap_invalidate_lock(inode->i_mapping); -+ f2fs_zero_post_eof_page(inode, offset + len); -+ filemap_invalidate_unlock(inode->i_mapping); -+ - pg_start = ((unsigned long long) offset) >> PAGE_SHIFT; - pg_end = ((unsigned long long) offset + len) >> PAGE_SHIFT; - -@@ -1510,6 +1532,8 @@ static int f2fs_do_collapse(struct inode - f2fs_down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); - filemap_invalidate_lock(inode->i_mapping); - -+ f2fs_zero_post_eof_page(inode, offset + len); -+ - f2fs_lock_op(sbi); - f2fs_drop_extent_tree(inode); - truncate_pagecache(inode, offset); -@@ -1631,6 +1655,10 @@ static int f2fs_zero_range(struct inode - if (ret) - return ret; - -+ filemap_invalidate_lock(mapping); -+ f2fs_zero_post_eof_page(inode, offset + len); -+ filemap_invalidate_unlock(mapping); -+ - pg_start = ((unsigned long long) offset) >> PAGE_SHIFT; - pg_end = ((unsigned long long) offset + len) >> PAGE_SHIFT; - -@@ -1762,6 +1790,8 @@ static int f2fs_insert_range(struct inod - /* avoid gc operation during block exchange */ - f2fs_down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); - filemap_invalidate_lock(mapping); -+ -+ f2fs_zero_post_eof_page(inode, offset + len); - truncate_pagecache(inode, offset); - - while (!ret && idx > pg_start) { -@@ -1819,6 +1849,10 @@ static int f2fs_expand_inode_data(struct - if (err) - return err; - -+ filemap_invalidate_lock(inode->i_mapping); -+ f2fs_zero_post_eof_page(inode, offset + len); -+ filemap_invalidate_unlock(inode->i_mapping); -+ - f2fs_balance_fs(sbi, true); - - pg_start = ((unsigned long long)offset) >> PAGE_SHIFT; -@@ -4860,6 +4894,10 @@ static ssize_t f2fs_write_checks(struct - err = file_modified(file); - if (err) - return err; -+ -+ filemap_invalidate_lock(inode->i_mapping); -+ f2fs_zero_post_eof_page(inode, iocb->ki_pos + iov_iter_count(from)); -+ filemap_invalidate_unlock(inode->i_mapping); - return count; - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/f2fs/gc.c BPI-Router-Linux-kernel-6.16.12/fs/f2fs/gc.c ---- BPI-Router-Linux-kernel/fs/f2fs/gc.c 2025-10-22 13:53:23.519327670 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/f2fs/gc.c 2025-10-22 13:53:56.715168177 -0400 -@@ -1891,6 +1891,7 @@ gc_more: - /* Let's run FG_GC, if we don't have enough space. */ - if (has_not_enough_free_secs(sbi, 0, 0)) { - gc_type = FG_GC; -+ gc_control->one_time = false; - - /* - * For example, if there are many prefree_segments below given -diff -purNx .git BPI-Router-Linux-kernel/fs/f2fs/inode.c BPI-Router-Linux-kernel-6.16.12/fs/f2fs/inode.c ---- BPI-Router-Linux-kernel/fs/f2fs/inode.c 2025-10-22 13:53:23.519327670 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/f2fs/inode.c 2025-10-22 13:53:56.715168177 -0400 -@@ -933,6 +933,19 @@ retry: - f2fs_update_inode_page(inode); - if (dquot_initialize_needed(inode)) - set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); -+ -+ /* -+ * If both f2fs_truncate() and f2fs_update_inode_page() failed -+ * due to fuzzed corrupted inode, call f2fs_inode_synced() to -+ * avoid triggering later f2fs_bug_on(). -+ */ -+ if (is_inode_flag_set(inode, FI_DIRTY_INODE)) { -+ f2fs_warn(sbi, -+ "f2fs_evict_inode: inode is dirty, ino:%lu", -+ inode->i_ino); -+ f2fs_inode_synced(inode); -+ set_sbi_flag(sbi, SBI_NEED_FSCK); -+ } - } - if (freeze_protected) - sb_end_intwrite(inode->i_sb); -@@ -949,8 +962,12 @@ no_delete: - if (likely(!f2fs_cp_error(sbi) && - !is_sbi_flag_set(sbi, SBI_CP_DISABLED))) - f2fs_bug_on(sbi, is_inode_flag_set(inode, FI_DIRTY_INODE)); -- else -- f2fs_inode_synced(inode); -+ -+ /* -+ * anyway, it needs to remove the inode from sbi->inode_list[DIRTY_META] -+ * list to avoid UAF in f2fs_sync_inode_meta() during checkpoint. -+ */ -+ f2fs_inode_synced(inode); - - /* for the case f2fs_new_inode() was failed, .i_ino is zero, skip it */ - if (inode->i_ino) -diff -purNx .git BPI-Router-Linux-kernel/fs/f2fs/node.c BPI-Router-Linux-kernel-6.16.12/fs/f2fs/node.c ---- BPI-Router-Linux-kernel/fs/f2fs/node.c 2025-10-22 13:53:23.519327670 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/f2fs/node.c 2025-10-22 13:53:56.715168177 -0400 -@@ -555,8 +555,8 @@ int f2fs_get_node_info(struct f2fs_sb_in - struct f2fs_nat_entry ne; - struct nat_entry *e; - pgoff_t index; -- block_t blkaddr; - int i; -+ bool need_cache = true; - - ni->flag = 0; - ni->nid = nid; -@@ -569,6 +569,10 @@ retry: - ni->blk_addr = nat_get_blkaddr(e); - ni->version = nat_get_version(e); - f2fs_up_read(&nm_i->nat_tree_lock); -+ if (IS_ENABLED(CONFIG_F2FS_CHECK_FS)) { -+ need_cache = false; -+ goto sanity_check; -+ } - return 0; - } - -@@ -594,7 +598,7 @@ retry: - up_read(&curseg->journal_rwsem); - if (i >= 0) { - f2fs_up_read(&nm_i->nat_tree_lock); -- goto cache; -+ goto sanity_check; - } - - /* Fill node_info from nat page */ -@@ -609,14 +613,23 @@ retry: - ne = nat_blk->entries[nid - start_nid]; - node_info_from_raw_nat(ni, &ne); - f2fs_folio_put(folio, true); --cache: -- blkaddr = le32_to_cpu(ne.block_addr); -- if (__is_valid_data_blkaddr(blkaddr) && -- !f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE)) -- return -EFAULT; -+sanity_check: -+ if (__is_valid_data_blkaddr(ni->blk_addr) && -+ !f2fs_is_valid_blkaddr(sbi, ni->blk_addr, -+ DATA_GENERIC_ENHANCE)) { -+ set_sbi_flag(sbi, SBI_NEED_FSCK); -+ f2fs_err_ratelimited(sbi, -+ "f2fs_get_node_info of %pS: inconsistent nat entry, " -+ "ino:%u, nid:%u, blkaddr:%u, ver:%u, flag:%u", -+ __builtin_return_address(0), -+ ni->ino, ni->nid, ni->blk_addr, ni->version, ni->flag); -+ f2fs_handle_error(sbi, ERROR_INCONSISTENT_NAT); -+ return -EFSCORRUPTED; -+ } - - /* cache nat entry */ -- cache_nat_entry(sbi, nid, &ne); -+ if (need_cache) -+ cache_nat_entry(sbi, nid, &ne); - return 0; - } - -@@ -803,6 +816,16 @@ int f2fs_get_dnode_of_data(struct dnode_ - for (i = 1; i <= level; i++) { - bool done = false; - -+ if (nids[i] && nids[i] == dn->inode->i_ino) { -+ err = -EFSCORRUPTED; -+ f2fs_err_ratelimited(sbi, -+ "inode mapping table is corrupted, run fsck to fix it, " -+ "ino:%lu, nid:%u, level:%d, offset:%d", -+ dn->inode->i_ino, nids[i], level, offset[level]); -+ set_sbi_flag(sbi, SBI_NEED_FSCK); -+ goto release_pages; -+ } -+ - if (!nids[i] && mode == ALLOC_NODE) { - /* alloc new node */ - if (!f2fs_alloc_nid(sbi, &(nids[i]))) { -@@ -2078,7 +2101,6 @@ write_node: - - if (!__write_node_folio(folio, false, &submitted, - wbc, do_balance, io_type, NULL)) { -- folio_unlock(folio); - folio_batch_release(&fbatch); - ret = -EIO; - goto out; -diff -purNx .git BPI-Router-Linux-kernel/fs/f2fs/segment.h BPI-Router-Linux-kernel-6.16.12/fs/f2fs/segment.h ---- BPI-Router-Linux-kernel/fs/f2fs/segment.h 2025-10-22 13:53:23.519327670 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/f2fs/segment.h 2025-10-22 13:53:56.715168177 -0400 -@@ -674,8 +674,7 @@ static inline void __get_secs_required(s - unsigned int dent_blocks = total_dent_blocks % CAP_BLKS_PER_SEC(sbi); - unsigned int data_blocks = 0; - -- if (f2fs_lfs_mode(sbi) && -- unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) { -+ if (f2fs_lfs_mode(sbi)) { - total_data_blocks = get_pages(sbi, F2FS_DIRTY_DATA); - data_secs = total_data_blocks / CAP_BLKS_PER_SEC(sbi); - data_blocks = total_data_blocks % CAP_BLKS_PER_SEC(sbi); -@@ -684,7 +683,7 @@ static inline void __get_secs_required(s - if (lower_p) - *lower_p = node_secs + dent_secs + data_secs; - if (upper_p) -- *upper_p = node_secs + dent_secs + -+ *upper_p = node_secs + dent_secs + data_secs + - (node_blocks ? 1 : 0) + (dent_blocks ? 1 : 0) + - (data_blocks ? 1 : 0); - if (curseg_p) -diff -purNx .git BPI-Router-Linux-kernel/fs/f2fs/super.c BPI-Router-Linux-kernel-6.16.12/fs/f2fs/super.c ---- BPI-Router-Linux-kernel/fs/f2fs/super.c 2025-10-22 13:53:23.519327670 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/f2fs/super.c 2025-10-22 13:53:56.715168177 -0400 -@@ -3451,6 +3451,7 @@ static int __f2fs_commit_super(struct f2 - f2fs_bug_on(sbi, 1); - - ret = submit_bio_wait(bio); -+ bio_put(bio); - folio_end_writeback(folio); - - return ret; -diff -purNx .git BPI-Router-Linux-kernel/fs/f2fs/sysfs.c BPI-Router-Linux-kernel-6.16.12/fs/f2fs/sysfs.c ---- BPI-Router-Linux-kernel/fs/f2fs/sysfs.c 2025-10-22 13:53:23.519327670 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/f2fs/sysfs.c 2025-10-22 13:53:56.719168157 -0400 -@@ -628,6 +628,27 @@ out: - return count; - } - -+ if (!strcmp(a->attr.name, "gc_no_zoned_gc_percent")) { -+ if (t > 100) -+ return -EINVAL; -+ *ui = (unsigned int)t; -+ return count; -+ } -+ -+ if (!strcmp(a->attr.name, "gc_boost_zoned_gc_percent")) { -+ if (t > 100) -+ return -EINVAL; -+ *ui = (unsigned int)t; -+ return count; -+ } -+ -+ if (!strcmp(a->attr.name, "gc_valid_thresh_ratio")) { -+ if (t > 100) -+ return -EINVAL; -+ *ui = (unsigned int)t; -+ return count; -+ } -+ - #ifdef CONFIG_F2FS_IOSTAT - if (!strcmp(a->attr.name, "iostat_enable")) { - sbi->iostat_enable = !!t; -diff -purNx .git BPI-Router-Linux-kernel/fs/fhandle.c BPI-Router-Linux-kernel-6.16.12/fs/fhandle.c ---- BPI-Router-Linux-kernel/fs/fhandle.c 2025-10-22 13:53:23.519327670 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/fhandle.c 2025-10-22 13:53:56.719168157 -0400 -@@ -88,7 +88,7 @@ static long do_sys_name_to_handle(const - if (fh_flags & EXPORT_FH_CONNECTABLE) { - handle->handle_type |= FILEID_IS_CONNECTABLE; - if (d_is_dir(path->dentry)) -- fh_flags |= FILEID_IS_DIR; -+ handle->handle_type |= FILEID_IS_DIR; - } - retval = 0; - } -@@ -203,6 +203,14 @@ static int vfs_dentry_acceptable(void *c - return 1; - - /* -+ * Verify that the decoded dentry itself has a valid id mapping. -+ * In case the decoded dentry is the mountfd root itself, this -+ * verifies that the mountfd inode itself has a valid id mapping. -+ */ -+ if (!privileged_wrt_inode_uidgid(user_ns, idmap, d_inode(dentry))) -+ return 0; -+ -+ /* - * It's racy as we're not taking rename_lock but we're able to ignore - * permissions and we just need an approximation whether we were able - * to follow a path to the file. -@@ -404,7 +412,7 @@ static long do_handle_open(int mountdirf - if (retval) - return retval; - -- CLASS(get_unused_fd, fd)(O_CLOEXEC); -+ CLASS(get_unused_fd, fd)(open_flag); - if (fd < 0) - return fd; - -diff -purNx .git BPI-Router-Linux-kernel/fs/file.c BPI-Router-Linux-kernel-6.16.12/fs/file.c ---- BPI-Router-Linux-kernel/fs/file.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/file.c 2025-10-22 13:53:56.719168157 -0400 -@@ -197,6 +197,21 @@ static struct fdtable *alloc_fdtable(uns - return ERR_PTR(-EMFILE); - } - -+ /* -+ * Check if the allocation size would exceed INT_MAX. kvmalloc_array() -+ * and kvmalloc() will warn if the allocation size is greater than -+ * INT_MAX, as filp_cachep objects are not __GFP_NOWARN. -+ * -+ * This can happen when sysctl_nr_open is set to a very high value and -+ * a process tries to use a file descriptor near that limit. For example, -+ * if sysctl_nr_open is set to 1073741816 (0x3ffffff8) - which is what -+ * systemd typically sets it to - then trying to use a file descriptor -+ * close to that value will require allocating a file descriptor table -+ * that exceeds 8GB in size. -+ */ -+ if (unlikely(nr > INT_MAX / sizeof(struct file *))) -+ return ERR_PTR(-EMFILE); -+ - fdt = kmalloc(sizeof(struct fdtable), GFP_KERNEL_ACCOUNT); - if (!fdt) - goto out; -@@ -1198,8 +1213,12 @@ bool file_seek_cur_needs_f_lock(struct f - if (!(file->f_mode & FMODE_ATOMIC_POS) && !file->f_op->iterate_shared) - return false; - -- VFS_WARN_ON_ONCE((file_count(file) > 1) && -- !mutex_is_locked(&file->f_pos_lock)); -+ /* -+ * Note that we are not guaranteed to be called after fdget_pos() on -+ * this file obj, in which case the caller is expected to provide the -+ * appropriate locking. -+ */ -+ - return true; - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/fs-writeback.c BPI-Router-Linux-kernel-6.16.12/fs/fs-writeback.c ---- BPI-Router-Linux-kernel/fs/fs-writeback.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/fs-writeback.c 2025-10-22 13:53:56.719168157 -0400 -@@ -2608,10 +2608,6 @@ void __mark_inode_dirty(struct inode *in - wakeup_bdi = inode_io_list_move_locked(inode, wb, - dirty_list); - -- spin_unlock(&wb->list_lock); -- spin_unlock(&inode->i_lock); -- trace_writeback_dirty_inode_enqueue(inode); -- - /* - * If this is the first dirty inode for this bdi, - * we have to wake-up the corresponding bdi thread -@@ -2621,6 +2617,11 @@ void __mark_inode_dirty(struct inode *in - if (wakeup_bdi && - (wb->bdi->capabilities & BDI_CAP_WRITEBACK)) - wb_wakeup_delayed(wb); -+ -+ spin_unlock(&wb->list_lock); -+ spin_unlock(&inode->i_lock); -+ trace_writeback_dirty_inode_enqueue(inode); -+ - return; - } - } -diff -purNx .git BPI-Router-Linux-kernel/fs/fuse/dev.c BPI-Router-Linux-kernel-6.16.12/fs/fuse/dev.c ---- BPI-Router-Linux-kernel/fs/fuse/dev.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/fuse/dev.c 2025-10-22 13:53:56.719168157 -0400 -@@ -1893,7 +1893,7 @@ static int fuse_retrieve(struct fuse_mou - - index = outarg->offset >> PAGE_SHIFT; - -- while (num) { -+ while (num && ap->num_folios < num_pages) { - struct folio *folio; - unsigned int folio_offset; - unsigned int nr_bytes; -diff -purNx .git BPI-Router-Linux-kernel/fs/fuse/file.c BPI-Router-Linux-kernel-6.16.12/fs/fuse/file.c ---- BPI-Router-Linux-kernel/fs/fuse/file.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/fuse/file.c 2025-10-22 13:53:56.719168157 -0400 -@@ -1147,7 +1147,7 @@ static ssize_t fuse_send_write_pages(str - static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia, - struct address_space *mapping, - struct iov_iter *ii, loff_t pos, -- unsigned int max_pages) -+ unsigned int max_folios) - { - struct fuse_args_pages *ap = &ia->ap; - struct fuse_conn *fc = get_fuse_conn(mapping->host); -@@ -1157,12 +1157,11 @@ static ssize_t fuse_fill_write_pages(str - int err = 0; - - num = min(iov_iter_count(ii), fc->max_write); -- num = min(num, max_pages << PAGE_SHIFT); - - ap->args.in_pages = true; - ap->descs[0].offset = offset; - -- while (num) { -+ while (num && ap->num_folios < max_folios) { - size_t tmp; - struct folio *folio; - pgoff_t index = pos >> PAGE_SHIFT; -@@ -3014,7 +3013,7 @@ static ssize_t __fuse_copy_file_range(st - .nodeid_out = ff_out->nodeid, - .fh_out = ff_out->fh, - .off_out = pos_out, -- .len = len, -+ .len = min_t(size_t, len, UINT_MAX & PAGE_MASK), - .flags = flags - }; - struct fuse_write_out outarg; -@@ -3080,6 +3079,9 @@ static ssize_t __fuse_copy_file_range(st - fc->no_copy_file_range = 1; - err = -EOPNOTSUPP; - } -+ if (!err && outarg.size > len) -+ err = -EIO; -+ - if (err) - goto out; - -diff -purNx .git BPI-Router-Linux-kernel/fs/fuse/inode.c BPI-Router-Linux-kernel-6.16.12/fs/fuse/inode.c ---- BPI-Router-Linux-kernel/fs/fuse/inode.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/fuse/inode.c 2025-10-22 13:53:56.719168157 -0400 -@@ -9,6 +9,7 @@ - #include "fuse_i.h" - #include "dev_uring_i.h" - -+#include - #include - #include - #include -@@ -162,6 +163,9 @@ static void fuse_evict_inode(struct inod - /* Will write inode on close/munmap and in all other dirtiers */ - WARN_ON(inode->i_state & I_DIRTY_INODE); - -+ if (FUSE_IS_DAX(inode)) -+ dax_break_layout_final(inode); -+ - truncate_inode_pages_final(&inode->i_data); - clear_inode(inode); - if (inode->i_sb->s_flags & SB_ACTIVE) { -diff -purNx .git BPI-Router-Linux-kernel/fs/fuse/passthrough.c BPI-Router-Linux-kernel-6.16.12/fs/fuse/passthrough.c ---- BPI-Router-Linux-kernel/fs/fuse/passthrough.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/fuse/passthrough.c 2025-10-22 13:53:56.719168157 -0400 -@@ -237,6 +237,11 @@ int fuse_backing_open(struct fuse_conn * - if (!file) - goto out; - -+ /* read/write/splice/mmap passthrough only relevant for regular files */ -+ res = d_is_dir(file->f_path.dentry) ? -EISDIR : -EINVAL; -+ if (!d_is_reg(file->f_path.dentry)) -+ goto out_fput; -+ - backing_sb = file_inode(file)->i_sb; - res = -ELOOP; - if (backing_sb->s_stack_depth >= fc->max_stack_depth) -diff -purNx .git BPI-Router-Linux-kernel/fs/gfs2/dir.c BPI-Router-Linux-kernel-6.16.12/fs/gfs2/dir.c ---- BPI-Router-Linux-kernel/fs/gfs2/dir.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/gfs2/dir.c 2025-10-22 13:53:56.719168157 -0400 -@@ -60,6 +60,7 @@ - #include - #include - #include -+#include - - #include "gfs2.h" - #include "incore.h" -@@ -912,7 +913,6 @@ static int dir_make_exhash(struct inode - struct qstr args; - struct buffer_head *bh, *dibh; - struct gfs2_leaf *leaf; -- int y; - u32 x; - __be64 *lp; - u64 bn; -@@ -979,9 +979,7 @@ static int dir_make_exhash(struct inode - i_size_write(inode, sdp->sd_sb.sb_bsize / 2); - gfs2_add_inode_blocks(&dip->i_inode, 1); - dip->i_diskflags |= GFS2_DIF_EXHASH; -- -- for (x = sdp->sd_hash_ptrs, y = -1; x; x >>= 1, y++) ; -- dip->i_depth = y; -+ dip->i_depth = ilog2(sdp->sd_hash_ptrs); - - gfs2_dinode_out(dip, dibh->b_data); - -diff -purNx .git BPI-Router-Linux-kernel/fs/gfs2/glock.c BPI-Router-Linux-kernel-6.16.12/fs/gfs2/glock.c ---- BPI-Router-Linux-kernel/fs/gfs2/glock.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/gfs2/glock.c 2025-10-22 13:53:56.719168157 -0400 -@@ -802,7 +802,8 @@ skip_inval: - * We skip telling dlm to do the locking, so we won't get a - * reply that would otherwise clear GLF_LOCK. So we clear it here. - */ -- clear_bit(GLF_LOCK, &gl->gl_flags); -+ if (!test_bit(GLF_CANCELING, &gl->gl_flags)) -+ clear_bit(GLF_LOCK, &gl->gl_flags); - clear_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags); - gfs2_glock_queue_work(gl, GL_GLOCK_DFT_HOLD); - return; -diff -purNx .git BPI-Router-Linux-kernel/fs/gfs2/glops.c BPI-Router-Linux-kernel-6.16.12/fs/gfs2/glops.c ---- BPI-Router-Linux-kernel/fs/gfs2/glops.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/gfs2/glops.c 2025-10-22 13:53:56.719168157 -0400 -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - - #include "gfs2.h" - #include "incore.h" -@@ -450,6 +451,11 @@ static int gfs2_dinode_in(struct gfs2_in - gfs2_consist_inode(ip); - return -EIO; - } -+ if ((ip->i_diskflags & GFS2_DIF_EXHASH) && -+ depth < ilog2(sdp->sd_hash_ptrs)) { -+ gfs2_consist_inode(ip); -+ return -EIO; -+ } - ip->i_depth = (u8)depth; - ip->i_entries = be32_to_cpu(str->di_entries); - -diff -purNx .git BPI-Router-Linux-kernel/fs/gfs2/meta_io.c BPI-Router-Linux-kernel-6.16.12/fs/gfs2/meta_io.c ---- BPI-Router-Linux-kernel/fs/gfs2/meta_io.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/gfs2/meta_io.c 2025-10-22 13:53:56.719168157 -0400 -@@ -103,6 +103,7 @@ const struct address_space_operations gf - .invalidate_folio = block_invalidate_folio, - .writepages = gfs2_aspace_writepages, - .release_folio = gfs2_release_folio, -+ .migrate_folio = buffer_migrate_folio_norefs, - }; - - const struct address_space_operations gfs2_rgrp_aops = { -@@ -110,6 +111,7 @@ const struct address_space_operations gf - .invalidate_folio = block_invalidate_folio, - .writepages = gfs2_aspace_writepages, - .release_folio = gfs2_release_folio, -+ .migrate_folio = buffer_migrate_folio_norefs, - }; - - /** -diff -purNx .git BPI-Router-Linux-kernel/fs/gfs2/util.c BPI-Router-Linux-kernel-6.16.12/fs/gfs2/util.c ---- BPI-Router-Linux-kernel/fs/gfs2/util.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/gfs2/util.c 2025-10-22 13:53:56.719168157 -0400 -@@ -232,32 +232,23 @@ static void signal_our_withdraw(struct g - */ - ret = gfs2_glock_nq(&sdp->sd_live_gh); - -+ gfs2_glock_put(live_gl); /* drop extra reference we acquired */ -+ clear_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags); -+ - /* - * If we actually got the "live" lock in EX mode, there are no other -- * nodes available to replay our journal. So we try to replay it -- * ourselves. We hold the "live" glock to prevent other mounters -- * during recovery, then just dequeue it and reacquire it in our -- * normal SH mode. Just in case the problem that caused us to -- * withdraw prevents us from recovering our journal (e.g. io errors -- * and such) we still check if the journal is clean before proceeding -- * but we may wait forever until another mounter does the recovery. -+ * nodes available to replay our journal. - */ - if (ret == 0) { -- fs_warn(sdp, "No other mounters found. Trying to recover our " -- "own journal jid %d.\n", sdp->sd_lockstruct.ls_jid); -- if (gfs2_recover_journal(sdp->sd_jdesc, 1)) -- fs_warn(sdp, "Unable to recover our journal jid %d.\n", -- sdp->sd_lockstruct.ls_jid); -- gfs2_glock_dq_wait(&sdp->sd_live_gh); -- gfs2_holder_reinit(LM_ST_SHARED, -- LM_FLAG_NOEXP | GL_EXACT | GL_NOPID, -- &sdp->sd_live_gh); -- gfs2_glock_nq(&sdp->sd_live_gh); -+ fs_warn(sdp, "No other mounters found.\n"); -+ /* -+ * We are about to release the lockspace. By keeping live_gl -+ * locked here, we ensure that the next mounter coming along -+ * will be a "first" mounter which will perform recovery. -+ */ -+ goto skip_recovery; - } - -- gfs2_glock_put(live_gl); /* drop extra reference we acquired */ -- clear_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags); -- - /* - * At this point our journal is evicted, so we need to get a new inode - * for it. Once done, we need to call gfs2_find_jhead which -diff -purNx .git BPI-Router-Linux-kernel/fs/hfs/bfind.c BPI-Router-Linux-kernel-6.16.12/fs/hfs/bfind.c ---- BPI-Router-Linux-kernel/fs/hfs/bfind.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/hfs/bfind.c 2025-10-22 13:53:56.719168157 -0400 -@@ -16,6 +16,9 @@ int hfs_find_init(struct hfs_btree *tree - { - void *ptr; - -+ if (!tree || !fd) -+ return -EINVAL; -+ - fd->tree = tree; - fd->bnode = NULL; - ptr = kmalloc(tree->max_key_len * 2 + 4, GFP_KERNEL); -diff -purNx .git BPI-Router-Linux-kernel/fs/hfs/bnode.c BPI-Router-Linux-kernel-6.16.12/fs/hfs/bnode.c ---- BPI-Router-Linux-kernel/fs/hfs/bnode.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/hfs/bnode.c 2025-10-22 13:53:56.719168157 -0400 -@@ -15,6 +15,48 @@ - - #include "btree.h" - -+static inline -+bool is_bnode_offset_valid(struct hfs_bnode *node, int off) -+{ -+ bool is_valid = off < node->tree->node_size; -+ -+ if (!is_valid) { -+ pr_err("requested invalid offset: " -+ "NODE: id %u, type %#x, height %u, " -+ "node_size %u, offset %d\n", -+ node->this, node->type, node->height, -+ node->tree->node_size, off); -+ } -+ -+ return is_valid; -+} -+ -+static inline -+int check_and_correct_requested_length(struct hfs_bnode *node, int off, int len) -+{ -+ unsigned int node_size; -+ -+ if (!is_bnode_offset_valid(node, off)) -+ return 0; -+ -+ node_size = node->tree->node_size; -+ -+ if ((off + len) > node_size) { -+ int new_len = (int)node_size - off; -+ -+ pr_err("requested length has been corrected: " -+ "NODE: id %u, type %#x, height %u, " -+ "node_size %u, offset %d, " -+ "requested_len %d, corrected_len %d\n", -+ node->this, node->type, node->height, -+ node->tree->node_size, off, len, new_len); -+ -+ return new_len; -+ } -+ -+ return len; -+} -+ - void hfs_bnode_read(struct hfs_bnode *node, void *buf, int off, int len) - { - struct page *page; -@@ -22,6 +64,20 @@ void hfs_bnode_read(struct hfs_bnode *no - int bytes_read; - int bytes_to_read; - -+ if (!is_bnode_offset_valid(node, off)) -+ return; -+ -+ if (len == 0) { -+ pr_err("requested zero length: " -+ "NODE: id %u, type %#x, height %u, " -+ "node_size %u, offset %d, len %d\n", -+ node->this, node->type, node->height, -+ node->tree->node_size, off, len); -+ return; -+ } -+ -+ len = check_and_correct_requested_length(node, off, len); -+ - off += node->page_offset; - pagenum = off >> PAGE_SHIFT; - off &= ~PAGE_MASK; /* compute page offset for the first page */ -@@ -80,6 +136,20 @@ void hfs_bnode_write(struct hfs_bnode *n - { - struct page *page; - -+ if (!is_bnode_offset_valid(node, off)) -+ return; -+ -+ if (len == 0) { -+ pr_err("requested zero length: " -+ "NODE: id %u, type %#x, height %u, " -+ "node_size %u, offset %d, len %d\n", -+ node->this, node->type, node->height, -+ node->tree->node_size, off, len); -+ return; -+ } -+ -+ len = check_and_correct_requested_length(node, off, len); -+ - off += node->page_offset; - page = node->page[0]; - -@@ -104,6 +174,20 @@ void hfs_bnode_clear(struct hfs_bnode *n - { - struct page *page; - -+ if (!is_bnode_offset_valid(node, off)) -+ return; -+ -+ if (len == 0) { -+ pr_err("requested zero length: " -+ "NODE: id %u, type %#x, height %u, " -+ "node_size %u, offset %d, len %d\n", -+ node->this, node->type, node->height, -+ node->tree->node_size, off, len); -+ return; -+ } -+ -+ len = check_and_correct_requested_length(node, off, len); -+ - off += node->page_offset; - page = node->page[0]; - -@@ -119,6 +203,10 @@ void hfs_bnode_copy(struct hfs_bnode *ds - hfs_dbg(BNODE_MOD, "copybytes: %u,%u,%u\n", dst, src, len); - if (!len) - return; -+ -+ len = check_and_correct_requested_length(src_node, src, len); -+ len = check_and_correct_requested_length(dst_node, dst, len); -+ - src += src_node->page_offset; - dst += dst_node->page_offset; - src_page = src_node->page[0]; -@@ -136,6 +224,10 @@ void hfs_bnode_move(struct hfs_bnode *no - hfs_dbg(BNODE_MOD, "movebytes: %u,%u,%u\n", dst, src, len); - if (!len) - return; -+ -+ len = check_and_correct_requested_length(node, src, len); -+ len = check_and_correct_requested_length(node, dst, len); -+ - src += node->page_offset; - dst += node->page_offset; - page = node->page[0]; -@@ -482,6 +574,7 @@ void hfs_bnode_put(struct hfs_bnode *nod - if (test_bit(HFS_BNODE_DELETED, &node->flags)) { - hfs_bnode_unhash(node); - spin_unlock(&tree->hash_lock); -+ hfs_bnode_clear(node, 0, tree->node_size); - hfs_bmap_free(node); - hfs_bnode_free(node); - return; -diff -purNx .git BPI-Router-Linux-kernel/fs/hfs/btree.c BPI-Router-Linux-kernel-6.16.12/fs/hfs/btree.c ---- BPI-Router-Linux-kernel/fs/hfs/btree.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/hfs/btree.c 2025-10-22 13:53:56.719168157 -0400 -@@ -21,8 +21,12 @@ struct hfs_btree *hfs_btree_open(struct - struct hfs_btree *tree; - struct hfs_btree_header_rec *head; - struct address_space *mapping; -- struct page *page; -+ struct folio *folio; -+ struct buffer_head *bh; - unsigned int size; -+ u16 dblock; -+ sector_t start_block; -+ loff_t offset; - - tree = kzalloc(sizeof(*tree), GFP_KERNEL); - if (!tree) -@@ -75,12 +79,40 @@ struct hfs_btree *hfs_btree_open(struct - unlock_new_inode(tree->inode); - - mapping = tree->inode->i_mapping; -- page = read_mapping_page(mapping, 0, NULL); -- if (IS_ERR(page)) -+ folio = filemap_grab_folio(mapping, 0); -+ if (IS_ERR(folio)) - goto free_inode; - -+ folio_zero_range(folio, 0, folio_size(folio)); -+ -+ dblock = hfs_ext_find_block(HFS_I(tree->inode)->first_extents, 0); -+ start_block = HFS_SB(sb)->fs_start + (dblock * HFS_SB(sb)->fs_div); -+ -+ size = folio_size(folio); -+ offset = 0; -+ while (size > 0) { -+ size_t len; -+ -+ bh = sb_bread(sb, start_block); -+ if (!bh) { -+ pr_err("unable to read tree header\n"); -+ goto put_folio; -+ } -+ -+ len = min_t(size_t, folio_size(folio), sb->s_blocksize); -+ memcpy_to_folio(folio, offset, bh->b_data, sb->s_blocksize); -+ -+ brelse(bh); -+ -+ start_block++; -+ offset += len; -+ size -= len; -+ } -+ -+ folio_mark_uptodate(folio); -+ - /* Load the header */ -- head = (struct hfs_btree_header_rec *)(kmap_local_page(page) + -+ head = (struct hfs_btree_header_rec *)(kmap_local_folio(folio, 0) + - sizeof(struct hfs_bnode_desc)); - tree->root = be32_to_cpu(head->root); - tree->leaf_count = be32_to_cpu(head->leaf_count); -@@ -95,22 +127,22 @@ struct hfs_btree *hfs_btree_open(struct - - size = tree->node_size; - if (!is_power_of_2(size)) -- goto fail_page; -+ goto fail_folio; - if (!tree->node_count) -- goto fail_page; -+ goto fail_folio; - switch (id) { - case HFS_EXT_CNID: - if (tree->max_key_len != HFS_MAX_EXT_KEYLEN) { - pr_err("invalid extent max_key_len %d\n", - tree->max_key_len); -- goto fail_page; -+ goto fail_folio; - } - break; - case HFS_CAT_CNID: - if (tree->max_key_len != HFS_MAX_CAT_KEYLEN) { - pr_err("invalid catalog max_key_len %d\n", - tree->max_key_len); -- goto fail_page; -+ goto fail_folio; - } - break; - default: -@@ -121,12 +153,15 @@ struct hfs_btree *hfs_btree_open(struct - tree->pages_per_bnode = (tree->node_size + PAGE_SIZE - 1) >> PAGE_SHIFT; - - kunmap_local(head); -- put_page(page); -+ folio_unlock(folio); -+ folio_put(folio); - return tree; - --fail_page: -+fail_folio: - kunmap_local(head); -- put_page(page); -+put_folio: -+ folio_unlock(folio); -+ folio_put(folio); - free_inode: - tree->inode->i_mapping->a_ops = &hfs_aops; - iput(tree->inode); -diff -purNx .git BPI-Router-Linux-kernel/fs/hfs/extent.c BPI-Router-Linux-kernel-6.16.12/fs/hfs/extent.c ---- BPI-Router-Linux-kernel/fs/hfs/extent.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/hfs/extent.c 2025-10-22 13:53:56.719168157 -0400 -@@ -71,7 +71,7 @@ int hfs_ext_keycmp(const btree_key *key1 - * - * Find a block within an extent record - */ --static u16 hfs_ext_find_block(struct hfs_extent *ext, u16 off) -+u16 hfs_ext_find_block(struct hfs_extent *ext, u16 off) - { - int i; - u16 count; -diff -purNx .git BPI-Router-Linux-kernel/fs/hfs/hfs_fs.h BPI-Router-Linux-kernel-6.16.12/fs/hfs/hfs_fs.h ---- BPI-Router-Linux-kernel/fs/hfs/hfs_fs.h 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/hfs/hfs_fs.h 2025-10-22 13:53:56.719168157 -0400 -@@ -190,6 +190,7 @@ extern const struct inode_operations hfs - - /* extent.c */ - extern int hfs_ext_keycmp(const btree_key *, const btree_key *); -+extern u16 hfs_ext_find_block(struct hfs_extent *ext, u16 off); - extern int hfs_free_fork(struct super_block *, struct hfs_cat_file *, int); - extern int hfs_ext_write_extent(struct inode *); - extern int hfs_extend_file(struct inode *); -diff -purNx .git BPI-Router-Linux-kernel/fs/hfs/inode.c BPI-Router-Linux-kernel-6.16.12/fs/hfs/inode.c ---- BPI-Router-Linux-kernel/fs/hfs/inode.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/hfs/inode.c 2025-10-22 13:53:56.719168157 -0400 -@@ -692,6 +692,7 @@ static const struct file_operations hfs_ - .write_iter = generic_file_write_iter, - .mmap = generic_file_mmap, - .splice_read = filemap_splice_read, -+ .splice_write = iter_file_splice_write, - .fsync = hfs_file_fsync, - .open = hfs_file_open, - .release = hfs_file_release, -diff -purNx .git BPI-Router-Linux-kernel/fs/hfsplus/bnode.c BPI-Router-Linux-kernel-6.16.12/fs/hfsplus/bnode.c ---- BPI-Router-Linux-kernel/fs/hfsplus/bnode.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/hfsplus/bnode.c 2025-10-22 13:53:56.719168157 -0400 -@@ -18,12 +18,68 @@ - #include "hfsplus_fs.h" - #include "hfsplus_raw.h" - -+static inline -+bool is_bnode_offset_valid(struct hfs_bnode *node, int off) -+{ -+ bool is_valid = off < node->tree->node_size; -+ -+ if (!is_valid) { -+ pr_err("requested invalid offset: " -+ "NODE: id %u, type %#x, height %u, " -+ "node_size %u, offset %d\n", -+ node->this, node->type, node->height, -+ node->tree->node_size, off); -+ } -+ -+ return is_valid; -+} -+ -+static inline -+int check_and_correct_requested_length(struct hfs_bnode *node, int off, int len) -+{ -+ unsigned int node_size; -+ -+ if (!is_bnode_offset_valid(node, off)) -+ return 0; -+ -+ node_size = node->tree->node_size; -+ -+ if ((off + len) > node_size) { -+ int new_len = (int)node_size - off; -+ -+ pr_err("requested length has been corrected: " -+ "NODE: id %u, type %#x, height %u, " -+ "node_size %u, offset %d, " -+ "requested_len %d, corrected_len %d\n", -+ node->this, node->type, node->height, -+ node->tree->node_size, off, len, new_len); -+ -+ return new_len; -+ } -+ -+ return len; -+} -+ - /* Copy a specified range of bytes from the raw data of a node */ - void hfs_bnode_read(struct hfs_bnode *node, void *buf, int off, int len) - { - struct page **pagep; - int l; - -+ if (!is_bnode_offset_valid(node, off)) -+ return; -+ -+ if (len == 0) { -+ pr_err("requested zero length: " -+ "NODE: id %u, type %#x, height %u, " -+ "node_size %u, offset %d, len %d\n", -+ node->this, node->type, node->height, -+ node->tree->node_size, off, len); -+ return; -+ } -+ -+ len = check_and_correct_requested_length(node, off, len); -+ - off += node->page_offset; - pagep = node->page + (off >> PAGE_SHIFT); - off &= ~PAGE_MASK; -@@ -81,6 +137,20 @@ void hfs_bnode_write(struct hfs_bnode *n - struct page **pagep; - int l; - -+ if (!is_bnode_offset_valid(node, off)) -+ return; -+ -+ if (len == 0) { -+ pr_err("requested zero length: " -+ "NODE: id %u, type %#x, height %u, " -+ "node_size %u, offset %d, len %d\n", -+ node->this, node->type, node->height, -+ node->tree->node_size, off, len); -+ return; -+ } -+ -+ len = check_and_correct_requested_length(node, off, len); -+ - off += node->page_offset; - pagep = node->page + (off >> PAGE_SHIFT); - off &= ~PAGE_MASK; -@@ -109,6 +179,20 @@ void hfs_bnode_clear(struct hfs_bnode *n - struct page **pagep; - int l; - -+ if (!is_bnode_offset_valid(node, off)) -+ return; -+ -+ if (len == 0) { -+ pr_err("requested zero length: " -+ "NODE: id %u, type %#x, height %u, " -+ "node_size %u, offset %d, len %d\n", -+ node->this, node->type, node->height, -+ node->tree->node_size, off, len); -+ return; -+ } -+ -+ len = check_and_correct_requested_length(node, off, len); -+ - off += node->page_offset; - pagep = node->page + (off >> PAGE_SHIFT); - off &= ~PAGE_MASK; -@@ -133,6 +217,10 @@ void hfs_bnode_copy(struct hfs_bnode *ds - hfs_dbg(BNODE_MOD, "copybytes: %u,%u,%u\n", dst, src, len); - if (!len) - return; -+ -+ len = check_and_correct_requested_length(src_node, src, len); -+ len = check_and_correct_requested_length(dst_node, dst, len); -+ - src += src_node->page_offset; - dst += dst_node->page_offset; - src_page = src_node->page + (src >> PAGE_SHIFT); -@@ -187,6 +275,10 @@ void hfs_bnode_move(struct hfs_bnode *no - hfs_dbg(BNODE_MOD, "movebytes: %u,%u,%u\n", dst, src, len); - if (!len) - return; -+ -+ len = check_and_correct_requested_length(node, src, len); -+ len = check_and_correct_requested_length(node, dst, len); -+ - src += node->page_offset; - dst += node->page_offset; - if (dst > src) { -diff -purNx .git BPI-Router-Linux-kernel/fs/hfsplus/extents.c BPI-Router-Linux-kernel-6.16.12/fs/hfsplus/extents.c ---- BPI-Router-Linux-kernel/fs/hfsplus/extents.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/hfsplus/extents.c 2025-10-22 13:53:56.719168157 -0400 -@@ -342,9 +342,6 @@ static int hfsplus_free_extents(struct s - int i; - int err = 0; - -- /* Mapping the allocation file may lock the extent tree */ -- WARN_ON(mutex_is_locked(&HFSPLUS_SB(sb)->ext_tree->tree_lock)); -- - hfsplus_dump_extent(extent); - for (i = 0; i < 8; extent++, i++) { - count = be32_to_cpu(extent->block_count); -diff -purNx .git BPI-Router-Linux-kernel/fs/hfsplus/inode.c BPI-Router-Linux-kernel-6.16.12/fs/hfsplus/inode.c ---- BPI-Router-Linux-kernel/fs/hfsplus/inode.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/hfsplus/inode.c 2025-10-22 13:53:56.719168157 -0400 -@@ -368,6 +368,7 @@ static const struct file_operations hfsp - .write_iter = generic_file_write_iter, - .mmap = generic_file_mmap, - .splice_read = filemap_splice_read, -+ .splice_write = iter_file_splice_write, - .fsync = hfsplus_file_fsync, - .open = hfsplus_file_open, - .release = hfsplus_file_release, -diff -purNx .git BPI-Router-Linux-kernel/fs/hfsplus/unicode.c BPI-Router-Linux-kernel-6.16.12/fs/hfsplus/unicode.c ---- BPI-Router-Linux-kernel/fs/hfsplus/unicode.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/hfsplus/unicode.c 2025-10-22 13:53:56.719168157 -0400 -@@ -132,7 +132,14 @@ int hfsplus_uni2asc(struct super_block * - - op = astr; - ip = ustr->unicode; -+ - ustrlen = be16_to_cpu(ustr->length); -+ if (ustrlen > HFSPLUS_MAX_STRLEN) { -+ ustrlen = HFSPLUS_MAX_STRLEN; -+ pr_err("invalid length %u has been corrected to %d\n", -+ be16_to_cpu(ustr->length), ustrlen); -+ } -+ - len = *len_p; - ce1 = NULL; - compose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags); -diff -purNx .git BPI-Router-Linux-kernel/fs/hfsplus/xattr.c BPI-Router-Linux-kernel-6.16.12/fs/hfsplus/xattr.c ---- BPI-Router-Linux-kernel/fs/hfsplus/xattr.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/hfsplus/xattr.c 2025-10-22 13:53:56.719168157 -0400 -@@ -172,7 +172,11 @@ check_attr_tree_state_again: - return PTR_ERR(attr_file); - } - -- BUG_ON(i_size_read(attr_file) != 0); -+ if (i_size_read(attr_file) != 0) { -+ err = -EIO; -+ pr_err("detected inconsistent attributes file, running fsck.hfsplus is recommended.\n"); -+ goto end_attr_file_creation; -+ } - - hip = HFSPLUS_I(attr_file); - -diff -purNx .git BPI-Router-Linux-kernel/fs/hugetlbfs/inode.c BPI-Router-Linux-kernel-6.16.12/fs/hugetlbfs/inode.c ---- BPI-Router-Linux-kernel/fs/hugetlbfs/inode.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/hugetlbfs/inode.c 2025-10-22 13:53:56.719168157 -0400 -@@ -520,14 +520,16 @@ static bool remove_inode_single_folio(st - - /* - * If folio is mapped, it was faulted in after being -- * unmapped in caller. Unmap (again) while holding -- * the fault mutex. The mutex will prevent faults -- * until we finish removing the folio. -+ * unmapped in caller or hugetlb_vmdelete_list() skips -+ * unmapping it due to fail to grab lock. Unmap (again) -+ * while holding the fault mutex. The mutex will prevent -+ * faults until we finish removing the folio. Hold folio -+ * lock to guarantee no concurrent migration. - */ -+ folio_lock(folio); - if (unlikely(folio_mapped(folio))) - hugetlb_unmap_file_folio(h, mapping, folio, index); - -- folio_lock(folio); - /* - * We must remove the folio from page cache before removing - * the region/ reserve map (hugetlb_unreserve_pages). In -diff -purNx .git BPI-Router-Linux-kernel/fs/internal.h BPI-Router-Linux-kernel-6.16.12/fs/internal.h ---- BPI-Router-Linux-kernel/fs/internal.h 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/internal.h 2025-10-22 13:53:56.719168157 -0400 -@@ -322,12 +322,15 @@ struct mnt_idmap *alloc_mnt_idmap(struct - struct mnt_idmap *mnt_idmap_get(struct mnt_idmap *idmap); - void mnt_idmap_put(struct mnt_idmap *idmap); - struct stashed_operations { -+ struct dentry *(*stash_dentry)(struct dentry **stashed, -+ struct dentry *dentry); - void (*put_data)(void *data); - int (*init_inode)(struct inode *inode, void *data); - }; - int path_from_stashed(struct dentry **stashed, struct vfsmount *mnt, void *data, - struct path *path); - void stashed_dentry_prune(struct dentry *dentry); -+struct dentry *stash_dentry(struct dentry **stashed, struct dentry *dentry); - struct dentry *stashed_dentry_get(struct dentry **stashed); - /** - * path_mounted - check whether path is mounted -diff -purNx .git BPI-Router-Linux-kernel/fs/iomap/buffered-io.c BPI-Router-Linux-kernel-6.16.12/fs/iomap/buffered-io.c ---- BPI-Router-Linux-kernel/fs/iomap/buffered-io.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/iomap/buffered-io.c 2025-10-22 13:53:56.719168157 -0400 -@@ -71,6 +71,9 @@ static void iomap_set_range_uptodate(str - unsigned long flags; - bool uptodate = true; - -+ if (folio_test_uptodate(folio)) -+ return; -+ - if (ifs) { - spin_lock_irqsave(&ifs->state_lock, flags); - uptodate = ifs_set_range_uptodate(folio, ifs, off, len); -diff -purNx .git BPI-Router-Linux-kernel/fs/iomap/direct-io.c BPI-Router-Linux-kernel-6.16.12/fs/iomap/direct-io.c ---- BPI-Router-Linux-kernel/fs/iomap/direct-io.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/iomap/direct-io.c 2025-10-22 13:53:56.719168157 -0400 -@@ -368,14 +368,14 @@ static int iomap_dio_bio_iter(struct iom - if (iomap->flags & IOMAP_F_SHARED) - dio->flags |= IOMAP_DIO_COW; - -- if (iomap->flags & IOMAP_F_NEW) { -+ if (iomap->flags & IOMAP_F_NEW) - need_zeroout = true; -- } else if (iomap->type == IOMAP_MAPPED) { -- if (iomap_dio_can_use_fua(iomap, dio)) -- bio_opf |= REQ_FUA; -- else -- dio->flags &= ~IOMAP_DIO_WRITE_THROUGH; -- } -+ else if (iomap->type == IOMAP_MAPPED && -+ iomap_dio_can_use_fua(iomap, dio)) -+ bio_opf |= REQ_FUA; -+ -+ if (!(bio_opf & REQ_FUA)) -+ dio->flags &= ~IOMAP_DIO_WRITE_THROUGH; - - /* - * We can only do deferred completion for pure overwrites that -diff -purNx .git BPI-Router-Linux-kernel/fs/isofs/inode.c BPI-Router-Linux-kernel-6.16.12/fs/isofs/inode.c ---- BPI-Router-Linux-kernel/fs/isofs/inode.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/isofs/inode.c 2025-10-22 13:53:56.719168157 -0400 -@@ -1440,9 +1440,16 @@ static int isofs_read_inode(struct inode - inode->i_op = &page_symlink_inode_operations; - inode_nohighmem(inode); - inode->i_data.a_ops = &isofs_symlink_aops; -- } else -+ } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || -+ S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { - /* XXX - parse_rock_ridge_inode() had already set i_rdev. */ - init_special_inode(inode, inode->i_mode, inode->i_rdev); -+ } else { -+ printk(KERN_DEBUG "ISOFS: Invalid file type 0%04o for inode %lu.\n", -+ inode->i_mode, inode->i_ino); -+ ret = -EIO; -+ goto fail; -+ } - - ret = 0; - out: -diff -purNx .git BPI-Router-Linux-kernel/fs/jbd2/checkpoint.c BPI-Router-Linux-kernel-6.16.12/fs/jbd2/checkpoint.c ---- BPI-Router-Linux-kernel/fs/jbd2/checkpoint.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/jbd2/checkpoint.c 2025-10-22 13:53:56.719168157 -0400 -@@ -285,6 +285,7 @@ restart: - retry: - if (batch_count) - __flush_batch(journal, &batch_count); -+ cond_resched(); - spin_lock(&journal->j_list_lock); - goto restart; - } -diff -purNx .git BPI-Router-Linux-kernel/fs/jfs/file.c BPI-Router-Linux-kernel-6.16.12/fs/jfs/file.c ---- BPI-Router-Linux-kernel/fs/jfs/file.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/jfs/file.c 2025-10-22 13:53:56.719168157 -0400 -@@ -44,6 +44,9 @@ static int jfs_open(struct inode *inode, - { - int rc; - -+ if (S_ISREG(inode->i_mode) && inode->i_size < 0) -+ return -EIO; -+ - if ((rc = dquot_file_open(inode, file))) - return rc; - -diff -purNx .git BPI-Router-Linux-kernel/fs/jfs/inode.c BPI-Router-Linux-kernel-6.16.12/fs/jfs/inode.c ---- BPI-Router-Linux-kernel/fs/jfs/inode.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/jfs/inode.c 2025-10-22 13:53:56.719168157 -0400 -@@ -145,9 +145,9 @@ void jfs_evict_inode(struct inode *inode - if (!inode->i_nlink && !is_bad_inode(inode)) { - dquot_initialize(inode); - -+ truncate_inode_pages_final(&inode->i_data); - if (JFS_IP(inode)->fileset == FILESYSTEM_I) { - struct inode *ipimap = JFS_SBI(inode->i_sb)->ipimap; -- truncate_inode_pages_final(&inode->i_data); - - if (test_cflag(COMMIT_Freewmap, inode)) - jfs_free_zero_link(inode); -diff -purNx .git BPI-Router-Linux-kernel/fs/jfs/jfs_dmap.c BPI-Router-Linux-kernel-6.16.12/fs/jfs/jfs_dmap.c ---- BPI-Router-Linux-kernel/fs/jfs/jfs_dmap.c 2025-10-22 13:53:23.523327650 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/jfs/jfs_dmap.c 2025-10-22 13:53:56.719168157 -0400 -@@ -1389,6 +1389,12 @@ dbAllocAG(struct bmap * bmp, int agno, s - (1 << (L2LPERCTL - (bmp->db_agheight << 1))) / bmp->db_agwidth; - ti = bmp->db_agstart + bmp->db_agwidth * (agno & (agperlev - 1)); - -+ if (ti < 0 || ti >= le32_to_cpu(dcp->nleafs)) { -+ jfs_error(bmp->db_ipbmap->i_sb, "Corrupt dmapctl page\n"); -+ release_metapage(mp); -+ return -EIO; -+ } -+ - /* dmap control page trees fan-out by 4 and a single allocation - * group may be described by 1 or 2 subtrees within the ag level - * dmap control page, depending upon the ag size. examine the ag's -@@ -1809,8 +1815,10 @@ dbAllocCtl(struct bmap * bmp, s64 nblock - return -EIO; - dp = (struct dmap *) mp->data; - -- if (dp->tree.budmin < 0) -+ if (dp->tree.budmin < 0) { -+ release_metapage(mp); - return -EIO; -+ } - - /* try to allocate the blocks. - */ -diff -purNx .git BPI-Router-Linux-kernel/fs/kernfs/file.c BPI-Router-Linux-kernel-6.16.12/fs/kernfs/file.c ---- BPI-Router-Linux-kernel/fs/kernfs/file.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/kernfs/file.c 2025-10-22 13:53:56.719168157 -0400 -@@ -70,6 +70,24 @@ static struct kernfs_open_node *of_on(st - !list_empty(&of->list)); - } - -+/* Get active reference to kernfs node for an open file */ -+static struct kernfs_open_file *kernfs_get_active_of(struct kernfs_open_file *of) -+{ -+ /* Skip if file was already released */ -+ if (unlikely(of->released)) -+ return NULL; -+ -+ if (!kernfs_get_active(of->kn)) -+ return NULL; -+ -+ return of; -+} -+ -+static void kernfs_put_active_of(struct kernfs_open_file *of) -+{ -+ return kernfs_put_active(of->kn); -+} -+ - /** - * kernfs_deref_open_node_locked - Get kernfs_open_node corresponding to @kn - * -@@ -139,7 +157,7 @@ static void kernfs_seq_stop_active(struc - - if (ops->seq_stop) - ops->seq_stop(sf, v); -- kernfs_put_active(of->kn); -+ kernfs_put_active_of(of); - } - - static void *kernfs_seq_start(struct seq_file *sf, loff_t *ppos) -@@ -152,7 +170,7 @@ static void *kernfs_seq_start(struct seq - * the ops aren't called concurrently for the same open file. - */ - mutex_lock(&of->mutex); -- if (!kernfs_get_active(of->kn)) -+ if (!kernfs_get_active_of(of)) - return ERR_PTR(-ENODEV); - - ops = kernfs_ops(of->kn); -@@ -238,7 +256,7 @@ static ssize_t kernfs_file_read_iter(str - * the ops aren't called concurrently for the same open file. - */ - mutex_lock(&of->mutex); -- if (!kernfs_get_active(of->kn)) { -+ if (!kernfs_get_active_of(of)) { - len = -ENODEV; - mutex_unlock(&of->mutex); - goto out_free; -@@ -252,7 +270,7 @@ static ssize_t kernfs_file_read_iter(str - else - len = -EINVAL; - -- kernfs_put_active(of->kn); -+ kernfs_put_active_of(of); - mutex_unlock(&of->mutex); - - if (len < 0) -@@ -323,7 +341,7 @@ static ssize_t kernfs_fop_write_iter(str - * the ops aren't called concurrently for the same open file. - */ - mutex_lock(&of->mutex); -- if (!kernfs_get_active(of->kn)) { -+ if (!kernfs_get_active_of(of)) { - mutex_unlock(&of->mutex); - len = -ENODEV; - goto out_free; -@@ -335,7 +353,7 @@ static ssize_t kernfs_fop_write_iter(str - else - len = -EINVAL; - -- kernfs_put_active(of->kn); -+ kernfs_put_active_of(of); - mutex_unlock(&of->mutex); - - if (len > 0) -@@ -357,13 +375,13 @@ static void kernfs_vma_open(struct vm_ar - if (!of->vm_ops) - return; - -- if (!kernfs_get_active(of->kn)) -+ if (!kernfs_get_active_of(of)) - return; - - if (of->vm_ops->open) - of->vm_ops->open(vma); - -- kernfs_put_active(of->kn); -+ kernfs_put_active_of(of); - } - - static vm_fault_t kernfs_vma_fault(struct vm_fault *vmf) -@@ -375,14 +393,14 @@ static vm_fault_t kernfs_vma_fault(struc - if (!of->vm_ops) - return VM_FAULT_SIGBUS; - -- if (!kernfs_get_active(of->kn)) -+ if (!kernfs_get_active_of(of)) - return VM_FAULT_SIGBUS; - - ret = VM_FAULT_SIGBUS; - if (of->vm_ops->fault) - ret = of->vm_ops->fault(vmf); - -- kernfs_put_active(of->kn); -+ kernfs_put_active_of(of); - return ret; - } - -@@ -395,7 +413,7 @@ static vm_fault_t kernfs_vma_page_mkwrit - if (!of->vm_ops) - return VM_FAULT_SIGBUS; - -- if (!kernfs_get_active(of->kn)) -+ if (!kernfs_get_active_of(of)) - return VM_FAULT_SIGBUS; - - ret = 0; -@@ -404,7 +422,7 @@ static vm_fault_t kernfs_vma_page_mkwrit - else - file_update_time(file); - -- kernfs_put_active(of->kn); -+ kernfs_put_active_of(of); - return ret; - } - -@@ -418,14 +436,14 @@ static int kernfs_vma_access(struct vm_a - if (!of->vm_ops) - return -EINVAL; - -- if (!kernfs_get_active(of->kn)) -+ if (!kernfs_get_active_of(of)) - return -EINVAL; - - ret = -EINVAL; - if (of->vm_ops->access) - ret = of->vm_ops->access(vma, addr, buf, len, write); - -- kernfs_put_active(of->kn); -+ kernfs_put_active_of(of); - return ret; - } - -@@ -455,7 +473,7 @@ static int kernfs_fop_mmap(struct file * - mutex_lock(&of->mutex); - - rc = -ENODEV; -- if (!kernfs_get_active(of->kn)) -+ if (!kernfs_get_active_of(of)) - goto out_unlock; - - ops = kernfs_ops(of->kn); -@@ -490,7 +508,7 @@ static int kernfs_fop_mmap(struct file * - } - vma->vm_ops = &kernfs_vm_ops; - out_put: -- kernfs_put_active(of->kn); -+ kernfs_put_active_of(of); - out_unlock: - mutex_unlock(&of->mutex); - -@@ -852,7 +870,7 @@ static __poll_t kernfs_fop_poll(struct f - struct kernfs_node *kn = kernfs_dentry_node(filp->f_path.dentry); - __poll_t ret; - -- if (!kernfs_get_active(kn)) -+ if (!kernfs_get_active_of(of)) - return DEFAULT_POLLMASK|EPOLLERR|EPOLLPRI; - - if (kn->attr.ops->poll) -@@ -860,7 +878,7 @@ static __poll_t kernfs_fop_poll(struct f - else - ret = kernfs_generic_poll(of, wait); - -- kernfs_put_active(kn); -+ kernfs_put_active_of(of); - return ret; - } - -@@ -875,7 +893,7 @@ static loff_t kernfs_fop_llseek(struct f - * the ops aren't called concurrently for the same open file. - */ - mutex_lock(&of->mutex); -- if (!kernfs_get_active(of->kn)) { -+ if (!kernfs_get_active_of(of)) { - mutex_unlock(&of->mutex); - return -ENODEV; - } -@@ -886,7 +904,7 @@ static loff_t kernfs_fop_llseek(struct f - else - ret = generic_file_llseek(file, offset, whence); - -- kernfs_put_active(of->kn); -+ kernfs_put_active_of(of); - mutex_unlock(&of->mutex); - return ret; - } -diff -purNx .git BPI-Router-Linux-kernel/fs/libfs.c BPI-Router-Linux-kernel-6.16.12/fs/libfs.c ---- BPI-Router-Linux-kernel/fs/libfs.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/libfs.c 2025-10-22 13:53:56.723168138 -0400 -@@ -613,7 +613,7 @@ void simple_recursive_removal(struct den - struct dentry *victim = NULL, *child; - struct inode *inode = this->d_inode; - -- inode_lock(inode); -+ inode_lock_nested(inode, I_MUTEX_CHILD); - if (d_is_dir(this)) - inode->i_flags |= S_DEAD; - while ((child = find_next_child(this, victim)) == NULL) { -@@ -625,7 +625,7 @@ void simple_recursive_removal(struct den - victim = this; - this = this->d_parent; - inode = this->d_inode; -- inode_lock(inode); -+ inode_lock_nested(inode, I_MUTEX_CHILD); - if (simple_positive(victim)) { - d_invalidate(victim); // avoid lost mounts - if (d_is_dir(victim)) -@@ -1649,12 +1649,10 @@ struct inode *alloc_anon_inode(struct su - */ - inode->i_state = I_DIRTY; - /* -- * Historically anonymous inodes didn't have a type at all and -- * userspace has come to rely on this. Internally they're just -- * regular files but S_IFREG is masked off when reporting -- * information to userspace. -+ * Historically anonymous inodes don't have a type at all and -+ * userspace has come to rely on this. - */ -- inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR; -+ inode->i_mode = S_IRUSR | S_IWUSR; - inode->i_uid = current_fsuid(); - inode->i_gid = current_fsgid(); - inode->i_flags |= S_PRIVATE | S_ANON_INODE; -@@ -2128,6 +2126,8 @@ struct dentry *stashed_dentry_get(struct - dentry = rcu_dereference(*stashed); - if (!dentry) - return NULL; -+ if (IS_ERR(dentry)) -+ return dentry; - if (!lockref_get_not_dead(&dentry->d_lockref)) - return NULL; - return dentry; -@@ -2176,8 +2176,7 @@ static struct dentry *prepare_anon_dentr - return dentry; - } - --static struct dentry *stash_dentry(struct dentry **stashed, -- struct dentry *dentry) -+struct dentry *stash_dentry(struct dentry **stashed, struct dentry *dentry) - { - guard(rcu)(); - for (;;) { -@@ -2218,12 +2217,15 @@ static struct dentry *stash_dentry(struc - int path_from_stashed(struct dentry **stashed, struct vfsmount *mnt, void *data, - struct path *path) - { -- struct dentry *dentry; -+ struct dentry *dentry, *res; - const struct stashed_operations *sops = mnt->mnt_sb->s_fs_info; - - /* See if dentry can be reused. */ -- path->dentry = stashed_dentry_get(stashed); -- if (path->dentry) { -+ res = stashed_dentry_get(stashed); -+ if (IS_ERR(res)) -+ return PTR_ERR(res); -+ if (res) { -+ path->dentry = res; - sops->put_data(data); - goto out_path; - } -@@ -2234,8 +2236,17 @@ int path_from_stashed(struct dentry **st - return PTR_ERR(dentry); - - /* Added a new dentry. @data is now owned by the filesystem. */ -- path->dentry = stash_dentry(stashed, dentry); -- if (path->dentry != dentry) -+ if (sops->stash_dentry) -+ res = sops->stash_dentry(stashed, dentry); -+ else -+ res = stash_dentry(stashed, dentry); -+ if (IS_ERR(res)) { -+ dput(dentry); -+ return PTR_ERR(res); -+ } -+ path->dentry = res; -+ /* A dentry was reused. */ -+ if (res != dentry) - dput(dentry); - - out_path: -diff -purNx .git BPI-Router-Linux-kernel/fs/namei.c BPI-Router-Linux-kernel-6.16.12/fs/namei.c ---- BPI-Router-Linux-kernel/fs/namei.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/namei.c 2025-10-22 13:53:56.723168138 -0400 -@@ -2917,7 +2917,8 @@ static int lookup_one_common(struct mnt_ - * @base: base directory to lookup from - * - * Look up a dentry by name in the dcache, returning NULL if it does not -- * currently exist. The function does not try to create a dentry. -+ * currently exist. The function does not try to create a dentry and if one -+ * is found it doesn't try to revalidate it. - * - * Note that this routine is purely a helper for filesystem usage and should - * not be called by generic code. It does no permission checking. -@@ -2933,7 +2934,7 @@ struct dentry *try_lookup_noperm(struct - if (err) - return ERR_PTR(err); - -- return lookup_dcache(name, base, 0); -+ return d_lookup(base, name); - } - EXPORT_SYMBOL(try_lookup_noperm); - -@@ -3057,14 +3058,22 @@ EXPORT_SYMBOL(lookup_one_positive_unlock - * Note that this routine is purely a helper for filesystem usage and should - * not be called by generic code. It does no permission checking. - * -- * Unlike lookup_noperm, it should be called without the parent -+ * Unlike lookup_noperm(), it should be called without the parent - * i_rwsem held, and will take the i_rwsem itself if necessary. -+ * -+ * Unlike try_lookup_noperm() it *does* revalidate the dentry if it already -+ * existed. - */ - struct dentry *lookup_noperm_unlocked(struct qstr *name, struct dentry *base) - { - struct dentry *ret; -+ int err; - -- ret = try_lookup_noperm(name, base); -+ err = lookup_noperm_common(name, base); -+ if (err) -+ return ERR_PTR(err); -+ -+ ret = lookup_dcache(name, base, 0); - if (!ret) - ret = lookup_slow(name, base, 0); - return ret; -@@ -3471,7 +3480,7 @@ static int may_open(struct mnt_idmap *id - return -EACCES; - break; - default: -- VFS_BUG_ON_INODE(1, inode); -+ VFS_BUG_ON_INODE(!IS_ANON_FILE(inode), inode); - } - - error = inode_permission(idmap, inode, MAY_OPEN | acc_mode); -diff -purNx .git BPI-Router-Linux-kernel/fs/namespace.c BPI-Router-Linux-kernel-6.16.12/fs/namespace.c ---- BPI-Router-Linux-kernel/fs/namespace.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/namespace.c 2025-10-22 13:53:56.723168138 -0400 -@@ -2310,21 +2310,62 @@ out: - return dst_mnt; - } - --/* Caller should check returned pointer for errors */ -+static inline bool extend_array(struct path **res, struct path **to_free, -+ unsigned n, unsigned *count, unsigned new_count) -+{ -+ struct path *p; - --struct vfsmount *collect_mounts(const struct path *path) -+ if (likely(n < *count)) -+ return true; -+ p = kmalloc_array(new_count, sizeof(struct path), GFP_KERNEL); -+ if (p && *count) -+ memcpy(p, *res, *count * sizeof(struct path)); -+ *count = new_count; -+ kfree(*to_free); -+ *to_free = *res = p; -+ return p; -+} -+ -+struct path *collect_paths(const struct path *path, -+ struct path *prealloc, unsigned count) - { -- struct mount *tree; -- namespace_lock(); -- if (!check_mnt(real_mount(path->mnt))) -- tree = ERR_PTR(-EINVAL); -- else -- tree = copy_tree(real_mount(path->mnt), path->dentry, -- CL_COPY_ALL | CL_PRIVATE); -- namespace_unlock(); -- if (IS_ERR(tree)) -- return ERR_CAST(tree); -- return &tree->mnt; -+ struct mount *root = real_mount(path->mnt); -+ struct mount *child; -+ struct path *res = prealloc, *to_free = NULL; -+ unsigned n = 0; -+ -+ guard(rwsem_read)(&namespace_sem); -+ -+ if (!check_mnt(root)) -+ return ERR_PTR(-EINVAL); -+ if (!extend_array(&res, &to_free, 0, &count, 32)) -+ return ERR_PTR(-ENOMEM); -+ res[n++] = *path; -+ list_for_each_entry(child, &root->mnt_mounts, mnt_child) { -+ if (!is_subdir(child->mnt_mountpoint, path->dentry)) -+ continue; -+ for (struct mount *m = child; m; m = next_mnt(m, child)) { -+ if (!extend_array(&res, &to_free, n, &count, 2 * count)) -+ return ERR_PTR(-ENOMEM); -+ res[n].mnt = &m->mnt; -+ res[n].dentry = m->mnt.mnt_root; -+ n++; -+ } -+ } -+ if (!extend_array(&res, &to_free, n, &count, count + 1)) -+ return ERR_PTR(-ENOMEM); -+ memset(res + n, 0, (count - n) * sizeof(struct path)); -+ for (struct path *p = res; p->mnt; p++) -+ path_get(p); -+ return res; -+} -+ -+void drop_collected_paths(struct path *paths, struct path *prealloc) -+{ -+ for (struct path *p = paths; p->mnt; p++) -+ path_put(p); -+ if (paths != prealloc) -+ kfree(paths); - } - - static void free_mnt_ns(struct mnt_namespace *); -@@ -2401,15 +2442,6 @@ void dissolve_on_fput(struct vfsmount *m - free_mnt_ns(ns); - } - --void drop_collected_mounts(struct vfsmount *mnt) --{ -- namespace_lock(); -- lock_mount_hash(); -- umount_tree(real_mount(mnt), 0); -- unlock_mount_hash(); -- namespace_unlock(); --} -- - static bool __has_locked_children(struct mount *mnt, struct dentry *dentry) - { - struct mount *child; -@@ -2511,21 +2543,6 @@ struct vfsmount *clone_private_mount(con - } - EXPORT_SYMBOL_GPL(clone_private_mount); - --int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg, -- struct vfsmount *root) --{ -- struct mount *mnt; -- int res = f(root, arg); -- if (res) -- return res; -- list_for_each_entry(mnt, &real_mount(root)->mnt_list, mnt_list) { -- res = f(&mnt->mnt, arg); -- if (res) -- return res; -- } -- return 0; --} -- - static void lock_mnt_tree(struct mount *mnt) - { - struct mount *p; -@@ -2751,14 +2768,14 @@ static int attach_recursive_mnt(struct m - hlist_for_each_entry_safe(child, n, &tree_list, mnt_hash) { - struct mount *q; - hlist_del_init(&child->mnt_hash); -- q = __lookup_mnt(&child->mnt_parent->mnt, -- child->mnt_mountpoint); -- if (q) -- mnt_change_mountpoint(child, smp, q); - /* Notice when we are propagating across user namespaces */ - if (child->mnt_parent->mnt_ns->user_ns != user_ns) - lock_mnt_tree(child); - child->mnt.mnt_flags &= ~MNT_LOCKED; -+ q = __lookup_mnt(&child->mnt_parent->mnt, -+ child->mnt_mountpoint); -+ if (q) -+ mnt_change_mountpoint(child, smp, q); - commit_tree(child); - } - put_mountpoint(smp); -@@ -2908,6 +2925,19 @@ static int graft_tree(struct mount *mnt, - return attach_recursive_mnt(mnt, p, mp, 0); - } - -+static int may_change_propagation(const struct mount *m) -+{ -+ struct mnt_namespace *ns = m->mnt_ns; -+ -+ // it must be mounted in some namespace -+ if (IS_ERR_OR_NULL(ns)) // is_mounted() -+ return -EINVAL; -+ // and the caller must be admin in userns of that namespace -+ if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN)) -+ return -EPERM; -+ return 0; -+} -+ - /* - * Sanity check the flags to change_mnt_propagation. - */ -@@ -2944,10 +2974,10 @@ static int do_change_type(struct path *p - return -EINVAL; - - namespace_lock(); -- if (!check_mnt(mnt)) { -- err = -EINVAL; -+ err = may_change_propagation(mnt); -+ if (err) - goto out_unlock; -- } -+ - if (type == MS_SHARED) { - err = invent_group_ids(mnt, recurse); - if (err) -@@ -3402,18 +3432,11 @@ static int do_set_group(struct path *fro - - namespace_lock(); - -- err = -EINVAL; -- /* To and From must be mounted */ -- if (!is_mounted(&from->mnt)) -- goto out; -- if (!is_mounted(&to->mnt)) -- goto out; -- -- err = -EPERM; -- /* We should be allowed to modify mount namespaces of both mounts */ -- if (!ns_capable(from->mnt_ns->user_ns, CAP_SYS_ADMIN)) -+ err = may_change_propagation(from); -+ if (err) - goto out; -- if (!ns_capable(to->mnt_ns->user_ns, CAP_SYS_ADMIN)) -+ err = may_change_propagation(to); -+ if (err) - goto out; - - err = -EINVAL; -@@ -4640,20 +4663,10 @@ SYSCALL_DEFINE5(move_mount, - if (flags & MOVE_MOUNT_SET_GROUP) mflags |= MNT_TREE_PROPAGATION; - if (flags & MOVE_MOUNT_BENEATH) mflags |= MNT_TREE_BENEATH; - -- lflags = 0; -- if (flags & MOVE_MOUNT_F_SYMLINKS) lflags |= LOOKUP_FOLLOW; -- if (flags & MOVE_MOUNT_F_AUTOMOUNTS) lflags |= LOOKUP_AUTOMOUNT; - uflags = 0; -- if (flags & MOVE_MOUNT_F_EMPTY_PATH) uflags = AT_EMPTY_PATH; -- from_name = getname_maybe_null(from_pathname, uflags); -- if (IS_ERR(from_name)) -- return PTR_ERR(from_name); -+ if (flags & MOVE_MOUNT_T_EMPTY_PATH) -+ uflags = AT_EMPTY_PATH; - -- lflags = 0; -- if (flags & MOVE_MOUNT_T_SYMLINKS) lflags |= LOOKUP_FOLLOW; -- if (flags & MOVE_MOUNT_T_AUTOMOUNTS) lflags |= LOOKUP_AUTOMOUNT; -- uflags = 0; -- if (flags & MOVE_MOUNT_T_EMPTY_PATH) uflags = AT_EMPTY_PATH; - to_name = getname_maybe_null(to_pathname, uflags); - if (IS_ERR(to_name)) - return PTR_ERR(to_name); -@@ -4666,11 +4679,24 @@ SYSCALL_DEFINE5(move_mount, - to_path = fd_file(f_to)->f_path; - path_get(&to_path); - } else { -+ lflags = 0; -+ if (flags & MOVE_MOUNT_T_SYMLINKS) -+ lflags |= LOOKUP_FOLLOW; -+ if (flags & MOVE_MOUNT_T_AUTOMOUNTS) -+ lflags |= LOOKUP_AUTOMOUNT; - ret = filename_lookup(to_dfd, to_name, lflags, &to_path, NULL); - if (ret) - return ret; - } - -+ uflags = 0; -+ if (flags & MOVE_MOUNT_F_EMPTY_PATH) -+ uflags = AT_EMPTY_PATH; -+ -+ from_name = getname_maybe_null(from_pathname, uflags); -+ if (IS_ERR(from_name)) -+ return PTR_ERR(from_name); -+ - if (!from_name && from_dfd >= 0) { - CLASS(fd_raw, f_from)(from_dfd); - if (fd_empty(f_from)) -@@ -4679,6 +4705,11 @@ SYSCALL_DEFINE5(move_mount, - return vfs_move_mount(&fd_file(f_from)->f_path, &to_path, mflags); - } - -+ lflags = 0; -+ if (flags & MOVE_MOUNT_F_SYMLINKS) -+ lflags |= LOOKUP_FOLLOW; -+ if (flags & MOVE_MOUNT_F_AUTOMOUNTS) -+ lflags |= LOOKUP_AUTOMOUNT; - ret = filename_lookup(from_dfd, from_name, lflags, &from_path, NULL); - if (ret) - return ret; -@@ -5285,21 +5316,18 @@ SYSCALL_DEFINE5(open_tree_attr, int, dfd - int ret; - struct mount_kattr kattr = {}; - -- kattr.kflags = MOUNT_KATTR_IDMAP_REPLACE; -+ if (flags & OPEN_TREE_CLONE) -+ kattr.kflags = MOUNT_KATTR_IDMAP_REPLACE; - if (flags & AT_RECURSIVE) - kattr.kflags |= MOUNT_KATTR_RECURSE; - - ret = wants_mount_setattr(uattr, usize, &kattr); -- if (ret < 0) -- return ret; -- -- if (ret) { -+ if (ret > 0) { - ret = do_mount_setattr(&file->f_path, &kattr); -- if (ret) -- return ret; -- - finish_mount_kattr(&kattr); - } -+ if (ret) -+ return ret; - } - - fd = get_unused_fd_flags(flags & O_CLOEXEC); -@@ -6262,7 +6290,11 @@ void put_mnt_ns(struct mnt_namespace *ns - { - if (!refcount_dec_and_test(&ns->ns.count)) - return; -- drop_collected_mounts(&ns->root->mnt); -+ namespace_lock(); -+ lock_mount_hash(); -+ umount_tree(ns->root, 0); -+ unlock_mount_hash(); -+ namespace_unlock(); - free_mnt_ns(ns); - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/netfs/buffered_read.c BPI-Router-Linux-kernel-6.16.12/fs/netfs/buffered_read.c ---- BPI-Router-Linux-kernel/fs/netfs/buffered_read.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/netfs/buffered_read.c 2025-10-22 13:53:56.723168138 -0400 -@@ -369,7 +369,7 @@ void netfs_readahead(struct readahead_co - return netfs_put_request(rreq, netfs_rreq_trace_put_return); - - cleanup_free: -- return netfs_put_request(rreq, netfs_rreq_trace_put_failed); -+ return netfs_put_failed_request(rreq); - } - EXPORT_SYMBOL(netfs_readahead); - -@@ -472,7 +472,7 @@ static int netfs_read_gaps(struct file * - return ret < 0 ? ret : 0; - - discard: -- netfs_put_request(rreq, netfs_rreq_trace_put_discard); -+ netfs_put_failed_request(rreq); - alloc_error: - folio_unlock(folio); - return ret; -@@ -532,7 +532,7 @@ int netfs_read_folio(struct file *file, - return ret < 0 ? ret : 0; - - discard: -- netfs_put_request(rreq, netfs_rreq_trace_put_discard); -+ netfs_put_failed_request(rreq); - alloc_error: - folio_unlock(folio); - return ret; -@@ -699,7 +699,7 @@ have_folio_no_wait: - return 0; - - error_put: -- netfs_put_request(rreq, netfs_rreq_trace_put_failed); -+ netfs_put_failed_request(rreq); - error: - if (folio) { - folio_unlock(folio); -@@ -754,7 +754,7 @@ int netfs_prefetch_for_write(struct file - return ret < 0 ? ret : 0; - - error_put: -- netfs_put_request(rreq, netfs_rreq_trace_put_discard); -+ netfs_put_failed_request(rreq); - error: - _leave(" = %d", ret); - return ret; -diff -purNx .git BPI-Router-Linux-kernel/fs/netfs/buffered_write.c BPI-Router-Linux-kernel-6.16.12/fs/netfs/buffered_write.c ---- BPI-Router-Linux-kernel/fs/netfs/buffered_write.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/netfs/buffered_write.c 2025-10-22 13:53:56.723168138 -0400 -@@ -53,30 +53,40 @@ static struct folio *netfs_grab_folio_fo - * data written into the pagecache until we can find out from the server what - * the values actually are. - */ --static void netfs_update_i_size(struct netfs_inode *ctx, struct inode *inode, -- loff_t i_size, loff_t pos, size_t copied) -+void netfs_update_i_size(struct netfs_inode *ctx, struct inode *inode, -+ loff_t pos, size_t copied) - { -+ loff_t i_size, end = pos + copied; - blkcnt_t add; - size_t gap; - -+ if (end <= i_size_read(inode)) -+ return; -+ - if (ctx->ops->update_i_size) { -- ctx->ops->update_i_size(inode, pos); -+ ctx->ops->update_i_size(inode, end); - return; - } - -- i_size_write(inode, pos); -+ spin_lock(&inode->i_lock); -+ -+ i_size = i_size_read(inode); -+ if (end > i_size) { -+ i_size_write(inode, end); - #if IS_ENABLED(CONFIG_FSCACHE) -- fscache_update_cookie(ctx->cache, NULL, &pos); -+ fscache_update_cookie(ctx->cache, NULL, &end); - #endif - -- gap = SECTOR_SIZE - (i_size & (SECTOR_SIZE - 1)); -- if (copied > gap) { -- add = DIV_ROUND_UP(copied - gap, SECTOR_SIZE); -- -- inode->i_blocks = min_t(blkcnt_t, -- DIV_ROUND_UP(pos, SECTOR_SIZE), -- inode->i_blocks + add); -+ gap = SECTOR_SIZE - (i_size & (SECTOR_SIZE - 1)); -+ if (copied > gap) { -+ add = DIV_ROUND_UP(copied - gap, SECTOR_SIZE); -+ -+ inode->i_blocks = min_t(blkcnt_t, -+ DIV_ROUND_UP(end, SECTOR_SIZE), -+ inode->i_blocks + add); -+ } - } -+ spin_unlock(&inode->i_lock); - } - - /** -@@ -111,7 +121,7 @@ ssize_t netfs_perform_write(struct kiocb - struct folio *folio = NULL, *writethrough = NULL; - unsigned int bdp_flags = (iocb->ki_flags & IOCB_NOWAIT) ? BDP_ASYNC : 0; - ssize_t written = 0, ret, ret2; -- loff_t i_size, pos = iocb->ki_pos; -+ loff_t pos = iocb->ki_pos; - size_t max_chunk = mapping_max_folio_size(mapping); - bool maybe_trouble = false; - -@@ -337,17 +347,15 @@ ssize_t netfs_perform_write(struct kiocb - folio_put(folio); - ret = filemap_write_and_wait_range(mapping, fpos, fpos + flen - 1); - if (ret < 0) -- goto error_folio_unlock; -+ goto out; - continue; - - copied: - flush_dcache_folio(folio); - - /* Update the inode size if we moved the EOF marker */ -+ netfs_update_i_size(ctx, inode, pos, copied); - pos += copied; -- i_size = i_size_read(inode); -- if (pos > i_size) -- netfs_update_i_size(ctx, inode, i_size, pos, copied); - written += copied; - - if (likely(!wreq)) { -diff -purNx .git BPI-Router-Linux-kernel/fs/netfs/direct_read.c BPI-Router-Linux-kernel-6.16.12/fs/netfs/direct_read.c ---- BPI-Router-Linux-kernel/fs/netfs/direct_read.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/netfs/direct_read.c 2025-10-22 13:53:56.723168138 -0400 -@@ -131,6 +131,7 @@ static ssize_t netfs_unbuffered_read(str - - if (rreq->len == 0) { - pr_err("Zero-sized read [R=%x]\n", rreq->debug_id); -+ netfs_put_request(rreq, netfs_rreq_trace_put_discard); - return -EIO; - } - -@@ -205,7 +206,7 @@ ssize_t netfs_unbuffered_read_iter_locke - if (user_backed_iter(iter)) { - ret = netfs_extract_user_iter(iter, rreq->len, &rreq->buffer.iter, 0); - if (ret < 0) -- goto out; -+ goto error_put; - rreq->direct_bv = (struct bio_vec *)rreq->buffer.iter.bvec; - rreq->direct_bv_count = ret; - rreq->direct_bv_unpin = iov_iter_extract_will_pin(iter); -@@ -238,6 +239,10 @@ out: - if (ret > 0) - orig_count -= ret; - return ret; -+ -+error_put: -+ netfs_put_failed_request(rreq); -+ return ret; - } - EXPORT_SYMBOL(netfs_unbuffered_read_iter_locked); - -diff -purNx .git BPI-Router-Linux-kernel/fs/netfs/direct_write.c BPI-Router-Linux-kernel-6.16.12/fs/netfs/direct_write.c ---- BPI-Router-Linux-kernel/fs/netfs/direct_write.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/netfs/direct_write.c 2025-10-22 13:53:56.723168138 -0400 -@@ -9,20 +9,6 @@ - #include - #include "internal.h" - --static void netfs_cleanup_dio_write(struct netfs_io_request *wreq) --{ -- struct inode *inode = wreq->inode; -- unsigned long long end = wreq->start + wreq->transferred; -- -- if (!wreq->error && -- i_size_read(inode) < end) { -- if (wreq->netfs_ops->update_i_size) -- wreq->netfs_ops->update_i_size(inode, end); -- else -- i_size_write(inode, end); -- } --} -- - /* - * Perform an unbuffered write where we may have to do an RMW operation on an - * encrypted file. This can also be used for direct I/O writes. -@@ -71,7 +57,7 @@ ssize_t netfs_unbuffered_write_iter_lock - n = netfs_extract_user_iter(iter, len, &wreq->buffer.iter, 0); - if (n < 0) { - ret = n; -- goto out; -+ goto error_put; - } - wreq->direct_bv = (struct bio_vec *)wreq->buffer.iter.bvec; - wreq->direct_bv_count = n; -@@ -98,7 +84,6 @@ ssize_t netfs_unbuffered_write_iter_lock - if (async) - wreq->iocb = iocb; - wreq->len = iov_iter_count(&wreq->buffer.iter); -- wreq->cleanup = netfs_cleanup_dio_write; - ret = netfs_unbuffered_write(wreq, is_sync_kiocb(iocb), wreq->len); - if (ret < 0) { - _debug("begin = %zd", ret); -@@ -106,7 +91,6 @@ ssize_t netfs_unbuffered_write_iter_lock - } - - if (!async) { -- trace_netfs_rreq(wreq, netfs_rreq_trace_wait_ip); - ret = netfs_wait_for_write(wreq); - if (ret > 0) - iocb->ki_pos += ret; -@@ -117,6 +101,10 @@ ssize_t netfs_unbuffered_write_iter_lock - out: - netfs_put_request(wreq, netfs_rreq_trace_put_return); - return ret; -+ -+error_put: -+ netfs_put_failed_request(wreq); -+ return ret; - } - EXPORT_SYMBOL(netfs_unbuffered_write_iter_locked); - -diff -purNx .git BPI-Router-Linux-kernel/fs/netfs/internal.h BPI-Router-Linux-kernel-6.16.12/fs/netfs/internal.h ---- BPI-Router-Linux-kernel/fs/netfs/internal.h 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/netfs/internal.h 2025-10-22 13:53:56.723168138 -0400 -@@ -28,6 +28,12 @@ int netfs_prefetch_for_write(struct file - size_t offset, size_t len); - - /* -+ * buffered_write.c -+ */ -+void netfs_update_i_size(struct netfs_inode *ctx, struct inode *inode, -+ loff_t pos, size_t copied); -+ -+/* - * main.c - */ - extern unsigned int netfs_debug; -@@ -81,6 +87,7 @@ struct netfs_io_request *netfs_alloc_req - void netfs_get_request(struct netfs_io_request *rreq, enum netfs_rreq_ref_trace what); - void netfs_clear_subrequests(struct netfs_io_request *rreq); - void netfs_put_request(struct netfs_io_request *rreq, enum netfs_rreq_ref_trace what); -+void netfs_put_failed_request(struct netfs_io_request *rreq); - struct netfs_io_subrequest *netfs_alloc_subrequest(struct netfs_io_request *rreq); - - static inline void netfs_see_request(struct netfs_io_request *rreq, -@@ -267,14 +274,32 @@ static inline void netfs_wake_rreq_flag( - enum netfs_rreq_trace trace) - { - if (test_bit(rreq_flag, &rreq->flags)) { -- trace_netfs_rreq(rreq, trace); - clear_bit_unlock(rreq_flag, &rreq->flags); - smp_mb__after_atomic(); /* Set flag before task state */ -+ trace_netfs_rreq(rreq, trace); - wake_up(&rreq->waitq); - } - } - - /* -+ * Test the NETFS_RREQ_IN_PROGRESS flag, inserting an appropriate barrier. -+ */ -+static inline bool netfs_check_rreq_in_progress(const struct netfs_io_request *rreq) -+{ -+ /* Order read of flags before read of anything else, such as error. */ -+ return test_bit_acquire(NETFS_RREQ_IN_PROGRESS, &rreq->flags); -+} -+ -+/* -+ * Test the NETFS_SREQ_IN_PROGRESS flag, inserting an appropriate barrier. -+ */ -+static inline bool netfs_check_subreq_in_progress(const struct netfs_io_subrequest *subreq) -+{ -+ /* Order read of flags before read of anything else, such as error. */ -+ return test_bit_acquire(NETFS_SREQ_IN_PROGRESS, &subreq->flags); -+} -+ -+/* - * fscache-cache.c - */ - #ifdef CONFIG_PROC_FS -diff -purNx .git BPI-Router-Linux-kernel/fs/netfs/main.c BPI-Router-Linux-kernel-6.16.12/fs/netfs/main.c ---- BPI-Router-Linux-kernel/fs/netfs/main.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/netfs/main.c 2025-10-22 13:53:56.723168138 -0400 -@@ -58,15 +58,15 @@ static int netfs_requests_seq_show(struc - - if (v == &netfs_io_requests) { - seq_puts(m, -- "REQUEST OR REF FL ERR OPS COVERAGE\n" -- "======== == === == ==== === =========\n" -+ "REQUEST OR REF FLAG ERR OPS COVERAGE\n" -+ "======== == === ==== ==== === =========\n" - ); - return 0; - } - - rreq = list_entry(v, struct netfs_io_request, proc_link); - seq_printf(m, -- "%08x %s %3d %2lx %4ld %3d @%04llx %llx/%llx", -+ "%08x %s %3d %4lx %4ld %3d @%04llx %llx/%llx", - rreq->debug_id, - netfs_origins[rreq->origin], - refcount_read(&rreq->ref), -diff -purNx .git BPI-Router-Linux-kernel/fs/netfs/misc.c BPI-Router-Linux-kernel-6.16.12/fs/netfs/misc.c ---- BPI-Router-Linux-kernel/fs/netfs/misc.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/netfs/misc.c 2025-10-22 13:53:56.723168138 -0400 -@@ -356,22 +356,22 @@ void netfs_wait_for_in_progress_stream(s - DEFINE_WAIT(myself); - - list_for_each_entry(subreq, &stream->subrequests, rreq_link) { -- if (!test_bit(NETFS_SREQ_IN_PROGRESS, &subreq->flags)) -+ if (!netfs_check_subreq_in_progress(subreq)) - continue; - -- trace_netfs_rreq(rreq, netfs_rreq_trace_wait_queue); -+ trace_netfs_rreq(rreq, netfs_rreq_trace_wait_quiesce); - for (;;) { - prepare_to_wait(&rreq->waitq, &myself, TASK_UNINTERRUPTIBLE); - -- if (!test_bit(NETFS_SREQ_IN_PROGRESS, &subreq->flags)) -+ if (!netfs_check_subreq_in_progress(subreq)) - break; - - trace_netfs_sreq(subreq, netfs_sreq_trace_wait_for); - schedule(); -- trace_netfs_rreq(rreq, netfs_rreq_trace_woke_queue); - } - } - -+ trace_netfs_rreq(rreq, netfs_rreq_trace_waited_quiesce); - finish_wait(&rreq->waitq, &myself); - } - -@@ -381,7 +381,12 @@ void netfs_wait_for_in_progress_stream(s - static int netfs_collect_in_app(struct netfs_io_request *rreq, - bool (*collector)(struct netfs_io_request *rreq)) - { -- bool need_collect = false, inactive = true; -+ bool need_collect = false, inactive = true, done = true; -+ -+ if (!netfs_check_rreq_in_progress(rreq)) { -+ trace_netfs_rreq(rreq, netfs_rreq_trace_recollect); -+ return 1; /* Done */ -+ } - - for (int i = 0; i < NR_IO_STREAMS; i++) { - struct netfs_io_subrequest *subreq; -@@ -395,14 +400,16 @@ static int netfs_collect_in_app(struct n - struct netfs_io_subrequest, - rreq_link); - if (subreq && -- (!test_bit(NETFS_SREQ_IN_PROGRESS, &subreq->flags) || -+ (!netfs_check_subreq_in_progress(subreq) || - test_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags))) { - need_collect = true; - break; - } -+ if (subreq || !test_bit(NETFS_RREQ_ALL_QUEUED, &rreq->flags)) -+ done = false; - } - -- if (!need_collect && !inactive) -+ if (!need_collect && !inactive && !done) - return 0; /* Sleep */ - - __set_current_state(TASK_RUNNING); -@@ -423,14 +430,13 @@ static int netfs_collect_in_app(struct n - /* - * Wait for a request to complete, successfully or otherwise. - */ --static ssize_t netfs_wait_for_request(struct netfs_io_request *rreq, -- bool (*collector)(struct netfs_io_request *rreq)) -+static ssize_t netfs_wait_for_in_progress(struct netfs_io_request *rreq, -+ bool (*collector)(struct netfs_io_request *rreq)) - { - DEFINE_WAIT(myself); - ssize_t ret; - - for (;;) { -- trace_netfs_rreq(rreq, netfs_rreq_trace_wait_queue); - prepare_to_wait(&rreq->waitq, &myself, TASK_UNINTERRUPTIBLE); - - if (!test_bit(NETFS_RREQ_OFFLOAD_COLLECTION, &rreq->flags)) { -@@ -440,18 +446,22 @@ static ssize_t netfs_wait_for_request(st - case 1: - goto all_collected; - case 2: -+ if (!netfs_check_rreq_in_progress(rreq)) -+ break; -+ cond_resched(); - continue; - } - } - -- if (!test_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags)) -+ if (!netfs_check_rreq_in_progress(rreq)) - break; - -+ trace_netfs_rreq(rreq, netfs_rreq_trace_wait_ip); - schedule(); -- trace_netfs_rreq(rreq, netfs_rreq_trace_woke_queue); - } - - all_collected: -+ trace_netfs_rreq(rreq, netfs_rreq_trace_waited_ip); - finish_wait(&rreq->waitq, &myself); - - ret = rreq->error; -@@ -478,12 +488,12 @@ all_collected: - - ssize_t netfs_wait_for_read(struct netfs_io_request *rreq) - { -- return netfs_wait_for_request(rreq, netfs_read_collection); -+ return netfs_wait_for_in_progress(rreq, netfs_read_collection); - } - - ssize_t netfs_wait_for_write(struct netfs_io_request *rreq) - { -- return netfs_wait_for_request(rreq, netfs_write_collection); -+ return netfs_wait_for_in_progress(rreq, netfs_write_collection); - } - - /* -@@ -494,10 +504,8 @@ static void netfs_wait_for_pause(struct - { - DEFINE_WAIT(myself); - -- trace_netfs_rreq(rreq, netfs_rreq_trace_wait_pause); -- - for (;;) { -- trace_netfs_rreq(rreq, netfs_rreq_trace_wait_queue); -+ trace_netfs_rreq(rreq, netfs_rreq_trace_wait_pause); - prepare_to_wait(&rreq->waitq, &myself, TASK_UNINTERRUPTIBLE); - - if (!test_bit(NETFS_RREQ_OFFLOAD_COLLECTION, &rreq->flags)) { -@@ -507,19 +515,23 @@ static void netfs_wait_for_pause(struct - case 1: - goto all_collected; - case 2: -+ if (!netfs_check_rreq_in_progress(rreq) || -+ !test_bit(NETFS_RREQ_PAUSE, &rreq->flags)) -+ break; -+ cond_resched(); - continue; - } - } - -- if (!test_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags) || -+ if (!netfs_check_rreq_in_progress(rreq) || - !test_bit(NETFS_RREQ_PAUSE, &rreq->flags)) - break; - - schedule(); -- trace_netfs_rreq(rreq, netfs_rreq_trace_woke_queue); - } - - all_collected: -+ trace_netfs_rreq(rreq, netfs_rreq_trace_waited_pause); - finish_wait(&rreq->waitq, &myself); - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/netfs/objects.c BPI-Router-Linux-kernel-6.16.12/fs/netfs/objects.c ---- BPI-Router-Linux-kernel/fs/netfs/objects.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/netfs/objects.c 2025-10-22 13:53:56.723168138 -0400 -@@ -116,10 +116,8 @@ static void netfs_free_request_rcu(struc - netfs_stat_d(&netfs_n_rh_rreq); - } - --static void netfs_free_request(struct work_struct *work) -+static void netfs_deinit_request(struct netfs_io_request *rreq) - { -- struct netfs_io_request *rreq = -- container_of(work, struct netfs_io_request, cleanup_work); - struct netfs_inode *ictx = netfs_inode(rreq->inode); - unsigned int i; - -@@ -149,6 +147,14 @@ static void netfs_free_request(struct wo - - if (atomic_dec_and_test(&ictx->io_count)) - wake_up_var(&ictx->io_count); -+} -+ -+static void netfs_free_request(struct work_struct *work) -+{ -+ struct netfs_io_request *rreq = -+ container_of(work, struct netfs_io_request, cleanup_work); -+ -+ netfs_deinit_request(rreq); - call_rcu(&rreq->rcu, netfs_free_request_rcu); - } - -@@ -168,6 +174,24 @@ void netfs_put_request(struct netfs_io_r - } - - /* -+ * Free a request (synchronously) that was just allocated but has -+ * failed before it could be submitted. -+ */ -+void netfs_put_failed_request(struct netfs_io_request *rreq) -+{ -+ int r = refcount_read(&rreq->ref); -+ -+ /* new requests have two references (see -+ * netfs_alloc_request(), and this function is only allowed on -+ * new request objects -+ */ -+ WARN_ON_ONCE(r != 2); -+ -+ trace_netfs_rreq_ref(rreq->debug_id, r, netfs_rreq_trace_put_failed); -+ netfs_free_request(&rreq->cleanup_work); -+} -+ -+/* - * Allocate and partially initialise an I/O request structure. - */ - struct netfs_io_subrequest *netfs_alloc_subrequest(struct netfs_io_request *rreq) -diff -purNx .git BPI-Router-Linux-kernel/fs/netfs/read_collect.c BPI-Router-Linux-kernel-6.16.12/fs/netfs/read_collect.c ---- BPI-Router-Linux-kernel/fs/netfs/read_collect.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/netfs/read_collect.c 2025-10-22 13:53:56.723168138 -0400 -@@ -218,7 +218,7 @@ reassess: - stream->collected_to = front->start; - } - -- if (test_bit(NETFS_SREQ_IN_PROGRESS, &front->flags)) -+ if (netfs_check_subreq_in_progress(front)) - notes |= HIT_PENDING; - smp_rmb(); /* Read counters after IN_PROGRESS flag. */ - transferred = READ_ONCE(front->transferred); -@@ -281,8 +281,10 @@ reassess: - } else if (test_bit(NETFS_RREQ_SHORT_TRANSFER, &rreq->flags)) { - notes |= MADE_PROGRESS; - } else { -- if (!stream->failed) -+ if (!stream->failed) { - stream->transferred += transferred; -+ stream->transferred_valid = true; -+ } - if (front->transferred < front->len) - set_bit(NETFS_RREQ_SHORT_TRANSFER, &rreq->flags); - notes |= MADE_PROGRESS; -@@ -293,7 +295,9 @@ reassess: - spin_lock(&rreq->lock); - - remove = front; -- trace_netfs_sreq(front, netfs_sreq_trace_discard); -+ trace_netfs_sreq(front, -+ notes & ABANDON_SREQ ? -+ netfs_sreq_trace_abandoned : netfs_sreq_trace_consumed); - list_del_init(&front->rreq_link); - front = list_first_entry_or_null(&stream->subrequests, - struct netfs_io_subrequest, rreq_link); -@@ -353,9 +357,11 @@ static void netfs_rreq_assess_dio(struct - - if (rreq->iocb) { - rreq->iocb->ki_pos += rreq->transferred; -- if (rreq->iocb->ki_complete) -+ if (rreq->iocb->ki_complete) { -+ trace_netfs_rreq(rreq, netfs_rreq_trace_ki_complete); - rreq->iocb->ki_complete( - rreq->iocb, rreq->error ? rreq->error : rreq->transferred); -+ } - } - if (rreq->netfs_ops->done) - rreq->netfs_ops->done(rreq); -@@ -379,9 +385,11 @@ static void netfs_rreq_assess_single(str - - if (rreq->iocb) { - rreq->iocb->ki_pos += rreq->transferred; -- if (rreq->iocb->ki_complete) -+ if (rreq->iocb->ki_complete) { -+ trace_netfs_rreq(rreq, netfs_rreq_trace_ki_complete); - rreq->iocb->ki_complete( - rreq->iocb, rreq->error ? rreq->error : rreq->transferred); -+ } - } - if (rreq->netfs_ops->done) - rreq->netfs_ops->done(rreq); -@@ -445,7 +453,7 @@ void netfs_read_collection_worker(struct - struct netfs_io_request *rreq = container_of(work, struct netfs_io_request, work); - - netfs_see_request(rreq, netfs_rreq_trace_see_work); -- if (test_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags)) { -+ if (netfs_check_rreq_in_progress(rreq)) { - if (netfs_read_collection(rreq)) - /* Drop the ref from the IN_PROGRESS flag. */ - netfs_put_request(rreq, netfs_rreq_trace_put_work_ip); -diff -purNx .git BPI-Router-Linux-kernel/fs/netfs/read_pgpriv2.c BPI-Router-Linux-kernel-6.16.12/fs/netfs/read_pgpriv2.c ---- BPI-Router-Linux-kernel/fs/netfs/read_pgpriv2.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/netfs/read_pgpriv2.c 2025-10-22 13:53:56.723168138 -0400 -@@ -110,13 +110,15 @@ static struct netfs_io_request *netfs_pg - if (!creq->io_streams[1].avail) - goto cancel_put; - -+ __set_bit(NETFS_RREQ_OFFLOAD_COLLECTION, &creq->flags); -+ trace_netfs_copy2cache(rreq, creq); - trace_netfs_write(creq, netfs_write_trace_copy_to_cache); - netfs_stat(&netfs_n_wh_copy_to_cache); - rreq->copy_to_cache = creq; - return creq; - - cancel_put: -- netfs_put_request(creq, netfs_rreq_trace_put_return); -+ netfs_put_failed_request(creq); - cancel: - rreq->copy_to_cache = ERR_PTR(-ENOBUFS); - clear_bit(NETFS_RREQ_FOLIO_COPY_TO_CACHE, &rreq->flags); -@@ -154,6 +156,9 @@ void netfs_pgpriv2_end_copy_to_cache(str - netfs_issue_write(creq, &creq->io_streams[1]); - smp_wmb(); /* Write lists before ALL_QUEUED. */ - set_bit(NETFS_RREQ_ALL_QUEUED, &creq->flags); -+ trace_netfs_rreq(rreq, netfs_rreq_trace_end_copy_to_cache); -+ if (list_empty_careful(&creq->io_streams[1].subrequests)) -+ netfs_wake_collector(creq); - - netfs_put_request(creq, netfs_rreq_trace_put_return); - creq->copy_to_cache = NULL; -diff -purNx .git BPI-Router-Linux-kernel/fs/netfs/read_single.c BPI-Router-Linux-kernel-6.16.12/fs/netfs/read_single.c ---- BPI-Router-Linux-kernel/fs/netfs/read_single.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/netfs/read_single.c 2025-10-22 13:53:56.723168138 -0400 -@@ -189,7 +189,7 @@ ssize_t netfs_read_single(struct inode * - return ret; - - cleanup_free: -- netfs_put_request(rreq, netfs_rreq_trace_put_failed); -+ netfs_put_failed_request(rreq); - return ret; - } - EXPORT_SYMBOL(netfs_read_single); -diff -purNx .git BPI-Router-Linux-kernel/fs/netfs/write_collect.c BPI-Router-Linux-kernel-6.16.12/fs/netfs/write_collect.c ---- BPI-Router-Linux-kernel/fs/netfs/write_collect.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/netfs/write_collect.c 2025-10-22 13:53:56.723168138 -0400 -@@ -240,7 +240,7 @@ reassess_streams: - } - - /* Stall if the front is still undergoing I/O. */ -- if (test_bit(NETFS_SREQ_IN_PROGRESS, &front->flags)) { -+ if (netfs_check_subreq_in_progress(front)) { - notes |= HIT_PENDING; - break; - } -@@ -254,6 +254,7 @@ reassess_streams: - if (front->start + front->transferred > stream->collected_to) { - stream->collected_to = front->start + front->transferred; - stream->transferred = stream->collected_to - wreq->start; -+ stream->transferred_valid = true; - notes |= MADE_PROGRESS; - } - if (test_bit(NETFS_SREQ_FAILED, &front->flags)) { -@@ -356,6 +357,7 @@ bool netfs_write_collection(struct netfs - { - struct netfs_inode *ictx = netfs_inode(wreq->inode); - size_t transferred; -+ bool transferred_valid = false; - int s; - - _enter("R=%x", wreq->debug_id); -@@ -376,12 +378,16 @@ bool netfs_write_collection(struct netfs - continue; - if (!list_empty(&stream->subrequests)) - return false; -- if (stream->transferred < transferred) -+ if (stream->transferred_valid && -+ stream->transferred < transferred) { - transferred = stream->transferred; -+ transferred_valid = true; -+ } - } - - /* Okay, declare that all I/O is complete. */ -- wreq->transferred = transferred; -+ if (transferred_valid) -+ wreq->transferred = transferred; - trace_netfs_rreq(wreq, netfs_rreq_trace_write_done); - - if (wreq->io_streams[1].active && -@@ -393,8 +399,10 @@ bool netfs_write_collection(struct netfs - ictx->ops->invalidate_cache(wreq); - } - -- if (wreq->cleanup) -- wreq->cleanup(wreq); -+ if ((wreq->origin == NETFS_UNBUFFERED_WRITE || -+ wreq->origin == NETFS_DIO_WRITE) && -+ !wreq->error) -+ netfs_update_i_size(ictx, &ictx->inode, wreq->start, wreq->transferred); - - if (wreq->origin == NETFS_DIO_WRITE && - wreq->mapping->nrpages) { -@@ -419,9 +427,11 @@ bool netfs_write_collection(struct netfs - if (wreq->iocb) { - size_t written = min(wreq->transferred, wreq->len); - wreq->iocb->ki_pos += written; -- if (wreq->iocb->ki_complete) -+ if (wreq->iocb->ki_complete) { -+ trace_netfs_rreq(wreq, netfs_rreq_trace_ki_complete); - wreq->iocb->ki_complete( - wreq->iocb, wreq->error ? wreq->error : written); -+ } - wreq->iocb = VFS_PTR_POISON; - } - -@@ -434,7 +444,7 @@ void netfs_write_collection_worker(struc - struct netfs_io_request *rreq = container_of(work, struct netfs_io_request, work); - - netfs_see_request(rreq, netfs_rreq_trace_see_work); -- if (test_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags)) { -+ if (netfs_check_rreq_in_progress(rreq)) { - if (netfs_write_collection(rreq)) - /* Drop the ref from the IN_PROGRESS flag. */ - netfs_put_request(rreq, netfs_rreq_trace_put_work_ip); -diff -purNx .git BPI-Router-Linux-kernel/fs/netfs/write_issue.c BPI-Router-Linux-kernel-6.16.12/fs/netfs/write_issue.c ---- BPI-Router-Linux-kernel/fs/netfs/write_issue.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/netfs/write_issue.c 2025-10-22 13:53:56.723168138 -0400 -@@ -118,12 +118,12 @@ struct netfs_io_request *netfs_create_wr - wreq->io_streams[0].prepare_write = ictx->ops->prepare_write; - wreq->io_streams[0].issue_write = ictx->ops->issue_write; - wreq->io_streams[0].collected_to = start; -- wreq->io_streams[0].transferred = LONG_MAX; -+ wreq->io_streams[0].transferred = 0; - - wreq->io_streams[1].stream_nr = 1; - wreq->io_streams[1].source = NETFS_WRITE_TO_CACHE; - wreq->io_streams[1].collected_to = start; -- wreq->io_streams[1].transferred = LONG_MAX; -+ wreq->io_streams[1].transferred = 0; - if (fscache_resources_valid(&wreq->cache_resources)) { - wreq->io_streams[1].avail = true; - wreq->io_streams[1].active = true; -@@ -133,8 +133,7 @@ struct netfs_io_request *netfs_create_wr - - return wreq; - nomem: -- wreq->error = -ENOMEM; -- netfs_put_request(wreq, netfs_rreq_trace_put_failed); -+ netfs_put_failed_request(wreq); - return ERR_PTR(-ENOMEM); - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/netfs/write_retry.c BPI-Router-Linux-kernel-6.16.12/fs/netfs/write_retry.c ---- BPI-Router-Linux-kernel/fs/netfs/write_retry.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/netfs/write_retry.c 2025-10-22 13:53:56.723168138 -0400 -@@ -146,14 +146,13 @@ static void netfs_retry_write_stream(str - subreq = netfs_alloc_subrequest(wreq); - subreq->source = to->source; - subreq->start = start; -- subreq->debug_index = atomic_inc_return(&wreq->subreq_counter); - subreq->stream_nr = to->stream_nr; - subreq->retry_count = 1; - - trace_netfs_sreq_ref(wreq->debug_id, subreq->debug_index, - refcount_read(&subreq->ref), - netfs_sreq_trace_new); -- netfs_get_subrequest(subreq, netfs_sreq_trace_get_resubmit); -+ trace_netfs_sreq(subreq, netfs_sreq_trace_split); - - list_add(&subreq->rreq_link, &to->rreq_link); - to = list_next_entry(to, rreq_link); -diff -purNx .git BPI-Router-Linux-kernel/fs/nfs/blocklayout/blocklayout.c BPI-Router-Linux-kernel-6.16.12/fs/nfs/blocklayout/blocklayout.c ---- BPI-Router-Linux-kernel/fs/nfs/blocklayout/blocklayout.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfs/blocklayout/blocklayout.c 2025-10-22 13:53:56.723168138 -0400 -@@ -149,8 +149,8 @@ do_add_page_to_bio(struct bio *bio, int - - /* limit length to what the device mapping allows */ - end = disk_addr + *len; -- if (end >= map->start + map->len) -- *len = map->start + map->len - disk_addr; -+ if (end >= map->disk_offset + map->len) -+ *len = map->disk_offset + map->len - disk_addr; - - retry: - if (!bio) { -diff -purNx .git BPI-Router-Linux-kernel/fs/nfs/blocklayout/dev.c BPI-Router-Linux-kernel-6.16.12/fs/nfs/blocklayout/dev.c ---- BPI-Router-Linux-kernel/fs/nfs/blocklayout/dev.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfs/blocklayout/dev.c 2025-10-22 13:53:56.723168138 -0400 -@@ -257,10 +257,11 @@ static bool bl_map_stripe(struct pnfs_bl - struct pnfs_block_dev *child; - u64 chunk; - u32 chunk_idx; -+ u64 disk_chunk; - u64 disk_offset; - - chunk = div_u64(offset, dev->chunk_size); -- div_u64_rem(chunk, dev->nr_children, &chunk_idx); -+ disk_chunk = div_u64_rem(chunk, dev->nr_children, &chunk_idx); - - if (chunk_idx >= dev->nr_children) { - dprintk("%s: invalid chunk idx %d (%lld/%lld)\n", -@@ -273,7 +274,7 @@ static bool bl_map_stripe(struct pnfs_bl - offset = chunk * dev->chunk_size; - - /* disk offset of the stripe */ -- disk_offset = div_u64(offset, dev->nr_children); -+ disk_offset = disk_chunk * dev->chunk_size; - - child = &dev->children[chunk_idx]; - child->map(child, disk_offset, map); -diff -purNx .git BPI-Router-Linux-kernel/fs/nfs/blocklayout/extent_tree.c BPI-Router-Linux-kernel-6.16.12/fs/nfs/blocklayout/extent_tree.c ---- BPI-Router-Linux-kernel/fs/nfs/blocklayout/extent_tree.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfs/blocklayout/extent_tree.c 2025-10-22 13:53:56.723168138 -0400 -@@ -552,6 +552,15 @@ static int ext_tree_encode_commit(struct - return ret; - } - -+/** -+ * ext_tree_prepare_commit - encode extents that need to be committed -+ * @arg: layout commit data -+ * -+ * Return values: -+ * %0: Success, all required extents are encoded -+ * %-ENOSPC: Some extents are encoded, but not all, due to RPC size limit -+ * %-ENOMEM: Out of memory, extents not encoded -+ */ - int - ext_tree_prepare_commit(struct nfs4_layoutcommit_args *arg) - { -@@ -568,12 +577,12 @@ ext_tree_prepare_commit(struct nfs4_layo - start_p = page_address(arg->layoutupdate_page); - arg->layoutupdate_pages = &arg->layoutupdate_page; - --retry: -- ret = ext_tree_encode_commit(bl, start_p + 1, buffer_size, &count, &arg->lastbytewritten); -+ ret = ext_tree_encode_commit(bl, start_p + 1, buffer_size, -+ &count, &arg->lastbytewritten); - if (unlikely(ret)) { - ext_tree_free_commitdata(arg, buffer_size); - -- buffer_size = ext_tree_layoutupdate_size(bl, count); -+ buffer_size = NFS_SERVER(arg->inode)->wsize; - count = 0; - - arg->layoutupdate_pages = -@@ -588,7 +597,8 @@ retry: - return -ENOMEM; - } - -- goto retry; -+ ret = ext_tree_encode_commit(bl, start_p + 1, buffer_size, -+ &count, &arg->lastbytewritten); - } - - *start_p = cpu_to_be32(count); -@@ -608,7 +618,7 @@ retry: - } - - dprintk("%s found %zu ranges\n", __func__, count); -- return 0; -+ return ret; - } - - void -diff -purNx .git BPI-Router-Linux-kernel/fs/nfs/client.c BPI-Router-Linux-kernel-6.16.12/fs/nfs/client.c ---- BPI-Router-Linux-kernel/fs/nfs/client.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfs/client.c 2025-10-22 13:53:56.723168138 -0400 -@@ -682,6 +682,44 @@ struct nfs_client *nfs_init_client(struc - } - EXPORT_SYMBOL_GPL(nfs_init_client); - -+static void nfs4_server_set_init_caps(struct nfs_server *server) -+{ -+#if IS_ENABLED(CONFIG_NFS_V4) -+ /* Set the basic capabilities */ -+ server->caps = server->nfs_client->cl_mvops->init_caps; -+ if (server->flags & NFS_MOUNT_NORDIRPLUS) -+ server->caps &= ~NFS_CAP_READDIRPLUS; -+ if (server->nfs_client->cl_proto == XPRT_TRANSPORT_RDMA) -+ server->caps &= ~NFS_CAP_READ_PLUS; -+ -+ /* -+ * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower -+ * authentication. -+ */ -+ if (nfs4_disable_idmapping && -+ server->client->cl_auth->au_flavor == RPC_AUTH_UNIX) -+ server->caps |= NFS_CAP_UIDGID_NOMAP; -+#endif -+} -+ -+void nfs_server_set_init_caps(struct nfs_server *server) -+{ -+ switch (server->nfs_client->rpc_ops->version) { -+ case 2: -+ server->caps = NFS_CAP_HARDLINKS | NFS_CAP_SYMLINKS; -+ break; -+ case 3: -+ server->caps = NFS_CAP_HARDLINKS | NFS_CAP_SYMLINKS; -+ if (!(server->flags & NFS_MOUNT_NORDIRPLUS)) -+ server->caps |= NFS_CAP_READDIRPLUS; -+ break; -+ default: -+ nfs4_server_set_init_caps(server); -+ break; -+ } -+} -+EXPORT_SYMBOL_GPL(nfs_server_set_init_caps); -+ - /* - * Create a version 2 or 3 client - */ -@@ -726,7 +764,6 @@ static int nfs_init_server(struct nfs_se - /* Initialise the client representation from the mount data */ - server->flags = ctx->flags; - server->options = ctx->options; -- server->caps |= NFS_CAP_HARDLINKS | NFS_CAP_SYMLINKS; - - switch (clp->rpc_ops->version) { - case 2: -@@ -762,6 +799,8 @@ static int nfs_init_server(struct nfs_se - if (error < 0) - goto error; - -+ nfs_server_set_init_caps(server); -+ - /* Preserve the values of mount_server-related mount options */ - if (ctx->mount_server.addrlen) { - memcpy(&server->mountd_address, &ctx->mount_server.address, -@@ -851,6 +890,8 @@ static void nfs_server_set_fsinfo(struct - - if (fsinfo->xattr_support) - server->caps |= NFS_CAP_XATTR; -+ else -+ server->caps &= ~NFS_CAP_XATTR; - #endif - } - -@@ -936,7 +977,6 @@ void nfs_server_copy_userdata(struct nfs - target->acregmax = source->acregmax; - target->acdirmin = source->acdirmin; - target->acdirmax = source->acdirmax; -- target->caps = source->caps; - target->options = source->options; - target->auth_info = source->auth_info; - target->port = source->port; -@@ -1170,6 +1210,8 @@ struct nfs_server *nfs_clone_server(stru - if (error < 0) - goto out_free_server; - -+ nfs_server_set_init_caps(server); -+ - /* probe the filesystem info for this server filesystem */ - error = nfs_probe_server(server, fh); - if (error < 0) -diff -purNx .git BPI-Router-Linux-kernel/fs/nfs/dir.c BPI-Router-Linux-kernel-6.16.12/fs/nfs/dir.c ---- BPI-Router-Linux-kernel/fs/nfs/dir.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfs/dir.c 2025-10-22 13:53:56.723168138 -0400 -@@ -1828,9 +1828,7 @@ static void block_revalidate(struct dent - - static void unblock_revalidate(struct dentry *dentry) - { -- /* store_release ensures wait_var_event() sees the update */ -- smp_store_release(&dentry->d_fsdata, NULL); -- wake_up_var(&dentry->d_fsdata); -+ store_release_wake_up(&dentry->d_fsdata, NULL); - } - - /* -diff -purNx .git BPI-Router-Linux-kernel/fs/nfs/export.c BPI-Router-Linux-kernel-6.16.12/fs/nfs/export.c ---- BPI-Router-Linux-kernel/fs/nfs/export.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfs/export.c 2025-10-22 13:53:56.723168138 -0400 -@@ -66,14 +66,21 @@ nfs_fh_to_dentry(struct super_block *sb, - { - struct nfs_fattr *fattr = NULL; - struct nfs_fh *server_fh = nfs_exp_embedfh(fid->raw); -- size_t fh_size = offsetof(struct nfs_fh, data) + server_fh->size; -+ size_t fh_size = offsetof(struct nfs_fh, data); - const struct nfs_rpc_ops *rpc_ops; - struct dentry *dentry; - struct inode *inode; -- int len = EMBED_FH_OFF + XDR_QUADLEN(fh_size); -+ int len = EMBED_FH_OFF; - u32 *p = fid->raw; - int ret; - -+ /* Initial check of bounds */ -+ if (fh_len < len + XDR_QUADLEN(fh_size) || -+ fh_len > XDR_QUADLEN(NFS_MAXFHSIZE)) -+ return NULL; -+ /* Calculate embedded filehandle size */ -+ fh_size += server_fh->size; -+ len += XDR_QUADLEN(fh_size); - /* NULL translates to ESTALE */ - if (fh_len < len || fh_type != len) - return NULL; -diff -purNx .git BPI-Router-Linux-kernel/fs/nfs/file.c BPI-Router-Linux-kernel-6.16.12/fs/nfs/file.c ---- BPI-Router-Linux-kernel/fs/nfs/file.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfs/file.c 2025-10-22 13:53:56.723168138 -0400 -@@ -28,6 +28,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -279,6 +280,37 @@ nfs_file_fsync(struct file *file, loff_t - } - EXPORT_SYMBOL_GPL(nfs_file_fsync); - -+void nfs_truncate_last_folio(struct address_space *mapping, loff_t from, -+ loff_t to) -+{ -+ struct folio *folio; -+ -+ if (from >= to) -+ return; -+ -+ folio = filemap_lock_folio(mapping, from >> PAGE_SHIFT); -+ if (IS_ERR(folio)) -+ return; -+ -+ if (folio_mkclean(folio)) -+ folio_mark_dirty(folio); -+ -+ if (folio_test_uptodate(folio)) { -+ loff_t fpos = folio_pos(folio); -+ size_t offset = from - fpos; -+ size_t end = folio_size(folio); -+ -+ if (to - fpos < end) -+ end = to - fpos; -+ folio_zero_segment(folio, offset, end); -+ trace_nfs_size_truncate_folio(mapping->host, to); -+ } -+ -+ folio_unlock(folio); -+ folio_put(folio); -+} -+EXPORT_SYMBOL_GPL(nfs_truncate_last_folio); -+ - /* - * Decide whether a read/modify/write cycle may be more efficient - * then a modify/write/read cycle when writing to a page in the -@@ -353,6 +385,7 @@ static int nfs_write_begin(struct file * - - dfprintk(PAGECACHE, "NFS: write_begin(%pD2(%lu), %u@%lld)\n", - file, mapping->host->i_ino, len, (long long) pos); -+ nfs_truncate_last_folio(mapping, i_size_read(mapping->host), pos); - - fgp |= fgf_set_order(len); - start: -@@ -437,10 +470,11 @@ static void nfs_invalidate_folio(struct - dfprintk(PAGECACHE, "NFS: invalidate_folio(%lu, %zu, %zu)\n", - folio->index, offset, length); - -- if (offset != 0 || length < folio_size(folio)) -- return; - /* Cancel any unstarted writes on this page */ -- nfs_wb_folio_cancel(inode, folio); -+ if (offset != 0 || length < folio_size(folio)) -+ nfs_wb_folio(inode, folio); -+ else -+ nfs_wb_folio_cancel(inode, folio); - folio_wait_private_2(folio); /* [DEPRECATED] */ - trace_nfs_invalidate_folio(inode, folio_pos(folio) + offset, length); - } -diff -purNx .git BPI-Router-Linux-kernel/fs/nfs/flexfilelayout/flexfilelayout.c BPI-Router-Linux-kernel-6.16.12/fs/nfs/flexfilelayout/flexfilelayout.c ---- BPI-Router-Linux-kernel/fs/nfs/flexfilelayout/flexfilelayout.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfs/flexfilelayout/flexfilelayout.c 2025-10-22 13:53:56.723168138 -0400 -@@ -293,7 +293,7 @@ ff_lseg_match_mirrors(struct pnfs_layout - struct pnfs_layout_segment *l2) - { - const struct nfs4_ff_layout_segment *fl1 = FF_LAYOUT_LSEG(l1); -- const struct nfs4_ff_layout_segment *fl2 = FF_LAYOUT_LSEG(l1); -+ const struct nfs4_ff_layout_segment *fl2 = FF_LAYOUT_LSEG(l2); - u32 i; - - if (fl1->mirror_array_cnt != fl2->mirror_array_cnt) -@@ -762,25 +762,28 @@ ff_layout_choose_ds_for_read(struct pnfs - { - struct nfs4_ff_layout_segment *fls = FF_LAYOUT_LSEG(lseg); - struct nfs4_ff_layout_mirror *mirror; -- struct nfs4_pnfs_ds *ds; -+ struct nfs4_pnfs_ds *ds = ERR_PTR(-EAGAIN); - u32 idx; - - /* mirrors are initially sorted by efficiency */ - for (idx = start_idx; idx < fls->mirror_array_cnt; idx++) { - mirror = FF_LAYOUT_COMP(lseg, idx); - ds = nfs4_ff_layout_prepare_ds(lseg, mirror, false); -- if (!ds) -+ if (IS_ERR(ds)) - continue; - - if (check_device && -- nfs4_test_deviceid_unavailable(&mirror->mirror_ds->id_node)) -+ nfs4_test_deviceid_unavailable(&mirror->mirror_ds->id_node)) { -+ // reinitialize the error state in case if this is the last iteration -+ ds = ERR_PTR(-EINVAL); - continue; -+ } - - *best_idx = idx; -- return ds; -+ break; - } - -- return NULL; -+ return ds; - } - - static struct nfs4_pnfs_ds * -@@ -804,7 +807,7 @@ ff_layout_choose_best_ds_for_read(struct - struct nfs4_pnfs_ds *ds; - - ds = ff_layout_choose_valid_ds_for_read(lseg, start_idx, best_idx); -- if (ds) -+ if (!IS_ERR(ds)) - return ds; - return ff_layout_choose_any_ds_for_read(lseg, start_idx, best_idx); - } -@@ -818,7 +821,7 @@ ff_layout_get_ds_for_read(struct nfs_pag - - ds = ff_layout_choose_best_ds_for_read(lseg, pgio->pg_mirror_idx, - best_idx); -- if (ds || !pgio->pg_mirror_idx) -+ if (!IS_ERR(ds) || !pgio->pg_mirror_idx) - return ds; - return ff_layout_choose_best_ds_for_read(lseg, 0, best_idx); - } -@@ -868,7 +871,7 @@ retry: - req->wb_nio = 0; - - ds = ff_layout_get_ds_for_read(pgio, &ds_idx); -- if (!ds) { -+ if (IS_ERR(ds)) { - if (!ff_layout_no_fallback_to_mds(pgio->pg_lseg)) - goto out_mds; - pnfs_generic_pg_cleanup(pgio); -@@ -942,7 +945,7 @@ retry: - for (i = 0; i < pgio->pg_mirror_count; i++) { - mirror = FF_LAYOUT_COMP(pgio->pg_lseg, i); - ds = nfs4_ff_layout_prepare_ds(pgio->pg_lseg, mirror, true); -- if (!ds) { -+ if (IS_ERR(ds)) { - if (!ff_layout_no_fallback_to_mds(pgio->pg_lseg)) - goto out_mds; - pnfs_generic_pg_cleanup(pgio); -@@ -1072,11 +1075,13 @@ static void ff_layout_resend_pnfs_read(s - { - u32 idx = hdr->pgio_mirror_idx + 1; - u32 new_idx = 0; -+ struct nfs4_pnfs_ds *ds; - -- if (ff_layout_choose_any_ds_for_read(hdr->lseg, idx, &new_idx)) -- ff_layout_send_layouterror(hdr->lseg); -- else -+ ds = ff_layout_choose_any_ds_for_read(hdr->lseg, idx, &new_idx); -+ if (IS_ERR(ds)) - pnfs_error_mark_layout_for_return(hdr->inode, hdr->lseg); -+ else -+ ff_layout_send_layouterror(hdr->lseg); - pnfs_read_resend_pnfs(hdr, new_idx); - } - -@@ -1105,6 +1110,7 @@ static void ff_layout_reset_read(struct - } - - static int ff_layout_async_handle_error_v4(struct rpc_task *task, -+ u32 op_status, - struct nfs4_state *state, - struct nfs_client *clp, - struct pnfs_layout_segment *lseg, -@@ -1115,34 +1121,42 @@ static int ff_layout_async_handle_error_ - struct nfs4_deviceid_node *devid = FF_LAYOUT_DEVID_NODE(lseg, idx); - struct nfs4_slot_table *tbl = &clp->cl_session->fc_slot_table; - -- switch (task->tk_status) { -- case -NFS4ERR_BADSESSION: -- case -NFS4ERR_BADSLOT: -- case -NFS4ERR_BAD_HIGH_SLOT: -- case -NFS4ERR_DEADSESSION: -- case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: -- case -NFS4ERR_SEQ_FALSE_RETRY: -- case -NFS4ERR_SEQ_MISORDERED: -+ switch (op_status) { -+ case NFS4_OK: -+ case NFS4ERR_NXIO: -+ break; -+ case NFSERR_PERM: -+ if (!task->tk_xprt) -+ break; -+ xprt_force_disconnect(task->tk_xprt); -+ goto out_retry; -+ case NFS4ERR_BADSESSION: -+ case NFS4ERR_BADSLOT: -+ case NFS4ERR_BAD_HIGH_SLOT: -+ case NFS4ERR_DEADSESSION: -+ case NFS4ERR_CONN_NOT_BOUND_TO_SESSION: -+ case NFS4ERR_SEQ_FALSE_RETRY: -+ case NFS4ERR_SEQ_MISORDERED: - dprintk("%s ERROR %d, Reset session. Exchangeid " - "flags 0x%x\n", __func__, task->tk_status, - clp->cl_exchange_flags); - nfs4_schedule_session_recovery(clp->cl_session, task->tk_status); -- break; -- case -NFS4ERR_DELAY: -+ goto out_retry; -+ case NFS4ERR_DELAY: - nfs_inc_stats(lseg->pls_layout->plh_inode, NFSIOS_DELAY); - fallthrough; -- case -NFS4ERR_GRACE: -+ case NFS4ERR_GRACE: - rpc_delay(task, FF_LAYOUT_POLL_RETRY_MAX); -- break; -- case -NFS4ERR_RETRY_UNCACHED_REP: -- break; -+ goto out_retry; -+ case NFS4ERR_RETRY_UNCACHED_REP: -+ goto out_retry; - /* Invalidate Layout errors */ -- case -NFS4ERR_PNFS_NO_LAYOUT: -- case -ESTALE: /* mapped NFS4ERR_STALE */ -- case -EBADHANDLE: /* mapped NFS4ERR_BADHANDLE */ -- case -EISDIR: /* mapped NFS4ERR_ISDIR */ -- case -NFS4ERR_FHEXPIRED: -- case -NFS4ERR_WRONG_TYPE: -+ case NFS4ERR_PNFS_NO_LAYOUT: -+ case NFS4ERR_STALE: -+ case NFS4ERR_BADHANDLE: -+ case NFS4ERR_ISDIR: -+ case NFS4ERR_FHEXPIRED: -+ case NFS4ERR_WRONG_TYPE: - dprintk("%s Invalid layout error %d\n", __func__, - task->tk_status); - /* -@@ -1155,6 +1169,11 @@ static int ff_layout_async_handle_error_ - pnfs_destroy_layout(NFS_I(inode)); - rpc_wake_up(&tbl->slot_tbl_waitq); - goto reset; -+ default: -+ break; -+ } -+ -+ switch (task->tk_status) { - /* RPC connection errors */ - case -ENETDOWN: - case -ENETUNREACH: -@@ -1174,27 +1193,56 @@ static int ff_layout_async_handle_error_ - nfs4_delete_deviceid(devid->ld, devid->nfs_client, - &devid->deviceid); - rpc_wake_up(&tbl->slot_tbl_waitq); -- fallthrough; -+ break; - default: -- if (ff_layout_avoid_mds_available_ds(lseg)) -- return -NFS4ERR_RESET_TO_PNFS; --reset: -- dprintk("%s Retry through MDS. Error %d\n", __func__, -- task->tk_status); -- return -NFS4ERR_RESET_TO_MDS; -+ break; - } -+ -+ if (ff_layout_avoid_mds_available_ds(lseg)) -+ return -NFS4ERR_RESET_TO_PNFS; -+reset: -+ dprintk("%s Retry through MDS. Error %d\n", __func__, -+ task->tk_status); -+ return -NFS4ERR_RESET_TO_MDS; -+ -+out_retry: - task->tk_status = 0; - return -EAGAIN; - } - - /* Retry all errors through either pNFS or MDS except for -EJUKEBOX */ - static int ff_layout_async_handle_error_v3(struct rpc_task *task, -+ u32 op_status, - struct nfs_client *clp, - struct pnfs_layout_segment *lseg, - u32 idx) - { - struct nfs4_deviceid_node *devid = FF_LAYOUT_DEVID_NODE(lseg, idx); - -+ switch (op_status) { -+ case NFS_OK: -+ case NFSERR_NXIO: -+ break; -+ case NFSERR_PERM: -+ if (!task->tk_xprt) -+ break; -+ xprt_force_disconnect(task->tk_xprt); -+ goto out_retry; -+ case NFSERR_ACCES: -+ case NFSERR_BADHANDLE: -+ case NFSERR_FBIG: -+ case NFSERR_IO: -+ case NFSERR_NOSPC: -+ case NFSERR_ROFS: -+ case NFSERR_STALE: -+ goto out_reset_to_pnfs; -+ case NFSERR_JUKEBOX: -+ nfs_inc_stats(lseg->pls_layout->plh_inode, NFSIOS_DELAY); -+ goto out_retry; -+ default: -+ break; -+ } -+ - switch (task->tk_status) { - /* File access problems. Don't mark the device as unavailable */ - case -EACCES: -@@ -1218,6 +1266,7 @@ static int ff_layout_async_handle_error_ - nfs4_delete_deviceid(devid->ld, devid->nfs_client, - &devid->deviceid); - } -+out_reset_to_pnfs: - /* FIXME: Need to prevent infinite looping here. */ - return -NFS4ERR_RESET_TO_PNFS; - out_retry: -@@ -1228,6 +1277,7 @@ out_retry: - } - - static int ff_layout_async_handle_error(struct rpc_task *task, -+ u32 op_status, - struct nfs4_state *state, - struct nfs_client *clp, - struct pnfs_layout_segment *lseg, -@@ -1246,10 +1296,11 @@ static int ff_layout_async_handle_error( - - switch (vers) { - case 3: -- return ff_layout_async_handle_error_v3(task, clp, lseg, idx); -- case 4: -- return ff_layout_async_handle_error_v4(task, state, clp, -+ return ff_layout_async_handle_error_v3(task, op_status, clp, - lseg, idx); -+ case 4: -+ return ff_layout_async_handle_error_v4(task, op_status, state, -+ clp, lseg, idx); - default: - /* should never happen */ - WARN_ON_ONCE(1); -@@ -1302,6 +1353,7 @@ static void ff_layout_io_track_ds_error( - switch (status) { - case NFS4ERR_DELAY: - case NFS4ERR_GRACE: -+ case NFS4ERR_PERM: - break; - case NFS4ERR_NXIO: - ff_layout_mark_ds_unreachable(lseg, idx); -@@ -1334,7 +1386,8 @@ static int ff_layout_read_done_cb(struct - trace_ff_layout_read_error(hdr, task->tk_status); - } - -- err = ff_layout_async_handle_error(task, hdr->args.context->state, -+ err = ff_layout_async_handle_error(task, hdr->res.op_status, -+ hdr->args.context->state, - hdr->ds_clp, hdr->lseg, - hdr->pgio_mirror_idx); - -@@ -1507,7 +1560,8 @@ static int ff_layout_write_done_cb(struc - trace_ff_layout_write_error(hdr, task->tk_status); - } - -- err = ff_layout_async_handle_error(task, hdr->args.context->state, -+ err = ff_layout_async_handle_error(task, hdr->res.op_status, -+ hdr->args.context->state, - hdr->ds_clp, hdr->lseg, - hdr->pgio_mirror_idx); - -@@ -1556,8 +1610,9 @@ static int ff_layout_commit_done_cb(stru - trace_ff_layout_commit_error(data, task->tk_status); - } - -- err = ff_layout_async_handle_error(task, NULL, data->ds_clp, -- data->lseg, data->ds_commit_index); -+ err = ff_layout_async_handle_error(task, data->res.op_status, -+ NULL, data->ds_clp, data->lseg, -+ data->ds_commit_index); - - trace_nfs4_pnfs_commit_ds(data, err); - switch (err) { -@@ -1817,6 +1872,7 @@ ff_layout_read_pagelist(struct nfs_pgio_ - u32 idx = hdr->pgio_mirror_idx; - int vers; - struct nfs_fh *fh; -+ bool ds_fatal_error = false; - - dprintk("--> %s ino %lu pgbase %u req %zu@%llu\n", - __func__, hdr->inode->i_ino, -@@ -1824,8 +1880,10 @@ ff_layout_read_pagelist(struct nfs_pgio_ - - mirror = FF_LAYOUT_COMP(lseg, idx); - ds = nfs4_ff_layout_prepare_ds(lseg, mirror, false); -- if (!ds) -+ if (IS_ERR(ds)) { -+ ds_fatal_error = nfs_error_is_fatal(PTR_ERR(ds)); - goto out_failed; -+ } - - ds_clnt = nfs4_ff_find_or_create_ds_client(mirror, ds->ds_clp, - hdr->inode); -@@ -1873,7 +1931,7 @@ ff_layout_read_pagelist(struct nfs_pgio_ - return PNFS_ATTEMPTED; - - out_failed: -- if (ff_layout_avoid_mds_available_ds(lseg)) -+ if (ff_layout_avoid_mds_available_ds(lseg) && !ds_fatal_error) - return PNFS_TRY_AGAIN; - trace_pnfs_mds_fallback_read_pagelist(hdr->inode, - hdr->args.offset, hdr->args.count, -@@ -1895,11 +1953,14 @@ ff_layout_write_pagelist(struct nfs_pgio - int vers; - struct nfs_fh *fh; - u32 idx = hdr->pgio_mirror_idx; -+ bool ds_fatal_error = false; - - mirror = FF_LAYOUT_COMP(lseg, idx); - ds = nfs4_ff_layout_prepare_ds(lseg, mirror, true); -- if (!ds) -+ if (IS_ERR(ds)) { -+ ds_fatal_error = nfs_error_is_fatal(PTR_ERR(ds)); - goto out_failed; -+ } - - ds_clnt = nfs4_ff_find_or_create_ds_client(mirror, ds->ds_clp, - hdr->inode); -@@ -1950,7 +2011,7 @@ ff_layout_write_pagelist(struct nfs_pgio - return PNFS_ATTEMPTED; - - out_failed: -- if (ff_layout_avoid_mds_available_ds(lseg)) -+ if (ff_layout_avoid_mds_available_ds(lseg) && !ds_fatal_error) - return PNFS_TRY_AGAIN; - trace_pnfs_mds_fallback_write_pagelist(hdr->inode, - hdr->args.offset, hdr->args.count, -@@ -1993,7 +2054,7 @@ static int ff_layout_initiate_commit(str - idx = calc_ds_index_from_commit(lseg, data->ds_commit_index); - mirror = FF_LAYOUT_COMP(lseg, idx); - ds = nfs4_ff_layout_prepare_ds(lseg, mirror, true); -- if (!ds) -+ if (IS_ERR(ds)) - goto out_err; - - ds_clnt = nfs4_ff_find_or_create_ds_client(mirror, ds->ds_clp, -diff -purNx .git BPI-Router-Linux-kernel/fs/nfs/flexfilelayout/flexfilelayoutdev.c BPI-Router-Linux-kernel-6.16.12/fs/nfs/flexfilelayout/flexfilelayoutdev.c ---- BPI-Router-Linux-kernel/fs/nfs/flexfilelayout/flexfilelayoutdev.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfs/flexfilelayout/flexfilelayoutdev.c 2025-10-22 13:53:56.723168138 -0400 -@@ -370,11 +370,11 @@ nfs4_ff_layout_prepare_ds(struct pnfs_la - struct nfs4_ff_layout_mirror *mirror, - bool fail_return) - { -- struct nfs4_pnfs_ds *ds = NULL; -+ struct nfs4_pnfs_ds *ds; - struct inode *ino = lseg->pls_layout->plh_inode; - struct nfs_server *s = NFS_SERVER(ino); - unsigned int max_payload; -- int status; -+ int status = -EAGAIN; - - if (!ff_layout_init_mirror_ds(lseg->pls_layout, mirror)) - goto noconnect; -@@ -418,7 +418,7 @@ noconnect: - ff_layout_send_layouterror(lseg); - if (fail_return || !ff_layout_has_available_ds(lseg)) - pnfs_error_mark_layout_for_return(ino, lseg); -- ds = NULL; -+ ds = ERR_PTR(status); - out: - return ds; - } -diff -purNx .git BPI-Router-Linux-kernel/fs/nfs/inode.c BPI-Router-Linux-kernel-6.16.12/fs/nfs/inode.c ---- BPI-Router-Linux-kernel/fs/nfs/inode.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfs/inode.c 2025-10-22 13:53:56.723168138 -0400 -@@ -710,6 +710,7 @@ nfs_setattr(struct mnt_idmap *idmap, str - { - struct inode *inode = d_inode(dentry); - struct nfs_fattr *fattr; -+ loff_t oldsize = i_size_read(inode); - int error = 0; - - nfs_inc_stats(inode, NFSIOS_VFSSETATTR); -@@ -725,7 +726,7 @@ nfs_setattr(struct mnt_idmap *idmap, str - if (error) - return error; - -- if (attr->ia_size == i_size_read(inode)) -+ if (attr->ia_size == oldsize) - attr->ia_valid &= ~ATTR_SIZE; - } - -@@ -761,8 +762,10 @@ nfs_setattr(struct mnt_idmap *idmap, str - trace_nfs_setattr_enter(inode); - - /* Write all dirty data */ -- if (S_ISREG(inode->i_mode)) -+ if (S_ISREG(inode->i_mode)) { -+ nfs_file_block_o_direct(NFS_I(inode)); - nfs_sync_inode(inode); -+ } - - fattr = nfs_alloc_fattr_with_label(NFS_SERVER(inode)); - if (fattr == NULL) { -@@ -771,8 +774,12 @@ nfs_setattr(struct mnt_idmap *idmap, str - } - - error = NFS_PROTO(inode)->setattr(dentry, fattr, attr); -- if (error == 0) -+ if (error == 0) { -+ if (attr->ia_valid & ATTR_SIZE) -+ nfs_truncate_last_folio(inode->i_mapping, oldsize, -+ attr->ia_size); - error = nfs_refresh_inode(inode, fattr); -+ } - nfs_free_fattr(fattr); - out: - trace_nfs_setattr_exit(inode, error); -@@ -2589,15 +2596,26 @@ EXPORT_SYMBOL_GPL(nfs_net_id); - static int nfs_net_init(struct net *net) - { - struct nfs_net *nn = net_generic(net, nfs_net_id); -+ int err; - - nfs_clients_init(net); - - if (!rpc_proc_register(net, &nn->rpcstats)) { -- nfs_clients_exit(net); -- return -ENOMEM; -+ err = -ENOMEM; -+ goto err_proc_rpc; - } - -- return nfs_fs_proc_net_init(net); -+ err = nfs_fs_proc_net_init(net); -+ if (err) -+ goto err_proc_nfs; -+ -+ return 0; -+ -+err_proc_nfs: -+ rpc_proc_unregister(net, "nfs"); -+err_proc_rpc: -+ nfs_clients_exit(net); -+ return err; - } - - static void nfs_net_exit(struct net *net) -diff -purNx .git BPI-Router-Linux-kernel/fs/nfs/internal.h BPI-Router-Linux-kernel-6.16.12/fs/nfs/internal.h ---- BPI-Router-Linux-kernel/fs/nfs/internal.h 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfs/internal.h 2025-10-22 13:53:56.723168138 -0400 -@@ -232,7 +232,7 @@ extern struct nfs_client * - nfs4_find_client_sessionid(struct net *, const struct sockaddr *, - struct nfs4_sessionid *, u32); - extern struct nfs_server *nfs_create_server(struct fs_context *); --extern void nfs4_server_set_init_caps(struct nfs_server *); -+extern void nfs_server_set_init_caps(struct nfs_server *); - extern struct nfs_server *nfs4_create_server(struct fs_context *); - extern struct nfs_server *nfs4_create_referral_server(struct fs_context *); - extern int nfs4_update_server(struct nfs_server *server, const char *hostname, -@@ -438,6 +438,8 @@ int nfs_file_release(struct inode *, str - int nfs_lock(struct file *, int, struct file_lock *); - int nfs_flock(struct file *, int, struct file_lock *); - int nfs_check_flags(int); -+void nfs_truncate_last_folio(struct address_space *mapping, loff_t from, -+ loff_t to); - - /* inode.c */ - extern struct workqueue_struct *nfsiod_workqueue; -@@ -531,6 +533,16 @@ static inline bool nfs_file_io_is_buffer - return test_bit(NFS_INO_ODIRECT, &nfsi->flags) == 0; - } - -+/* Must be called with exclusively locked inode->i_rwsem */ -+static inline void nfs_file_block_o_direct(struct nfs_inode *nfsi) -+{ -+ if (test_bit(NFS_INO_ODIRECT, &nfsi->flags)) { -+ clear_bit(NFS_INO_ODIRECT, &nfsi->flags); -+ inode_dio_wait(&nfsi->vfs_inode); -+ } -+} -+ -+ - /* namespace.c */ - #define NFS_PATH_CANONICAL 1 - extern char *nfs_path(char **p, struct dentry *dentry, -@@ -671,9 +683,12 @@ nfs_write_match_verf(const struct nfs_wr - - static inline gfp_t nfs_io_gfp_mask(void) - { -- if (current->flags & PF_WQ_WORKER) -- return GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN; -- return GFP_KERNEL; -+ gfp_t ret = current_gfp_context(GFP_KERNEL); -+ -+ /* For workers __GFP_NORETRY only with __GFP_IO or __GFP_FS */ -+ if ((current->flags & PF_WQ_WORKER) && ret == GFP_KERNEL) -+ ret |= __GFP_NORETRY | __GFP_NOWARN; -+ return ret; - } - - /* -diff -purNx .git BPI-Router-Linux-kernel/fs/nfs/io.c BPI-Router-Linux-kernel-6.16.12/fs/nfs/io.c ---- BPI-Router-Linux-kernel/fs/nfs/io.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfs/io.c 2025-10-22 13:53:56.723168138 -0400 -@@ -14,15 +14,6 @@ - - #include "internal.h" - --/* Call with exclusively locked inode->i_rwsem */ --static void nfs_block_o_direct(struct nfs_inode *nfsi, struct inode *inode) --{ -- if (test_bit(NFS_INO_ODIRECT, &nfsi->flags)) { -- clear_bit(NFS_INO_ODIRECT, &nfsi->flags); -- inode_dio_wait(inode); -- } --} -- - /** - * nfs_start_io_read - declare the file is being used for buffered reads - * @inode: file inode -@@ -57,7 +48,7 @@ nfs_start_io_read(struct inode *inode) - err = down_write_killable(&inode->i_rwsem); - if (err) - return err; -- nfs_block_o_direct(nfsi, inode); -+ nfs_file_block_o_direct(nfsi); - downgrade_write(&inode->i_rwsem); - - return 0; -@@ -90,7 +81,7 @@ nfs_start_io_write(struct inode *inode) - - err = down_write_killable(&inode->i_rwsem); - if (!err) -- nfs_block_o_direct(NFS_I(inode), inode); -+ nfs_file_block_o_direct(NFS_I(inode)); - return err; - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/nfs/localio.c BPI-Router-Linux-kernel-6.16.12/fs/nfs/localio.c ---- BPI-Router-Linux-kernel/fs/nfs/localio.c 2025-10-22 13:53:23.527327632 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfs/localio.c 2025-10-22 13:53:56.723168138 -0400 -@@ -453,12 +453,13 @@ static void nfs_local_call_read(struct w - nfs_local_iter_init(&iter, iocb, READ); - - status = filp->f_op->read_iter(&iocb->kiocb, &iter); -+ -+ revert_creds(save_cred); -+ - if (status != -EIOCBQUEUED) { - nfs_local_read_done(iocb, status); - nfs_local_pgio_release(iocb); - } -- -- revert_creds(save_cred); - } - - static int -@@ -649,14 +650,15 @@ static void nfs_local_call_write(struct - file_start_write(filp); - status = filp->f_op->write_iter(&iocb->kiocb, &iter); - file_end_write(filp); -+ -+ revert_creds(save_cred); -+ current->flags = old_flags; -+ - if (status != -EIOCBQUEUED) { - nfs_local_write_done(iocb, status); - nfs_local_vfs_getattr(iocb); - nfs_local_pgio_release(iocb); - } -- -- revert_creds(save_cred); -- current->flags = old_flags; - } - - static int -diff -purNx .git BPI-Router-Linux-kernel/fs/nfs/nfs42proc.c BPI-Router-Linux-kernel-6.16.12/fs/nfs/nfs42proc.c ---- BPI-Router-Linux-kernel/fs/nfs/nfs42proc.c 2025-10-22 13:53:23.531327613 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfs/nfs42proc.c 2025-10-22 13:53:56.723168138 -0400 -@@ -114,6 +114,7 @@ static int nfs42_proc_fallocate(struct r - exception.inode = inode; - exception.state = lock->open_context->state; - -+ nfs_file_block_o_direct(NFS_I(inode)); - err = nfs_sync_inode(inode); - if (err) - goto out; -@@ -137,6 +138,7 @@ int nfs42_proc_allocate(struct file *fil - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ALLOCATE], - }; - struct inode *inode = file_inode(filep); -+ loff_t oldsize = i_size_read(inode); - int err; - - if (!nfs_server_capable(inode, NFS_CAP_ALLOCATE)) -@@ -145,7 +147,11 @@ int nfs42_proc_allocate(struct file *fil - inode_lock(inode); - - err = nfs42_proc_fallocate(&msg, filep, offset, len); -- if (err == -EOPNOTSUPP) -+ -+ if (err == 0) -+ nfs_truncate_last_folio(inode->i_mapping, oldsize, -+ offset + len); -+ else if (err == -EOPNOTSUPP) - NFS_SERVER(inode)->caps &= ~(NFS_CAP_ALLOCATE | - NFS_CAP_ZERO_RANGE); - -@@ -183,6 +189,7 @@ int nfs42_proc_zero_range(struct file *f - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ZERO_RANGE], - }; - struct inode *inode = file_inode(filep); -+ loff_t oldsize = i_size_read(inode); - int err; - - if (!nfs_server_capable(inode, NFS_CAP_ZERO_RANGE)) -@@ -191,9 +198,11 @@ int nfs42_proc_zero_range(struct file *f - inode_lock(inode); - - err = nfs42_proc_fallocate(&msg, filep, offset, len); -- if (err == 0) -+ if (err == 0) { -+ nfs_truncate_last_folio(inode->i_mapping, oldsize, -+ offset + len); - truncate_pagecache_range(inode, offset, (offset + len) -1); -- if (err == -EOPNOTSUPP) -+ } else if (err == -EOPNOTSUPP) - NFS_SERVER(inode)->caps &= ~NFS_CAP_ZERO_RANGE; - - inode_unlock(inode); -@@ -354,22 +363,27 @@ out: - - /** - * nfs42_copy_dest_done - perform inode cache updates after clone/copy offload -- * @inode: pointer to destination inode -+ * @file: pointer to destination file - * @pos: destination offset - * @len: copy length -+ * @oldsize: length of the file prior to clone/copy - * - * Punch a hole in the inode page cache, so that the NFS client will - * know to retrieve new data. - * Update the file size if necessary, and then mark the inode as having - * invalid cached values for change attribute, ctime, mtime and space used. - */ --static void nfs42_copy_dest_done(struct inode *inode, loff_t pos, loff_t len) -+static void nfs42_copy_dest_done(struct file *file, loff_t pos, loff_t len, -+ loff_t oldsize) - { -+ struct inode *inode = file_inode(file); -+ struct address_space *mapping = file->f_mapping; - loff_t newsize = pos + len; - loff_t end = newsize - 1; - -- WARN_ON_ONCE(invalidate_inode_pages2_range(inode->i_mapping, -- pos >> PAGE_SHIFT, end >> PAGE_SHIFT)); -+ nfs_truncate_last_folio(mapping, oldsize, pos); -+ WARN_ON_ONCE(invalidate_inode_pages2_range(mapping, pos >> PAGE_SHIFT, -+ end >> PAGE_SHIFT)); - - spin_lock(&inode->i_lock); - if (newsize > i_size_read(inode)) -@@ -402,6 +416,7 @@ static ssize_t _nfs42_proc_copy(struct f - struct nfs_server *src_server = NFS_SERVER(src_inode); - loff_t pos_src = args->src_pos; - loff_t pos_dst = args->dst_pos; -+ loff_t oldsize_dst = i_size_read(dst_inode); - size_t count = args->count; - ssize_t status; - -@@ -430,6 +445,7 @@ static ssize_t _nfs42_proc_copy(struct f - return status; - } - -+ nfs_file_block_o_direct(NFS_I(dst_inode)); - status = nfs_sync_inode(dst_inode); - if (status) - return status; -@@ -475,7 +491,7 @@ static ssize_t _nfs42_proc_copy(struct f - goto out; - } - -- nfs42_copy_dest_done(dst_inode, pos_dst, res->write_res.count); -+ nfs42_copy_dest_done(dst, pos_dst, res->write_res.count, oldsize_dst); - nfs_invalidate_atime(src_inode); - status = res->write_res.count; - out: -@@ -1242,6 +1258,7 @@ static int _nfs42_proc_clone(struct rpc_ - struct nfs42_clone_res res = { - .server = server, - }; -+ loff_t oldsize_dst = i_size_read(dst_inode); - int status; - - msg->rpc_argp = &args; -@@ -1276,7 +1293,7 @@ static int _nfs42_proc_clone(struct rpc_ - /* a zero-length count means clone to EOF in src */ - if (count == 0 && res.dst_fattr->valid & NFS_ATTR_FATTR_SIZE) - count = nfs_size_to_loff_t(res.dst_fattr->size) - dst_offset; -- nfs42_copy_dest_done(dst_inode, dst_offset, count); -+ nfs42_copy_dest_done(dst_f, dst_offset, count, oldsize_dst); - status = nfs_post_op_update_inode(dst_inode, res.dst_fattr); - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/nfs/nfs4client.c BPI-Router-Linux-kernel-6.16.12/fs/nfs/nfs4client.c ---- BPI-Router-Linux-kernel/fs/nfs/nfs4client.c 2025-10-22 13:53:23.531327613 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfs/nfs4client.c 2025-10-22 13:53:56.723168138 -0400 -@@ -1088,24 +1088,6 @@ static void nfs4_session_limit_xasize(st - #endif - } - --void nfs4_server_set_init_caps(struct nfs_server *server) --{ -- /* Set the basic capabilities */ -- server->caps |= server->nfs_client->cl_mvops->init_caps; -- if (server->flags & NFS_MOUNT_NORDIRPLUS) -- server->caps &= ~NFS_CAP_READDIRPLUS; -- if (server->nfs_client->cl_proto == XPRT_TRANSPORT_RDMA) -- server->caps &= ~NFS_CAP_READ_PLUS; -- -- /* -- * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower -- * authentication. -- */ -- if (nfs4_disable_idmapping && -- server->client->cl_auth->au_flavor == RPC_AUTH_UNIX) -- server->caps |= NFS_CAP_UIDGID_NOMAP; --} -- - static int nfs4_server_common_setup(struct nfs_server *server, - struct nfs_fh *mntfh, bool auth_probe) - { -@@ -1120,7 +1102,7 @@ static int nfs4_server_common_setup(stru - if (error < 0) - goto out; - -- nfs4_server_set_init_caps(server); -+ nfs_server_set_init_caps(server); - - /* Probe the root fh to retrieve its FSID and filehandle */ - error = nfs4_get_rootfh(server, mntfh, auth_probe); -diff -purNx .git BPI-Router-Linux-kernel/fs/nfs/nfs4file.c BPI-Router-Linux-kernel-6.16.12/fs/nfs/nfs4file.c ---- BPI-Router-Linux-kernel/fs/nfs/nfs4file.c 2025-10-22 13:53:23.531327613 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfs/nfs4file.c 2025-10-22 13:53:56.723168138 -0400 -@@ -291,9 +291,11 @@ static loff_t nfs42_remap_file_range(str - - /* flush all pending writes on both src and dst so that server - * has the latest data */ -+ nfs_file_block_o_direct(NFS_I(src_inode)); - ret = nfs_sync_inode(src_inode); - if (ret) - goto out_unlock; -+ nfs_file_block_o_direct(NFS_I(dst_inode)); - ret = nfs_sync_inode(dst_inode); - if (ret) - goto out_unlock; -diff -purNx .git BPI-Router-Linux-kernel/fs/nfs/nfs4proc.c BPI-Router-Linux-kernel-6.16.12/fs/nfs/nfs4proc.c ---- BPI-Router-Linux-kernel/fs/nfs/nfs4proc.c 2025-10-22 13:53:23.531327613 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfs/nfs4proc.c 2025-10-22 13:53:56.727168119 -0400 -@@ -4007,8 +4007,10 @@ static int _nfs4_server_capabilities(str - res.attr_bitmask[2]; - } - memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask)); -- server->caps &= ~(NFS_CAP_ACLS | NFS_CAP_HARDLINKS | -- NFS_CAP_SYMLINKS| NFS_CAP_SECURITY_LABEL); -+ server->caps &= -+ ~(NFS_CAP_ACLS | NFS_CAP_HARDLINKS | NFS_CAP_SYMLINKS | -+ NFS_CAP_SECURITY_LABEL | NFS_CAP_FS_LOCATIONS | -+ NFS_CAP_OPEN_XOR | NFS_CAP_DELEGTIME); - server->fattr_valid = NFS_ATTR_FATTR_V4; - if (res.attr_bitmask[0] & FATTR4_WORD0_ACL && - res.acl_bitmask & ACL4_SUPPORT_ALLOW_ACL) -@@ -4082,7 +4084,6 @@ int nfs4_server_capabilities(struct nfs_ - }; - int err; - -- nfs4_server_set_init_caps(server); - do { - err = nfs4_handle_exception(server, - _nfs4_server_capabilities(server, fhandle), -@@ -10867,7 +10868,7 @@ const struct nfs4_minor_version_ops *nfs - - static ssize_t nfs4_listxattr(struct dentry *dentry, char *list, size_t size) - { -- ssize_t error, error2, error3, error4; -+ ssize_t error, error2, error3, error4 = 0; - size_t left = size; - - error = generic_listxattr(dentry, list, left); -@@ -10895,9 +10896,11 @@ static ssize_t nfs4_listxattr(struct den - left -= error3; - } - -- error4 = security_inode_listsecurity(d_inode(dentry), list, left); -- if (error4 < 0) -- return error4; -+ if (!nfs_server_capable(d_inode(dentry), NFS_CAP_SECURITY_LABEL)) { -+ error4 = security_inode_listsecurity(d_inode(dentry), list, left); -+ if (error4 < 0) -+ return error4; -+ } - - error += error2 + error3 + error4; - if (size && error > size) -diff -purNx .git BPI-Router-Linux-kernel/fs/nfs/nfstrace.h BPI-Router-Linux-kernel-6.16.12/fs/nfs/nfstrace.h ---- BPI-Router-Linux-kernel/fs/nfs/nfstrace.h 2025-10-22 13:53:23.531327613 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfs/nfstrace.h 2025-10-22 13:53:56.727168119 -0400 -@@ -267,6 +267,7 @@ DECLARE_EVENT_CLASS(nfs_update_size_clas - TP_ARGS(inode, new_size)) - - DEFINE_NFS_UPDATE_SIZE_EVENT(truncate); -+DEFINE_NFS_UPDATE_SIZE_EVENT(truncate_folio); - DEFINE_NFS_UPDATE_SIZE_EVENT(wcc); - DEFINE_NFS_UPDATE_SIZE_EVENT(update); - DEFINE_NFS_UPDATE_SIZE_EVENT(grow); -diff -purNx .git BPI-Router-Linux-kernel/fs/nfs/pagelist.c BPI-Router-Linux-kernel-6.16.12/fs/nfs/pagelist.c ---- BPI-Router-Linux-kernel/fs/nfs/pagelist.c 2025-10-22 13:53:23.531327613 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfs/pagelist.c 2025-10-22 13:53:56.727168119 -0400 -@@ -253,13 +253,14 @@ nfs_page_group_unlock(struct nfs_page *r - nfs_page_clear_headlock(req); - } - --/* -- * nfs_page_group_sync_on_bit_locked -+/** -+ * nfs_page_group_sync_on_bit_locked - Test if all requests have @bit set -+ * @req: request in page group -+ * @bit: PG_* bit that is used to sync page group - * - * must be called with page group lock held - */ --static bool --nfs_page_group_sync_on_bit_locked(struct nfs_page *req, unsigned int bit) -+bool nfs_page_group_sync_on_bit_locked(struct nfs_page *req, unsigned int bit) - { - struct nfs_page *head = req->wb_head; - struct nfs_page *tmp; -diff -purNx .git BPI-Router-Linux-kernel/fs/nfs/pnfs.c BPI-Router-Linux-kernel-6.16.12/fs/nfs/pnfs.c ---- BPI-Router-Linux-kernel/fs/nfs/pnfs.c 2025-10-22 13:53:23.531327613 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfs/pnfs.c 2025-10-22 13:53:56.727168119 -0400 -@@ -2059,8 +2059,10 @@ static void nfs_layoutget_begin(struct p - static void nfs_layoutget_end(struct pnfs_layout_hdr *lo) - { - if (atomic_dec_and_test(&lo->plh_outstanding) && -- test_and_clear_bit(NFS_LAYOUT_DRAIN, &lo->plh_flags)) -+ test_and_clear_bit(NFS_LAYOUT_DRAIN, &lo->plh_flags)) { -+ smp_mb__after_atomic(); - wake_up_bit(&lo->plh_flags, NFS_LAYOUT_DRAIN); -+ } - } - - static bool pnfs_is_first_layoutget(struct pnfs_layout_hdr *lo) -@@ -3338,6 +3340,7 @@ pnfs_layoutcommit_inode(struct inode *in - struct nfs_inode *nfsi = NFS_I(inode); - loff_t end_pos; - int status; -+ bool mark_as_dirty = false; - - if (!pnfs_layoutcommit_outstanding(inode)) - return 0; -@@ -3389,19 +3392,23 @@ pnfs_layoutcommit_inode(struct inode *in - if (ld->prepare_layoutcommit) { - status = ld->prepare_layoutcommit(&data->args); - if (status) { -- put_cred(data->cred); -+ if (status != -ENOSPC) -+ put_cred(data->cred); - spin_lock(&inode->i_lock); - set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags); - if (end_pos > nfsi->layout->plh_lwb) - nfsi->layout->plh_lwb = end_pos; -- goto out_unlock; -+ if (status != -ENOSPC) -+ goto out_unlock; -+ spin_unlock(&inode->i_lock); -+ mark_as_dirty = true; - } - } - - - status = nfs4_proc_layoutcommit(data, sync); - out: -- if (status) -+ if (status || mark_as_dirty) - mark_inode_dirty_sync(inode); - dprintk("<-- %s status %d\n", __func__, status); - return status; -diff -purNx .git BPI-Router-Linux-kernel/fs/nfs/write.c BPI-Router-Linux-kernel-6.16.12/fs/nfs/write.c ---- BPI-Router-Linux-kernel/fs/nfs/write.c 2025-10-22 13:53:23.531327613 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfs/write.c 2025-10-22 13:53:56.727168119 -0400 -@@ -153,20 +153,10 @@ nfs_page_set_inode_ref(struct nfs_page * - } - } - --static int --nfs_cancel_remove_inode(struct nfs_page *req, struct inode *inode) -+static void nfs_cancel_remove_inode(struct nfs_page *req, struct inode *inode) - { -- int ret; -- -- if (!test_bit(PG_REMOVE, &req->wb_flags)) -- return 0; -- ret = nfs_page_group_lock(req); -- if (ret) -- return ret; - if (test_and_clear_bit(PG_REMOVE, &req->wb_flags)) - nfs_page_set_inode_ref(req, inode); -- nfs_page_group_unlock(req); -- return 0; - } - - /** -@@ -585,19 +575,18 @@ retry: - } - } - -+ ret = nfs_page_group_lock(head); -+ if (ret < 0) -+ goto out_unlock; -+ - /* Ensure that nobody removed the request before we locked it */ - if (head != folio->private) { -+ nfs_page_group_unlock(head); - nfs_unlock_and_release_request(head); - goto retry; - } - -- ret = nfs_cancel_remove_inode(head, inode); -- if (ret < 0) -- goto out_unlock; -- -- ret = nfs_page_group_lock(head); -- if (ret < 0) -- goto out_unlock; -+ nfs_cancel_remove_inode(head, inode); - - /* lock each request in the page group */ - for (subreq = head->wb_this_page; -@@ -786,7 +775,8 @@ static void nfs_inode_remove_request(str - { - struct nfs_inode *nfsi = NFS_I(nfs_page_to_inode(req)); - -- if (nfs_page_group_sync_on_bit(req, PG_REMOVE)) { -+ nfs_page_group_lock(req); -+ if (nfs_page_group_sync_on_bit_locked(req, PG_REMOVE)) { - struct folio *folio = nfs_page_to_folio(req->wb_head); - struct address_space *mapping = folio->mapping; - -@@ -798,6 +788,7 @@ static void nfs_inode_remove_request(str - } - spin_unlock(&mapping->i_private_lock); - } -+ nfs_page_group_unlock(req); - - if (test_and_clear_bit(PG_INODE_REF, &req->wb_flags)) { - atomic_long_dec(&nfsi->nrequests); -@@ -2054,6 +2045,7 @@ int nfs_wb_folio_cancel(struct inode *in - * release it */ - nfs_inode_remove_request(req); - nfs_unlock_and_release_request(req); -+ folio_cancel_dirty(folio); - } - - return ret; -diff -purNx .git BPI-Router-Linux-kernel/fs/nfs_common/nfslocalio.c BPI-Router-Linux-kernel-6.16.12/fs/nfs_common/nfslocalio.c ---- BPI-Router-Linux-kernel/fs/nfs_common/nfslocalio.c 2025-10-22 13:53:23.531327613 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfs_common/nfslocalio.c 2025-10-22 13:53:56.727168119 -0400 -@@ -177,7 +177,7 @@ static bool nfs_uuid_put(nfs_uuid_t *nfs - /* nfs_close_local_fh() is doing the - * close and we must wait. until it unlinks - */ -- wait_var_event_spinlock(nfl, -+ wait_var_event_spinlock(nfs_uuid, - list_first_entry_or_null( - &nfs_uuid->files, - struct nfs_file_localio, -@@ -198,8 +198,7 @@ static bool nfs_uuid_put(nfs_uuid_t *nfs - /* Now we can allow racing nfs_close_local_fh() to - * skip the locking. - */ -- RCU_INIT_POINTER(nfl->nfs_uuid, NULL); -- wake_up_var_locked(&nfl->nfs_uuid, &nfs_uuid->lock); -+ store_release_wake_up(&nfl->nfs_uuid, RCU_INITIALIZER(NULL)); - } - - /* Remove client from nn->local_clients */ -@@ -243,15 +242,20 @@ void nfs_localio_invalidate_clients(stru - } - EXPORT_SYMBOL_GPL(nfs_localio_invalidate_clients); - --static void nfs_uuid_add_file(nfs_uuid_t *nfs_uuid, struct nfs_file_localio *nfl) -+static int nfs_uuid_add_file(nfs_uuid_t *nfs_uuid, struct nfs_file_localio *nfl) - { -+ int ret = 0; -+ - /* Add nfl to nfs_uuid->files if it isn't already */ - spin_lock(&nfs_uuid->lock); -- if (list_empty(&nfl->list)) { -+ if (rcu_access_pointer(nfs_uuid->net) == NULL) { -+ ret = -ENXIO; -+ } else if (list_empty(&nfl->list)) { - rcu_assign_pointer(nfl->nfs_uuid, nfs_uuid); - list_add_tail(&nfl->list, &nfs_uuid->files); - } - spin_unlock(&nfs_uuid->lock); -+ return ret; - } - - /* -@@ -285,11 +289,13 @@ struct nfsd_file *nfs_open_local_fh(nfs_ - } - rcu_read_unlock(); - /* We have an implied reference to net thanks to nfsd_net_try_get */ -- localio = nfs_to->nfsd_open_local_fh(net, uuid->dom, rpc_clnt, -- cred, nfs_fh, pnf, fmode); -+ localio = nfs_to->nfsd_open_local_fh(net, uuid->dom, rpc_clnt, cred, -+ nfs_fh, pnf, fmode); -+ if (!IS_ERR(localio) && nfs_uuid_add_file(uuid, nfl) < 0) { -+ /* Delete the cached file when racing with nfs_uuid_put() */ -+ nfs_to_nfsd_file_put_local(pnf); -+ } - nfs_to_nfsd_net_put(net); -- if (!IS_ERR(localio)) -- nfs_uuid_add_file(uuid, nfl); - - return localio; - } -@@ -314,7 +320,7 @@ void nfs_close_local_fh(struct nfs_file_ - rcu_read_unlock(); - return; - } -- if (list_empty(&nfs_uuid->files)) { -+ if (list_empty(&nfl->list)) { - /* nfs_uuid_put() has started closing files, wait for it - * to finished - */ -@@ -338,7 +344,7 @@ void nfs_close_local_fh(struct nfs_file_ - */ - spin_lock(&nfs_uuid->lock); - list_del_init(&nfl->list); -- wake_up_var_locked(&nfl->nfs_uuid, &nfs_uuid->lock); -+ wake_up_var_locked(nfs_uuid, &nfs_uuid->lock); - spin_unlock(&nfs_uuid->lock); - } - EXPORT_SYMBOL_GPL(nfs_close_local_fh); -diff -purNx .git BPI-Router-Linux-kernel/fs/nfsd/localio.c BPI-Router-Linux-kernel-6.16.12/fs/nfsd/localio.c ---- BPI-Router-Linux-kernel/fs/nfsd/localio.c 2025-10-22 13:53:23.531327613 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfsd/localio.c 2025-10-22 13:53:56.727168119 -0400 -@@ -103,10 +103,11 @@ nfsd_open_local_fh(struct net *net, stru - if (nfsd_file_get(new) == NULL) - goto again; - /* -- * Drop the ref we were going to install and the -- * one we were going to return. -+ * Drop the ref we were going to install (both file and -+ * net) and the one we were going to return (only file). - */ - nfsd_file_put(localio); -+ nfsd_net_put(net); - nfsd_file_put(localio); - localio = new; - } -diff -purNx .git BPI-Router-Linux-kernel/fs/nfsd/nfs4callback.c BPI-Router-Linux-kernel-6.16.12/fs/nfsd/nfs4callback.c ---- BPI-Router-Linux-kernel/fs/nfsd/nfs4callback.c 2025-10-22 13:53:23.531327613 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfsd/nfs4callback.c 2025-10-22 13:53:56.727168119 -0400 -@@ -1409,6 +1409,7 @@ void nfsd41_cb_referring_call(struct nfs - out: - if (!rcl->__nr_referring_calls) { - cb->cb_nr_referring_call_list--; -+ list_del(&rcl->__list); - kfree(rcl); - } - } -diff -purNx .git BPI-Router-Linux-kernel/fs/nfsd/nfs4state.c BPI-Router-Linux-kernel-6.16.12/fs/nfsd/nfs4state.c ---- BPI-Router-Linux-kernel/fs/nfsd/nfs4state.c 2025-10-22 13:53:23.531327613 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfsd/nfs4state.c 2025-10-22 13:53:56.727168119 -0400 -@@ -4697,10 +4697,16 @@ nfsd4_setclientid_confirm(struct svc_rqs - } - status = nfs_ok; - if (conf) { -- old = unconf; -- unhash_client_locked(old); -- nfsd4_change_callback(conf, &unconf->cl_cb_conn); -- } else { -+ if (get_client_locked(conf) == nfs_ok) { -+ old = unconf; -+ unhash_client_locked(old); -+ nfsd4_change_callback(conf, &unconf->cl_cb_conn); -+ } else { -+ conf = NULL; -+ } -+ } -+ -+ if (!conf) { - old = find_confirmed_client_by_name(&unconf->cl_name, nn); - if (old) { - status = nfserr_clid_inuse; -@@ -4717,10 +4723,14 @@ nfsd4_setclientid_confirm(struct svc_rqs - } - trace_nfsd_clid_replaced(&old->cl_clientid); - } -+ status = get_client_locked(unconf); -+ if (status != nfs_ok) { -+ old = NULL; -+ goto out; -+ } - move_to_confirmed(unconf); - conf = unconf; - } -- get_client_locked(conf); - spin_unlock(&nn->client_lock); - if (conf == unconf) - fsnotify_dentry(conf->cl_nfsd_info_dentry, FS_MODIFY); -@@ -6322,6 +6332,20 @@ nfsd4_process_open2(struct svc_rqst *rqs - status = nfs4_check_deleg(cl, open, &dp); - if (status) - goto out; -+ if (dp && nfsd4_is_deleg_cur(open) && -+ (dp->dl_stid.sc_file != fp)) { -+ /* -+ * RFC8881 section 8.2.4 mandates the server to return -+ * NFS4ERR_BAD_STATEID if the selected table entry does -+ * not match the current filehandle. However returning -+ * NFS4ERR_BAD_STATEID in the OPEN can cause the client -+ * to repeatedly retry the operation with the same -+ * stateid, since the stateid itself is valid. To avoid -+ * this situation NFSD returns NFS4ERR_INVAL instead. -+ */ -+ status = nfserr_inval; -+ goto out; -+ } - stp = nfsd4_find_and_lock_existing_open(fp, open); - } else { - open->op_file = NULL; -diff -purNx .git BPI-Router-Linux-kernel/fs/nfsd/nfsctl.c BPI-Router-Linux-kernel-6.16.12/fs/nfsd/nfsctl.c ---- BPI-Router-Linux-kernel/fs/nfsd/nfsctl.c 2025-10-22 13:53:23.531327613 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfsd/nfsctl.c 2025-10-22 13:53:56.727168119 -0400 -@@ -1611,7 +1611,7 @@ out_unlock: - */ - int nfsd_nl_threads_set_doit(struct sk_buff *skb, struct genl_info *info) - { -- int *nthreads, count = 0, nrpools, i, ret = -EOPNOTSUPP, rem; -+ int *nthreads, nrpools = 0, i, ret = -EOPNOTSUPP, rem; - struct net *net = genl_info_net(info); - struct nfsd_net *nn = net_generic(net, nfsd_net_id); - const struct nlattr *attr; -@@ -1623,12 +1623,11 @@ int nfsd_nl_threads_set_doit(struct sk_b - /* count number of SERVER_THREADS values */ - nlmsg_for_each_attr(attr, info->nlhdr, GENL_HDRLEN, rem) { - if (nla_type(attr) == NFSD_A_SERVER_THREADS) -- count++; -+ nrpools++; - } - - mutex_lock(&nfsd_mutex); - -- nrpools = max(count, nfsd_nrpools(net)); - nthreads = kcalloc(nrpools, sizeof(int), GFP_KERNEL); - if (!nthreads) { - ret = -ENOMEM; -diff -purNx .git BPI-Router-Linux-kernel/fs/nfsd/vfs.c BPI-Router-Linux-kernel-6.16.12/fs/nfsd/vfs.c ---- BPI-Router-Linux-kernel/fs/nfsd/vfs.c 2025-10-22 13:53:23.531327613 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nfsd/vfs.c 2025-10-22 13:53:56.727168119 -0400 -@@ -470,7 +470,15 @@ static int __nfsd_setattr(struct dentry - if (!iap->ia_valid) - return 0; - -- iap->ia_valid |= ATTR_CTIME; -+ /* -+ * If ATTR_DELEG is set, then this is an update from a client that -+ * holds a delegation. If this is an update for only the atime, the -+ * ctime should not be changed. If the update contains the mtime -+ * too, then ATTR_CTIME should already be set. -+ */ -+ if (!(iap->ia_valid & ATTR_DELEG)) -+ iap->ia_valid |= ATTR_CTIME; -+ - return notify_change(&nop_mnt_idmap, dentry, iap, NULL); - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/nilfs2/inode.c BPI-Router-Linux-kernel-6.16.12/fs/nilfs2/inode.c ---- BPI-Router-Linux-kernel/fs/nilfs2/inode.c 2025-10-22 13:53:23.531327613 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nilfs2/inode.c 2025-10-22 13:53:56.727168119 -0400 -@@ -472,11 +472,18 @@ static int __nilfs_read_inode(struct sup - inode->i_op = &nilfs_symlink_inode_operations; - inode_nohighmem(inode); - inode->i_mapping->a_ops = &nilfs_aops; -- } else { -+ } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || -+ S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { - inode->i_op = &nilfs_special_inode_operations; - init_special_inode( - inode, inode->i_mode, - huge_decode_dev(le64_to_cpu(raw_inode->i_device_code))); -+ } else { -+ nilfs_error(sb, -+ "invalid file type bits in mode 0%o for inode %lu", -+ inode->i_mode, ino); -+ err = -EIO; -+ goto failed_unmap; - } - nilfs_ifile_unmap_inode(raw_inode); - brelse(bh); -diff -purNx .git BPI-Router-Linux-kernel/fs/nilfs2/sysfs.c BPI-Router-Linux-kernel-6.16.12/fs/nilfs2/sysfs.c ---- BPI-Router-Linux-kernel/fs/nilfs2/sysfs.c 2025-10-22 13:53:23.531327613 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nilfs2/sysfs.c 2025-10-22 13:53:56.727168119 -0400 -@@ -1075,7 +1075,7 @@ void nilfs_sysfs_delete_device_group(str - ************************************************************************/ - - static ssize_t nilfs_feature_revision_show(struct kobject *kobj, -- struct attribute *attr, char *buf) -+ struct kobj_attribute *attr, char *buf) - { - return sysfs_emit(buf, "%d.%d\n", - NILFS_CURRENT_REV, NILFS_MINOR_REV); -@@ -1087,7 +1087,7 @@ static const char features_readme_str[] - "(1) revision\n\tshow current revision of NILFS file system driver.\n"; - - static ssize_t nilfs_feature_README_show(struct kobject *kobj, -- struct attribute *attr, -+ struct kobj_attribute *attr, - char *buf) - { - return sysfs_emit(buf, features_readme_str); -diff -purNx .git BPI-Router-Linux-kernel/fs/nilfs2/sysfs.h BPI-Router-Linux-kernel-6.16.12/fs/nilfs2/sysfs.h ---- BPI-Router-Linux-kernel/fs/nilfs2/sysfs.h 2025-10-22 13:53:23.531327613 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/nilfs2/sysfs.h 2025-10-22 13:53:56.727168119 -0400 -@@ -50,16 +50,16 @@ struct nilfs_sysfs_dev_subgroups { - struct completion sg_segments_kobj_unregister; - }; - --#define NILFS_COMMON_ATTR_STRUCT(name) \ -+#define NILFS_KOBJ_ATTR_STRUCT(name) \ - struct nilfs_##name##_attr { \ - struct attribute attr; \ -- ssize_t (*show)(struct kobject *, struct attribute *, \ -+ ssize_t (*show)(struct kobject *, struct kobj_attribute *, \ - char *); \ -- ssize_t (*store)(struct kobject *, struct attribute *, \ -+ ssize_t (*store)(struct kobject *, struct kobj_attribute *, \ - const char *, size_t); \ - } - --NILFS_COMMON_ATTR_STRUCT(feature); -+NILFS_KOBJ_ATTR_STRUCT(feature); - - #define NILFS_DEV_ATTR_STRUCT(name) \ - struct nilfs_##name##_attr { \ -diff -purNx .git BPI-Router-Linux-kernel/fs/notify/dnotify/dnotify.c BPI-Router-Linux-kernel-6.16.12/fs/notify/dnotify/dnotify.c ---- BPI-Router-Linux-kernel/fs/notify/dnotify/dnotify.c 2025-10-22 13:53:23.531327613 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/notify/dnotify/dnotify.c 2025-10-22 13:53:56.727168119 -0400 -@@ -308,6 +308,10 @@ int fcntl_dirnotify(int fd, struct file - goto out_err; - } - -+ error = file_f_owner_allocate(filp); -+ if (error) -+ goto out_err; -+ - /* new fsnotify mark, we expect most fcntl calls to add a new mark */ - new_dn_mark = kmem_cache_alloc(dnotify_mark_cache, GFP_KERNEL); - if (!new_dn_mark) { -@@ -315,10 +319,6 @@ int fcntl_dirnotify(int fd, struct file - goto out_err; - } - -- error = file_f_owner_allocate(filp); -- if (error) -- goto out_err; -- - /* set up the new_fsn_mark and new_dn_mark */ - new_fsn_mark = &new_dn_mark->fsn_mark; - fsnotify_init_mark(new_fsn_mark, dnotify_group); -diff -purNx .git BPI-Router-Linux-kernel/fs/notify/fanotify/fanotify.c BPI-Router-Linux-kernel-6.16.12/fs/notify/fanotify/fanotify.c ---- BPI-Router-Linux-kernel/fs/notify/fanotify/fanotify.c 2025-10-22 13:53:23.531327613 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/notify/fanotify/fanotify.c 2025-10-22 13:53:56.727168119 -0400 -@@ -454,7 +454,13 @@ static int fanotify_encode_fh(struct fan - dwords = fh_len >> 2; - type = exportfs_encode_fid(inode, buf, &dwords); - err = -EINVAL; -- if (type <= 0 || type == FILEID_INVALID || fh_len != dwords << 2) -+ /* -+ * Unlike file_handle, type and len of struct fanotify_fh are u8. -+ * Traditionally, filesystem return handle_type < 0xff, but there -+ * is no enforecement for that in vfs. -+ */ -+ BUILD_BUG_ON(MAX_HANDLE_SZ > 0xff || FILEID_INVALID > 0xff); -+ if (type <= 0 || type >= FILEID_INVALID || fh_len != dwords << 2) - goto out_err; - - fh->type = type; -diff -purNx .git BPI-Router-Linux-kernel/fs/ntfs3/dir.c BPI-Router-Linux-kernel-6.16.12/fs/ntfs3/dir.c ---- BPI-Router-Linux-kernel/fs/ntfs3/dir.c 2025-10-22 13:53:23.531327613 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ntfs3/dir.c 2025-10-22 13:53:56.727168119 -0400 -@@ -304,6 +304,9 @@ static inline bool ntfs_dir_emit(struct - if (sbi->options->nohidden && (fname->dup.fa & FILE_ATTRIBUTE_HIDDEN)) - return true; - -+ if (fname->name_len + sizeof(struct NTFS_DE) > le16_to_cpu(e->size)) -+ return true; -+ - name_len = ntfs_utf16_to_nls(sbi, fname->name, fname->name_len, name, - PATH_MAX); - if (name_len <= 0) { -diff -purNx .git BPI-Router-Linux-kernel/fs/ntfs3/file.c BPI-Router-Linux-kernel-6.16.12/fs/ntfs3/file.c ---- BPI-Router-Linux-kernel/fs/ntfs3/file.c 2025-10-22 13:53:23.531327613 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ntfs3/file.c 2025-10-22 13:53:56.727168119 -0400 -@@ -310,7 +310,10 @@ static int ntfs_file_mmap(struct file *f - } - - if (ni->i_valid < to) { -- inode_lock(inode); -+ if (!inode_trylock(inode)) { -+ err = -EAGAIN; -+ goto out; -+ } - err = ntfs_extend_initialized_size(file, ni, - ni->i_valid, to); - inode_unlock(inode); -diff -purNx .git BPI-Router-Linux-kernel/fs/ntfs3/frecord.c BPI-Router-Linux-kernel-6.16.12/fs/ntfs3/frecord.c ---- BPI-Router-Linux-kernel/fs/ntfs3/frecord.c 2025-10-22 13:53:23.531327613 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ntfs3/frecord.c 2025-10-22 13:53:56.727168119 -0400 -@@ -3003,8 +3003,7 @@ int ni_add_name(struct ntfs_inode *dir_n - * ni_rename - Remove one name and insert new name. - */ - int ni_rename(struct ntfs_inode *dir_ni, struct ntfs_inode *new_dir_ni, -- struct ntfs_inode *ni, struct NTFS_DE *de, struct NTFS_DE *new_de, -- bool *is_bad) -+ struct ntfs_inode *ni, struct NTFS_DE *de, struct NTFS_DE *new_de) - { - int err; - struct NTFS_DE *de2 = NULL; -@@ -3027,8 +3026,8 @@ int ni_rename(struct ntfs_inode *dir_ni, - err = ni_add_name(new_dir_ni, ni, new_de); - if (!err) { - err = ni_remove_name(dir_ni, ni, de, &de2, &undo); -- if (err && ni_remove_name(new_dir_ni, ni, new_de, &de2, &undo)) -- *is_bad = true; -+ WARN_ON(err && ni_remove_name(new_dir_ni, ni, new_de, &de2, -+ &undo)); - } - - /* -diff -purNx .git BPI-Router-Linux-kernel/fs/ntfs3/inode.c BPI-Router-Linux-kernel-6.16.12/fs/ntfs3/inode.c ---- BPI-Router-Linux-kernel/fs/ntfs3/inode.c 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ntfs3/inode.c 2025-10-22 13:53:56.727168119 -0400 -@@ -1062,10 +1062,10 @@ int inode_read_data(struct inode *inode, - * Number of bytes for REPARSE_DATA_BUFFER(IO_REPARSE_TAG_SYMLINK) - * for unicode string of @uni_len length. - */ --static inline u32 ntfs_reparse_bytes(u32 uni_len) -+static inline u32 ntfs_reparse_bytes(u32 uni_len, bool is_absolute) - { - /* Header + unicode string + decorated unicode string. */ -- return sizeof(short) * (2 * uni_len + 4) + -+ return sizeof(short) * (2 * uni_len + (is_absolute ? 4 : 0)) + - offsetof(struct REPARSE_DATA_BUFFER, - SymbolicLinkReparseBuffer.PathBuffer); - } -@@ -1078,8 +1078,11 @@ ntfs_create_reparse_buffer(struct ntfs_s - struct REPARSE_DATA_BUFFER *rp; - __le16 *rp_name; - typeof(rp->SymbolicLinkReparseBuffer) *rs; -+ bool is_absolute; - -- rp = kzalloc(ntfs_reparse_bytes(2 * size + 2), GFP_NOFS); -+ is_absolute = (strlen(symname) > 1 && symname[1] == ':'); -+ -+ rp = kzalloc(ntfs_reparse_bytes(2 * size + 2, is_absolute), GFP_NOFS); - if (!rp) - return ERR_PTR(-ENOMEM); - -@@ -1094,7 +1097,7 @@ ntfs_create_reparse_buffer(struct ntfs_s - goto out; - - /* err = the length of unicode name of symlink. */ -- *nsize = ntfs_reparse_bytes(err); -+ *nsize = ntfs_reparse_bytes(err, is_absolute); - - if (*nsize > sbi->reparse.max_size) { - err = -EFBIG; -@@ -1114,7 +1117,7 @@ ntfs_create_reparse_buffer(struct ntfs_s - - /* PrintName + SubstituteName. */ - rs->SubstituteNameOffset = cpu_to_le16(sizeof(short) * err); -- rs->SubstituteNameLength = cpu_to_le16(sizeof(short) * err + 8); -+ rs->SubstituteNameLength = cpu_to_le16(sizeof(short) * err + (is_absolute ? 8 : 0)); - rs->PrintNameLength = rs->SubstituteNameOffset; - - /* -@@ -1122,16 +1125,18 @@ ntfs_create_reparse_buffer(struct ntfs_s - * parse this path. - * 0-absolute path 1- relative path (SYMLINK_FLAG_RELATIVE). - */ -- rs->Flags = 0; -+ rs->Flags = cpu_to_le32(is_absolute ? 0 : SYMLINK_FLAG_RELATIVE); - -- memmove(rp_name + err + 4, rp_name, sizeof(short) * err); -+ memmove(rp_name + err + (is_absolute ? 4 : 0), rp_name, sizeof(short) * err); - -- /* Decorate SubstituteName. */ -- rp_name += err; -- rp_name[0] = cpu_to_le16('\\'); -- rp_name[1] = cpu_to_le16('?'); -- rp_name[2] = cpu_to_le16('?'); -- rp_name[3] = cpu_to_le16('\\'); -+ if (is_absolute) { -+ /* Decorate SubstituteName. */ -+ rp_name += err; -+ rp_name[0] = cpu_to_le16('\\'); -+ rp_name[1] = cpu_to_le16('?'); -+ rp_name[2] = cpu_to_le16('?'); -+ rp_name[3] = cpu_to_le16('\\'); -+ } - - return rp; - out: -diff -purNx .git BPI-Router-Linux-kernel/fs/ntfs3/namei.c BPI-Router-Linux-kernel-6.16.12/fs/ntfs3/namei.c ---- BPI-Router-Linux-kernel/fs/ntfs3/namei.c 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ntfs3/namei.c 2025-10-22 13:53:56.727168119 -0400 -@@ -244,7 +244,7 @@ static int ntfs_rename(struct mnt_idmap - struct ntfs_inode *ni = ntfs_i(inode); - struct inode *new_inode = d_inode(new_dentry); - struct NTFS_DE *de, *new_de; -- bool is_same, is_bad; -+ bool is_same; - /* - * de - memory of PATH_MAX bytes: - * [0-1024) - original name (dentry->d_name) -@@ -313,12 +313,8 @@ static int ntfs_rename(struct mnt_idmap - if (dir_ni != new_dir_ni) - ni_lock_dir2(new_dir_ni); - -- is_bad = false; -- err = ni_rename(dir_ni, new_dir_ni, ni, de, new_de, &is_bad); -- if (is_bad) { -- /* Restore after failed rename failed too. */ -- _ntfs_bad_inode(inode); -- } else if (!err) { -+ err = ni_rename(dir_ni, new_dir_ni, ni, de, new_de); -+ if (!err) { - simple_rename_timestamp(dir, dentry, new_dir, new_dentry); - mark_inode_dirty(inode); - mark_inode_dirty(dir); -diff -purNx .git BPI-Router-Linux-kernel/fs/ntfs3/ntfs_fs.h BPI-Router-Linux-kernel-6.16.12/fs/ntfs3/ntfs_fs.h ---- BPI-Router-Linux-kernel/fs/ntfs3/ntfs_fs.h 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ntfs3/ntfs_fs.h 2025-10-22 13:53:56.727168119 -0400 -@@ -577,8 +577,7 @@ int ni_add_name(struct ntfs_inode *dir_n - struct NTFS_DE *de); - - int ni_rename(struct ntfs_inode *dir_ni, struct ntfs_inode *new_dir_ni, -- struct ntfs_inode *ni, struct NTFS_DE *de, struct NTFS_DE *new_de, -- bool *is_bad); -+ struct ntfs_inode *ni, struct NTFS_DE *de, struct NTFS_DE *new_de); - - bool ni_is_dirty(struct inode *inode); - -diff -purNx .git BPI-Router-Linux-kernel/fs/ocfs2/aops.c BPI-Router-Linux-kernel-6.16.12/fs/ocfs2/aops.c ---- BPI-Router-Linux-kernel/fs/ocfs2/aops.c 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ocfs2/aops.c 2025-10-22 13:53:56.727168119 -0400 -@@ -1071,6 +1071,7 @@ static int ocfs2_grab_folios_for_write(s - if (IS_ERR(wc->w_folios[i])) { - ret = PTR_ERR(wc->w_folios[i]); - mlog_errno(ret); -+ wc->w_folios[i] = NULL; - goto out; - } - } -diff -purNx .git BPI-Router-Linux-kernel/fs/ocfs2/extent_map.c BPI-Router-Linux-kernel-6.16.12/fs/ocfs2/extent_map.c ---- BPI-Router-Linux-kernel/fs/ocfs2/extent_map.c 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ocfs2/extent_map.c 2025-10-22 13:53:56.727168119 -0400 -@@ -706,6 +706,8 @@ out: - * it not only handles the fiemap for inlined files, but also deals - * with the fast symlink, cause they have no difference for extent - * mapping per se. -+ * -+ * Must be called with ip_alloc_sem semaphore held. - */ - static int ocfs2_fiemap_inline(struct inode *inode, struct buffer_head *di_bh, - struct fiemap_extent_info *fieinfo, -@@ -717,6 +719,7 @@ static int ocfs2_fiemap_inline(struct in - u64 phys; - u32 flags = FIEMAP_EXTENT_DATA_INLINE|FIEMAP_EXTENT_LAST; - struct ocfs2_inode_info *oi = OCFS2_I(inode); -+ lockdep_assert_held_read(&oi->ip_alloc_sem); - - di = (struct ocfs2_dinode *)di_bh->b_data; - if (ocfs2_inode_is_fast_symlink(inode)) -@@ -732,8 +735,11 @@ static int ocfs2_fiemap_inline(struct in - phys += offsetof(struct ocfs2_dinode, - id2.i_data.id_data); - -+ /* Release the ip_alloc_sem to prevent deadlock on page fault */ -+ up_read(&OCFS2_I(inode)->ip_alloc_sem); - ret = fiemap_fill_next_extent(fieinfo, 0, phys, id_count, - flags); -+ down_read(&OCFS2_I(inode)->ip_alloc_sem); - if (ret < 0) - return ret; - } -@@ -802,9 +808,11 @@ int ocfs2_fiemap(struct inode *inode, st - len_bytes = (u64)le16_to_cpu(rec.e_leaf_clusters) << osb->s_clustersize_bits; - phys_bytes = le64_to_cpu(rec.e_blkno) << osb->sb->s_blocksize_bits; - virt_bytes = (u64)le32_to_cpu(rec.e_cpos) << osb->s_clustersize_bits; -- -+ /* Release the ip_alloc_sem to prevent deadlock on page fault */ -+ up_read(&OCFS2_I(inode)->ip_alloc_sem); - ret = fiemap_fill_next_extent(fieinfo, virt_bytes, phys_bytes, - len_bytes, fe_flags); -+ down_read(&OCFS2_I(inode)->ip_alloc_sem); - if (ret) - break; - -diff -purNx .git BPI-Router-Linux-kernel/fs/ocfs2/inode.c BPI-Router-Linux-kernel-6.16.12/fs/ocfs2/inode.c ---- BPI-Router-Linux-kernel/fs/ocfs2/inode.c 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ocfs2/inode.c 2025-10-22 13:53:56.727168119 -0400 -@@ -1219,6 +1219,9 @@ static void ocfs2_clear_inode(struct ino - * the journal is flushed before journal shutdown. Thus it is safe to - * have inodes get cleaned up after journal shutdown. - */ -+ if (!osb->journal) -+ return; -+ - jbd2_journal_release_jbd_inode(osb->journal->j_journal, - &oi->ip_jinode); - } -diff -purNx .git BPI-Router-Linux-kernel/fs/orangefs/orangefs-debugfs.c BPI-Router-Linux-kernel-6.16.12/fs/orangefs/orangefs-debugfs.c ---- BPI-Router-Linux-kernel/fs/orangefs/orangefs-debugfs.c 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/orangefs/orangefs-debugfs.c 2025-10-22 13:53:56.727168119 -0400 -@@ -396,7 +396,7 @@ static ssize_t orangefs_debug_read(struc - goto out; - - mutex_lock(&orangefs_debug_lock); -- sprintf_ret = sprintf(buf, "%s", (char *)file->private_data); -+ sprintf_ret = scnprintf(buf, ORANGEFS_MAX_DEBUG_STRING_LEN, "%s", (char *)file->private_data); - mutex_unlock(&orangefs_debug_lock); - - read_ret = simple_read_from_buffer(ubuf, count, ppos, buf, sprintf_ret); -@@ -769,8 +769,8 @@ static void do_k_string(void *k_mask, in - - if (*mask & s_kmod_keyword_mask_map[index].mask_val) { - if ((strlen(kernel_debug_string) + -- strlen(s_kmod_keyword_mask_map[index].keyword)) -- < ORANGEFS_MAX_DEBUG_STRING_LEN - 1) { -+ strlen(s_kmod_keyword_mask_map[index].keyword) + 1) -+ < ORANGEFS_MAX_DEBUG_STRING_LEN) { - strcat(kernel_debug_string, - s_kmod_keyword_mask_map[index].keyword); - strcat(kernel_debug_string, ","); -@@ -797,7 +797,7 @@ static void do_c_string(void *c_mask, in - (mask->mask2 & cdm_array[index].mask2)) { - if ((strlen(client_debug_string) + - strlen(cdm_array[index].keyword) + 1) -- < ORANGEFS_MAX_DEBUG_STRING_LEN - 2) { -+ < ORANGEFS_MAX_DEBUG_STRING_LEN) { - strcat(client_debug_string, - cdm_array[index].keyword); - strcat(client_debug_string, ","); -diff -purNx .git BPI-Router-Linux-kernel/fs/overlayfs/copy_up.c BPI-Router-Linux-kernel-6.16.12/fs/overlayfs/copy_up.c ---- BPI-Router-Linux-kernel/fs/overlayfs/copy_up.c 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/overlayfs/copy_up.c 2025-10-22 13:53:56.727168119 -0400 -@@ -779,7 +779,7 @@ static int ovl_copy_up_workdir(struct ov - return err; - - ovl_start_write(c->dentry); -- inode_lock(wdir); -+ inode_lock_nested(wdir, I_MUTEX_PARENT); - temp = ovl_create_temp(ofs, c->workdir, &cattr); - inode_unlock(wdir); - ovl_end_write(c->dentry); -diff -purNx .git BPI-Router-Linux-kernel/fs/overlayfs/namei.c BPI-Router-Linux-kernel-6.16.12/fs/overlayfs/namei.c ---- BPI-Router-Linux-kernel/fs/overlayfs/namei.c 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/overlayfs/namei.c 2025-10-22 13:53:56.731168099 -0400 -@@ -1393,7 +1393,7 @@ out: - bool ovl_lower_positive(struct dentry *dentry) - { - struct ovl_entry *poe = OVL_E(dentry->d_parent); -- struct qstr *name = &dentry->d_name; -+ const struct qstr *name = &dentry->d_name; - const struct cred *old_cred; - unsigned int i; - bool positive = false; -@@ -1416,9 +1416,15 @@ bool ovl_lower_positive(struct dentry *d - struct dentry *this; - struct ovl_path *parentpath = &ovl_lowerstack(poe)[i]; - -+ /* -+ * We need to make a non-const copy of dentry->d_name, -+ * because lookup_one_positive_unlocked() will hash name -+ * with parentpath base, which is on another (lower fs). -+ */ - this = lookup_one_positive_unlocked( - mnt_idmap(parentpath->layer->mnt), -- name, parentpath->dentry); -+ &QSTR_LEN(name->name, name->len), -+ parentpath->dentry); - if (IS_ERR(this)) { - switch (PTR_ERR(this)) { - case -ENOENT: -diff -purNx .git BPI-Router-Linux-kernel/fs/overlayfs/overlayfs.h BPI-Router-Linux-kernel-6.16.12/fs/overlayfs/overlayfs.h ---- BPI-Router-Linux-kernel/fs/overlayfs/overlayfs.h 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/overlayfs/overlayfs.h 2025-10-22 13:53:56.731168099 -0400 -@@ -246,9 +246,11 @@ static inline struct dentry *ovl_do_mkdi - struct dentry *dentry, - umode_t mode) - { -- dentry = vfs_mkdir(ovl_upper_mnt_idmap(ofs), dir, dentry, mode); -- pr_debug("mkdir(%pd2, 0%o) = %i\n", dentry, mode, PTR_ERR_OR_ZERO(dentry)); -- return dentry; -+ struct dentry *ret; -+ -+ ret = vfs_mkdir(ovl_upper_mnt_idmap(ofs), dir, dentry, mode); -+ pr_debug("mkdir(%pd2, 0%o) = %i\n", dentry, mode, PTR_ERR_OR_ZERO(ret)); -+ return ret; - } - - static inline int ovl_do_mknod(struct ovl_fs *ofs, -diff -purNx .git BPI-Router-Linux-kernel/fs/pidfs.c BPI-Router-Linux-kernel-6.16.12/fs/pidfs.c ---- BPI-Router-Linux-kernel/fs/pidfs.c 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/pidfs.c 2025-10-22 13:53:56.731168099 -0400 -@@ -319,7 +319,7 @@ static long pidfd_info(struct file *file - if (!c) - return -ESRCH; - -- if (!(kinfo.mask & PIDFD_INFO_COREDUMP)) { -+ if ((kinfo.mask & PIDFD_INFO_COREDUMP) && !(kinfo.coredump_mask)) { - task_lock(task); - if (task->mm) - kinfo.coredump_mask = pidfs_coredump_mask(task->mm->flags); -@@ -366,7 +366,7 @@ static long pidfd_info(struct file *file - kinfo.pid = task_pid_vnr(task); - kinfo.mask |= PIDFD_INFO_PID; - -- if (kinfo.pid == 0 || kinfo.tgid == 0 || (kinfo.ppid == 0 && kinfo.pid != 1)) -+ if (kinfo.pid == 0 || kinfo.tgid == 0) - return -ESRCH; - - copy_out: -@@ -891,6 +891,8 @@ static int pidfs_init_fs_context(struct - if (!ctx) - return -ENOMEM; - -+ fc->s_iflags |= SB_I_NOEXEC; -+ fc->s_iflags |= SB_I_NODEV; - ctx->ops = &pidfs_sops; - ctx->eops = &pidfs_export_operations; - ctx->dops = &pidfs_dentry_operations; -diff -purNx .git BPI-Router-Linux-kernel/fs/pnode.h BPI-Router-Linux-kernel-6.16.12/fs/pnode.h ---- BPI-Router-Linux-kernel/fs/pnode.h 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/pnode.h 2025-10-22 13:53:56.731168099 -0400 -@@ -28,8 +28,6 @@ - #define CL_SHARED_TO_SLAVE 0x20 - #define CL_COPY_MNT_NS_FILE 0x40 - --#define CL_COPY_ALL (CL_COPY_UNBINDABLE | CL_COPY_MNT_NS_FILE) -- - static inline void set_mnt_shared(struct mount *mnt) - { - mnt->mnt.mnt_flags &= ~MNT_SHARED_MASK; -diff -purNx .git BPI-Router-Linux-kernel/fs/proc/generic.c BPI-Router-Linux-kernel-6.16.12/fs/proc/generic.c ---- BPI-Router-Linux-kernel/fs/proc/generic.c 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/proc/generic.c 2025-10-22 13:53:56.731168099 -0400 -@@ -364,6 +364,25 @@ static const struct inode_operations pro - .setattr = proc_notify_change, - }; - -+static void pde_set_flags(struct proc_dir_entry *pde) -+{ -+ const struct proc_ops *proc_ops = pde->proc_ops; -+ -+ if (!proc_ops) -+ return; -+ -+ if (proc_ops->proc_flags & PROC_ENTRY_PERMANENT) -+ pde->flags |= PROC_ENTRY_PERMANENT; -+ if (proc_ops->proc_read_iter) -+ pde->flags |= PROC_ENTRY_proc_read_iter; -+#ifdef CONFIG_COMPAT -+ if (proc_ops->proc_compat_ioctl) -+ pde->flags |= PROC_ENTRY_proc_compat_ioctl; -+#endif -+ if (proc_ops->proc_lseek) -+ pde->flags |= PROC_ENTRY_proc_lseek; -+} -+ - /* returns the registered entry, or frees dp and returns NULL on failure */ - struct proc_dir_entry *proc_register(struct proc_dir_entry *dir, - struct proc_dir_entry *dp) -@@ -371,6 +390,9 @@ struct proc_dir_entry *proc_register(str - if (proc_alloc_inum(&dp->low_ino)) - goto out_free_entry; - -+ if (!S_ISDIR(dp->mode)) -+ pde_set_flags(dp); -+ - write_lock(&proc_subdir_lock); - dp->parent = dir; - if (pde_subdir_insert(dir, dp) == false) { -@@ -559,18 +581,6 @@ struct proc_dir_entry *proc_create_reg(c - return p; - } - --static void pde_set_flags(struct proc_dir_entry *pde) --{ -- if (pde->proc_ops->proc_flags & PROC_ENTRY_PERMANENT) -- pde->flags |= PROC_ENTRY_PERMANENT; -- if (pde->proc_ops->proc_read_iter) -- pde->flags |= PROC_ENTRY_proc_read_iter; --#ifdef CONFIG_COMPAT -- if (pde->proc_ops->proc_compat_ioctl) -- pde->flags |= PROC_ENTRY_proc_compat_ioctl; --#endif --} -- - struct proc_dir_entry *proc_create_data(const char *name, umode_t mode, - struct proc_dir_entry *parent, - const struct proc_ops *proc_ops, void *data) -@@ -581,7 +591,6 @@ struct proc_dir_entry *proc_create_data( - if (!p) - return NULL; - p->proc_ops = proc_ops; -- pde_set_flags(p); - return proc_register(parent, p); - } - EXPORT_SYMBOL(proc_create_data); -@@ -632,7 +641,6 @@ struct proc_dir_entry *proc_create_seq_p - p->proc_ops = &proc_seq_ops; - p->seq_ops = ops; - p->state_size = state_size; -- pde_set_flags(p); - return proc_register(parent, p); - } - EXPORT_SYMBOL(proc_create_seq_private); -@@ -663,7 +671,6 @@ struct proc_dir_entry *proc_create_singl - return NULL; - p->proc_ops = &proc_single_ops; - p->single_show = show; -- pde_set_flags(p); - return proc_register(parent, p); - } - EXPORT_SYMBOL(proc_create_single_data); -diff -purNx .git BPI-Router-Linux-kernel/fs/proc/inode.c BPI-Router-Linux-kernel-6.16.12/fs/proc/inode.c ---- BPI-Router-Linux-kernel/fs/proc/inode.c 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/proc/inode.c 2025-10-22 13:53:56.731168099 -0400 -@@ -42,7 +42,7 @@ static void proc_evict_inode(struct inod - - head = ei->sysctl; - if (head) { -- RCU_INIT_POINTER(ei->sysctl, NULL); -+ WRITE_ONCE(ei->sysctl, NULL); - proc_sys_evict_inode(inode, head); - } - } -@@ -473,7 +473,7 @@ static int proc_reg_open(struct inode *i - typeof_member(struct proc_ops, proc_open) open; - struct pde_opener *pdeo; - -- if (!pde->proc_ops->proc_lseek) -+ if (!pde_has_proc_lseek(pde)) - file->f_mode &= ~FMODE_LSEEK; - - if (pde_is_permanent(pde)) { -diff -purNx .git BPI-Router-Linux-kernel/fs/proc/internal.h BPI-Router-Linux-kernel-6.16.12/fs/proc/internal.h ---- BPI-Router-Linux-kernel/fs/proc/internal.h 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/proc/internal.h 2025-10-22 13:53:56.731168099 -0400 -@@ -99,6 +99,11 @@ static inline bool pde_has_proc_compat_i - #endif - } - -+static inline bool pde_has_proc_lseek(const struct proc_dir_entry *pde) -+{ -+ return pde->flags & PROC_ENTRY_proc_lseek; -+} -+ - extern struct kmem_cache *proc_dir_entry_cache; - void pde_free(struct proc_dir_entry *pde); - -diff -purNx .git BPI-Router-Linux-kernel/fs/proc/proc_sysctl.c BPI-Router-Linux-kernel-6.16.12/fs/proc/proc_sysctl.c ---- BPI-Router-Linux-kernel/fs/proc/proc_sysctl.c 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/proc/proc_sysctl.c 2025-10-22 13:53:56.731168099 -0400 -@@ -918,17 +918,21 @@ static int proc_sys_compare(const struct - struct ctl_table_header *head; - struct inode *inode; - -- /* Although proc doesn't have negative dentries, rcu-walk means -- * that inode here can be NULL */ -- /* AV: can it, indeed? */ -- inode = d_inode_rcu(dentry); -- if (!inode) -- return 1; - if (name->len != len) - return 1; - if (memcmp(name->name, str, len)) - return 1; -- head = rcu_dereference(PROC_I(inode)->sysctl); -+ -+ // false positive is fine here - we'll recheck anyway -+ if (d_in_lookup(dentry)) -+ return 0; -+ -+ inode = d_inode_rcu(dentry); -+ // we just might have run into dentry in the middle of __dentry_kill() -+ if (!inode) -+ return 1; -+ -+ head = READ_ONCE(PROC_I(inode)->sysctl); - return !head || !sysctl_is_seen(head); - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/proc/task_mmu.c BPI-Router-Linux-kernel-6.16.12/fs/proc/task_mmu.c ---- BPI-Router-Linux-kernel/fs/proc/task_mmu.c 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/proc/task_mmu.c 2025-10-22 13:53:56.731168099 -0400 -@@ -36,9 +36,9 @@ void task_mem(struct seq_file *m, struct - unsigned long text, lib, swap, anon, file, shmem; - unsigned long hiwater_vm, total_vm, hiwater_rss, total_rss; - -- anon = get_mm_counter(mm, MM_ANONPAGES); -- file = get_mm_counter(mm, MM_FILEPAGES); -- shmem = get_mm_counter(mm, MM_SHMEMPAGES); -+ anon = get_mm_counter_sum(mm, MM_ANONPAGES); -+ file = get_mm_counter_sum(mm, MM_FILEPAGES); -+ shmem = get_mm_counter_sum(mm, MM_SHMEMPAGES); - - /* - * Note: to minimize their overhead, mm maintains hiwater_vm and -@@ -59,7 +59,7 @@ void task_mem(struct seq_file *m, struct - text = min(text, mm->exec_vm << PAGE_SHIFT); - lib = (mm->exec_vm << PAGE_SHIFT) - text; - -- swap = get_mm_counter(mm, MM_SWAPENTS); -+ swap = get_mm_counter_sum(mm, MM_SWAPENTS); - SEQ_PUT_DEC("VmPeak:\t", hiwater_vm); - SEQ_PUT_DEC(" kB\nVmSize:\t", total_vm); - SEQ_PUT_DEC(" kB\nVmLck:\t", mm->locked_vm); -@@ -92,12 +92,12 @@ unsigned long task_statm(struct mm_struc - unsigned long *shared, unsigned long *text, - unsigned long *data, unsigned long *resident) - { -- *shared = get_mm_counter(mm, MM_FILEPAGES) + -- get_mm_counter(mm, MM_SHMEMPAGES); -+ *shared = get_mm_counter_sum(mm, MM_FILEPAGES) + -+ get_mm_counter_sum(mm, MM_SHMEMPAGES); - *text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) - >> PAGE_SHIFT; - *data = mm->data_vm + mm->stack_vm; -- *resident = *shared + get_mm_counter(mm, MM_ANONPAGES); -+ *resident = *shared + get_mm_counter_sum(mm, MM_ANONPAGES); - return mm->total_vm; - } - -@@ -212,8 +212,8 @@ static int proc_maps_open(struct inode * - - priv->inode = inode; - priv->mm = proc_mem_open(inode, PTRACE_MODE_READ); -- if (IS_ERR_OR_NULL(priv->mm)) { -- int err = priv->mm ? PTR_ERR(priv->mm) : -ESRCH; -+ if (IS_ERR(priv->mm)) { -+ int err = PTR_ERR(priv->mm); - - seq_release_private(inode, file); - return err; -@@ -1020,10 +1020,13 @@ static int smaps_hugetlb_range(pte_t *pt - { - struct mem_size_stats *mss = walk->private; - struct vm_area_struct *vma = walk->vma; -- pte_t ptent = huge_ptep_get(walk->mm, addr, pte); - struct folio *folio = NULL; - bool present = false; -+ spinlock_t *ptl; -+ pte_t ptent; - -+ ptl = huge_pte_lock(hstate_vma(vma), walk->mm, pte); -+ ptent = huge_ptep_get(walk->mm, addr, pte); - if (pte_present(ptent)) { - folio = page_folio(pte_page(ptent)); - present = true; -@@ -1042,6 +1045,7 @@ static int smaps_hugetlb_range(pte_t *pt - else - mss->private_hugetlb += huge_page_size(hstate_vma(vma)); - } -+ spin_unlock(ptl); - return 0; - } - #else -@@ -2182,7 +2186,7 @@ static unsigned long pagemap_thp_categor - categories |= PAGE_IS_FILE; - } - -- if (is_zero_pfn(pmd_pfn(pmd))) -+ if (is_huge_zero_pmd(pmd)) - categories |= PAGE_IS_PFNZERO; - if (pmd_soft_dirty(pmd)) - categories |= PAGE_IS_SOFT_DIRTY; -@@ -2282,6 +2286,9 @@ static void pagemap_scan_backout_range(s - { - struct page_region *cur_buf = &p->vec_buf[p->vec_buf_index]; - -+ if (!p->vec_buf) -+ return; -+ - if (cur_buf->start != addr) - cur_buf->end = addr; - else -diff -purNx .git BPI-Router-Linux-kernel/fs/resctrl/ctrlmondata.c BPI-Router-Linux-kernel-6.16.12/fs/resctrl/ctrlmondata.c ---- BPI-Router-Linux-kernel/fs/resctrl/ctrlmondata.c 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/resctrl/ctrlmondata.c 2025-10-22 13:53:56.731168099 -0400 -@@ -594,9 +594,10 @@ int rdtgroup_mondata_show(struct seq_fil - struct rmid_read rr = {0}; - struct rdt_mon_domain *d; - struct rdtgroup *rdtgrp; -+ int domid, cpu, ret = 0; - struct rdt_resource *r; -+ struct cacheinfo *ci; - struct mon_data *md; -- int domid, ret = 0; - - rdtgrp = rdtgroup_kn_lock_live(of->kn); - if (!rdtgrp) { -@@ -623,10 +624,14 @@ int rdtgroup_mondata_show(struct seq_fil - * one that matches this cache id. - */ - list_for_each_entry(d, &r->mon_domains, hdr.list) { -- if (d->ci->id == domid) { -- rr.ci = d->ci; -+ if (d->ci_id == domid) { -+ cpu = cpumask_any(&d->hdr.cpu_mask); -+ ci = get_cpu_cacheinfo_level(cpu, RESCTRL_L3_CACHE); -+ if (!ci) -+ continue; -+ rr.ci = ci; - mon_event_read(&rr, r, NULL, rdtgrp, -- &d->ci->shared_cpu_map, evtid, false); -+ &ci->shared_cpu_map, evtid, false); - goto checkresult; - } - } -diff -purNx .git BPI-Router-Linux-kernel/fs/resctrl/monitor.c BPI-Router-Linux-kernel-6.16.12/fs/resctrl/monitor.c ---- BPI-Router-Linux-kernel/fs/resctrl/monitor.c 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/resctrl/monitor.c 2025-10-22 13:53:56.731168099 -0400 -@@ -400,7 +400,7 @@ static int __mon_event_count(u32 closid, - */ - ret = -EINVAL; - list_for_each_entry(d, &rr->r->mon_domains, hdr.list) { -- if (d->ci->id != rr->ci->id) -+ if (d->ci_id != rr->ci->id) - continue; - err = resctrl_arch_rmid_read(rr->r, d, closid, rmid, - rr->evtid, &tval, rr->arch_mon_ctx); -diff -purNx .git BPI-Router-Linux-kernel/fs/resctrl/rdtgroup.c BPI-Router-Linux-kernel-6.16.12/fs/resctrl/rdtgroup.c ---- BPI-Router-Linux-kernel/fs/resctrl/rdtgroup.c 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/resctrl/rdtgroup.c 2025-10-22 13:53:56.731168099 -0400 -@@ -3036,7 +3036,7 @@ static void rmdir_mondata_subdir_allrdtg - char name[32]; - - snc_mode = r->mon_scope == RESCTRL_L3_NODE; -- sprintf(name, "mon_%s_%02d", r->name, snc_mode ? d->ci->id : d->hdr.id); -+ sprintf(name, "mon_%s_%02d", r->name, snc_mode ? d->ci_id : d->hdr.id); - if (snc_mode) - sprintf(subname, "mon_sub_%s_%02d", r->name, d->hdr.id); - -@@ -3061,7 +3061,7 @@ static int mon_add_all_files(struct kern - return -EPERM; - - list_for_each_entry(mevt, &r->evt_list, list) { -- domid = do_sum ? d->ci->id : d->hdr.id; -+ domid = do_sum ? d->ci_id : d->hdr.id; - priv = mon_get_kn_priv(r->rid, domid, mevt, do_sum); - if (WARN_ON_ONCE(!priv)) - return -EINVAL; -@@ -3089,7 +3089,7 @@ static int mkdir_mondata_subdir(struct k - lockdep_assert_held(&rdtgroup_mutex); - - snc_mode = r->mon_scope == RESCTRL_L3_NODE; -- sprintf(name, "mon_%s_%02d", r->name, snc_mode ? d->ci->id : d->hdr.id); -+ sprintf(name, "mon_%s_%02d", r->name, snc_mode ? d->ci_id : d->hdr.id); - kn = kernfs_find_and_get(parent_kn, name); - if (kn) { - /* -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/cached_dir.c BPI-Router-Linux-kernel-6.16.12/fs/smb/client/cached_dir.c ---- BPI-Router-Linux-kernel/fs/smb/client/cached_dir.c 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/cached_dir.c 2025-10-22 13:53:56.731168099 -0400 -@@ -509,8 +509,17 @@ void close_all_cached_dirs(struct cifs_s - spin_lock(&cfids->cfid_list_lock); - list_for_each_entry(cfid, &cfids->entries, entry) { - tmp_list = kmalloc(sizeof(*tmp_list), GFP_ATOMIC); -- if (tmp_list == NULL) -- break; -+ if (tmp_list == NULL) { -+ /* -+ * If the malloc() fails, we won't drop all -+ * dentries, and unmounting is likely to trigger -+ * a 'Dentry still in use' error. -+ */ -+ cifs_tcon_dbg(VFS, "Out of memory while dropping dentries\n"); -+ spin_unlock(&cfids->cfid_list_lock); -+ spin_unlock(&cifs_sb->tlink_tree_lock); -+ goto done; -+ } - spin_lock(&cfid->fid_lock); - tmp_list->dentry = cfid->dentry; - cfid->dentry = NULL; -@@ -522,6 +531,7 @@ void close_all_cached_dirs(struct cifs_s - } - spin_unlock(&cifs_sb->tlink_tree_lock); - -+done: - list_for_each_entry_safe(tmp_list, q, &entry, entry) { - list_del(&tmp_list->entry); - dput(tmp_list->dentry); -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/cached_dir.h BPI-Router-Linux-kernel-6.16.12/fs/smb/client/cached_dir.h ---- BPI-Router-Linux-kernel/fs/smb/client/cached_dir.h 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/cached_dir.h 2025-10-22 13:53:56.731168099 -0400 -@@ -21,12 +21,12 @@ struct cached_dirent { - struct cached_dirents { - bool is_valid:1; - bool is_failed:1; -- struct dir_context *ctx; /* -- * Only used to make sure we only take entries -- * from a single context. Never dereferenced. -- */ -+ struct file *file; /* -+ * Used to associate the cache with a single -+ * open file instance. -+ */ - struct mutex de_mutex; -- int pos; /* Expected ctx->pos */ -+ loff_t pos; /* Expected ctx->pos */ - struct list_head entries; - }; - -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/cifs_debug.c BPI-Router-Linux-kernel-6.16.12/fs/smb/client/cifs_debug.c ---- BPI-Router-Linux-kernel/fs/smb/client/cifs_debug.c 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/cifs_debug.c 2025-10-22 13:53:56.731168099 -0400 -@@ -432,10 +432,8 @@ static int cifs_debug_data_proc_show(str - server->smbd_conn->receive_credit_target); - seq_printf(m, "\nPending send_pending: %x ", - atomic_read(&server->smbd_conn->send_pending)); -- seq_printf(m, "\nReceive buffers count_receive_queue: %x " -- "count_empty_packet_queue: %x", -- server->smbd_conn->count_receive_queue, -- server->smbd_conn->count_empty_packet_queue); -+ seq_printf(m, "\nReceive buffers count_receive_queue: %x ", -+ server->smbd_conn->count_receive_queue); - seq_printf(m, "\nMR responder_resources: %x " - "max_frmr_depth: %x mr_type: %x", - server->smbd_conn->responder_resources, -@@ -1105,7 +1103,7 @@ static ssize_t cifs_security_flags_proc_ - if ((count < 1) || (count > 11)) - return -EINVAL; - -- memset(flags_string, 0, 12); -+ memset(flags_string, 0, sizeof(flags_string)); - - if (copy_from_user(flags_string, buffer, count)) - return -EFAULT; -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/cifsencrypt.c BPI-Router-Linux-kernel-6.16.12/fs/smb/client/cifsencrypt.c ---- BPI-Router-Linux-kernel/fs/smb/client/cifsencrypt.c 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/cifsencrypt.c 2025-10-22 13:53:56.731168099 -0400 -@@ -343,7 +343,7 @@ static struct ntlmssp2_name *find_next_a - len = AV_LEN(av); - if (AV_TYPE(av) == NTLMSSP_AV_EOL) - return NULL; -- if (!len || (u8 *)av + sizeof(*av) + len > end) -+ if ((u8 *)av + sizeof(*av) + len > end) - return NULL; - return av; - } -@@ -363,7 +363,7 @@ static int find_av_name(struct cifs_ses - - av_for_each_entry(ses, av) { - len = AV_LEN(av); -- if (AV_TYPE(av) != type) -+ if (AV_TYPE(av) != type || !len) - continue; - if (!IS_ALIGNED(len, sizeof(__le16))) { - cifs_dbg(VFS | ONCE, "%s: bad length(%u) for type %u\n", -@@ -532,17 +532,67 @@ CalcNTLMv2_response(const struct cifs_se - return rc; - } - -+/* -+ * Set up NTLMv2 response blob with SPN (cifs/) appended to the -+ * existing list of AV pairs. -+ */ -+static int set_auth_key_response(struct cifs_ses *ses) -+{ -+ size_t baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp); -+ size_t len, spnlen, tilen = 0, num_avs = 2 /* SPN + EOL */; -+ struct TCP_Server_Info *server = ses->server; -+ char *spn __free(kfree) = NULL; -+ struct ntlmssp2_name *av; -+ char *rsp = NULL; -+ int rc; -+ -+ spnlen = strlen(server->hostname); -+ len = sizeof("cifs/") + spnlen; -+ spn = kmalloc(len, GFP_KERNEL); -+ if (!spn) { -+ rc = -ENOMEM; -+ goto out; -+ } -+ -+ spnlen = scnprintf(spn, len, "cifs/%.*s", -+ (int)spnlen, server->hostname); -+ -+ av_for_each_entry(ses, av) -+ tilen += sizeof(*av) + AV_LEN(av); -+ -+ len = baselen + tilen + spnlen * sizeof(__le16) + num_avs * sizeof(*av); -+ rsp = kmalloc(len, GFP_KERNEL); -+ if (!rsp) { -+ rc = -ENOMEM; -+ goto out; -+ } -+ -+ memcpy(rsp + baselen, ses->auth_key.response, tilen); -+ av = (void *)(rsp + baselen + tilen); -+ av->type = cpu_to_le16(NTLMSSP_AV_TARGET_NAME); -+ av->length = cpu_to_le16(spnlen * sizeof(__le16)); -+ cifs_strtoUTF16((__le16 *)av->data, spn, spnlen, ses->local_nls); -+ av = (void *)((__u8 *)av + sizeof(*av) + AV_LEN(av)); -+ av->type = cpu_to_le16(NTLMSSP_AV_EOL); -+ av->length = 0; -+ -+ rc = 0; -+ ses->auth_key.len = len; -+out: -+ ses->auth_key.response = rsp; -+ return rc; -+} -+ - int - setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) - { - struct shash_desc *hmacmd5 = NULL; -- int rc; -- int baselen; -- unsigned int tilen; -+ unsigned char *tiblob = NULL; /* target info blob */ - struct ntlmv2_resp *ntlmv2; - char ntlmv2_hash[16]; -- unsigned char *tiblob = NULL; /* target info blob */ - __le64 rsp_timestamp; -+ __u64 cc; -+ int rc; - - if (nls_cp == NULL) { - cifs_dbg(VFS, "%s called with nls_cp==NULL\n", __func__); -@@ -588,32 +638,25 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, c - * (as Windows 7 does) - */ - rsp_timestamp = find_timestamp(ses); -+ get_random_bytes(&cc, sizeof(cc)); - -- baselen = CIFS_SESS_KEY_SIZE + sizeof(struct ntlmv2_resp); -- tilen = ses->auth_key.len; -- tiblob = ses->auth_key.response; -+ cifs_server_lock(ses->server); - -- ses->auth_key.response = kmalloc(baselen + tilen, GFP_KERNEL); -- if (!ses->auth_key.response) { -- rc = -ENOMEM; -+ tiblob = ses->auth_key.response; -+ rc = set_auth_key_response(ses); -+ if (rc) { - ses->auth_key.len = 0; -- goto setup_ntlmv2_rsp_ret; -+ goto unlock; - } -- ses->auth_key.len += baselen; - - ntlmv2 = (struct ntlmv2_resp *) - (ses->auth_key.response + CIFS_SESS_KEY_SIZE); - ntlmv2->blob_signature = cpu_to_le32(0x00000101); - ntlmv2->reserved = 0; - ntlmv2->time = rsp_timestamp; -- -- get_random_bytes(&ntlmv2->client_chal, sizeof(ntlmv2->client_chal)); -+ ntlmv2->client_chal = cc; - ntlmv2->reserved2 = 0; - -- memcpy(ses->auth_key.response + baselen, tiblob, tilen); -- -- cifs_server_lock(ses->server); -- - rc = cifs_alloc_hash("hmac(md5)", &hmacmd5); - if (rc) { - cifs_dbg(VFS, "Could not allocate HMAC-MD5, rc=%d\n", rc); -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/cifsfs.c BPI-Router-Linux-kernel-6.16.12/fs/smb/client/cifsfs.c ---- BPI-Router-Linux-kernel/fs/smb/client/cifsfs.c 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/cifsfs.c 2025-10-22 13:53:56.731168099 -0400 -@@ -723,7 +723,7 @@ cifs_show_options(struct seq_file *s, st - else - seq_puts(s, ",nativesocket"); - seq_show_option(s, "symlink", -- cifs_symlink_type_str(get_cifs_symlink_type(cifs_sb))); -+ cifs_symlink_type_str(cifs_symlink_type(cifs_sb))); - - seq_printf(s, ",rsize=%u", cifs_sb->ctx->rsize); - seq_printf(s, ",wsize=%u", cifs_sb->ctx->wsize); -@@ -1358,6 +1358,20 @@ static loff_t cifs_remap_file_range(stru - truncate_setsize(target_inode, new_size); - fscache_resize_cookie(cifs_inode_cookie(target_inode), - new_size); -+ } else if (rc == -EOPNOTSUPP) { -+ /* -+ * copy_file_range syscall man page indicates EINVAL -+ * is returned e.g when "fd_in and fd_out refer to the -+ * same file and the source and target ranges overlap." -+ * Test generic/157 was what showed these cases where -+ * we need to remap EOPNOTSUPP to EINVAL -+ */ -+ if (off >= src_inode->i_size) { -+ rc = -EINVAL; -+ } else if (src_inode == target_inode) { -+ if (off + len > destoff) -+ rc = -EINVAL; -+ } - } - if (rc == 0 && new_size > target_cifsi->netfs.zero_point) - target_cifsi->netfs.zero_point = new_size; -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/cifsglob.h BPI-Router-Linux-kernel-6.16.12/fs/smb/client/cifsglob.h ---- BPI-Router-Linux-kernel/fs/smb/client/cifsglob.h 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/cifsglob.h 2025-10-22 13:53:56.731168099 -0400 -@@ -87,7 +87,7 @@ - #define SMB_INTERFACE_POLL_INTERVAL 600 - - /* maximum number of PDUs in one compound */ --#define MAX_COMPOUND 7 -+#define MAX_COMPOUND 10 - - /* - * Default number of credits to keep available for SMB3. -@@ -709,6 +709,7 @@ inc_rfc1001_len(void *buf, int count) - struct TCP_Server_Info { - struct list_head tcp_ses_list; - struct list_head smb_ses_list; -+ struct list_head rlist; /* reconnect list */ - spinlock_t srv_lock; /* protect anything here that is not protected */ - __u64 conn_id; /* connection identifier (useful for debugging) */ - int srv_count; /* reference counter */ -@@ -776,6 +777,7 @@ struct TCP_Server_Info { - __le32 session_key_id; /* retrieved from negotiate response and send in session setup request */ - struct session_key session_key; - unsigned long lstrp; /* when we got last response from this server */ -+ unsigned long neg_start; /* when negotiate started (jiffies) */ - struct cifs_secmech secmech; /* crypto sec mech functs, descriptors */ - #define CIFS_NEGFLAVOR_UNENCAP 1 /* wct == 17, but no ext_sec */ - #define CIFS_NEGFLAVOR_EXTENDED 2 /* wct == 17, ext_sec bit set */ -@@ -1302,6 +1304,7 @@ struct cifs_tcon { - bool use_persistent:1; /* use persistent instead of durable handles */ - bool no_lease:1; /* Do not request leases on files or directories */ - bool use_witness:1; /* use witness protocol */ -+ bool dummy:1; /* dummy tcon used for reconnecting channels */ - __le32 capabilities; - __u32 share_flags; - __u32 maximal_access; -@@ -1874,9 +1877,12 @@ static inline bool is_replayable_error(i - - - /* cifs_get_writable_file() flags */ --#define FIND_WR_ANY 0 --#define FIND_WR_FSUID_ONLY 1 --#define FIND_WR_WITH_DELETE 2 -+enum cifs_writable_file_flags { -+ FIND_WR_ANY = 0U, -+ FIND_WR_FSUID_ONLY = (1U << 0), -+ FIND_WR_WITH_DELETE = (1U << 1), -+ FIND_WR_NO_PENDING_DELETE = (1U << 2), -+}; - - #define MID_FREE 0 - #define MID_REQUEST_ALLOCATED 1 -@@ -2336,6 +2342,8 @@ struct smb2_compound_vars { - struct kvec qi_iov; - struct kvec io_iov[SMB2_IOCTL_IOV_SIZE]; - struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE]; -+ struct kvec unlink_iov[SMB2_SET_INFO_IOV_SIZE]; -+ struct kvec rename_iov[SMB2_SET_INFO_IOV_SIZE]; - struct kvec close_iov; - struct smb2_file_rename_info_hdr rename_info; - struct smb2_file_link_info_hdr link_info; -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/cifs_ioctl.h BPI-Router-Linux-kernel-6.16.12/fs/smb/client/cifs_ioctl.h ---- BPI-Router-Linux-kernel/fs/smb/client/cifs_ioctl.h 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/cifs_ioctl.h 2025-10-22 13:53:56.731168099 -0400 -@@ -61,7 +61,7 @@ struct smb_query_info { - struct smb3_key_debug_info { - __u64 Suid; - __u16 cipher_type; -- __u8 auth_key[16]; /* SMB2_NTLMV2_SESSKEY_SIZE */ -+ __u8 auth_key[SMB2_NTLMV2_SESSKEY_SIZE]; - __u8 smb3encryptionkey[SMB3_SIGN_KEY_SIZE]; - __u8 smb3decryptionkey[SMB3_SIGN_KEY_SIZE]; - } __packed; -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/cifsproto.h BPI-Router-Linux-kernel-6.16.12/fs/smb/client/cifsproto.h ---- BPI-Router-Linux-kernel/fs/smb/client/cifsproto.h 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/cifsproto.h 2025-10-22 13:53:56.731168099 -0400 -@@ -136,6 +136,7 @@ extern int SendReceiveBlockingLock(const - struct smb_hdr *out_buf, - int *bytes_returned); - -+void smb2_query_server_interfaces(struct work_struct *work); - void - cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server, - bool all_channels); -@@ -296,8 +297,8 @@ extern void cifs_close_deferred_file(str - - extern void cifs_close_all_deferred_files(struct cifs_tcon *cifs_tcon); - --extern void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon, -- const char *path); -+void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon, -+ struct dentry *dentry); - - extern void cifs_mark_open_handles_for_deleted_file(struct inode *inode, - const char *path); -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/cifssmb.c BPI-Router-Linux-kernel-6.16.12/fs/smb/client/cifssmb.c ---- BPI-Router-Linux-kernel/fs/smb/client/cifssmb.c 2025-10-22 13:53:23.539327574 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/cifssmb.c 2025-10-22 13:53:56.731168099 -0400 -@@ -1334,7 +1334,12 @@ cifs_readv_callback(struct mid_q_entry * - cifs_stats_bytes_read(tcon, rdata->got_bytes); - break; - case MID_REQUEST_SUBMITTED: -+ trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_req_submitted); -+ goto do_retry; - case MID_RETRY_NEEDED: -+ trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_retry_needed); -+do_retry: -+ __set_bit(NETFS_SREQ_NEED_RETRY, &rdata->subreq.flags); - rdata->result = -EAGAIN; - if (server->sign && rdata->got_bytes) - /* reset bytes number since we can not check a sign */ -@@ -1343,8 +1348,14 @@ cifs_readv_callback(struct mid_q_entry * - task_io_account_read(rdata->got_bytes); - cifs_stats_bytes_read(tcon, rdata->got_bytes); - break; -+ case MID_RESPONSE_MALFORMED: -+ trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_malformed); -+ rdata->result = -EIO; -+ break; - default: -+ trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_unknown); - rdata->result = -EIO; -+ break; - } - - if (rdata->result == -ENODATA) { -@@ -1713,10 +1724,21 @@ cifs_writev_callback(struct mid_q_entry - } - break; - case MID_REQUEST_SUBMITTED: -+ trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_req_submitted); -+ __set_bit(NETFS_SREQ_NEED_RETRY, &wdata->subreq.flags); -+ result = -EAGAIN; -+ break; - case MID_RETRY_NEEDED: -+ trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_retry_needed); -+ __set_bit(NETFS_SREQ_NEED_RETRY, &wdata->subreq.flags); - result = -EAGAIN; - break; -+ case MID_RESPONSE_MALFORMED: -+ trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_malformed); -+ result = -EIO; -+ break; - default: -+ trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_unknown); - result = -EIO; - break; - } -@@ -3998,6 +4020,12 @@ findFirstRetry: - pSMB->FileName[name_len] = 0; - pSMB->FileName[name_len+1] = 0; - name_len += 2; -+ } else if (!searchName[0]) { -+ pSMB->FileName[0] = CIFS_DIR_SEP(cifs_sb); -+ pSMB->FileName[1] = 0; -+ pSMB->FileName[2] = 0; -+ pSMB->FileName[3] = 0; -+ name_len = 4; - } - } else { - name_len = copy_path_name(pSMB->FileName, searchName); -@@ -4009,6 +4037,10 @@ findFirstRetry: - pSMB->FileName[name_len] = '*'; - pSMB->FileName[name_len+1] = 0; - name_len += 2; -+ } else if (!searchName[0]) { -+ pSMB->FileName[0] = CIFS_DIR_SEP(cifs_sb); -+ pSMB->FileName[1] = 0; -+ name_len = 2; - } - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/cifs_unicode.c BPI-Router-Linux-kernel-6.16.12/fs/smb/client/cifs_unicode.c ---- BPI-Router-Linux-kernel/fs/smb/client/cifs_unicode.c 2025-10-22 13:53:23.535327593 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/cifs_unicode.c 2025-10-22 13:53:56.731168099 -0400 -@@ -629,6 +629,9 @@ cifs_strndup_to_utf16(const char *src, c - int len; - __le16 *dst; - -+ if (!src) -+ return NULL; -+ - len = cifs_local_to_utf16_bytes(src, maxlen, cp); - len += 2; /* NULL */ - dst = kmalloc(len, GFP_KERNEL); -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/compress.c BPI-Router-Linux-kernel-6.16.12/fs/smb/client/compress.c ---- BPI-Router-Linux-kernel/fs/smb/client/compress.c 2025-10-22 13:53:23.539327574 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/compress.c 2025-10-22 13:53:56.731168099 -0400 -@@ -155,58 +155,29 @@ static int cmp_bkt(const void *_a, const - } - - /* -- * TODO: -- * Support other iter types, if required. -- * Only ITER_XARRAY is supported for now. -+ * Collect some 2K samples with 2K gaps between. - */ --static int collect_sample(const struct iov_iter *iter, ssize_t max, u8 *sample) -+static int collect_sample(const struct iov_iter *source, ssize_t max, u8 *sample) - { -- struct folio *folios[16], *folio; -- unsigned int nr, i, j, npages; -- loff_t start = iter->xarray_start + iter->iov_offset; -- pgoff_t last, index = start / PAGE_SIZE; -- size_t len, off, foff; -- void *p; -- int s = 0; -- -- last = (start + max - 1) / PAGE_SIZE; -- do { -- nr = xa_extract(iter->xarray, (void **)folios, index, last, ARRAY_SIZE(folios), -- XA_PRESENT); -- if (nr == 0) -- return -EIO; -- -- for (i = 0; i < nr; i++) { -- folio = folios[i]; -- npages = folio_nr_pages(folio); -- foff = start - folio_pos(folio); -- off = foff % PAGE_SIZE; -- -- for (j = foff / PAGE_SIZE; j < npages; j++) { -- size_t len2; -- -- len = min_t(size_t, max, PAGE_SIZE - off); -- len2 = min_t(size_t, len, SZ_2K); -- -- p = kmap_local_page(folio_page(folio, j)); -- memcpy(&sample[s], p, len2); -- kunmap_local(p); -- -- s += len2; -- -- if (len2 < SZ_2K || s >= max - SZ_2K) -- return s; -- -- max -= len; -- if (max <= 0) -- return s; -- -- start += len; -- off = 0; -- index++; -- } -- } -- } while (nr == ARRAY_SIZE(folios)); -+ struct iov_iter iter = *source; -+ size_t s = 0; -+ -+ while (iov_iter_count(&iter) >= SZ_2K) { -+ size_t part = umin(umin(iov_iter_count(&iter), SZ_2K), max); -+ size_t n; -+ -+ n = copy_from_iter(sample + s, part, &iter); -+ if (n != part) -+ return -EFAULT; -+ -+ s += n; -+ max -= n; -+ -+ if (iov_iter_count(&iter) < PAGE_SIZE - SZ_2K) -+ break; -+ -+ iov_iter_advance(&iter, SZ_2K); -+ } - - return s; - } -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/connect.c BPI-Router-Linux-kernel-6.16.12/fs/smb/client/connect.c ---- BPI-Router-Linux-kernel/fs/smb/client/connect.c 2025-10-22 13:53:23.539327574 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/connect.c 2025-10-22 13:53:56.731168099 -0400 -@@ -97,7 +97,7 @@ static int reconn_set_ipaddr_from_hostna - return rc; - } - --static void smb2_query_server_interfaces(struct work_struct *work) -+void smb2_query_server_interfaces(struct work_struct *work) - { - int rc; - int xid; -@@ -124,6 +124,14 @@ static void smb2_query_server_interfaces - (SMB_INTERFACE_POLL_INTERVAL * HZ)); - } - -+#define set_need_reco(server) \ -+do { \ -+ spin_lock(&server->srv_lock); \ -+ if (server->tcpStatus != CifsExiting) \ -+ server->tcpStatus = CifsNeedReconnect; \ -+ spin_unlock(&server->srv_lock); \ -+} while (0) -+ - /* - * Update the tcpStatus for the server. - * This is used to signal the cifsd thread to call cifs_reconnect -@@ -137,39 +145,45 @@ void - cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server, - bool all_channels) - { -- struct TCP_Server_Info *pserver; -+ struct TCP_Server_Info *nserver; - struct cifs_ses *ses; -+ LIST_HEAD(reco); - int i; - -- /* If server is a channel, select the primary channel */ -- pserver = SERVER_IS_CHAN(server) ? server->primary_server : server; -- - /* if we need to signal just this channel */ - if (!all_channels) { -- spin_lock(&server->srv_lock); -- if (server->tcpStatus != CifsExiting) -- server->tcpStatus = CifsNeedReconnect; -- spin_unlock(&server->srv_lock); -+ set_need_reco(server); - return; - } - -- spin_lock(&cifs_tcp_ses_lock); -- list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) { -- if (cifs_ses_exiting(ses)) -- continue; -- spin_lock(&ses->chan_lock); -- for (i = 0; i < ses->chan_count; i++) { -- if (!ses->chans[i].server) -+ if (SERVER_IS_CHAN(server)) -+ server = server->primary_server; -+ scoped_guard(spinlock, &cifs_tcp_ses_lock) { -+ set_need_reco(server); -+ list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { -+ spin_lock(&ses->ses_lock); -+ if (ses->ses_status == SES_EXITING) { -+ spin_unlock(&ses->ses_lock); - continue; -- -- spin_lock(&ses->chans[i].server->srv_lock); -- if (ses->chans[i].server->tcpStatus != CifsExiting) -- ses->chans[i].server->tcpStatus = CifsNeedReconnect; -- spin_unlock(&ses->chans[i].server->srv_lock); -+ } -+ spin_lock(&ses->chan_lock); -+ for (i = 1; i < ses->chan_count; i++) { -+ nserver = ses->chans[i].server; -+ if (!nserver) -+ continue; -+ nserver->srv_count++; -+ list_add(&nserver->rlist, &reco); -+ } -+ spin_unlock(&ses->chan_lock); -+ spin_unlock(&ses->ses_lock); - } -- spin_unlock(&ses->chan_lock); - } -- spin_unlock(&cifs_tcp_ses_lock); -+ -+ list_for_each_entry_safe(server, nserver, &reco, rlist) { -+ list_del_init(&server->rlist); -+ set_need_reco(server); -+ cifs_put_tcp_session(server, 0); -+ } - } - - /* -@@ -665,12 +679,12 @@ server_unresponsive(struct TCP_Server_In - /* - * If we're in the process of mounting a share or reconnecting a session - * and the server abruptly shut down (e.g. socket wasn't closed, packet -- * had been ACK'ed but no SMB response), don't wait longer than 20s to -- * negotiate protocol. -+ * had been ACK'ed but no SMB response), don't wait longer than 20s from -+ * when negotiate actually started. - */ - spin_lock(&server->srv_lock); - if (server->tcpStatus == CifsInNegotiate && -- time_after(jiffies, server->lstrp + 20 * HZ)) { -+ time_after(jiffies, server->neg_start + 20 * HZ)) { - spin_unlock(&server->srv_lock); - cifs_reconnect(server, false); - return true; -@@ -2866,20 +2880,14 @@ cifs_get_tcon(struct cifs_ses *ses, stru - tcon->max_cached_dirs = ctx->max_cached_dirs; - tcon->nodelete = ctx->nodelete; - tcon->local_lease = ctx->local_lease; -- INIT_LIST_HEAD(&tcon->pending_opens); - tcon->status = TID_GOOD; - -- INIT_DELAYED_WORK(&tcon->query_interfaces, -- smb2_query_server_interfaces); - if (ses->server->dialect >= SMB30_PROT_ID && - (ses->server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) { - /* schedule query interfaces poll */ - queue_delayed_work(cifsiod_wq, &tcon->query_interfaces, - (SMB_INTERFACE_POLL_INTERVAL * HZ)); - } --#ifdef CONFIG_CIFS_DFS_UPCALL -- INIT_DELAYED_WORK(&tcon->dfs_cache_work, dfs_cache_refresh); --#endif - spin_lock(&cifs_tcp_ses_lock); - list_add(&tcon->tcon_list, &ses->tcon_list); - spin_unlock(&cifs_tcp_ses_lock); -@@ -3354,18 +3362,15 @@ generic_ip_connect(struct TCP_Server_Inf - struct net *net = cifs_net_ns(server); - struct sock *sk; - -- rc = __sock_create(net, sfamily, SOCK_STREAM, -- IPPROTO_TCP, &server->ssocket, 1); -+ rc = sock_create_kern(net, sfamily, SOCK_STREAM, -+ IPPROTO_TCP, &server->ssocket); - if (rc < 0) { - cifs_server_dbg(VFS, "Error %d creating socket\n", rc); - return rc; - } - - sk = server->ssocket->sk; -- __netns_tracker_free(net, &sk->ns_tracker, false); -- sk->sk_net_refcnt = 1; -- get_net_track(net, &sk->ns_tracker, GFP_KERNEL); -- sock_inuse_add(net, 1); -+ sk_net_refcnt_upgrade(sk); - - /* BB other socket options to set KEEPALIVE, NODELAY? */ - cifs_dbg(FYI, "Socket created\n"); -@@ -3718,9 +3723,15 @@ int cifs_mount_get_tcon(struct cifs_moun - goto out; - } - -- /* if new SMB3.11 POSIX extensions are supported do not remap / and \ */ -- if (tcon->posix_extensions) -+ /* -+ * if new SMB3.11 POSIX extensions are supported, do not change anything in the -+ * path (i.e., do not remap / and \ and do not map any special characters) -+ */ -+ if (tcon->posix_extensions) { - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS; -+ cifs_sb->mnt_cifs_flags &= ~(CIFS_MOUNT_MAP_SFM_CHR | -+ CIFS_MOUNT_MAP_SPECIAL_CHR); -+ } - - #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY - /* tell server which Unix caps we support */ -@@ -4194,6 +4205,7 @@ retry: - } - - server->tcpStatus = CifsInNegotiate; -+ server->neg_start = jiffies; - spin_unlock(&server->srv_lock); - - rc = server->ops->negotiate(xid, ses, server); -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/dir.c BPI-Router-Linux-kernel-6.16.12/fs/smb/client/dir.c ---- BPI-Router-Linux-kernel/fs/smb/client/dir.c 2025-10-22 13:53:23.539327574 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/dir.c 2025-10-22 13:53:56.731168099 -0400 -@@ -190,6 +190,7 @@ static int cifs_do_create(struct inode * - int disposition; - struct TCP_Server_Info *server = tcon->ses->server; - struct cifs_open_parms oparms; -+ struct cached_fid *parent_cfid = NULL; - int rdwr_for_fscache = 0; - __le32 lease_flags = 0; - -@@ -313,10 +314,10 @@ static int cifs_do_create(struct inode * - if (!tcon->unix_ext && (mode & S_IWUGO) == 0) - create_options |= CREATE_OPTION_READONLY; - -+ - retry_open: - if (tcon->cfids && direntry->d_parent && server->dialect >= SMB30_PROT_ID) { -- struct cached_fid *parent_cfid; -- -+ parent_cfid = NULL; - spin_lock(&tcon->cfids->cfid_list_lock); - list_for_each_entry(parent_cfid, &tcon->cfids->entries, entry) { - if (parent_cfid->dentry == direntry->d_parent) { -@@ -327,6 +328,7 @@ retry_open: - memcpy(fid->parent_lease_key, - parent_cfid->fid.lease_key, - SMB2_LEASE_KEY_SIZE); -+ parent_cfid->dirents.is_valid = false; - } - break; - } -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/file.c BPI-Router-Linux-kernel-6.16.12/fs/smb/client/file.c ---- BPI-Router-Linux-kernel/fs/smb/client/file.c 2025-10-22 13:53:23.539327574 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/file.c 2025-10-22 13:53:56.731168099 -0400 -@@ -52,6 +52,7 @@ static void cifs_prepare_write(struct ne - struct netfs_io_stream *stream = &req->rreq.io_streams[subreq->stream_nr]; - struct TCP_Server_Info *server; - struct cifsFileInfo *open_file = req->cfile; -+ struct cifs_sb_info *cifs_sb = CIFS_SB(wdata->rreq->inode->i_sb); - size_t wsize = req->rreq.wsize; - int rc; - -@@ -63,6 +64,10 @@ static void cifs_prepare_write(struct ne - server = cifs_pick_channel(tlink_tcon(open_file->tlink)->ses); - wdata->server = server; - -+ if (cifs_sb->ctx->wsize == 0) -+ cifs_negotiate_wsize(server, cifs_sb->ctx, -+ tlink_tcon(req->cfile->tlink)); -+ - retry: - if (open_file->invalidHandle) { - rc = cifs_reopen_file(open_file, false); -@@ -160,10 +165,9 @@ static int cifs_prepare_read(struct netf - server = cifs_pick_channel(tlink_tcon(req->cfile->tlink)->ses); - rdata->server = server; - -- if (cifs_sb->ctx->rsize == 0) { -+ if (cifs_sb->ctx->rsize == 0) - cifs_negotiate_rsize(server, cifs_sb->ctx, - tlink_tcon(req->cfile->tlink)); -- } - - rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->rsize, - &size, &rdata->credits); -@@ -994,20 +998,26 @@ int cifs_open(struct inode *inode, struc - - /* Get the cached handle as SMB2 close is deferred */ - if (OPEN_FMODE(file->f_flags) & FMODE_WRITE) { -- rc = cifs_get_writable_path(tcon, full_path, FIND_WR_FSUID_ONLY, &cfile); -+ rc = cifs_get_writable_path(tcon, full_path, -+ FIND_WR_FSUID_ONLY | -+ FIND_WR_NO_PENDING_DELETE, -+ &cfile); - } else { - rc = cifs_get_readable_path(tcon, full_path, &cfile); - } - if (rc == 0) { -- if (file->f_flags == cfile->f_flags) { -+ unsigned int oflags = file->f_flags & ~(O_CREAT|O_EXCL|O_TRUNC); -+ unsigned int cflags = cfile->f_flags & ~(O_CREAT|O_EXCL|O_TRUNC); -+ -+ if (cifs_convert_flags(oflags, 0) == cifs_convert_flags(cflags, 0) && -+ (oflags & (O_SYNC|O_DIRECT)) == (cflags & (O_SYNC|O_DIRECT))) { - file->private_data = cfile; - spin_lock(&CIFS_I(inode)->deferred_lock); - cifs_del_deferred_close(cfile); - spin_unlock(&CIFS_I(inode)->deferred_lock); - goto use_cache; -- } else { -- _cifsFileInfo_put(cfile, true, false); - } -+ _cifsFileInfo_put(cfile, true, false); - } else { - /* hard link on the defeered close file */ - rc = cifs_get_hardlink_path(tcon, inode, file); -@@ -2523,6 +2533,9 @@ refind_writable: - continue; - if (with_delete && !(open_file->fid.access & DELETE)) - continue; -+ if ((flags & FIND_WR_NO_PENDING_DELETE) && -+ open_file->status_file_deleted) -+ continue; - if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { - if (!open_file->invalidHandle) { - /* found a good writable file */ -@@ -2640,6 +2653,16 @@ cifs_get_readable_path(struct cifs_tcon - spin_unlock(&tcon->open_file_lock); - free_dentry_path(page); - *ret_file = find_readable_file(cinode, 0); -+ if (*ret_file) { -+ spin_lock(&cinode->open_file_lock); -+ if ((*ret_file)->status_file_deleted) { -+ spin_unlock(&cinode->open_file_lock); -+ cifsFileInfo_put(*ret_file); -+ *ret_file = NULL; -+ } else { -+ spin_unlock(&cinode->open_file_lock); -+ } -+ } - return *ret_file ? 0 : -ENOENT; - } - -@@ -3081,7 +3104,8 @@ void cifs_oplock_break(struct work_struc - struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, - oplock_break); - struct inode *inode = d_inode(cfile->dentry); -- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); -+ struct super_block *sb = inode->i_sb; -+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - struct cifsInodeInfo *cinode = CIFS_I(inode); - struct cifs_tcon *tcon; - struct TCP_Server_Info *server; -@@ -3091,6 +3115,12 @@ void cifs_oplock_break(struct work_struc - __u64 persistent_fid, volatile_fid; - __u16 net_fid; - -+ /* -+ * Hold a reference to the superblock to prevent it and its inodes from -+ * being freed while we are accessing cinode. Otherwise, _cifsFileInfo_put() -+ * may release the last reference to the sb and trigger inode eviction. -+ */ -+ cifs_sb_active(sb); - wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS, - TASK_UNINTERRUPTIBLE); - -@@ -3163,6 +3193,7 @@ oplock_break_ack: - cifs_put_tlink(tlink); - out: - cifs_done_oplock_break(cinode); -+ cifs_sb_deactive(sb); - } - - static int cifs_swap_activate(struct swap_info_struct *sis, -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/fs_context.c BPI-Router-Linux-kernel-6.16.12/fs/smb/client/fs_context.c ---- BPI-Router-Linux-kernel/fs/smb/client/fs_context.c 2025-10-22 13:53:23.539327574 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/fs_context.c 2025-10-22 13:53:56.731168099 -0400 -@@ -1674,6 +1674,7 @@ static int smb3_fs_context_parse_param(s - pr_warn_once("conflicting posix mount options specified\n"); - ctx->linux_ext = 1; - ctx->no_linux_ext = 0; -+ ctx->nonativesocket = 1; /* POSIX mounts use NFS style reparse points */ - } - break; - case Opt_nocase: -@@ -1824,10 +1825,14 @@ static int smb3_fs_context_parse_param(s - cifs_errorf(fc, "symlinkroot mount options must be absolute path\n"); - goto cifs_parse_mount_err; - } -- kfree(ctx->symlinkroot); -- ctx->symlinkroot = kstrdup(param->string, GFP_KERNEL); -- if (!ctx->symlinkroot) -+ if (strnlen(param->string, PATH_MAX) == PATH_MAX) { -+ cifs_errorf(fc, "symlinkroot path too long (max path length: %u)\n", -+ PATH_MAX - 1); - goto cifs_parse_mount_err; -+ } -+ kfree(ctx->symlinkroot); -+ ctx->symlinkroot = param->string; -+ param->string = NULL; - break; - } - /* case Opt_ignore: - is ignored as expected ... */ -@@ -1837,13 +1842,6 @@ static int smb3_fs_context_parse_param(s - goto cifs_parse_mount_err; - } - -- /* -- * By default resolve all native absolute symlinks relative to "/mnt/". -- * Same default has drvfs driver running in WSL for resolving SMB shares. -- */ -- if (!ctx->symlinkroot) -- ctx->symlinkroot = kstrdup("/mnt/", GFP_KERNEL); -- - return 0; - - cifs_parse_mount_err: -@@ -1854,24 +1852,6 @@ static int smb3_fs_context_parse_param(s - return -EINVAL; - } - --enum cifs_symlink_type get_cifs_symlink_type(struct cifs_sb_info *cifs_sb) --{ -- if (cifs_sb->ctx->symlink_type == CIFS_SYMLINK_TYPE_DEFAULT) { -- if (cifs_sb->ctx->mfsymlinks) -- return CIFS_SYMLINK_TYPE_MFSYMLINKS; -- else if (cifs_sb->ctx->sfu_emul) -- return CIFS_SYMLINK_TYPE_SFU; -- else if (cifs_sb->ctx->linux_ext && !cifs_sb->ctx->no_linux_ext) -- return CIFS_SYMLINK_TYPE_UNIX; -- else if (cifs_sb->ctx->reparse_type != CIFS_REPARSE_TYPE_NONE) -- return CIFS_SYMLINK_TYPE_NATIVE; -- else -- return CIFS_SYMLINK_TYPE_NONE; -- } else { -- return cifs_sb->ctx->symlink_type; -- } --} -- - int smb3_init_fs_context(struct fs_context *fc) - { - struct smb3_fs_context *ctx; -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/fs_context.h BPI-Router-Linux-kernel-6.16.12/fs/smb/client/fs_context.h ---- BPI-Router-Linux-kernel/fs/smb/client/fs_context.h 2025-10-22 13:53:23.539327574 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/fs_context.h 2025-10-22 13:53:56.731168099 -0400 -@@ -341,7 +341,23 @@ struct smb3_fs_context { - - extern const struct fs_parameter_spec smb3_fs_parameters[]; - --extern enum cifs_symlink_type get_cifs_symlink_type(struct cifs_sb_info *cifs_sb); -+static inline enum cifs_symlink_type cifs_symlink_type(struct cifs_sb_info *cifs_sb) -+{ -+ bool posix = cifs_sb_master_tcon(cifs_sb)->posix_extensions; -+ -+ if (cifs_sb->ctx->symlink_type != CIFS_SYMLINK_TYPE_DEFAULT) -+ return cifs_sb->ctx->symlink_type; -+ -+ if (cifs_sb->ctx->mfsymlinks) -+ return CIFS_SYMLINK_TYPE_MFSYMLINKS; -+ else if (cifs_sb->ctx->sfu_emul) -+ return CIFS_SYMLINK_TYPE_SFU; -+ else if (cifs_sb->ctx->linux_ext && !cifs_sb->ctx->no_linux_ext) -+ return posix ? CIFS_SYMLINK_TYPE_NATIVE : CIFS_SYMLINK_TYPE_UNIX; -+ else if (cifs_sb->ctx->reparse_type != CIFS_REPARSE_TYPE_NONE) -+ return CIFS_SYMLINK_TYPE_NATIVE; -+ return CIFS_SYMLINK_TYPE_NONE; -+} - - extern int smb3_init_fs_context(struct fs_context *fc); - extern void smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx); -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/inode.c BPI-Router-Linux-kernel-6.16.12/fs/smb/client/inode.c ---- BPI-Router-Linux-kernel/fs/smb/client/inode.c 2025-10-22 13:53:23.539327574 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/inode.c 2025-10-22 13:53:56.731168099 -0400 -@@ -1931,7 +1931,7 @@ cifs_drop_nlink(struct inode *inode) - * but will return the EACCES to the caller. Note that the VFS does not call - * unlink on negative dentries currently. - */ --int cifs_unlink(struct inode *dir, struct dentry *dentry) -+static int __cifs_unlink(struct inode *dir, struct dentry *dentry, bool sillyrename) - { - int rc = 0; - unsigned int xid; -@@ -1943,15 +1943,24 @@ int cifs_unlink(struct inode *dir, struc - struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - struct tcon_link *tlink; - struct cifs_tcon *tcon; -+ __u32 dosattr = 0, origattr = 0; - struct TCP_Server_Info *server; - struct iattr *attrs = NULL; -- __u32 dosattr = 0, origattr = 0; -+ bool rehash = false; - - cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry); - - if (unlikely(cifs_forced_shutdown(cifs_sb))) - return -EIO; - -+ /* Unhash dentry in advance to prevent any concurrent opens */ -+ spin_lock(&dentry->d_lock); -+ if (!d_unhashed(dentry)) { -+ __d_drop(dentry); -+ rehash = true; -+ } -+ spin_unlock(&dentry->d_lock); -+ - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); -@@ -1975,7 +1984,7 @@ int cifs_unlink(struct inode *dir, struc - } - - netfs_wait_for_outstanding_io(inode); -- cifs_close_deferred_file_under_dentry(tcon, full_path); -+ cifs_close_deferred_file_under_dentry(tcon, dentry); - #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY - if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP & - le64_to_cpu(tcon->fsUnixInfo.Capability))) { -@@ -1994,7 +2003,24 @@ retry_std_delete: - goto psx_del_no_retry; - } - -- rc = server->ops->unlink(xid, tcon, full_path, cifs_sb, dentry); -+ /* For SMB2+, if the file is open, we always perform a silly rename. -+ * -+ * We check for d_count() right after calling -+ * cifs_close_deferred_file_under_dentry() to make sure that the -+ * dentry's refcount gets dropped in case the file had any deferred -+ * close. -+ */ -+ if (!sillyrename && server->vals->protocol_id > SMB10_PROT_ID) { -+ spin_lock(&dentry->d_lock); -+ if (d_count(dentry) > 1) -+ sillyrename = true; -+ spin_unlock(&dentry->d_lock); -+ } -+ -+ if (sillyrename) -+ rc = -EBUSY; -+ else -+ rc = server->ops->unlink(xid, tcon, full_path, cifs_sb, dentry); - - psx_del_no_retry: - if (!rc) { -@@ -2003,7 +2029,8 @@ psx_del_no_retry: - cifs_drop_nlink(inode); - } - } else if (rc == -ENOENT) { -- d_drop(dentry); -+ if (simple_positive(dentry)) -+ d_delete(dentry); - } else if (rc == -EBUSY) { - if (server->ops->rename_pending_delete) { - rc = server->ops->rename_pending_delete(full_path, -@@ -2056,9 +2083,16 @@ unlink_out: - kfree(attrs); - free_xid(xid); - cifs_put_tlink(tlink); -+ if (rehash) -+ d_rehash(dentry); - return rc; - } - -+int cifs_unlink(struct inode *dir, struct dentry *dentry) -+{ -+ return __cifs_unlink(dir, dentry, false); -+} -+ - static int - cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode, - const char *full_path, struct cifs_sb_info *cifs_sb, -@@ -2346,14 +2380,16 @@ int cifs_rmdir(struct inode *inode, stru - rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb); - cifs_put_tlink(tlink); - -+ cifsInode = CIFS_I(d_inode(direntry)); -+ - if (!rc) { -+ set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags); - spin_lock(&d_inode(direntry)->i_lock); - i_size_write(d_inode(direntry), 0); - clear_nlink(d_inode(direntry)); - spin_unlock(&d_inode(direntry)->i_lock); - } - -- cifsInode = CIFS_I(d_inode(direntry)); - /* force revalidate to go get info when needed */ - cifsInode->time = 0; - -@@ -2446,8 +2482,11 @@ cifs_do_rename(const unsigned int xid, s - } - #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ - do_rename_exit: -- if (rc == 0) -+ if (rc == 0) { - d_move(from_dentry, to_dentry); -+ /* Force a new lookup */ -+ d_drop(from_dentry); -+ } - cifs_put_tlink(tlink); - return rc; - } -@@ -2458,10 +2497,12 @@ cifs_rename2(struct mnt_idmap *idmap, st - struct dentry *target_dentry, unsigned int flags) - { - const char *from_name, *to_name; -+ struct TCP_Server_Info *server; - void *page1, *page2; - struct cifs_sb_info *cifs_sb; - struct tcon_link *tlink; - struct cifs_tcon *tcon; -+ bool rehash = false; - unsigned int xid; - int rc, tmprc; - int retry_count = 0; -@@ -2477,10 +2518,22 @@ cifs_rename2(struct mnt_idmap *idmap, st - if (unlikely(cifs_forced_shutdown(cifs_sb))) - return -EIO; - -+ /* -+ * Prevent any concurrent opens on the target by unhashing the dentry. -+ * VFS already unhashes the target when renaming directories. -+ */ -+ if (d_is_positive(target_dentry) && !d_is_dir(target_dentry)) { -+ if (!d_unhashed(target_dentry)) { -+ d_drop(target_dentry); -+ rehash = true; -+ } -+ } -+ - tlink = cifs_sb_tlink(cifs_sb); - if (IS_ERR(tlink)) - return PTR_ERR(tlink); - tcon = tlink_tcon(tlink); -+ server = tcon->ses->server; - - page1 = alloc_dentry_path(); - page2 = alloc_dentry_path(); -@@ -2498,10 +2551,10 @@ cifs_rename2(struct mnt_idmap *idmap, st - goto cifs_rename_exit; - } - -- cifs_close_deferred_file_under_dentry(tcon, from_name); -+ cifs_close_deferred_file_under_dentry(tcon, source_dentry); - if (d_inode(target_dentry) != NULL) { - netfs_wait_for_outstanding_io(d_inode(target_dentry)); -- cifs_close_deferred_file_under_dentry(tcon, to_name); -+ cifs_close_deferred_file_under_dentry(tcon, target_dentry); - } - - rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry, -@@ -2518,6 +2571,8 @@ cifs_rename2(struct mnt_idmap *idmap, st - } - } - -+ if (!rc) -+ rehash = false; - /* - * No-replace is the natural behavior for CIFS, so skip unlink hacks. - */ -@@ -2565,23 +2620,61 @@ cifs_rename2(struct mnt_idmap *idmap, st - - unlink_target: - #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ -- -- /* Try unlinking the target dentry if it's not negative */ -- if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) { -- if (d_is_dir(target_dentry)) -- tmprc = cifs_rmdir(target_dir, target_dentry); -- else -- tmprc = cifs_unlink(target_dir, target_dentry); -- if (tmprc) -- goto cifs_rename_exit; -- rc = cifs_do_rename(xid, source_dentry, from_name, -- target_dentry, to_name); -+ if (d_really_is_positive(target_dentry)) { -+ if (!rc) { -+ struct inode *inode = d_inode(target_dentry); -+ /* -+ * Samba and ksmbd servers allow renaming a target -+ * directory that is open, so make sure to update -+ * ->i_nlink and then mark it as delete pending. -+ */ -+ if (S_ISDIR(inode->i_mode)) { -+ drop_cached_dir_by_name(xid, tcon, to_name, cifs_sb); -+ spin_lock(&inode->i_lock); -+ i_size_write(inode, 0); -+ clear_nlink(inode); -+ spin_unlock(&inode->i_lock); -+ set_bit(CIFS_INO_DELETE_PENDING, &CIFS_I(inode)->flags); -+ CIFS_I(inode)->time = 0; /* force reval */ -+ inode_set_ctime_current(inode); -+ inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); -+ } -+ } else if (rc == -EACCES || rc == -EEXIST) { -+ /* -+ * Rename failed, possibly due to a busy target. -+ * Retry it by unliking the target first. -+ */ -+ if (d_is_dir(target_dentry)) { -+ tmprc = cifs_rmdir(target_dir, target_dentry); -+ } else { -+ tmprc = __cifs_unlink(target_dir, target_dentry, -+ server->vals->protocol_id > SMB10_PROT_ID); -+ } -+ if (tmprc) { -+ /* -+ * Some servers will return STATUS_ACCESS_DENIED -+ * or STATUS_DIRECTORY_NOT_EMPTY when failing to -+ * rename a non-empty directory. Make sure to -+ * propagate the appropriate error back to -+ * userspace. -+ */ -+ if (tmprc == -EEXIST || tmprc == -ENOTEMPTY) -+ rc = tmprc; -+ goto cifs_rename_exit; -+ } -+ rc = cifs_do_rename(xid, source_dentry, from_name, -+ target_dentry, to_name); -+ if (!rc) -+ rehash = false; -+ } - } - - /* force revalidate to go get info when needed */ - CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0; - - cifs_rename_exit: -+ if (rehash) -+ d_rehash(target_dentry); - kfree(info_buf_source); - free_dentry_path(page2); - free_dentry_path(page1); -@@ -2599,6 +2692,8 @@ cifs_dentry_needs_reval(struct dentry *d - struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); - struct cached_fid *cfid = NULL; - -+ if (test_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags)) -+ return false; - if (cifs_i->time == 0) - return true; - -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/ioctl.c BPI-Router-Linux-kernel-6.16.12/fs/smb/client/ioctl.c ---- BPI-Router-Linux-kernel/fs/smb/client/ioctl.c 2025-10-22 13:53:23.539327574 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/ioctl.c 2025-10-22 13:53:56.731168099 -0400 -@@ -506,7 +506,7 @@ long cifs_ioctl(struct file *filep, unsi - le16_to_cpu(tcon->ses->server->cipher_type); - pkey_inf.Suid = tcon->ses->Suid; - memcpy(pkey_inf.auth_key, tcon->ses->auth_key.response, -- 16 /* SMB2_NTLMV2_SESSKEY_SIZE */); -+ SMB2_NTLMV2_SESSKEY_SIZE); - memcpy(pkey_inf.smb3decryptionkey, - tcon->ses->smb3decryptionkey, SMB3_SIGN_KEY_SIZE); - memcpy(pkey_inf.smb3encryptionkey, -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/link.c BPI-Router-Linux-kernel-6.16.12/fs/smb/client/link.c ---- BPI-Router-Linux-kernel/fs/smb/client/link.c 2025-10-22 13:53:23.539327574 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/link.c 2025-10-22 13:53:56.731168099 -0400 -@@ -606,14 +606,7 @@ cifs_symlink(struct mnt_idmap *idmap, st - - /* BB what if DFS and this volume is on different share? BB */ - rc = -EOPNOTSUPP; -- switch (get_cifs_symlink_type(cifs_sb)) { -- case CIFS_SYMLINK_TYPE_DEFAULT: -- /* should not happen, get_cifs_symlink_type() resolves the default */ -- break; -- -- case CIFS_SYMLINK_TYPE_NONE: -- break; -- -+ switch (cifs_symlink_type(cifs_sb)) { - case CIFS_SYMLINK_TYPE_UNIX: - #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY - if (pTcon->unix_ext) { -@@ -653,6 +646,8 @@ cifs_symlink(struct mnt_idmap *idmap, st - goto symlink_exit; - } - break; -+ default: -+ break; - } - - if (rc == 0) { -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/misc.c BPI-Router-Linux-kernel-6.16.12/fs/smb/client/misc.c ---- BPI-Router-Linux-kernel/fs/smb/client/misc.c 2025-10-22 13:53:23.539327574 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/misc.c 2025-10-22 13:53:56.735168080 -0400 -@@ -151,6 +151,12 @@ tcon_info_alloc(bool dir_leases_enabled, - #ifdef CONFIG_CIFS_DFS_UPCALL - INIT_LIST_HEAD(&ret_buf->dfs_ses_list); - #endif -+ INIT_LIST_HEAD(&ret_buf->pending_opens); -+ INIT_DELAYED_WORK(&ret_buf->query_interfaces, -+ smb2_query_server_interfaces); -+#ifdef CONFIG_CIFS_DFS_UPCALL -+ INIT_DELAYED_WORK(&ret_buf->dfs_cache_work, dfs_cache_refresh); -+#endif - - return ret_buf; - } -@@ -826,33 +832,28 @@ cifs_close_all_deferred_files(struct cif - kfree(tmp_list); - } - } --void --cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, const char *path) -+ -+void cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, -+ struct dentry *dentry) - { -- struct cifsFileInfo *cfile; - struct file_list *tmp_list, *tmp_next_list; -- void *page; -- const char *full_path; -+ struct cifsFileInfo *cfile; - LIST_HEAD(file_head); - -- page = alloc_dentry_path(); - spin_lock(&tcon->open_file_lock); - list_for_each_entry(cfile, &tcon->openFileList, tlist) { -- full_path = build_path_from_dentry(cfile->dentry, page); -- if (strstr(full_path, path)) { -- if (delayed_work_pending(&cfile->deferred)) { -- if (cancel_delayed_work(&cfile->deferred)) { -- spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock); -- cifs_del_deferred_close(cfile); -- spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock); -- -- tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC); -- if (tmp_list == NULL) -- break; -- tmp_list->cfile = cfile; -- list_add_tail(&tmp_list->list, &file_head); -- } -- } -+ if ((cfile->dentry == dentry) && -+ delayed_work_pending(&cfile->deferred) && -+ cancel_delayed_work(&cfile->deferred)) { -+ spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock); -+ cifs_del_deferred_close(cfile); -+ spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock); -+ -+ tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC); -+ if (tmp_list == NULL) -+ break; -+ tmp_list->cfile = cfile; -+ list_add_tail(&tmp_list->list, &file_head); - } - } - spin_unlock(&tcon->open_file_lock); -@@ -862,7 +863,6 @@ cifs_close_deferred_file_under_dentry(st - list_del(&tmp_list->list); - kfree(tmp_list); - } -- free_dentry_path(page); - } - - /* -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/readdir.c BPI-Router-Linux-kernel-6.16.12/fs/smb/client/readdir.c ---- BPI-Router-Linux-kernel/fs/smb/client/readdir.c 2025-10-22 13:53:23.539327574 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/readdir.c 2025-10-22 13:53:56.735168080 -0400 -@@ -264,7 +264,7 @@ cifs_posix_to_fattr(struct cifs_fattr *f - /* The Mode field in the response can now include the file type as well */ - fattr->cf_mode = wire_mode_to_posix(le32_to_cpu(info->Mode), - fattr->cf_cifsattrs & ATTR_DIRECTORY); -- fattr->cf_dtype = S_DT(le32_to_cpu(info->Mode)); -+ fattr->cf_dtype = S_DT(fattr->cf_mode); - - switch (fattr->cf_mode & S_IFMT) { - case S_IFLNK: -@@ -851,9 +851,9 @@ static bool emit_cached_dirents(struct c - } - - static void update_cached_dirents_count(struct cached_dirents *cde, -- struct dir_context *ctx) -+ struct file *file) - { -- if (cde->ctx != ctx) -+ if (cde->file != file) - return; - if (cde->is_valid || cde->is_failed) - return; -@@ -862,9 +862,9 @@ static void update_cached_dirents_count( - } - - static void finished_cached_dirents_count(struct cached_dirents *cde, -- struct dir_context *ctx) -+ struct dir_context *ctx, struct file *file) - { -- if (cde->ctx != ctx) -+ if (cde->file != file) - return; - if (cde->is_valid || cde->is_failed) - return; -@@ -877,11 +877,12 @@ static void finished_cached_dirents_coun - static void add_cached_dirent(struct cached_dirents *cde, - struct dir_context *ctx, - const char *name, int namelen, -- struct cifs_fattr *fattr) -+ struct cifs_fattr *fattr, -+ struct file *file) - { - struct cached_dirent *de; - -- if (cde->ctx != ctx) -+ if (cde->file != file) - return; - if (cde->is_valid || cde->is_failed) - return; -@@ -911,7 +912,8 @@ static void add_cached_dirent(struct cac - static bool cifs_dir_emit(struct dir_context *ctx, - const char *name, int namelen, - struct cifs_fattr *fattr, -- struct cached_fid *cfid) -+ struct cached_fid *cfid, -+ struct file *file) - { - bool rc; - ino_t ino = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid); -@@ -923,7 +925,7 @@ static bool cifs_dir_emit(struct dir_con - if (cfid) { - mutex_lock(&cfid->dirents.de_mutex); - add_cached_dirent(&cfid->dirents, ctx, name, namelen, -- fattr); -+ fattr, file); - mutex_unlock(&cfid->dirents.de_mutex); - } - -@@ -1023,7 +1025,7 @@ static int cifs_filldir(char *find_entry - cifs_prime_dcache(file_dentry(file), &name, &fattr); - - return !cifs_dir_emit(ctx, name.name, name.len, -- &fattr, cfid); -+ &fattr, cfid, file); - } - - -@@ -1074,8 +1076,8 @@ int cifs_readdir(struct file *file, stru - * we need to initialize scanning and storing the - * directory content. - */ -- if (ctx->pos == 0 && cfid->dirents.ctx == NULL) { -- cfid->dirents.ctx = ctx; -+ if (ctx->pos == 0 && cfid->dirents.file == NULL) { -+ cfid->dirents.file = file; - cfid->dirents.pos = 2; - } - /* -@@ -1143,7 +1145,7 @@ int cifs_readdir(struct file *file, stru - } else { - if (cfid) { - mutex_lock(&cfid->dirents.de_mutex); -- finished_cached_dirents_count(&cfid->dirents, ctx); -+ finished_cached_dirents_count(&cfid->dirents, ctx, file); - mutex_unlock(&cfid->dirents.de_mutex); - } - cifs_dbg(FYI, "Could not find entry\n"); -@@ -1184,7 +1186,7 @@ int cifs_readdir(struct file *file, stru - ctx->pos++; - if (cfid) { - mutex_lock(&cfid->dirents.de_mutex); -- update_cached_dirents_count(&cfid->dirents, ctx); -+ update_cached_dirents_count(&cfid->dirents, file); - mutex_unlock(&cfid->dirents.de_mutex); - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/reparse.c BPI-Router-Linux-kernel-6.16.12/fs/smb/client/reparse.c ---- BPI-Router-Linux-kernel/fs/smb/client/reparse.c 2025-10-22 13:53:23.539327574 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/reparse.c 2025-10-22 13:53:56.735168080 -0400 -@@ -38,7 +38,7 @@ int smb2_create_reparse_symlink(const un - struct dentry *dentry, struct cifs_tcon *tcon, - const char *full_path, const char *symname) - { -- switch (get_cifs_symlink_type(CIFS_SB(inode->i_sb))) { -+ switch (cifs_symlink_type(CIFS_SB(inode->i_sb))) { - case CIFS_SYMLINK_TYPE_NATIVE: - return create_native_symlink(xid, inode, dentry, tcon, full_path, symname); - case CIFS_SYMLINK_TYPE_NFS: -@@ -57,6 +57,7 @@ static int create_native_symlink(const u - struct reparse_symlink_data_buffer *buf = NULL; - struct cifs_open_info_data data = {}; - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); -+ const char *symroot = cifs_sb->ctx->symlinkroot; - struct inode *new; - struct kvec iov; - __le16 *path = NULL; -@@ -82,7 +83,8 @@ static int create_native_symlink(const u - .symlink_target = symlink_target, - }; - -- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) && symname[0] == '/') { -+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) && -+ symroot && symname[0] == '/') { - /* - * This is a request to create an absolute symlink on the server - * which does not support POSIX paths, and expects symlink in -@@ -92,7 +94,7 @@ static int create_native_symlink(const u - * ensure compatibility of this symlink stored in absolute form - * on the SMB server. - */ -- if (!strstarts(symname, cifs_sb->ctx->symlinkroot)) { -+ if (!strstarts(symname, symroot)) { - /* - * If the absolute Linux symlink target path is not - * inside "symlinkroot" location then there is no way -@@ -101,12 +103,12 @@ static int create_native_symlink(const u - cifs_dbg(VFS, - "absolute symlink '%s' cannot be converted to NT format " - "because it is outside of symlinkroot='%s'\n", -- symname, cifs_sb->ctx->symlinkroot); -+ symname, symroot); - rc = -EINVAL; - goto out; - } -- len = strlen(cifs_sb->ctx->symlinkroot); -- if (cifs_sb->ctx->symlinkroot[len-1] != '/') -+ len = strlen(symroot); -+ if (symroot[len - 1] != '/') - len++; - if (symname[len] >= 'a' && symname[len] <= 'z' && - (symname[len+1] == '/' || symname[len+1] == '\0')) { -@@ -782,6 +784,7 @@ int smb2_parse_native_symlink(char **tar - const char *full_path, - struct cifs_sb_info *cifs_sb) - { -+ const char *symroot = cifs_sb->ctx->symlinkroot; - char sep = CIFS_DIR_SEP(cifs_sb); - char *linux_target = NULL; - char *smb_target = NULL; -@@ -815,7 +818,8 @@ int smb2_parse_native_symlink(char **tar - goto out; - } - -- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) && !relative) { -+ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) && -+ symroot && !relative) { - /* - * This is an absolute symlink from the server which does not - * support POSIX paths, so the symlink is in NT-style path. -@@ -875,15 +879,8 @@ globalroot: - abs_path += sizeof("\\DosDevices\\")-1; - else if (strstarts(abs_path, "\\GLOBAL??\\")) - abs_path += sizeof("\\GLOBAL??\\")-1; -- else { -- /* Unhandled absolute symlink, points outside of DOS/Win32 */ -- cifs_dbg(VFS, -- "absolute symlink '%s' cannot be converted from NT format " -- "because points to unknown target\n", -- smb_target); -- rc = -EIO; -- goto out; -- } -+ else -+ goto out_unhandled_target; - - /* Sometimes path separator after \?? is double backslash */ - if (abs_path[0] == '\\') -@@ -910,25 +907,19 @@ globalroot: - abs_path++; - abs_path[0] = drive_letter; - } else { -- /* Unhandled absolute symlink. Report an error. */ -- cifs_dbg(VFS, -- "absolute symlink '%s' cannot be converted from NT format " -- "because points to unknown target\n", -- smb_target); -- rc = -EIO; -- goto out; -+ goto out_unhandled_target; - } - - abs_path_len = strlen(abs_path)+1; -- symlinkroot_len = strlen(cifs_sb->ctx->symlinkroot); -- if (cifs_sb->ctx->symlinkroot[symlinkroot_len-1] == '/') -+ symlinkroot_len = strlen(symroot); -+ if (symroot[symlinkroot_len - 1] == '/') - symlinkroot_len--; - linux_target = kmalloc(symlinkroot_len + 1 + abs_path_len, GFP_KERNEL); - if (!linux_target) { - rc = -ENOMEM; - goto out; - } -- memcpy(linux_target, cifs_sb->ctx->symlinkroot, symlinkroot_len); -+ memcpy(linux_target, symroot, symlinkroot_len); - linux_target[symlinkroot_len] = '/'; - memcpy(linux_target + symlinkroot_len + 1, abs_path, abs_path_len); - } else if (smb_target[0] == sep && relative) { -@@ -966,6 +957,7 @@ globalroot: - * These paths have same format as Linux symlinks, so no - * conversion is needed. - */ -+out_unhandled_target: - linux_target = smb_target; - smb_target = NULL; - } -@@ -1172,7 +1164,6 @@ out: - if (!have_xattr_dev && (tag == IO_REPARSE_TAG_LX_CHR || tag == IO_REPARSE_TAG_LX_BLK)) - return false; - -- fattr->cf_dtype = S_DT(fattr->cf_mode); - return true; - } - -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/sess.c BPI-Router-Linux-kernel-6.16.12/fs/smb/client/sess.c ---- BPI-Router-Linux-kernel/fs/smb/client/sess.c 2025-10-22 13:53:23.539327574 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/sess.c 2025-10-22 13:53:56.735168080 -0400 -@@ -332,6 +332,7 @@ cifs_chan_update_iface(struct cifs_ses * - struct cifs_server_iface *old_iface = NULL; - struct cifs_server_iface *last_iface = NULL; - struct sockaddr_storage ss; -+ int retry = 0; - - spin_lock(&ses->chan_lock); - chan_index = cifs_ses_get_chan_index(ses, server); -@@ -360,6 +361,7 @@ cifs_chan_update_iface(struct cifs_ses * - return; - } - -+try_again: - last_iface = list_last_entry(&ses->iface_list, struct cifs_server_iface, - iface_head); - iface_min_speed = last_iface->speed; -@@ -397,6 +399,13 @@ cifs_chan_update_iface(struct cifs_ses * - } - - if (list_entry_is_head(iface, &ses->iface_list, iface_head)) { -+ list_for_each_entry(iface, &ses->iface_list, iface_head) -+ iface->weight_fulfilled = 0; -+ -+ /* see if it can be satisfied in second attempt */ -+ if (!retry++) -+ goto try_again; -+ - iface = NULL; - cifs_dbg(FYI, "unable to find a suitable iface\n"); - } -@@ -498,8 +507,7 @@ cifs_ses_add_channel(struct cifs_ses *se - ctx->domainauto = ses->domainAuto; - ctx->domainname = ses->domainName; - -- /* no hostname for extra channels */ -- ctx->server_hostname = ""; -+ ctx->server_hostname = ses->server->hostname; - - ctx->username = ses->user_name; - ctx->password = ses->password; -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/smb2glob.h BPI-Router-Linux-kernel-6.16.12/fs/smb/client/smb2glob.h ---- BPI-Router-Linux-kernel/fs/smb/client/smb2glob.h 2025-10-22 13:53:23.539327574 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/smb2glob.h 2025-10-22 13:53:56.735168080 -0400 -@@ -30,10 +30,9 @@ enum smb2_compound_ops { - SMB2_OP_QUERY_DIR, - SMB2_OP_MKDIR, - SMB2_OP_RENAME, -- SMB2_OP_DELETE, - SMB2_OP_HARDLINK, - SMB2_OP_SET_EOF, -- SMB2_OP_RMDIR, -+ SMB2_OP_UNLINK, - SMB2_OP_POSIX_QUERY_INFO, - SMB2_OP_SET_REPARSE, - SMB2_OP_GET_REPARSE, -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/smb2inode.c BPI-Router-Linux-kernel-6.16.12/fs/smb/client/smb2inode.c ---- BPI-Router-Linux-kernel/fs/smb/client/smb2inode.c 2025-10-22 13:53:23.539327574 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/smb2inode.c 2025-10-22 13:53:56.735168080 -0400 -@@ -207,8 +207,10 @@ replay_again: - server = cifs_pick_channel(ses); - - vars = kzalloc(sizeof(*vars), GFP_ATOMIC); -- if (vars == NULL) -- return -ENOMEM; -+ if (vars == NULL) { -+ rc = -ENOMEM; -+ goto out; -+ } - rqst = &vars->rqst[0]; - rsp_iov = &vars->rsp_iov[0]; - -@@ -344,9 +346,6 @@ replay_again: - trace_smb3_posix_query_info_compound_enter(xid, tcon->tid, - ses->Suid, full_path); - break; -- case SMB2_OP_DELETE: -- trace_smb3_delete_enter(xid, tcon->tid, ses->Suid, full_path); -- break; - case SMB2_OP_MKDIR: - /* - * Directories are created through parameters in the -@@ -354,23 +353,40 @@ replay_again: - */ - trace_smb3_mkdir_enter(xid, tcon->tid, ses->Suid, full_path); - break; -- case SMB2_OP_RMDIR: -- rqst[num_rqst].rq_iov = &vars->si_iov[0]; -+ case SMB2_OP_UNLINK: -+ rqst[num_rqst].rq_iov = vars->unlink_iov; - rqst[num_rqst].rq_nvec = 1; - - size[0] = 1; /* sizeof __u8 See MS-FSCC section 2.4.11 */ - data[0] = &delete_pending[0]; - -- rc = SMB2_set_info_init(tcon, server, -- &rqst[num_rqst], COMPOUND_FID, -- COMPOUND_FID, current->tgid, -- FILE_DISPOSITION_INFORMATION, -- SMB2_O_INFO_FILE, 0, data, size); -- if (rc) -+ if (cfile) { -+ rc = SMB2_set_info_init(tcon, server, -+ &rqst[num_rqst], -+ cfile->fid.persistent_fid, -+ cfile->fid.volatile_fid, -+ current->tgid, -+ FILE_DISPOSITION_INFORMATION, -+ SMB2_O_INFO_FILE, 0, -+ data, size); -+ } else { -+ rc = SMB2_set_info_init(tcon, server, -+ &rqst[num_rqst], -+ COMPOUND_FID, -+ COMPOUND_FID, -+ current->tgid, -+ FILE_DISPOSITION_INFORMATION, -+ SMB2_O_INFO_FILE, 0, -+ data, size); -+ } -+ if (!rc && (!cfile || num_rqst > 1)) { -+ smb2_set_next_command(tcon, &rqst[num_rqst]); -+ smb2_set_related(&rqst[num_rqst]); -+ } else if (rc) { - goto finished; -- smb2_set_next_command(tcon, &rqst[num_rqst]); -- smb2_set_related(&rqst[num_rqst++]); -- trace_smb3_rmdir_enter(xid, tcon->tid, ses->Suid, full_path); -+ } -+ num_rqst++; -+ trace_smb3_unlink_enter(xid, tcon->tid, ses->Suid, full_path); - break; - case SMB2_OP_SET_EOF: - rqst[num_rqst].rq_iov = &vars->si_iov[0]; -@@ -440,7 +456,7 @@ replay_again: - ses->Suid, full_path); - break; - case SMB2_OP_RENAME: -- rqst[num_rqst].rq_iov = &vars->si_iov[0]; -+ rqst[num_rqst].rq_iov = vars->rename_iov; - rqst[num_rqst].rq_nvec = 2; - - len = in_iov[i].iov_len; -@@ -671,7 +687,7 @@ finished: - } - - for (i = 0; i < num_cmds; i++) { -- char *buf = rsp_iov[i + i].iov_base; -+ char *buf = rsp_iov[i + 1].iov_base; - - if (buf && resp_buftype[i + 1] != CIFS_NO_BUFFER) - rc = server->ops->map_error(buf, false); -@@ -730,19 +746,6 @@ finished: - trace_smb3_posix_query_info_compound_done(xid, tcon->tid, - ses->Suid); - break; -- case SMB2_OP_DELETE: -- if (rc) -- trace_smb3_delete_err(xid, tcon->tid, ses->Suid, rc); -- else { -- /* -- * If dentry (hence, inode) is NULL, lease break is going to -- * take care of degrading leases on handles for deleted files. -- */ -- if (inode) -- cifs_mark_open_handles_for_deleted_file(inode, full_path); -- trace_smb3_delete_done(xid, tcon->tid, ses->Suid); -- } -- break; - case SMB2_OP_MKDIR: - if (rc) - trace_smb3_mkdir_err(xid, tcon->tid, ses->Suid, rc); -@@ -763,11 +766,11 @@ finished: - trace_smb3_rename_done(xid, tcon->tid, ses->Suid); - SMB2_set_info_free(&rqst[num_rqst++]); - break; -- case SMB2_OP_RMDIR: -- if (rc) -- trace_smb3_rmdir_err(xid, tcon->tid, ses->Suid, rc); -+ case SMB2_OP_UNLINK: -+ if (!rc) -+ trace_smb3_unlink_done(xid, tcon->tid, ses->Suid); - else -- trace_smb3_rmdir_done(xid, tcon->tid, ses->Suid); -+ trace_smb3_unlink_err(xid, tcon->tid, ses->Suid, rc); - SMB2_set_info_free(&rqst[num_rqst++]); - break; - case SMB2_OP_SET_EOF: -@@ -864,6 +867,7 @@ finished: - smb2_should_replay(tcon, &retries, &cur_sleep)) - goto replay_again; - -+out: - if (cfile) - cifsFileInfo_put(cfile); - -@@ -1162,7 +1166,7 @@ smb2_rmdir(const unsigned int xid, struc - FILE_OPEN, CREATE_NOT_FILE, ACL_NO_MODE); - return smb2_compound_op(xid, tcon, cifs_sb, - name, &oparms, NULL, -- &(int){SMB2_OP_RMDIR}, 1, -+ &(int){SMB2_OP_UNLINK}, 1, - NULL, NULL, NULL, NULL); - } - -@@ -1171,20 +1175,29 @@ smb2_unlink(const unsigned int xid, stru - struct cifs_sb_info *cifs_sb, struct dentry *dentry) - { - struct cifs_open_parms oparms; -+ struct inode *inode = NULL; -+ int rc; - -- oparms = CIFS_OPARMS(cifs_sb, tcon, name, -- DELETE, FILE_OPEN, -- CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT, -- ACL_NO_MODE); -- int rc = smb2_compound_op(xid, tcon, cifs_sb, name, &oparms, -- NULL, &(int){SMB2_OP_DELETE}, 1, -- NULL, NULL, NULL, dentry); -+ if (dentry) -+ inode = d_inode(dentry); -+ -+ oparms = CIFS_OPARMS(cifs_sb, tcon, name, DELETE, -+ FILE_OPEN, OPEN_REPARSE_POINT, ACL_NO_MODE); -+ rc = smb2_compound_op(xid, tcon, cifs_sb, name, &oparms, -+ NULL, &(int){SMB2_OP_UNLINK}, -+ 1, NULL, NULL, NULL, dentry); - if (rc == -EINVAL) { - cifs_dbg(FYI, "invalid lease key, resending request without lease"); - rc = smb2_compound_op(xid, tcon, cifs_sb, name, &oparms, -- NULL, &(int){SMB2_OP_DELETE}, 1, -- NULL, NULL, NULL, NULL); -+ NULL, &(int){SMB2_OP_UNLINK}, -+ 1, NULL, NULL, NULL, NULL); - } -+ /* -+ * If dentry (hence, inode) is NULL, lease break is going to -+ * take care of degrading leases on handles for deleted files. -+ */ -+ if (!rc && inode) -+ cifs_mark_open_handles_for_deleted_file(inode, name); - return rc; - } - -@@ -1346,7 +1359,8 @@ struct inode *smb2_get_reparse_inode(str - * empty object on the server. - */ - if (!(le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS)) -- return ERR_PTR(-EOPNOTSUPP); -+ if (!tcon->posix_extensions) -+ return ERR_PTR(-EOPNOTSUPP); - - oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, - SYNCHRONIZE | DELETE | -@@ -1437,3 +1451,113 @@ out: - cifs_free_open_info(&data); - return rc; - } -+ -+static inline __le16 *utf16_smb2_path(struct cifs_sb_info *cifs_sb, -+ const char *name, size_t namelen) -+{ -+ int len; -+ -+ if (*name == '\\' || -+ (cifs_sb_master_tlink(cifs_sb) && -+ cifs_sb_master_tcon(cifs_sb)->posix_extensions && *name == '/')) -+ name++; -+ return cifs_strndup_to_utf16(name, namelen, &len, -+ cifs_sb->local_nls, -+ cifs_remap(cifs_sb)); -+} -+ -+int smb2_rename_pending_delete(const char *full_path, -+ struct dentry *dentry, -+ const unsigned int xid) -+{ -+ struct cifs_sb_info *cifs_sb = CIFS_SB(d_inode(dentry)->i_sb); -+ struct cifsInodeInfo *cinode = CIFS_I(d_inode(dentry)); -+ __le16 *utf16_path __free(kfree) = NULL; -+ __u32 co = file_create_options(dentry); -+ int cmds[] = { -+ SMB2_OP_SET_INFO, -+ SMB2_OP_RENAME, -+ SMB2_OP_UNLINK, -+ }; -+ const int num_cmds = ARRAY_SIZE(cmds); -+ char *to_name __free(kfree) = NULL; -+ __u32 attrs = cinode->cifsAttrs; -+ struct cifs_open_parms oparms; -+ static atomic_t sillycounter; -+ struct cifsFileInfo *cfile; -+ struct tcon_link *tlink; -+ struct cifs_tcon *tcon; -+ struct kvec iov[2]; -+ const char *ppath; -+ void *page; -+ size_t len; -+ int rc; -+ -+ tlink = cifs_sb_tlink(cifs_sb); -+ if (IS_ERR(tlink)) -+ return PTR_ERR(tlink); -+ tcon = tlink_tcon(tlink); -+ -+ page = alloc_dentry_path(); -+ -+ ppath = build_path_from_dentry(dentry->d_parent, page); -+ if (IS_ERR(ppath)) { -+ rc = PTR_ERR(ppath); -+ goto out; -+ } -+ -+ len = strlen(ppath) + strlen("/.__smb1234") + 1; -+ to_name = kmalloc(len, GFP_KERNEL); -+ if (!to_name) { -+ rc = -ENOMEM; -+ goto out; -+ } -+ -+ scnprintf(to_name, len, "%s%c.__smb%04X", ppath, CIFS_DIR_SEP(cifs_sb), -+ atomic_inc_return(&sillycounter) & 0xffff); -+ -+ utf16_path = utf16_smb2_path(cifs_sb, to_name, len); -+ if (!utf16_path) { -+ rc = -ENOMEM; -+ goto out; -+ } -+ -+ drop_cached_dir_by_name(xid, tcon, full_path, cifs_sb); -+ oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, -+ DELETE | FILE_WRITE_ATTRIBUTES, -+ FILE_OPEN, co, ACL_NO_MODE); -+ -+ attrs &= ~ATTR_READONLY; -+ if (!attrs) -+ attrs = ATTR_NORMAL; -+ if (d_inode(dentry)->i_nlink <= 1) -+ attrs |= ATTR_HIDDEN; -+ iov[0].iov_base = &(FILE_BASIC_INFO) { -+ .Attributes = cpu_to_le32(attrs), -+ }; -+ iov[0].iov_len = sizeof(FILE_BASIC_INFO); -+ iov[1].iov_base = utf16_path; -+ iov[1].iov_len = sizeof(*utf16_path) * UniStrlen((wchar_t *)utf16_path); -+ -+ cifs_get_writable_path(tcon, full_path, FIND_WR_WITH_DELETE, &cfile); -+ rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, iov, -+ cmds, num_cmds, cfile, NULL, NULL, dentry); -+ if (rc == -EINVAL) { -+ cifs_dbg(FYI, "invalid lease key, resending request without lease\n"); -+ cifs_get_writable_path(tcon, full_path, -+ FIND_WR_WITH_DELETE, &cfile); -+ rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, iov, -+ cmds, num_cmds, cfile, NULL, NULL, NULL); -+ } -+ if (!rc) { -+ set_bit(CIFS_INO_DELETE_PENDING, &cinode->flags); -+ } else { -+ cifs_tcon_dbg(FYI, "%s: failed to rename '%s' to '%s': %d\n", -+ __func__, full_path, to_name, rc); -+ rc = -EIO; -+ } -+out: -+ cifs_put_tlink(tlink); -+ free_dentry_path(page); -+ return rc; -+} -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/smb2ops.c BPI-Router-Linux-kernel-6.16.12/fs/smb/client/smb2ops.c ---- BPI-Router-Linux-kernel/fs/smb/client/smb2ops.c 2025-10-22 13:53:23.539327574 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/smb2ops.c 2025-10-22 13:53:56.735168080 -0400 -@@ -772,6 +772,13 @@ next_iface: - bytes_left -= sizeof(*p); - break; - } -+ /* Validate that Next doesn't point beyond the buffer */ -+ if (next > bytes_left) { -+ cifs_dbg(VFS, "%s: invalid Next pointer %zu > %zd\n", -+ __func__, next, bytes_left); -+ rc = -EINVAL; -+ goto out; -+ } - p = (struct network_interface_info_ioctl_rsp *)((u8 *)p+next); - bytes_left -= next; - } -@@ -783,7 +790,9 @@ next_iface: - } - - /* Azure rounds the buffer size up 8, to a 16 byte boundary */ -- if ((bytes_left > 8) || p->Next) -+ if ((bytes_left > 8) || -+ (bytes_left >= offsetof(struct network_interface_info_ioctl_rsp, Next) -+ + sizeof(p->Next) && p->Next)) - cifs_dbg(VFS, "%s: incomplete interface info\n", __func__); - - ses->iface_last_update = jiffies; -@@ -2631,13 +2640,35 @@ smb2_set_next_command(struct cifs_tcon * - } - - /* SMB headers in a compound are 8 byte aligned. */ -- if (!IS_ALIGNED(len, 8)) { -- num_padding = 8 - (len & 7); -+ if (IS_ALIGNED(len, 8)) -+ goto out; -+ -+ num_padding = 8 - (len & 7); -+ if (smb3_encryption_required(tcon)) { -+ int i; -+ -+ /* -+ * Flatten request into a single buffer with required padding as -+ * the encryption layer can't handle the padding iovs. -+ */ -+ for (i = 1; i < rqst->rq_nvec; i++) { -+ memcpy(rqst->rq_iov[0].iov_base + -+ rqst->rq_iov[0].iov_len, -+ rqst->rq_iov[i].iov_base, -+ rqst->rq_iov[i].iov_len); -+ rqst->rq_iov[0].iov_len += rqst->rq_iov[i].iov_len; -+ } -+ memset(rqst->rq_iov[0].iov_base + rqst->rq_iov[0].iov_len, -+ 0, num_padding); -+ rqst->rq_iov[0].iov_len += num_padding; -+ rqst->rq_nvec = 1; -+ } else { - rqst->rq_iov[rqst->rq_nvec].iov_base = smb2_padding; - rqst->rq_iov[rqst->rq_nvec].iov_len = num_padding; - rqst->rq_nvec++; -- len += num_padding; - } -+ len += num_padding; -+out: - shdr->NextCommand = cpu_to_le32(len); - } - -@@ -4316,6 +4347,7 @@ crypt_message(struct TCP_Server_Info *se - u8 key[SMB3_ENC_DEC_KEY_SIZE]; - struct aead_request *req; - u8 *iv; -+ DECLARE_CRYPTO_WAIT(wait); - unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize); - void *creq; - size_t sensitive_size; -@@ -4366,7 +4398,11 @@ crypt_message(struct TCP_Server_Info *se - aead_request_set_crypt(req, sg, sg, crypt_len, iv); - aead_request_set_ad(req, assoc_data_len); - -- rc = enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req); -+ aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, -+ crypto_req_done, &wait); -+ -+ rc = crypto_wait_req(enc ? crypto_aead_encrypt(req) -+ : crypto_aead_decrypt(req), &wait); - - if (!rc && enc) - memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE); -@@ -4482,7 +4518,7 @@ smb3_init_transform_rq(struct TCP_Server - for (int i = 1; i < num_rqst; i++) { - struct smb_rqst *old = &old_rq[i - 1]; - struct smb_rqst *new = &new_rq[i]; -- struct folio_queue *buffer; -+ struct folio_queue *buffer = NULL; - size_t size = iov_iter_count(&old->rq_iter); - - orig_len += smb_rqst_len(server, old); -@@ -5255,7 +5291,8 @@ static int smb2_make_node(unsigned int x - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { - rc = cifs_sfu_make_node(xid, inode, dentry, tcon, - full_path, mode, dev); -- } else if (le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS) { -+ } else if ((le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS) -+ || (tcon->posix_extensions)) { - rc = smb2_mknod_reparse(xid, inode, dentry, tcon, - full_path, mode, dev); - } -@@ -5362,6 +5399,7 @@ struct smb_version_operations smb20_oper - .llseek = smb3_llseek, - .is_status_io_timeout = smb2_is_status_io_timeout, - .is_network_name_deleted = smb2_is_network_name_deleted, -+ .rename_pending_delete = smb2_rename_pending_delete, - }; - #endif /* CIFS_ALLOW_INSECURE_LEGACY */ - -@@ -5467,6 +5505,7 @@ struct smb_version_operations smb21_oper - .llseek = smb3_llseek, - .is_status_io_timeout = smb2_is_status_io_timeout, - .is_network_name_deleted = smb2_is_network_name_deleted, -+ .rename_pending_delete = smb2_rename_pending_delete, - }; - - struct smb_version_operations smb30_operations = { -@@ -5583,6 +5622,7 @@ struct smb_version_operations smb30_oper - .llseek = smb3_llseek, - .is_status_io_timeout = smb2_is_status_io_timeout, - .is_network_name_deleted = smb2_is_network_name_deleted, -+ .rename_pending_delete = smb2_rename_pending_delete, - }; - - struct smb_version_operations smb311_operations = { -@@ -5699,6 +5739,7 @@ struct smb_version_operations smb311_ope - .llseek = smb3_llseek, - .is_status_io_timeout = smb2_is_status_io_timeout, - .is_network_name_deleted = smb2_is_network_name_deleted, -+ .rename_pending_delete = smb2_rename_pending_delete, - }; - - #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/smb2pdu.c BPI-Router-Linux-kernel-6.16.12/fs/smb/client/smb2pdu.c ---- BPI-Router-Linux-kernel/fs/smb/client/smb2pdu.c 2025-10-22 13:53:23.539327574 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/smb2pdu.c 2025-10-22 13:53:56.735168080 -0400 -@@ -424,9 +424,9 @@ skip_sess_setup: - free_xid(xid); - ses->flags &= ~CIFS_SES_FLAGS_PENDING_QUERY_INTERFACES; - -- /* regardless of rc value, setup polling */ -- queue_delayed_work(cifsiod_wq, &tcon->query_interfaces, -- (SMB_INTERFACE_POLL_INTERVAL * HZ)); -+ if (!tcon->ipc && !tcon->dummy) -+ queue_delayed_work(cifsiod_wq, &tcon->query_interfaces, -+ (SMB_INTERFACE_POLL_INTERVAL * HZ)); - - mutex_unlock(&ses->session_mutex); - -@@ -4229,10 +4229,8 @@ void smb2_reconnect_server(struct work_s - } - goto done; - } -- - tcon->status = TID_GOOD; -- tcon->retry = false; -- tcon->need_reconnect = false; -+ tcon->dummy = true; - - /* now reconnect sessions for necessary channels */ - list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) { -@@ -4567,7 +4565,11 @@ smb2_readv_callback(struct mid_q_entry * - cifs_stats_bytes_read(tcon, rdata->got_bytes); - break; - case MID_REQUEST_SUBMITTED: -+ trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_req_submitted); -+ goto do_retry; - case MID_RETRY_NEEDED: -+ trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_retry_needed); -+do_retry: - __set_bit(NETFS_SREQ_NEED_RETRY, &rdata->subreq.flags); - rdata->result = -EAGAIN; - if (server->sign && rdata->got_bytes) -@@ -4578,11 +4580,15 @@ smb2_readv_callback(struct mid_q_entry * - cifs_stats_bytes_read(tcon, rdata->got_bytes); - break; - case MID_RESPONSE_MALFORMED: -+ trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_malformed); - credits.value = le16_to_cpu(shdr->CreditRequest); - credits.instance = server->reconnect_instance; -- fallthrough; -+ rdata->result = -EIO; -+ break; - default: -+ trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_unknown); - rdata->result = -EIO; -+ break; - } - #ifdef CONFIG_CIFS_SMB_DIRECT - /* -@@ -4835,11 +4841,14 @@ smb2_writev_callback(struct mid_q_entry - - switch (mid->mid_state) { - case MID_RESPONSE_RECEIVED: -+ trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_progress); - credits.value = le16_to_cpu(rsp->hdr.CreditRequest); - credits.instance = server->reconnect_instance; - result = smb2_check_receive(mid, server, 0); -- if (result != 0) -+ if (result != 0) { -+ trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_bad); - break; -+ } - - written = le32_to_cpu(rsp->DataLength); - /* -@@ -4861,14 +4870,23 @@ smb2_writev_callback(struct mid_q_entry - } - break; - case MID_REQUEST_SUBMITTED: -+ trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_req_submitted); -+ __set_bit(NETFS_SREQ_NEED_RETRY, &wdata->subreq.flags); -+ result = -EAGAIN; -+ break; - case MID_RETRY_NEEDED: -+ trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_retry_needed); -+ __set_bit(NETFS_SREQ_NEED_RETRY, &wdata->subreq.flags); - result = -EAGAIN; - break; - case MID_RESPONSE_MALFORMED: -+ trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_malformed); - credits.value = le16_to_cpu(rsp->hdr.CreditRequest); - credits.instance = server->reconnect_instance; -- fallthrough; -+ result = -EIO; -+ break; - default: -+ trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_unknown); - result = -EIO; - break; - } -@@ -4908,7 +4926,6 @@ smb2_writev_callback(struct mid_q_entry - server->credits, server->in_flight, - 0, cifs_trace_rw_credits_write_response_clear); - wdata->credits.value = 0; -- trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_progress); - cifs_write_subrequest_terminated(wdata, result ?: written); - release_mid(mid); - trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, 0, -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/smb2proto.h BPI-Router-Linux-kernel-6.16.12/fs/smb/client/smb2proto.h ---- BPI-Router-Linux-kernel/fs/smb/client/smb2proto.h 2025-10-22 13:53:23.539327574 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/smb2proto.h 2025-10-22 13:53:56.735168080 -0400 -@@ -320,5 +320,8 @@ int smb2_create_reparse_symlink(const un - int smb2_make_nfs_node(unsigned int xid, struct inode *inode, - struct dentry *dentry, struct cifs_tcon *tcon, - const char *full_path, umode_t mode, dev_t dev); -+int smb2_rename_pending_delete(const char *full_path, -+ struct dentry *dentry, -+ const unsigned int xid); - - #endif /* _SMB2PROTO_H */ -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/smbdirect.c BPI-Router-Linux-kernel-6.16.12/fs/smb/client/smbdirect.c ---- BPI-Router-Linux-kernel/fs/smb/client/smbdirect.c 2025-10-22 13:53:23.539327574 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/smbdirect.c 2025-10-22 13:53:56.735168080 -0400 -@@ -13,27 +13,23 @@ - #include "cifsproto.h" - #include "smb2proto.h" - --static struct smbd_response *get_empty_queue_buffer( -- struct smbd_connection *info); --static struct smbd_response *get_receive_buffer( -+static struct smbdirect_recv_io *get_receive_buffer( - struct smbd_connection *info); - static void put_receive_buffer( - struct smbd_connection *info, -- struct smbd_response *response); -+ struct smbdirect_recv_io *response); - static int allocate_receive_buffers(struct smbd_connection *info, int num_buf); - static void destroy_receive_buffers(struct smbd_connection *info); - --static void put_empty_packet( -- struct smbd_connection *info, struct smbd_response *response); - static void enqueue_reassembly( - struct smbd_connection *info, -- struct smbd_response *response, int data_length); --static struct smbd_response *_get_first_reassembly( -+ struct smbdirect_recv_io *response, int data_length); -+static struct smbdirect_recv_io *_get_first_reassembly( - struct smbd_connection *info); - - static int smbd_post_recv( - struct smbd_connection *info, -- struct smbd_response *response); -+ struct smbdirect_recv_io *response); - - static int smbd_post_send_empty(struct smbd_connection *info); - -@@ -264,7 +260,7 @@ static inline void *smbd_request_payload - return (void *)request->packet; - } - --static inline void *smbd_response_payload(struct smbd_response *response) -+static inline void *smbdirect_recv_io_payload(struct smbdirect_recv_io *response) - { - return (void *)response->packet; - } -@@ -281,18 +277,20 @@ static void send_done(struct ib_cq *cq, - log_rdma_send(INFO, "smbd_request 0x%p completed wc->status=%d\n", - request, wc->status); - -- if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_SEND) { -- log_rdma_send(ERR, "wc->status=%d wc->opcode=%d\n", -- wc->status, wc->opcode); -- smbd_disconnect_rdma_connection(request->info); -- } -- - for (i = 0; i < request->num_sge; i++) - ib_dma_unmap_single(sc->ib.dev, - request->sge[i].addr, - request->sge[i].length, - DMA_TO_DEVICE); - -+ if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_SEND) { -+ log_rdma_send(ERR, "wc->status=%d wc->opcode=%d\n", -+ wc->status, wc->opcode); -+ mempool_free(request, info->request_mempool); -+ smbd_disconnect_rdma_connection(info); -+ return; -+ } -+ - if (atomic_dec_and_test(&request->info->send_pending)) - wake_up(&request->info->wait_send_pending); - -@@ -317,12 +315,13 @@ static void dump_smbdirect_negotiate_res - * return value: true if negotiation is a success, false if failed - */ - static bool process_negotiation_response( -- struct smbd_response *response, int packet_length) -+ struct smbdirect_recv_io *response, int packet_length) - { -- struct smbd_connection *info = response->info; -- struct smbdirect_socket *sc = &info->socket; -+ struct smbdirect_socket *sc = response->socket; -+ struct smbd_connection *info = -+ container_of(sc, struct smbd_connection, socket); - struct smbdirect_socket_parameters *sp = &sc->parameters; -- struct smbdirect_negotiate_resp *packet = smbd_response_payload(response); -+ struct smbdirect_negotiate_resp *packet = smbdirect_recv_io_payload(response); - - if (packet_length < sizeof(struct smbdirect_negotiate_resp)) { - log_rdma_event(ERR, -@@ -385,15 +384,15 @@ static bool process_negotiation_response - info->max_frmr_depth * PAGE_SIZE); - info->max_frmr_depth = sp->max_read_write_size / PAGE_SIZE; - -+ sc->recv_io.expected = SMBDIRECT_EXPECT_DATA_TRANSFER; - return true; - } - - static void smbd_post_send_credits(struct work_struct *work) - { - int ret = 0; -- int use_receive_queue = 1; - int rc; -- struct smbd_response *response; -+ struct smbdirect_recv_io *response; - struct smbd_connection *info = - container_of(work, struct smbd_connection, - post_send_credits_work); -@@ -407,20 +406,10 @@ static void smbd_post_send_credits(struc - if (info->receive_credit_target > - atomic_read(&info->receive_credits)) { - while (true) { -- if (use_receive_queue) -- response = get_receive_buffer(info); -- else -- response = get_empty_queue_buffer(info); -- if (!response) { -- /* now switch to empty packet queue */ -- if (use_receive_queue) { -- use_receive_queue = 0; -- continue; -- } else -- break; -- } -+ response = get_receive_buffer(info); -+ if (!response) -+ break; - -- response->type = SMBD_TRANSFER_DATA; - response->first_segment = false; - rc = smbd_post_recv(info, response); - if (rc) { -@@ -454,19 +443,23 @@ static void smbd_post_send_credits(struc - static void recv_done(struct ib_cq *cq, struct ib_wc *wc) - { - struct smbdirect_data_transfer *data_transfer; -- struct smbd_response *response = -- container_of(wc->wr_cqe, struct smbd_response, cqe); -- struct smbd_connection *info = response->info; -- int data_length = 0; -+ struct smbdirect_recv_io *response = -+ container_of(wc->wr_cqe, struct smbdirect_recv_io, cqe); -+ struct smbdirect_socket *sc = response->socket; -+ struct smbdirect_socket_parameters *sp = &sc->parameters; -+ struct smbd_connection *info = -+ container_of(sc, struct smbd_connection, socket); -+ u32 data_offset = 0; -+ u32 data_length = 0; -+ u32 remaining_data_length = 0; - - log_rdma_recv(INFO, "response=0x%p type=%d wc status=%d wc opcode %d byte_len=%d pkey_index=%u\n", -- response, response->type, wc->status, wc->opcode, -+ response, sc->recv_io.expected, wc->status, wc->opcode, - wc->byte_len, wc->pkey_index); - - if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_RECV) { - log_rdma_recv(INFO, "wc->status=%d opcode=%d\n", - wc->status, wc->opcode); -- smbd_disconnect_rdma_connection(info); - goto error; - } - -@@ -476,25 +469,37 @@ static void recv_done(struct ib_cq *cq, - response->sge.length, - DMA_FROM_DEVICE); - -- switch (response->type) { -+ switch (sc->recv_io.expected) { - /* SMBD negotiation response */ -- case SMBD_NEGOTIATE_RESP: -- dump_smbdirect_negotiate_resp(smbd_response_payload(response)); -+ case SMBDIRECT_EXPECT_NEGOTIATE_REP: -+ dump_smbdirect_negotiate_resp(smbdirect_recv_io_payload(response)); - info->full_packet_received = true; - info->negotiate_done = - process_negotiation_response(response, wc->byte_len); -+ put_receive_buffer(info, response); - complete(&info->negotiate_completion); -- break; -+ return; - - /* SMBD data transfer packet */ -- case SMBD_TRANSFER_DATA: -- data_transfer = smbd_response_payload(response); -+ case SMBDIRECT_EXPECT_DATA_TRANSFER: -+ data_transfer = smbdirect_recv_io_payload(response); -+ -+ if (wc->byte_len < -+ offsetof(struct smbdirect_data_transfer, padding)) -+ goto error; -+ -+ remaining_data_length = le32_to_cpu(data_transfer->remaining_data_length); -+ data_offset = le32_to_cpu(data_transfer->data_offset); - data_length = le32_to_cpu(data_transfer->data_length); -+ if (wc->byte_len < data_offset || -+ (u64)wc->byte_len < (u64)data_offset + data_length) -+ goto error; -+ -+ if (remaining_data_length > sp->max_fragmented_recv_size || -+ data_length > sp->max_fragmented_recv_size || -+ (u64)remaining_data_length + (u64)data_length > (u64)sp->max_fragmented_recv_size) -+ goto error; - -- /* -- * If this is a packet with data playload place the data in -- * reassembly queue and wake up the reading thread -- */ - if (data_length) { - if (info->full_packet_received) - response->first_segment = true; -@@ -503,16 +508,7 @@ static void recv_done(struct ib_cq *cq, - info->full_packet_received = false; - else - info->full_packet_received = true; -- -- enqueue_reassembly( -- info, -- response, -- data_length); -- } else -- put_empty_packet(info, response); -- -- if (data_length) -- wake_up_interruptible(&info->wait_reassembly_queue); -+ } - - atomic_dec(&info->receive_credits); - info->receive_credit_target = -@@ -540,15 +536,31 @@ static void recv_done(struct ib_cq *cq, - info->keep_alive_requested = KEEP_ALIVE_PENDING; - } - -+ /* -+ * If this is a packet with data playload place the data in -+ * reassembly queue and wake up the reading thread -+ */ -+ if (data_length) { -+ enqueue_reassembly(info, response, data_length); -+ wake_up_interruptible(&info->wait_reassembly_queue); -+ } else -+ put_receive_buffer(info, response); -+ - return; - -- default: -- log_rdma_recv(ERR, -- "unexpected response type=%d\n", response->type); -+ case SMBDIRECT_EXPECT_NEGOTIATE_REQ: -+ /* Only server... */ -+ break; - } - -+ /* -+ * This is an internal error! -+ */ -+ log_rdma_recv(ERR, "unexpected response type=%d\n", sc->recv_io.expected); -+ WARN_ON_ONCE(sc->recv_io.expected != SMBDIRECT_EXPECT_DATA_TRANSFER); - error: - put_receive_buffer(info, response); -+ smbd_disconnect_rdma_connection(info); - } - - static struct rdma_cm_id *smbd_create_id( -@@ -907,8 +919,10 @@ wait_send_queue: - .local_dma_lkey = sc->ib.pd->local_dma_lkey, - .direction = DMA_TO_DEVICE, - }; -+ size_t payload_len = umin(*_remaining_data_length, -+ sp->max_send_size - sizeof(*packet)); - -- rc = smb_extract_iter_to_rdma(iter, *_remaining_data_length, -+ rc = smb_extract_iter_to_rdma(iter, payload_len, - &extract); - if (rc < 0) - goto err_dma; -@@ -1013,13 +1027,34 @@ static int smbd_post_send_empty(struct s - return smbd_post_send_iter(info, NULL, &remaining_data_length); - } - -+static int smbd_post_send_full_iter(struct smbd_connection *info, -+ struct iov_iter *iter, -+ int *_remaining_data_length) -+{ -+ int rc = 0; -+ -+ /* -+ * smbd_post_send_iter() respects the -+ * negotiated max_send_size, so we need to -+ * loop until the full iter is posted -+ */ -+ -+ while (iov_iter_count(iter) > 0) { -+ rc = smbd_post_send_iter(info, iter, _remaining_data_length); -+ if (rc < 0) -+ break; -+ } -+ -+ return rc; -+} -+ - /* - * Post a receive request to the transport - * The remote peer can only send data when a receive request is posted - * The interaction is controlled by send/receive credit system - */ - static int smbd_post_recv( -- struct smbd_connection *info, struct smbd_response *response) -+ struct smbd_connection *info, struct smbdirect_recv_io *response) - { - struct smbdirect_socket *sc = &info->socket; - struct smbdirect_socket_parameters *sp = &sc->parameters; -@@ -1046,6 +1081,7 @@ static int smbd_post_recv( - if (rc) { - ib_dma_unmap_single(sc->ib.dev, response->sge.addr, - response->sge.length, DMA_FROM_DEVICE); -+ response->sge.length = 0; - smbd_disconnect_rdma_connection(info); - log_rdma_recv(ERR, "ib_post_recv failed rc=%d\n", rc); - } -@@ -1056,16 +1092,19 @@ static int smbd_post_recv( - /* Perform SMBD negotiate according to [MS-SMBD] 3.1.5.2 */ - static int smbd_negotiate(struct smbd_connection *info) - { -+ struct smbdirect_socket *sc = &info->socket; - int rc; -- struct smbd_response *response = get_receive_buffer(info); -+ struct smbdirect_recv_io *response = get_receive_buffer(info); - -- response->type = SMBD_NEGOTIATE_RESP; -+ sc->recv_io.expected = SMBDIRECT_EXPECT_NEGOTIATE_REP; - rc = smbd_post_recv(info, response); - log_rdma_event(INFO, "smbd_post_recv rc=%d iov.addr=0x%llx iov.length=%u iov.lkey=0x%x\n", - rc, response->sge.addr, - response->sge.length, response->sge.lkey); -- if (rc) -+ if (rc) { -+ put_receive_buffer(info, response); - return rc; -+ } - - init_completion(&info->negotiate_completion); - info->negotiate_done = false; -@@ -1090,17 +1129,6 @@ static int smbd_negotiate(struct smbd_co - return rc; - } - --static void put_empty_packet( -- struct smbd_connection *info, struct smbd_response *response) --{ -- spin_lock(&info->empty_packet_queue_lock); -- list_add_tail(&response->list, &info->empty_packet_queue); -- info->count_empty_packet_queue++; -- spin_unlock(&info->empty_packet_queue_lock); -- -- queue_work(info->workqueue, &info->post_send_credits_work); --} -- - /* - * Implement Connection.FragmentReassemblyBuffer defined in [MS-SMBD] 3.1.1.1 - * This is a queue for reassembling upper layer payload and present to upper -@@ -1113,7 +1141,7 @@ static void put_empty_packet( - */ - static void enqueue_reassembly( - struct smbd_connection *info, -- struct smbd_response *response, -+ struct smbdirect_recv_io *response, - int data_length) - { - spin_lock(&info->reassembly_queue_lock); -@@ -1137,34 +1165,15 @@ static void enqueue_reassembly( - * Caller is responsible for locking - * return value: the first entry if any, NULL if queue is empty - */ --static struct smbd_response *_get_first_reassembly(struct smbd_connection *info) -+static struct smbdirect_recv_io *_get_first_reassembly(struct smbd_connection *info) - { -- struct smbd_response *ret = NULL; -+ struct smbdirect_recv_io *ret = NULL; - - if (!list_empty(&info->reassembly_queue)) { - ret = list_first_entry( - &info->reassembly_queue, -- struct smbd_response, list); -- } -- return ret; --} -- --static struct smbd_response *get_empty_queue_buffer( -- struct smbd_connection *info) --{ -- struct smbd_response *ret = NULL; -- unsigned long flags; -- -- spin_lock_irqsave(&info->empty_packet_queue_lock, flags); -- if (!list_empty(&info->empty_packet_queue)) { -- ret = list_first_entry( -- &info->empty_packet_queue, -- struct smbd_response, list); -- list_del(&ret->list); -- info->count_empty_packet_queue--; -+ struct smbdirect_recv_io, list); - } -- spin_unlock_irqrestore(&info->empty_packet_queue_lock, flags); -- - return ret; - } - -@@ -1174,16 +1183,16 @@ static struct smbd_response *get_empty_q - * pre-allocated in advance. - * return value: the receive buffer, NULL if none is available - */ --static struct smbd_response *get_receive_buffer(struct smbd_connection *info) -+static struct smbdirect_recv_io *get_receive_buffer(struct smbd_connection *info) - { -- struct smbd_response *ret = NULL; -+ struct smbdirect_recv_io *ret = NULL; - unsigned long flags; - - spin_lock_irqsave(&info->receive_queue_lock, flags); - if (!list_empty(&info->receive_queue)) { - ret = list_first_entry( - &info->receive_queue, -- struct smbd_response, list); -+ struct smbdirect_recv_io, list); - list_del(&ret->list); - info->count_receive_queue--; - info->count_get_receive_buffer++; -@@ -1200,13 +1209,18 @@ static struct smbd_response *get_receive - * receive buffer is returned. - */ - static void put_receive_buffer( -- struct smbd_connection *info, struct smbd_response *response) -+ struct smbd_connection *info, struct smbdirect_recv_io *response) - { - struct smbdirect_socket *sc = &info->socket; - unsigned long flags; - -- ib_dma_unmap_single(sc->ib.dev, response->sge.addr, -- response->sge.length, DMA_FROM_DEVICE); -+ if (likely(response->sge.length != 0)) { -+ ib_dma_unmap_single(sc->ib.dev, -+ response->sge.addr, -+ response->sge.length, -+ DMA_FROM_DEVICE); -+ response->sge.length = 0; -+ } - - spin_lock_irqsave(&info->receive_queue_lock, flags); - list_add_tail(&response->list, &info->receive_queue); -@@ -1220,8 +1234,9 @@ static void put_receive_buffer( - /* Preallocate all receive buffer on transport establishment */ - static int allocate_receive_buffers(struct smbd_connection *info, int num_buf) - { -+ struct smbdirect_socket *sc = &info->socket; -+ struct smbdirect_recv_io *response; - int i; -- struct smbd_response *response; - - INIT_LIST_HEAD(&info->reassembly_queue); - spin_lock_init(&info->reassembly_queue_lock); -@@ -1232,10 +1247,6 @@ static int allocate_receive_buffers(stru - spin_lock_init(&info->receive_queue_lock); - info->count_receive_queue = 0; - -- INIT_LIST_HEAD(&info->empty_packet_queue); -- spin_lock_init(&info->empty_packet_queue_lock); -- info->count_empty_packet_queue = 0; -- - init_waitqueue_head(&info->wait_receive_queues); - - for (i = 0; i < num_buf; i++) { -@@ -1243,7 +1254,8 @@ static int allocate_receive_buffers(stru - if (!response) - goto allocate_failed; - -- response->info = info; -+ response->socket = sc; -+ response->sge.length = 0; - list_add_tail(&response->list, &info->receive_queue); - info->count_receive_queue++; - } -@@ -1254,7 +1266,7 @@ allocate_failed: - while (!list_empty(&info->receive_queue)) { - response = list_first_entry( - &info->receive_queue, -- struct smbd_response, list); -+ struct smbdirect_recv_io, list); - list_del(&response->list); - info->count_receive_queue--; - -@@ -1265,13 +1277,10 @@ allocate_failed: - - static void destroy_receive_buffers(struct smbd_connection *info) - { -- struct smbd_response *response; -+ struct smbdirect_recv_io *response; - - while ((response = get_receive_buffer(info))) - mempool_free(response, info->response_mempool); -- -- while ((response = get_empty_queue_buffer(info))) -- mempool_free(response, info->response_mempool); - } - - /* Implement idle connection timer [MS-SMBD] 3.1.6.2 */ -@@ -1309,7 +1318,7 @@ void smbd_destroy(struct TCP_Server_Info - struct smbd_connection *info = server->smbd_conn; - struct smbdirect_socket *sc; - struct smbdirect_socket_parameters *sp; -- struct smbd_response *response; -+ struct smbdirect_recv_io *response; - unsigned long flags; - - if (!info) { -@@ -1328,17 +1337,16 @@ void smbd_destroy(struct TCP_Server_Info - sc->status == SMBDIRECT_SOCKET_DISCONNECTED); - } - -+ log_rdma_event(INFO, "cancelling post_send_credits_work\n"); -+ disable_work_sync(&info->post_send_credits_work); -+ - log_rdma_event(INFO, "destroying qp\n"); - ib_drain_qp(sc->ib.qp); - rdma_destroy_qp(sc->rdma.cm_id); - sc->ib.qp = NULL; - - log_rdma_event(INFO, "cancelling idle timer\n"); -- cancel_delayed_work_sync(&info->idle_timer_work); -- -- log_rdma_event(INFO, "wait for all send posted to IB to finish\n"); -- wait_event(info->wait_send_pending, -- atomic_read(&info->send_pending) == 0); -+ disable_delayed_work_sync(&info->idle_timer_work); - - /* It's not possible for upper layer to get to reassembly */ - log_rdma_event(INFO, "drain the reassembly queue\n"); -@@ -1358,8 +1366,7 @@ void smbd_destroy(struct TCP_Server_Info - - log_rdma_event(INFO, "free receive buffers\n"); - wait_event(info->wait_receive_queues, -- info->count_receive_queue + info->count_empty_packet_queue -- == sp->recv_credit_max); -+ info->count_receive_queue == sp->recv_credit_max); - destroy_receive_buffers(info); - - /* -@@ -1452,6 +1459,9 @@ static int allocate_caches_and_workqueue - char name[MAX_NAME_LEN]; - int rc; - -+ if (WARN_ON_ONCE(sp->max_recv_size < sizeof(struct smbdirect_data_transfer))) -+ return -ENOMEM; -+ - scnprintf(name, MAX_NAME_LEN, "smbd_request_%p", info); - info->request_cache = - kmem_cache_create( -@@ -1468,13 +1478,18 @@ static int allocate_caches_and_workqueue - if (!info->request_mempool) - goto out1; - -- scnprintf(name, MAX_NAME_LEN, "smbd_response_%p", info); -+ scnprintf(name, MAX_NAME_LEN, "smbdirect_recv_io_%p", info); -+ -+ struct kmem_cache_args response_args = { -+ .align = __alignof__(struct smbdirect_recv_io), -+ .useroffset = (offsetof(struct smbdirect_recv_io, packet) + -+ sizeof(struct smbdirect_data_transfer)), -+ .usersize = sp->max_recv_size - sizeof(struct smbdirect_data_transfer), -+ }; - info->response_cache = -- kmem_cache_create( -- name, -- sizeof(struct smbd_response) + -- sp->max_recv_size, -- 0, SLAB_HWCACHE_ALIGN, NULL); -+ kmem_cache_create(name, -+ sizeof(struct smbdirect_recv_io) + sp->max_recv_size, -+ &response_args, SLAB_HWCACHE_ALIGN); - if (!info->response_cache) - goto out2; - -@@ -1649,8 +1664,10 @@ static struct smbd_connection *_smbd_get - goto rdma_connect_failed; - } - -- wait_event_interruptible( -- info->conn_wait, sc->status != SMBDIRECT_SOCKET_CONNECTING); -+ wait_event_interruptible_timeout( -+ info->conn_wait, -+ sc->status != SMBDIRECT_SOCKET_CONNECTING, -+ msecs_to_jiffies(RDMA_RESOLVE_TIMEOUT)); - - if (sc->status != SMBDIRECT_SOCKET_CONNECTED) { - log_rdma_event(ERR, "rdma_connect failed port=%d\n", port); -@@ -1701,10 +1718,9 @@ allocate_mr_failed: - return NULL; - - negotiation_failed: -- cancel_delayed_work_sync(&info->idle_timer_work); -+ disable_delayed_work_sync(&info->idle_timer_work); - destroy_caches_and_workqueue(info); - sc->status = SMBDIRECT_SOCKET_NEGOTIATE_FAILED; -- init_waitqueue_head(&info->conn_wait); - rdma_disconnect(sc->rdma.cm_id); - wait_event(info->conn_wait, - sc->status == SMBDIRECT_SOCKET_DISCONNECTED); -@@ -1747,35 +1763,39 @@ try_again: - } - - /* -- * Receive data from receive reassembly queue -+ * Receive data from the transport's receive reassembly queue - * All the incoming data packets are placed in reassembly queue -- * buf: the buffer to read data into -+ * iter: the buffer to read data into - * size: the length of data to read - * return value: actual data read -- * Note: this implementation copies the data from reassebmly queue to receive -+ * -+ * Note: this implementation copies the data from reassembly queue to receive - * buffers used by upper layer. This is not the optimal code path. A better way - * to do it is to not have upper layer allocate its receive buffers but rather - * borrow the buffer from reassembly queue, and return it after data is - * consumed. But this will require more changes to upper layer code, and also - * need to consider packet boundaries while they still being reassembled. - */ --static int smbd_recv_buf(struct smbd_connection *info, char *buf, -- unsigned int size) -+int smbd_recv(struct smbd_connection *info, struct msghdr *msg) - { - struct smbdirect_socket *sc = &info->socket; -- struct smbd_response *response; -+ struct smbdirect_recv_io *response; - struct smbdirect_data_transfer *data_transfer; -+ size_t size = iov_iter_count(&msg->msg_iter); - int to_copy, to_read, data_read, offset; - u32 data_length, remaining_data_length, data_offset; - int rc; - -+ if (WARN_ON_ONCE(iov_iter_rw(&msg->msg_iter) == WRITE)) -+ return -EINVAL; /* It's a bug in upper layer to get there */ -+ - again: - /* - * No need to hold the reassembly queue lock all the time as we are - * the only one reading from the front of the queue. The transport - * may add more entries to the back of the queue at the same time - */ -- log_read(INFO, "size=%d info->reassembly_data_length=%d\n", size, -+ log_read(INFO, "size=%zd info->reassembly_data_length=%d\n", size, - info->reassembly_data_length); - if (info->reassembly_data_length >= size) { - int queue_length; -@@ -1795,7 +1815,7 @@ again: - offset = info->first_entry_offset; - while (data_read < size) { - response = _get_first_reassembly(info); -- data_transfer = smbd_response_payload(response); -+ data_transfer = smbdirect_recv_io_payload(response); - data_length = le32_to_cpu(data_transfer->data_length); - remaining_data_length = - le32_to_cpu( -@@ -1813,7 +1833,10 @@ again: - if (response->first_segment && size == 4) { - unsigned int rfc1002_len = - data_length + remaining_data_length; -- *((__be32 *)buf) = cpu_to_be32(rfc1002_len); -+ __be32 rfc1002_hdr = cpu_to_be32(rfc1002_len); -+ if (copy_to_iter(&rfc1002_hdr, sizeof(rfc1002_hdr), -+ &msg->msg_iter) != sizeof(rfc1002_hdr)) -+ return -EFAULT; - data_read = 4; - response->first_segment = false; - log_read(INFO, "returning rfc1002 length %d\n", -@@ -1822,10 +1845,9 @@ again: - } - - to_copy = min_t(int, data_length - offset, to_read); -- memcpy( -- buf + data_read, -- (char *)data_transfer + data_offset + offset, -- to_copy); -+ if (copy_to_iter((char *)data_transfer + data_offset + offset, -+ to_copy, &msg->msg_iter) != to_copy) -+ return -EFAULT; - - /* move on to the next buffer? */ - if (to_copy == data_length - offset) { -@@ -1891,90 +1913,6 @@ read_rfc1002_done: - } - - /* -- * Receive a page from receive reassembly queue -- * page: the page to read data into -- * to_read: the length of data to read -- * return value: actual data read -- */ --static int smbd_recv_page(struct smbd_connection *info, -- struct page *page, unsigned int page_offset, -- unsigned int to_read) --{ -- struct smbdirect_socket *sc = &info->socket; -- int ret; -- char *to_address; -- void *page_address; -- -- /* make sure we have the page ready for read */ -- ret = wait_event_interruptible( -- info->wait_reassembly_queue, -- info->reassembly_data_length >= to_read || -- sc->status != SMBDIRECT_SOCKET_CONNECTED); -- if (ret) -- return ret; -- -- /* now we can read from reassembly queue and not sleep */ -- page_address = kmap_atomic(page); -- to_address = (char *) page_address + page_offset; -- -- log_read(INFO, "reading from page=%p address=%p to_read=%d\n", -- page, to_address, to_read); -- -- ret = smbd_recv_buf(info, to_address, to_read); -- kunmap_atomic(page_address); -- -- return ret; --} -- --/* -- * Receive data from transport -- * msg: a msghdr point to the buffer, can be ITER_KVEC or ITER_BVEC -- * return: total bytes read, or 0. SMB Direct will not do partial read. -- */ --int smbd_recv(struct smbd_connection *info, struct msghdr *msg) --{ -- char *buf; -- struct page *page; -- unsigned int to_read, page_offset; -- int rc; -- -- if (iov_iter_rw(&msg->msg_iter) == WRITE) { -- /* It's a bug in upper layer to get there */ -- cifs_dbg(VFS, "Invalid msg iter dir %u\n", -- iov_iter_rw(&msg->msg_iter)); -- rc = -EINVAL; -- goto out; -- } -- -- switch (iov_iter_type(&msg->msg_iter)) { -- case ITER_KVEC: -- buf = msg->msg_iter.kvec->iov_base; -- to_read = msg->msg_iter.kvec->iov_len; -- rc = smbd_recv_buf(info, buf, to_read); -- break; -- -- case ITER_BVEC: -- page = msg->msg_iter.bvec->bv_page; -- page_offset = msg->msg_iter.bvec->bv_offset; -- to_read = msg->msg_iter.bvec->bv_len; -- rc = smbd_recv_page(info, page, page_offset, to_read); -- break; -- -- default: -- /* It's a bug in upper layer to get there */ -- cifs_dbg(VFS, "Invalid msg type %d\n", -- iov_iter_type(&msg->msg_iter)); -- rc = -EINVAL; -- } -- --out: -- /* SMBDirect will read it all or nothing */ -- if (rc > 0) -- msg->msg_iter.count = 0; -- return rc; --} -- --/* - * Send data to transport - * Each rqst is transported as a SMBDirect payload - * rqst: the data to write -@@ -2032,14 +1970,14 @@ int smbd_send(struct TCP_Server_Info *se - klen += rqst->rq_iov[i].iov_len; - iov_iter_kvec(&iter, ITER_SOURCE, rqst->rq_iov, rqst->rq_nvec, klen); - -- rc = smbd_post_send_iter(info, &iter, &remaining_data_length); -+ rc = smbd_post_send_full_iter(info, &iter, &remaining_data_length); - if (rc < 0) - break; - - if (iov_iter_count(&rqst->rq_iter) > 0) { - /* And then the data pages if there are any */ -- rc = smbd_post_send_iter(info, &rqst->rq_iter, -- &remaining_data_length); -+ rc = smbd_post_send_full_iter(info, &rqst->rq_iter, -+ &remaining_data_length); - if (rc < 0) - break; - } -@@ -2054,7 +1992,11 @@ int smbd_send(struct TCP_Server_Info *se - */ - - wait_event(info->wait_send_pending, -- atomic_read(&info->send_pending) == 0); -+ atomic_read(&info->send_pending) == 0 || -+ sc->status != SMBDIRECT_SOCKET_CONNECTED); -+ -+ if (sc->status != SMBDIRECT_SOCKET_CONNECTED && rc == 0) -+ rc = -EAGAIN; - - return rc; - } -@@ -2135,7 +2077,7 @@ static void destroy_mr_list(struct smbd_ - struct smbdirect_socket *sc = &info->socket; - struct smbd_mr *mr, *tmp; - -- cancel_work_sync(&info->mr_recovery_work); -+ disable_work_sync(&info->mr_recovery_work); - list_for_each_entry_safe(mr, tmp, &info->mr_list, list) { - if (mr->state == MR_INVALIDATED) - ib_dma_unmap_sg(sc->ib.dev, mr->sgt.sgl, -@@ -2589,13 +2531,14 @@ static ssize_t smb_extract_folioq_to_rdm - size_t fsize = folioq_folio_size(folioq, slot); - - if (offset < fsize) { -- size_t part = umin(maxsize - ret, fsize - offset); -+ size_t part = umin(maxsize, fsize - offset); - - if (!smb_set_sge(rdma, folio_page(folio, 0), offset, part)) - return -EIO; - - offset += part; - ret += part; -+ maxsize -= part; - } - - if (offset >= fsize) { -@@ -2610,7 +2553,7 @@ static ssize_t smb_extract_folioq_to_rdm - slot = 0; - } - } -- } while (rdma->nr_sge < rdma->max_sge || maxsize > 0); -+ } while (rdma->nr_sge < rdma->max_sge && maxsize > 0); - - iter->folioq = folioq; - iter->folioq_slot = slot; -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/smbdirect.h BPI-Router-Linux-kernel-6.16.12/fs/smb/client/smbdirect.h ---- BPI-Router-Linux-kernel/fs/smb/client/smbdirect.h 2025-10-22 13:53:23.539327574 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/smbdirect.h 2025-10-22 13:53:56.735168080 -0400 -@@ -110,10 +110,6 @@ struct smbd_connection { - int count_receive_queue; - spinlock_t receive_queue_lock; - -- struct list_head empty_packet_queue; -- int count_empty_packet_queue; -- spinlock_t empty_packet_queue_lock; -- - wait_queue_head_t wait_receive_queues; - - /* Reassembly queue */ -@@ -161,11 +157,6 @@ struct smbd_connection { - unsigned int count_send_empty; - }; - --enum smbd_message_type { -- SMBD_NEGOTIATE_RESP, -- SMBD_TRANSFER_DATA, --}; -- - /* Maximum number of SGEs used by smbdirect.c in any send work request */ - #define SMBDIRECT_MAX_SEND_SGE 6 - -@@ -185,24 +176,6 @@ struct smbd_request { - /* Maximum number of SGEs used by smbdirect.c in any receive work request */ - #define SMBDIRECT_MAX_RECV_SGE 1 - --/* The context for a SMBD response */ --struct smbd_response { -- struct smbd_connection *info; -- struct ib_cqe cqe; -- struct ib_sge sge; -- -- enum smbd_message_type type; -- -- /* Link to receive queue or reassembly queue */ -- struct list_head list; -- -- /* Indicate if this is the 1st packet of a payload */ -- bool first_segment; -- -- /* SMBD packet header and payload follows this structure */ -- u8 packet[]; --}; -- - /* Create a SMBDirect session */ - struct smbd_connection *smbd_get_connection( - struct TCP_Server_Info *server, struct sockaddr *dstaddr); -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/client/trace.h BPI-Router-Linux-kernel-6.16.12/fs/smb/client/trace.h ---- BPI-Router-Linux-kernel/fs/smb/client/trace.h 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/client/trace.h 2025-10-22 13:53:56.735168080 -0400 -@@ -140,7 +140,7 @@ DECLARE_EVENT_CLASS(smb3_rw_err_class, - __entry->len = len; - __entry->rc = rc; - ), -- TP_printk("\tR=%08x[%x] xid=%u sid=0x%llx tid=0x%x fid=0x%llx offset=0x%llx len=0x%x rc=%d", -+ TP_printk("R=%08x[%x] xid=%u sid=0x%llx tid=0x%x fid=0x%llx offset=0x%llx len=0x%x rc=%d", - __entry->rreq_debug_id, __entry->rreq_debug_index, - __entry->xid, __entry->sesid, __entry->tid, __entry->fid, - __entry->offset, __entry->len, __entry->rc) -@@ -190,7 +190,7 @@ DECLARE_EVENT_CLASS(smb3_other_err_class - __entry->len = len; - __entry->rc = rc; - ), -- TP_printk("\txid=%u sid=0x%llx tid=0x%x fid=0x%llx offset=0x%llx len=0x%x rc=%d", -+ TP_printk("xid=%u sid=0x%llx tid=0x%x fid=0x%llx offset=0x%llx len=0x%x rc=%d", - __entry->xid, __entry->sesid, __entry->tid, __entry->fid, - __entry->offset, __entry->len, __entry->rc) - ) -@@ -247,7 +247,7 @@ DECLARE_EVENT_CLASS(smb3_copy_range_err_ - __entry->len = len; - __entry->rc = rc; - ), -- TP_printk("\txid=%u sid=0x%llx tid=0x%x source fid=0x%llx source offset=0x%llx target fid=0x%llx target offset=0x%llx len=0x%x rc=%d", -+ TP_printk("xid=%u sid=0x%llx tid=0x%x source fid=0x%llx source offset=0x%llx target fid=0x%llx target offset=0x%llx len=0x%x rc=%d", - __entry->xid, __entry->sesid, __entry->tid, __entry->target_fid, - __entry->src_offset, __entry->target_fid, __entry->target_offset, __entry->len, __entry->rc) - ) -@@ -298,7 +298,7 @@ DECLARE_EVENT_CLASS(smb3_copy_range_done - __entry->target_offset = target_offset; - __entry->len = len; - ), -- TP_printk("\txid=%u sid=0x%llx tid=0x%x source fid=0x%llx source offset=0x%llx target fid=0x%llx target offset=0x%llx len=0x%x", -+ TP_printk("xid=%u sid=0x%llx tid=0x%x source fid=0x%llx source offset=0x%llx target fid=0x%llx target offset=0x%llx len=0x%x", - __entry->xid, __entry->sesid, __entry->tid, __entry->target_fid, - __entry->src_offset, __entry->target_fid, __entry->target_offset, __entry->len) - ) -@@ -482,7 +482,7 @@ DECLARE_EVENT_CLASS(smb3_fd_class, - __entry->tid = tid; - __entry->sesid = sesid; - ), -- TP_printk("\txid=%u sid=0x%llx tid=0x%x fid=0x%llx", -+ TP_printk("xid=%u sid=0x%llx tid=0x%x fid=0x%llx", - __entry->xid, __entry->sesid, __entry->tid, __entry->fid) - ) - -@@ -521,7 +521,7 @@ DECLARE_EVENT_CLASS(smb3_fd_err_class, - __entry->sesid = sesid; - __entry->rc = rc; - ), -- TP_printk("\txid=%u sid=0x%llx tid=0x%x fid=0x%llx rc=%d", -+ TP_printk("xid=%u sid=0x%llx tid=0x%x fid=0x%llx rc=%d", - __entry->xid, __entry->sesid, __entry->tid, __entry->fid, - __entry->rc) - ) -@@ -669,13 +669,12 @@ DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(que - DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(posix_query_info_compound_enter); - DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(hardlink_enter); - DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(rename_enter); --DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(rmdir_enter); -+DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(unlink_enter); - DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(set_eof_enter); - DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(set_info_compound_enter); - DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(set_reparse_compound_enter); - DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(get_reparse_compound_enter); - DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(query_wsl_ea_compound_enter); --DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(delete_enter); - DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(mkdir_enter); - DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(tdis_enter); - DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(mknod_enter); -@@ -710,13 +709,12 @@ DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(quer - DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(posix_query_info_compound_done); - DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(hardlink_done); - DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(rename_done); --DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(rmdir_done); -+DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(unlink_done); - DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(set_eof_done); - DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(set_info_compound_done); - DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(set_reparse_compound_done); - DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(get_reparse_compound_done); - DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(query_wsl_ea_compound_done); --DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(delete_done); - DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(mkdir_done); - DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(tdis_done); - DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(mknod_done); -@@ -756,14 +754,13 @@ DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(query - DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(posix_query_info_compound_err); - DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(hardlink_err); - DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(rename_err); --DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(rmdir_err); -+DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(unlink_err); - DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(set_eof_err); - DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(set_info_compound_err); - DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(set_reparse_compound_err); - DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(get_reparse_compound_err); - DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(query_wsl_ea_compound_err); - DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(mkdir_err); --DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(delete_err); - DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(tdis_err); - DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(mknod_err); - -@@ -794,7 +791,7 @@ DECLARE_EVENT_CLASS(smb3_cmd_err_class, - __entry->status = status; - __entry->rc = rc; - ), -- TP_printk("\tsid=0x%llx tid=0x%x cmd=%u mid=%llu status=0x%x rc=%d", -+ TP_printk("sid=0x%llx tid=0x%x cmd=%u mid=%llu status=0x%x rc=%d", - __entry->sesid, __entry->tid, __entry->cmd, __entry->mid, - __entry->status, __entry->rc) - ) -@@ -829,7 +826,7 @@ DECLARE_EVENT_CLASS(smb3_cmd_done_class, - __entry->cmd = cmd; - __entry->mid = mid; - ), -- TP_printk("\tsid=0x%llx tid=0x%x cmd=%u mid=%llu", -+ TP_printk("sid=0x%llx tid=0x%x cmd=%u mid=%llu", - __entry->sesid, __entry->tid, - __entry->cmd, __entry->mid) - ) -@@ -867,7 +864,7 @@ DECLARE_EVENT_CLASS(smb3_mid_class, - __entry->when_sent = when_sent; - __entry->when_received = when_received; - ), -- TP_printk("\tcmd=%u mid=%llu pid=%u, when_sent=%lu when_rcv=%lu", -+ TP_printk("cmd=%u mid=%llu pid=%u, when_sent=%lu when_rcv=%lu", - __entry->cmd, __entry->mid, __entry->pid, __entry->when_sent, - __entry->when_received) - ) -@@ -898,7 +895,7 @@ DECLARE_EVENT_CLASS(smb3_exit_err_class, - __assign_str(func_name); - __entry->rc = rc; - ), -- TP_printk("\t%s: xid=%u rc=%d", -+ TP_printk("%s: xid=%u rc=%d", - __get_str(func_name), __entry->xid, __entry->rc) - ) - -@@ -924,7 +921,7 @@ DECLARE_EVENT_CLASS(smb3_sync_err_class, - __entry->ino = ino; - __entry->rc = rc; - ), -- TP_printk("\tino=%lu rc=%d", -+ TP_printk("ino=%lu rc=%d", - __entry->ino, __entry->rc) - ) - -@@ -950,7 +947,7 @@ DECLARE_EVENT_CLASS(smb3_enter_exit_clas - __entry->xid = xid; - __assign_str(func_name); - ), -- TP_printk("\t%s: xid=%u", -+ TP_printk("%s: xid=%u", - __get_str(func_name), __entry->xid) - ) - -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/common/smbdirect/smbdirect_socket.h BPI-Router-Linux-kernel-6.16.12/fs/smb/common/smbdirect/smbdirect_socket.h ---- BPI-Router-Linux-kernel/fs/smb/common/smbdirect/smbdirect_socket.h 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/common/smbdirect/smbdirect_socket.h 2025-10-22 13:53:56.735168080 -0400 -@@ -38,6 +38,35 @@ struct smbdirect_socket { - } ib; - - struct smbdirect_socket_parameters parameters; -+ -+ /* -+ * The state for posted receive buffers -+ */ -+ struct { -+ /* -+ * The type of PDU we are expecting -+ */ -+ enum { -+ SMBDIRECT_EXPECT_NEGOTIATE_REQ = 1, -+ SMBDIRECT_EXPECT_NEGOTIATE_REP = 2, -+ SMBDIRECT_EXPECT_DATA_TRANSFER = 3, -+ } expected; -+ } recv_io; -+}; -+ -+struct smbdirect_recv_io { -+ struct smbdirect_socket *socket; -+ struct ib_cqe cqe; -+ struct ib_sge sge; -+ -+ /* Link to free or reassembly list */ -+ struct list_head list; -+ -+ /* Indicate if this is the 1st packet of a payload */ -+ bool first_segment; -+ -+ /* SMBD packet header and payload follows this structure */ -+ u8 packet[]; - }; - - #endif /* __FS_SMB_COMMON_SMBDIRECT_SMBDIRECT_SOCKET_H__ */ -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/server/connection.c BPI-Router-Linux-kernel-6.16.12/fs/smb/server/connection.c ---- BPI-Router-Linux-kernel/fs/smb/server/connection.c 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/server/connection.c 2025-10-22 13:53:56.735168080 -0400 -@@ -40,7 +40,7 @@ void ksmbd_conn_free(struct ksmbd_conn * - kvfree(conn->request_buf); - kfree(conn->preauth_info); - if (atomic_dec_and_test(&conn->refcnt)) { -- ksmbd_free_transport(conn->transport); -+ conn->transport->ops->free_transport(conn->transport); - kfree(conn); - } - } -@@ -504,7 +504,8 @@ void ksmbd_conn_transport_destroy(void) - { - mutex_lock(&init_lock); - ksmbd_tcp_destroy(); -- ksmbd_rdma_destroy(); -+ ksmbd_rdma_stop_listening(); - stop_sessions(); -+ ksmbd_rdma_destroy(); - mutex_unlock(&init_lock); - } -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/server/connection.h BPI-Router-Linux-kernel-6.16.12/fs/smb/server/connection.h ---- BPI-Router-Linux-kernel/fs/smb/server/connection.h 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/server/connection.h 2025-10-22 13:53:56.735168080 -0400 -@@ -46,6 +46,12 @@ struct ksmbd_conn { - struct mutex srv_mutex; - int status; - unsigned int cli_cap; -+ union { -+ __be32 inet_addr; -+#if IS_ENABLED(CONFIG_IPV6) -+ u8 inet6_addr[16]; -+#endif -+ }; - char *request_buf; - struct ksmbd_transport *transport; - struct nls_table *local_nls; -@@ -133,6 +139,7 @@ struct ksmbd_transport_ops { - void *buf, unsigned int len, - struct smb2_buffer_desc_v1 *desc, - unsigned int desc_len); -+ void (*free_transport)(struct ksmbd_transport *kt); - }; - - struct ksmbd_transport { -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/server/oplock.c BPI-Router-Linux-kernel-6.16.12/fs/smb/server/oplock.c ---- BPI-Router-Linux-kernel/fs/smb/server/oplock.c 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/server/oplock.c 2025-10-22 13:53:56.735168080 -0400 -@@ -1102,8 +1102,10 @@ void smb_send_parent_lease_break_noti(st - if (!atomic_inc_not_zero(&opinfo->refcount)) - continue; - -- if (ksmbd_conn_releasing(opinfo->conn)) -+ if (ksmbd_conn_releasing(opinfo->conn)) { -+ opinfo_put(opinfo); - continue; -+ } - - oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE, NULL); - opinfo_put(opinfo); -@@ -1139,8 +1141,11 @@ void smb_lazy_parent_lease_break_close(s - if (!atomic_inc_not_zero(&opinfo->refcount)) - continue; - -- if (ksmbd_conn_releasing(opinfo->conn)) -+ if (ksmbd_conn_releasing(opinfo->conn)) { -+ opinfo_put(opinfo); - continue; -+ } -+ - oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE, NULL); - opinfo_put(opinfo); - } -@@ -1343,8 +1348,10 @@ void smb_break_all_levII_oplock(struct k - if (!atomic_inc_not_zero(&brk_op->refcount)) - continue; - -- if (ksmbd_conn_releasing(brk_op->conn)) -+ if (ksmbd_conn_releasing(brk_op->conn)) { -+ opinfo_put(brk_op); - continue; -+ } - - if (brk_op->is_lease && (brk_op->o_lease->state & - (~(SMB2_LEASE_READ_CACHING_LE | -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/server/smb2pdu.c BPI-Router-Linux-kernel-6.16.12/fs/smb/server/smb2pdu.c ---- BPI-Router-Linux-kernel/fs/smb/server/smb2pdu.c 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/server/smb2pdu.c 2025-10-22 13:53:56.735168080 -0400 -@@ -1607,24 +1607,38 @@ static int krb5_authenticate(struct ksmb - out_len = work->response_sz - - (le16_to_cpu(rsp->SecurityBufferOffset) + 4); - -- /* Check previous session */ -- prev_sess_id = le64_to_cpu(req->PreviousSessionId); -- if (prev_sess_id && prev_sess_id != sess->id) -- destroy_previous_session(conn, sess->user, prev_sess_id); -- - retval = ksmbd_krb5_authenticate(sess, in_blob, in_len, - out_blob, &out_len); - if (retval) { - ksmbd_debug(SMB, "krb5 authentication failed\n"); - return -EINVAL; - } -+ -+ /* Check previous session */ -+ prev_sess_id = le64_to_cpu(req->PreviousSessionId); -+ if (prev_sess_id && prev_sess_id != sess->id) -+ destroy_previous_session(conn, sess->user, prev_sess_id); -+ - rsp->SecurityBufferLength = cpu_to_le16(out_len); - -- if ((conn->sign || server_conf.enforced_signing) || -+ /* -+ * If session state is SMB2_SESSION_VALID, We can assume -+ * that it is reauthentication. And the user/password -+ * has been verified, so return it here. -+ */ -+ if (sess->state == SMB2_SESSION_VALID) { -+ if (conn->binding) -+ goto binding_session; -+ return 0; -+ } -+ -+ if ((rsp->SessionFlags != SMB2_SESSION_FLAG_IS_GUEST_LE && -+ (conn->sign || server_conf.enforced_signing)) || - (req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED)) - sess->sign = true; - -- if (smb3_encryption_negotiated(conn)) { -+ if (smb3_encryption_negotiated(conn) && -+ !(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) { - retval = conn->ops->generate_encryptionkey(conn, sess); - if (retval) { - ksmbd_debug(SMB, -@@ -1637,6 +1651,7 @@ static int krb5_authenticate(struct ksmb - sess->sign = false; - } - -+binding_session: - if (conn->dialect >= SMB30_PROT_ID) { - chann = lookup_chann_list(sess, conn); - if (!chann) { -@@ -1832,8 +1847,6 @@ int smb2_sess_setup(struct ksmbd_work *w - ksmbd_conn_set_good(conn); - sess->state = SMB2_SESSION_VALID; - } -- kfree(sess->Preauth_HashValue); -- sess->Preauth_HashValue = NULL; - } else if (conn->preferred_auth_mech == KSMBD_AUTH_NTLMSSP) { - if (negblob->MessageType == NtLmNegotiate) { - rc = ntlm_negotiate(work, negblob, negblob_len, rsp); -@@ -1860,8 +1873,6 @@ int smb2_sess_setup(struct ksmbd_work *w - kfree(preauth_sess); - } - } -- kfree(sess->Preauth_HashValue); -- sess->Preauth_HashValue = NULL; - } else { - pr_info_ratelimited("Unknown NTLMSSP message type : 0x%x\n", - le32_to_cpu(negblob->MessageType)); -@@ -4871,8 +4882,13 @@ static int get_file_standard_info(struct - sinfo = (struct smb2_file_standard_info *)rsp->Buffer; - delete_pending = ksmbd_inode_pending_delete(fp); - -- sinfo->AllocationSize = cpu_to_le64(stat.blocks << 9); -- sinfo->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size); -+ if (ksmbd_stream_fd(fp) == false) { -+ sinfo->AllocationSize = cpu_to_le64(stat.blocks << 9); -+ sinfo->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size); -+ } else { -+ sinfo->AllocationSize = cpu_to_le64(fp->stream.size); -+ sinfo->EndOfFile = cpu_to_le64(fp->stream.size); -+ } - sinfo->NumberOfLinks = cpu_to_le32(get_nlink(&stat) - delete_pending); - sinfo->DeletePending = delete_pending; - sinfo->Directory = S_ISDIR(stat.mode) ? 1 : 0; -@@ -4935,9 +4951,14 @@ static int get_file_all_info(struct ksmb - file_info->ChangeTime = cpu_to_le64(time); - file_info->Attributes = fp->f_ci->m_fattr; - file_info->Pad1 = 0; -- file_info->AllocationSize = -- cpu_to_le64(stat.blocks << 9); -- file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size); -+ if (ksmbd_stream_fd(fp) == false) { -+ file_info->AllocationSize = -+ cpu_to_le64(stat.blocks << 9); -+ file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size); -+ } else { -+ file_info->AllocationSize = cpu_to_le64(fp->stream.size); -+ file_info->EndOfFile = cpu_to_le64(fp->stream.size); -+ } - file_info->NumberOfLinks = - cpu_to_le32(get_nlink(&stat) - delete_pending); - file_info->DeletePending = delete_pending; -@@ -4946,7 +4967,10 @@ static int get_file_all_info(struct ksmb - file_info->IndexNumber = cpu_to_le64(stat.ino); - file_info->EASize = 0; - file_info->AccessFlags = fp->daccess; -- file_info->CurrentByteOffset = cpu_to_le64(fp->filp->f_pos); -+ if (ksmbd_stream_fd(fp) == false) -+ file_info->CurrentByteOffset = cpu_to_le64(fp->filp->f_pos); -+ else -+ file_info->CurrentByteOffset = cpu_to_le64(fp->stream.pos); - file_info->Mode = fp->coption; - file_info->AlignmentRequirement = 0; - conv_len = smbConvertToUTF16((__le16 *)file_info->FileName, filename, -@@ -5134,8 +5158,13 @@ static int get_file_network_open_info(st - time = ksmbd_UnixTimeToNT(stat.ctime); - file_info->ChangeTime = cpu_to_le64(time); - file_info->Attributes = fp->f_ci->m_fattr; -- file_info->AllocationSize = cpu_to_le64(stat.blocks << 9); -- file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size); -+ if (ksmbd_stream_fd(fp) == false) { -+ file_info->AllocationSize = cpu_to_le64(stat.blocks << 9); -+ file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size); -+ } else { -+ file_info->AllocationSize = cpu_to_le64(fp->stream.size); -+ file_info->EndOfFile = cpu_to_le64(fp->stream.size); -+ } - file_info->Reserved = cpu_to_le32(0); - rsp->OutputBufferLength = - cpu_to_le32(sizeof(struct smb2_file_ntwrk_info)); -@@ -5158,7 +5187,11 @@ static void get_file_position_info(struc - struct smb2_file_pos_info *file_info; - - file_info = (struct smb2_file_pos_info *)rsp->Buffer; -- file_info->CurrentByteOffset = cpu_to_le64(fp->filp->f_pos); -+ if (ksmbd_stream_fd(fp) == false) -+ file_info->CurrentByteOffset = cpu_to_le64(fp->filp->f_pos); -+ else -+ file_info->CurrentByteOffset = cpu_to_le64(fp->stream.pos); -+ - rsp->OutputBufferLength = - cpu_to_le32(sizeof(struct smb2_file_pos_info)); - } -@@ -5247,8 +5280,13 @@ static int find_file_posix_info(struct s - file_info->ChangeTime = cpu_to_le64(time); - file_info->DosAttributes = fp->f_ci->m_fattr; - file_info->Inode = cpu_to_le64(stat.ino); -- file_info->EndOfFile = cpu_to_le64(stat.size); -- file_info->AllocationSize = cpu_to_le64(stat.blocks << 9); -+ if (ksmbd_stream_fd(fp) == false) { -+ file_info->EndOfFile = cpu_to_le64(stat.size); -+ file_info->AllocationSize = cpu_to_le64(stat.blocks << 9); -+ } else { -+ file_info->EndOfFile = cpu_to_le64(fp->stream.size); -+ file_info->AllocationSize = cpu_to_le64(fp->stream.size); -+ } - file_info->HardLinks = cpu_to_le32(stat.nlink); - file_info->Mode = cpu_to_le32(stat.mode & 0777); - switch (stat.mode & S_IFMT) { -@@ -6025,7 +6063,6 @@ static int smb2_create_link(struct ksmbd - { - char *link_name = NULL, *target_name = NULL, *pathname = NULL; - struct path path, parent_path; -- bool file_present = false; - int rc; - - if (buf_len < (u64)sizeof(struct smb2_file_link_info) + -@@ -6058,11 +6095,8 @@ static int smb2_create_link(struct ksmbd - if (rc) { - if (rc != -ENOENT) - goto out; -- } else -- file_present = true; -- -- if (file_info->ReplaceIfExists) { -- if (file_present) { -+ } else { -+ if (file_info->ReplaceIfExists) { - rc = ksmbd_vfs_remove_file(work, &path); - if (rc) { - rc = -EINVAL; -@@ -6070,21 +6104,17 @@ static int smb2_create_link(struct ksmbd - link_name); - goto out; - } -- } -- } else { -- if (file_present) { -+ } else { - rc = -EEXIST; - ksmbd_debug(SMB, "link already exists\n"); - goto out; - } -+ ksmbd_vfs_kern_path_unlock(&parent_path, &path); - } -- - rc = ksmbd_vfs_link(work, target_name, link_name); - if (rc) - rc = -EINVAL; - out: -- if (file_present) -- ksmbd_vfs_kern_path_unlock(&parent_path, &path); - - if (!IS_ERR(link_name)) - kfree(link_name); -@@ -6190,6 +6220,9 @@ static int set_file_allocation_info(stru - if (!(fp->daccess & FILE_WRITE_DATA_LE)) - return -EACCES; - -+ if (ksmbd_stream_fd(fp) == true) -+ return 0; -+ - rc = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS, - AT_STATX_SYNC_AS_STAT); - if (rc) -@@ -6248,7 +6281,8 @@ static int set_end_of_file_info(struct k - * truncate of some filesystem like FAT32 fill zero data in - * truncated range. - */ -- if (inode->i_sb->s_magic != MSDOS_SUPER_MAGIC) { -+ if (inode->i_sb->s_magic != MSDOS_SUPER_MAGIC && -+ ksmbd_stream_fd(fp) == false) { - ksmbd_debug(SMB, "truncated to newsize %lld\n", newsize); - rc = ksmbd_vfs_truncate(work, fp, newsize); - if (rc) { -@@ -6321,7 +6355,13 @@ static int set_file_position_info(struct - return -EINVAL; - } - -- fp->filp->f_pos = current_byte_offset; -+ if (ksmbd_stream_fd(fp) == false) -+ fp->filp->f_pos = current_byte_offset; -+ else { -+ if (current_byte_offset > XATTR_SIZE_MAX) -+ current_byte_offset = XATTR_SIZE_MAX; -+ fp->stream.pos = current_byte_offset; -+ } - return 0; - } - -@@ -8535,11 +8575,6 @@ static void smb20_oplock_break_ack(struc - goto err_out; - } - -- opinfo->op_state = OPLOCK_STATE_NONE; -- wake_up_interruptible_all(&opinfo->oplock_q); -- opinfo_put(opinfo); -- ksmbd_fd_put(work, fp); -- - rsp->StructureSize = cpu_to_le16(24); - rsp->OplockLevel = rsp_oplevel; - rsp->Reserved = 0; -@@ -8547,16 +8582,15 @@ static void smb20_oplock_break_ack(struc - rsp->VolatileFid = volatile_id; - rsp->PersistentFid = persistent_id; - ret = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_oplock_break)); -- if (!ret) -- return; -- -+ if (ret) { - err_out: -+ smb2_set_err_rsp(work); -+ } -+ - opinfo->op_state = OPLOCK_STATE_NONE; - wake_up_interruptible_all(&opinfo->oplock_q); -- - opinfo_put(opinfo); - ksmbd_fd_put(work, fp); -- smb2_set_err_rsp(work); - } - - static int check_lease_state(struct lease *lease, __le32 req_state) -@@ -8686,11 +8720,6 @@ static void smb21_lease_break_ack(struct - } - - lease_state = lease->state; -- opinfo->op_state = OPLOCK_STATE_NONE; -- wake_up_interruptible_all(&opinfo->oplock_q); -- atomic_dec(&opinfo->breaking_cnt); -- wake_up_interruptible_all(&opinfo->oplock_brk); -- opinfo_put(opinfo); - - rsp->StructureSize = cpu_to_le16(36); - rsp->Reserved = 0; -@@ -8699,16 +8728,16 @@ static void smb21_lease_break_ack(struct - rsp->LeaseState = lease_state; - rsp->LeaseDuration = 0; - ret = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_lease_ack)); -- if (!ret) -- return; -- -+ if (ret) { - err_out: -+ smb2_set_err_rsp(work); -+ } -+ -+ opinfo->op_state = OPLOCK_STATE_NONE; - wake_up_interruptible_all(&opinfo->oplock_q); - atomic_dec(&opinfo->breaking_cnt); - wake_up_interruptible_all(&opinfo->oplock_brk); -- - opinfo_put(opinfo); -- smb2_set_err_rsp(work); - } - - /** -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/server/smb_common.c BPI-Router-Linux-kernel-6.16.12/fs/smb/server/smb_common.c ---- BPI-Router-Linux-kernel/fs/smb/server/smb_common.c 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/server/smb_common.c 2025-10-22 13:53:56.735168080 -0400 -@@ -515,7 +515,7 @@ int ksmbd_extract_shortname(struct ksmbd - - p = strrchr(longname, '.'); - if (p == longname) { /*name starts with a dot*/ -- strscpy(extension, "___", strlen("___")); -+ strscpy(extension, "___", sizeof(extension)); - } else { - if (p) { - p++; -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/server/transport_rdma.c BPI-Router-Linux-kernel-6.16.12/fs/smb/server/transport_rdma.c ---- BPI-Router-Linux-kernel/fs/smb/server/transport_rdma.c 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/server/transport_rdma.c 2025-10-22 13:53:56.735168080 -0400 -@@ -129,9 +129,6 @@ struct smb_direct_transport { - spinlock_t recvmsg_queue_lock; - struct list_head recvmsg_queue; - -- spinlock_t empty_recvmsg_queue_lock; -- struct list_head empty_recvmsg_queue; -- - int send_credit_target; - atomic_t send_credits; - spinlock_t lock_new_recv_credits; -@@ -151,7 +148,7 @@ struct smb_direct_transport { - wait_queue_head_t wait_send_pending; - atomic_t send_pending; - -- struct delayed_work post_recv_credits_work; -+ struct work_struct post_recv_credits_work; - struct work_struct send_immediate_work; - struct work_struct disconnect_work; - -@@ -159,7 +156,8 @@ struct smb_direct_transport { - }; - - #define KSMBD_TRANS(t) ((struct ksmbd_transport *)&((t)->transport)) -- -+#define SMBD_TRANS(t) ((struct smb_direct_transport *)container_of(t, \ -+ struct smb_direct_transport, transport)) - enum { - SMB_DIRECT_MSG_NEGOTIATE_REQ = 0, - SMB_DIRECT_MSG_DATA_TRANSFER -@@ -267,40 +265,19 @@ smb_direct_recvmsg *get_free_recvmsg(str - static void put_recvmsg(struct smb_direct_transport *t, - struct smb_direct_recvmsg *recvmsg) - { -- ib_dma_unmap_single(t->cm_id->device, recvmsg->sge.addr, -- recvmsg->sge.length, DMA_FROM_DEVICE); -+ if (likely(recvmsg->sge.length != 0)) { -+ ib_dma_unmap_single(t->cm_id->device, -+ recvmsg->sge.addr, -+ recvmsg->sge.length, -+ DMA_FROM_DEVICE); -+ recvmsg->sge.length = 0; -+ } - - spin_lock(&t->recvmsg_queue_lock); - list_add(&recvmsg->list, &t->recvmsg_queue); - spin_unlock(&t->recvmsg_queue_lock); - } - --static struct --smb_direct_recvmsg *get_empty_recvmsg(struct smb_direct_transport *t) --{ -- struct smb_direct_recvmsg *recvmsg = NULL; -- -- spin_lock(&t->empty_recvmsg_queue_lock); -- if (!list_empty(&t->empty_recvmsg_queue)) { -- recvmsg = list_first_entry(&t->empty_recvmsg_queue, -- struct smb_direct_recvmsg, list); -- list_del(&recvmsg->list); -- } -- spin_unlock(&t->empty_recvmsg_queue_lock); -- return recvmsg; --} -- --static void put_empty_recvmsg(struct smb_direct_transport *t, -- struct smb_direct_recvmsg *recvmsg) --{ -- ib_dma_unmap_single(t->cm_id->device, recvmsg->sge.addr, -- recvmsg->sge.length, DMA_FROM_DEVICE); -- -- spin_lock(&t->empty_recvmsg_queue_lock); -- list_add_tail(&recvmsg->list, &t->empty_recvmsg_queue); -- spin_unlock(&t->empty_recvmsg_queue_lock); --} -- - static void enqueue_reassembly(struct smb_direct_transport *t, - struct smb_direct_recvmsg *recvmsg, - int data_length) -@@ -385,16 +362,13 @@ static struct smb_direct_transport *allo - spin_lock_init(&t->recvmsg_queue_lock); - INIT_LIST_HEAD(&t->recvmsg_queue); - -- spin_lock_init(&t->empty_recvmsg_queue_lock); -- INIT_LIST_HEAD(&t->empty_recvmsg_queue); -- - init_waitqueue_head(&t->wait_send_pending); - atomic_set(&t->send_pending, 0); - - spin_lock_init(&t->lock_new_recv_credits); - -- INIT_DELAYED_WORK(&t->post_recv_credits_work, -- smb_direct_post_recv_credits); -+ INIT_WORK(&t->post_recv_credits_work, -+ smb_direct_post_recv_credits); - INIT_WORK(&t->send_immediate_work, smb_direct_send_immediate_work); - INIT_WORK(&t->disconnect_work, smb_direct_disconnect_rdma_work); - -@@ -410,6 +384,11 @@ err: - return NULL; - } - -+static void smb_direct_free_transport(struct ksmbd_transport *kt) -+{ -+ kfree(SMBD_TRANS(kt)); -+} -+ - static void free_transport(struct smb_direct_transport *t) - { - struct smb_direct_recvmsg *recvmsg; -@@ -420,14 +399,15 @@ static void free_transport(struct smb_di - wait_event(t->wait_send_pending, - atomic_read(&t->send_pending) == 0); - -- cancel_work_sync(&t->disconnect_work); -- cancel_delayed_work_sync(&t->post_recv_credits_work); -- cancel_work_sync(&t->send_immediate_work); -+ disable_work_sync(&t->disconnect_work); -+ disable_work_sync(&t->post_recv_credits_work); -+ disable_work_sync(&t->send_immediate_work); - - if (t->qp) { - ib_drain_qp(t->qp); - ib_mr_pool_destroy(t->qp, &t->qp->rdma_mrs); -- ib_destroy_qp(t->qp); -+ t->qp = NULL; -+ rdma_destroy_qp(t->cm_id); - } - - ksmbd_debug(RDMA, "drain the reassembly queue\n"); -@@ -455,7 +435,6 @@ static void free_transport(struct smb_di - - smb_direct_destroy_pools(t); - ksmbd_conn_free(KSMBD_TRANS(t)->conn); -- kfree(t); - } - - static struct smb_direct_sendmsg -@@ -542,13 +521,13 @@ static void recv_done(struct ib_cq *cq, - t = recvmsg->transport; - - if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_RECV) { -+ put_recvmsg(t, recvmsg); - if (wc->status != IB_WC_WR_FLUSH_ERR) { - pr_err("Recv error. status='%s (%d)' opcode=%d\n", - ib_wc_status_msg(wc->status), wc->status, - wc->opcode); - smb_direct_disconnect_rdma_connection(t); - } -- put_empty_recvmsg(t, recvmsg); - return; - } - -@@ -562,7 +541,8 @@ static void recv_done(struct ib_cq *cq, - switch (recvmsg->type) { - case SMB_DIRECT_MSG_NEGOTIATE_REQ: - if (wc->byte_len < sizeof(struct smb_direct_negotiate_req)) { -- put_empty_recvmsg(t, recvmsg); -+ put_recvmsg(t, recvmsg); -+ smb_direct_disconnect_rdma_connection(t); - return; - } - t->negotiation_requested = true; -@@ -570,27 +550,39 @@ static void recv_done(struct ib_cq *cq, - t->status = SMB_DIRECT_CS_CONNECTED; - enqueue_reassembly(t, recvmsg, 0); - wake_up_interruptible(&t->wait_status); -- break; -+ return; - case SMB_DIRECT_MSG_DATA_TRANSFER: { - struct smb_direct_data_transfer *data_transfer = - (struct smb_direct_data_transfer *)recvmsg->packet; -- unsigned int data_length; -+ u32 remaining_data_length, data_offset, data_length; - int avail_recvmsg_count, receive_credits; - - if (wc->byte_len < - offsetof(struct smb_direct_data_transfer, padding)) { -- put_empty_recvmsg(t, recvmsg); -+ put_recvmsg(t, recvmsg); -+ smb_direct_disconnect_rdma_connection(t); - return; - } - -+ remaining_data_length = le32_to_cpu(data_transfer->remaining_data_length); - data_length = le32_to_cpu(data_transfer->data_length); -- if (data_length) { -- if (wc->byte_len < sizeof(struct smb_direct_data_transfer) + -- (u64)data_length) { -- put_empty_recvmsg(t, recvmsg); -- return; -- } -+ data_offset = le32_to_cpu(data_transfer->data_offset); -+ if (wc->byte_len < data_offset || -+ wc->byte_len < (u64)data_offset + data_length) { -+ put_recvmsg(t, recvmsg); -+ smb_direct_disconnect_rdma_connection(t); -+ return; -+ } -+ if (remaining_data_length > t->max_fragmented_recv_size || -+ data_length > t->max_fragmented_recv_size || -+ (u64)remaining_data_length + (u64)data_length > -+ (u64)t->max_fragmented_recv_size) { -+ put_recvmsg(t, recvmsg); -+ smb_direct_disconnect_rdma_connection(t); -+ return; -+ } - -+ if (data_length) { - if (t->full_packet_received) - recvmsg->first_segment = true; - -@@ -599,16 +591,11 @@ static void recv_done(struct ib_cq *cq, - else - t->full_packet_received = true; - -- enqueue_reassembly(t, recvmsg, (int)data_length); -- wake_up_interruptible(&t->wait_reassembly_queue); -- - spin_lock(&t->receive_credit_lock); - receive_credits = --(t->recv_credits); - avail_recvmsg_count = t->count_avail_recvmsg; - spin_unlock(&t->receive_credit_lock); - } else { -- put_empty_recvmsg(t, recvmsg); -- - spin_lock(&t->receive_credit_lock); - receive_credits = --(t->recv_credits); - avail_recvmsg_count = ++(t->count_avail_recvmsg); -@@ -628,13 +615,24 @@ static void recv_done(struct ib_cq *cq, - wake_up_interruptible(&t->wait_send_credits); - - if (is_receive_credit_post_required(receive_credits, avail_recvmsg_count)) -- mod_delayed_work(smb_direct_wq, -- &t->post_recv_credits_work, 0); -- break; -+ queue_work(smb_direct_wq, &t->post_recv_credits_work); -+ -+ if (data_length) { -+ enqueue_reassembly(t, recvmsg, (int)data_length); -+ wake_up_interruptible(&t->wait_reassembly_queue); -+ } else -+ put_recvmsg(t, recvmsg); -+ -+ return; - } -- default: -- break; - } -+ -+ /* -+ * This is an internal error! -+ */ -+ WARN_ON_ONCE(recvmsg->type != SMB_DIRECT_MSG_DATA_TRANSFER); -+ put_recvmsg(t, recvmsg); -+ smb_direct_disconnect_rdma_connection(t); - } - - static int smb_direct_post_recv(struct smb_direct_transport *t, -@@ -664,6 +662,7 @@ static int smb_direct_post_recv(struct s - ib_dma_unmap_single(t->cm_id->device, - recvmsg->sge.addr, recvmsg->sge.length, - DMA_FROM_DEVICE); -+ recvmsg->sge.length = 0; - smb_direct_disconnect_rdma_connection(t); - return ret; - } -@@ -773,8 +772,7 @@ again: - st->count_avail_recvmsg += queue_removed; - if (is_receive_credit_post_required(st->recv_credits, st->count_avail_recvmsg)) { - spin_unlock(&st->receive_credit_lock); -- mod_delayed_work(smb_direct_wq, -- &st->post_recv_credits_work, 0); -+ queue_work(smb_direct_wq, &st->post_recv_credits_work); - } else { - spin_unlock(&st->receive_credit_lock); - } -@@ -801,11 +799,10 @@ read_rfc1002_done: - static void smb_direct_post_recv_credits(struct work_struct *work) - { - struct smb_direct_transport *t = container_of(work, -- struct smb_direct_transport, post_recv_credits_work.work); -+ struct smb_direct_transport, post_recv_credits_work); - struct smb_direct_recvmsg *recvmsg; - int receive_credits, credits = 0; - int ret; -- int use_free = 1; - - spin_lock(&t->receive_credit_lock); - receive_credits = t->recv_credits; -@@ -813,18 +810,9 @@ static void smb_direct_post_recv_credits - - if (receive_credits < t->recv_credit_target) { - while (true) { -- if (use_free) -- recvmsg = get_free_recvmsg(t); -- else -- recvmsg = get_empty_recvmsg(t); -- if (!recvmsg) { -- if (use_free) { -- use_free = 0; -- continue; -- } else { -- break; -- } -- } -+ recvmsg = get_free_recvmsg(t); -+ if (!recvmsg) -+ break; - - recvmsg->type = SMB_DIRECT_MSG_DATA_TRANSFER; - recvmsg->first_segment = false; -@@ -1229,78 +1217,130 @@ static int smb_direct_writev(struct ksmb - bool need_invalidate, unsigned int remote_key) - { - struct smb_direct_transport *st = smb_trans_direct_transfort(t); -- int remaining_data_length; -- int start, i, j; -- int max_iov_size = st->max_send_size - -+ size_t remaining_data_length; -+ size_t iov_idx; -+ size_t iov_ofs; -+ size_t max_iov_size = st->max_send_size - - sizeof(struct smb_direct_data_transfer); - int ret; -- struct kvec vec; - struct smb_direct_send_ctx send_ctx; -+ int error = 0; - - if (st->status != SMB_DIRECT_CS_CONNECTED) - return -ENOTCONN; - - //FIXME: skip RFC1002 header.. -+ if (WARN_ON_ONCE(niovs <= 1 || iov[0].iov_len != 4)) -+ return -EINVAL; - buflen -= 4; -+ iov_idx = 1; -+ iov_ofs = 0; - - remaining_data_length = buflen; - ksmbd_debug(RDMA, "Sending smb (RDMA): smb_len=%u\n", buflen); - - smb_direct_send_ctx_init(st, &send_ctx, need_invalidate, remote_key); -- start = i = 1; -- buflen = 0; -- while (true) { -- buflen += iov[i].iov_len; -- if (buflen > max_iov_size) { -- if (i > start) { -- remaining_data_length -= -- (buflen - iov[i].iov_len); -- ret = smb_direct_post_send_data(st, &send_ctx, -- &iov[start], i - start, -- remaining_data_length); -- if (ret) -+ while (remaining_data_length) { -+ struct kvec vecs[SMB_DIRECT_MAX_SEND_SGES - 1]; /* minus smbdirect hdr */ -+ size_t possible_bytes = max_iov_size; -+ size_t possible_vecs; -+ size_t bytes = 0; -+ size_t nvecs = 0; -+ -+ /* -+ * For the last message remaining_data_length should be -+ * have been 0 already! -+ */ -+ if (WARN_ON_ONCE(iov_idx >= niovs)) { -+ error = -EINVAL; -+ goto done; -+ } -+ -+ /* -+ * We have 2 factors which limit the arguments we pass -+ * to smb_direct_post_send_data(): -+ * -+ * 1. The number of supported sges for the send, -+ * while one is reserved for the smbdirect header. -+ * And we currently need one SGE per page. -+ * 2. The number of negotiated payload bytes per send. -+ */ -+ possible_vecs = min_t(size_t, ARRAY_SIZE(vecs), niovs - iov_idx); -+ -+ while (iov_idx < niovs && possible_vecs && possible_bytes) { -+ struct kvec *v = &vecs[nvecs]; -+ int page_count; -+ -+ v->iov_base = ((u8 *)iov[iov_idx].iov_base) + iov_ofs; -+ v->iov_len = min_t(size_t, -+ iov[iov_idx].iov_len - iov_ofs, -+ possible_bytes); -+ page_count = get_buf_page_count(v->iov_base, v->iov_len); -+ if (page_count > possible_vecs) { -+ /* -+ * If the number of pages in the buffer -+ * is to much (because we currently require -+ * one SGE per page), we need to limit the -+ * length. -+ * -+ * We know possible_vecs is at least 1, -+ * so we always keep the first page. -+ * -+ * We need to calculate the number extra -+ * pages (epages) we can also keep. -+ * -+ * We calculate the number of bytes in the -+ * first page (fplen), this should never be -+ * larger than v->iov_len because page_count is -+ * at least 2, but adding a limitation feels -+ * better. -+ * -+ * Then we calculate the number of bytes (elen) -+ * we can keep for the extra pages. -+ */ -+ size_t epages = possible_vecs - 1; -+ size_t fpofs = offset_in_page(v->iov_base); -+ size_t fplen = min_t(size_t, PAGE_SIZE - fpofs, v->iov_len); -+ size_t elen = min_t(size_t, v->iov_len - fplen, epages*PAGE_SIZE); -+ -+ v->iov_len = fplen + elen; -+ page_count = get_buf_page_count(v->iov_base, v->iov_len); -+ if (WARN_ON_ONCE(page_count > possible_vecs)) { -+ /* -+ * Something went wrong in the above -+ * logic... -+ */ -+ error = -EINVAL; - goto done; -- } else { -- /* iov[start] is too big, break it */ -- int nvec = (buflen + max_iov_size - 1) / -- max_iov_size; -- -- for (j = 0; j < nvec; j++) { -- vec.iov_base = -- (char *)iov[start].iov_base + -- j * max_iov_size; -- vec.iov_len = -- min_t(int, max_iov_size, -- buflen - max_iov_size * j); -- remaining_data_length -= vec.iov_len; -- ret = smb_direct_post_send_data(st, &send_ctx, &vec, 1, -- remaining_data_length); -- if (ret) -- goto done; - } -- i++; -- if (i == niovs) -- break; - } -- start = i; -- buflen = 0; -- } else { -- i++; -- if (i == niovs) { -- /* send out all remaining vecs */ -- remaining_data_length -= buflen; -- ret = smb_direct_post_send_data(st, &send_ctx, -- &iov[start], i - start, -- remaining_data_length); -- if (ret) -- goto done; -- break; -+ possible_vecs -= page_count; -+ nvecs += 1; -+ possible_bytes -= v->iov_len; -+ bytes += v->iov_len; -+ -+ iov_ofs += v->iov_len; -+ if (iov_ofs >= iov[iov_idx].iov_len) { -+ iov_idx += 1; -+ iov_ofs = 0; - } - } -+ -+ remaining_data_length -= bytes; -+ -+ ret = smb_direct_post_send_data(st, &send_ctx, -+ vecs, nvecs, -+ remaining_data_length); -+ if (unlikely(ret)) { -+ error = ret; -+ goto done; -+ } - } - - done: - ret = smb_direct_flush_send_list(st, &send_ctx, true); -+ if (unlikely(!ret && error)) -+ ret = error; - - /* - * As an optimization, we don't wait for individual I/O to finish -@@ -1692,7 +1732,7 @@ static int smb_direct_prepare_negotiatio - goto out_err; - } - -- smb_direct_post_recv_credits(&t->post_recv_credits_work.work); -+ smb_direct_post_recv_credits(&t->post_recv_credits_work); - return 0; - out_err: - put_recvmsg(t, recvmsg); -@@ -1764,6 +1804,11 @@ static int smb_direct_init_params(struct - return -EINVAL; - } - -+ if (device->attrs.max_send_sge < SMB_DIRECT_MAX_SEND_SGES) { -+ pr_err("warning: device max_send_sge = %d too small\n", -+ device->attrs.max_send_sge); -+ return -EINVAL; -+ } - if (device->attrs.max_recv_sge < SMB_DIRECT_MAX_RECV_SGES) { - pr_err("warning: device max_recv_sge = %d too small\n", - device->attrs.max_recv_sge); -@@ -1787,7 +1832,7 @@ static int smb_direct_init_params(struct - - cap->max_send_wr = max_send_wrs; - cap->max_recv_wr = t->recv_credit_max; -- cap->max_send_sge = max_sge_per_wr; -+ cap->max_send_sge = SMB_DIRECT_MAX_SEND_SGES; - cap->max_recv_sge = SMB_DIRECT_MAX_RECV_SGES; - cap->max_inline_data = 0; - cap->max_rdma_ctxs = t->max_rw_credits; -@@ -1800,8 +1845,6 @@ static void smb_direct_destroy_pools(str - - while ((recvmsg = get_free_recvmsg(t))) - mempool_free(recvmsg, t->recvmsg_mempool); -- while ((recvmsg = get_empty_recvmsg(t))) -- mempool_free(recvmsg, t->recvmsg_mempool); - - mempool_destroy(t->recvmsg_mempool); - t->recvmsg_mempool = NULL; -@@ -1857,6 +1900,7 @@ static int smb_direct_create_pools(struc - if (!recvmsg) - goto err; - recvmsg->transport = t; -+ recvmsg->sge.length = 0; - list_add(&recvmsg->list, &t->recvmsg_queue); - } - t->count_avail_recvmsg = t->recv_credit_max; -@@ -1935,8 +1979,8 @@ static int smb_direct_create_qpair(struc - return 0; - err: - if (t->qp) { -- ib_destroy_qp(t->qp); - t->qp = NULL; -+ rdma_destroy_qp(t->cm_id); - } - if (t->recv_cq) { - ib_destroy_cq(t->recv_cq); -@@ -2215,7 +2259,7 @@ int ksmbd_rdma_init(void) - return 0; - } - --void ksmbd_rdma_destroy(void) -+void ksmbd_rdma_stop_listening(void) - { - if (!smb_direct_listener.cm_id) - return; -@@ -2224,7 +2268,10 @@ void ksmbd_rdma_destroy(void) - rdma_destroy_id(smb_direct_listener.cm_id); - - smb_direct_listener.cm_id = NULL; -+} - -+void ksmbd_rdma_destroy(void) -+{ - if (smb_direct_wq) { - destroy_workqueue(smb_direct_wq); - smb_direct_wq = NULL; -@@ -2281,4 +2328,5 @@ static const struct ksmbd_transport_ops - .read = smb_direct_read, - .rdma_read = smb_direct_rdma_read, - .rdma_write = smb_direct_rdma_write, -+ .free_transport = smb_direct_free_transport, - }; -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/server/transport_rdma.h BPI-Router-Linux-kernel-6.16.12/fs/smb/server/transport_rdma.h ---- BPI-Router-Linux-kernel/fs/smb/server/transport_rdma.h 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/server/transport_rdma.h 2025-10-22 13:53:56.735168080 -0400 -@@ -54,13 +54,15 @@ struct smb_direct_data_transfer { - - #ifdef CONFIG_SMB_SERVER_SMBDIRECT - int ksmbd_rdma_init(void); -+void ksmbd_rdma_stop_listening(void); - void ksmbd_rdma_destroy(void); - bool ksmbd_rdma_capable_netdev(struct net_device *netdev); - void init_smbd_max_io_size(unsigned int sz); - unsigned int get_smbd_max_read_write_size(void); - #else - static inline int ksmbd_rdma_init(void) { return 0; } --static inline int ksmbd_rdma_destroy(void) { return 0; } -+static inline void ksmbd_rdma_stop_listening(void) { } -+static inline void ksmbd_rdma_destroy(void) { } - static inline bool ksmbd_rdma_capable_netdev(struct net_device *netdev) { return false; } - static inline void init_smbd_max_io_size(unsigned int sz) { } - static inline unsigned int get_smbd_max_read_write_size(void) { return 0; } -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/server/transport_tcp.c BPI-Router-Linux-kernel-6.16.12/fs/smb/server/transport_tcp.c ---- BPI-Router-Linux-kernel/fs/smb/server/transport_tcp.c 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/server/transport_tcp.c 2025-10-22 13:53:56.735168080 -0400 -@@ -87,13 +87,21 @@ static struct tcp_transport *alloc_trans - return NULL; - } - -+#if IS_ENABLED(CONFIG_IPV6) -+ if (client_sk->sk->sk_family == AF_INET6) -+ memcpy(&conn->inet6_addr, &client_sk->sk->sk_v6_daddr, 16); -+ else -+ conn->inet_addr = inet_sk(client_sk->sk)->inet_daddr; -+#else -+ conn->inet_addr = inet_sk(client_sk->sk)->inet_daddr; -+#endif - conn->transport = KSMBD_TRANS(t); - KSMBD_TRANS(t)->conn = conn; - KSMBD_TRANS(t)->ops = &ksmbd_tcp_transport_ops; - return t; - } - --void ksmbd_free_transport(struct ksmbd_transport *kt) -+static void ksmbd_tcp_free_transport(struct ksmbd_transport *kt) - { - struct tcp_transport *t = TCP_TRANS(kt); - -@@ -230,6 +238,7 @@ static int ksmbd_kthread_fn(void *p) - { - struct socket *client_sk = NULL; - struct interface *iface = (struct interface *)p; -+ struct ksmbd_conn *conn; - int ret; - - while (!kthread_should_stop()) { -@@ -248,6 +257,34 @@ static int ksmbd_kthread_fn(void *p) - continue; - } - -+ /* -+ * Limits repeated connections from clients with the same IP. -+ */ -+ down_read(&conn_list_lock); -+ list_for_each_entry(conn, &conn_list, conns_list) -+#if IS_ENABLED(CONFIG_IPV6) -+ if (client_sk->sk->sk_family == AF_INET6) { -+ if (memcmp(&client_sk->sk->sk_v6_daddr, -+ &conn->inet6_addr, 16) == 0) { -+ ret = -EAGAIN; -+ break; -+ } -+ } else if (inet_sk(client_sk->sk)->inet_daddr == -+ conn->inet_addr) { -+ ret = -EAGAIN; -+ break; -+ } -+#else -+ if (inet_sk(client_sk->sk)->inet_daddr == -+ conn->inet_addr) { -+ ret = -EAGAIN; -+ break; -+ } -+#endif -+ up_read(&conn_list_lock); -+ if (ret == -EAGAIN) -+ continue; -+ - if (server_conf.max_connections && - atomic_inc_return(&active_num_conn) >= server_conf.max_connections) { - pr_info_ratelimited("Limit the maximum number of connections(%u)\n", -@@ -656,4 +693,5 @@ static const struct ksmbd_transport_ops - .read = ksmbd_tcp_read, - .writev = ksmbd_tcp_writev, - .disconnect = ksmbd_tcp_disconnect, -+ .free_transport = ksmbd_tcp_free_transport, - }; -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/server/vfs.c BPI-Router-Linux-kernel-6.16.12/fs/smb/server/vfs.c ---- BPI-Router-Linux-kernel/fs/smb/server/vfs.c 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/server/vfs.c 2025-10-22 13:53:56.735168080 -0400 -@@ -293,6 +293,7 @@ static int ksmbd_vfs_stream_read(struct - - if (v_len - *pos < count) - count = v_len - *pos; -+ fp->stream.pos = v_len; - - memcpy(buf, &stream_buf[*pos], count); - -@@ -456,8 +457,8 @@ static int ksmbd_vfs_stream_write(struct - true); - if (err < 0) - goto out; -- -- fp->filp->f_pos = *pos; -+ else -+ fp->stream.pos = size; - err = 0; - out: - kvfree(stream_buf); -@@ -547,7 +548,8 @@ int ksmbd_vfs_getattr(const struct path - { - int err; - -- err = vfs_getattr(path, stat, STATX_BTIME, AT_STATX_SYNC_AS_STAT); -+ err = vfs_getattr(path, stat, STATX_BASIC_STATS | STATX_BTIME, -+ AT_STATX_SYNC_AS_STAT); - if (err) - pr_err("getattr failed, err %d\n", err); - return err; -@@ -1281,6 +1283,7 @@ out1: - - err = ksmbd_vfs_lock_parent(parent_path->dentry, path->dentry); - if (err) { -+ mnt_drop_write(parent_path->mnt); - path_put(path); - path_put(parent_path); - } -diff -purNx .git BPI-Router-Linux-kernel/fs/smb/server/vfs_cache.h BPI-Router-Linux-kernel-6.16.12/fs/smb/server/vfs_cache.h ---- BPI-Router-Linux-kernel/fs/smb/server/vfs_cache.h 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/smb/server/vfs_cache.h 2025-10-22 13:53:56.735168080 -0400 -@@ -44,6 +44,7 @@ struct ksmbd_lock { - struct stream { - char *name; - ssize_t size; -+ loff_t pos; - }; - - struct ksmbd_inode { -diff -purNx .git BPI-Router-Linux-kernel/fs/splice.c BPI-Router-Linux-kernel-6.16.12/fs/splice.c ---- BPI-Router-Linux-kernel/fs/splice.c 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/splice.c 2025-10-22 13:53:56.735168080 -0400 -@@ -739,6 +739,9 @@ iter_file_splice_write(struct pipe_inode - sd.pos = kiocb.ki_pos; - if (ret <= 0) - break; -+ WARN_ONCE(ret > sd.total_len - left, -+ "Splice Exceeded! ret=%zd tot=%zu left=%zu\n", -+ ret, sd.total_len, left); - - sd.num_spliced += ret; - sd.total_len -= ret; -diff -purNx .git BPI-Router-Linux-kernel/fs/squashfs/block.c BPI-Router-Linux-kernel-6.16.12/fs/squashfs/block.c ---- BPI-Router-Linux-kernel/fs/squashfs/block.c 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/squashfs/block.c 2025-10-22 13:53:56.735168080 -0400 -@@ -80,23 +80,22 @@ static int squashfs_bio_read_cached(stru - struct address_space *cache_mapping, u64 index, int length, - u64 read_start, u64 read_end, int page_count) - { -- struct page *head_to_cache = NULL, *tail_to_cache = NULL; -+ struct folio *head_to_cache = NULL, *tail_to_cache = NULL; - struct block_device *bdev = fullbio->bi_bdev; - int start_idx = 0, end_idx = 0; -- struct bvec_iter_all iter_all; -+ struct folio_iter fi;; - struct bio *bio = NULL; -- struct bio_vec *bv; - int idx = 0; - int err = 0; - #ifdef CONFIG_SQUASHFS_COMP_CACHE_FULL -- struct page **cache_pages = kmalloc_array(page_count, -- sizeof(void *), GFP_KERNEL | __GFP_ZERO); -+ struct folio **cache_folios = kmalloc_array(page_count, -+ sizeof(*cache_folios), GFP_KERNEL | __GFP_ZERO); - #endif - -- bio_for_each_segment_all(bv, fullbio, iter_all) { -- struct page *page = bv->bv_page; -+ bio_for_each_folio_all(fi, fullbio) { -+ struct folio *folio = fi.folio; - -- if (page->mapping == cache_mapping) { -+ if (folio->mapping == cache_mapping) { - idx++; - continue; - } -@@ -111,13 +110,13 @@ static int squashfs_bio_read_cached(stru - * adjacent blocks. - */ - if (idx == 0 && index != read_start) -- head_to_cache = page; -+ head_to_cache = folio; - else if (idx == page_count - 1 && index + length != read_end) -- tail_to_cache = page; -+ tail_to_cache = folio; - #ifdef CONFIG_SQUASHFS_COMP_CACHE_FULL - /* Cache all pages in the BIO for repeated reads */ -- else if (cache_pages) -- cache_pages[idx] = page; -+ else if (cache_folios) -+ cache_folios[idx] = folio; - #endif - - if (!bio || idx != end_idx) { -@@ -150,45 +149,45 @@ static int squashfs_bio_read_cached(stru - return err; - - if (head_to_cache) { -- int ret = add_to_page_cache_lru(head_to_cache, cache_mapping, -+ int ret = filemap_add_folio(cache_mapping, head_to_cache, - read_start >> PAGE_SHIFT, - GFP_NOIO); - - if (!ret) { -- SetPageUptodate(head_to_cache); -- unlock_page(head_to_cache); -+ folio_mark_uptodate(head_to_cache); -+ folio_unlock(head_to_cache); - } - - } - - if (tail_to_cache) { -- int ret = add_to_page_cache_lru(tail_to_cache, cache_mapping, -+ int ret = filemap_add_folio(cache_mapping, tail_to_cache, - (read_end >> PAGE_SHIFT) - 1, - GFP_NOIO); - - if (!ret) { -- SetPageUptodate(tail_to_cache); -- unlock_page(tail_to_cache); -+ folio_mark_uptodate(tail_to_cache); -+ folio_unlock(tail_to_cache); - } - } - - #ifdef CONFIG_SQUASHFS_COMP_CACHE_FULL -- if (!cache_pages) -+ if (!cache_folios) - goto out; - - for (idx = 0; idx < page_count; idx++) { -- if (!cache_pages[idx]) -+ if (!cache_folios[idx]) - continue; -- int ret = add_to_page_cache_lru(cache_pages[idx], cache_mapping, -+ int ret = filemap_add_folio(cache_mapping, cache_folios[idx], - (read_start >> PAGE_SHIFT) + idx, - GFP_NOIO); - - if (!ret) { -- SetPageUptodate(cache_pages[idx]); -- unlock_page(cache_pages[idx]); -+ folio_mark_uptodate(cache_folios[idx]); -+ folio_unlock(cache_folios[idx]); - } - } -- kfree(cache_pages); -+ kfree(cache_folios); - out: - #endif - return 0; -diff -purNx .git BPI-Router-Linux-kernel/fs/squashfs/super.c BPI-Router-Linux-kernel-6.16.12/fs/squashfs/super.c ---- BPI-Router-Linux-kernel/fs/squashfs/super.c 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/squashfs/super.c 2025-10-22 13:53:56.735168080 -0400 -@@ -187,10 +187,15 @@ static int squashfs_fill_super(struct su - unsigned short flags; - unsigned int fragments; - u64 lookup_table_start, xattr_id_table_start, next_table; -- int err; -+ int err, devblksize = sb_min_blocksize(sb, SQUASHFS_DEVBLK_SIZE); - - TRACE("Entered squashfs_fill_superblock\n"); - -+ if (!devblksize) { -+ errorf(fc, "squashfs: unable to set blocksize\n"); -+ return -EINVAL; -+ } -+ - sb->s_fs_info = kzalloc(sizeof(*msblk), GFP_KERNEL); - if (sb->s_fs_info == NULL) { - ERROR("Failed to allocate squashfs_sb_info\n"); -@@ -201,12 +206,7 @@ static int squashfs_fill_super(struct su - - msblk->panic_on_errors = (opts->errors == Opt_errors_panic); - -- msblk->devblksize = sb_min_blocksize(sb, SQUASHFS_DEVBLK_SIZE); -- if (!msblk->devblksize) { -- errorf(fc, "squashfs: unable to set blocksize\n"); -- return -EINVAL; -- } -- -+ msblk->devblksize = devblksize; - msblk->devblksize_log2 = ffz(~msblk->devblksize); - - mutex_init(&msblk->meta_index_mutex); -diff -purNx .git BPI-Router-Linux-kernel/fs/super.c BPI-Router-Linux-kernel-6.16.12/fs/super.c ---- BPI-Router-Linux-kernel/fs/super.c 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/super.c 2025-10-22 13:53:56.735168080 -0400 -@@ -964,8 +964,10 @@ void iterate_supers_type(struct file_sys - spin_unlock(&sb_lock); - - locked = super_lock_shared(sb); -- if (locked) -+ if (locked) { - f(sb, arg); -+ super_unlock_shared(sb); -+ } - - spin_lock(&sb_lock); - if (p) -diff -purNx .git BPI-Router-Linux-kernel/fs/tracefs/inode.c BPI-Router-Linux-kernel-6.16.12/fs/tracefs/inode.c ---- BPI-Router-Linux-kernel/fs/tracefs/inode.c 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/tracefs/inode.c 2025-10-22 13:53:56.735168080 -0400 -@@ -465,9 +465,20 @@ static int tracefs_d_revalidate(struct i - return !(ei && ei->is_freed); - } - -+static int tracefs_d_delete(const struct dentry *dentry) -+{ -+ /* -+ * We want to keep eventfs dentries around but not tracefs -+ * ones. eventfs dentries have content in d_fsdata. -+ * Use d_fsdata to determine if it's a eventfs dentry or not. -+ */ -+ return dentry->d_fsdata == NULL; -+} -+ - static const struct dentry_operations tracefs_dentry_operations = { - .d_revalidate = tracefs_d_revalidate, - .d_release = tracefs_d_release, -+ .d_delete = tracefs_d_delete, - }; - - static int tracefs_fill_super(struct super_block *sb, struct fs_context *fc) -diff -purNx .git BPI-Router-Linux-kernel/fs/udf/super.c BPI-Router-Linux-kernel-6.16.12/fs/udf/super.c ---- BPI-Router-Linux-kernel/fs/udf/super.c 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/udf/super.c 2025-10-22 13:53:56.739168061 -0400 -@@ -1440,7 +1440,7 @@ static int udf_load_logicalvol(struct su - struct genericPartitionMap *gpm; - uint16_t ident; - struct buffer_head *bh; -- unsigned int table_len; -+ unsigned int table_len, part_map_count; - int ret; - - bh = udf_read_tagged(sb, block, block, &ident); -@@ -1461,7 +1461,16 @@ static int udf_load_logicalvol(struct su - "logical volume"); - if (ret) - goto out_bh; -- ret = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps)); -+ -+ part_map_count = le32_to_cpu(lvd->numPartitionMaps); -+ if (part_map_count > table_len / sizeof(struct genericPartitionMap1)) { -+ udf_err(sb, "error loading logical volume descriptor: " -+ "Too many partition maps (%u > %u)\n", part_map_count, -+ table_len / (unsigned)sizeof(struct genericPartitionMap1)); -+ ret = -EIO; -+ goto out_bh; -+ } -+ ret = udf_sb_alloc_partition_maps(sb, part_map_count); - if (ret) - goto out_bh; - -diff -purNx .git BPI-Router-Linux-kernel/fs/ufs/super.c BPI-Router-Linux-kernel-6.16.12/fs/ufs/super.c ---- BPI-Router-Linux-kernel/fs/ufs/super.c 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/ufs/super.c 2025-10-22 13:53:56.739168061 -0400 -@@ -397,7 +397,7 @@ static int ufs_parse_param(struct fs_con - pr_err("ufstype can't be changed during remount\n"); - return -EINVAL; - } -- if (!ctx->flavour) { -+ if (ctx->flavour) { - pr_err("conflicting ufstype options\n"); - return -EINVAL; - } -diff -purNx .git BPI-Router-Linux-kernel/fs/xattr.c BPI-Router-Linux-kernel-6.16.12/fs/xattr.c ---- BPI-Router-Linux-kernel/fs/xattr.c 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xattr.c 2025-10-22 13:53:56.739168061 -0400 -@@ -1479,6 +1479,7 @@ ssize_t simple_xattr_list(struct inode * - buffer += err; - } - remaining_size -= err; -+ err = 0; - - read_lock(&xattrs->lock); - for (rbp = rb_first(&xattrs->rb_root); rbp; rbp = rb_next(rbp)) { -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/libxfs/xfs_alloc.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/libxfs/xfs_alloc.c ---- BPI-Router-Linux-kernel/fs/xfs/libxfs/xfs_alloc.c 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/libxfs/xfs_alloc.c 2025-10-22 13:53:56.739168061 -0400 -@@ -3444,16 +3444,41 @@ xfs_alloc_read_agf( - - set_bit(XFS_AGSTATE_AGF_INIT, &pag->pag_opstate); - } -+ - #ifdef DEBUG -- else if (!xfs_is_shutdown(mp)) { -- ASSERT(pag->pagf_freeblks == be32_to_cpu(agf->agf_freeblks)); -- ASSERT(pag->pagf_btreeblks == be32_to_cpu(agf->agf_btreeblks)); -- ASSERT(pag->pagf_flcount == be32_to_cpu(agf->agf_flcount)); -- ASSERT(pag->pagf_longest == be32_to_cpu(agf->agf_longest)); -- ASSERT(pag->pagf_bno_level == be32_to_cpu(agf->agf_bno_level)); -- ASSERT(pag->pagf_cnt_level == be32_to_cpu(agf->agf_cnt_level)); -+ /* -+ * It's possible for the AGF to be out of sync if the block device is -+ * silently dropping writes. This can happen in fstests with dmflakey -+ * enabled, which allows the buffer to be cleaned and reclaimed by -+ * memory pressure and then re-read from disk here. We will get a -+ * stale version of the AGF from disk, and nothing good can happen from -+ * here. Hence if we detect this situation, immediately shut down the -+ * filesystem. -+ * -+ * This can also happen if we are already in the middle of a forced -+ * shutdown, so don't bother checking if we are already shut down. -+ */ -+ if (!xfs_is_shutdown(pag_mount(pag))) { -+ bool ok = true; -+ -+ ok &= pag->pagf_freeblks == be32_to_cpu(agf->agf_freeblks); -+ ok &= pag->pagf_freeblks == be32_to_cpu(agf->agf_freeblks); -+ ok &= pag->pagf_btreeblks == be32_to_cpu(agf->agf_btreeblks); -+ ok &= pag->pagf_flcount == be32_to_cpu(agf->agf_flcount); -+ ok &= pag->pagf_longest == be32_to_cpu(agf->agf_longest); -+ ok &= pag->pagf_bno_level == be32_to_cpu(agf->agf_bno_level); -+ ok &= pag->pagf_cnt_level == be32_to_cpu(agf->agf_cnt_level); -+ -+ if (XFS_IS_CORRUPT(pag_mount(pag), !ok)) { -+ xfs_ag_mark_sick(pag, XFS_SICK_AG_AGF); -+ xfs_trans_brelse(tp, agfbp); -+ xfs_force_shutdown(pag_mount(pag), -+ SHUTDOWN_CORRUPT_ONDISK); -+ return -EFSCORRUPTED; -+ } - } --#endif -+#endif /* DEBUG */ -+ - if (agfbpp) - *agfbpp = agfbp; - else -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/libxfs/xfs_attr_remote.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/libxfs/xfs_attr_remote.c ---- BPI-Router-Linux-kernel/fs/xfs/libxfs/xfs_attr_remote.c 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/libxfs/xfs_attr_remote.c 2025-10-22 13:53:56.739168061 -0400 -@@ -435,6 +435,13 @@ xfs_attr_rmtval_get( - 0, &bp, &xfs_attr3_rmt_buf_ops); - if (xfs_metadata_is_sick(error)) - xfs_dirattr_mark_sick(args->dp, XFS_ATTR_FORK); -+ /* -+ * ENODATA from disk implies a disk medium failure; -+ * ENODATA for xattrs means attribute not found, so -+ * disambiguate that here. -+ */ -+ if (error == -ENODATA) -+ error = -EIO; - if (error) - return error; - -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/libxfs/xfs_da_btree.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/libxfs/xfs_da_btree.c ---- BPI-Router-Linux-kernel/fs/xfs/libxfs/xfs_da_btree.c 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/libxfs/xfs_da_btree.c 2025-10-22 13:53:56.739168061 -0400 -@@ -2833,6 +2833,12 @@ xfs_da_read_buf( - &bp, ops); - if (xfs_metadata_is_sick(error)) - xfs_dirattr_mark_sick(dp, whichfork); -+ /* -+ * ENODATA from disk implies a disk medium failure; ENODATA for -+ * xattrs means attribute not found, so disambiguate that here. -+ */ -+ if (error == -ENODATA && whichfork == XFS_ATTR_FORK) -+ error = -EIO; - if (error) - goto out_free; - -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/libxfs/xfs_group.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/libxfs/xfs_group.c ---- BPI-Router-Linux-kernel/fs/xfs/libxfs/xfs_group.c 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/libxfs/xfs_group.c 2025-10-22 13:53:56.739168061 -0400 -@@ -163,7 +163,8 @@ xfs_group_free( - - xfs_defer_drain_free(&xg->xg_intents_drain); - #ifdef __KERNEL__ -- kfree(xg->xg_busy_extents); -+ if (xfs_group_has_extent_busy(xg->xg_mount, xg->xg_type)) -+ kfree(xg->xg_busy_extents); - #endif - - if (uninit) -@@ -189,9 +190,11 @@ xfs_group_insert( - xg->xg_type = type; - - #ifdef __KERNEL__ -- xg->xg_busy_extents = xfs_extent_busy_alloc(); -- if (!xg->xg_busy_extents) -- return -ENOMEM; -+ if (xfs_group_has_extent_busy(mp, type)) { -+ xg->xg_busy_extents = xfs_extent_busy_alloc(); -+ if (!xg->xg_busy_extents) -+ return -ENOMEM; -+ } - spin_lock_init(&xg->xg_state_lock); - xfs_hooks_init(&xg->xg_rmap_update_hooks); - #endif -@@ -210,7 +213,8 @@ xfs_group_insert( - out_drain: - xfs_defer_drain_free(&xg->xg_intents_drain); - #ifdef __KERNEL__ -- kfree(xg->xg_busy_extents); -+ if (xfs_group_has_extent_busy(xg->xg_mount, xg->xg_type)) -+ kfree(xg->xg_busy_extents); - #endif - return error; - } -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/libxfs/xfs_ialloc.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/libxfs/xfs_ialloc.c ---- BPI-Router-Linux-kernel/fs/xfs/libxfs/xfs_ialloc.c 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/libxfs/xfs_ialloc.c 2025-10-22 13:53:56.739168061 -0400 -@@ -2801,12 +2801,35 @@ xfs_ialloc_read_agi( - set_bit(XFS_AGSTATE_AGI_INIT, &pag->pag_opstate); - } - -+#ifdef DEBUG - /* -- * It's possible for these to be out of sync if -- * we are in the middle of a forced shutdown. -+ * It's possible for the AGF to be out of sync if the block device is -+ * silently dropping writes. This can happen in fstests with dmflakey -+ * enabled, which allows the buffer to be cleaned and reclaimed by -+ * memory pressure and then re-read from disk here. We will get a -+ * stale version of the AGF from disk, and nothing good can happen from -+ * here. Hence if we detect this situation, immediately shut down the -+ * filesystem. -+ * -+ * This can also happen if we are already in the middle of a forced -+ * shutdown, so don't bother checking if we are already shut down. - */ -- ASSERT(pag->pagi_freecount == be32_to_cpu(agi->agi_freecount) || -- xfs_is_shutdown(pag_mount(pag))); -+ if (!xfs_is_shutdown(pag_mount(pag))) { -+ bool ok = true; -+ -+ ok &= pag->pagi_freecount == be32_to_cpu(agi->agi_freecount); -+ ok &= pag->pagi_count == be32_to_cpu(agi->agi_count); -+ -+ if (XFS_IS_CORRUPT(pag_mount(pag), !ok)) { -+ xfs_ag_mark_sick(pag, XFS_SICK_AG_AGI); -+ xfs_trans_brelse(tp, agibp); -+ xfs_force_shutdown(pag_mount(pag), -+ SHUTDOWN_CORRUPT_ONDISK); -+ return -EFSCORRUPTED; -+ } -+ } -+#endif /* DEBUG */ -+ - if (agibpp) - *agibpp = agibp; - else -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/libxfs/xfs_refcount.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/libxfs/xfs_refcount.c ---- BPI-Router-Linux-kernel/fs/xfs/libxfs/xfs_refcount.c 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/libxfs/xfs_refcount.c 2025-10-22 13:53:56.739168061 -0400 -@@ -2099,9 +2099,7 @@ xfs_refcount_recover_cow_leftovers( - * recording the CoW debris we cancel the (empty) transaction - * and everything goes away cleanly. - */ -- error = xfs_trans_alloc_empty(mp, &tp); -- if (error) -- return error; -+ tp = xfs_trans_alloc_empty(mp); - - if (isrt) { - xfs_rtgroup_lock(to_rtg(xg), XFS_RTGLOCK_REFCOUNT); -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/scrub/common.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/scrub/common.c ---- BPI-Router-Linux-kernel/fs/xfs/scrub/common.c 2025-10-22 13:53:23.543327555 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/scrub/common.c 2025-10-22 13:53:56.739168061 -0400 -@@ -870,7 +870,8 @@ int - xchk_trans_alloc_empty( - struct xfs_scrub *sc) - { -- return xfs_trans_alloc_empty(sc->mp, &sc->tp); -+ sc->tp = xfs_trans_alloc_empty(sc->mp); -+ return 0; - } - - /* -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/scrub/repair.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/scrub/repair.c ---- BPI-Router-Linux-kernel/fs/xfs/scrub/repair.c 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/scrub/repair.c 2025-10-22 13:53:56.739168061 -0400 -@@ -1279,18 +1279,10 @@ xrep_trans_alloc_hook_dummy( - void **cookiep, - struct xfs_trans **tpp) - { -- int error; -- - *cookiep = current->journal_info; - current->journal_info = NULL; -- -- error = xfs_trans_alloc_empty(mp, tpp); -- if (!error) -- return 0; -- -- current->journal_info = *cookiep; -- *cookiep = NULL; -- return error; -+ *tpp = xfs_trans_alloc_empty(mp); -+ return 0; - } - - /* Cancel a dummy transaction used by a live update hook function. */ -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/scrub/scrub.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/scrub/scrub.c ---- BPI-Router-Linux-kernel/fs/xfs/scrub/scrub.c 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/scrub/scrub.c 2025-10-22 13:53:56.739168061 -0400 -@@ -876,10 +876,7 @@ xchk_scrubv_open_by_handle( - struct xfs_inode *ip; - int error; - -- error = xfs_trans_alloc_empty(mp, &tp); -- if (error) -- return NULL; -- -+ tp = xfs_trans_alloc_empty(mp); - error = xfs_iget(mp, tp, head->svh_ino, XCHK_IGET_FLAGS, 0, &ip); - xfs_trans_cancel(tp); - if (error) -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/scrub/trace.h BPI-Router-Linux-kernel-6.16.12/fs/xfs/scrub/trace.h ---- BPI-Router-Linux-kernel/fs/xfs/scrub/trace.h 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/scrub/trace.h 2025-10-22 13:53:56.739168061 -0400 -@@ -479,7 +479,7 @@ DECLARE_EVENT_CLASS(xchk_dqiter_class, - __field(xfs_exntst_t, state) - ), - TP_fast_assign( -- __entry->dev = cursor->sc->ip->i_mount->m_super->s_dev; -+ __entry->dev = cursor->sc->mp->m_super->s_dev; - __entry->dqtype = cursor->dqtype; - __entry->ino = cursor->quota_ip->i_ino; - __entry->cur_id = cursor->id; -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_attr_item.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_attr_item.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_attr_item.c 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_attr_item.c 2025-10-22 13:53:56.739168061 -0400 -@@ -616,10 +616,7 @@ xfs_attri_iread_extents( - struct xfs_trans *tp; - int error; - -- error = xfs_trans_alloc_empty(ip->i_mount, &tp); -- if (error) -- return error; -- -+ tp = xfs_trans_alloc_empty(ip->i_mount); - xfs_ilock(ip, XFS_ILOCK_EXCL); - error = xfs_iread_extents(tp, ip, XFS_ATTR_FORK); - xfs_iunlock(ip, XFS_ILOCK_EXCL); -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_buf.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_buf.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_buf.c 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_buf.c 2025-10-22 13:53:56.739168061 -0400 -@@ -1683,7 +1683,7 @@ xfs_free_buftarg( - fs_put_dax(btp->bt_daxdev, btp->bt_mount); - /* the main block device is closed by kill_block_super */ - if (btp->bt_bdev != btp->bt_mount->m_super->s_bdev) -- bdev_fput(btp->bt_bdev_file); -+ bdev_fput(btp->bt_file); - kfree(btp); - } - -@@ -1712,8 +1712,8 @@ xfs_configure_buftarg_atomic_writes( - max_bytes = 0; - } - -- btp->bt_bdev_awu_min = min_bytes; -- btp->bt_bdev_awu_max = max_bytes; -+ btp->bt_awu_min = min_bytes; -+ btp->bt_awu_max = max_bytes; - } - - /* Configure a buffer target that abstracts a block device. */ -@@ -1738,14 +1738,9 @@ xfs_configure_buftarg( - return -EINVAL; - } - -- /* -- * Flush the block device pagecache so our bios see anything dirtied -- * before mount. -- */ - if (bdev_can_atomic_write(btp->bt_bdev)) - xfs_configure_buftarg_atomic_writes(btp); -- -- return sync_blockdev(btp->bt_bdev); -+ return 0; - } - - int -@@ -1803,7 +1798,7 @@ xfs_alloc_buftarg( - btp = kzalloc(sizeof(*btp), GFP_KERNEL | __GFP_NOFAIL); - - btp->bt_mount = mp; -- btp->bt_bdev_file = bdev_file; -+ btp->bt_file = bdev_file; - btp->bt_bdev = file_bdev(bdev_file); - btp->bt_dev = btp->bt_bdev->bd_dev; - btp->bt_daxdev = fs_dax_get_by_bdev(btp->bt_bdev, &btp->bt_dax_part_off, -@@ -2081,44 +2076,6 @@ xfs_buf_delwri_submit( - - return error; - } -- --/* -- * Push a single buffer on a delwri queue. -- * -- * The purpose of this function is to submit a single buffer of a delwri queue -- * and return with the buffer still on the original queue. -- * -- * The buffer locking and queue management logic between _delwri_pushbuf() and -- * _delwri_queue() guarantee that the buffer cannot be queued to another list -- * before returning. -- */ --int --xfs_buf_delwri_pushbuf( -- struct xfs_buf *bp, -- struct list_head *buffer_list) --{ -- int error; -- -- ASSERT(bp->b_flags & _XBF_DELWRI_Q); -- -- trace_xfs_buf_delwri_pushbuf(bp, _RET_IP_); -- -- xfs_buf_lock(bp); -- bp->b_flags &= ~(_XBF_DELWRI_Q | XBF_ASYNC); -- bp->b_flags |= XBF_WRITE; -- xfs_buf_submit(bp); -- -- /* -- * The buffer is now locked, under I/O but still on the original delwri -- * queue. Wait for I/O completion, restore the DELWRI_Q flag and -- * return with the buffer unlocked and still on the original queue. -- */ -- error = xfs_buf_iowait(bp); -- bp->b_flags |= _XBF_DELWRI_Q; -- xfs_buf_unlock(bp); -- -- return error; --} - - void xfs_buf_set_ref(struct xfs_buf *bp, int lru_ref) - { -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_buf.h BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_buf.h ---- BPI-Router-Linux-kernel/fs/xfs/xfs_buf.h 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_buf.h 2025-10-22 13:53:56.739168061 -0400 -@@ -94,7 +94,6 @@ void xfs_buf_cache_destroy(struct xfs_bu - */ - struct xfs_buftarg { - dev_t bt_dev; -- struct file *bt_bdev_file; - struct block_device *bt_bdev; - struct dax_device *bt_daxdev; - struct file *bt_file; -@@ -112,9 +111,9 @@ struct xfs_buftarg { - struct percpu_counter bt_readahead_count; - struct ratelimit_state bt_ioerror_rl; - -- /* Atomic write unit values, bytes */ -- unsigned int bt_bdev_awu_min; -- unsigned int bt_bdev_awu_max; -+ /* Hardware atomic write unit values, bytes */ -+ unsigned int bt_awu_min; -+ unsigned int bt_awu_max; - - /* built-in cache, if we're not using the perag one */ - struct xfs_buf_cache bt_cache[]; -@@ -326,7 +325,6 @@ extern bool xfs_buf_delwri_queue(struct - void xfs_buf_delwri_queue_here(struct xfs_buf *bp, struct list_head *bl); - extern int xfs_buf_delwri_submit(struct list_head *); - extern int xfs_buf_delwri_submit_nowait(struct list_head *); --extern int xfs_buf_delwri_pushbuf(struct xfs_buf *, struct list_head *); - - static inline xfs_daddr_t xfs_buf_daddr(struct xfs_buf *bp) - { -@@ -376,7 +374,6 @@ extern void xfs_buftarg_wait(struct xfs_ - extern void xfs_buftarg_drain(struct xfs_buftarg *); - int xfs_configure_buftarg(struct xfs_buftarg *btp, unsigned int sectorsize); - --#define xfs_getsize_buftarg(buftarg) block_size((buftarg)->bt_bdev) - #define xfs_readonly_buftarg(buftarg) bdev_read_only((buftarg)->bt_bdev) - - int xfs_buf_reverify(struct xfs_buf *bp, const struct xfs_buf_ops *ops); -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_buf_item.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_buf_item.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_buf_item.c 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_buf_item.c 2025-10-22 13:53:56.739168061 -0400 -@@ -32,6 +32,61 @@ static inline struct xfs_buf_log_item *B - return container_of(lip, struct xfs_buf_log_item, bli_item); - } - -+static void -+xfs_buf_item_get_format( -+ struct xfs_buf_log_item *bip, -+ int count) -+{ -+ ASSERT(bip->bli_formats == NULL); -+ bip->bli_format_count = count; -+ -+ if (count == 1) { -+ bip->bli_formats = &bip->__bli_format; -+ return; -+ } -+ -+ bip->bli_formats = kzalloc(count * sizeof(struct xfs_buf_log_format), -+ GFP_KERNEL | __GFP_NOFAIL); -+} -+ -+static void -+xfs_buf_item_free_format( -+ struct xfs_buf_log_item *bip) -+{ -+ if (bip->bli_formats != &bip->__bli_format) { -+ kfree(bip->bli_formats); -+ bip->bli_formats = NULL; -+ } -+} -+ -+static void -+xfs_buf_item_free( -+ struct xfs_buf_log_item *bip) -+{ -+ xfs_buf_item_free_format(bip); -+ kvfree(bip->bli_item.li_lv_shadow); -+ kmem_cache_free(xfs_buf_item_cache, bip); -+} -+ -+/* -+ * xfs_buf_item_relse() is called when the buf log item is no longer needed. -+ */ -+static void -+xfs_buf_item_relse( -+ struct xfs_buf_log_item *bip) -+{ -+ struct xfs_buf *bp = bip->bli_buf; -+ -+ trace_xfs_buf_item_relse(bp, _RET_IP_); -+ -+ ASSERT(!test_bit(XFS_LI_IN_AIL, &bip->bli_item.li_flags)); -+ ASSERT(atomic_read(&bip->bli_refcount) == 0); -+ -+ bp->b_log_item = NULL; -+ xfs_buf_rele(bp); -+ xfs_buf_item_free(bip); -+} -+ - /* Is this log iovec plausibly large enough to contain the buffer log format? */ - bool - xfs_buf_log_check_iovec( -@@ -390,6 +445,42 @@ xfs_buf_item_pin( - } - - /* -+ * For a stale BLI, process all the necessary completions that must be -+ * performed when the final BLI reference goes away. The buffer will be -+ * referenced and locked here - we return to the caller with the buffer still -+ * referenced and locked for them to finalise processing of the buffer. -+ */ -+static void -+xfs_buf_item_finish_stale( -+ struct xfs_buf_log_item *bip) -+{ -+ struct xfs_buf *bp = bip->bli_buf; -+ struct xfs_log_item *lip = &bip->bli_item; -+ -+ ASSERT(bip->bli_flags & XFS_BLI_STALE); -+ ASSERT(xfs_buf_islocked(bp)); -+ ASSERT(bp->b_flags & XBF_STALE); -+ ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); -+ ASSERT(list_empty(&lip->li_trans)); -+ ASSERT(!bp->b_transp); -+ -+ if (bip->bli_flags & XFS_BLI_STALE_INODE) { -+ xfs_buf_item_done(bp); -+ xfs_buf_inode_iodone(bp); -+ ASSERT(list_empty(&bp->b_li_list)); -+ return; -+ } -+ -+ /* -+ * We may or may not be on the AIL here, xfs_trans_ail_delete() will do -+ * the right thing regardless of the situation in which we are called. -+ */ -+ xfs_trans_ail_delete(lip, SHUTDOWN_LOG_IO_ERROR); -+ xfs_buf_item_relse(bip); -+ ASSERT(bp->b_log_item == NULL); -+} -+ -+/* - * This is called to unpin the buffer associated with the buf log item which was - * previously pinned with a call to xfs_buf_item_pin(). We enter this function - * with a buffer pin count, a buffer reference and a BLI reference. -@@ -438,13 +529,6 @@ xfs_buf_item_unpin( - } - - if (stale) { -- ASSERT(bip->bli_flags & XFS_BLI_STALE); -- ASSERT(xfs_buf_islocked(bp)); -- ASSERT(bp->b_flags & XBF_STALE); -- ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); -- ASSERT(list_empty(&lip->li_trans)); -- ASSERT(!bp->b_transp); -- - trace_xfs_buf_item_unpin_stale(bip); - - /* -@@ -455,22 +539,7 @@ xfs_buf_item_unpin( - * processing is complete. - */ - xfs_buf_rele(bp); -- -- /* -- * If we get called here because of an IO error, we may or may -- * not have the item on the AIL. xfs_trans_ail_delete() will -- * take care of that situation. xfs_trans_ail_delete() drops -- * the AIL lock. -- */ -- if (bip->bli_flags & XFS_BLI_STALE_INODE) { -- xfs_buf_item_done(bp); -- xfs_buf_inode_iodone(bp); -- ASSERT(list_empty(&bp->b_li_list)); -- } else { -- xfs_trans_ail_delete(lip, SHUTDOWN_LOG_IO_ERROR); -- xfs_buf_item_relse(bp); -- ASSERT(bp->b_log_item == NULL); -- } -+ xfs_buf_item_finish_stale(bip); - xfs_buf_relse(bp); - return; - } -@@ -543,43 +612,42 @@ xfs_buf_item_push( - * Drop the buffer log item refcount and take appropriate action. This helper - * determines whether the bli must be freed or not, since a decrement to zero - * does not necessarily mean the bli is unused. -- * -- * Return true if the bli is freed, false otherwise. - */ --bool -+void - xfs_buf_item_put( - struct xfs_buf_log_item *bip) - { -- struct xfs_log_item *lip = &bip->bli_item; -- bool aborted; -- bool dirty; -+ -+ ASSERT(xfs_buf_islocked(bip->bli_buf)); - - /* drop the bli ref and return if it wasn't the last one */ - if (!atomic_dec_and_test(&bip->bli_refcount)) -- return false; -+ return; - -- /* -- * We dropped the last ref and must free the item if clean or aborted. -- * If the bli is dirty and non-aborted, the buffer was clean in the -- * transaction but still awaiting writeback from previous changes. In -- * that case, the bli is freed on buffer writeback completion. -- */ -- aborted = test_bit(XFS_LI_ABORTED, &lip->li_flags) || -- xlog_is_shutdown(lip->li_log); -- dirty = bip->bli_flags & XFS_BLI_DIRTY; -- if (dirty && !aborted) -- return false; -+ /* If the BLI is in the AIL, then it is still dirty and in use */ -+ if (test_bit(XFS_LI_IN_AIL, &bip->bli_item.li_flags)) { -+ ASSERT(bip->bli_flags & XFS_BLI_DIRTY); -+ return; -+ } - - /* -- * The bli is aborted or clean. An aborted item may be in the AIL -- * regardless of dirty state. For example, consider an aborted -- * transaction that invalidated a dirty bli and cleared the dirty -- * state. -- */ -- if (aborted) -- xfs_trans_ail_delete(lip, 0); -- xfs_buf_item_relse(bip->bli_buf); -- return true; -+ * In shutdown conditions, we can be asked to free a dirty BLI that -+ * isn't in the AIL. This can occur due to a checkpoint aborting a BLI -+ * instead of inserting it into the AIL at checkpoint IO completion. If -+ * there's another bli reference (e.g. a btree cursor holds a clean -+ * reference) and it is released via xfs_trans_brelse(), we can get here -+ * with that aborted, dirty BLI. In this case, it is safe to free the -+ * dirty BLI immediately, as it is not in the AIL and there are no -+ * other references to it. -+ * -+ * We should never get here with a stale BLI via that path as -+ * xfs_trans_brelse() specifically holds onto stale buffers rather than -+ * releasing them. -+ */ -+ ASSERT(!(bip->bli_flags & XFS_BLI_DIRTY) || -+ test_bit(XFS_LI_ABORTED, &bip->bli_item.li_flags)); -+ ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); -+ xfs_buf_item_relse(bip); - } - - /* -@@ -600,6 +668,15 @@ xfs_buf_item_put( - * if necessary but do not unlock the buffer. This is for support of - * xfs_trans_bhold(). Make sure the XFS_BLI_HOLD field is cleared if we don't - * free the item. -+ * -+ * If the XFS_BLI_STALE flag is set, the last reference to the BLI *must* -+ * perform a completion abort of any objects attached to the buffer for IO -+ * tracking purposes. This generally only happens in shutdown situations, -+ * normally xfs_buf_item_unpin() will drop the last BLI reference and perform -+ * completion processing. However, because transaction completion can race with -+ * checkpoint completion during a shutdown, this release context may end up -+ * being the last active reference to the BLI and so needs to perform this -+ * cleanup. - */ - STATIC void - xfs_buf_item_release( -@@ -607,18 +684,19 @@ xfs_buf_item_release( - { - struct xfs_buf_log_item *bip = BUF_ITEM(lip); - struct xfs_buf *bp = bip->bli_buf; -- bool released; - bool hold = bip->bli_flags & XFS_BLI_HOLD; - bool stale = bip->bli_flags & XFS_BLI_STALE; --#if defined(DEBUG) || defined(XFS_WARN) -- bool ordered = bip->bli_flags & XFS_BLI_ORDERED; -- bool dirty = bip->bli_flags & XFS_BLI_DIRTY; - bool aborted = test_bit(XFS_LI_ABORTED, - &lip->li_flags); -+ bool dirty = bip->bli_flags & XFS_BLI_DIRTY; -+#if defined(DEBUG) || defined(XFS_WARN) -+ bool ordered = bip->bli_flags & XFS_BLI_ORDERED; - #endif - - trace_xfs_buf_item_release(bip); - -+ ASSERT(xfs_buf_islocked(bp)); -+ - /* - * The bli dirty state should match whether the blf has logged segments - * except for ordered buffers, where only the bli should be dirty. -@@ -634,16 +712,56 @@ xfs_buf_item_release( - bp->b_transp = NULL; - bip->bli_flags &= ~(XFS_BLI_LOGGED | XFS_BLI_HOLD | XFS_BLI_ORDERED); - -+ /* If there are other references, then we have nothing to do. */ -+ if (!atomic_dec_and_test(&bip->bli_refcount)) -+ goto out_release; -+ -+ /* -+ * Stale buffer completion frees the BLI, unlocks and releases the -+ * buffer. Neither the BLI or buffer are safe to reference after this -+ * call, so there's nothing more we need to do here. -+ * -+ * If we get here with a stale buffer and references to the BLI remain, -+ * we must not unlock the buffer as the last BLI reference owns lock -+ * context, not us. -+ */ -+ if (stale) { -+ xfs_buf_item_finish_stale(bip); -+ xfs_buf_relse(bp); -+ ASSERT(!hold); -+ return; -+ } -+ - /* -- * Unref the item and unlock the buffer unless held or stale. Stale -- * buffers remain locked until final unpin unless the bli is freed by -- * the unref call. The latter implies shutdown because buffer -- * invalidation dirties the bli and transaction. -+ * Dirty or clean, aborted items are done and need to be removed from -+ * the AIL and released. This frees the BLI, but leaves the buffer -+ * locked and referenced. - */ -- released = xfs_buf_item_put(bip); -- if (hold || (stale && !released)) -+ if (aborted || xlog_is_shutdown(lip->li_log)) { -+ ASSERT(list_empty(&bip->bli_buf->b_li_list)); -+ xfs_buf_item_done(bp); -+ goto out_release; -+ } -+ -+ /* -+ * Clean, unreferenced BLIs can be immediately freed, leaving the buffer -+ * locked and referenced. -+ * -+ * Dirty, unreferenced BLIs *must* be in the AIL awaiting writeback. -+ */ -+ if (!dirty) -+ xfs_buf_item_relse(bip); -+ else -+ ASSERT(test_bit(XFS_LI_IN_AIL, &lip->li_flags)); -+ -+ /* Not safe to reference the BLI from here */ -+out_release: -+ /* -+ * If we get here with a stale buffer, we must not unlock the -+ * buffer as the last BLI reference owns lock context, not us. -+ */ -+ if (stale || hold) - return; -- ASSERT(!stale || aborted); - xfs_buf_relse(bp); - } - -@@ -729,33 +847,6 @@ static const struct xfs_item_ops xfs_buf - .iop_push = xfs_buf_item_push, - }; - --STATIC void --xfs_buf_item_get_format( -- struct xfs_buf_log_item *bip, -- int count) --{ -- ASSERT(bip->bli_formats == NULL); -- bip->bli_format_count = count; -- -- if (count == 1) { -- bip->bli_formats = &bip->__bli_format; -- return; -- } -- -- bip->bli_formats = kzalloc(count * sizeof(struct xfs_buf_log_format), -- GFP_KERNEL | __GFP_NOFAIL); --} -- --STATIC void --xfs_buf_item_free_format( -- struct xfs_buf_log_item *bip) --{ -- if (bip->bli_formats != &bip->__bli_format) { -- kfree(bip->bli_formats); -- bip->bli_formats = NULL; -- } --} -- - /* - * Allocate a new buf log item to go with the given buffer. - * Set the buffer's b_log_item field to point to the new -@@ -976,34 +1067,6 @@ xfs_buf_item_dirty_format( - return false; - } - --STATIC void --xfs_buf_item_free( -- struct xfs_buf_log_item *bip) --{ -- xfs_buf_item_free_format(bip); -- kvfree(bip->bli_item.li_lv_shadow); -- kmem_cache_free(xfs_buf_item_cache, bip); --} -- --/* -- * xfs_buf_item_relse() is called when the buf log item is no longer needed. -- */ --void --xfs_buf_item_relse( -- struct xfs_buf *bp) --{ -- struct xfs_buf_log_item *bip = bp->b_log_item; -- -- trace_xfs_buf_item_relse(bp, _RET_IP_); -- ASSERT(!test_bit(XFS_LI_IN_AIL, &bip->bli_item.li_flags)); -- -- if (atomic_read(&bip->bli_refcount)) -- return; -- bp->b_log_item = NULL; -- xfs_buf_rele(bp); -- xfs_buf_item_free(bip); --} -- - void - xfs_buf_item_done( - struct xfs_buf *bp) -@@ -1023,5 +1086,5 @@ xfs_buf_item_done( - xfs_trans_ail_delete(&bp->b_log_item->bli_item, - (bp->b_flags & _XBF_LOGRECOVERY) ? 0 : - SHUTDOWN_CORRUPT_INCORE); -- xfs_buf_item_relse(bp); -+ xfs_buf_item_relse(bp->b_log_item); - } -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_buf_item.h BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_buf_item.h ---- BPI-Router-Linux-kernel/fs/xfs/xfs_buf_item.h 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_buf_item.h 2025-10-22 13:53:56.739168061 -0400 -@@ -49,8 +49,7 @@ struct xfs_buf_log_item { - - int xfs_buf_item_init(struct xfs_buf *, struct xfs_mount *); - void xfs_buf_item_done(struct xfs_buf *bp); --void xfs_buf_item_relse(struct xfs_buf *); --bool xfs_buf_item_put(struct xfs_buf_log_item *); -+void xfs_buf_item_put(struct xfs_buf_log_item *bip); - void xfs_buf_item_log(struct xfs_buf_log_item *, uint, uint); - bool xfs_buf_item_dirty_format(struct xfs_buf_log_item *); - void xfs_buf_inode_iodone(struct xfs_buf *); -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_discard.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_discard.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_discard.c 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_discard.c 2025-10-22 13:53:56.739168061 -0400 -@@ -103,24 +103,6 @@ xfs_discard_endio( - bio_put(bio); - } - --static inline struct block_device * --xfs_group_bdev( -- const struct xfs_group *xg) --{ -- struct xfs_mount *mp = xg->xg_mount; -- -- switch (xg->xg_type) { -- case XG_TYPE_AG: -- return mp->m_ddev_targp->bt_bdev; -- case XG_TYPE_RTG: -- return mp->m_rtdev_targp->bt_bdev; -- default: -- ASSERT(0); -- break; -- } -- return NULL; --} -- - /* - * Walk the discard list and issue discards on all the busy extents in the - * list. We plug and chain the bios so that we only need a single completion -@@ -138,11 +120,14 @@ xfs_discard_extents( - - blk_start_plug(&plug); - list_for_each_entry(busyp, &extents->extent_list, list) { -- trace_xfs_discard_extent(busyp->group, busyp->bno, -- busyp->length); -+ struct xfs_group *xg = busyp->group; -+ struct xfs_buftarg *btp = -+ xfs_group_type_buftarg(xg->xg_mount, xg->xg_type); -+ -+ trace_xfs_discard_extent(xg, busyp->bno, busyp->length); - -- error = __blkdev_issue_discard(xfs_group_bdev(busyp->group), -- xfs_gbno_to_daddr(busyp->group, busyp->bno), -+ error = __blkdev_issue_discard(btp->bt_bdev, -+ xfs_gbno_to_daddr(xg, busyp->bno), - XFS_FSB_TO_BB(mp, busyp->length), - GFP_KERNEL, &bio); - if (error && error != -EOPNOTSUPP) { -@@ -204,9 +189,7 @@ xfs_trim_gather_extents( - */ - xfs_log_force(mp, XFS_LOG_SYNC); - -- error = xfs_trans_alloc_empty(mp, &tp); -- if (error) -- return error; -+ tp = xfs_trans_alloc_empty(mp); - - error = xfs_alloc_read_agf(pag, tp, 0, &agbp); - if (error) -@@ -598,9 +581,7 @@ xfs_trim_rtextents( - struct xfs_trans *tp; - int error; - -- error = xfs_trans_alloc_empty(mp, &tp); -- if (error) -- return error; -+ tp = xfs_trans_alloc_empty(mp); - - /* - * Walk the free ranges between low and high. The query_range function -@@ -716,9 +697,7 @@ xfs_trim_rtgroup_extents( - struct xfs_trans *tp; - int error; - -- error = xfs_trans_alloc_empty(mp, &tp); -- if (error) -- return error; -+ tp = xfs_trans_alloc_empty(mp); - - /* - * Walk the free ranges between low and high. The query_range function -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_dquot.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_dquot.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_dquot.c 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_dquot.c 2025-10-22 13:53:56.739168061 -0400 -@@ -1398,11 +1398,9 @@ xfs_qm_dqflush( - - ASSERT(XFS_DQ_IS_LOCKED(dqp)); - ASSERT(!completion_done(&dqp->q_flush)); -+ ASSERT(atomic_read(&dqp->q_pincount) == 0); - - trace_xfs_dqflush(dqp); -- -- xfs_qm_dqunpin_wait(dqp); -- - fa = xfs_qm_dqflush_check(dqp); - if (fa) { - xfs_alert(mp, "corrupt dquot ID 0x%x in memory at %pS", -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_extent_busy.h BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_extent_busy.h ---- BPI-Router-Linux-kernel/fs/xfs/xfs_extent_busy.h 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_extent_busy.h 2025-10-22 13:53:56.739168061 -0400 -@@ -68,4 +68,12 @@ static inline void xfs_extent_busy_sort( - list_sort(NULL, list, xfs_extent_busy_ag_cmp); - } - -+/* -+ * Zoned RTGs don't need to track busy extents, as the actual block freeing only -+ * happens by a zone reset, which forces out all transactions that touched the -+ * to be reset zone first. -+ */ -+#define xfs_group_has_extent_busy(mp, type) \ -+ ((type) == XG_TYPE_AG || !xfs_has_zoned((mp))) -+ - #endif /* __XFS_EXTENT_BUSY_H__ */ -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_file.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_file.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_file.c 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_file.c 2025-10-22 13:53:56.739168061 -0400 -@@ -752,7 +752,7 @@ xfs_file_dio_write_atomic( - * HW offload should be faster, so try that first if it is already - * known that the write length is not too large. - */ -- if (ocount > xfs_inode_buftarg(ip)->bt_bdev_awu_max) -+ if (ocount > xfs_inode_buftarg(ip)->bt_awu_max) - dops = &xfs_atomic_write_cow_iomap_ops; - else - dops = &xfs_direct_write_iomap_ops; -@@ -1335,9 +1335,10 @@ xfs_falloc_allocate_range( - } - - #define XFS_FALLOC_FL_SUPPORTED \ -- (FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | \ -- FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE | \ -- FALLOC_FL_INSERT_RANGE | FALLOC_FL_UNSHARE_RANGE) -+ (FALLOC_FL_ALLOCATE_RANGE | FALLOC_FL_KEEP_SIZE | \ -+ FALLOC_FL_PUNCH_HOLE | FALLOC_FL_COLLAPSE_RANGE | \ -+ FALLOC_FL_ZERO_RANGE | FALLOC_FL_INSERT_RANGE | \ -+ FALLOC_FL_UNSHARE_RANGE) - - STATIC long - __xfs_file_fallocate( -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_fsmap.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_fsmap.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_fsmap.c 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_fsmap.c 2025-10-22 13:53:56.739168061 -0400 -@@ -1270,9 +1270,7 @@ xfs_getfsmap( - * buffer locking abilities to detect cycles in the rmapbt - * without deadlocking. - */ -- error = xfs_trans_alloc_empty(mp, &tp); -- if (error) -- break; -+ tp = xfs_trans_alloc_empty(mp); - - info.dev = handlers[i].dev; - info.last = false; -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_icache.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_icache.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_icache.c 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_icache.c 2025-10-22 13:53:56.739168061 -0400 -@@ -893,10 +893,7 @@ xfs_metafile_iget( - struct xfs_trans *tp; - int error; - -- error = xfs_trans_alloc_empty(mp, &tp); -- if (error) -- return error; -- -+ tp = xfs_trans_alloc_empty(mp); - error = xfs_trans_metafile_iget(tp, ino, metafile_type, ipp); - xfs_trans_cancel(tp); - return error; -@@ -979,7 +976,15 @@ xfs_reclaim_inode( - */ - if (xlog_is_shutdown(ip->i_mount->m_log)) { - xfs_iunpin_wait(ip); -+ /* -+ * Avoid a ABBA deadlock on the inode cluster buffer vs -+ * concurrent xfs_ifree_cluster() trying to mark the inode -+ * stale. We don't need the inode locked to run the flush abort -+ * code, but the flush abort needs to lock the cluster buffer. -+ */ -+ xfs_iunlock(ip, XFS_ILOCK_EXCL); - xfs_iflush_shutdown_abort(ip); -+ xfs_ilock(ip, XFS_ILOCK_EXCL); - goto reclaim; - } - if (xfs_ipincount(ip)) -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_inode.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_inode.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_inode.c 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_inode.c 2025-10-22 13:53:56.739168061 -0400 -@@ -1635,7 +1635,7 @@ retry: - iip = ip->i_itemp; - if (__xfs_iflags_test(ip, XFS_IFLUSHING)) { - ASSERT(!list_empty(&iip->ili_item.li_bio_list)); -- ASSERT(iip->ili_last_fields); -+ ASSERT(iip->ili_last_fields || xlog_is_shutdown(mp->m_log)); - goto out_iunlock; - } - -@@ -2932,12 +2932,9 @@ xfs_inode_reload_unlinked( - struct xfs_inode *ip) - { - struct xfs_trans *tp; -- int error; -- -- error = xfs_trans_alloc_empty(ip->i_mount, &tp); -- if (error) -- return error; -+ int error = 0; - -+ tp = xfs_trans_alloc_empty(ip->i_mount); - xfs_ilock(ip, XFS_ILOCK_SHARED); - if (xfs_inode_unlinked_incomplete(ip)) - error = xfs_inode_reload_unlinked_bucket(tp, ip); -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_inode.h BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_inode.h ---- BPI-Router-Linux-kernel/fs/xfs/xfs_inode.h 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_inode.h 2025-10-22 13:53:56.739168061 -0400 -@@ -358,7 +358,7 @@ static inline bool xfs_inode_has_bigrtal - - static inline bool xfs_inode_can_hw_atomic_write(const struct xfs_inode *ip) - { -- return xfs_inode_buftarg(ip)->bt_bdev_awu_max > 0; -+ return xfs_inode_buftarg(ip)->bt_awu_max > 0; - } - - /* -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_inode_item.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_inode_item.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_inode_item.c 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_inode_item.c 2025-10-22 13:53:56.743168042 -0400 -@@ -758,11 +758,14 @@ xfs_inode_item_push( - * completed and items removed from the AIL before the next push - * attempt. - */ -+ trace_xfs_inode_push_stale(ip, _RET_IP_); - return XFS_ITEM_PINNED; - } - -- if (xfs_ipincount(ip) > 0 || xfs_buf_ispinned(bp)) -+ if (xfs_ipincount(ip) > 0 || xfs_buf_ispinned(bp)) { -+ trace_xfs_inode_push_pinned(ip, _RET_IP_); - return XFS_ITEM_PINNED; -+ } - - if (xfs_iflags_test(ip, XFS_IFLUSHING)) - return XFS_ITEM_FLUSHING; -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_iomap.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_iomap.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_iomap.c 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_iomap.c 2025-10-22 13:53:56.743168042 -0400 -@@ -827,7 +827,7 @@ xfs_bmap_hw_atomic_write_possible( - /* - * The ->iomap_begin caller should ensure this, but check anyway. - */ -- return len <= xfs_inode_buftarg(ip)->bt_bdev_awu_max; -+ return len <= xfs_inode_buftarg(ip)->bt_awu_max; - } - - static int -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_iops.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_iops.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_iops.c 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_iops.c 2025-10-22 13:53:56.743168042 -0400 -@@ -665,7 +665,7 @@ xfs_get_atomic_write_max_opt( - * less than our out of place write limit, but we don't want to exceed - * the awu_max. - */ -- return min(awu_max, xfs_inode_buftarg(ip)->bt_bdev_awu_max); -+ return min(awu_max, xfs_inode_buftarg(ip)->bt_awu_max); - } - - static void -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_itable.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_itable.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_itable.c 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_itable.c 2025-10-22 13:53:56.743168042 -0400 -@@ -239,14 +239,10 @@ xfs_bulkstat_one( - * Grab an empty transaction so that we can use its recursive buffer - * locking abilities to detect cycles in the inobt without deadlocking. - */ -- error = xfs_trans_alloc_empty(breq->mp, &tp); -- if (error) -- goto out; -- -+ tp = xfs_trans_alloc_empty(breq->mp); - error = xfs_bulkstat_one_int(breq->mp, breq->idmap, tp, - breq->startino, &bc); - xfs_trans_cancel(tp); --out: - kfree(bc.buf); - - /* -@@ -331,17 +327,13 @@ xfs_bulkstat( - * Grab an empty transaction so that we can use its recursive buffer - * locking abilities to detect cycles in the inobt without deadlocking. - */ -- error = xfs_trans_alloc_empty(breq->mp, &tp); -- if (error) -- goto out; -- -+ tp = xfs_trans_alloc_empty(breq->mp); - if (breq->flags & XFS_IBULK_SAME_AG) - iwalk_flags |= XFS_IWALK_SAME_AG; - - error = xfs_iwalk(breq->mp, tp, breq->startino, iwalk_flags, - xfs_bulkstat_iwalk, breq->icount, &bc); - xfs_trans_cancel(tp); --out: - kfree(bc.buf); - - /* -@@ -455,23 +447,23 @@ xfs_inumbers( - .breq = breq, - }; - struct xfs_trans *tp; -+ unsigned int iwalk_flags = 0; - int error = 0; - - if (xfs_bulkstat_already_done(breq->mp, breq->startino)) - return 0; - -+ if (breq->flags & XFS_IBULK_SAME_AG) -+ iwalk_flags |= XFS_IWALK_SAME_AG; -+ - /* - * Grab an empty transaction so that we can use its recursive buffer - * locking abilities to detect cycles in the inobt without deadlocking. - */ -- error = xfs_trans_alloc_empty(breq->mp, &tp); -- if (error) -- goto out; -- -- error = xfs_inobt_walk(breq->mp, tp, breq->startino, breq->flags, -+ tp = xfs_trans_alloc_empty(breq->mp); -+ error = xfs_inobt_walk(breq->mp, tp, breq->startino, iwalk_flags, - xfs_inumbers_walk, breq->icount, &ic); - xfs_trans_cancel(tp); --out: - - /* - * We found some inode groups, so clear the error status and return -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_iwalk.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_iwalk.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_iwalk.c 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_iwalk.c 2025-10-22 13:53:56.743168042 -0400 -@@ -377,11 +377,8 @@ xfs_iwalk_run_callbacks( - if (!has_more) - return 0; - -- if (iwag->drop_trans) { -- error = xfs_trans_alloc_empty(mp, &iwag->tp); -- if (error) -- return error; -- } -+ if (iwag->drop_trans) -+ iwag->tp = xfs_trans_alloc_empty(mp); - - /* ...and recreate the cursor just past where we left off. */ - error = xfs_ialloc_read_agi(iwag->pag, iwag->tp, 0, agi_bpp); -@@ -617,9 +614,7 @@ xfs_iwalk_ag_work( - * Grab an empty transaction so that we can use its recursive buffer - * locking abilities to detect cycles in the inobt without deadlocking. - */ -- error = xfs_trans_alloc_empty(mp, &iwag->tp); -- if (error) -- goto out; -+ iwag->tp = xfs_trans_alloc_empty(mp); - iwag->drop_trans = 1; - - error = xfs_iwalk_ag(iwag); -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_log_cil.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_log_cil.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_log_cil.c 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_log_cil.c 2025-10-22 13:53:56.743168042 -0400 -@@ -793,8 +793,10 @@ xlog_cil_ail_insert( - struct xfs_log_item *lip = lv->lv_item; - xfs_lsn_t item_lsn; - -- if (aborted) -+ if (aborted) { -+ trace_xlog_ail_insert_abort(lip); - set_bit(XFS_LI_ABORTED, &lip->li_flags); -+ } - - if (lip->li_ops->flags & XFS_ITEM_RELEASE_WHEN_COMMITTED) { - lip->li_ops->iop_release(lip); -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_mount.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_mount.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_mount.c 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_mount.c 2025-10-22 13:53:56.743168042 -0400 -@@ -171,19 +171,16 @@ xfs_readsb( - ASSERT(mp->m_ddev_targp != NULL); - - /* -- * For the initial read, we must guess at the sector -- * size based on the block device. It's enough to -- * get the sb_sectsize out of the superblock and -- * then reread with the proper length. -- * We don't verify it yet, because it may not be complete. -+ * In the first pass, use the device sector size to just read enough -+ * of the superblock to extract the XFS sector size. -+ * -+ * The device sector size must be smaller than or equal to the XFS -+ * sector size and thus we can always read the superblock. Once we know -+ * the XFS sector size, re-read it and run the buffer verifier. - */ -- sector_size = xfs_getsize_buftarg(mp->m_ddev_targp); -+ sector_size = mp->m_ddev_targp->bt_logical_sectorsize; - buf_ops = NULL; - -- /* -- * Allocate a (locked) buffer to hold the superblock. This will be kept -- * around at all times to optimize access to the superblock. -- */ - reread: - error = xfs_buf_read_uncached(mp->m_ddev_targp, XFS_SB_DADDR, - BTOBB(sector_size), &bp, buf_ops); -@@ -247,6 +244,10 @@ reread: - /* no need to be quiet anymore, so reset the buf ops */ - bp->b_ops = &xfs_sb_buf_ops; - -+ /* -+ * Keep a pointer of the sb buffer around instead of caching it in the -+ * buffer cache because we access it frequently. -+ */ - mp->m_sb_bp = bp; - xfs_buf_unlock(bp); - return 0; -@@ -678,68 +679,46 @@ static inline unsigned int max_pow_of_tw - } - - /* -- * If the data device advertises atomic write support, limit the size of data -- * device atomic writes to the greatest power-of-two factor of the AG size so -- * that every atomic write unit aligns with the start of every AG. This is -- * required so that the per-AG allocations for an atomic write will always be -+ * If the underlying device advertises atomic write support, limit the size of -+ * atomic writes to the greatest power-of-two factor of the group size so -+ * that every atomic write unit aligns with the start of every group. This is -+ * required so that the allocations for an atomic write will always be - * aligned compatibly with the alignment requirements of the storage. - * -- * If the data device doesn't advertise atomic writes, then there are no -- * alignment restrictions and the largest out-of-place write we can do -- * ourselves is the number of blocks that user files can allocate from any AG. -- */ --static inline xfs_extlen_t xfs_calc_perag_awu_max(struct xfs_mount *mp) --{ -- if (mp->m_ddev_targp->bt_bdev_awu_min > 0) -- return max_pow_of_two_factor(mp->m_sb.sb_agblocks); -- return rounddown_pow_of_two(mp->m_ag_max_usable); --} -- --/* -- * Reflink on the realtime device requires rtgroups, and atomic writes require -- * reflink. -- * -- * If the realtime device advertises atomic write support, limit the size of -- * data device atomic writes to the greatest power-of-two factor of the rtgroup -- * size so that every atomic write unit aligns with the start of every rtgroup. -- * This is required so that the per-rtgroup allocations for an atomic write -- * will always be aligned compatibly with the alignment requirements of the -- * storage. -- * -- * If the rt device doesn't advertise atomic writes, then there are no -- * alignment restrictions and the largest out-of-place write we can do -- * ourselves is the number of blocks that user files can allocate from any -- * rtgroup. -+ * If the device doesn't advertise atomic writes, then there are no alignment -+ * restrictions and the largest out-of-place write we can do ourselves is the -+ * number of blocks that user files can allocate from any group. - */ --static inline xfs_extlen_t xfs_calc_rtgroup_awu_max(struct xfs_mount *mp) -+static xfs_extlen_t -+xfs_calc_group_awu_max( -+ struct xfs_mount *mp, -+ enum xfs_group_type type) - { -- struct xfs_groups *rgs = &mp->m_groups[XG_TYPE_RTG]; -+ struct xfs_groups *g = &mp->m_groups[type]; -+ struct xfs_buftarg *btp = xfs_group_type_buftarg(mp, type); - -- if (rgs->blocks == 0) -+ if (g->blocks == 0) - return 0; -- if (mp->m_rtdev_targp && mp->m_rtdev_targp->bt_bdev_awu_min > 0) -- return max_pow_of_two_factor(rgs->blocks); -- return rounddown_pow_of_two(rgs->blocks); -+ if (btp && btp->bt_awu_min > 0) -+ return max_pow_of_two_factor(g->blocks); -+ return rounddown_pow_of_two(g->blocks); - } - - /* Compute the maximum atomic write unit size for each section. */ - static inline void - xfs_calc_atomic_write_unit_max( -- struct xfs_mount *mp) -+ struct xfs_mount *mp, -+ enum xfs_group_type type) - { -- struct xfs_groups *ags = &mp->m_groups[XG_TYPE_AG]; -- struct xfs_groups *rgs = &mp->m_groups[XG_TYPE_RTG]; -+ struct xfs_groups *g = &mp->m_groups[type]; - - const xfs_extlen_t max_write = xfs_calc_atomic_write_max(mp); - const xfs_extlen_t max_ioend = xfs_reflink_max_atomic_cow(mp); -- const xfs_extlen_t max_agsize = xfs_calc_perag_awu_max(mp); -- const xfs_extlen_t max_rgsize = xfs_calc_rtgroup_awu_max(mp); -- -- ags->awu_max = min3(max_write, max_ioend, max_agsize); -- rgs->awu_max = min3(max_write, max_ioend, max_rgsize); -+ const xfs_extlen_t max_gsize = xfs_calc_group_awu_max(mp, type); - -- trace_xfs_calc_atomic_write_unit_max(mp, max_write, max_ioend, -- max_agsize, max_rgsize); -+ g->awu_max = min3(max_write, max_ioend, max_gsize); -+ trace_xfs_calc_atomic_write_unit_max(mp, type, max_write, max_ioend, -+ max_gsize, g->awu_max); - } - - /* -@@ -757,7 +736,8 @@ xfs_set_max_atomic_write_opt( - max(mp->m_groups[XG_TYPE_AG].blocks, - mp->m_groups[XG_TYPE_RTG].blocks); - const xfs_extlen_t max_group_write = -- max(xfs_calc_perag_awu_max(mp), xfs_calc_rtgroup_awu_max(mp)); -+ max(xfs_calc_group_awu_max(mp, XG_TYPE_AG), -+ xfs_calc_group_awu_max(mp, XG_TYPE_RTG)); - int error; - - if (new_max_bytes == 0) -@@ -813,7 +793,8 @@ set_limit: - return error; - } - -- xfs_calc_atomic_write_unit_max(mp); -+ xfs_calc_atomic_write_unit_max(mp, XG_TYPE_AG); -+ xfs_calc_atomic_write_unit_max(mp, XG_TYPE_RTG); - mp->m_awu_max_bytes = new_max_bytes; - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_mount.h BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_mount.h ---- BPI-Router-Linux-kernel/fs/xfs/xfs_mount.h 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_mount.h 2025-10-22 13:53:56.743168042 -0400 -@@ -802,4 +802,21 @@ static inline void xfs_mod_sb_delalloc(s - int xfs_set_max_atomic_write_opt(struct xfs_mount *mp, - unsigned long long new_max_bytes); - -+static inline struct xfs_buftarg * -+xfs_group_type_buftarg( -+ struct xfs_mount *mp, -+ enum xfs_group_type type) -+{ -+ switch (type) { -+ case XG_TYPE_AG: -+ return mp->m_ddev_targp; -+ case XG_TYPE_RTG: -+ return mp->m_rtdev_targp; -+ default: -+ ASSERT(0); -+ break; -+ } -+ return NULL; -+} -+ - #endif /* __XFS_MOUNT_H__ */ -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_mru_cache.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_mru_cache.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_mru_cache.c 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_mru_cache.c 2025-10-22 13:53:56.743168042 -0400 -@@ -320,7 +320,7 @@ xfs_mru_cache_create( - xfs_mru_cache_free_func_t free_func) - { - struct xfs_mru_cache *mru = NULL; -- int err = 0, grp; -+ int grp; - unsigned int grp_time; - - if (mrup) -@@ -341,8 +341,8 @@ xfs_mru_cache_create( - mru->lists = kzalloc(mru->grp_count * sizeof(*mru->lists), - GFP_KERNEL | __GFP_NOFAIL); - if (!mru->lists) { -- err = -ENOMEM; -- goto exit; -+ kfree(mru); -+ return -ENOMEM; - } - - for (grp = 0; grp < mru->grp_count; grp++) -@@ -361,14 +361,7 @@ xfs_mru_cache_create( - mru->free_func = free_func; - mru->data = data; - *mrup = mru; -- --exit: -- if (err && mru && mru->lists) -- kfree(mru->lists); -- if (err && mru) -- kfree(mru); -- -- return err; -+ return 0; - } - - /* -@@ -425,10 +418,6 @@ xfs_mru_cache_insert( - { - int error = -EINVAL; - -- ASSERT(mru && mru->lists); -- if (!mru || !mru->lists) -- goto out_free; -- - error = -ENOMEM; - if (radix_tree_preload(GFP_KERNEL)) - goto out_free; -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_notify_failure.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_notify_failure.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_notify_failure.c 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_notify_failure.c 2025-10-22 13:53:56.743168042 -0400 -@@ -253,8 +253,7 @@ xfs_dax_notify_dev_failure( - return -EOPNOTSUPP; - } - -- error = xfs_dax_translate_range(type == XG_TYPE_RTG ? -- mp->m_rtdev_targp : mp->m_ddev_targp, -+ error = xfs_dax_translate_range(xfs_group_type_buftarg(mp, type), - offset, len, &daddr, &bblen); - if (error) - return error; -@@ -280,10 +279,7 @@ xfs_dax_notify_dev_failure( - kernel_frozen = xfs_dax_notify_failure_freeze(mp) == 0; - } - -- error = xfs_trans_alloc_empty(mp, &tp); -- if (error) -- goto out; -- -+ tp = xfs_trans_alloc_empty(mp); - start_gno = xfs_fsb_to_gno(mp, start_bno, type); - end_gno = xfs_fsb_to_gno(mp, end_bno, type); - while ((xg = xfs_group_next_range(mp, xg, start_gno, end_gno, type))) { -@@ -354,7 +350,6 @@ xfs_dax_notify_dev_failure( - error = -EFSCORRUPTED; - } - --out: - /* Thaw the fs if it has been frozen before. */ - if (mf_flags & MF_MEM_PRE_REMOVE) - xfs_dax_notify_failure_thaw(mp, kernel_frozen); -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_qm.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_qm.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_qm.c 2025-10-22 13:53:23.547327535 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_qm.c 2025-10-22 13:53:56.743168042 -0400 -@@ -134,6 +134,7 @@ xfs_qm_dqpurge( - - dqp->q_flags |= XFS_DQFLAG_FREEING; - -+ xfs_qm_dqunpin_wait(dqp); - xfs_dqflock(dqp); - - /* -@@ -465,6 +466,7 @@ xfs_qm_dquot_isolate( - struct xfs_dquot *dqp = container_of(item, - struct xfs_dquot, q_lru); - struct xfs_qm_isolate *isol = arg; -+ enum lru_status ret = LRU_SKIP; - - if (!xfs_dqlock_nowait(dqp)) - goto out_miss_busy; -@@ -478,6 +480,16 @@ xfs_qm_dquot_isolate( - goto out_miss_unlock; - - /* -+ * If the dquot is pinned or dirty, rotate it to the end of the LRU to -+ * give some time for it to be cleaned before we try to isolate it -+ * again. -+ */ -+ ret = LRU_ROTATE; -+ if (XFS_DQ_IS_DIRTY(dqp) || atomic_read(&dqp->q_pincount) > 0) { -+ goto out_miss_unlock; -+ } -+ -+ /* - * This dquot has acquired a reference in the meantime remove it from - * the freelist and try again. - */ -@@ -492,41 +504,14 @@ xfs_qm_dquot_isolate( - } - - /* -- * If the dquot is dirty, flush it. If it's already being flushed, just -- * skip it so there is time for the IO to complete before we try to -- * reclaim it again on the next LRU pass. -+ * The dquot may still be under IO, in which case the flush lock will be -+ * held. If we can't get the flush lock now, just skip over the dquot as -+ * if it was dirty. - */ - if (!xfs_dqflock_nowait(dqp)) - goto out_miss_unlock; - -- if (XFS_DQ_IS_DIRTY(dqp)) { -- struct xfs_buf *bp = NULL; -- int error; -- -- trace_xfs_dqreclaim_dirty(dqp); -- -- /* we have to drop the LRU lock to flush the dquot */ -- spin_unlock(&lru->lock); -- -- error = xfs_dquot_use_attached_buf(dqp, &bp); -- if (!bp || error == -EAGAIN) { -- xfs_dqfunlock(dqp); -- goto out_unlock_dirty; -- } -- -- /* -- * dqflush completes dqflock on error, and the delwri ioend -- * does it on success. -- */ -- error = xfs_qm_dqflush(dqp, bp); -- if (error) -- goto out_unlock_dirty; -- -- xfs_buf_delwri_queue(bp, &isol->buffers); -- xfs_buf_relse(bp); -- goto out_unlock_dirty; -- } -- -+ ASSERT(!XFS_DQ_IS_DIRTY(dqp)); - xfs_dquot_detach_buf(dqp); - xfs_dqfunlock(dqp); - -@@ -548,13 +533,7 @@ out_miss_unlock: - out_miss_busy: - trace_xfs_dqreclaim_busy(dqp); - XFS_STATS_INC(dqp->q_mount, xs_qm_dqreclaim_misses); -- return LRU_SKIP; -- --out_unlock_dirty: -- trace_xfs_dqreclaim_busy(dqp); -- XFS_STATS_INC(dqp->q_mount, xs_qm_dqreclaim_misses); -- xfs_dqunlock(dqp); -- return LRU_RETRY; -+ return ret; - } - - static unsigned long -@@ -681,10 +660,7 @@ xfs_qm_load_metadir_qinos( - struct xfs_trans *tp; - int error; - -- error = xfs_trans_alloc_empty(mp, &tp); -- if (error) -- return error; -- -+ tp = xfs_trans_alloc_empty(mp); - error = xfs_dqinode_load_parent(tp, &qi->qi_dirip); - if (error == -ENOENT) { - /* no quota dir directory, but we'll create one later */ -@@ -1486,7 +1462,6 @@ xfs_qm_flush_one( - struct xfs_dquot *dqp, - void *data) - { -- struct xfs_mount *mp = dqp->q_mount; - struct list_head *buffer_list = data; - struct xfs_buf *bp = NULL; - int error = 0; -@@ -1497,34 +1472,8 @@ xfs_qm_flush_one( - if (!XFS_DQ_IS_DIRTY(dqp)) - goto out_unlock; - -- /* -- * The only way the dquot is already flush locked by the time quotacheck -- * gets here is if reclaim flushed it before the dqadjust walk dirtied -- * it for the final time. Quotacheck collects all dquot bufs in the -- * local delwri queue before dquots are dirtied, so reclaim can't have -- * possibly queued it for I/O. The only way out is to push the buffer to -- * cycle the flush lock. -- */ -- if (!xfs_dqflock_nowait(dqp)) { -- /* buf is pinned in-core by delwri list */ -- error = xfs_buf_incore(mp->m_ddev_targp, dqp->q_blkno, -- mp->m_quotainfo->qi_dqchunklen, 0, &bp); -- if (error) -- goto out_unlock; -- -- if (!(bp->b_flags & _XBF_DELWRI_Q)) { -- error = -EAGAIN; -- xfs_buf_relse(bp); -- goto out_unlock; -- } -- xfs_buf_unlock(bp); -- -- xfs_buf_delwri_pushbuf(bp, buffer_list); -- xfs_buf_rele(bp); -- -- error = -EAGAIN; -- goto out_unlock; -- } -+ xfs_qm_dqunpin_wait(dqp); -+ xfs_dqflock(dqp); - - error = xfs_dquot_use_attached_buf(dqp, &bp); - if (error) -@@ -1803,10 +1752,7 @@ xfs_qm_qino_load( - struct xfs_inode *dp = NULL; - int error; - -- error = xfs_trans_alloc_empty(mp, &tp); -- if (error) -- return error; -- -+ tp = xfs_trans_alloc_empty(mp); - if (xfs_has_metadir(mp)) { - error = xfs_dqinode_load_parent(tp, &dp); - if (error) -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_rtalloc.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_rtalloc.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_rtalloc.c 2025-10-22 13:53:23.551327516 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_rtalloc.c 2025-10-22 13:53:56.743168042 -0400 -@@ -729,9 +729,7 @@ xfs_rtginode_ensure( - if (rtg->rtg_inodes[type]) - return 0; - -- error = xfs_trans_alloc_empty(rtg_mount(rtg), &tp); -- if (error) -- return error; -+ tp = xfs_trans_alloc_empty(rtg_mount(rtg)); - error = xfs_rtginode_load(rtg, type, tp); - xfs_trans_cancel(tp); - -@@ -1259,6 +1257,8 @@ xfs_growfs_check_rtgeom( - - kfree(nmp); - -+ trace_xfs_growfs_check_rtgeom(mp, min_logfsbs); -+ - if (min_logfsbs > mp->m_sb.sb_logblocks) - return -EINVAL; - -@@ -1303,9 +1303,7 @@ xfs_growfs_rt_prep_groups( - if (!mp->m_rtdirip) { - struct xfs_trans *tp; - -- error = xfs_trans_alloc_empty(mp, &tp); -- if (error) -- return error; -+ tp = xfs_trans_alloc_empty(mp); - error = xfs_rtginode_load_parent(tp); - xfs_trans_cancel(tp); - -@@ -1672,10 +1670,7 @@ xfs_rtmount_inodes( - struct xfs_rtgroup *rtg = NULL; - int error; - -- error = xfs_trans_alloc_empty(mp, &tp); -- if (error) -- return error; -- -+ tp = xfs_trans_alloc_empty(mp); - if (xfs_has_rtgroups(mp) && mp->m_sb.sb_rgcount > 0) { - error = xfs_rtginode_load_parent(tp); - if (error) -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_super.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_super.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_super.c 2025-10-22 13:53:23.551327516 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_super.c 2025-10-22 13:53:56.743168042 -0400 -@@ -2020,14 +2020,13 @@ xfs_remount_rw( - int error; - - if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp && -- bdev_read_only(mp->m_logdev_targp->bt_bdev)) { -+ xfs_readonly_buftarg(mp->m_logdev_targp)) { - xfs_warn(mp, - "ro->rw transition prohibited by read-only logdev"); - return -EACCES; - } - -- if (mp->m_rtdev_targp && -- bdev_read_only(mp->m_rtdev_targp->bt_bdev)) { -+ if (mp->m_rtdev_targp && xfs_readonly_buftarg(mp->m_rtdev_targp)) { - xfs_warn(mp, - "ro->rw transition prohibited by read-only rtdev"); - return -EACCES; -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_trace.h BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_trace.h ---- BPI-Router-Linux-kernel/fs/xfs/xfs_trace.h 2025-10-22 13:53:23.551327516 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_trace.h 2025-10-22 13:53:56.743168042 -0400 -@@ -171,36 +171,33 @@ DEFINE_ATTR_LIST_EVENT(xfs_attr_leaf_lis - DEFINE_ATTR_LIST_EVENT(xfs_attr_node_list); - - TRACE_EVENT(xfs_calc_atomic_write_unit_max, -- TP_PROTO(struct xfs_mount *mp, unsigned int max_write, -- unsigned int max_ioend, unsigned int max_agsize, -- unsigned int max_rgsize), -- TP_ARGS(mp, max_write, max_ioend, max_agsize, max_rgsize), -+ TP_PROTO(struct xfs_mount *mp, enum xfs_group_type type, -+ unsigned int max_write, unsigned int max_ioend, -+ unsigned int max_gsize, unsigned int awu_max), -+ TP_ARGS(mp, type, max_write, max_ioend, max_gsize, awu_max), - TP_STRUCT__entry( - __field(dev_t, dev) -+ __field(enum xfs_group_type, type) - __field(unsigned int, max_write) - __field(unsigned int, max_ioend) -- __field(unsigned int, max_agsize) -- __field(unsigned int, max_rgsize) -- __field(unsigned int, data_awu_max) -- __field(unsigned int, rt_awu_max) -+ __field(unsigned int, max_gsize) -+ __field(unsigned int, awu_max) - ), - TP_fast_assign( - __entry->dev = mp->m_super->s_dev; -+ __entry->type = type; - __entry->max_write = max_write; - __entry->max_ioend = max_ioend; -- __entry->max_agsize = max_agsize; -- __entry->max_rgsize = max_rgsize; -- __entry->data_awu_max = mp->m_groups[XG_TYPE_AG].awu_max; -- __entry->rt_awu_max = mp->m_groups[XG_TYPE_RTG].awu_max; -+ __entry->max_gsize = max_gsize; -+ __entry->awu_max = awu_max; - ), -- TP_printk("dev %d:%d max_write %u max_ioend %u max_agsize %u max_rgsize %u data_awu_max %u rt_awu_max %u", -+ TP_printk("dev %d:%d %s max_write %u max_ioend %u max_gsize %u awu_max %u", - MAJOR(__entry->dev), MINOR(__entry->dev), -+ __print_symbolic(__entry->type, XG_TYPE_STRINGS), - __entry->max_write, - __entry->max_ioend, -- __entry->max_agsize, -- __entry->max_rgsize, -- __entry->data_awu_max, -- __entry->rt_awu_max) -+ __entry->max_gsize, -+ __entry->awu_max) - ); - - TRACE_EVENT(xfs_calc_max_atomic_write_fsblocks, -@@ -778,7 +775,6 @@ DEFINE_BUF_EVENT(xfs_buf_iowait_done); - DEFINE_BUF_EVENT(xfs_buf_delwri_queue); - DEFINE_BUF_EVENT(xfs_buf_delwri_queued); - DEFINE_BUF_EVENT(xfs_buf_delwri_split); --DEFINE_BUF_EVENT(xfs_buf_delwri_pushbuf); - DEFINE_BUF_EVENT(xfs_buf_get_uncached); - DEFINE_BUF_EVENT(xfs_buf_item_relse); - DEFINE_BUF_EVENT(xfs_buf_iodone_async); -@@ -1147,6 +1143,7 @@ DECLARE_EVENT_CLASS(xfs_iref_class, - __field(xfs_ino_t, ino) - __field(int, count) - __field(int, pincount) -+ __field(unsigned long, iflags) - __field(unsigned long, caller_ip) - ), - TP_fast_assign( -@@ -1154,13 +1151,15 @@ DECLARE_EVENT_CLASS(xfs_iref_class, - __entry->ino = ip->i_ino; - __entry->count = atomic_read(&VFS_I(ip)->i_count); - __entry->pincount = atomic_read(&ip->i_pincount); -+ __entry->iflags = ip->i_flags; - __entry->caller_ip = caller_ip; - ), -- TP_printk("dev %d:%d ino 0x%llx count %d pincount %d caller %pS", -+ TP_printk("dev %d:%d ino 0x%llx count %d pincount %d iflags 0x%lx caller %pS", - MAJOR(__entry->dev), MINOR(__entry->dev), - __entry->ino, - __entry->count, - __entry->pincount, -+ __entry->iflags, - (char *)__entry->caller_ip) - ) - -@@ -1250,6 +1249,8 @@ DEFINE_IREF_EVENT(xfs_irele); - DEFINE_IREF_EVENT(xfs_inode_pin); - DEFINE_IREF_EVENT(xfs_inode_unpin); - DEFINE_IREF_EVENT(xfs_inode_unpin_nowait); -+DEFINE_IREF_EVENT(xfs_inode_push_pinned); -+DEFINE_IREF_EVENT(xfs_inode_push_stale); - - DECLARE_EVENT_CLASS(xfs_namespace_class, - TP_PROTO(struct xfs_inode *dp, const struct xfs_name *name), -@@ -1654,6 +1655,8 @@ DEFINE_LOG_ITEM_EVENT(xfs_ail_flushing); - DEFINE_LOG_ITEM_EVENT(xfs_cil_whiteout_mark); - DEFINE_LOG_ITEM_EVENT(xfs_cil_whiteout_skip); - DEFINE_LOG_ITEM_EVENT(xfs_cil_whiteout_unpin); -+DEFINE_LOG_ITEM_EVENT(xlog_ail_insert_abort); -+DEFINE_LOG_ITEM_EVENT(xfs_trans_free_abort); - - DECLARE_EVENT_CLASS(xfs_ail_class, - TP_PROTO(struct xfs_log_item *lip, xfs_lsn_t old_lsn, xfs_lsn_t new_lsn), -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_trans.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_trans.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_trans.c 2025-10-22 13:53:23.551327516 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_trans.c 2025-10-22 13:53:56.743168042 -0400 -@@ -241,6 +241,28 @@ undo_blocks: - return error; - } - -+static struct xfs_trans * -+__xfs_trans_alloc( -+ struct xfs_mount *mp, -+ uint flags) -+{ -+ struct xfs_trans *tp; -+ -+ ASSERT(!(flags & XFS_TRANS_RES_FDBLKS) || xfs_has_lazysbcount(mp)); -+ -+ tp = kmem_cache_zalloc(xfs_trans_cache, GFP_KERNEL | __GFP_NOFAIL); -+ if (!(flags & XFS_TRANS_NO_WRITECOUNT)) -+ sb_start_intwrite(mp->m_super); -+ xfs_trans_set_context(tp); -+ tp->t_flags = flags; -+ tp->t_mountp = mp; -+ INIT_LIST_HEAD(&tp->t_items); -+ INIT_LIST_HEAD(&tp->t_busy); -+ INIT_LIST_HEAD(&tp->t_dfops); -+ tp->t_highest_agno = NULLAGNUMBER; -+ return tp; -+} -+ - int - xfs_trans_alloc( - struct xfs_mount *mp, -@@ -254,33 +276,16 @@ xfs_trans_alloc( - bool want_retry = true; - int error; - -+ ASSERT(resp->tr_logres > 0); -+ - /* - * Allocate the handle before we do our freeze accounting and setting up - * GFP_NOFS allocation context so that we avoid lockdep false positives - * by doing GFP_KERNEL allocations inside sb_start_intwrite(). - */ - retry: -- tp = kmem_cache_zalloc(xfs_trans_cache, GFP_KERNEL | __GFP_NOFAIL); -- if (!(flags & XFS_TRANS_NO_WRITECOUNT)) -- sb_start_intwrite(mp->m_super); -- xfs_trans_set_context(tp); -- -- /* -- * Zero-reservation ("empty") transactions can't modify anything, so -- * they're allowed to run while we're frozen. -- */ -- WARN_ON(resp->tr_logres > 0 && -- mp->m_super->s_writers.frozen == SB_FREEZE_COMPLETE); -- ASSERT(!(flags & XFS_TRANS_RES_FDBLKS) || -- xfs_has_lazysbcount(mp)); -- -- tp->t_flags = flags; -- tp->t_mountp = mp; -- INIT_LIST_HEAD(&tp->t_items); -- INIT_LIST_HEAD(&tp->t_busy); -- INIT_LIST_HEAD(&tp->t_dfops); -- tp->t_highest_agno = NULLAGNUMBER; -- -+ tp = __xfs_trans_alloc(mp, flags); -+ WARN_ON(mp->m_super->s_writers.frozen == SB_FREEZE_COMPLETE); - error = xfs_trans_reserve(tp, resp, blocks, rtextents); - if (error == -ENOSPC && want_retry) { - xfs_trans_cancel(tp); -@@ -324,14 +329,11 @@ retry: - * where we can be grabbing buffers at the same time that freeze is trying to - * drain the buffer LRU list. - */ --int -+struct xfs_trans * - xfs_trans_alloc_empty( -- struct xfs_mount *mp, -- struct xfs_trans **tpp) -+ struct xfs_mount *mp) - { -- struct xfs_trans_res resv = {0}; -- -- return xfs_trans_alloc(mp, &resv, 0, 0, XFS_TRANS_NO_WRITECOUNT, tpp); -+ return __xfs_trans_alloc(mp, XFS_TRANS_NO_WRITECOUNT); - } - - /* -@@ -742,8 +744,10 @@ xfs_trans_free_items( - - list_for_each_entry_safe(lip, next, &tp->t_items, li_trans) { - xfs_trans_del_item(lip); -- if (abort) -+ if (abort) { -+ trace_xfs_trans_free_abort(lip); - set_bit(XFS_LI_ABORTED, &lip->li_flags); -+ } - if (lip->li_ops->iop_release) - lip->li_ops->iop_release(lip); - } -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_trans.h BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_trans.h ---- BPI-Router-Linux-kernel/fs/xfs/xfs_trans.h 2025-10-22 13:53:23.551327516 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_trans.h 2025-10-22 13:53:56.743168042 -0400 -@@ -168,8 +168,7 @@ int xfs_trans_alloc(struct xfs_mount *m - struct xfs_trans **tpp); - int xfs_trans_reserve_more(struct xfs_trans *tp, - unsigned int blocks, unsigned int rtextents); --int xfs_trans_alloc_empty(struct xfs_mount *mp, -- struct xfs_trans **tpp); -+struct xfs_trans *xfs_trans_alloc_empty(struct xfs_mount *mp); - void xfs_trans_mod_sb(xfs_trans_t *, uint, int64_t); - - int xfs_trans_get_buf_map(struct xfs_trans *tp, struct xfs_buftarg *target, -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_xattr.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_xattr.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_xattr.c 2025-10-22 13:53:23.551327516 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_xattr.c 2025-10-22 13:53:56.743168042 -0400 -@@ -243,7 +243,7 @@ __xfs_xattr_put_listent( - offset = context->buffer + context->count; - memcpy(offset, prefix, prefix_len); - offset += prefix_len; -- strncpy(offset, (char *)name, namelen); /* real name */ -+ memcpy(offset, (char *)name, namelen); /* real name */ - offset += namelen; - *offset = '\0'; - -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_zone_alloc.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_zone_alloc.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_zone_alloc.c 2025-10-22 13:53:23.551327516 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_zone_alloc.c 2025-10-22 13:53:56.743168042 -0400 -@@ -654,13 +654,6 @@ static inline bool xfs_zoned_pack_tight( - !(ip->i_diflags & XFS_DIFLAG_APPEND); - } - --/* -- * Pick a new zone for writes. -- * -- * If we aren't using up our budget of open zones just open a new one from the -- * freelist. Else try to find one that matches the expected data lifetime. If -- * we don't find one that is good pick any zone that is available. -- */ - static struct xfs_open_zone * - xfs_select_zone_nowait( - struct xfs_mount *mp, -@@ -688,7 +681,8 @@ xfs_select_zone_nowait( - goto out_unlock; - - /* -- * See if we can open a new zone and use that. -+ * See if we can open a new zone and use that so that data for different -+ * files is mixed as little as possible. - */ - oz = xfs_try_open_zone(mp, write_hint); - if (oz) -@@ -727,7 +721,7 @@ xfs_select_zone( - for (;;) { - prepare_to_wait(&zi->zi_zone_wait, &wait, TASK_UNINTERRUPTIBLE); - oz = xfs_select_zone_nowait(mp, write_hint, pack_tight); -- if (oz) -+ if (oz || xfs_is_shutdown(mp)) - break; - schedule(); - } -@@ -777,26 +771,6 @@ xfs_mark_rtg_boundary( - ioend->io_flags |= IOMAP_IOEND_BOUNDARY; - } - --static void --xfs_submit_zoned_bio( -- struct iomap_ioend *ioend, -- struct xfs_open_zone *oz, -- bool is_seq) --{ -- ioend->io_bio.bi_iter.bi_sector = ioend->io_sector; -- ioend->io_private = oz; -- atomic_inc(&oz->oz_ref); /* for xfs_zoned_end_io */ -- -- if (is_seq) { -- ioend->io_bio.bi_opf &= ~REQ_OP_WRITE; -- ioend->io_bio.bi_opf |= REQ_OP_ZONE_APPEND; -- } else { -- xfs_mark_rtg_boundary(ioend); -- } -- -- submit_bio(&ioend->io_bio); --} -- - /* - * Cache the last zone written to for an inode so that it is considered first - * for subsequent writes. -@@ -891,6 +865,26 @@ xfs_zone_cache_create_association( - xfs_mru_cache_insert(mp->m_zone_cache, ip->i_ino, &item->mru); - } - -+static void -+xfs_submit_zoned_bio( -+ struct iomap_ioend *ioend, -+ struct xfs_open_zone *oz, -+ bool is_seq) -+{ -+ ioend->io_bio.bi_iter.bi_sector = ioend->io_sector; -+ ioend->io_private = oz; -+ atomic_inc(&oz->oz_ref); /* for xfs_zoned_end_io */ -+ -+ if (is_seq) { -+ ioend->io_bio.bi_opf &= ~REQ_OP_WRITE; -+ ioend->io_bio.bi_opf |= REQ_OP_ZONE_APPEND; -+ } else { -+ xfs_mark_rtg_boundary(ioend); -+ } -+ -+ submit_bio(&ioend->io_bio); -+} -+ - void - xfs_zone_alloc_and_submit( - struct iomap_ioend *ioend, -diff -purNx .git BPI-Router-Linux-kernel/fs/xfs/xfs_zone_gc.c BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_zone_gc.c ---- BPI-Router-Linux-kernel/fs/xfs/xfs_zone_gc.c 2025-10-22 13:53:23.551327516 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/fs/xfs/xfs_zone_gc.c 2025-10-22 13:53:56.743168042 -0400 -@@ -328,10 +328,7 @@ xfs_zone_gc_query( - iter->rec_idx = 0; - iter->rec_count = 0; - -- error = xfs_trans_alloc_empty(mp, &tp); -- if (error) -- return error; -- -+ tp = xfs_trans_alloc_empty(mp); - xfs_rtgroup_lock(rtg, XFS_RTGLOCK_RMAP); - cur = xfs_rtrmapbt_init_cursor(tp, rtg); - error = xfs_rmap_query_range(cur, &ri_low, &ri_high, -diff -purNx .git BPI-Router-Linux-kernel/.gitignore BPI-Router-Linux-kernel-6.16.12/.gitignore ---- BPI-Router-Linux-kernel/.gitignore 2025-10-22 13:53:23.031330005 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/.gitignore 2025-10-22 13:53:56.267170337 -0400 -@@ -114,6 +114,7 @@ modules.order - !.gitignore - !.kunitconfig - !.mailmap -+!.pylintrc - !.rustfmt.toml - - # -diff -purNx .git BPI-Router-Linux-kernel/include/crypto/hash.h BPI-Router-Linux-kernel-6.16.12/include/crypto/hash.h ---- BPI-Router-Linux-kernel/include/crypto/hash.h 2025-10-22 13:53:23.551327516 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/crypto/hash.h 2025-10-22 13:53:56.743168042 -0400 -@@ -184,7 +184,7 @@ struct shash_desc { - * Worst case is hmac(sha3-224-s390). Its context is a nested 'shash_desc' - * containing a 'struct s390_sha_ctx'. - */ --#define HASH_MAX_DESCSIZE (sizeof(struct shash_desc) + 360) -+#define HASH_MAX_DESCSIZE (sizeof(struct shash_desc) + 361) - #define MAX_SYNC_HASH_REQSIZE (sizeof(struct ahash_request) + \ - HASH_MAX_DESCSIZE) - -@@ -202,6 +202,8 @@ struct shash_desc { - #define HASH_REQUEST_CLONE(name, gfp) \ - hash_request_clone(name, sizeof(__##name##_req), gfp) - -+#define CRYPTO_HASH_STATESIZE(coresize, blocksize) (coresize + blocksize + 1) -+ - /** - * struct shash_alg - synchronous message digest definition - * @init: see struct ahash_alg -diff -purNx .git BPI-Router-Linux-kernel/include/crypto/if_alg.h BPI-Router-Linux-kernel-6.16.12/include/crypto/if_alg.h ---- BPI-Router-Linux-kernel/include/crypto/if_alg.h 2025-10-22 13:53:23.551327516 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/crypto/if_alg.h 2025-10-22 13:53:56.743168042 -0400 -@@ -135,6 +135,7 @@ struct af_alg_async_req { - * SG? - * @enc: Cryptographic operation to be performed when - * recvmsg is invoked. -+ * @write: True if we are in the middle of a write. - * @init: True if metadata has been sent. - * @len: Length of memory allocated for this data structure. - * @inflight: Non-zero when AIO requests are in flight. -@@ -151,10 +152,11 @@ struct af_alg_ctx { - size_t used; - atomic_t rcvused; - -- bool more; -- bool merge; -- bool enc; -- bool init; -+ bool more:1, -+ merge:1, -+ enc:1, -+ write:1, -+ init:1; - - unsigned int len; - -diff -purNx .git BPI-Router-Linux-kernel/include/crypto/internal/acompress.h BPI-Router-Linux-kernel-6.16.12/include/crypto/internal/acompress.h ---- BPI-Router-Linux-kernel/include/crypto/internal/acompress.h 2025-10-22 13:53:23.551327516 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/crypto/internal/acompress.h 2025-10-22 13:53:56.743168042 -0400 -@@ -63,10 +63,7 @@ struct crypto_acomp_stream { - struct crypto_acomp_streams { - /* These must come first because of struct scomp_alg. */ - void *(*alloc_ctx)(void); -- union { -- void (*free_ctx)(void *); -- void (*cfree_ctx)(const void *); -- }; -+ void (*free_ctx)(void *); - - struct crypto_acomp_stream __percpu *streams; - struct work_struct stream_work; -diff -purNx .git BPI-Router-Linux-kernel/include/crypto/internal/hash.h BPI-Router-Linux-kernel-6.16.12/include/crypto/internal/hash.h ---- BPI-Router-Linux-kernel/include/crypto/internal/hash.h 2025-10-22 13:53:23.551327516 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/crypto/internal/hash.h 2025-10-22 13:53:56.743168042 -0400 -@@ -91,6 +91,12 @@ static inline bool crypto_hash_alg_needs - !(alg->base.cra_flags & CRYPTO_ALG_OPTIONAL_KEY); - } - -+static inline bool crypto_hash_no_export_core(struct crypto_ahash *tfm) -+{ -+ return crypto_hash_alg_common(tfm)->base.cra_flags & -+ CRYPTO_AHASH_ALG_NO_EXPORT_CORE; -+} -+ - int crypto_grab_ahash(struct crypto_ahash_spawn *spawn, - struct crypto_instance *inst, - const char *name, u32 type, u32 mask); -diff -purNx .git BPI-Router-Linux-kernel/include/crypto/internal/sha2.h BPI-Router-Linux-kernel-6.16.12/include/crypto/internal/sha2.h ---- BPI-Router-Linux-kernel/include/crypto/internal/sha2.h 2025-10-22 13:53:23.551327516 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/crypto/internal/sha2.h 2025-10-22 13:53:56.747168022 -0400 -@@ -25,7 +25,7 @@ void sha256_blocks_arch(u32 state[SHA256 - void sha256_blocks_simd(u32 state[SHA256_STATE_WORDS], - const u8 *data, size_t nblocks); - --static inline void sha256_choose_blocks( -+static __always_inline void sha256_choose_blocks( - u32 state[SHA256_STATE_WORDS], const u8 *data, size_t nblocks, - bool force_generic, bool force_simd) - { -diff -purNx .git BPI-Router-Linux-kernel/include/crypto/internal/simd.h BPI-Router-Linux-kernel-6.16.12/include/crypto/internal/simd.h ---- BPI-Router-Linux-kernel/include/crypto/internal/simd.h 2025-10-22 13:53:23.551327516 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/crypto/internal/simd.h 2025-10-22 13:53:56.747168022 -0400 -@@ -44,9 +44,11 @@ void simd_unregister_aeads(struct aead_a - * - * This delegates to may_use_simd(), except that this also returns false if SIMD - * in crypto code has been temporarily disabled on this CPU by the crypto -- * self-tests, in order to test the no-SIMD fallback code. -+ * self-tests, in order to test the no-SIMD fallback code. This override is -+ * currently limited to configurations where the "full" self-tests are enabled, -+ * because it might be a bit too invasive to be part of the "fast" self-tests. - */ --#ifdef CONFIG_CRYPTO_SELFTESTS -+#ifdef CONFIG_CRYPTO_SELFTESTS_FULL - DECLARE_PER_CPU(bool, crypto_simd_disabled_for_test); - #define crypto_simd_usable() \ - (may_use_simd() && !this_cpu_read(crypto_simd_disabled_for_test)) -diff -purNx .git BPI-Router-Linux-kernel/include/crypto/md5.h BPI-Router-Linux-kernel-6.16.12/include/crypto/md5.h ---- BPI-Router-Linux-kernel/include/crypto/md5.h 2025-10-22 13:53:23.551327516 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/crypto/md5.h 2025-10-22 13:53:56.747168022 -0400 -@@ -2,6 +2,7 @@ - #ifndef _CRYPTO_MD5_H - #define _CRYPTO_MD5_H - -+#include - #include - - #define MD5_DIGEST_SIZE 16 -@@ -15,6 +16,9 @@ - #define MD5_H2 0x98badcfeUL - #define MD5_H3 0x10325476UL - -+#define CRYPTO_MD5_STATESIZE \ -+ CRYPTO_HASH_STATESIZE(MD5_STATE_SIZE, MD5_HMAC_BLOCK_SIZE) -+ - extern const u8 md5_zero_message_hash[MD5_DIGEST_SIZE]; - - struct md5_state { -diff -purNx .git BPI-Router-Linux-kernel/include/drm/display/drm_dp_helper.h BPI-Router-Linux-kernel-6.16.12/include/drm/display/drm_dp_helper.h ---- BPI-Router-Linux-kernel/include/drm/display/drm_dp_helper.h 2025-10-22 13:53:23.551327516 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/drm/display/drm_dp_helper.h 2025-10-22 13:53:56.747168022 -0400 -@@ -523,10 +523,16 @@ struct drm_dp_aux { - * @no_zero_sized: If the hw can't use zero sized transfers (NVIDIA) - */ - bool no_zero_sized; -+ -+ /** -+ * @dpcd_probe_disabled: If probing before a DPCD access is disabled. -+ */ -+ bool dpcd_probe_disabled; - }; - - int drm_dp_dpcd_probe(struct drm_dp_aux *aux, unsigned int offset); - void drm_dp_dpcd_set_powered(struct drm_dp_aux *aux, bool powered); -+void drm_dp_dpcd_set_probe(struct drm_dp_aux *aux, bool enable); - ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset, - void *buffer, size_t size); - ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned int offset, -diff -purNx .git BPI-Router-Linux-kernel/include/drm/drm_buddy.h BPI-Router-Linux-kernel-6.16.12/include/drm/drm_buddy.h ---- BPI-Router-Linux-kernel/include/drm/drm_buddy.h 2025-10-22 13:53:23.551327516 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/drm/drm_buddy.h 2025-10-22 13:53:56.747168022 -0400 -@@ -160,6 +160,8 @@ int drm_buddy_block_trim(struct drm_budd - u64 new_size, - struct list_head *blocks); - -+void drm_buddy_reset_clear(struct drm_buddy *mm, bool is_clear); -+ - void drm_buddy_free_block(struct drm_buddy *mm, struct drm_buddy_block *block); - - void drm_buddy_free_list(struct drm_buddy *mm, -diff -purNx .git BPI-Router-Linux-kernel/include/drm/drm_connector.h BPI-Router-Linux-kernel-6.16.12/include/drm/drm_connector.h ---- BPI-Router-Linux-kernel/include/drm/drm_connector.h 2025-10-22 13:53:23.551327516 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/drm/drm_connector.h 2025-10-22 13:53:56.747168022 -0400 -@@ -843,7 +843,9 @@ struct drm_display_info { - int vics_len; - - /** -- * @quirks: EDID based quirks. Internal to EDID parsing. -+ * @quirks: EDID based quirks. DRM core and drivers can query the -+ * @drm_edid_quirk quirks using drm_edid_has_quirk(), the rest of -+ * the quirks also tracked here are internal to EDID parsing. - */ - u32 quirks; - -diff -purNx .git BPI-Router-Linux-kernel/include/drm/drm_edid.h BPI-Router-Linux-kernel-6.16.12/include/drm/drm_edid.h ---- BPI-Router-Linux-kernel/include/drm/drm_edid.h 2025-10-22 13:53:23.551327516 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/drm/drm_edid.h 2025-10-22 13:53:56.747168022 -0400 -@@ -109,6 +109,13 @@ struct detailed_data_string { - #define DRM_EDID_CVT_FLAGS_STANDARD_BLANKING (1 << 3) - #define DRM_EDID_CVT_FLAGS_REDUCED_BLANKING (1 << 4) - -+enum drm_edid_quirk { -+ /* Do a dummy read before DPCD accesses, to prevent corruption. */ -+ DRM_EDID_QUIRK_DP_DPCD_PROBE, -+ -+ DRM_EDID_QUIRK_NUM, -+}; -+ - struct detailed_data_monitor_range { - u8 min_vfreq; - u8 max_vfreq; -@@ -476,5 +483,6 @@ void drm_edid_print_product_id(struct dr - u32 drm_edid_get_panel_id(const struct drm_edid *drm_edid); - bool drm_edid_match(const struct drm_edid *drm_edid, - const struct drm_edid_ident *ident); -+bool drm_edid_has_quirk(struct drm_connector *connector, enum drm_edid_quirk quirk); - - #endif /* __DRM_EDID_H__ */ -diff -purNx .git BPI-Router-Linux-kernel/include/drm/drm_file.h BPI-Router-Linux-kernel-6.16.12/include/drm/drm_file.h ---- BPI-Router-Linux-kernel/include/drm/drm_file.h 2025-10-22 13:53:23.551327516 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/drm/drm_file.h 2025-10-22 13:53:56.747168022 -0400 -@@ -300,6 +300,9 @@ struct drm_file { - * - * Mapping of mm object handles to object pointers. Used by the GEM - * subsystem. Protected by @table_lock. -+ * -+ * Note that allocated entries might be NULL as a transient state when -+ * creating or deleting a handle. - */ - struct idr object_idr; - -diff -purNx .git BPI-Router-Linux-kernel/include/drm/drm_format_helper.h BPI-Router-Linux-kernel-6.16.12/include/drm/drm_format_helper.h ---- BPI-Router-Linux-kernel/include/drm/drm_format_helper.h 2025-10-22 13:53:23.551327516 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/drm/drm_format_helper.h 2025-10-22 13:53:56.747168022 -0400 -@@ -102,6 +102,15 @@ void drm_fb_xrgb8888_to_bgr888(struct io - void drm_fb_xrgb8888_to_argb8888(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *src, const struct drm_framebuffer *fb, - const struct drm_rect *clip, struct drm_format_conv_state *state); -+void drm_fb_xrgb8888_to_abgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, -+ const struct iosys_map *src, const struct drm_framebuffer *fb, -+ const struct drm_rect *clip, struct drm_format_conv_state *state); -+void drm_fb_xrgb8888_to_xbgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, -+ const struct iosys_map *src, const struct drm_framebuffer *fb, -+ const struct drm_rect *clip, struct drm_format_conv_state *state); -+void drm_fb_xrgb8888_to_bgrx8888(struct iosys_map *dst, const unsigned int *dst_pitch, -+ const struct iosys_map *src, const struct drm_framebuffer *fb, -+ const struct drm_rect *clip, struct drm_format_conv_state *state); - void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *src, const struct drm_framebuffer *fb, - const struct drm_rect *clip, -diff -purNx .git BPI-Router-Linux-kernel/include/drm/drm_framebuffer.h BPI-Router-Linux-kernel-6.16.12/include/drm/drm_framebuffer.h ---- BPI-Router-Linux-kernel/include/drm/drm_framebuffer.h 2025-10-22 13:53:23.551327516 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/drm/drm_framebuffer.h 2025-10-22 13:53:56.747168022 -0400 -@@ -23,6 +23,7 @@ - #ifndef __DRM_FRAMEBUFFER_H__ - #define __DRM_FRAMEBUFFER_H__ - -+#include - #include - #include - #include -@@ -100,6 +101,8 @@ struct drm_framebuffer_funcs { - unsigned num_clips); - }; - -+#define DRM_FRAMEBUFFER_HAS_HANDLE_REF(_i) BIT(0u + (_i)) -+ - /** - * struct drm_framebuffer - frame buffer object - * -@@ -189,6 +192,10 @@ struct drm_framebuffer { - */ - int flags; - /** -+ * @internal_flags: Framebuffer flags like DRM_FRAMEBUFFER_HAS_HANDLE_REF. -+ */ -+ unsigned int internal_flags; -+ /** - * @filp_head: Placed on &drm_file.fbs, protected by &drm_file.fbs_lock. - */ - struct list_head filp_head; -diff -purNx .git BPI-Router-Linux-kernel/include/drm/drm_mipi_dsi.h BPI-Router-Linux-kernel-6.16.12/include/drm/drm_mipi_dsi.h ---- BPI-Router-Linux-kernel/include/drm/drm_mipi_dsi.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/drm/drm_mipi_dsi.h 2025-10-22 13:53:56.747168022 -0400 -@@ -223,6 +223,9 @@ struct mipi_dsi_multi_context { - - #define to_mipi_dsi_device(__dev) container_of_const(__dev, struct mipi_dsi_device, dev) - -+extern const struct bus_type mipi_dsi_bus_type; -+#define dev_is_mipi_dsi(dev) ((dev)->bus == &mipi_dsi_bus_type) -+ - /** - * mipi_dsi_pixel_format_to_bpp - obtain the number of bits per pixel for any - * given pixel format defined by the MIPI DSI -diff -purNx .git BPI-Router-Linux-kernel/include/drm/gpu_scheduler.h BPI-Router-Linux-kernel-6.16.12/include/drm/gpu_scheduler.h ---- BPI-Router-Linux-kernel/include/drm/gpu_scheduler.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/drm/gpu_scheduler.h 2025-10-22 13:53:56.747168022 -0400 -@@ -508,6 +508,24 @@ struct drm_sched_backend_ops { - * and it's time to clean it up. - */ - void (*free_job)(struct drm_sched_job *sched_job); -+ -+ /** -+ * @cancel_job: Used by the scheduler to guarantee remaining jobs' fences -+ * get signaled in drm_sched_fini(). -+ * -+ * Used by the scheduler to cancel all jobs that have not been executed -+ * with &struct drm_sched_backend_ops.run_job by the time -+ * drm_sched_fini() gets invoked. -+ * -+ * Drivers need to signal the passed job's hardware fence with an -+ * appropriate error code (e.g., -ECANCELED) in this callback. They -+ * must not free the job. -+ * -+ * The scheduler will only call this callback once it stopped calling -+ * all other callbacks forever, with the exception of &struct -+ * drm_sched_backend_ops.free_job. -+ */ -+ void (*cancel_job)(struct drm_sched_job *sched_job); - }; - - /** -diff -purNx .git BPI-Router-Linux-kernel/include/drm/intel/pciids.h BPI-Router-Linux-kernel-6.16.12/include/drm/intel/pciids.h ---- BPI-Router-Linux-kernel/include/drm/intel/pciids.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/drm/intel/pciids.h 2025-10-22 13:53:56.747168022 -0400 -@@ -846,6 +846,7 @@ - /* BMG */ - #define INTEL_BMG_IDS(MACRO__, ...) \ - MACRO__(0xE202, ## __VA_ARGS__), \ -+ MACRO__(0xE209, ## __VA_ARGS__), \ - MACRO__(0xE20B, ## __VA_ARGS__), \ - MACRO__(0xE20C, ## __VA_ARGS__), \ - MACRO__(0xE20D, ## __VA_ARGS__), \ -diff -purNx .git BPI-Router-Linux-kernel/include/drm/spsc_queue.h BPI-Router-Linux-kernel-6.16.12/include/drm/spsc_queue.h ---- BPI-Router-Linux-kernel/include/drm/spsc_queue.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/drm/spsc_queue.h 2025-10-22 13:53:56.747168022 -0400 -@@ -70,9 +70,11 @@ static inline bool spsc_queue_push(struc - - preempt_disable(); - -+ atomic_inc(&queue->job_count); -+ smp_mb__after_atomic(); -+ - tail = (struct spsc_node **)atomic_long_xchg(&queue->tail, (long)&node->next); - WRITE_ONCE(*tail, node); -- atomic_inc(&queue->job_count); - - /* - * In case of first element verify new node will be visible to the consumer -diff -purNx .git BPI-Router-Linux-kernel/include/dt-bindings/clock/sun8i-v3s-ccu.h BPI-Router-Linux-kernel-6.16.12/include/dt-bindings/clock/sun8i-v3s-ccu.h ---- BPI-Router-Linux-kernel/include/dt-bindings/clock/sun8i-v3s-ccu.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/dt-bindings/clock/sun8i-v3s-ccu.h 2025-10-22 13:53:56.747168022 -0400 -@@ -96,7 +96,7 @@ - #define CLK_TCON0 64 - #define CLK_CSI_MISC 65 - #define CLK_CSI0_MCLK 66 --#define CLK_CSI1_SCLK 67 -+#define CLK_CSI_SCLK 67 - #define CLK_CSI1_MCLK 68 - #define CLK_VE 69 - #define CLK_AC_DIG 70 -diff -purNx .git BPI-Router-Linux-kernel/include/linux/acpi.h BPI-Router-Linux-kernel-6.16.12/include/linux/acpi.h ---- BPI-Router-Linux-kernel/include/linux/acpi.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/acpi.h 2025-10-22 13:53:56.747168022 -0400 -@@ -1503,7 +1503,7 @@ int acpi_parse_spcr(bool enable_earlycon - #else - static inline int acpi_parse_spcr(bool enable_earlycon, bool enable_console) - { -- return 0; -+ return -ENODEV; - } - #endif - -diff -purNx .git BPI-Router-Linux-kernel/include/linux/arm_ffa.h BPI-Router-Linux-kernel-6.16.12/include/linux/arm_ffa.h ---- BPI-Router-Linux-kernel/include/linux/arm_ffa.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/arm_ffa.h 2025-10-22 13:53:56.747168022 -0400 -@@ -283,6 +283,7 @@ struct ffa_indirect_msg_hdr { - u32 offset; - u32 send_recv_id; - u32 size; -+ u32 res1; - uuid_t uuid; - }; - -diff -purNx .git BPI-Router-Linux-kernel/include/linux/arm-smccc.h BPI-Router-Linux-kernel-6.16.12/include/linux/arm-smccc.h ---- BPI-Router-Linux-kernel/include/linux/arm-smccc.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/arm-smccc.h 2025-10-22 13:53:56.747168022 -0400 -@@ -113,7 +113,7 @@ - - /* KVM UID value: 28b46fb6-2ec5-11e9-a9ca-4b564d003a74 */ - #define ARM_SMCCC_VENDOR_HYP_UID_KVM UUID_INIT(\ -- 0xb66fb428, 0xc52e, 0xe911, \ -+ 0x28b46fb6, 0x2ec5, 0x11e9, \ - 0xa9, 0xca, 0x4b, 0x56, \ - 0x4d, 0x00, 0x3a, 0x74) - -diff -purNx .git BPI-Router-Linux-kernel/include/linux/atmdev.h BPI-Router-Linux-kernel-6.16.12/include/linux/atmdev.h ---- BPI-Router-Linux-kernel/include/linux/atmdev.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/atmdev.h 2025-10-22 13:53:56.747168022 -0400 -@@ -185,6 +185,7 @@ struct atmdev_ops { /* only send is requ - int (*compat_ioctl)(struct atm_dev *dev,unsigned int cmd, - void __user *arg); - #endif -+ int (*pre_send)(struct atm_vcc *vcc, struct sk_buff *skb); - int (*send)(struct atm_vcc *vcc,struct sk_buff *skb); - int (*send_bh)(struct atm_vcc *vcc, struct sk_buff *skb); - int (*send_oam)(struct atm_vcc *vcc,void *cell,int flags); -@@ -249,6 +250,12 @@ static inline void atm_account_tx(struct - ATM_SKB(skb)->atm_options = vcc->atm_options; - } - -+static inline void atm_return_tx(struct atm_vcc *vcc, struct sk_buff *skb) -+{ -+ WARN_ON_ONCE(refcount_sub_and_test(ATM_SKB(skb)->acct_truesize, -+ &sk_atm(vcc)->sk_wmem_alloc)); -+} -+ - static inline void atm_force_charge(struct atm_vcc *vcc,int truesize) - { - atomic_add(truesize, &sk_atm(vcc)->sk_rmem_alloc); -diff -purNx .git BPI-Router-Linux-kernel/include/linux/audit.h BPI-Router-Linux-kernel-6.16.12/include/linux/audit.h ---- BPI-Router-Linux-kernel/include/linux/audit.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/audit.h 2025-10-22 13:53:56.747168022 -0400 -@@ -417,7 +417,7 @@ extern int __audit_log_bprm_fcaps(struct - extern void __audit_log_capset(const struct cred *new, const struct cred *old); - extern void __audit_mmap_fd(int fd, int flags); - extern void __audit_openat2_how(struct open_how *how); --extern void __audit_log_kern_module(char *name); -+extern void __audit_log_kern_module(const char *name); - extern void __audit_fanotify(u32 response, struct fanotify_response_info_audit_rule *friar); - extern void __audit_tk_injoffset(struct timespec64 offset); - extern void __audit_ntp_log(const struct audit_ntp_data *ad); -@@ -519,7 +519,7 @@ static inline void audit_openat2_how(str - __audit_openat2_how(how); - } - --static inline void audit_log_kern_module(char *name) -+static inline void audit_log_kern_module(const char *name) - { - if (!audit_dummy_context()) - __audit_log_kern_module(name); -@@ -677,9 +677,8 @@ static inline void audit_mmap_fd(int fd, - static inline void audit_openat2_how(struct open_how *how) - { } - --static inline void audit_log_kern_module(char *name) --{ --} -+static inline void audit_log_kern_module(const char *name) -+{ } - - static inline void audit_fanotify(u32 response, struct fanotify_response_info_audit_rule *friar) - { } -diff -purNx .git BPI-Router-Linux-kernel/include/linux/bio.h BPI-Router-Linux-kernel-6.16.12/include/linux/bio.h ---- BPI-Router-Linux-kernel/include/linux/bio.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/bio.h 2025-10-22 13:53:56.747168022 -0400 -@@ -291,7 +291,7 @@ static inline void bio_first_folio(struc - - fi->folio = page_folio(bvec->bv_page); - fi->offset = bvec->bv_offset + -- PAGE_SIZE * (bvec->bv_page - &fi->folio->page); -+ PAGE_SIZE * folio_page_idx(fi->folio, bvec->bv_page); - fi->_seg_count = bvec->bv_len; - fi->length = min(folio_size(fi->folio) - fi->offset, fi->_seg_count); - fi->_next = folio_next(fi->folio); -diff -purNx .git BPI-Router-Linux-kernel/include/linux/blkdev.h BPI-Router-Linux-kernel-6.16.12/include/linux/blkdev.h ---- BPI-Router-Linux-kernel/include/linux/blkdev.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/blkdev.h 2025-10-22 13:53:56.747168022 -0400 -@@ -269,11 +269,16 @@ static inline dev_t disk_devt(struct gen - return MKDEV(disk->major, disk->first_minor); - } - -+#ifdef CONFIG_TRANSPARENT_HUGEPAGE - /* - * We should strive for 1 << (PAGE_SHIFT + MAX_PAGECACHE_ORDER) - * however we constrain this to what we can validate and test. - */ - #define BLK_MAX_BLOCK_SIZE SZ_64K -+#else -+#define BLK_MAX_BLOCK_SIZE PAGE_SIZE -+#endif -+ - - /* blk_validate_limits() validates bsize, so drivers don't usually need to */ - static inline int blk_validate_block_size(unsigned long bsize) -@@ -647,6 +652,7 @@ enum { - QUEUE_FLAG_SQ_SCHED, /* single queue style io dispatch */ - QUEUE_FLAG_DISABLE_WBT_DEF, /* for sched to disable/enable wbt */ - QUEUE_FLAG_NO_ELV_SWITCH, /* can't switch elevator any more */ -+ QUEUE_FLAG_QOS_ENABLED, /* qos is enabled */ - QUEUE_FLAG_MAX - }; - -@@ -837,6 +843,55 @@ static inline unsigned int disk_nr_zones - { - return disk->nr_zones; - } -+ -+/** -+ * bio_needs_zone_write_plugging - Check if a BIO needs to be handled with zone -+ * write plugging -+ * @bio: The BIO being submitted -+ * -+ * Return true whenever @bio execution needs to be handled through zone -+ * write plugging (using blk_zone_plug_bio()). Return false otherwise. -+ */ -+static inline bool bio_needs_zone_write_plugging(struct bio *bio) -+{ -+ enum req_op op = bio_op(bio); -+ -+ /* -+ * Only zoned block devices have a zone write plug hash table. But not -+ * all of them have one (e.g. DM devices may not need one). -+ */ -+ if (!bio->bi_bdev->bd_disk->zone_wplugs_hash) -+ return false; -+ -+ /* Only write operations need zone write plugging. */ -+ if (!op_is_write(op)) -+ return false; -+ -+ /* Ignore empty flush */ -+ if (op_is_flush(bio->bi_opf) && !bio_sectors(bio)) -+ return false; -+ -+ /* Ignore BIOs that already have been handled by zone write plugging. */ -+ if (bio_flagged(bio, BIO_ZONE_WRITE_PLUGGING)) -+ return false; -+ -+ /* -+ * All zone write operations must be handled through zone write plugging -+ * using blk_zone_plug_bio(). -+ */ -+ switch (op) { -+ case REQ_OP_ZONE_APPEND: -+ case REQ_OP_WRITE: -+ case REQ_OP_WRITE_ZEROES: -+ case REQ_OP_ZONE_FINISH: -+ case REQ_OP_ZONE_RESET: -+ case REQ_OP_ZONE_RESET_ALL: -+ return true; -+ default: -+ return false; -+ } -+} -+ - bool blk_zone_plug_bio(struct bio *bio, unsigned int nr_segs); - - /** -@@ -866,6 +921,12 @@ static inline unsigned int disk_nr_zones - { - return 0; - } -+ -+static inline bool bio_needs_zone_write_plugging(struct bio *bio) -+{ -+ return false; -+} -+ - static inline bool blk_zone_plug_bio(struct bio *bio, unsigned int nr_segs) - { - return false; -diff -purNx .git BPI-Router-Linux-kernel/include/linux/blk_types.h BPI-Router-Linux-kernel-6.16.12/include/linux/blk_types.h ---- BPI-Router-Linux-kernel/include/linux/blk_types.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/blk_types.h 2025-10-22 13:53:56.747168022 -0400 -@@ -350,11 +350,11 @@ enum req_op { - /* Close a zone */ - REQ_OP_ZONE_CLOSE = (__force blk_opf_t)11, - /* Transition a zone to full */ -- REQ_OP_ZONE_FINISH = (__force blk_opf_t)12, -+ REQ_OP_ZONE_FINISH = (__force blk_opf_t)13, - /* reset a zone write pointer */ -- REQ_OP_ZONE_RESET = (__force blk_opf_t)13, -+ REQ_OP_ZONE_RESET = (__force blk_opf_t)15, - /* reset all the zone present on the device */ -- REQ_OP_ZONE_RESET_ALL = (__force blk_opf_t)15, -+ REQ_OP_ZONE_RESET_ALL = (__force blk_opf_t)17, - - /* Driver private requests */ - REQ_OP_DRV_IN = (__force blk_opf_t)34, -diff -purNx .git BPI-Router-Linux-kernel/include/linux/bpf-cgroup.h BPI-Router-Linux-kernel-6.16.12/include/linux/bpf-cgroup.h ---- BPI-Router-Linux-kernel/include/linux/bpf-cgroup.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/bpf-cgroup.h 2025-10-22 13:53:56.747168022 -0400 -@@ -77,9 +77,6 @@ to_cgroup_bpf_attach_type(enum bpf_attac - extern struct static_key_false cgroup_bpf_enabled_key[MAX_CGROUP_BPF_ATTACH_TYPE]; - #define cgroup_bpf_enabled(atype) static_branch_unlikely(&cgroup_bpf_enabled_key[atype]) - --#define for_each_cgroup_storage_type(stype) \ -- for (stype = 0; stype < MAX_BPF_CGROUP_STORAGE_TYPE; stype++) -- - struct bpf_cgroup_storage_map; - - struct bpf_storage_buffer { -@@ -511,8 +508,6 @@ static inline int bpf_percpu_cgroup_stor - #define BPF_CGROUP_RUN_PROG_SETSOCKOPT(sock, level, optname, optval, optlen, \ - kernel_optval) ({ 0; }) - --#define for_each_cgroup_storage_type(stype) for (; false; ) -- - #endif /* CONFIG_CGROUP_BPF */ - - #endif /* _BPF_CGROUP_H */ -diff -purNx .git BPI-Router-Linux-kernel/include/linux/bpf.h BPI-Router-Linux-kernel-6.16.12/include/linux/bpf.h ---- BPI-Router-Linux-kernel/include/linux/bpf.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/bpf.h 2025-10-22 13:53:56.747168022 -0400 -@@ -208,6 +208,20 @@ enum btf_field_type { - BPF_RES_SPIN_LOCK = (1 << 12), - }; - -+enum bpf_cgroup_storage_type { -+ BPF_CGROUP_STORAGE_SHARED, -+ BPF_CGROUP_STORAGE_PERCPU, -+ __BPF_CGROUP_STORAGE_MAX -+#define MAX_BPF_CGROUP_STORAGE_TYPE __BPF_CGROUP_STORAGE_MAX -+}; -+ -+#ifdef CONFIG_CGROUP_BPF -+# define for_each_cgroup_storage_type(stype) \ -+ for (stype = 0; stype < MAX_BPF_CGROUP_STORAGE_TYPE; stype++) -+#else -+# define for_each_cgroup_storage_type(stype) for (; false; ) -+#endif /* CONFIG_CGROUP_BPF */ -+ - typedef void (*btf_dtor_kfunc_t)(void *); - - struct btf_field_kptr { -@@ -260,6 +274,19 @@ struct bpf_list_node_kern { - void *owner; - } __attribute__((aligned(8))); - -+/* 'Ownership' of program-containing map is claimed by the first program -+ * that is going to use this map or by the first program which FD is -+ * stored in the map to make sure that all callers and callees have the -+ * same prog type, JITed flag and xdp_has_frags flag. -+ */ -+struct bpf_map_owner { -+ enum bpf_prog_type type; -+ bool jited; -+ bool xdp_has_frags; -+ u64 storage_cookie[MAX_BPF_CGROUP_STORAGE_TYPE]; -+ const struct btf_type *attach_func_proto; -+}; -+ - struct bpf_map { - const struct bpf_map_ops *ops; - struct bpf_map *inner_map_meta; -@@ -292,24 +319,15 @@ struct bpf_map { - struct rcu_head rcu; - }; - atomic64_t writecnt; -- /* 'Ownership' of program-containing map is claimed by the first program -- * that is going to use this map or by the first program which FD is -- * stored in the map to make sure that all callers and callees have the -- * same prog type, JITed flag and xdp_has_frags flag. -- */ -- struct { -- const struct btf_type *attach_func_proto; -- spinlock_t lock; -- enum bpf_prog_type type; -- bool jited; -- bool xdp_has_frags; -- } owner; -+ spinlock_t owner_lock; -+ struct bpf_map_owner *owner; - bool bypass_spec_v1; - bool frozen; /* write-once; write-protected by freeze_mutex */ - bool free_after_mult_rcu_gp; - bool free_after_rcu_gp; - atomic64_t sleepable_refcnt; - s64 __percpu *elem_count; -+ u64 cookie; /* write-once */ - }; - - static inline const char *btf_field_type_name(enum btf_field_type type) -@@ -1082,14 +1100,6 @@ struct bpf_prog_offload { - u32 jited_len; - }; - --enum bpf_cgroup_storage_type { -- BPF_CGROUP_STORAGE_SHARED, -- BPF_CGROUP_STORAGE_PERCPU, -- __BPF_CGROUP_STORAGE_MAX --}; -- --#define MAX_BPF_CGROUP_STORAGE_TYPE __BPF_CGROUP_STORAGE_MAX -- - /* The longest tracepoint has 12 args. - * See include/trace/bpf_probe.h - */ -@@ -2071,6 +2081,16 @@ static inline bool bpf_map_flags_access_ - (BPF_F_RDONLY_PROG | BPF_F_WRONLY_PROG); - } - -+static inline struct bpf_map_owner *bpf_map_owner_alloc(struct bpf_map *map) -+{ -+ return kzalloc(sizeof(*map->owner), GFP_ATOMIC); -+} -+ -+static inline void bpf_map_owner_free(struct bpf_map *map) -+{ -+ kfree(map->owner); -+} -+ - struct bpf_event_entry { - struct perf_event *event; - struct file *perf_file; -diff -purNx .git BPI-Router-Linux-kernel/include/linux/bvec.h BPI-Router-Linux-kernel-6.16.12/include/linux/bvec.h ---- BPI-Router-Linux-kernel/include/linux/bvec.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/bvec.h 2025-10-22 13:53:56.747168022 -0400 -@@ -57,9 +57,12 @@ static inline void bvec_set_page(struct - * @offset: offset into the folio - */ - static inline void bvec_set_folio(struct bio_vec *bv, struct folio *folio, -- unsigned int len, unsigned int offset) -+ size_t len, size_t offset) - { -- bvec_set_page(bv, &folio->page, len, offset); -+ unsigned long nr = offset / PAGE_SIZE; -+ -+ WARN_ON_ONCE(len > UINT_MAX); -+ bvec_set_page(bv, folio_page(folio, nr), len, offset % PAGE_SIZE); - } - - /** -diff -purNx .git BPI-Router-Linux-kernel/include/linux/compiler-clang.h BPI-Router-Linux-kernel-6.16.12/include/linux/compiler-clang.h ---- BPI-Router-Linux-kernel/include/linux/compiler-clang.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/compiler-clang.h 2025-10-22 13:53:56.747168022 -0400 -@@ -18,23 +18,42 @@ - #define KASAN_ABI_VERSION 5 - - /* -+ * Clang 22 added preprocessor macros to match GCC, in hopes of eventually -+ * dropping __has_feature support for sanitizers: -+ * https://github.com/llvm/llvm-project/commit/568c23bbd3303518c5056d7f03444dae4fdc8a9c -+ * Create these macros for older versions of clang so that it is easy to clean -+ * up once the minimum supported version of LLVM for building the kernel always -+ * creates these macros. -+ * - * Note: Checking __has_feature(*_sanitizer) is only true if the feature is - * enabled. Therefore it is not required to additionally check defined(CONFIG_*) - * to avoid adding redundant attributes in other configurations. - */ -+#if __has_feature(address_sanitizer) && !defined(__SANITIZE_ADDRESS__) -+#define __SANITIZE_ADDRESS__ -+#endif -+#if __has_feature(hwaddress_sanitizer) && !defined(__SANITIZE_HWADDRESS__) -+#define __SANITIZE_HWADDRESS__ -+#endif -+#if __has_feature(thread_sanitizer) && !defined(__SANITIZE_THREAD__) -+#define __SANITIZE_THREAD__ -+#endif - --#if __has_feature(address_sanitizer) || __has_feature(hwaddress_sanitizer) --/* Emulate GCC's __SANITIZE_ADDRESS__ flag */ -+/* -+ * Treat __SANITIZE_HWADDRESS__ the same as __SANITIZE_ADDRESS__ in the kernel. -+ */ -+#ifdef __SANITIZE_HWADDRESS__ - #define __SANITIZE_ADDRESS__ -+#endif -+ -+#ifdef __SANITIZE_ADDRESS__ - #define __no_sanitize_address \ - __attribute__((no_sanitize("address", "hwaddress"))) - #else - #define __no_sanitize_address - #endif - --#if __has_feature(thread_sanitizer) --/* emulate gcc's __SANITIZE_THREAD__ flag */ --#define __SANITIZE_THREAD__ -+#ifdef __SANITIZE_THREAD__ - #define __no_sanitize_thread \ - __attribute__((no_sanitize("thread"))) - #else -diff -purNx .git BPI-Router-Linux-kernel/include/linux/compiler.h BPI-Router-Linux-kernel-6.16.12/include/linux/compiler.h ---- BPI-Router-Linux-kernel/include/linux/compiler.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/compiler.h 2025-10-22 13:53:56.747168022 -0400 -@@ -288,14 +288,6 @@ static inline void *offset_to_ptr(const - #define __ADDRESSABLE(sym) \ - ___ADDRESSABLE(sym, __section(".discard.addressable")) - --#define __ADDRESSABLE_ASM(sym) \ -- .pushsection .discard.addressable,"aw"; \ -- .align ARCH_SEL(8,4); \ -- ARCH_SEL(.quad, .long) __stringify(sym); \ -- .popsection; -- --#define __ADDRESSABLE_ASM_STR(sym) __stringify(__ADDRESSABLE_ASM(sym)) -- - /* - * This returns a constant expression while determining if an argument is - * a constant expression, most importantly without evaluating the argument. -diff -purNx .git BPI-Router-Linux-kernel/include/linux/cpu.h BPI-Router-Linux-kernel-6.16.12/include/linux/cpu.h ---- BPI-Router-Linux-kernel/include/linux/cpu.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/cpu.h 2025-10-22 13:53:56.747168022 -0400 -@@ -82,6 +82,8 @@ extern ssize_t cpu_show_old_microcode(st - struct device_attribute *attr, char *buf); - extern ssize_t cpu_show_indirect_target_selection(struct device *dev, - struct device_attribute *attr, char *buf); -+extern ssize_t cpu_show_tsa(struct device *dev, struct device_attribute *attr, char *buf); -+extern ssize_t cpu_show_vmscape(struct device *dev, struct device_attribute *attr, char *buf); - - extern __printf(4, 5) - struct device *cpu_device_create(struct device *parent, void *drvdata, -@@ -120,6 +122,7 @@ extern void cpu_maps_update_begin(void); - extern void cpu_maps_update_done(void); - int bringup_hibernate_cpu(unsigned int sleep_cpu); - void bringup_nonboot_cpus(unsigned int max_cpus); -+int arch_cpu_rescan_dead_smt_siblings(void); - - #else /* CONFIG_SMP */ - #define cpuhp_tasks_frozen 0 -@@ -134,6 +137,8 @@ static inline void cpu_maps_update_done( - - static inline int add_cpu(unsigned int cpu) { return 0;} - -+static inline int arch_cpu_rescan_dead_smt_siblings(void) { return 0; } -+ - #endif /* CONFIG_SMP */ - extern const struct bus_type cpu_subsys; - -diff -purNx .git BPI-Router-Linux-kernel/include/linux/cpuhotplug.h BPI-Router-Linux-kernel-6.16.12/include/linux/cpuhotplug.h ---- BPI-Router-Linux-kernel/include/linux/cpuhotplug.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/cpuhotplug.h 2025-10-22 13:53:56.747168022 -0400 -@@ -169,6 +169,7 @@ enum cpuhp_state { - CPUHP_AP_QCOM_TIMER_STARTING, - CPUHP_AP_TEGRA_TIMER_STARTING, - CPUHP_AP_ARMADA_TIMER_STARTING, -+ CPUHP_AP_LOONGARCH_ARCH_TIMER_STARTING, - CPUHP_AP_MIPS_GIC_TIMER_STARTING, - CPUHP_AP_ARC_TIMER_STARTING, - CPUHP_AP_REALTEK_TIMER_STARTING, -diff -purNx .git BPI-Router-Linux-kernel/include/linux/crypto.h BPI-Router-Linux-kernel-6.16.12/include/linux/crypto.h ---- BPI-Router-Linux-kernel/include/linux/crypto.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/crypto.h 2025-10-22 13:53:56.747168022 -0400 -@@ -136,6 +136,9 @@ - /* Set if the algorithm supports virtual addresses. */ - #define CRYPTO_ALG_REQ_VIRT 0x00040000 - -+/* Set if the algorithm cannot have a fallback (e.g., phmac). */ -+#define CRYPTO_ALG_NO_FALLBACK 0x00080000 -+ - /* The high bits 0xff000000 are reserved for type-specific flags. */ - - /* -diff -purNx .git BPI-Router-Linux-kernel/include/linux/device.h BPI-Router-Linux-kernel-6.16.12/include/linux/device.h ---- BPI-Router-Linux-kernel/include/linux/device.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/device.h 2025-10-22 13:53:56.747168022 -0400 -@@ -851,6 +851,9 @@ static inline bool device_pm_not_require - static inline void device_set_pm_not_required(struct device *dev) - { - dev->power.no_pm = true; -+#ifdef CONFIG_PM -+ dev->power.no_callbacks = true; -+#endif - } - - static inline void dev_pm_syscore_device(struct device *dev, bool val) -diff -purNx .git BPI-Router-Linux-kernel/include/linux/dma-map-ops.h BPI-Router-Linux-kernel-6.16.12/include/linux/dma-map-ops.h ---- BPI-Router-Linux-kernel/include/linux/dma-map-ops.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/dma-map-ops.h 2025-10-22 13:53:56.747168022 -0400 -@@ -153,6 +153,9 @@ static inline void dma_free_contiguous(s - { - __free_pages(page, get_order(size)); - } -+static inline void dma_contiguous_early_fixup(phys_addr_t base, unsigned long size) -+{ -+} - #endif /* CONFIG_DMA_CMA*/ - - #ifdef CONFIG_DMA_DECLARE_COHERENT -diff -purNx .git BPI-Router-Linux-kernel/include/linux/energy_model.h BPI-Router-Linux-kernel-6.16.12/include/linux/energy_model.h ---- BPI-Router-Linux-kernel/include/linux/energy_model.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/energy_model.h 2025-10-22 13:53:56.747168022 -0400 -@@ -171,6 +171,9 @@ int em_dev_update_perf_domain(struct dev - int em_dev_register_perf_domain(struct device *dev, unsigned int nr_states, - const struct em_data_callback *cb, - const cpumask_t *cpus, bool microwatts); -+int em_dev_register_pd_no_update(struct device *dev, unsigned int nr_states, -+ const struct em_data_callback *cb, -+ const cpumask_t *cpus, bool microwatts); - void em_dev_unregister_perf_domain(struct device *dev); - struct em_perf_table *em_table_alloc(struct em_perf_domain *pd); - void em_table_free(struct em_perf_table *table); -@@ -350,6 +353,13 @@ int em_dev_register_perf_domain(struct d - { - return -EINVAL; - } -+static inline -+int em_dev_register_pd_no_update(struct device *dev, unsigned int nr_states, -+ const struct em_data_callback *cb, -+ const cpumask_t *cpus, bool microwatts) -+{ -+ return -EINVAL; -+} - static inline void em_dev_unregister_perf_domain(struct device *dev) - { - } -diff -purNx .git BPI-Router-Linux-kernel/include/linux/execmem.h BPI-Router-Linux-kernel-6.16.12/include/linux/execmem.h ---- BPI-Router-Linux-kernel/include/linux/execmem.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/execmem.h 2025-10-22 13:53:56.747168022 -0400 -@@ -54,7 +54,7 @@ enum execmem_range_flags { - EXECMEM_ROX_CACHE = (1 << 1), - }; - --#if defined(CONFIG_ARCH_HAS_EXECMEM_ROX) && defined(CONFIG_EXECMEM) -+#ifdef CONFIG_ARCH_HAS_EXECMEM_ROX - /** - * execmem_fill_trapping_insns - set memory to contain instructions that - * will trap -@@ -94,15 +94,9 @@ int execmem_make_temp_rw(void *ptr, size - * Return: 0 on success or negative error code on failure. - */ - int execmem_restore_rox(void *ptr, size_t size); -- --/* -- * Called from mark_readonly(), where the system transitions to ROX. -- */ --void execmem_cache_make_ro(void); - #else - static inline int execmem_make_temp_rw(void *ptr, size_t size) { return 0; } - static inline int execmem_restore_rox(void *ptr, size_t size) { return 0; } --static inline void execmem_cache_make_ro(void) { } - #endif - - /** -diff -purNx .git BPI-Router-Linux-kernel/include/linux/firmware/imx/sm.h BPI-Router-Linux-kernel-6.16.12/include/linux/firmware/imx/sm.h ---- BPI-Router-Linux-kernel/include/linux/firmware/imx/sm.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/firmware/imx/sm.h 2025-10-22 13:53:56.747168022 -0400 -@@ -18,13 +18,43 @@ - #define SCMI_IMX_CTRL_SAI4_MCLK 4 /* WAKE SAI4 MCLK */ - #define SCMI_IMX_CTRL_SAI5_MCLK 5 /* WAKE SAI5 MCLK */ - -+#if IS_ENABLED(CONFIG_IMX_SCMI_MISC_DRV) - int scmi_imx_misc_ctrl_get(u32 id, u32 *num, u32 *val); - int scmi_imx_misc_ctrl_set(u32 id, u32 val); -+#else -+static inline int scmi_imx_misc_ctrl_get(u32 id, u32 *num, u32 *val) -+{ -+ return -EOPNOTSUPP; -+} - -+static inline int scmi_imx_misc_ctrl_set(u32 id, u32 val) -+{ -+ return -EOPNOTSUPP; -+} -+#endif -+ -+#if IS_ENABLED(CONFIG_IMX_SCMI_CPU_DRV) - int scmi_imx_cpu_start(u32 cpuid, bool start); - int scmi_imx_cpu_started(u32 cpuid, bool *started); - int scmi_imx_cpu_reset_vector_set(u32 cpuid, u64 vector, bool start, bool boot, - bool resume); -+#else -+static inline int scmi_imx_cpu_start(u32 cpuid, bool start) -+{ -+ return -EOPNOTSUPP; -+} -+ -+static inline int scmi_imx_cpu_started(u32 cpuid, bool *started) -+{ -+ return -EOPNOTSUPP; -+} -+ -+static inline int scmi_imx_cpu_reset_vector_set(u32 cpuid, u64 vector, bool start, -+ bool boot, bool resume) -+{ -+ return -EOPNOTSUPP; -+} -+#endif - - enum scmi_imx_lmm_op { - SCMI_IMX_LMM_BOOT, -@@ -36,7 +66,24 @@ enum scmi_imx_lmm_op { - #define SCMI_IMX_LMM_OP_FORCEFUL 0 - #define SCMI_IMX_LMM_OP_GRACEFUL BIT(0) - -+#if IS_ENABLED(CONFIG_IMX_SCMI_LMM_DRV) - int scmi_imx_lmm_operation(u32 lmid, enum scmi_imx_lmm_op op, u32 flags); - int scmi_imx_lmm_info(u32 lmid, struct scmi_imx_lmm_info *info); - int scmi_imx_lmm_reset_vector_set(u32 lmid, u32 cpuid, u32 flags, u64 vector); -+#else -+static inline int scmi_imx_lmm_operation(u32 lmid, enum scmi_imx_lmm_op op, u32 flags) -+{ -+ return -EOPNOTSUPP; -+} -+ -+static inline int scmi_imx_lmm_info(u32 lmid, struct scmi_imx_lmm_info *info) -+{ -+ return -EOPNOTSUPP; -+} -+ -+static inline int scmi_imx_lmm_reset_vector_set(u32 lmid, u32 cpuid, u32 flags, u64 vector) -+{ -+ return -EOPNOTSUPP; -+} -+#endif - #endif -diff -purNx .git BPI-Router-Linux-kernel/include/linux/firmware/qcom/qcom_scm.h BPI-Router-Linux-kernel-6.16.12/include/linux/firmware/qcom/qcom_scm.h ---- BPI-Router-Linux-kernel/include/linux/firmware/qcom/qcom_scm.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/firmware/qcom/qcom_scm.h 2025-10-22 13:53:56.747168022 -0400 -@@ -148,11 +148,10 @@ bool qcom_scm_lmh_dcvsh_available(void); - - int qcom_scm_gpu_init_regs(u32 gpu_req); - --int qcom_scm_shm_bridge_enable(void); --int qcom_scm_shm_bridge_create(struct device *dev, u64 pfn_and_ns_perm_flags, -+int qcom_scm_shm_bridge_create(u64 pfn_and_ns_perm_flags, - u64 ipfn_and_s_perm_flags, u64 size_and_flags, - u64 ns_vmids, u64 *handle); --int qcom_scm_shm_bridge_delete(struct device *dev, u64 handle); -+int qcom_scm_shm_bridge_delete(u64 handle); - - #ifdef CONFIG_QCOM_QSEECOM - -diff -purNx .git BPI-Router-Linux-kernel/include/linux/fortify-string.h BPI-Router-Linux-kernel-6.16.12/include/linux/fortify-string.h ---- BPI-Router-Linux-kernel/include/linux/fortify-string.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/fortify-string.h 2025-10-22 13:53:56.747168022 -0400 -@@ -596,7 +596,7 @@ __FORTIFY_INLINE bool fortify_memcpy_chk - if (p_size != SIZE_MAX && p_size < size) - fortify_panic(func, FORTIFY_WRITE, p_size, size, true); - else if (q_size != SIZE_MAX && q_size < size) -- fortify_panic(func, FORTIFY_READ, p_size, size, true); -+ fortify_panic(func, FORTIFY_READ, q_size, size, true); - - /* - * Warn when writing beyond destination field size. -diff -purNx .git BPI-Router-Linux-kernel/include/linux/fs_context.h BPI-Router-Linux-kernel-6.16.12/include/linux/fs_context.h ---- BPI-Router-Linux-kernel/include/linux/fs_context.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/fs_context.h 2025-10-22 13:53:56.747168022 -0400 -@@ -200,7 +200,7 @@ void logfc(struct fc_log *log, const cha - */ - #define infof(fc, fmt, ...) __logfc(fc, 'i', fmt, ## __VA_ARGS__) - #define info_plog(p, fmt, ...) __plog(p, 'i', fmt, ## __VA_ARGS__) --#define infofc(p, fmt, ...) __plog((&(fc)->log), 'i', fmt, ## __VA_ARGS__) -+#define infofc(fc, fmt, ...) __plog((&(fc)->log), 'i', fmt, ## __VA_ARGS__) - - /** - * warnf - Store supplementary warning message -diff -purNx .git BPI-Router-Linux-kernel/include/linux/fs.h BPI-Router-Linux-kernel-6.16.12/include/linux/fs.h ---- BPI-Router-Linux-kernel/include/linux/fs.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/fs.h 2025-10-22 13:53:56.747168022 -0400 -@@ -149,7 +149,8 @@ typedef int (dio_iodone_t)(struct kiocb - /* Expect random access pattern */ - #define FMODE_RANDOM ((__force fmode_t)(1 << 12)) - --/* FMODE_* bit 13 */ -+/* Supports IOCB_HAS_METADATA */ -+#define FMODE_HAS_METADATA ((__force fmode_t)(1 << 13)) - - /* File is opened with O_PATH; almost nothing can be done with it */ - #define FMODE_PATH ((__force fmode_t)(1 << 14)) -@@ -399,7 +400,9 @@ struct readahead_control; - { IOCB_WAITQ, "WAITQ" }, \ - { IOCB_NOIO, "NOIO" }, \ - { IOCB_ALLOC_CACHE, "ALLOC_CACHE" }, \ -- { IOCB_DIO_CALLER_COMP, "CALLER_COMP" } -+ { IOCB_DIO_CALLER_COMP, "CALLER_COMP" }, \ -+ { IOCB_AIO_RW, "AIO_RW" }, \ -+ { IOCB_HAS_METADATA, "AIO_HAS_METADATA" } - - struct kiocb { - struct file *ki_filp; -@@ -2274,10 +2277,12 @@ static inline bool file_has_valid_mmap_h - return true; - } - -+int compat_vma_mmap_prepare(struct file *file, struct vm_area_struct *vma); -+ - static inline int call_mmap(struct file *file, struct vm_area_struct *vma) - { -- if (WARN_ON_ONCE(file->f_op->mmap_prepare)) -- return -EINVAL; -+ if (file->f_op->mmap_prepare) -+ return compat_vma_mmap_prepare(file, vma); - - return file->f_op->mmap(file, vma); - } -@@ -3604,6 +3609,8 @@ extern int simple_write_begin(struct fil - extern const struct address_space_operations ram_aops; - extern int always_delete_dentry(const struct dentry *); - extern struct inode *alloc_anon_inode(struct super_block *); -+struct inode *anon_inode_make_secure_inode(struct super_block *sb, const char *name, -+ const struct inode *context_inode); - extern int simple_nosetlease(struct file *, int, struct file_lease **, void **); - extern const struct dentry_operations simple_dentry_operations; - -diff -purNx .git BPI-Router-Linux-kernel/include/linux/futex.h BPI-Router-Linux-kernel-6.16.12/include/linux/futex.h ---- BPI-Router-Linux-kernel/include/linux/futex.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/futex.h 2025-10-22 13:53:56.747168022 -0400 -@@ -89,6 +89,7 @@ void futex_hash_free(struct mm_struct *m - static inline void futex_mm_init(struct mm_struct *mm) - { - RCU_INIT_POINTER(mm->futex_phash, NULL); -+ mm->futex_phash_new = NULL; - mutex_init(&mm->futex_hash_lock); - } - -diff -purNx .git BPI-Router-Linux-kernel/include/linux/hid.h BPI-Router-Linux-kernel-6.16.12/include/linux/hid.h ---- BPI-Router-Linux-kernel/include/linux/hid.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/hid.h 2025-10-22 13:53:56.751168003 -0400 -@@ -1239,6 +1239,8 @@ void hid_quirks_exit(__u16 bus); - dev_notice(&(hid)->dev, fmt, ##__VA_ARGS__) - #define hid_warn(hid, fmt, ...) \ - dev_warn(&(hid)->dev, fmt, ##__VA_ARGS__) -+#define hid_warn_ratelimited(hid, fmt, ...) \ -+ dev_warn_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__) - #define hid_info(hid, fmt, ...) \ - dev_info(&(hid)->dev, fmt, ##__VA_ARGS__) - #define hid_dbg(hid, fmt, ...) \ -diff -purNx .git BPI-Router-Linux-kernel/include/linux/hypervisor.h BPI-Router-Linux-kernel-6.16.12/include/linux/hypervisor.h ---- BPI-Router-Linux-kernel/include/linux/hypervisor.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/hypervisor.h 2025-10-22 13:53:56.751168003 -0400 -@@ -37,6 +37,9 @@ static inline bool hypervisor_isolated_p - if (IS_ENABLED(CONFIG_S390)) - return true; - -+ if (IS_ENABLED(CONFIG_LOONGARCH)) -+ return true; -+ - return jailhouse_paravirt(); - } - -diff -purNx .git BPI-Router-Linux-kernel/include/linux/i3c/device.h BPI-Router-Linux-kernel-6.16.12/include/linux/i3c/device.h ---- BPI-Router-Linux-kernel/include/linux/i3c/device.h 2025-10-22 13:53:23.555327498 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/i3c/device.h 2025-10-22 13:53:56.751168003 -0400 -@@ -245,7 +245,7 @@ void i3c_driver_unregister(struct i3c_dr - * - * Return: 0 if both registrations succeeds, a negative error code otherwise. - */ --static inline int i3c_i2c_driver_register(struct i3c_driver *i3cdrv, -+static __always_inline int i3c_i2c_driver_register(struct i3c_driver *i3cdrv, - struct i2c_driver *i2cdrv) - { - int ret; -@@ -270,7 +270,7 @@ static inline int i3c_i2c_driver_registe - * Note that when CONFIG_I3C is not enabled, this function only unregisters the - * @i2cdrv. - */ --static inline void i3c_i2c_driver_unregister(struct i3c_driver *i3cdrv, -+static __always_inline void i3c_i2c_driver_unregister(struct i3c_driver *i3cdrv, - struct i2c_driver *i2cdrv) - { - if (IS_ENABLED(CONFIG_I3C)) -diff -purNx .git BPI-Router-Linux-kernel/include/linux/ieee80211.h BPI-Router-Linux-kernel-6.16.12/include/linux/ieee80211.h ---- BPI-Router-Linux-kernel/include/linux/ieee80211.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/ieee80211.h 2025-10-22 13:53:56.751168003 -0400 -@@ -663,18 +663,6 @@ static inline bool ieee80211_s1g_has_css - } - - /** -- * ieee80211_is_s1g_short_beacon - check if frame is an S1G short beacon -- * @fc: frame control bytes in little-endian byteorder -- * Return: whether or not the frame is an S1G short beacon, -- * i.e. it is an S1G beacon with 'next TBTT' flag set -- */ --static inline bool ieee80211_is_s1g_short_beacon(__le16 fc) --{ -- return ieee80211_is_s1g_beacon(fc) && -- (fc & cpu_to_le16(IEEE80211_S1G_BCN_NEXT_TBTT)); --} -- --/** - * ieee80211_is_atim - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ATIM - * @fc: frame control bytes in little-endian byteorder - * Return: whether or not the frame is an ATIM frame -@@ -1278,7 +1266,7 @@ struct ieee80211_ext { - u8 sa[ETH_ALEN]; - __le32 timestamp; - u8 change_seq; -- u8 variable[0]; -+ u8 variable[]; - } __packed s1g_beacon; - } u; - } __packed __aligned(2); -@@ -1536,7 +1524,7 @@ struct ieee80211_mgmt { - u8 action_code; - u8 dialog_token; - __le16 capability; -- u8 variable[0]; -+ u8 variable[]; - } __packed tdls_discover_resp; - struct { - u8 action_code; -@@ -1721,35 +1709,35 @@ struct ieee80211_tdls_data { - struct { - u8 dialog_token; - __le16 capability; -- u8 variable[0]; -+ u8 variable[]; - } __packed setup_req; - struct { - __le16 status_code; - u8 dialog_token; - __le16 capability; -- u8 variable[0]; -+ u8 variable[]; - } __packed setup_resp; - struct { - __le16 status_code; - u8 dialog_token; -- u8 variable[0]; -+ u8 variable[]; - } __packed setup_cfm; - struct { - __le16 reason_code; -- u8 variable[0]; -+ u8 variable[]; - } __packed teardown; - struct { - u8 dialog_token; -- u8 variable[0]; -+ u8 variable[]; - } __packed discover_req; - struct { - u8 target_channel; - u8 oper_class; -- u8 variable[0]; -+ u8 variable[]; - } __packed chan_switch_req; - struct { - __le16 status_code; -- u8 variable[0]; -+ u8 variable[]; - } __packed chan_switch_resp; - } u; - } __packed; -@@ -4901,6 +4889,39 @@ static inline bool ieee80211_is_ftm(stru - return false; - } - -+/** -+ * ieee80211_is_s1g_short_beacon - check if frame is an S1G short beacon -+ * @fc: frame control bytes in little-endian byteorder -+ * @variable: pointer to the beacon frame elements -+ * @variable_len: length of the frame elements -+ * Return: whether or not the frame is an S1G short beacon. As per -+ * IEEE80211-2024 11.1.3.10.1, The S1G beacon compatibility element shall -+ * always be present as the first element in beacon frames generated at a -+ * TBTT (Target Beacon Transmission Time), so any frame not containing -+ * this element must have been generated at a TSBTT (Target Short Beacon -+ * Transmission Time) that is not a TBTT. Additionally, short beacons are -+ * prohibited from containing the S1G beacon compatibility element as per -+ * IEEE80211-2024 9.3.4.3 Table 9-76, so if we have an S1G beacon with -+ * either no elements or the first element is not the beacon compatibility -+ * element, we have a short beacon. -+ */ -+static inline bool ieee80211_is_s1g_short_beacon(__le16 fc, const u8 *variable, -+ size_t variable_len) -+{ -+ if (!ieee80211_is_s1g_beacon(fc)) -+ return false; -+ -+ /* -+ * If the frame does not contain at least 1 element (this is perfectly -+ * valid in a short beacon) and is an S1G beacon, we have a short -+ * beacon. -+ */ -+ if (variable_len < 2) -+ return true; -+ -+ return variable[0] != WLAN_EID_S1G_BCN_COMPAT; -+} -+ - struct element { - u8 id; - u8 datalen; -diff -purNx .git BPI-Router-Linux-kernel/include/linux/if_team.h BPI-Router-Linux-kernel-6.16.12/include/linux/if_team.h ---- BPI-Router-Linux-kernel/include/linux/if_team.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/if_team.h 2025-10-22 13:53:56.751168003 -0400 -@@ -191,8 +191,6 @@ struct team { - - const struct header_ops *header_ops_cache; - -- struct mutex lock; /* used for overall locking, e.g. port lists write */ -- - /* - * List of enabled ports and their count - */ -@@ -223,7 +221,6 @@ struct team { - atomic_t count_pending; - struct delayed_work dw; - } mcast_rejoin; -- struct lock_class_key team_lock_key; - long mode_priv[TEAM_MODE_PRIV_LONGS]; - }; - -diff -purNx .git BPI-Router-Linux-kernel/include/linux/if_vlan.h BPI-Router-Linux-kernel-6.16.12/include/linux/if_vlan.h ---- BPI-Router-Linux-kernel/include/linux/if_vlan.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/if_vlan.h 2025-10-22 13:53:56.751168003 -0400 -@@ -79,11 +79,6 @@ static inline struct vlan_ethhdr *skb_vl - /* found in socket.c */ - extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *)); - --static inline bool is_vlan_dev(const struct net_device *dev) --{ -- return dev->priv_flags & IFF_802_1Q_VLAN; --} -- - #define skb_vlan_tag_present(__skb) (!!(__skb)->vlan_all) - #define skb_vlan_tag_get(__skb) ((__skb)->vlan_tci) - #define skb_vlan_tag_get_id(__skb) ((__skb)->vlan_tci & VLAN_VID_MASK) -@@ -200,6 +195,11 @@ struct vlan_dev_priv { - #endif - }; - -+static inline bool is_vlan_dev(const struct net_device *dev) -+{ -+ return dev->priv_flags & IFF_802_1Q_VLAN; -+} -+ - static inline struct vlan_dev_priv *vlan_dev_priv(const struct net_device *dev) - { - return netdev_priv(dev); -@@ -237,6 +237,11 @@ extern void vlan_vids_del_by_dev(struct - extern bool vlan_uses_dev(const struct net_device *dev); - - #else -+static inline bool is_vlan_dev(const struct net_device *dev) -+{ -+ return false; -+} -+ - static inline struct net_device * - __vlan_find_dev_deep_rcu(struct net_device *real_dev, - __be16 vlan_proto, u16 vlan_id) -@@ -254,19 +259,19 @@ vlan_for_each(struct net_device *dev, - - static inline struct net_device *vlan_dev_real_dev(const struct net_device *dev) - { -- BUG(); -+ WARN_ON_ONCE(1); - return NULL; - } - - static inline u16 vlan_dev_vlan_id(const struct net_device *dev) - { -- BUG(); -+ WARN_ON_ONCE(1); - return 0; - } - - static inline __be16 vlan_dev_vlan_proto(const struct net_device *dev) - { -- BUG(); -+ WARN_ON_ONCE(1); - return 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/include/linux/interconnect-provider.h BPI-Router-Linux-kernel-6.16.12/include/linux/interconnect-provider.h ---- BPI-Router-Linux-kernel/include/linux/interconnect-provider.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/interconnect-provider.h 2025-10-22 13:53:56.751168003 -0400 -@@ -119,6 +119,7 @@ int icc_std_aggregate(struct icc_node *n - struct icc_node *icc_node_create_dyn(void); - struct icc_node *icc_node_create(int id); - void icc_node_destroy(int id); -+int icc_node_set_name(struct icc_node *node, const struct icc_provider *provider, const char *name); - int icc_link_nodes(struct icc_node *src_node, struct icc_node **dst_node); - int icc_link_create(struct icc_node *node, const int dst_id); - void icc_node_add(struct icc_node *node, struct icc_provider *provider); -@@ -152,6 +153,12 @@ static inline void icc_node_destroy(int - { - } - -+static inline int icc_node_set_name(struct icc_node *node, const struct icc_provider *provider, -+ const char *name) -+{ -+ return -EOPNOTSUPP; -+} -+ - static inline int icc_link_nodes(struct icc_node *src_node, struct icc_node **dst_node) - { - return -EOPNOTSUPP; -diff -purNx .git BPI-Router-Linux-kernel/include/linux/ioprio.h BPI-Router-Linux-kernel-6.16.12/include/linux/ioprio.h ---- BPI-Router-Linux-kernel/include/linux/ioprio.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/ioprio.h 2025-10-22 13:53:56.751168003 -0400 -@@ -60,7 +60,8 @@ static inline int __get_task_ioprio(stru - int prio; - - if (!ioc) -- return IOPRIO_DEFAULT; -+ return IOPRIO_PRIO_VALUE(task_nice_ioclass(p), -+ task_nice_ioprio(p)); - - if (p != current) - lockdep_assert_held(&p->alloc_lock); -diff -purNx .git BPI-Router-Linux-kernel/include/linux/iosys-map.h BPI-Router-Linux-kernel-6.16.12/include/linux/iosys-map.h ---- BPI-Router-Linux-kernel/include/linux/iosys-map.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/iosys-map.h 2025-10-22 13:53:56.751168003 -0400 -@@ -264,12 +264,7 @@ static inline bool iosys_map_is_set(cons - */ - static inline void iosys_map_clear(struct iosys_map *map) - { -- if (map->is_iomem) { -- map->vaddr_iomem = NULL; -- map->is_iomem = false; -- } else { -- map->vaddr = NULL; -- } -+ memset(map, 0, sizeof(*map)); - } - - /** -diff -purNx .git BPI-Router-Linux-kernel/include/linux/io_uring_types.h BPI-Router-Linux-kernel-6.16.12/include/linux/io_uring_types.h ---- BPI-Router-Linux-kernel/include/linux/io_uring_types.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/io_uring_types.h 2025-10-22 13:53:56.751168003 -0400 -@@ -418,9 +418,6 @@ struct io_ring_ctx { - struct list_head defer_list; - unsigned nr_drained; - -- struct io_alloc_cache msg_cache; -- spinlock_t msg_lock; -- - #ifdef CONFIG_NET_RX_BUSY_POLL - struct list_head napi_list; /* track busy poll napi_id */ - spinlock_t napi_lock; /* napi_list lock */ -@@ -698,6 +695,8 @@ struct io_kiocb { - struct hlist_node hash_node; - /* For IOPOLL setup queues, with hybrid polling */ - u64 iopoll_start; -+ /* for private io_kiocb freeing */ -+ struct rcu_head rcu_head; - }; - /* internal polling, see IORING_FEAT_FAST_POLL */ - struct async_poll *apoll; -diff -purNx .git BPI-Router-Linux-kernel/include/linux/iov_iter.h BPI-Router-Linux-kernel-6.16.12/include/linux/iov_iter.h ---- BPI-Router-Linux-kernel/include/linux/iov_iter.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/iov_iter.h 2025-10-22 13:53:56.751168003 -0400 -@@ -160,7 +160,7 @@ size_t iterate_folioq(struct iov_iter *i - - do { - struct folio *folio = folioq_folio(folioq, slot); -- size_t part, remain, consumed; -+ size_t part, remain = 0, consumed; - size_t fsize; - void *base; - -@@ -168,14 +168,16 @@ size_t iterate_folioq(struct iov_iter *i - break; - - fsize = folioq_folio_size(folioq, slot); -- base = kmap_local_folio(folio, skip); -- part = umin(len, PAGE_SIZE - skip % PAGE_SIZE); -- remain = step(base, progress, part, priv, priv2); -- kunmap_local(base); -- consumed = part - remain; -- len -= consumed; -- progress += consumed; -- skip += consumed; -+ if (skip < fsize) { -+ base = kmap_local_folio(folio, skip); -+ part = umin(len, PAGE_SIZE - skip % PAGE_SIZE); -+ remain = step(base, progress, part, priv, priv2); -+ kunmap_local(base); -+ consumed = part - remain; -+ len -= consumed; -+ progress += consumed; -+ skip += consumed; -+ } - if (skip >= fsize) { - skip = 0; - slot++; -diff -purNx .git BPI-Router-Linux-kernel/include/linux/irqchip/irq-msi-lib.h BPI-Router-Linux-kernel-6.16.12/include/linux/irqchip/irq-msi-lib.h ---- BPI-Router-Linux-kernel/include/linux/irqchip/irq-msi-lib.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/irqchip/irq-msi-lib.h 2025-10-22 13:53:56.751168003 -0400 -@@ -17,6 +17,7 @@ - - #define MATCH_PLATFORM_MSI BIT(DOMAIN_BUS_PLATFORM_MSI) - -+struct msi_domain_info; - int msi_lib_irq_domain_select(struct irq_domain *d, struct irq_fwspec *fwspec, - enum irq_domain_bus_token bus_token); - -diff -purNx .git BPI-Router-Linux-kernel/include/linux/ism.h BPI-Router-Linux-kernel-6.16.12/include/linux/ism.h ---- BPI-Router-Linux-kernel/include/linux/ism.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/ism.h 2025-10-22 13:53:56.751168003 -0400 -@@ -28,6 +28,7 @@ struct ism_dmb { - - struct ism_dev { - spinlock_t lock; /* protects the ism device */ -+ spinlock_t cmd_lock; /* serializes cmds */ - struct list_head list; - struct pci_dev *pdev; - -diff -purNx .git BPI-Router-Linux-kernel/include/linux/kasan.h BPI-Router-Linux-kernel-6.16.12/include/linux/kasan.h ---- BPI-Router-Linux-kernel/include/linux/kasan.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/kasan.h 2025-10-22 13:53:56.751168003 -0400 -@@ -562,7 +562,7 @@ static inline void kasan_init_hw_tags(vo - #if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS) - - void kasan_populate_early_vm_area_shadow(void *start, unsigned long size); --int kasan_populate_vmalloc(unsigned long addr, unsigned long size); -+int kasan_populate_vmalloc(unsigned long addr, unsigned long size, gfp_t gfp_mask); - void kasan_release_vmalloc(unsigned long start, unsigned long end, - unsigned long free_region_start, - unsigned long free_region_end, -@@ -574,7 +574,7 @@ static inline void kasan_populate_early_ - unsigned long size) - { } - static inline int kasan_populate_vmalloc(unsigned long start, -- unsigned long size) -+ unsigned long size, gfp_t gfp_mask) - { - return 0; - } -@@ -610,7 +610,7 @@ static __always_inline void kasan_poison - static inline void kasan_populate_early_vm_area_shadow(void *start, - unsigned long size) { } - static inline int kasan_populate_vmalloc(unsigned long start, -- unsigned long size) -+ unsigned long size, gfp_t gfp_mask) - { - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/include/linux/kcov.h BPI-Router-Linux-kernel-6.16.12/include/linux/kcov.h ---- BPI-Router-Linux-kernel/include/linux/kcov.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/kcov.h 2025-10-22 13:53:56.751168003 -0400 -@@ -57,47 +57,21 @@ static inline void kcov_remote_start_usb - - /* - * The softirq flavor of kcov_remote_*() functions is introduced as a temporary -- * workaround for KCOV's lack of nested remote coverage sections support. -- * -- * Adding support is tracked in https://bugzilla.kernel.org/show_bug.cgi?id=210337. -- * -- * kcov_remote_start_usb_softirq(): -- * -- * 1. Only collects coverage when called in the softirq context. This allows -- * avoiding nested remote coverage collection sections in the task context. -- * For example, USB/IP calls usb_hcd_giveback_urb() in the task context -- * within an existing remote coverage collection section. Thus, KCOV should -- * not attempt to start collecting coverage within the coverage collection -- * section in __usb_hcd_giveback_urb() in this case. -- * -- * 2. Disables interrupts for the duration of the coverage collection section. -- * This allows avoiding nested remote coverage collection sections in the -- * softirq context (a softirq might occur during the execution of a work in -- * the BH workqueue, which runs with in_serving_softirq() > 0). -- * For example, usb_giveback_urb_bh() runs in the BH workqueue with -- * interrupts enabled, so __usb_hcd_giveback_urb() might be interrupted in -- * the middle of its remote coverage collection section, and the interrupt -- * handler might invoke __usb_hcd_giveback_urb() again. -+ * work around for kcov's lack of nested remote coverage sections support in -+ * task context. Adding support for nested sections is tracked in: -+ * https://bugzilla.kernel.org/show_bug.cgi?id=210337 - */ - --static inline unsigned long kcov_remote_start_usb_softirq(u64 id) -+static inline void kcov_remote_start_usb_softirq(u64 id) - { -- unsigned long flags = 0; -- -- if (in_serving_softirq()) { -- local_irq_save(flags); -+ if (in_serving_softirq() && !in_hardirq()) - kcov_remote_start_usb(id); -- } -- -- return flags; - } - --static inline void kcov_remote_stop_softirq(unsigned long flags) -+static inline void kcov_remote_stop_softirq(void) - { -- if (in_serving_softirq()) { -+ if (in_serving_softirq() && !in_hardirq()) - kcov_remote_stop(); -- local_irq_restore(flags); -- } - } - - #ifdef CONFIG_64BIT -@@ -131,11 +105,8 @@ static inline u64 kcov_common_handle(voi - } - static inline void kcov_remote_start_common(u64 id) {} - static inline void kcov_remote_start_usb(u64 id) {} --static inline unsigned long kcov_remote_start_usb_softirq(u64 id) --{ -- return 0; --} --static inline void kcov_remote_stop_softirq(unsigned long flags) {} -+static inline void kcov_remote_start_usb_softirq(u64 id) {} -+static inline void kcov_remote_stop_softirq(void) {} - - #endif /* CONFIG_KCOV */ - #endif /* _LINUX_KCOV_H */ -diff -purNx .git BPI-Router-Linux-kernel/include/linux/key.h BPI-Router-Linux-kernel-6.16.12/include/linux/key.h ---- BPI-Router-Linux-kernel/include/linux/key.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/key.h 2025-10-22 13:53:56.751168003 -0400 -@@ -236,7 +236,7 @@ struct key { - #define KEY_FLAG_ROOT_CAN_INVAL 7 /* set if key can be invalidated by root without permission */ - #define KEY_FLAG_KEEP 8 /* set if key should not be removed */ - #define KEY_FLAG_UID_KEYRING 9 /* set if key is a user or user session keyring */ --#define KEY_FLAG_FINAL_PUT 10 /* set if final put has happened on key */ -+#define KEY_FLAG_USER_ALIVE 10 /* set if final put has not happened on key yet */ - - /* the key type and key description string - * - the desc is used to match a key against search criteria -diff -purNx .git BPI-Router-Linux-kernel/include/linux/kmemleak.h BPI-Router-Linux-kernel-6.16.12/include/linux/kmemleak.h ---- BPI-Router-Linux-kernel/include/linux/kmemleak.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/kmemleak.h 2025-10-22 13:53:56.751168003 -0400 -@@ -28,6 +28,7 @@ extern void kmemleak_update_trace(const - extern void kmemleak_not_leak(const void *ptr) __ref; - extern void kmemleak_transient_leak(const void *ptr) __ref; - extern void kmemleak_ignore(const void *ptr) __ref; -+extern void kmemleak_ignore_percpu(const void __percpu *ptr) __ref; - extern void kmemleak_scan_area(const void *ptr, size_t size, gfp_t gfp) __ref; - extern void kmemleak_no_scan(const void *ptr) __ref; - extern void kmemleak_alloc_phys(phys_addr_t phys, size_t size, -@@ -97,6 +98,9 @@ static inline void kmemleak_not_leak(con - static inline void kmemleak_transient_leak(const void *ptr) - { - } -+static inline void kmemleak_ignore_percpu(const void __percpu *ptr) -+{ -+} - static inline void kmemleak_ignore(const void *ptr) - { - } -diff -purNx .git BPI-Router-Linux-kernel/include/linux/libata.h BPI-Router-Linux-kernel-6.16.12/include/linux/libata.h ---- BPI-Router-Linux-kernel/include/linux/libata.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/libata.h 2025-10-22 13:53:56.751168003 -0400 -@@ -534,6 +534,7 @@ typedef void (*ata_postreset_fn_t)(struc - - extern struct device_attribute dev_attr_unload_heads; - #ifdef CONFIG_SATA_HOST -+extern struct device_attribute dev_attr_link_power_management_supported; - extern struct device_attribute dev_attr_link_power_management_policy; - extern struct device_attribute dev_attr_ncq_prio_supported; - extern struct device_attribute dev_attr_ncq_prio_enable; -@@ -1352,7 +1353,7 @@ int ata_acpi_stm(struct ata_port *ap, co - int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *stm); - unsigned int ata_acpi_gtm_xfermask(struct ata_device *dev, - const struct ata_acpi_gtm *gtm); --int ata_acpi_cbl_80wire(struct ata_port *ap, const struct ata_acpi_gtm *gtm); -+int ata_acpi_cbl_pata_type(struct ata_port *ap); - #else - static inline const struct ata_acpi_gtm *ata_acpi_init_gtm(struct ata_port *ap) - { -@@ -1377,10 +1378,9 @@ static inline unsigned int ata_acpi_gtm_ - return 0; - } - --static inline int ata_acpi_cbl_80wire(struct ata_port *ap, -- const struct ata_acpi_gtm *gtm) -+static inline int ata_acpi_cbl_pata_type(struct ata_port *ap) - { -- return 0; -+ return ATA_CBL_PATA40; - } - #endif - -diff -purNx .git BPI-Router-Linux-kernel/include/linux/memory-tiers.h BPI-Router-Linux-kernel-6.16.12/include/linux/memory-tiers.h ---- BPI-Router-Linux-kernel/include/linux/memory-tiers.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/memory-tiers.h 2025-10-22 13:53:56.751168003 -0400 -@@ -18,7 +18,7 @@ - * adistance value (slightly faster) than default DRAM adistance to be part of - * the same memory tier. - */ --#define MEMTIER_ADISTANCE_DRAM ((4 * MEMTIER_CHUNK_SIZE) + (MEMTIER_CHUNK_SIZE >> 1)) -+#define MEMTIER_ADISTANCE_DRAM ((4L * MEMTIER_CHUNK_SIZE) + (MEMTIER_CHUNK_SIZE >> 1)) - - struct memory_tier; - struct memory_dev_type { -diff -purNx .git BPI-Router-Linux-kernel/include/linux/mlx5/device.h BPI-Router-Linux-kernel-6.16.12/include/linux/mlx5/device.h ---- BPI-Router-Linux-kernel/include/linux/mlx5/device.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/mlx5/device.h 2025-10-22 13:53:56.751168003 -0400 -@@ -280,6 +280,7 @@ enum { - MLX5_MKEY_MASK_SMALL_FENCE = 1ull << 23, - MLX5_MKEY_MASK_RELAXED_ORDERING_WRITE = 1ull << 25, - MLX5_MKEY_MASK_FREE = 1ull << 29, -+ MLX5_MKEY_MASK_PAGE_SIZE_5 = 1ull << 42, - MLX5_MKEY_MASK_RELAXED_ORDERING_READ = 1ull << 47, - }; - -diff -purNx .git BPI-Router-Linux-kernel/include/linux/mlx5/driver.h BPI-Router-Linux-kernel-6.16.12/include/linux/mlx5/driver.h ---- BPI-Router-Linux-kernel/include/linux/mlx5/driver.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/mlx5/driver.h 2025-10-22 13:53:56.751168003 -0400 -@@ -662,6 +662,7 @@ struct mlx5e_resources { - bool tisn_valid; - } hw_objs; - struct net_device *uplink_netdev; -+ netdevice_tracker tracker; - struct mutex uplink_netdev_lock; - struct mlx5_crypto_dek_priv *dek_priv; - }; -diff -purNx .git BPI-Router-Linux-kernel/include/linux/mlx5/fs.h BPI-Router-Linux-kernel-6.16.12/include/linux/mlx5/fs.h ---- BPI-Router-Linux-kernel/include/linux/mlx5/fs.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/mlx5/fs.h 2025-10-22 13:53:56.751168003 -0400 -@@ -308,6 +308,8 @@ struct mlx5_fc *mlx5_fc_create(struct ml - void mlx5_fc_destroy(struct mlx5_core_dev *dev, struct mlx5_fc *counter); - struct mlx5_fc *mlx5_fc_local_create(u32 counter_id, u32 offset, u32 bulk_size); - void mlx5_fc_local_destroy(struct mlx5_fc *counter); -+void mlx5_fc_local_get(struct mlx5_fc *counter); -+void mlx5_fc_local_put(struct mlx5_fc *counter); - u64 mlx5_fc_query_lastuse(struct mlx5_fc *counter); - void mlx5_fc_query_cached(struct mlx5_fc *counter, - u64 *bytes, u64 *packets, u64 *lastuse); -diff -purNx .git BPI-Router-Linux-kernel/include/linux/mlx5/mlx5_ifc.h BPI-Router-Linux-kernel-6.16.12/include/linux/mlx5/mlx5_ifc.h ---- BPI-Router-Linux-kernel/include/linux/mlx5/mlx5_ifc.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/mlx5/mlx5_ifc.h 2025-10-22 13:53:56.751168003 -0400 -@@ -10460,8 +10460,16 @@ struct mlx5_ifc_pifr_reg_bits { - u8 port_filter_update_en[8][0x20]; - }; - -+enum { -+ MLX5_BUF_OWNERSHIP_UNKNOWN = 0x0, -+ MLX5_BUF_OWNERSHIP_FW_OWNED = 0x1, -+ MLX5_BUF_OWNERSHIP_SW_OWNED = 0x2, -+}; -+ - struct mlx5_ifc_pfcc_reg_bits { -- u8 reserved_at_0[0x8]; -+ u8 reserved_at_0[0x4]; -+ u8 buf_ownership[0x2]; -+ u8 reserved_at_6[0x2]; - u8 local_port[0x8]; - u8 reserved_at_10[0xb]; - u8 ppan_mask_n[0x1]; -@@ -10597,7 +10605,9 @@ struct mlx5_ifc_pcam_enhanced_features_b - u8 fec_200G_per_lane_in_pplm[0x1]; - u8 reserved_at_1e[0x2a]; - u8 fec_100G_per_lane_in_pplm[0x1]; -- u8 reserved_at_49[0x1f]; -+ u8 reserved_at_49[0xa]; -+ u8 buffer_ownership[0x1]; -+ u8 resereved_at_54[0x14]; - u8 fec_50G_per_lane_in_pplm[0x1]; - u8 reserved_at_69[0x4]; - u8 rx_icrc_encapsulated_counter[0x1]; -diff -purNx .git BPI-Router-Linux-kernel/include/linux/mmap_lock.h BPI-Router-Linux-kernel-6.16.12/include/linux/mmap_lock.h ---- BPI-Router-Linux-kernel/include/linux/mmap_lock.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/mmap_lock.h 2025-10-22 13:53:56.751168003 -0400 -@@ -12,6 +12,7 @@ extern int rcuwait_wake_up(struct rcuwai - #include - #include - #include -+#include - - #define MMAP_LOCK_INITIALIZER(name) \ - .mmap_lock = __RWSEM_INITIALIZER((name).mmap_lock), -@@ -154,6 +155,10 @@ static inline void vma_refcount_put(stru - * reused and attached to a different mm before we lock it. - * Returns the vma on success, NULL on failure to lock and EAGAIN if vma got - * detached. -+ * -+ * WARNING! The vma passed to this function cannot be used if the function -+ * fails to lock it because in certain cases RCU lock is dropped and then -+ * reacquired. Once RCU lock is dropped the vma can be concurently freed. - */ - static inline struct vm_area_struct *vma_start_read(struct mm_struct *mm, - struct vm_area_struct *vma) -@@ -183,6 +188,31 @@ static inline struct vm_area_struct *vma - } - - rwsem_acquire_read(&vma->vmlock_dep_map, 0, 1, _RET_IP_); -+ -+ /* -+ * If vma got attached to another mm from under us, that mm is not -+ * stable and can be freed in the narrow window after vma->vm_refcnt -+ * is dropped and before rcuwait_wake_up(mm) is called. Grab it before -+ * releasing vma->vm_refcnt. -+ */ -+ if (unlikely(vma->vm_mm != mm)) { -+ /* Use a copy of vm_mm in case vma is freed after we drop vm_refcnt */ -+ struct mm_struct *other_mm = vma->vm_mm; -+ -+ /* -+ * __mmdrop() is a heavy operation and we don't need RCU -+ * protection here. Release RCU lock during these operations. -+ * We reinstate the RCU read lock as the caller expects it to -+ * be held when this function returns even on error. -+ */ -+ rcu_read_unlock(); -+ mmgrab(other_mm); -+ vma_refcount_put(vma); -+ mmdrop(other_mm); -+ rcu_read_lock(); -+ return NULL; -+ } -+ - /* - * Overflow of vm_lock_seq/mm_lock_seq might produce false locked result. - * False unlocked result is impossible because we modify and check -diff -purNx .git BPI-Router-Linux-kernel/include/linux/mm.h BPI-Router-Linux-kernel-6.16.12/include/linux/mm.h ---- BPI-Router-Linux-kernel/include/linux/mm.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/mm.h 2025-10-22 13:53:56.751168003 -0400 -@@ -2568,6 +2568,11 @@ static inline unsigned long get_mm_count - return percpu_counter_read_positive(&mm->rss_stat[member]); - } - -+static inline unsigned long get_mm_counter_sum(struct mm_struct *mm, int member) -+{ -+ return percpu_counter_sum_positive(&mm->rss_stat[member]); -+} -+ - void mm_trace_rss_stat(struct mm_struct *mm, int member); - - static inline void add_mm_counter(struct mm_struct *mm, int member, long value) -diff -purNx .git BPI-Router-Linux-kernel/include/linux/module.h BPI-Router-Linux-kernel-6.16.12/include/linux/module.h ---- BPI-Router-Linux-kernel/include/linux/module.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/module.h 2025-10-22 13:53:56.751168003 -0400 -@@ -586,11 +586,6 @@ struct module { - atomic_t refcnt; - #endif - --#ifdef CONFIG_MITIGATION_ITS -- int its_num_pages; -- void **its_page_array; --#endif -- - #ifdef CONFIG_CONSTRUCTORS - /* Constructor functions. */ - ctor_fn_t *ctors; -diff -purNx .git BPI-Router-Linux-kernel/include/linux/moduleparam.h BPI-Router-Linux-kernel-6.16.12/include/linux/moduleparam.h ---- BPI-Router-Linux-kernel/include/linux/moduleparam.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/moduleparam.h 2025-10-22 13:53:56.751168003 -0400 -@@ -282,10 +282,9 @@ struct kparam_array - #define __moduleparam_const const - #endif - --/* This is the fundamental function for registering boot/module -- parameters. */ -+/* This is the fundamental function for registering boot/module parameters. */ - #define __module_param_call(prefix, name, ops, arg, perm, level, flags) \ -- /* Default value instead of permissions? */ \ -+ static_assert(sizeof(""prefix) - 1 <= MAX_PARAM_PREFIX_LEN); \ - static const char __param_str_##name[] = prefix #name; \ - static struct kernel_param __moduleparam_const __param_##name \ - __used __section("__param") \ -diff -purNx .git BPI-Router-Linux-kernel/include/linux/mount.h BPI-Router-Linux-kernel-6.16.12/include/linux/mount.h ---- BPI-Router-Linux-kernel/include/linux/mount.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/mount.h 2025-10-22 13:53:56.751168003 -0400 -@@ -116,10 +116,8 @@ extern int may_umount_tree(struct vfsmou - extern int may_umount(struct vfsmount *); - int do_mount(const char *, const char __user *, - const char *, unsigned long, void *); --extern struct vfsmount *collect_mounts(const struct path *); --extern void drop_collected_mounts(struct vfsmount *); --extern int iterate_mounts(int (*)(struct vfsmount *, void *), void *, -- struct vfsmount *); -+extern struct path *collect_paths(const struct path *, struct path *, unsigned); -+extern void drop_collected_paths(struct path *, struct path *); - extern void kern_unmount_array(struct vfsmount *mnt[], unsigned int num); - - extern int cifs_root_data(char **dev, char **opts); -diff -purNx .git BPI-Router-Linux-kernel/include/linux/mtd/nand-qpic-common.h BPI-Router-Linux-kernel-6.16.12/include/linux/mtd/nand-qpic-common.h ---- BPI-Router-Linux-kernel/include/linux/mtd/nand-qpic-common.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/mtd/nand-qpic-common.h 2025-10-22 13:53:56.751168003 -0400 -@@ -237,6 +237,9 @@ - * @last_data_desc - last DMA desc in data channel (tx/rx). - * @last_cmd_desc - last DMA desc in command channel. - * @txn_done - completion for NAND transfer. -+ * @bam_ce_nitems - the number of elements in the @bam_ce array -+ * @cmd_sgl_nitems - the number of elements in the @cmd_sgl array -+ * @data_sgl_nitems - the number of elements in the @data_sgl array - * @bam_ce_pos - the index in bam_ce which is available for next sgl - * @bam_ce_start - the index in bam_ce which marks the start position ce - * for current sgl. It will be used for size calculation -@@ -255,6 +258,11 @@ struct bam_transaction { - struct dma_async_tx_descriptor *last_data_desc; - struct dma_async_tx_descriptor *last_cmd_desc; - struct completion txn_done; -+ -+ unsigned int bam_ce_nitems; -+ unsigned int cmd_sgl_nitems; -+ unsigned int data_sgl_nitems; -+ - struct_group(bam_positions, - u32 bam_ce_pos; - u32 bam_ce_start; -diff -purNx .git BPI-Router-Linux-kernel/include/linux/mtd/partitions.h BPI-Router-Linux-kernel-6.16.12/include/linux/mtd/partitions.h ---- BPI-Router-Linux-kernel/include/linux/mtd/partitions.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/mtd/partitions.h 2025-10-22 13:53:56.751168003 -0400 -@@ -108,7 +108,7 @@ extern void deregister_mtd_parser(struct - deregister_mtd_parser) - - int mtd_add_partition(struct mtd_info *master, const char *name, -- long long offset, long long length, struct mtd_info **part); -+ long long offset, long long length); - int mtd_del_partition(struct mtd_info *master, int partno); - uint64_t mtd_get_device_size(const struct mtd_info *mtd); - -diff -purNx .git BPI-Router-Linux-kernel/include/linux/mtd/spinand.h BPI-Router-Linux-kernel-6.16.12/include/linux/mtd/spinand.h ---- BPI-Router-Linux-kernel/include/linux/mtd/spinand.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/mtd/spinand.h 2025-10-22 13:53:56.751168003 -0400 -@@ -113,11 +113,12 @@ - SPI_MEM_DTR_OP_DATA_IN(len, buf, 2), \ - SPI_MEM_OP_MAX_FREQ(freq)) - --#define SPINAND_PAGE_READ_FROM_CACHE_1S_2S_2S_OP(addr, ndummy, buf, len) \ -+#define SPINAND_PAGE_READ_FROM_CACHE_1S_2S_2S_OP(addr, ndummy, buf, len, ...) \ - SPI_MEM_OP(SPI_MEM_OP_CMD(0xbb, 1), \ - SPI_MEM_OP_ADDR(2, addr, 2), \ - SPI_MEM_OP_DUMMY(ndummy, 2), \ -- SPI_MEM_OP_DATA_IN(len, buf, 2)) -+ SPI_MEM_OP_DATA_IN(len, buf, 2), \ -+ SPI_MEM_OP_MAX_FREQ(__VA_ARGS__ + 0)) - - #define SPINAND_PAGE_READ_FROM_CACHE_3A_1S_2S_2S_OP(addr, ndummy, buf, len) \ - SPI_MEM_OP(SPI_MEM_OP_CMD(0xbb, 1), \ -@@ -151,11 +152,12 @@ - SPI_MEM_DTR_OP_DATA_IN(len, buf, 4), \ - SPI_MEM_OP_MAX_FREQ(freq)) - --#define SPINAND_PAGE_READ_FROM_CACHE_1S_4S_4S_OP(addr, ndummy, buf, len) \ -+#define SPINAND_PAGE_READ_FROM_CACHE_1S_4S_4S_OP(addr, ndummy, buf, len, ...) \ - SPI_MEM_OP(SPI_MEM_OP_CMD(0xeb, 1), \ - SPI_MEM_OP_ADDR(2, addr, 4), \ - SPI_MEM_OP_DUMMY(ndummy, 4), \ -- SPI_MEM_OP_DATA_IN(len, buf, 4)) -+ SPI_MEM_OP_DATA_IN(len, buf, 4), \ -+ SPI_MEM_OP_MAX_FREQ(__VA_ARGS__ + 0)) - - #define SPINAND_PAGE_READ_FROM_CACHE_3A_1S_4S_4S_OP(addr, ndummy, buf, len) \ - SPI_MEM_OP(SPI_MEM_OP_CMD(0xeb, 1), \ -@@ -482,6 +484,7 @@ struct spinand_user_otp { - * @op_variants.update_cache: variants of the update-cache operation - * @select_target: function used to select a target/die. Required only for - * multi-die chips -+ * @configure_chip: Align the chip configuration with the core settings - * @set_cont_read: enable/disable continuous cached reads - * @fact_otp: SPI NAND factory OTP info. - * @user_otp: SPI NAND user OTP info. -@@ -505,6 +508,7 @@ struct spinand_info { - } op_variants; - int (*select_target)(struct spinand_device *spinand, - unsigned int target); -+ int (*configure_chip)(struct spinand_device *spinand); - int (*set_cont_read)(struct spinand_device *spinand, - bool enable); - struct spinand_fact_otp fact_otp; -@@ -537,6 +541,9 @@ struct spinand_info { - #define SPINAND_SELECT_TARGET(__func) \ - .select_target = __func - -+#define SPINAND_CONFIGURE_CHIP(__configure_chip) \ -+ .configure_chip = __configure_chip -+ - #define SPINAND_CONT_READ(__set_cont_read) \ - .set_cont_read = __set_cont_read - -@@ -605,6 +612,7 @@ struct spinand_dirmap { - * passed in spi_mem_op be DMA-able, so we can't based the bufs on - * the stack - * @manufacturer: SPI NAND manufacturer information -+ * @configure_chip: Align the chip configuration with the core settings - * @cont_read_possible: Field filled by the core once the whole system - * configuration is known to tell whether continuous reads are - * suitable to use or not in general with this chip/configuration. -@@ -645,6 +653,7 @@ struct spinand_device { - const struct spinand_manufacturer *manufacturer; - void *priv; - -+ int (*configure_chip)(struct spinand_device *spinand); - bool cont_read_possible; - int (*set_cont_read)(struct spinand_device *spinand, - bool enable); -@@ -721,6 +730,7 @@ int spinand_match_and_init(struct spinan - enum spinand_readid_method rdid_method); - - int spinand_upd_cfg(struct spinand_device *spinand, u8 mask, u8 val); -+int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val); - int spinand_write_reg_op(struct spinand_device *spinand, u8 reg, u8 val); - int spinand_select_target(struct spinand_device *spinand, unsigned int target); - -diff -purNx .git BPI-Router-Linux-kernel/include/linux/netfs.h BPI-Router-Linux-kernel-6.16.12/include/linux/netfs.h ---- BPI-Router-Linux-kernel/include/linux/netfs.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/netfs.h 2025-10-22 13:53:56.751168003 -0400 -@@ -150,6 +150,7 @@ struct netfs_io_stream { - bool active; /* T if stream is active */ - bool need_retry; /* T if this stream needs retrying */ - bool failed; /* T if this stream failed */ -+ bool transferred_valid; /* T is ->transferred is valid */ - }; - - /* -@@ -265,21 +266,20 @@ struct netfs_io_request { - bool direct_bv_unpin; /* T if direct_bv[] must be unpinned */ - refcount_t ref; - unsigned long flags; --#define NETFS_RREQ_OFFLOAD_COLLECTION 0 /* Offload collection to workqueue */ --#define NETFS_RREQ_NO_UNLOCK_FOLIO 2 /* Don't unlock no_unlock_folio on completion */ --#define NETFS_RREQ_FAILED 4 /* The request failed */ --#define NETFS_RREQ_IN_PROGRESS 5 /* Unlocked when the request completes (has ref) */ --#define NETFS_RREQ_FOLIO_COPY_TO_CACHE 6 /* Copy current folio to cache from read */ --#define NETFS_RREQ_UPLOAD_TO_SERVER 8 /* Need to write to the server */ --#define NETFS_RREQ_PAUSE 11 /* Pause subrequest generation */ -+#define NETFS_RREQ_IN_PROGRESS 0 /* Unlocked when the request completes (has ref) */ -+#define NETFS_RREQ_ALL_QUEUED 1 /* All subreqs are now queued */ -+#define NETFS_RREQ_PAUSE 2 /* Pause subrequest generation */ -+#define NETFS_RREQ_FAILED 3 /* The request failed */ -+#define NETFS_RREQ_RETRYING 4 /* Set if we're in the retry path */ -+#define NETFS_RREQ_SHORT_TRANSFER 5 /* Set if we have a short transfer */ -+#define NETFS_RREQ_OFFLOAD_COLLECTION 8 /* Offload collection to workqueue */ -+#define NETFS_RREQ_NO_UNLOCK_FOLIO 9 /* Don't unlock no_unlock_folio on completion */ -+#define NETFS_RREQ_FOLIO_COPY_TO_CACHE 10 /* Copy current folio to cache from read */ -+#define NETFS_RREQ_UPLOAD_TO_SERVER 11 /* Need to write to the server */ - #define NETFS_RREQ_USE_IO_ITER 12 /* Use ->io_iter rather than ->i_pages */ --#define NETFS_RREQ_ALL_QUEUED 13 /* All subreqs are now queued */ --#define NETFS_RREQ_RETRYING 14 /* Set if we're in the retry path */ --#define NETFS_RREQ_SHORT_TRANSFER 15 /* Set if we have a short transfer */ - #define NETFS_RREQ_USE_PGPRIV2 31 /* [DEPRECATED] Use PG_private_2 to mark - * write to cache on read */ - const struct netfs_request_ops *netfs_ops; -- void (*cleanup)(struct netfs_io_request *req); - }; - - /* -diff -purNx .git BPI-Router-Linux-kernel/include/linux/nfs_page.h BPI-Router-Linux-kernel-6.16.12/include/linux/nfs_page.h ---- BPI-Router-Linux-kernel/include/linux/nfs_page.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/nfs_page.h 2025-10-22 13:53:56.751168003 -0400 -@@ -160,6 +160,7 @@ extern void nfs_join_page_group(struct n - extern int nfs_page_group_lock(struct nfs_page *); - extern void nfs_page_group_unlock(struct nfs_page *); - extern bool nfs_page_group_sync_on_bit(struct nfs_page *, unsigned int); -+extern bool nfs_page_group_sync_on_bit_locked(struct nfs_page *, unsigned int); - extern int nfs_page_set_headlock(struct nfs_page *req); - extern void nfs_page_clear_headlock(struct nfs_page *req); - extern bool nfs_async_iocounter_wait(struct rpc_task *, struct nfs_lock_context *); -diff -purNx .git BPI-Router-Linux-kernel/include/linux/packing.h BPI-Router-Linux-kernel-6.16.12/include/linux/packing.h ---- BPI-Router-Linux-kernel/include/linux/packing.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/packing.h 2025-10-22 13:53:56.751168003 -0400 -@@ -5,8 +5,12 @@ - #ifndef _LINUX_PACKING_H - #define _LINUX_PACKING_H - --#include -+#include - #include -+#include -+#include -+#include -+#include - - #define GEN_PACKED_FIELD_STRUCT(__type) \ - struct packed_field_ ## __type { \ -diff -purNx .git BPI-Router-Linux-kernel/include/linux/padata.h BPI-Router-Linux-kernel-6.16.12/include/linux/padata.h ---- BPI-Router-Linux-kernel/include/linux/padata.h 2025-10-22 13:53:23.559327478 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/padata.h 2025-10-22 13:53:56.751168003 -0400 -@@ -90,8 +90,6 @@ struct padata_cpumask { - * @processed: Number of already processed objects. - * @cpu: Next CPU to be processed. - * @cpumask: The cpumasks in use for parallel and serial workers. -- * @reorder_work: work struct for reordering. -- * @lock: Reorder lock. - */ - struct parallel_data { - struct padata_shell *ps; -@@ -102,8 +100,6 @@ struct parallel_data { - unsigned int processed; - int cpu; - struct padata_cpumask cpumask; -- struct work_struct reorder_work; -- spinlock_t ____cacheline_aligned lock; - }; - - /** -diff -purNx .git BPI-Router-Linux-kernel/include/linux/pci.h BPI-Router-Linux-kernel-6.16.12/include/linux/pci.h ---- BPI-Router-Linux-kernel/include/linux/pci.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/pci.h 2025-10-22 13:53:56.751168003 -0400 -@@ -328,6 +328,11 @@ struct rcec_ea; - * determined (e.g., for Root Complex Integrated - * Endpoints without the relevant Capability - * Registers). -+ * @is_hotplug_bridge: Hotplug bridge of any kind (e.g. PCIe Hot-Plug Capable, -+ * Conventional PCI Hot-Plug, ACPI slot). -+ * Such bridges are allocated additional MMIO and bus -+ * number resources to allow for hierarchy expansion. -+ * @is_pciehp: PCIe Hot-Plug Capable bridge. - */ - struct pci_dev { - struct list_head bus_list; /* Node in per-bus list */ -@@ -451,6 +456,7 @@ struct pci_dev { - unsigned int is_physfn:1; - unsigned int is_virtfn:1; - unsigned int is_hotplug_bridge:1; -+ unsigned int is_pciehp:1; - unsigned int shpc_managed:1; /* SHPC owned by shpchp */ - unsigned int is_thunderbolt:1; /* Thunderbolt controller */ - /* -diff -purNx .git BPI-Router-Linux-kernel/include/linux/perf_event.h BPI-Router-Linux-kernel-6.16.12/include/linux/perf_event.h ---- BPI-Router-Linux-kernel/include/linux/perf_event.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/perf_event.h 2025-10-22 13:53:56.751168003 -0400 -@@ -635,8 +635,46 @@ struct perf_addr_filter_range { - unsigned long size; - }; - --/** -- * enum perf_event_state - the states of an event: -+/* -+ * The normal states are: -+ * -+ * ACTIVE --. -+ * ^ | -+ * | | -+ * sched_{in,out}() | -+ * | | -+ * v | -+ * ,---> INACTIVE --+ <-. -+ * | | | -+ * | {dis,en}able() -+ * sched_in() | | -+ * | OFF <--' --+ -+ * | | -+ * `---> ERROR ------' -+ * -+ * That is: -+ * -+ * sched_in: INACTIVE -> {ACTIVE,ERROR} -+ * sched_out: ACTIVE -> INACTIVE -+ * disable: {ACTIVE,INACTIVE} -> OFF -+ * enable: {OFF,ERROR} -> INACTIVE -+ * -+ * Where {OFF,ERROR} are disabled states. -+ * -+ * Then we have the {EXIT,REVOKED,DEAD} states which are various shades of -+ * defunct events: -+ * -+ * - EXIT means task that the even was assigned to died, but child events -+ * still live, and further children can still be created. But the event -+ * itself will never be active again. It can only transition to -+ * {REVOKED,DEAD}; -+ * -+ * - REVOKED means the PMU the event was associated with is gone; all -+ * functionality is stopped but the event is still alive. Can only -+ * transition to DEAD; -+ * -+ * - DEAD event really is DYING tearing down state and freeing bits. -+ * - */ - enum perf_event_state { - PERF_EVENT_STATE_DEAD = -5, -diff -purNx .git BPI-Router-Linux-kernel/include/linux/pgalloc.h BPI-Router-Linux-kernel-6.16.12/include/linux/pgalloc.h ---- BPI-Router-Linux-kernel/include/linux/pgalloc.h 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/pgalloc.h 2025-10-22 13:53:56.751168003 -0400 -@@ -0,0 +1,29 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+#ifndef _LINUX_PGALLOC_H -+#define _LINUX_PGALLOC_H -+ -+#include -+#include -+ -+/* -+ * {pgd,p4d}_populate_kernel() are defined as macros to allow -+ * compile-time optimization based on the configured page table levels. -+ * Without this, linking may fail because callers (e.g., KASAN) may rely -+ * on calls to these functions being optimized away when passing symbols -+ * that exist only for certain page table levels. -+ */ -+#define pgd_populate_kernel(addr, pgd, p4d) \ -+ do { \ -+ pgd_populate(&init_mm, pgd, p4d); \ -+ if (ARCH_PAGE_TABLE_SYNC_MASK & PGTBL_PGD_MODIFIED) \ -+ arch_sync_kernel_mappings(addr, addr); \ -+ } while (0) -+ -+#define p4d_populate_kernel(addr, p4d, pud) \ -+ do { \ -+ p4d_populate(&init_mm, p4d, pud); \ -+ if (ARCH_PAGE_TABLE_SYNC_MASK & PGTBL_P4D_MODIFIED) \ -+ arch_sync_kernel_mappings(addr, addr); \ -+ } while (0) -+ -+#endif /* _LINUX_PGALLOC_H */ -diff -purNx .git BPI-Router-Linux-kernel/include/linux/pgtable.h BPI-Router-Linux-kernel-6.16.12/include/linux/pgtable.h ---- BPI-Router-Linux-kernel/include/linux/pgtable.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/pgtable.h 2025-10-22 13:53:56.755167984 -0400 -@@ -1695,6 +1695,22 @@ static inline int pmd_protnone(pmd_t pmd - } - #endif /* CONFIG_NUMA_BALANCING */ - -+/* -+ * Architectures can set this mask to a combination of PGTBL_P?D_MODIFIED values -+ * and let generic vmalloc, ioremap and page table update code know when -+ * arch_sync_kernel_mappings() needs to be called. -+ */ -+#ifndef ARCH_PAGE_TABLE_SYNC_MASK -+#define ARCH_PAGE_TABLE_SYNC_MASK 0 -+#endif -+ -+/* -+ * There is no default implementation for arch_sync_kernel_mappings(). It is -+ * relied upon the compiler to optimize calls out if ARCH_PAGE_TABLE_SYNC_MASK -+ * is 0. -+ */ -+void arch_sync_kernel_mappings(unsigned long start, unsigned long end); -+ - #endif /* CONFIG_MMU */ - - #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP -@@ -1815,10 +1831,11 @@ static inline bool arch_has_pfn_modify_c - /* - * Page Table Modification bits for pgtbl_mod_mask. - * -- * These are used by the p?d_alloc_track*() set of functions an in the generic -- * vmalloc/ioremap code to track at which page-table levels entries have been -- * modified. Based on that the code can better decide when vmalloc and ioremap -- * mapping changes need to be synchronized to other page-tables in the system. -+ * These are used by the p?d_alloc_track*() and p*d_populate_kernel() -+ * functions in the generic vmalloc, ioremap and page table update code -+ * to track at which page-table levels entries have been modified. -+ * Based on that the code can better decide when page table changes need -+ * to be synchronized to other page-tables in the system. - */ - #define __PGTBL_PGD_MODIFIED 0 - #define __PGTBL_P4D_MODIFIED 1 -diff -purNx .git BPI-Router-Linux-kernel/include/linux/phy/phy.h BPI-Router-Linux-kernel-6.16.12/include/linux/phy/phy.h ---- BPI-Router-Linux-kernel/include/linux/phy/phy.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/phy/phy.h 2025-10-22 13:53:56.755167984 -0400 -@@ -154,6 +154,7 @@ struct phy_attrs { - * @id: id of the phy device - * @ops: function pointers for performing phy operations - * @mutex: mutex to protect phy_ops -+ * @lockdep_key: lockdep information for this mutex - * @init_count: used to protect when the PHY is used by multiple consumers - * @power_count: used to protect when the PHY is used by multiple consumers - * @attrs: used to specify PHY specific attributes -@@ -165,6 +166,7 @@ struct phy { - int id; - const struct phy_ops *ops; - struct mutex mutex; -+ struct lock_class_key lockdep_key; - int init_count; - int power_count; - struct phy_attrs attrs; -diff -purNx .git BPI-Router-Linux-kernel/include/linux/platform_data/x86/amd-fch.h BPI-Router-Linux-kernel-6.16.12/include/linux/platform_data/x86/amd-fch.h ---- BPI-Router-Linux-kernel/include/linux/platform_data/x86/amd-fch.h 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/platform_data/x86/amd-fch.h 2025-10-22 13:53:56.755167984 -0400 -@@ -0,0 +1,13 @@ -+/* SPDX-License-Identifier: GPL-2.0 */ -+#ifndef _ASM_X86_AMD_FCH_H_ -+#define _ASM_X86_AMD_FCH_H_ -+ -+#define FCH_PM_BASE 0xFED80300 -+ -+/* Register offsets from PM base: */ -+#define FCH_PM_DECODEEN 0x00 -+#define FCH_PM_DECODEEN_SMBUS0SEL GENMASK(20, 19) -+#define FCH_PM_SCRATCH 0x80 -+#define FCH_PM_S5_RESET_STATUS 0xC0 -+ -+#endif /* _ASM_X86_AMD_FCH_H_ */ -diff -purNx .git BPI-Router-Linux-kernel/include/linux/platform_data/x86/int3472.h BPI-Router-Linux-kernel-6.16.12/include/linux/platform_data/x86/int3472.h ---- BPI-Router-Linux-kernel/include/linux/platform_data/x86/int3472.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/platform_data/x86/int3472.h 2025-10-22 13:53:56.755167984 -0400 -@@ -27,6 +27,7 @@ - #define INT3472_GPIO_TYPE_CLK_ENABLE 0x0c - #define INT3472_GPIO_TYPE_PRIVACY_LED 0x0d - #define INT3472_GPIO_TYPE_HANDSHAKE 0x12 -+#define INT3472_GPIO_TYPE_HOTPLUG_DETECT 0x13 - - #define INT3472_PDEV_MAX_NAME_LEN 23 - #define INT3472_MAX_SENSOR_GPIOS 3 -diff -purNx .git BPI-Router-Linux-kernel/include/linux/power_supply.h BPI-Router-Linux-kernel-6.16.12/include/linux/power_supply.h ---- BPI-Router-Linux-kernel/include/linux/power_supply.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/power_supply.h 2025-10-22 13:53:56.755167984 -0400 -@@ -888,15 +888,23 @@ static inline int power_supply_is_system - extern int power_supply_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val); -+int power_supply_get_property_direct(struct power_supply *psy, enum power_supply_property psp, -+ union power_supply_propval *val); - #if IS_ENABLED(CONFIG_POWER_SUPPLY) - extern int power_supply_set_property(struct power_supply *psy, - enum power_supply_property psp, - const union power_supply_propval *val); -+int power_supply_set_property_direct(struct power_supply *psy, enum power_supply_property psp, -+ const union power_supply_propval *val); - #else - static inline int power_supply_set_property(struct power_supply *psy, - enum power_supply_property psp, - const union power_supply_propval *val) - { return 0; } -+static inline int power_supply_set_property_direct(struct power_supply *psy, -+ enum power_supply_property psp, -+ const union power_supply_propval *val) -+{ return 0; } - #endif - extern void power_supply_external_power_changed(struct power_supply *psy); - -diff -purNx .git BPI-Router-Linux-kernel/include/linux/pps_kernel.h BPI-Router-Linux-kernel-6.16.12/include/linux/pps_kernel.h ---- BPI-Router-Linux-kernel/include/linux/pps_kernel.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/pps_kernel.h 2025-10-22 13:53:56.755167984 -0400 -@@ -52,6 +52,7 @@ struct pps_device { - int current_mode; /* PPS mode at event time */ - - unsigned int last_ev; /* last PPS event id */ -+ unsigned int last_fetched_ev; /* last fetched PPS event id */ - wait_queue_head_t queue; /* PPS event queue */ - - unsigned int id; /* PPS source unique ID */ -diff -purNx .git BPI-Router-Linux-kernel/include/linux/proc_fs.h BPI-Router-Linux-kernel-6.16.12/include/linux/proc_fs.h ---- BPI-Router-Linux-kernel/include/linux/proc_fs.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/proc_fs.h 2025-10-22 13:53:56.755167984 -0400 -@@ -27,6 +27,7 @@ enum { - - PROC_ENTRY_proc_read_iter = 1U << 1, - PROC_ENTRY_proc_compat_ioctl = 1U << 2, -+ PROC_ENTRY_proc_lseek = 1U << 3, - }; - - struct proc_ops { -diff -purNx .git BPI-Router-Linux-kernel/include/linux/psi_types.h BPI-Router-Linux-kernel-6.16.12/include/linux/psi_types.h ---- BPI-Router-Linux-kernel/include/linux/psi_types.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/psi_types.h 2025-10-22 13:53:56.755167984 -0400 -@@ -84,11 +84,9 @@ enum psi_aggregators { - struct psi_group_cpu { - /* 1st cacheline updated by the scheduler */ - -- /* Aggregator needs to know of concurrent changes */ -- seqcount_t seq ____cacheline_aligned_in_smp; -- - /* States of the tasks belonging to this group */ -- unsigned int tasks[NR_PSI_TASK_COUNTS]; -+ unsigned int tasks[NR_PSI_TASK_COUNTS] -+ ____cacheline_aligned_in_smp; - - /* Aggregate pressure state derived from the tasks */ - u32 state_mask; -diff -purNx .git BPI-Router-Linux-kernel/include/linux/psp-sev.h BPI-Router-Linux-kernel-6.16.12/include/linux/psp-sev.h ---- BPI-Router-Linux-kernel/include/linux/psp-sev.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/psp-sev.h 2025-10-22 13:53:56.755167984 -0400 -@@ -594,6 +594,7 @@ struct sev_data_snp_addr { - * @imi_en: launch flow is launching an IMI (Incoming Migration Image) for the - * purpose of guest-assisted migration. - * @rsvd: reserved -+ * @desired_tsc_khz: hypervisor desired mean TSC freq in kHz of the guest - * @gosvw: guest OS-visible workarounds, as defined by hypervisor - */ - struct sev_data_snp_launch_start { -@@ -603,6 +604,7 @@ struct sev_data_snp_launch_start { - u32 ma_en:1; /* In */ - u32 imi_en:1; /* In */ - u32 rsvd:30; -+ u32 desired_tsc_khz; /* In */ - u8 gosvw[16]; /* In */ - } __packed; - -diff -purNx .git BPI-Router-Linux-kernel/include/linux/resctrl.h BPI-Router-Linux-kernel-6.16.12/include/linux/resctrl.h ---- BPI-Router-Linux-kernel/include/linux/resctrl.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/resctrl.h 2025-10-22 13:53:56.755167984 -0400 -@@ -159,7 +159,7 @@ struct rdt_ctrl_domain { - /** - * struct rdt_mon_domain - group of CPUs sharing a resctrl monitor resource - * @hdr: common header for different domain types -- * @ci: cache info for this domain -+ * @ci_id: cache info id for this domain - * @rmid_busy_llc: bitmap of which limbo RMIDs are above threshold - * @mbm_total: saved state for MBM total bandwidth - * @mbm_local: saved state for MBM local bandwidth -@@ -170,7 +170,7 @@ struct rdt_ctrl_domain { - */ - struct rdt_mon_domain { - struct rdt_domain_hdr hdr; -- struct cacheinfo *ci; -+ unsigned int ci_id; - unsigned long *rmid_busy_llc; - struct mbm_state *mbm_total; - struct mbm_state *mbm_local; -diff -purNx .git BPI-Router-Linux-kernel/include/linux/ring_buffer.h BPI-Router-Linux-kernel-6.16.12/include/linux/ring_buffer.h ---- BPI-Router-Linux-kernel/include/linux/ring_buffer.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/ring_buffer.h 2025-10-22 13:53:56.755167984 -0400 -@@ -152,9 +152,7 @@ ring_buffer_consume(struct trace_buffer - unsigned long *lost_events); - - struct ring_buffer_iter * --ring_buffer_read_prepare(struct trace_buffer *buffer, int cpu, gfp_t flags); --void ring_buffer_read_prepare_sync(void); --void ring_buffer_read_start(struct ring_buffer_iter *iter); -+ring_buffer_read_start(struct trace_buffer *buffer, int cpu, gfp_t flags); - void ring_buffer_read_finish(struct ring_buffer_iter *iter); - - struct ring_buffer_event * -diff -purNx .git BPI-Router-Linux-kernel/include/linux/sbitmap.h BPI-Router-Linux-kernel-6.16.12/include/linux/sbitmap.h ---- BPI-Router-Linux-kernel/include/linux/sbitmap.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/sbitmap.h 2025-10-22 13:53:56.755167984 -0400 -@@ -213,12 +213,12 @@ int sbitmap_get(struct sbitmap *sb); - * sbitmap_get_shallow() - Try to allocate a free bit from a &struct sbitmap, - * limiting the depth used from each word. - * @sb: Bitmap to allocate from. -- * @shallow_depth: The maximum number of bits to allocate from a single word. -+ * @shallow_depth: The maximum number of bits to allocate from the bitmap. - * - * This rather specific operation allows for having multiple users with - * different allocation limits. E.g., there can be a high-priority class that - * uses sbitmap_get() and a low-priority class that uses sbitmap_get_shallow() -- * with a @shallow_depth of (1 << (@sb->shift - 1)). Then, the low-priority -+ * with a @shallow_depth of (sb->depth >> 1). Then, the low-priority - * class can only allocate half of the total bits in the bitmap, preventing it - * from starving out the high-priority class. - * -@@ -478,7 +478,7 @@ unsigned long __sbitmap_queue_get_batch( - * sbitmap_queue, limiting the depth used from each word, with preemption - * already disabled. - * @sbq: Bitmap queue to allocate from. -- * @shallow_depth: The maximum number of bits to allocate from a single word. -+ * @shallow_depth: The maximum number of bits to allocate from the queue. - * See sbitmap_get_shallow(). - * - * If you call this, make sure to call sbitmap_queue_min_shallow_depth() after -diff -purNx .git BPI-Router-Linux-kernel/include/linux/scatterlist.h BPI-Router-Linux-kernel-6.16.12/include/linux/scatterlist.h ---- BPI-Router-Linux-kernel/include/linux/scatterlist.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/scatterlist.h 2025-10-22 13:53:56.755167984 -0400 -@@ -99,7 +99,7 @@ static inline bool sg_is_last(struct sca - * @sg: The current sg entry - * - * Description: -- * Usually the next entry will be @sg@ + 1, but if this sg element is part -+ * Usually the next entry will be @sg + 1, but if this sg element is part - * of a chained scatterlist, it could jump to the start of a new - * scatterlist array. - * -@@ -254,7 +254,7 @@ static inline void __sg_chain(struct sca - * @sgl: Second scatterlist - * - * Description: -- * Links @prv@ and @sgl@ together, to form a longer scatterlist. -+ * Links @prv and @sgl together, to form a longer scatterlist. - * - **/ - static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents, -diff -purNx .git BPI-Router-Linux-kernel/include/linux/sched/task_stack.h BPI-Router-Linux-kernel-6.16.12/include/linux/sched/task_stack.h ---- BPI-Router-Linux-kernel/include/linux/sched/task_stack.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/sched/task_stack.h 2025-10-22 13:53:56.755167984 -0400 -@@ -53,7 +53,7 @@ static inline void setup_thread_stack(st - * When the stack grows up, this is the highest address. - * Beyond that position, we corrupt data on the next page. - */ --static inline unsigned long *end_of_stack(struct task_struct *p) -+static inline unsigned long *end_of_stack(const struct task_struct *p) - { - #ifdef CONFIG_STACK_GROWSUP - return (unsigned long *)((unsigned long)task_thread_info(p) + THREAD_SIZE) - 1; -diff -purNx .git BPI-Router-Linux-kernel/include/linux/sched.h BPI-Router-Linux-kernel-6.16.12/include/linux/sched.h ---- BPI-Router-Linux-kernel/include/linux/sched.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/sched.h 2025-10-22 13:53:56.755167984 -0400 -@@ -548,10 +548,6 @@ struct sched_statistics { - u64 nr_failed_migrations_running; - u64 nr_failed_migrations_hot; - u64 nr_forced_migrations; --#ifdef CONFIG_NUMA_BALANCING -- u64 numa_task_migrated; -- u64 numa_task_swapped; --#endif - - u64 nr_wakeups; - u64 nr_wakeups_sync; -diff -purNx .git BPI-Router-Linux-kernel/include/linux/skbuff.h BPI-Router-Linux-kernel-6.16.12/include/linux/skbuff.h ---- BPI-Router-Linux-kernel/include/linux/skbuff.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/skbuff.h 2025-10-22 13:53:56.755167984 -0400 -@@ -3033,6 +3033,29 @@ static inline void skb_reset_transport_h - skb->transport_header = offset; - } - -+/** -+ * skb_reset_transport_header_careful - conditionally reset transport header -+ * @skb: buffer to alter -+ * -+ * Hardened version of skb_reset_transport_header(). -+ * -+ * Returns: true if the operation was a success. -+ */ -+static inline bool __must_check -+skb_reset_transport_header_careful(struct sk_buff *skb) -+{ -+ long offset = skb->data - skb->head; -+ -+ if (unlikely(offset != (typeof(skb->transport_header))offset)) -+ return false; -+ -+ if (unlikely(offset == (typeof(skb->transport_header))~0U)) -+ return false; -+ -+ skb->transport_header = offset; -+ return true; -+} -+ - static inline void skb_set_transport_header(struct sk_buff *skb, - const int offset) - { -@@ -3665,7 +3688,13 @@ static inline void *skb_frag_address(con - */ - static inline void *skb_frag_address_safe(const skb_frag_t *frag) - { -- void *ptr = page_address(skb_frag_page(frag)); -+ struct page *page = skb_frag_page(frag); -+ void *ptr; -+ -+ if (!page) -+ return NULL; -+ -+ ptr = page_address(page); - if (unlikely(!ptr)) - return NULL; - -diff -purNx .git BPI-Router-Linux-kernel/include/linux/soc/amd/isp4_misc.h BPI-Router-Linux-kernel-6.16.12/include/linux/soc/amd/isp4_misc.h ---- BPI-Router-Linux-kernel/include/linux/soc/amd/isp4_misc.h 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/soc/amd/isp4_misc.h 2025-10-22 13:53:56.755167984 -0400 -@@ -0,0 +1,12 @@ -+// SPDX-License-Identifier: GPL-2.0+ -+ -+/* -+ * Copyright (C) 2025 Advanced Micro Devices, Inc. -+ */ -+ -+#ifndef __SOC_ISP4_MISC_H -+#define __SOC_ISP4_MISC_H -+ -+#define AMDISP_I2C_ADAP_NAME "AMDISP DesignWare I2C adapter" -+ -+#endif -diff -purNx .git BPI-Router-Linux-kernel/include/linux/soc/marvell/silicons.h BPI-Router-Linux-kernel-6.16.12/include/linux/soc/marvell/silicons.h ---- BPI-Router-Linux-kernel/include/linux/soc/marvell/silicons.h 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/soc/marvell/silicons.h 2025-10-22 13:53:56.755167984 -0400 -@@ -0,0 +1,25 @@ -+/* SPDX-License-Identifier: GPL-2.0-only -+ * Copyright (C) 2024 Marvell. -+ */ -+ -+#ifndef __SOC_SILICON_H -+#define __SOC_SILICON_H -+ -+#include -+#include -+ -+#if defined(CONFIG_ARM64) -+ -+#define CN20K_CHIPID 0x20 -+/* -+ * Silicon check for CN20K family -+ */ -+static inline bool is_cn20k(struct pci_dev *pdev) -+{ -+ return (pdev->subsystem_device & 0xFF) == CN20K_CHIPID; -+} -+#else -+#define is_cn20k(pdev) ((void)(pdev), 0) -+#endif -+ -+#endif /* __SOC_SILICON_H */ -diff -purNx .git BPI-Router-Linux-kernel/include/linux/soc/qcom/qmi.h BPI-Router-Linux-kernel-6.16.12/include/linux/soc/qcom/qmi.h ---- BPI-Router-Linux-kernel/include/linux/soc/qcom/qmi.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/soc/qcom/qmi.h 2025-10-22 13:53:56.755167984 -0400 -@@ -24,9 +24,9 @@ struct socket; - */ - struct qmi_header { - u8 type; -- u16 txn_id; -- u16 msg_id; -- u16 msg_len; -+ __le16 txn_id; -+ __le16 msg_id; -+ __le16 msg_len; - } __packed; - - #define QMI_REQUEST 0 -diff -purNx .git BPI-Router-Linux-kernel/include/linux/spi/spi.h BPI-Router-Linux-kernel-6.16.12/include/linux/spi/spi.h ---- BPI-Router-Linux-kernel/include/linux/spi/spi.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/spi/spi.h 2025-10-22 13:53:56.755167984 -0400 -@@ -21,7 +21,7 @@ - #include - - /* Max no. of CS supported per spi device */ --#define SPI_CS_CNT_MAX 16 -+#define SPI_CS_CNT_MAX 24 - - struct dma_chan; - struct software_node; -diff -purNx .git BPI-Router-Linux-kernel/include/linux/sprintf.h BPI-Router-Linux-kernel-6.16.12/include/linux/sprintf.h ---- BPI-Router-Linux-kernel/include/linux/sprintf.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/sprintf.h 2025-10-22 13:53:56.755167984 -0400 -@@ -4,6 +4,7 @@ - - #include - #include -+#include - - int num_to_str(char *buf, int size, unsigned long long num, unsigned int width); - -diff -purNx .git BPI-Router-Linux-kernel/include/linux/suspend.h BPI-Router-Linux-kernel-6.16.12/include/linux/suspend.h ---- BPI-Router-Linux-kernel/include/linux/suspend.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/suspend.h 2025-10-22 13:53:56.755167984 -0400 -@@ -446,6 +446,8 @@ extern int unregister_pm_notifier(struct - extern void ksys_sync_helper(void); - extern void pm_report_hw_sleep_time(u64 t); - extern void pm_report_max_hw_sleep(u64 t); -+void pm_restrict_gfp_mask(void); -+void pm_restore_gfp_mask(void); - - #define pm_notifier(fn, pri) { \ - static struct notifier_block fn##_nb = \ -@@ -492,6 +494,9 @@ static inline int unregister_pm_notifier - static inline void pm_report_hw_sleep_time(u64 t) {}; - static inline void pm_report_max_hw_sleep(u64 t) {}; - -+static inline void pm_restrict_gfp_mask(void) {} -+static inline void pm_restore_gfp_mask(void) {} -+ - static inline void ksys_sync_helper(void) {} - - #define pm_notifier(fn, pri) do { (void)(fn); } while (0) -diff -purNx .git BPI-Router-Linux-kernel/include/linux/swap.h BPI-Router-Linux-kernel-6.16.12/include/linux/swap.h ---- BPI-Router-Linux-kernel/include/linux/swap.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/swap.h 2025-10-22 13:53:56.755167984 -0400 -@@ -384,6 +384,16 @@ void folio_add_lru_vma(struct folio *, s - void mark_page_accessed(struct page *); - void folio_mark_accessed(struct folio *); - -+static inline bool folio_may_be_lru_cached(struct folio *folio) -+{ -+ /* -+ * Holding PMD-sized folios in per-CPU LRU cache unbalances accounting. -+ * Holding small numbers of low-order mTHP folios in per-CPU LRU cache -+ * will be sensible, but nobody has implemented and tested that yet. -+ */ -+ return !folio_test_large(folio); -+} -+ - extern atomic_t lru_disable_count; - - static inline bool lru_cache_disabled(void) -diff -purNx .git BPI-Router-Linux-kernel/include/linux/usb/cdc_ncm.h BPI-Router-Linux-kernel-6.16.12/include/linux/usb/cdc_ncm.h ---- BPI-Router-Linux-kernel/include/linux/usb/cdc_ncm.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/usb/cdc_ncm.h 2025-10-22 13:53:56.755167984 -0400 -@@ -119,6 +119,7 @@ struct cdc_ncm_ctx { - u32 timer_interval; - u32 max_ndp_size; - u8 is_ndp16; -+ u8 filtering_supported; - union { - struct usb_cdc_ncm_ndp16 *delayed_ndp16; - struct usb_cdc_ncm_ndp32 *delayed_ndp32; -diff -purNx .git BPI-Router-Linux-kernel/include/linux/usb/typec_dp.h BPI-Router-Linux-kernel-6.16.12/include/linux/usb/typec_dp.h ---- BPI-Router-Linux-kernel/include/linux/usb/typec_dp.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/usb/typec_dp.h 2025-10-22 13:53:56.755167984 -0400 -@@ -57,6 +57,7 @@ enum { - DP_PIN_ASSIGN_D, - DP_PIN_ASSIGN_E, - DP_PIN_ASSIGN_F, /* Not supported after v1.0b */ -+ DP_PIN_ASSIGN_MAX, - }; - - /* DisplayPort alt mode specific commands */ -diff -purNx .git BPI-Router-Linux-kernel/include/linux/usb/usbnet.h BPI-Router-Linux-kernel-6.16.12/include/linux/usb/usbnet.h ---- BPI-Router-Linux-kernel/include/linux/usb/usbnet.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/usb/usbnet.h 2025-10-22 13:53:56.755167984 -0400 -@@ -76,6 +76,7 @@ struct usbnet { - # define EVENT_LINK_CHANGE 11 - # define EVENT_SET_RX_MODE 12 - # define EVENT_NO_IP_ALIGN 13 -+# define EVENT_LINK_CARRIER_ON 14 - /* This one is special, as it indicates that the device is going away - * there are cyclic dependencies between tasklet, timer and bh - * that must be broken -diff -purNx .git BPI-Router-Linux-kernel/include/linux/usb.h BPI-Router-Linux-kernel-6.16.12/include/linux/usb.h ---- BPI-Router-Linux-kernel/include/linux/usb.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/usb.h 2025-10-22 13:53:56.755167984 -0400 -@@ -614,6 +614,7 @@ struct usb3_lpm_parameters { - * FIXME -- complete doc - * @authenticated: Crypto authentication passed - * @tunnel_mode: Connection native or tunneled over USB4 -+ * @usb4_link: device link to the USB4 host interface - * @lpm_capable: device supports LPM - * @lpm_devinit_allow: Allow USB3 device initiated LPM, exit latency is in range - * @usb2_hw_lpm_capable: device can perform USB2 hardware LPM -@@ -724,6 +725,7 @@ struct usb_device { - unsigned reset_resume:1; - unsigned port_is_suspended:1; - enum usb_link_tunnel_mode tunnel_mode; -+ struct device_link *usb4_link; - - int slot_id; - struct usb2_lpm_parameters l1_params; -diff -purNx .git BPI-Router-Linux-kernel/include/linux/vfio.h BPI-Router-Linux-kernel-6.16.12/include/linux/vfio.h ---- BPI-Router-Linux-kernel/include/linux/vfio.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/vfio.h 2025-10-22 13:53:56.755167984 -0400 -@@ -105,6 +105,9 @@ struct vfio_device { - * @match: Optional device name match callback (return: 0 for no-match, >0 for - * match, -errno for abort (ex. match with insufficient or incorrect - * additional args) -+ * @match_token_uuid: Optional device token match/validation. Return 0 -+ * if the uuid is valid for the device, -errno otherwise. uuid is NULL -+ * if none was provided. - * @dma_unmap: Called when userspace unmaps IOVA from the container - * this device is attached to. - * @device_feature: Optional, fill in the VFIO_DEVICE_FEATURE ioctl -@@ -132,6 +135,7 @@ struct vfio_device_ops { - int (*mmap)(struct vfio_device *vdev, struct vm_area_struct *vma); - void (*request)(struct vfio_device *vdev, unsigned int count); - int (*match)(struct vfio_device *vdev, char *buf); -+ int (*match_token_uuid)(struct vfio_device *vdev, const uuid_t *uuid); - void (*dma_unmap)(struct vfio_device *vdev, u64 iova, u64 length); - int (*device_feature)(struct vfio_device *device, u32 flags, - void __user *arg, size_t argsz); -diff -purNx .git BPI-Router-Linux-kernel/include/linux/vfio_pci_core.h BPI-Router-Linux-kernel-6.16.12/include/linux/vfio_pci_core.h ---- BPI-Router-Linux-kernel/include/linux/vfio_pci_core.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/vfio_pci_core.h 2025-10-22 13:53:56.755167984 -0400 -@@ -122,6 +122,8 @@ ssize_t vfio_pci_core_write(struct vfio_ - int vfio_pci_core_mmap(struct vfio_device *core_vdev, struct vm_area_struct *vma); - void vfio_pci_core_request(struct vfio_device *core_vdev, unsigned int count); - int vfio_pci_core_match(struct vfio_device *core_vdev, char *buf); -+int vfio_pci_core_match_token_uuid(struct vfio_device *core_vdev, -+ const uuid_t *uuid); - int vfio_pci_core_enable(struct vfio_pci_core_device *vdev); - void vfio_pci_core_disable(struct vfio_pci_core_device *vdev); - void vfio_pci_core_finish_enable(struct vfio_pci_core_device *vdev); -diff -purNx .git BPI-Router-Linux-kernel/include/linux/virtio_config.h BPI-Router-Linux-kernel-6.16.12/include/linux/virtio_config.h ---- BPI-Router-Linux-kernel/include/linux/virtio_config.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/virtio_config.h 2025-10-22 13:53:56.755167984 -0400 -@@ -329,8 +329,6 @@ static inline - bool virtio_get_shm_region(struct virtio_device *vdev, - struct virtio_shm_region *region, u8 id) - { -- if (!region->len) -- return false; - if (!vdev->config->get_shm_region) - return false; - return vdev->config->get_shm_region(vdev, region, id); -diff -purNx .git BPI-Router-Linux-kernel/include/linux/virtio_vsock.h BPI-Router-Linux-kernel-6.16.12/include/linux/virtio_vsock.h ---- BPI-Router-Linux-kernel/include/linux/virtio_vsock.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/virtio_vsock.h 2025-10-22 13:53:56.755167984 -0400 -@@ -111,7 +111,12 @@ static inline size_t virtio_vsock_skb_le - return (size_t)(skb_end_pointer(skb) - skb->head); - } - --#define VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE (1024 * 4) -+/* Dimension the RX SKB so that the entire thing fits exactly into -+ * a single 4KiB page. This avoids wasting memory due to alloc_skb() -+ * rounding up to the next page order and also means that we -+ * don't leave higher-order pages sitting around in the RX queue. -+ */ -+#define VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE SKB_WITH_OVERHEAD(1024 * 4) - #define VIRTIO_VSOCK_MAX_BUF_SIZE 0xFFFFFFFFUL - #define VIRTIO_VSOCK_MAX_PKT_BUF_SIZE (1024 * 64) - -diff -purNx .git BPI-Router-Linux-kernel/include/linux/vmalloc.h BPI-Router-Linux-kernel-6.16.12/include/linux/vmalloc.h ---- BPI-Router-Linux-kernel/include/linux/vmalloc.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/vmalloc.h 2025-10-22 13:53:56.755167984 -0400 -@@ -220,22 +220,6 @@ int vmap_pages_range(unsigned long addr, - struct page **pages, unsigned int page_shift); - - /* -- * Architectures can set this mask to a combination of PGTBL_P?D_MODIFIED values -- * and let generic vmalloc and ioremap code know when arch_sync_kernel_mappings() -- * needs to be called. -- */ --#ifndef ARCH_PAGE_TABLE_SYNC_MASK --#define ARCH_PAGE_TABLE_SYNC_MASK 0 --#endif -- --/* -- * There is no default implementation for arch_sync_kernel_mappings(). It is -- * relied upon the compiler to optimize calls out if ARCH_PAGE_TABLE_SYNC_MASK -- * is 0. -- */ --void arch_sync_kernel_mappings(unsigned long start, unsigned long end); -- --/* - * Lowlevel-APIs (not for driver use!) - */ - -diff -purNx .git BPI-Router-Linux-kernel/include/linux/vm_event_item.h BPI-Router-Linux-kernel-6.16.12/include/linux/vm_event_item.h ---- BPI-Router-Linux-kernel/include/linux/vm_event_item.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/linux/vm_event_item.h 2025-10-22 13:53:56.755167984 -0400 -@@ -66,8 +66,6 @@ enum vm_event_item { PGPGIN, PGPGOUT, PS - NUMA_HINT_FAULTS, - NUMA_HINT_FAULTS_LOCAL, - NUMA_PAGE_MIGRATE, -- NUMA_TASK_MIGRATE, -- NUMA_TASK_SWAP, - #endif - #ifdef CONFIG_MIGRATION - PGMIGRATE_SUCCESS, PGMIGRATE_FAIL, -diff -purNx .git BPI-Router-Linux-kernel/include/net/af_vsock.h BPI-Router-Linux-kernel-6.16.12/include/net/af_vsock.h ---- BPI-Router-Linux-kernel/include/net/af_vsock.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/af_vsock.h 2025-10-22 13:53:56.755167984 -0400 -@@ -243,8 +243,8 @@ int __vsock_dgram_recvmsg(struct socket - int vsock_dgram_recvmsg(struct socket *sock, struct msghdr *msg, - size_t len, int flags); - --#ifdef CONFIG_BPF_SYSCALL - extern struct proto vsock_proto; -+#ifdef CONFIG_BPF_SYSCALL - int vsock_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore); - void __init vsock_bpf_build_proto(void); - #else -diff -purNx .git BPI-Router-Linux-kernel/include/net/bluetooth/bluetooth.h BPI-Router-Linux-kernel-6.16.12/include/net/bluetooth/bluetooth.h ---- BPI-Router-Linux-kernel/include/net/bluetooth/bluetooth.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/bluetooth/bluetooth.h 2025-10-22 13:53:56.755167984 -0400 -@@ -638,7 +638,7 @@ static inline void sco_exit(void) - #if IS_ENABLED(CONFIG_BT_LE) - int iso_init(void); - int iso_exit(void); --bool iso_enabled(void); -+bool iso_inited(void); - #else - static inline int iso_init(void) - { -@@ -650,7 +650,7 @@ static inline int iso_exit(void) - return 0; - } - --static inline bool iso_enabled(void) -+static inline bool iso_inited(void) - { - return false; - } -diff -purNx .git BPI-Router-Linux-kernel/include/net/bluetooth/hci_core.h BPI-Router-Linux-kernel-6.16.12/include/net/bluetooth/hci_core.h ---- BPI-Router-Linux-kernel/include/net/bluetooth/hci_core.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/bluetooth/hci_core.h 2025-10-22 13:53:56.755167984 -0400 -@@ -29,6 +29,8 @@ - #include - #include - #include -+#include -+#include - - #include - #include -@@ -93,6 +95,7 @@ struct discovery_state { - u16 uuid_count; - u8 (*uuids)[16]; - unsigned long name_resolve_timeout; -+ spinlock_t lock; - }; - - #define SUSPEND_NOTIFIER_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ -@@ -126,7 +129,9 @@ struct hci_conn_hash { - struct list_head list; - unsigned int acl_num; - unsigned int sco_num; -- unsigned int iso_num; -+ unsigned int cis_num; -+ unsigned int bis_num; -+ unsigned int pa_num; - unsigned int le_num; - unsigned int le_num_peripheral; - }; -@@ -242,6 +247,7 @@ struct adv_info { - __u8 mesh; - __u8 instance; - __u8 handle; -+ __u8 sid; - __u32 flags; - __u16 timeout; - __u16 remaining_time; -@@ -346,6 +352,7 @@ struct adv_monitor { - - struct hci_dev { - struct list_head list; -+ struct srcu_struct srcu; - struct mutex lock; - - struct ida unset_handle_ida; -@@ -461,7 +468,7 @@ struct hci_dev { - - unsigned int auto_accept_delay; - -- unsigned long quirks; -+ DECLARE_BITMAP(quirk_flags, __HCI_NUM_QUIRKS); - - atomic_t cmd_cnt; - unsigned int acl_cnt; -@@ -546,6 +553,7 @@ struct hci_dev { - struct hci_conn_hash conn_hash; - - struct list_head mesh_pending; -+ struct mutex mgmt_pending_lock; - struct list_head mgmt_pending; - struct list_head reject_list; - struct list_head accept_list; -@@ -652,6 +660,10 @@ struct hci_dev { - u8 (*classify_pkt_type)(struct hci_dev *hdev, struct sk_buff *skb); - }; - -+#define hci_set_quirk(hdev, nr) set_bit((nr), (hdev)->quirk_flags) -+#define hci_clear_quirk(hdev, nr) clear_bit((nr), (hdev)->quirk_flags) -+#define hci_test_quirk(hdev, nr) test_bit((nr), (hdev)->quirk_flags) -+ - #define HCI_PHY_HANDLE(handle) (handle & 0xff) - - enum conn_reasons { -@@ -825,20 +837,20 @@ extern struct mutex hci_cb_list_lock; - #define hci_dev_test_and_clear_flag(hdev, nr) test_and_clear_bit((nr), (hdev)->dev_flags) - #define hci_dev_test_and_change_flag(hdev, nr) test_and_change_bit((nr), (hdev)->dev_flags) - --#define hci_dev_clear_volatile_flags(hdev) \ -- do { \ -- hci_dev_clear_flag(hdev, HCI_LE_SCAN); \ -- hci_dev_clear_flag(hdev, HCI_LE_ADV); \ -- hci_dev_clear_flag(hdev, HCI_LL_RPA_RESOLUTION);\ -- hci_dev_clear_flag(hdev, HCI_PERIODIC_INQ); \ -- hci_dev_clear_flag(hdev, HCI_QUALITY_REPORT); \ -+#define hci_dev_clear_volatile_flags(hdev) \ -+ do { \ -+ hci_dev_clear_flag((hdev), HCI_LE_SCAN); \ -+ hci_dev_clear_flag((hdev), HCI_LE_ADV); \ -+ hci_dev_clear_flag((hdev), HCI_LL_RPA_RESOLUTION); \ -+ hci_dev_clear_flag((hdev), HCI_PERIODIC_INQ); \ -+ hci_dev_clear_flag((hdev), HCI_QUALITY_REPORT); \ - } while (0) - - #define hci_dev_le_state_simultaneous(hdev) \ -- (!test_bit(HCI_QUIRK_BROKEN_LE_STATES, &hdev->quirks) && \ -- (hdev->le_states[4] & 0x08) && /* Central */ \ -- (hdev->le_states[4] & 0x40) && /* Peripheral */ \ -- (hdev->le_states[3] & 0x10)) /* Simultaneous */ -+ (!hci_test_quirk((hdev), HCI_QUIRK_BROKEN_LE_STATES) && \ -+ ((hdev)->le_states[4] & 0x08) && /* Central */ \ -+ ((hdev)->le_states[4] & 0x40) && /* Peripheral */ \ -+ ((hdev)->le_states[3] & 0x10)) /* Simultaneous */ - - /* ----- HCI interface to upper protocols ----- */ - int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr); -@@ -881,6 +893,7 @@ static inline void iso_recv(struct hci_c - - static inline void discovery_init(struct hci_dev *hdev) - { -+ spin_lock_init(&hdev->discovery.lock); - hdev->discovery.state = DISCOVERY_STOPPED; - INIT_LIST_HEAD(&hdev->discovery.all); - INIT_LIST_HEAD(&hdev->discovery.unknown); -@@ -895,8 +908,11 @@ static inline void hci_discovery_filter_ - hdev->discovery.report_invalid_rssi = true; - hdev->discovery.rssi = HCI_RSSI_INVALID; - hdev->discovery.uuid_count = 0; -+ -+ spin_lock(&hdev->discovery.lock); - kfree(hdev->discovery.uuids); - hdev->discovery.uuids = NULL; -+ spin_unlock(&hdev->discovery.lock); - } - - bool hci_discovery_active(struct hci_dev *hdev); -@@ -1000,8 +1016,13 @@ static inline void hci_conn_hash_add(str - h->sco_num++; - break; - case CIS_LINK: -+ h->cis_num++; -+ break; - case BIS_LINK: -- h->iso_num++; -+ h->bis_num++; -+ break; -+ case PA_LINK: -+ h->pa_num++; - break; - } - } -@@ -1027,8 +1048,13 @@ static inline void hci_conn_hash_del(str - h->sco_num--; - break; - case CIS_LINK: -+ h->cis_num--; -+ break; - case BIS_LINK: -- h->iso_num--; -+ h->bis_num--; -+ break; -+ case PA_LINK: -+ h->pa_num--; - break; - } - } -@@ -1045,8 +1071,11 @@ static inline unsigned int hci_conn_num( - case ESCO_LINK: - return h->sco_num; - case CIS_LINK: -+ return h->cis_num; - case BIS_LINK: -- return h->iso_num; -+ return h->bis_num; -+ case PA_LINK: -+ return h->pa_num; - default: - return 0; - } -@@ -1056,7 +1085,15 @@ static inline unsigned int hci_conn_coun - { - struct hci_conn_hash *c = &hdev->conn_hash; - -- return c->acl_num + c->sco_num + c->le_num + c->iso_num; -+ return c->acl_num + c->sco_num + c->le_num + c->cis_num + c->bis_num + -+ c->pa_num; -+} -+ -+static inline unsigned int hci_iso_count(struct hci_dev *hdev) -+{ -+ struct hci_conn_hash *c = &hdev->conn_hash; -+ -+ return c->cis_num + c->bis_num; - } - - static inline bool hci_conn_valid(struct hci_dev *hdev, struct hci_conn *conn) -@@ -1128,7 +1165,7 @@ hci_conn_hash_lookup_create_pa_sync(stru - rcu_read_lock(); - - list_for_each_entry_rcu(c, &h->list, list) { -- if (c->type != BIS_LINK) -+ if (c->type != PA_LINK) - continue; - - if (!test_bit(HCI_CONN_CREATE_PA_SYNC, &c->flags)) -@@ -1208,6 +1245,27 @@ static inline struct hci_conn *hci_conn_ - return NULL; - } - -+static inline struct hci_conn *hci_conn_hash_lookup_role(struct hci_dev *hdev, -+ __u8 type, __u8 role, -+ bdaddr_t *ba) -+{ -+ struct hci_conn_hash *h = &hdev->conn_hash; -+ struct hci_conn *c; -+ -+ rcu_read_lock(); -+ -+ list_for_each_entry_rcu(c, &h->list, list) { -+ if (c->type == type && c->role == role && !bacmp(&c->dst, ba)) { -+ rcu_read_unlock(); -+ return c; -+ } -+ } -+ -+ rcu_read_unlock(); -+ -+ return NULL; -+} -+ - static inline struct hci_conn *hci_conn_hash_lookup_le(struct hci_dev *hdev, - bdaddr_t *ba, - __u8 ba_type) -@@ -1323,7 +1381,7 @@ hci_conn_hash_lookup_big_sync_pend(struc - rcu_read_lock(); - - list_for_each_entry_rcu(c, &h->list, list) { -- if (c->type != BIS_LINK) -+ if (c->type != PA_LINK) - continue; - - if (handle == c->iso_qos.bcast.big && num_bis == c->num_bis) { -@@ -1338,7 +1396,8 @@ hci_conn_hash_lookup_big_sync_pend(struc - } - - static inline struct hci_conn * --hci_conn_hash_lookup_big_state(struct hci_dev *hdev, __u8 handle, __u16 state) -+hci_conn_hash_lookup_big_state(struct hci_dev *hdev, __u8 handle, __u16 state, -+ __u8 role) - { - struct hci_conn_hash *h = &hdev->conn_hash; - struct hci_conn *c; -@@ -1346,8 +1405,7 @@ hci_conn_hash_lookup_big_state(struct hc - rcu_read_lock(); - - list_for_each_entry_rcu(c, &h->list, list) { -- if (c->type != BIS_LINK || bacmp(&c->dst, BDADDR_ANY) || -- c->state != state) -+ if (c->type != BIS_LINK || c->state != state || c->role != role) - continue; - - if (handle == c->iso_qos.bcast.big) { -@@ -1393,7 +1451,7 @@ hci_conn_hash_lookup_pa_sync_handle(stru - rcu_read_lock(); - - list_for_each_entry_rcu(c, &h->list, list) { -- if (c->type != BIS_LINK) -+ if (c->type != PA_LINK) - continue; - - /* Ignore the listen hcon, we are looking -@@ -1550,13 +1608,14 @@ struct hci_conn *hci_connect_sco(struct - u16 timeout); - struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst, - __u8 dst_type, struct bt_iso_qos *qos); --struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, -+struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, __u8 sid, - struct bt_iso_qos *qos, - __u8 base_len, __u8 *base); - struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst, - __u8 dst_type, struct bt_iso_qos *qos); - struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst, -- __u8 dst_type, struct bt_iso_qos *qos, -+ __u8 dst_type, __u8 sid, -+ struct bt_iso_qos *qos, - __u8 data_len, __u8 *data); - struct hci_conn *hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst, - __u8 dst_type, __u8 sid, struct bt_iso_qos *qos); -@@ -1831,6 +1890,7 @@ int hci_remove_remote_oob_data(struct hc - - void hci_adv_instances_clear(struct hci_dev *hdev); - struct adv_info *hci_find_adv_instance(struct hci_dev *hdev, u8 instance); -+struct adv_info *hci_find_adv_sid(struct hci_dev *hdev, u8 sid); - struct adv_info *hci_get_next_instance(struct hci_dev *hdev, u8 instance); - struct adv_info *hci_add_adv_instance(struct hci_dev *hdev, u8 instance, - u32 flags, u16 adv_data_len, u8 *adv_data, -@@ -1838,7 +1898,7 @@ struct adv_info *hci_add_adv_instance(st - u16 timeout, u16 duration, s8 tx_power, - u32 min_interval, u32 max_interval, - u8 mesh_handle); --struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance, -+struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance, u8 sid, - u32 flags, u8 data_len, u8 *data, - u32 min_interval, u32 max_interval); - int hci_set_adv_instance_data(struct hci_dev *hdev, u8 instance, -@@ -1916,6 +1976,8 @@ void hci_conn_del_sysfs(struct hci_conn - !hci_dev_test_flag(dev, HCI_RPA_EXPIRED)) - #define adv_rpa_valid(adv) (bacmp(&adv->random_addr, BDADDR_ANY) && \ - !adv->rpa_expired) -+#define le_enabled(dev) (lmp_le_capable(dev) && \ -+ hci_dev_test_flag(dev, HCI_LE_ENABLED)) - - #define scan_1m(dev) (((dev)->le_tx_def_phys & HCI_LE_SET_PHY_1M) || \ - ((dev)->le_rx_def_phys & HCI_LE_SET_PHY_1M)) -@@ -1926,40 +1988,41 @@ void hci_conn_del_sysfs(struct hci_conn - ((dev)->le_rx_def_phys & HCI_LE_SET_PHY_2M)) - - #define le_coded_capable(dev) (((dev)->le_features[1] & HCI_LE_PHY_CODED) && \ -- !test_bit(HCI_QUIRK_BROKEN_LE_CODED, \ -- &(dev)->quirks)) -+ !hci_test_quirk((dev), \ -+ HCI_QUIRK_BROKEN_LE_CODED)) - - #define scan_coded(dev) (((dev)->le_tx_def_phys & HCI_LE_SET_PHY_CODED) || \ - ((dev)->le_rx_def_phys & HCI_LE_SET_PHY_CODED)) - - #define ll_privacy_capable(dev) ((dev)->le_features[0] & HCI_LE_LL_PRIVACY) -+#define ll_privacy_enabled(dev) (le_enabled(dev) && ll_privacy_capable(dev)) - - #define privacy_mode_capable(dev) (ll_privacy_capable(dev) && \ -- (hdev->commands[39] & 0x04)) -+ ((dev)->commands[39] & 0x04)) - - #define read_key_size_capable(dev) \ - ((dev)->commands[20] & 0x10 && \ -- !test_bit(HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, &hdev->quirks)) -+ !hci_test_quirk((dev), HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE)) - - #define read_voice_setting_capable(dev) \ - ((dev)->commands[9] & 0x04 && \ -- !test_bit(HCI_QUIRK_BROKEN_READ_VOICE_SETTING, &(dev)->quirks)) -+ !hci_test_quirk((dev), HCI_QUIRK_BROKEN_READ_VOICE_SETTING)) - - /* Use enhanced synchronous connection if command is supported and its quirk - * has not been set. - */ - #define enhanced_sync_conn_capable(dev) \ - (((dev)->commands[29] & 0x08) && \ -- !test_bit(HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN, &(dev)->quirks)) -+ !hci_test_quirk((dev), HCI_QUIRK_BROKEN_ENHANCED_SETUP_SYNC_CONN)) - - /* Use ext scanning if set ext scan param and ext scan enable is supported */ - #define use_ext_scan(dev) (((dev)->commands[37] & 0x20) && \ - ((dev)->commands[37] & 0x40) && \ -- !test_bit(HCI_QUIRK_BROKEN_EXT_SCAN, &(dev)->quirks)) -+ !hci_test_quirk((dev), HCI_QUIRK_BROKEN_EXT_SCAN)) - - /* Use ext create connection if command is supported */ - #define use_ext_conn(dev) (((dev)->commands[37] & 0x80) && \ -- !test_bit(HCI_QUIRK_BROKEN_EXT_CREATE_CONN, &(dev)->quirks)) -+ !hci_test_quirk((dev), HCI_QUIRK_BROKEN_EXT_CREATE_CONN)) - /* Extended advertising support */ - #define ext_adv_capable(dev) (((dev)->le_features[1] & HCI_LE_EXT_ADV)) - -@@ -1974,25 +2037,34 @@ void hci_conn_del_sysfs(struct hci_conn - */ - #define use_enhanced_conn_complete(dev) ((ll_privacy_capable(dev) || \ - ext_adv_capable(dev)) && \ -- !test_bit(HCI_QUIRK_BROKEN_EXT_CREATE_CONN, \ -- &(dev)->quirks)) -+ !hci_test_quirk((dev), \ -+ HCI_QUIRK_BROKEN_EXT_CREATE_CONN)) - - /* Periodic advertising support */ - #define per_adv_capable(dev) (((dev)->le_features[1] & HCI_LE_PERIODIC_ADV)) - - /* CIS Master/Slave and BIS support */ - #define iso_capable(dev) (cis_capable(dev) || bis_capable(dev)) -+#define iso_enabled(dev) (le_enabled(dev) && iso_capable(dev)) - #define cis_capable(dev) \ - (cis_central_capable(dev) || cis_peripheral_capable(dev)) -+#define cis_enabled(dev) (le_enabled(dev) && cis_capable(dev)) - #define cis_central_capable(dev) \ - ((dev)->le_features[3] & HCI_LE_CIS_CENTRAL) -+#define cis_central_enabled(dev) \ -+ (le_enabled(dev) && cis_central_capable(dev)) - #define cis_peripheral_capable(dev) \ - ((dev)->le_features[3] & HCI_LE_CIS_PERIPHERAL) -+#define cis_peripheral_enabled(dev) \ -+ (le_enabled(dev) && cis_peripheral_capable(dev)) - #define bis_capable(dev) ((dev)->le_features[3] & HCI_LE_ISO_BROADCASTER) --#define sync_recv_capable(dev) ((dev)->le_features[3] & HCI_LE_ISO_SYNC_RECEIVER) -+#define bis_enabled(dev) (le_enabled(dev) && bis_capable(dev)) -+#define sync_recv_capable(dev) \ -+ ((dev)->le_features[3] & HCI_LE_ISO_SYNC_RECEIVER) -+#define sync_recv_enabled(dev) (le_enabled(dev) && sync_recv_capable(dev)) - - #define mws_transport_config_capable(dev) (((dev)->commands[30] & 0x08) && \ -- (!test_bit(HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG, &(dev)->quirks))) -+ (!hci_test_quirk((dev), HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG))) - - /* ----- HCI protocols ----- */ - #define HCI_PROTO_DEFER 0x01 -@@ -2010,6 +2082,7 @@ static inline int hci_proto_connect_ind( - - case CIS_LINK: - case BIS_LINK: -+ case PA_LINK: - return iso_connect_ind(hdev, bdaddr, flags); - - default: -@@ -2400,7 +2473,6 @@ void mgmt_advertising_added(struct sock - u8 instance); - void mgmt_advertising_removed(struct sock *sk, struct hci_dev *hdev, - u8 instance); --void mgmt_adv_monitor_removed(struct hci_dev *hdev, u16 handle); - int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip); - void mgmt_adv_monitor_device_lost(struct hci_dev *hdev, u16 handle, - bdaddr_t *bdaddr, u8 addr_type); -diff -purNx .git BPI-Router-Linux-kernel/include/net/bluetooth/hci.h BPI-Router-Linux-kernel-6.16.12/include/net/bluetooth/hci.h ---- BPI-Router-Linux-kernel/include/net/bluetooth/hci.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/bluetooth/hci.h 2025-10-22 13:53:56.755167984 -0400 -@@ -377,6 +377,8 @@ enum { - * This quirk must be set before hci_register_dev is called. - */ - HCI_QUIRK_BROKEN_READ_PAGE_SCAN_TYPE, -+ -+ __HCI_NUM_QUIRKS, - }; - - /* HCI device flags */ -@@ -560,6 +562,7 @@ enum { - #define LE_LINK 0x80 - #define CIS_LINK 0x82 - #define BIS_LINK 0x83 -+#define PA_LINK 0x84 - #define INVALID_LINK 0xff - - /* LMP features */ -@@ -2632,6 +2635,7 @@ struct hci_ev_le_conn_complete { - #define LE_EXT_ADV_DIRECT_IND 0x0004 - #define LE_EXT_ADV_SCAN_RSP 0x0008 - #define LE_EXT_ADV_LEGACY_PDU 0x0010 -+#define LE_EXT_ADV_DATA_STATUS_MASK 0x0060 - #define LE_EXT_ADV_EVT_TYPE_MASK 0x007f - - #define ADDR_LE_DEV_PUBLIC 0x00 -@@ -2849,6 +2853,12 @@ struct hci_evt_le_big_sync_estabilished - __le16 bis[]; - } __packed; - -+#define HCI_EVT_LE_BIG_SYNC_LOST 0x1e -+struct hci_evt_le_big_sync_lost { -+ __u8 handle; -+ __u8 reason; -+} __packed; -+ - #define HCI_EVT_LE_BIG_INFO_ADV_REPORT 0x22 - struct hci_evt_le_big_info_adv_report { - __le16 sync_handle; -diff -purNx .git BPI-Router-Linux-kernel/include/net/bluetooth/hci_sync.h BPI-Router-Linux-kernel-6.16.12/include/net/bluetooth/hci_sync.h ---- BPI-Router-Linux-kernel/include/net/bluetooth/hci_sync.h 2025-10-22 13:53:23.563327459 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/bluetooth/hci_sync.h 2025-10-22 13:53:56.755167984 -0400 -@@ -93,7 +93,7 @@ int hci_update_class_sync(struct hci_dev - - int hci_update_eir_sync(struct hci_dev *hdev); - int hci_update_class_sync(struct hci_dev *hdev); --int hci_update_name_sync(struct hci_dev *hdev); -+int hci_update_name_sync(struct hci_dev *hdev, const u8 *name); - int hci_write_ssp_mode_sync(struct hci_dev *hdev, u8 mode); - - int hci_get_random_address(struct hci_dev *hdev, bool require_privacy, -@@ -115,8 +115,8 @@ int hci_enable_ext_advertising_sync(stru - int hci_enable_advertising_sync(struct hci_dev *hdev); - int hci_enable_advertising(struct hci_dev *hdev); - --int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 data_len, -- u8 *data, u32 flags, u16 min_interval, -+int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 sid, -+ u8 data_len, u8 *data, u32 flags, u16 min_interval, - u16 max_interval, u16 sync_interval); - - int hci_disable_per_advertising_sync(struct hci_dev *hdev, u8 instance); -diff -purNx .git BPI-Router-Linux-kernel/include/net/bond_3ad.h BPI-Router-Linux-kernel-6.16.12/include/net/bond_3ad.h ---- BPI-Router-Linux-kernel/include/net/bond_3ad.h 2025-10-22 13:53:23.567327440 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/bond_3ad.h 2025-10-22 13:53:56.759167965 -0400 -@@ -307,6 +307,7 @@ int bond_3ad_lacpdu_recv(const struct sk - struct slave *slave); - int bond_3ad_set_carrier(struct bonding *bond); - void bond_3ad_update_lacp_rate(struct bonding *bond); -+void bond_3ad_update_lacp_active(struct bonding *bond); - void bond_3ad_update_ad_actor_settings(struct bonding *bond); - int bond_3ad_stats_fill(struct sk_buff *skb, struct bond_3ad_stats *stats); - size_t bond_3ad_stats_size(void); -diff -purNx .git BPI-Router-Linux-kernel/include/net/cfg80211.h BPI-Router-Linux-kernel-6.16.12/include/net/cfg80211.h ---- BPI-Router-Linux-kernel/include/net/cfg80211.h 2025-10-22 13:53:23.567327440 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/cfg80211.h 2025-10-22 13:53:56.759167965 -0400 -@@ -633,7 +633,7 @@ ieee80211_get_sband_iftype_data(const st - const struct ieee80211_sband_iftype_data *data; - int i; - -- if (WARN_ON(iftype >= NL80211_IFTYPE_MAX)) -+ if (WARN_ON(iftype >= NUM_NL80211_IFTYPES)) - return NULL; - - if (iftype == NL80211_IFTYPE_AP_VLAN) -@@ -2690,7 +2690,7 @@ struct cfg80211_scan_request { - s8 tsf_report_link_id; - - /* keep last */ -- struct ieee80211_channel *channels[] __counted_by(n_channels); -+ struct ieee80211_channel *channels[]; - }; - - static inline void get_random_mask_addr(u8 *buf, const u8 *addr, const u8 *mask) -diff -purNx .git BPI-Router-Linux-kernel/include/net/devlink.h BPI-Router-Linux-kernel-6.16.12/include/net/devlink.h ---- BPI-Router-Linux-kernel/include/net/devlink.h 2025-10-22 13:53:23.567327440 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/devlink.h 2025-10-22 13:53:56.759167965 -0400 -@@ -78,6 +78,9 @@ struct devlink_port_pci_sf_attrs { - * @flavour: flavour of the port - * @split: indicates if this is split port - * @splittable: indicates if the port can be split. -+ * @no_phys_port_name: skip automatic phys_port_name generation; for -+ * compatibility only, newly added driver/port instance -+ * should never set this. - * @lanes: maximum number of lanes the port supports. 0 value is not passed to netlink. - * @switch_id: if the port is part of switch, this is buffer with ID, otherwise this is NULL - * @phys: physical port attributes -@@ -87,7 +90,8 @@ struct devlink_port_pci_sf_attrs { - */ - struct devlink_port_attrs { - u8 split:1, -- splittable:1; -+ splittable:1, -+ no_phys_port_name:1; - u32 lanes; - enum devlink_port_flavour flavour; - struct netdev_phys_item_id switch_id; -diff -purNx .git BPI-Router-Linux-kernel/include/net/dst.h BPI-Router-Linux-kernel-6.16.12/include/net/dst.h ---- BPI-Router-Linux-kernel/include/net/dst.h 2025-10-22 13:53:23.567327440 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/dst.h 2025-10-22 13:53:56.759167965 -0400 -@@ -456,7 +456,7 @@ INDIRECT_CALLABLE_DECLARE(int ip_output( - /* Output packet to network from transport. */ - static inline int dst_output(struct net *net, struct sock *sk, struct sk_buff *skb) - { -- return INDIRECT_CALL_INET(skb_dst(skb)->output, -+ return INDIRECT_CALL_INET(READ_ONCE(skb_dst(skb)->output), - ip6_output, ip_output, - net, sk, skb); - } -@@ -466,7 +466,7 @@ INDIRECT_CALLABLE_DECLARE(int ip_local_d - /* Input packet from network to transport. */ - static inline int dst_input(struct sk_buff *skb) - { -- return INDIRECT_CALL_INET(skb_dst(skb)->input, -+ return INDIRECT_CALL_INET(READ_ONCE(skb_dst(skb)->input), - ip6_input, ip_local_deliver, skb); - } - -@@ -561,6 +561,26 @@ static inline void skb_dst_update_pmtu_n - dst->ops->update_pmtu(dst, NULL, skb, mtu, false); - } - -+static inline struct net_device *dst_dev(const struct dst_entry *dst) -+{ -+ return READ_ONCE(dst->dev); -+} -+ -+static inline struct net_device *skb_dst_dev(const struct sk_buff *skb) -+{ -+ return dst_dev(skb_dst(skb)); -+} -+ -+static inline struct net *skb_dst_dev_net(const struct sk_buff *skb) -+{ -+ return dev_net(skb_dst_dev(skb)); -+} -+ -+static inline struct net *skb_dst_dev_net_rcu(const struct sk_buff *skb) -+{ -+ return dev_net_rcu(skb_dst_dev(skb)); -+} -+ - struct dst_entry *dst_blackhole_check(struct dst_entry *dst, u32 cookie); - void dst_blackhole_update_pmtu(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb, u32 mtu, bool confirm_neigh); -diff -purNx .git BPI-Router-Linux-kernel/include/net/dst_metadata.h BPI-Router-Linux-kernel-6.16.12/include/net/dst_metadata.h ---- BPI-Router-Linux-kernel/include/net/dst_metadata.h 2025-10-22 13:53:23.567327440 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/dst_metadata.h 2025-10-22 13:53:56.759167965 -0400 -@@ -3,6 +3,7 @@ - #define __NET_DST_METADATA_H 1 - - #include -+#include - #include - #include - #include -@@ -220,9 +221,15 @@ static inline struct metadata_dst *ip_tu - int md_size) - { - const struct iphdr *iph = ip_hdr(skb); -+ struct metadata_dst *tun_dst; -+ -+ tun_dst = __ip_tun_set_dst(iph->saddr, iph->daddr, iph->tos, iph->ttl, -+ 0, flags, tunnel_id, md_size); - -- return __ip_tun_set_dst(iph->saddr, iph->daddr, iph->tos, iph->ttl, -- 0, flags, tunnel_id, md_size); -+ if (tun_dst && (iph->frag_off & htons(IP_DF))) -+ __set_bit(IP_TUNNEL_DONT_FRAGMENT_BIT, -+ tun_dst->u.tun_info.key.tun_flags); -+ return tun_dst; - } - - static inline struct metadata_dst *__ipv6_tun_set_dst(const struct in6_addr *saddr, -diff -purNx .git BPI-Router-Linux-kernel/include/net/ip_vs.h BPI-Router-Linux-kernel-6.16.12/include/net/ip_vs.h ---- BPI-Router-Linux-kernel/include/net/ip_vs.h 2025-10-22 13:53:23.567327440 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/ip_vs.h 2025-10-22 13:53:56.759167965 -0400 -@@ -1163,6 +1163,14 @@ static inline const struct cpumask *sysc - return housekeeping_cpumask(HK_TYPE_KTHREAD); - } - -+static inline const struct cpumask *sysctl_est_preferred_cpulist(struct netns_ipvs *ipvs) -+{ -+ if (ipvs->est_cpulist_valid) -+ return ipvs->sysctl_est_cpulist; -+ else -+ return NULL; -+} -+ - static inline int sysctl_est_nice(struct netns_ipvs *ipvs) - { - return ipvs->sysctl_est_nice; -@@ -1270,6 +1278,11 @@ static inline const struct cpumask *sysc - return housekeeping_cpumask(HK_TYPE_KTHREAD); - } - -+static inline const struct cpumask *sysctl_est_preferred_cpulist(struct netns_ipvs *ipvs) -+{ -+ return NULL; -+} -+ - static inline int sysctl_est_nice(struct netns_ipvs *ipvs) - { - return IPVS_EST_NICE; -diff -purNx .git BPI-Router-Linux-kernel/include/net/kcm.h BPI-Router-Linux-kernel-6.16.12/include/net/kcm.h ---- BPI-Router-Linux-kernel/include/net/kcm.h 2025-10-22 13:53:23.567327440 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/kcm.h 2025-10-22 13:53:56.759167965 -0400 -@@ -71,7 +71,6 @@ struct kcm_sock { - struct list_head wait_psock_list; - struct sk_buff *seq_skb; - struct mutex tx_mutex; -- u32 tx_stopped : 1; - - /* Don't use bit fields here, these are set under different locks */ - bool tx_wait; -diff -purNx .git BPI-Router-Linux-kernel/include/net/lwtunnel.h BPI-Router-Linux-kernel-6.16.12/include/net/lwtunnel.h ---- BPI-Router-Linux-kernel/include/net/lwtunnel.h 2025-10-22 13:53:23.567327440 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/lwtunnel.h 2025-10-22 13:53:56.759167965 -0400 -@@ -138,12 +138,12 @@ int bpf_lwt_push_ip_encap(struct sk_buff - static inline void lwtunnel_set_redirect(struct dst_entry *dst) - { - if (lwtunnel_output_redirect(dst->lwtstate)) { -- dst->lwtstate->orig_output = dst->output; -- dst->output = lwtunnel_output; -+ dst->lwtstate->orig_output = READ_ONCE(dst->output); -+ WRITE_ONCE(dst->output, lwtunnel_output); - } - if (lwtunnel_input_redirect(dst->lwtstate)) { -- dst->lwtstate->orig_input = dst->input; -- dst->input = lwtunnel_input; -+ dst->lwtstate->orig_input = READ_ONCE(dst->input); -+ WRITE_ONCE(dst->input, lwtunnel_input); - } - } - #else -diff -purNx .git BPI-Router-Linux-kernel/include/net/mac80211.h BPI-Router-Linux-kernel-6.16.12/include/net/mac80211.h ---- BPI-Router-Linux-kernel/include/net/mac80211.h 2025-10-22 13:53:23.567327440 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/mac80211.h 2025-10-22 13:53:56.759167965 -0400 -@@ -4302,6 +4302,8 @@ struct ieee80211_prep_tx_info { - * @mgd_complete_tx: Notify the driver that the response frame for a previously - * transmitted frame announced with @mgd_prepare_tx was received, the data - * is filled similarly to @mgd_prepare_tx though the duration is not used. -+ * Note that this isn't always called for each mgd_prepare_tx() call, for -+ * example for SAE the 'confirm' messages can be on the air in any order. - * - * @mgd_protect_tdls_discover: Protect a TDLS discovery session. After sending - * a TDLS discovery-request, we expect a reply to arrive on the AP's -@@ -4466,6 +4468,8 @@ struct ieee80211_prep_tx_info { - * new links bitmaps may be 0 if going from/to a non-MLO situation. - * The @old array contains pointers to the old bss_conf structures - * that were already removed, in case they're needed. -+ * Note that removal of link should always succeed, so the return value -+ * will be ignored in a removal only case. - * This callback can sleep. - * @change_sta_links: Change the valid links of a station, similar to - * @change_vif_links. This callback can sleep. -diff -purNx .git BPI-Router-Linux-kernel/include/net/netfilter/nf_conntrack.h BPI-Router-Linux-kernel-6.16.12/include/net/netfilter/nf_conntrack.h ---- BPI-Router-Linux-kernel/include/net/netfilter/nf_conntrack.h 2025-10-22 13:53:23.567327440 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/netfilter/nf_conntrack.h 2025-10-22 13:53:56.759167965 -0400 -@@ -306,8 +306,19 @@ static inline bool nf_ct_is_expired(cons - /* use after obtaining a reference count */ - static inline bool nf_ct_should_gc(const struct nf_conn *ct) - { -- return nf_ct_is_expired(ct) && nf_ct_is_confirmed(ct) && -- !nf_ct_is_dying(ct); -+ if (!nf_ct_is_confirmed(ct)) -+ return false; -+ -+ /* load ct->timeout after is_confirmed() test. -+ * Pairs with __nf_conntrack_confirm() which: -+ * 1. Increases ct->timeout value -+ * 2. Inserts ct into rcu hlist -+ * 3. Sets the confirmed bit -+ * 4. Unlocks the hlist lock -+ */ -+ smp_acquire__after_ctrl_dep(); -+ -+ return nf_ct_is_expired(ct) && !nf_ct_is_dying(ct); - } - - #define NF_CT_DAY (86400 * HZ) -diff -purNx .git BPI-Router-Linux-kernel/include/net/netfilter/nf_flow_table.h BPI-Router-Linux-kernel-6.16.12/include/net/netfilter/nf_flow_table.h ---- BPI-Router-Linux-kernel/include/net/netfilter/nf_flow_table.h 2025-10-22 13:53:23.567327440 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/netfilter/nf_flow_table.h 2025-10-22 13:53:56.759167965 -0400 -@@ -370,7 +370,7 @@ static inline __be16 __nf_flow_pppoe_pro - - static inline bool nf_flow_pppoe_proto(struct sk_buff *skb, __be16 *inner_proto) - { -- if (!pskb_may_pull(skb, PPPOE_SES_HLEN)) -+ if (!pskb_may_pull(skb, ETH_HLEN + PPPOE_SES_HLEN)) - return false; - - *inner_proto = __nf_flow_pppoe_proto(skb); -diff -purNx .git BPI-Router-Linux-kernel/include/net/netfilter/nf_tables_core.h BPI-Router-Linux-kernel-6.16.12/include/net/netfilter/nf_tables_core.h ---- BPI-Router-Linux-kernel/include/net/netfilter/nf_tables_core.h 2025-10-22 13:53:23.567327440 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/netfilter/nf_tables_core.h 2025-10-22 13:53:56.759167965 -0400 -@@ -94,34 +94,35 @@ extern const struct nft_set_type nft_set - extern const struct nft_set_type nft_set_pipapo_avx2_type; - - #ifdef CONFIG_MITIGATION_RETPOLINE --bool nft_rhash_lookup(const struct net *net, const struct nft_set *set, -- const u32 *key, const struct nft_set_ext **ext); --bool nft_rbtree_lookup(const struct net *net, const struct nft_set *set, -- const u32 *key, const struct nft_set_ext **ext); --bool nft_bitmap_lookup(const struct net *net, const struct nft_set *set, -- const u32 *key, const struct nft_set_ext **ext); --bool nft_hash_lookup_fast(const struct net *net, -- const struct nft_set *set, -- const u32 *key, const struct nft_set_ext **ext); --bool nft_hash_lookup(const struct net *net, const struct nft_set *set, -- const u32 *key, const struct nft_set_ext **ext); --bool nft_set_do_lookup(const struct net *net, const struct nft_set *set, -- const u32 *key, const struct nft_set_ext **ext); --#else --static inline bool --nft_set_do_lookup(const struct net *net, const struct nft_set *set, -- const u32 *key, const struct nft_set_ext **ext) --{ -- return set->ops->lookup(net, set, key, ext); --} -+const struct nft_set_ext * -+nft_rhash_lookup(const struct net *net, const struct nft_set *set, -+ const u32 *key); -+const struct nft_set_ext * -+nft_rbtree_lookup(const struct net *net, const struct nft_set *set, -+ const u32 *key); -+const struct nft_set_ext * -+nft_bitmap_lookup(const struct net *net, const struct nft_set *set, -+ const u32 *key); -+const struct nft_set_ext * -+nft_hash_lookup_fast(const struct net *net, const struct nft_set *set, -+ const u32 *key); -+const struct nft_set_ext * -+nft_hash_lookup(const struct net *net, const struct nft_set *set, -+ const u32 *key); - #endif - -+const struct nft_set_ext * -+nft_set_do_lookup(const struct net *net, const struct nft_set *set, -+ const u32 *key); -+ - /* called from nft_pipapo_avx2.c */ --bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set, -- const u32 *key, const struct nft_set_ext **ext); -+const struct nft_set_ext * -+nft_pipapo_lookup(const struct net *net, const struct nft_set *set, -+ const u32 *key); - /* called from nft_set_pipapo.c */ --bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set, -- const u32 *key, const struct nft_set_ext **ext); -+const struct nft_set_ext * -+nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set, -+ const u32 *key); - - void nft_counter_init_seqcount(void); - -diff -purNx .git BPI-Router-Linux-kernel/include/net/netfilter/nf_tables.h BPI-Router-Linux-kernel-6.16.12/include/net/netfilter/nf_tables.h ---- BPI-Router-Linux-kernel/include/net/netfilter/nf_tables.h 2025-10-22 13:53:23.567327440 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/netfilter/nf_tables.h 2025-10-22 13:53:56.759167965 -0400 -@@ -459,19 +459,17 @@ struct nft_set_ext; - * control plane functions. - */ - struct nft_set_ops { -- bool (*lookup)(const struct net *net, -+ const struct nft_set_ext * (*lookup)(const struct net *net, - const struct nft_set *set, -- const u32 *key, -- const struct nft_set_ext **ext); -- bool (*update)(struct nft_set *set, -+ const u32 *key); -+ const struct nft_set_ext * (*update)(struct nft_set *set, - const u32 *key, - struct nft_elem_priv * - (*new)(struct nft_set *, - const struct nft_expr *, - struct nft_regs *), - const struct nft_expr *expr, -- struct nft_regs *regs, -- const struct nft_set_ext **ext); -+ struct nft_regs *regs); - bool (*delete)(const struct nft_set *set, - const u32 *key); - -@@ -1142,11 +1140,6 @@ int nft_set_catchall_validate(const stru - int nf_tables_bind_chain(const struct nft_ctx *ctx, struct nft_chain *chain); - void nf_tables_unbind_chain(const struct nft_ctx *ctx, struct nft_chain *chain); - --struct nft_hook; --void nf_tables_chain_device_notify(const struct nft_chain *chain, -- const struct nft_hook *hook, -- const struct net_device *dev, int event); -- - enum nft_chain_types { - NFT_CHAIN_T_DEFAULT = 0, - NFT_CHAIN_T_ROUTE, -@@ -1923,7 +1916,6 @@ struct nftables_pernet { - struct mutex commit_mutex; - u64 table_handle; - u64 tstamp; -- unsigned int base_seq; - unsigned int gc_seq; - u8 validate_state; - struct work_struct destroy_work; -diff -purNx .git BPI-Router-Linux-kernel/include/net/netns/nftables.h BPI-Router-Linux-kernel-6.16.12/include/net/netns/nftables.h ---- BPI-Router-Linux-kernel/include/net/netns/nftables.h 2025-10-22 13:53:23.571327421 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/netns/nftables.h 2025-10-22 13:53:56.759167965 -0400 -@@ -3,6 +3,7 @@ - #define _NETNS_NFTABLES_H_ - - struct netns_nftables { -+ unsigned int base_seq; - u8 gencursor; - }; - -diff -purNx .git BPI-Router-Linux-kernel/include/net/page_pool/types.h BPI-Router-Linux-kernel-6.16.12/include/net/page_pool/types.h ---- BPI-Router-Linux-kernel/include/net/page_pool/types.h 2025-10-22 13:53:23.571327421 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/page_pool/types.h 2025-10-22 13:53:56.759167965 -0400 -@@ -265,6 +265,8 @@ struct page_pool *page_pool_create_percp - struct xdp_mem_info; - - #ifdef CONFIG_PAGE_POOL -+void page_pool_enable_direct_recycling(struct page_pool *pool, -+ struct napi_struct *napi); - void page_pool_disable_direct_recycling(struct page_pool *pool); - void page_pool_destroy(struct page_pool *pool); - void page_pool_use_xdp_mem(struct page_pool *pool, void (*disconnect)(void *), -diff -purNx .git BPI-Router-Linux-kernel/include/net/pkt_sched.h BPI-Router-Linux-kernel-6.16.12/include/net/pkt_sched.h ---- BPI-Router-Linux-kernel/include/net/pkt_sched.h 2025-10-22 13:53:23.571327421 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/pkt_sched.h 2025-10-22 13:53:56.759167965 -0400 -@@ -114,7 +114,6 @@ struct qdisc_rate_table *qdisc_get_rtab( - struct netlink_ext_ack *extack); - void qdisc_put_rtab(struct qdisc_rate_table *tab); - void qdisc_put_stab(struct qdisc_size_table *tab); --void qdisc_warn_nonwc(const char *txt, struct Qdisc *qdisc); - bool sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q, - struct net_device *dev, struct netdev_queue *txq, - spinlock_t *root_lock, bool validate); -@@ -290,4 +289,28 @@ static inline bool tc_qdisc_stats_dump(s - return true; - } - -+static inline void qdisc_warn_nonwc(const char *txt, struct Qdisc *qdisc) -+{ -+ if (!(qdisc->flags & TCQ_F_WARN_NONWC)) { -+ pr_warn("%s: %s qdisc %X: is non-work-conserving?\n", -+ txt, qdisc->ops->id, qdisc->handle >> 16); -+ qdisc->flags |= TCQ_F_WARN_NONWC; -+ } -+} -+ -+static inline unsigned int qdisc_peek_len(struct Qdisc *sch) -+{ -+ struct sk_buff *skb; -+ unsigned int len; -+ -+ skb = sch->ops->peek(sch); -+ if (unlikely(skb == NULL)) { -+ qdisc_warn_nonwc("qdisc_peek_len", sch); -+ return 0; -+ } -+ len = qdisc_pkt_len(skb); -+ -+ return len; -+} -+ - #endif -diff -purNx .git BPI-Router-Linux-kernel/include/net/rose.h BPI-Router-Linux-kernel-6.16.12/include/net/rose.h ---- BPI-Router-Linux-kernel/include/net/rose.h 2025-10-22 13:53:23.571327421 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/rose.h 2025-10-22 13:53:56.759167965 -0400 -@@ -8,6 +8,7 @@ - #ifndef _ROSE_H - #define _ROSE_H - -+#include - #include - #include - #include -@@ -96,7 +97,7 @@ struct rose_neigh { - ax25_cb *ax25; - struct net_device *dev; - unsigned short count; -- unsigned short use; -+ refcount_t use; - unsigned int number; - char restarted; - char dce_mode; -@@ -151,6 +152,21 @@ struct rose_sock { - - #define rose_sk(sk) ((struct rose_sock *)(sk)) - -+static inline void rose_neigh_hold(struct rose_neigh *rose_neigh) -+{ -+ refcount_inc(&rose_neigh->use); -+} -+ -+static inline void rose_neigh_put(struct rose_neigh *rose_neigh) -+{ -+ if (refcount_dec_and_test(&rose_neigh->use)) { -+ if (rose_neigh->ax25) -+ ax25_cb_put(rose_neigh->ax25); -+ kfree(rose_neigh->digipeat); -+ kfree(rose_neigh); -+ } -+} -+ - /* af_rose.c */ - extern ax25_address rose_callsign; - extern int sysctl_rose_restart_request_timeout; -diff -purNx .git BPI-Router-Linux-kernel/include/net/route.h BPI-Router-Linux-kernel-6.16.12/include/net/route.h ---- BPI-Router-Linux-kernel/include/net/route.h 2025-10-22 13:53:23.571327421 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/route.h 2025-10-22 13:53:56.759167965 -0400 -@@ -153,7 +153,7 @@ static inline void inet_sk_init_flowi4(c - ip_sock_rt_tos(sk), ip_sock_rt_scope(sk), - sk->sk_protocol, inet_sk_flowi_flags(sk), daddr, - inet->inet_saddr, inet->inet_dport, -- inet->inet_sport, sk->sk_uid); -+ inet->inet_sport, sk_uid(sk)); - security_sk_classify_flow(sk, flowi4_to_flowi_common(fl4)); - } - -@@ -331,7 +331,7 @@ static inline void ip_route_connect_init - - flowi4_init_output(fl4, oif, READ_ONCE(sk->sk_mark), ip_sock_rt_tos(sk), - ip_sock_rt_scope(sk), protocol, flow_flags, dst, -- src, dport, sport, sk->sk_uid); -+ src, dport, sport, sk_uid(sk)); - } - - static inline struct rtable *ip_route_connect(struct flowi4 *fl4, __be32 dst, -diff -purNx .git BPI-Router-Linux-kernel/include/net/sch_generic.h BPI-Router-Linux-kernel-6.16.12/include/net/sch_generic.h ---- BPI-Router-Linux-kernel/include/net/sch_generic.h 2025-10-22 13:53:23.571327421 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/sch_generic.h 2025-10-22 13:53:56.759167965 -0400 -@@ -973,14 +973,6 @@ static inline void qdisc_qstats_qlen_bac - *backlog = qstats.backlog; - } - --static inline void qdisc_tree_flush_backlog(struct Qdisc *sch) --{ -- __u32 qlen, backlog; -- -- qdisc_qstats_qlen_backlog(sch, &qlen, &backlog); -- qdisc_tree_reduce_backlog(sch, qlen, backlog); --} -- - static inline void qdisc_purge_queue(struct Qdisc *sch) - { - __u32 qlen, backlog; -@@ -1046,12 +1038,17 @@ static inline struct sk_buff *qdisc_dequ - skb = __skb_dequeue(&sch->gso_skb); - if (skb) { - sch->q.qlen--; -+ qdisc_qstats_backlog_dec(sch, skb); - return skb; - } -- if (direct) -- return __qdisc_dequeue_head(&sch->q); -- else -+ if (direct) { -+ skb = __qdisc_dequeue_head(&sch->q); -+ if (skb) -+ qdisc_qstats_backlog_dec(sch, skb); -+ return skb; -+ } else { - return sch->dequeue(sch); -+ } - } - - static inline struct sk_buff *qdisc_dequeue_head(struct Qdisc *sch) -diff -purNx .git BPI-Router-Linux-kernel/include/net/sock.h BPI-Router-Linux-kernel-6.16.12/include/net/sock.h ---- BPI-Router-Linux-kernel/include/net/sock.h 2025-10-22 13:53:23.571327421 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/sock.h 2025-10-22 13:53:56.759167965 -0400 -@@ -285,6 +285,7 @@ struct sk_filter; - * @sk_ack_backlog: current listen backlog - * @sk_max_ack_backlog: listen backlog set in listen() - * @sk_uid: user id of owner -+ * @sk_ino: inode number (zero if orphaned) - * @sk_prefer_busy_poll: prefer busypolling over softirq processing - * @sk_busy_poll_budget: napi processing budget when busypolling - * @sk_priority: %SO_PRIORITY setting -@@ -518,6 +519,7 @@ struct sock { - u32 sk_ack_backlog; - u32 sk_max_ack_backlog; - kuid_t sk_uid; -+ unsigned long sk_ino; - spinlock_t sk_peer_lock; - int sk_bind_phc; - struct pid *sk_peer_pid; -@@ -2056,6 +2058,13 @@ static inline int sk_rx_queue_get(const - static inline void sk_set_socket(struct sock *sk, struct socket *sock) - { - sk->sk_socket = sock; -+ if (sock) { -+ WRITE_ONCE(sk->sk_uid, SOCK_INODE(sock)->i_uid); -+ WRITE_ONCE(sk->sk_ino, SOCK_INODE(sock)->i_ino); -+ } else { -+ /* Note: sk_uid is unchanged. */ -+ WRITE_ONCE(sk->sk_ino, 0); -+ } - } - - static inline wait_queue_head_t *sk_sleep(struct sock *sk) -@@ -2086,18 +2095,25 @@ static inline void sock_graft(struct soc - rcu_assign_pointer(sk->sk_wq, &parent->wq); - parent->sk = sk; - sk_set_socket(sk, parent); -- sk->sk_uid = SOCK_INODE(parent)->i_uid; - security_sock_graft(sk, parent); - write_unlock_bh(&sk->sk_callback_lock); - } - --kuid_t sock_i_uid(struct sock *sk); --unsigned long __sock_i_ino(struct sock *sk); --unsigned long sock_i_ino(struct sock *sk); -+static inline unsigned long sock_i_ino(const struct sock *sk) -+{ -+ /* Paired with WRITE_ONCE() in sock_graft() and sock_orphan() */ -+ return READ_ONCE(sk->sk_ino); -+} -+ -+static inline kuid_t sk_uid(const struct sock *sk) -+{ -+ /* Paired with WRITE_ONCE() in sockfs_setattr() */ -+ return READ_ONCE(sk->sk_uid); -+} - - static inline kuid_t sock_net_uid(const struct net *net, const struct sock *sk) - { -- return sk ? sk->sk_uid : make_kuid(net->user_ns, 0); -+ return sk ? sk_uid(sk) : make_kuid(net->user_ns, 0); - } - - static inline u32 net_tx_rndhash(void) -@@ -3010,8 +3026,11 @@ int sock_ioctl_inout(struct sock *sk, un - int sk_ioctl(struct sock *sk, unsigned int cmd, void __user *arg); - static inline bool sk_is_readable(struct sock *sk) - { -- if (sk->sk_prot->sock_is_readable) -- return sk->sk_prot->sock_is_readable(sk); -+ const struct proto *prot = READ_ONCE(sk->sk_prot); -+ -+ if (prot->sock_is_readable) -+ return prot->sock_is_readable(sk); -+ - return false; - } - #endif /* _SOCK_H */ -diff -purNx .git BPI-Router-Linux-kernel/include/net/tc_act/tc_ctinfo.h BPI-Router-Linux-kernel-6.16.12/include/net/tc_act/tc_ctinfo.h ---- BPI-Router-Linux-kernel/include/net/tc_act/tc_ctinfo.h 2025-10-22 13:53:23.571327421 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/tc_act/tc_ctinfo.h 2025-10-22 13:53:56.763167945 -0400 -@@ -18,9 +18,9 @@ struct tcf_ctinfo_params { - struct tcf_ctinfo { - struct tc_action common; - struct tcf_ctinfo_params __rcu *params; -- u64 stats_dscp_set; -- u64 stats_dscp_error; -- u64 stats_cpmark_set; -+ atomic64_t stats_dscp_set; -+ atomic64_t stats_dscp_error; -+ atomic64_t stats_cpmark_set; - }; - - enum { -diff -purNx .git BPI-Router-Linux-kernel/include/net/udp.h BPI-Router-Linux-kernel-6.16.12/include/net/udp.h ---- BPI-Router-Linux-kernel/include/net/udp.h 2025-10-22 13:53:23.571327421 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/udp.h 2025-10-22 13:53:56.763167945 -0400 -@@ -587,6 +587,16 @@ static inline struct sk_buff *udp_rcv_se - { - netdev_features_t features = NETIF_F_SG; - struct sk_buff *segs; -+ int drop_count; -+ -+ /* -+ * Segmentation in UDP receive path is only for UDP GRO, drop udp -+ * fragmentation offload (UFO) packets. -+ */ -+ if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP) { -+ drop_count = 1; -+ goto drop; -+ } - - /* Avoid csum recalculation by skb_segment unless userspace explicitly - * asks for the final checksum values -@@ -610,16 +620,18 @@ static inline struct sk_buff *udp_rcv_se - */ - segs = __skb_gso_segment(skb, features, false); - if (IS_ERR_OR_NULL(segs)) { -- int segs_nr = skb_shinfo(skb)->gso_segs; -- -- atomic_add(segs_nr, &sk->sk_drops); -- SNMP_ADD_STATS(__UDPX_MIB(sk, ipv4), UDP_MIB_INERRORS, segs_nr); -- kfree_skb(skb); -- return NULL; -+ drop_count = skb_shinfo(skb)->gso_segs; -+ goto drop; - } - - consume_skb(skb); - return segs; -+ -+drop: -+ atomic_add(drop_count, &sk->sk_drops); -+ SNMP_ADD_STATS(__UDPX_MIB(sk, ipv4), UDP_MIB_INERRORS, drop_count); -+ kfree_skb(skb); -+ return NULL; - } - - static inline void udp_post_segment_fix_csum(struct sk_buff *skb) -diff -purNx .git BPI-Router-Linux-kernel/include/net/xfrm.h BPI-Router-Linux-kernel-6.16.12/include/net/xfrm.h ---- BPI-Router-Linux-kernel/include/net/xfrm.h 2025-10-22 13:53:23.571327421 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/net/xfrm.h 2025-10-22 13:53:56.763167945 -0400 -@@ -441,7 +441,6 @@ int xfrm_input_register_afinfo(const str - int xfrm_input_unregister_afinfo(const struct xfrm_input_afinfo *afinfo); - - void xfrm_flush_gc(void); --void xfrm_state_delete_tunnel(struct xfrm_state *x); - - struct xfrm_type { - struct module *owner; -@@ -474,7 +473,7 @@ struct xfrm_type_offload { - - int xfrm_register_type_offload(const struct xfrm_type_offload *type, unsigned short family); - void xfrm_unregister_type_offload(const struct xfrm_type_offload *type, unsigned short family); --void xfrm_set_type_offload(struct xfrm_state *x); -+void xfrm_set_type_offload(struct xfrm_state *x, bool try_load); - static inline void xfrm_unset_type_offload(struct xfrm_state *x) - { - if (!x->type_offload) -@@ -916,7 +915,7 @@ static inline void xfrm_pols_put(struct - xfrm_pol_put(pols[i]); - } - --void __xfrm_state_destroy(struct xfrm_state *, bool); -+void __xfrm_state_destroy(struct xfrm_state *); - - static inline void __xfrm_state_put(struct xfrm_state *x) - { -@@ -926,13 +925,7 @@ static inline void __xfrm_state_put(stru - static inline void xfrm_state_put(struct xfrm_state *x) - { - if (refcount_dec_and_test(&x->refcnt)) -- __xfrm_state_destroy(x, false); --} -- --static inline void xfrm_state_put_sync(struct xfrm_state *x) --{ -- if (refcount_dec_and_test(&x->refcnt)) -- __xfrm_state_destroy(x, true); -+ __xfrm_state_destroy(x); - } - - static inline void xfrm_state_hold(struct xfrm_state *x) -@@ -1770,7 +1763,7 @@ struct xfrmk_spdinfo { - - struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq, u32 pcpu_num); - int xfrm_state_delete(struct xfrm_state *x); --int xfrm_state_flush(struct net *net, u8 proto, bool task_valid, bool sync); -+int xfrm_state_flush(struct net *net, u8 proto, bool task_valid); - int xfrm_dev_state_flush(struct net *net, struct net_device *dev, bool task_valid); - int xfrm_dev_policy_flush(struct net *net, struct net_device *dev, - bool task_valid); -diff -purNx .git BPI-Router-Linux-kernel/include/rdma/ib_verbs.h BPI-Router-Linux-kernel-6.16.12/include/rdma/ib_verbs.h ---- BPI-Router-Linux-kernel/include/rdma/ib_verbs.h 2025-10-22 13:53:23.571327421 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/rdma/ib_verbs.h 2025-10-22 13:53:56.763167945 -0400 -@@ -4794,11 +4794,17 @@ struct ib_ucontext *ib_uverbs_get_uconte - - #if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS) - int uverbs_destroy_def_handler(struct uverbs_attr_bundle *attrs); -+bool rdma_uattrs_has_raw_cap(const struct uverbs_attr_bundle *attrs); - #else - static inline int uverbs_destroy_def_handler(struct uverbs_attr_bundle *attrs) - { - return 0; - } -+static inline bool -+rdma_uattrs_has_raw_cap(const struct uverbs_attr_bundle *attrs) -+{ -+ return false; -+} - #endif - - struct net_device *rdma_alloc_netdev(struct ib_device *device, u32 port_num, -@@ -4855,6 +4861,12 @@ static inline int ibdev_to_node(struct i - bool rdma_dev_access_netns(const struct ib_device *device, - const struct net *net); - -+bool rdma_dev_has_raw_cap(const struct ib_device *dev); -+static inline struct net *rdma_dev_net(struct ib_device *device) -+{ -+ return read_pnet(&device->coredev.rdma_net); -+} -+ - #define IB_ROCE_UDP_ENCAP_VALID_PORT_MIN (0xC000) - #define IB_ROCE_UDP_ENCAP_VALID_PORT_MAX (0xFFFF) - #define IB_GRH_FLOWLABEL_MASK (0x000FFFFF) -diff -purNx .git BPI-Router-Linux-kernel/include/sound/cs35l56.h BPI-Router-Linux-kernel-6.16.12/include/sound/cs35l56.h ---- BPI-Router-Linux-kernel/include/sound/cs35l56.h 2025-10-22 13:53:23.571327421 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/sound/cs35l56.h 2025-10-22 13:53:56.763167945 -0400 -@@ -107,8 +107,8 @@ - #define CS35L56_DSP1_PMEM_5114 0x3804FE8 - - #define CS35L63_DSP1_FW_VER CS35L56_DSP1_FW_VER --#define CS35L63_DSP1_HALO_STATE 0x280396C --#define CS35L63_DSP1_PM_CUR_STATE 0x28042C8 -+#define CS35L63_DSP1_HALO_STATE 0x2803C04 -+#define CS35L63_DSP1_PM_CUR_STATE 0x2804518 - #define CS35L63_PROTECTION_STATUS 0x340009C - #define CS35L63_TRANSDUCER_ACTUAL_PS 0x34000F4 - #define CS35L63_MAIN_RENDER_USER_MUTE 0x3400020 -@@ -306,6 +306,7 @@ struct cs35l56_base { - struct gpio_desc *reset_gpio; - struct cs35l56_spi_payload *spi_payload_buf; - const struct cs35l56_fw_reg *fw_reg; -+ const struct cirrus_amp_cal_controls *calibration_controls; - }; - - static inline bool cs35l56_is_otp_register(unsigned int reg) -diff -purNx .git BPI-Router-Linux-kernel/include/sound/sdca_function.h BPI-Router-Linux-kernel-6.16.12/include/sound/sdca_function.h ---- BPI-Router-Linux-kernel/include/sound/sdca_function.h 2025-10-22 13:53:23.571327421 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/sound/sdca_function.h 2025-10-22 13:53:56.763167945 -0400 -@@ -16,6 +16,8 @@ struct device; - struct sdca_entity; - struct sdca_function_desc; - -+#define SDCA_NO_INTERRUPT -1 -+ - /* - * The addressing space for SDCA relies on 7 bits for Entities, so a - * maximum of 128 Entities per function can be represented. -diff -purNx .git BPI-Router-Linux-kernel/include/sound/sdca.h BPI-Router-Linux-kernel-6.16.12/include/sound/sdca.h ---- BPI-Router-Linux-kernel/include/sound/sdca.h 2025-10-22 13:53:23.571327421 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/sound/sdca.h 2025-10-22 13:53:56.763167945 -0400 -@@ -46,6 +46,7 @@ struct sdca_device_data { - - enum sdca_quirk { - SDCA_QUIRKS_RT712_VB, -+ SDCA_QUIRKS_SKIP_FUNC_TYPE_PATCHING, - }; - - #if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_SOC_SDCA) -diff -purNx .git BPI-Router-Linux-kernel/include/sound/tas2781-tlv.h BPI-Router-Linux-kernel-6.16.12/include/sound/tas2781-tlv.h ---- BPI-Router-Linux-kernel/include/sound/tas2781-tlv.h 2025-10-22 13:53:23.571327421 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/sound/tas2781-tlv.h 2025-10-22 13:53:56.763167945 -0400 -@@ -15,7 +15,7 @@ - #ifndef __TAS2781_TLV_H__ - #define __TAS2781_TLV_H__ - --static const __maybe_unused DECLARE_TLV_DB_SCALE(dvc_tlv, -10000, 100, 0); -+static const __maybe_unused DECLARE_TLV_DB_SCALE(dvc_tlv, -10000, 50, 0); - static const __maybe_unused DECLARE_TLV_DB_SCALE(amp_vol_tlv, 1100, 50, 0); - - #endif -diff -purNx .git BPI-Router-Linux-kernel/include/trace/events/btrfs.h BPI-Router-Linux-kernel-6.16.12/include/trace/events/btrfs.h ---- BPI-Router-Linux-kernel/include/trace/events/btrfs.h 2025-10-22 13:53:23.571327421 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/trace/events/btrfs.h 2025-10-22 13:53:56.763167945 -0400 -@@ -1095,7 +1095,7 @@ TRACE_EVENT(btrfs_cow_block, - TP_fast_assign_btrfs(root->fs_info, - __entry->root_objectid = btrfs_root_id(root); - __entry->buf_start = buf->start; -- __entry->refs = atomic_read(&buf->refs); -+ __entry->refs = refcount_read(&buf->refs); - __entry->cow_start = cow->start; - __entry->buf_level = btrfs_header_level(buf); - __entry->cow_level = btrfs_header_level(cow); -diff -purNx .git BPI-Router-Linux-kernel/include/trace/events/erofs.h BPI-Router-Linux-kernel-6.16.12/include/trace/events/erofs.h ---- BPI-Router-Linux-kernel/include/trace/events/erofs.h 2025-10-22 13:53:23.571327421 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/trace/events/erofs.h 2025-10-22 13:53:56.763167945 -0400 -@@ -211,24 +211,6 @@ TRACE_EVENT(erofs_map_blocks_exit, - show_mflags(__entry->mflags), __entry->ret) - ); - --TRACE_EVENT(erofs_destroy_inode, -- TP_PROTO(struct inode *inode), -- -- TP_ARGS(inode), -- -- TP_STRUCT__entry( -- __field( dev_t, dev ) -- __field( erofs_nid_t, nid ) -- ), -- -- TP_fast_assign( -- __entry->dev = inode->i_sb->s_dev; -- __entry->nid = EROFS_I(inode)->nid; -- ), -- -- TP_printk("dev = (%d,%d), nid = %llu", show_dev_nid(__entry)) --); -- - #endif /* _TRACE_EROFS_H */ - - /* This part must be outside protection */ -diff -purNx .git BPI-Router-Linux-kernel/include/trace/events/ext4.h BPI-Router-Linux-kernel-6.16.12/include/trace/events/ext4.h ---- BPI-Router-Linux-kernel/include/trace/events/ext4.h 2025-10-22 13:53:23.571327421 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/trace/events/ext4.h 2025-10-22 13:53:56.763167945 -0400 -@@ -482,16 +482,17 @@ TRACE_EVENT(ext4_writepages, - (unsigned long) __entry->writeback_index) - ); - --TRACE_EVENT(ext4_da_write_pages, -- TP_PROTO(struct inode *inode, pgoff_t first_page, -+TRACE_EVENT(ext4_da_write_folios_start, -+ TP_PROTO(struct inode *inode, loff_t start_pos, loff_t next_pos, - struct writeback_control *wbc), - -- TP_ARGS(inode, first_page, wbc), -+ TP_ARGS(inode, start_pos, next_pos, wbc), - - TP_STRUCT__entry( - __field( dev_t, dev ) - __field( ino_t, ino ) -- __field( pgoff_t, first_page ) -+ __field( loff_t, start_pos ) -+ __field( loff_t, next_pos ) - __field( long, nr_to_write ) - __field( int, sync_mode ) - ), -@@ -499,18 +500,48 @@ TRACE_EVENT(ext4_da_write_pages, - TP_fast_assign( - __entry->dev = inode->i_sb->s_dev; - __entry->ino = inode->i_ino; -- __entry->first_page = first_page; -+ __entry->start_pos = start_pos; -+ __entry->next_pos = next_pos; - __entry->nr_to_write = wbc->nr_to_write; - __entry->sync_mode = wbc->sync_mode; - ), - -- TP_printk("dev %d,%d ino %lu first_page %lu nr_to_write %ld " -- "sync_mode %d", -+ TP_printk("dev %d,%d ino %lu start_pos 0x%llx next_pos 0x%llx nr_to_write %ld sync_mode %d", - MAJOR(__entry->dev), MINOR(__entry->dev), -- (unsigned long) __entry->ino, __entry->first_page, -+ (unsigned long) __entry->ino, __entry->start_pos, __entry->next_pos, - __entry->nr_to_write, __entry->sync_mode) - ); - -+TRACE_EVENT(ext4_da_write_folios_end, -+ TP_PROTO(struct inode *inode, loff_t start_pos, loff_t next_pos, -+ struct writeback_control *wbc, int ret), -+ -+ TP_ARGS(inode, start_pos, next_pos, wbc, ret), -+ -+ TP_STRUCT__entry( -+ __field( dev_t, dev ) -+ __field( ino_t, ino ) -+ __field( loff_t, start_pos ) -+ __field( loff_t, next_pos ) -+ __field( long, nr_to_write ) -+ __field( int, ret ) -+ ), -+ -+ TP_fast_assign( -+ __entry->dev = inode->i_sb->s_dev; -+ __entry->ino = inode->i_ino; -+ __entry->start_pos = start_pos; -+ __entry->next_pos = next_pos; -+ __entry->nr_to_write = wbc->nr_to_write; -+ __entry->ret = ret; -+ ), -+ -+ TP_printk("dev %d,%d ino %lu start_pos 0x%llx next_pos 0x%llx nr_to_write %ld ret %d", -+ MAJOR(__entry->dev), MINOR(__entry->dev), -+ (unsigned long) __entry->ino, __entry->start_pos, __entry->next_pos, -+ __entry->nr_to_write, __entry->ret) -+); -+ - TRACE_EVENT(ext4_da_write_pages_extent, - TP_PROTO(struct inode *inode, struct ext4_map_blocks *map), - -diff -purNx .git BPI-Router-Linux-kernel/include/trace/events/netfs.h BPI-Router-Linux-kernel-6.16.12/include/trace/events/netfs.h ---- BPI-Router-Linux-kernel/include/trace/events/netfs.h 2025-10-22 13:53:23.571327421 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/trace/events/netfs.h 2025-10-22 13:53:56.763167945 -0400 -@@ -50,12 +50,15 @@ - - #define netfs_rreq_traces \ - EM(netfs_rreq_trace_assess, "ASSESS ") \ -- EM(netfs_rreq_trace_copy, "COPY ") \ - EM(netfs_rreq_trace_collect, "COLLECT") \ - EM(netfs_rreq_trace_complete, "COMPLET") \ -+ EM(netfs_rreq_trace_copy, "COPY ") \ - EM(netfs_rreq_trace_dirty, "DIRTY ") \ - EM(netfs_rreq_trace_done, "DONE ") \ -+ EM(netfs_rreq_trace_end_copy_to_cache, "END-C2C") \ - EM(netfs_rreq_trace_free, "FREE ") \ -+ EM(netfs_rreq_trace_ki_complete, "KI-CMPL") \ -+ EM(netfs_rreq_trace_recollect, "RECLLCT") \ - EM(netfs_rreq_trace_redirty, "REDIRTY") \ - EM(netfs_rreq_trace_resubmit, "RESUBMT") \ - EM(netfs_rreq_trace_set_abandon, "S-ABNDN") \ -@@ -63,13 +66,15 @@ - EM(netfs_rreq_trace_unlock, "UNLOCK ") \ - EM(netfs_rreq_trace_unlock_pgpriv2, "UNLCK-2") \ - EM(netfs_rreq_trace_unmark, "UNMARK ") \ -+ EM(netfs_rreq_trace_unpause, "UNPAUSE") \ - EM(netfs_rreq_trace_wait_ip, "WAIT-IP") \ -- EM(netfs_rreq_trace_wait_pause, "WT-PAUS") \ -- EM(netfs_rreq_trace_wait_queue, "WAIT-Q ") \ -+ EM(netfs_rreq_trace_wait_pause, "--PAUSED--") \ -+ EM(netfs_rreq_trace_wait_quiesce, "WAIT-QUIESCE") \ -+ EM(netfs_rreq_trace_waited_ip, "DONE-IP") \ -+ EM(netfs_rreq_trace_waited_pause, "--UNPAUSED--") \ -+ EM(netfs_rreq_trace_waited_quiesce, "DONE-QUIESCE") \ - EM(netfs_rreq_trace_wake_ip, "WAKE-IP") \ - EM(netfs_rreq_trace_wake_queue, "WAKE-Q ") \ -- EM(netfs_rreq_trace_woke_queue, "WOKE-Q ") \ -- EM(netfs_rreq_trace_unpause, "UNPAUSE") \ - E_(netfs_rreq_trace_write_done, "WR-DONE") - - #define netfs_sreq_sources \ -@@ -82,6 +87,7 @@ - E_(NETFS_WRITE_TO_CACHE, "WRIT") - - #define netfs_sreq_traces \ -+ EM(netfs_sreq_trace_abandoned, "ABNDN") \ - EM(netfs_sreq_trace_add_donations, "+DON ") \ - EM(netfs_sreq_trace_added, "ADD ") \ - EM(netfs_sreq_trace_cache_nowrite, "CA-NW") \ -@@ -89,6 +95,7 @@ - EM(netfs_sreq_trace_cache_write, "CA-WR") \ - EM(netfs_sreq_trace_cancel, "CANCL") \ - EM(netfs_sreq_trace_clear, "CLEAR") \ -+ EM(netfs_sreq_trace_consumed, "CONSM") \ - EM(netfs_sreq_trace_discard, "DSCRD") \ - EM(netfs_sreq_trace_donate_to_prev, "DON-P") \ - EM(netfs_sreq_trace_donate_to_next, "DON-N") \ -@@ -96,7 +103,12 @@ - EM(netfs_sreq_trace_fail, "FAIL ") \ - EM(netfs_sreq_trace_free, "FREE ") \ - EM(netfs_sreq_trace_hit_eof, "EOF ") \ -- EM(netfs_sreq_trace_io_progress, "IO ") \ -+ EM(netfs_sreq_trace_io_bad, "I-BAD") \ -+ EM(netfs_sreq_trace_io_malformed, "I-MLF") \ -+ EM(netfs_sreq_trace_io_unknown, "I-UNK") \ -+ EM(netfs_sreq_trace_io_progress, "I-OK ") \ -+ EM(netfs_sreq_trace_io_req_submitted, "I-RSB") \ -+ EM(netfs_sreq_trace_io_retry_needed, "I-RTR") \ - EM(netfs_sreq_trace_limited, "LIMIT") \ - EM(netfs_sreq_trace_need_clear, "N-CLR") \ - EM(netfs_sreq_trace_partial_read, "PARTR") \ -@@ -142,8 +154,8 @@ - - #define netfs_sreq_ref_traces \ - EM(netfs_sreq_trace_get_copy_to_cache, "GET COPY2C ") \ -- EM(netfs_sreq_trace_get_resubmit, "GET RESUBMIT") \ -- EM(netfs_sreq_trace_get_submit, "GET SUBMIT") \ -+ EM(netfs_sreq_trace_get_resubmit, "GET RESUBMT") \ -+ EM(netfs_sreq_trace_get_submit, "GET SUBMIT ") \ - EM(netfs_sreq_trace_get_short_read, "GET SHORTRD") \ - EM(netfs_sreq_trace_new, "NEW ") \ - EM(netfs_sreq_trace_put_abandon, "PUT ABANDON") \ -@@ -366,7 +378,7 @@ TRACE_EVENT(netfs_sreq, - __entry->slot = sreq->io_iter.folioq_slot; - ), - -- TP_printk("R=%08x[%x] %s %s f=%02x s=%llx %zx/%zx s=%u e=%d", -+ TP_printk("R=%08x[%x] %s %s f=%03x s=%llx %zx/%zx s=%u e=%d", - __entry->rreq, __entry->index, - __print_symbolic(__entry->source, netfs_sreq_sources), - __print_symbolic(__entry->what, netfs_sreq_traces), -@@ -548,6 +560,35 @@ TRACE_EVENT(netfs_write, - __entry->start, __entry->start + __entry->len - 1) - ); - -+TRACE_EVENT(netfs_copy2cache, -+ TP_PROTO(const struct netfs_io_request *rreq, -+ const struct netfs_io_request *creq), -+ -+ TP_ARGS(rreq, creq), -+ -+ TP_STRUCT__entry( -+ __field(unsigned int, rreq) -+ __field(unsigned int, creq) -+ __field(unsigned int, cookie) -+ __field(unsigned int, ino) -+ ), -+ -+ TP_fast_assign( -+ struct netfs_inode *__ctx = netfs_inode(rreq->inode); -+ struct fscache_cookie *__cookie = netfs_i_cookie(__ctx); -+ __entry->rreq = rreq->debug_id; -+ __entry->creq = creq->debug_id; -+ __entry->cookie = __cookie ? __cookie->debug_id : 0; -+ __entry->ino = rreq->inode->i_ino; -+ ), -+ -+ TP_printk("R=%08x CR=%08x c=%08x i=%x ", -+ __entry->rreq, -+ __entry->creq, -+ __entry->cookie, -+ __entry->ino) -+ ); -+ - TRACE_EVENT(netfs_collect, - TP_PROTO(const struct netfs_io_request *wreq), - -diff -purNx .git BPI-Router-Linux-kernel/include/trace/events/power.h BPI-Router-Linux-kernel-6.16.12/include/trace/events/power.h ---- BPI-Router-Linux-kernel/include/trace/events/power.h 2025-10-22 13:53:23.571327421 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/trace/events/power.h 2025-10-22 13:53:56.763167945 -0400 -@@ -99,28 +99,6 @@ DEFINE_EVENT(psci_domain_idle, psci_doma - TP_ARGS(cpu_id, state, s2idle) - ); - --TRACE_EVENT(powernv_throttle, -- -- TP_PROTO(int chip_id, const char *reason, int pmax), -- -- TP_ARGS(chip_id, reason, pmax), -- -- TP_STRUCT__entry( -- __field(int, chip_id) -- __string(reason, reason) -- __field(int, pmax) -- ), -- -- TP_fast_assign( -- __entry->chip_id = chip_id; -- __assign_str(reason); -- __entry->pmax = pmax; -- ), -- -- TP_printk("Chip %d Pmax %d %s", __entry->chip_id, -- __entry->pmax, __get_str(reason)) --); -- - TRACE_EVENT(pstate_sample, - - TP_PROTO(u32 core_busy, -diff -purNx .git BPI-Router-Linux-kernel/include/trace/events/rxrpc.h BPI-Router-Linux-kernel-6.16.12/include/trace/events/rxrpc.h ---- BPI-Router-Linux-kernel/include/trace/events/rxrpc.h 2025-10-22 13:53:23.575327401 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/trace/events/rxrpc.h 2025-10-22 13:53:56.763167945 -0400 -@@ -322,20 +322,24 @@ - EM(rxrpc_call_put_kernel, "PUT kernel ") \ - EM(rxrpc_call_put_poke, "PUT poke ") \ - EM(rxrpc_call_put_recvmsg, "PUT recvmsg ") \ -+ EM(rxrpc_call_put_release_recvmsg_q, "PUT rls-rcmq") \ - EM(rxrpc_call_put_release_sock, "PUT rls-sock") \ - EM(rxrpc_call_put_release_sock_tba, "PUT rls-sk-a") \ - EM(rxrpc_call_put_sendmsg, "PUT sendmsg ") \ -- EM(rxrpc_call_put_unnotify, "PUT unnotify") \ - EM(rxrpc_call_put_userid_exists, "PUT u-exists") \ - EM(rxrpc_call_put_userid, "PUT user-id ") \ - EM(rxrpc_call_see_accept, "SEE accept ") \ - EM(rxrpc_call_see_activate_client, "SEE act-clnt") \ -+ EM(rxrpc_call_see_already_released, "SEE alrdy-rl") \ - EM(rxrpc_call_see_connect_failed, "SEE con-fail") \ - EM(rxrpc_call_see_connected, "SEE connect ") \ - EM(rxrpc_call_see_conn_abort, "SEE conn-abt") \ -+ EM(rxrpc_call_see_discard, "SEE discard ") \ - EM(rxrpc_call_see_disconnected, "SEE disconn ") \ - EM(rxrpc_call_see_distribute_error, "SEE dist-err") \ - EM(rxrpc_call_see_input, "SEE input ") \ -+ EM(rxrpc_call_see_notify_released, "SEE nfy-rlsd") \ -+ EM(rxrpc_call_see_recvmsg, "SEE recvmsg ") \ - EM(rxrpc_call_see_release, "SEE release ") \ - EM(rxrpc_call_see_userid_exists, "SEE u-exists") \ - EM(rxrpc_call_see_waiting_call, "SEE q-conn ") \ -diff -purNx .git BPI-Router-Linux-kernel/include/trace/events/thp.h BPI-Router-Linux-kernel-6.16.12/include/trace/events/thp.h ---- BPI-Router-Linux-kernel/include/trace/events/thp.h 2025-10-22 13:53:23.575327401 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/trace/events/thp.h 2025-10-22 13:53:56.763167945 -0400 -@@ -8,6 +8,7 @@ - #include - #include - -+#ifdef CONFIG_PPC_BOOK3S_64 - DECLARE_EVENT_CLASS(hugepage_set, - - TP_PROTO(unsigned long addr, unsigned long pte), -@@ -66,6 +67,7 @@ DEFINE_EVENT(hugepage_update, hugepage_u - TP_PROTO(unsigned long addr, unsigned long pud, unsigned long clr, unsigned long set), - TP_ARGS(addr, pud, clr, set) - ); -+#endif /* CONFIG_PPC_BOOK3S_64 */ - - DECLARE_EVENT_CLASS(migration_pmd, - -diff -purNx .git BPI-Router-Linux-kernel/include/uapi/drm/panthor_drm.h BPI-Router-Linux-kernel-6.16.12/include/uapi/drm/panthor_drm.h ---- BPI-Router-Linux-kernel/include/uapi/drm/panthor_drm.h 2025-10-22 13:53:23.575327401 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/uapi/drm/panthor_drm.h 2025-10-22 13:53:56.763167945 -0400 -@@ -296,6 +296,9 @@ struct drm_panthor_gpu_info { - /** @as_present: Bitmask encoding the number of address-space exposed by the MMU. */ - __u32 as_present; - -+ /** @pad0: MBZ. */ -+ __u32 pad0; -+ - /** @shader_present: Bitmask encoding the shader cores exposed by the GPU. */ - __u64 shader_present; - -diff -purNx .git BPI-Router-Linux-kernel/include/uapi/drm/xe_drm.h BPI-Router-Linux-kernel-6.16.12/include/uapi/drm/xe_drm.h ---- BPI-Router-Linux-kernel/include/uapi/drm/xe_drm.h 2025-10-22 13:53:23.575327401 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/uapi/drm/xe_drm.h 2025-10-22 13:53:56.763167945 -0400 -@@ -925,9 +925,9 @@ struct drm_xe_gem_mmap_offset { - * - %DRM_XE_VM_CREATE_FLAG_LR_MODE - An LR, or Long Running VM accepts - * exec submissions to its exec_queues that don't have an upper time - * limit on the job execution time. But exec submissions to these -- * don't allow any of the flags DRM_XE_SYNC_FLAG_SYNCOBJ, -- * DRM_XE_SYNC_FLAG_TIMELINE_SYNCOBJ, DRM_XE_SYNC_FLAG_DMA_BUF, -- * used as out-syncobjs, that is, together with DRM_XE_SYNC_FLAG_SIGNAL. -+ * don't allow any of the sync types DRM_XE_SYNC_TYPE_SYNCOBJ, -+ * DRM_XE_SYNC_TYPE_TIMELINE_SYNCOBJ, used as out-syncobjs, that is, -+ * together with sync flag DRM_XE_SYNC_FLAG_SIGNAL. - * LR VMs can be created in recoverable page-fault mode using - * DRM_XE_VM_CREATE_FLAG_FAULT_MODE, if the device supports it. - * If that flag is omitted, the UMD can not rely on the slightly -@@ -1394,7 +1394,7 @@ struct drm_xe_sync { - - /** - * @timeline_value: Input for the timeline sync object. Needs to be -- * different than 0 when used with %DRM_XE_SYNC_FLAG_TIMELINE_SYNCOBJ. -+ * different than 0 when used with %DRM_XE_SYNC_TYPE_TIMELINE_SYNCOBJ. - */ - __u64 timeline_value; - -diff -purNx .git BPI-Router-Linux-kernel/include/uapi/linux/bits.h BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/bits.h ---- BPI-Router-Linux-kernel/include/uapi/linux/bits.h 2025-10-22 13:53:23.575327401 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/bits.h 2025-10-22 13:53:56.763167945 -0400 -@@ -4,9 +4,9 @@ - #ifndef _UAPI_LINUX_BITS_H - #define _UAPI_LINUX_BITS_H - --#define __GENMASK(h, l) (((~_UL(0)) << (l)) & (~_UL(0) >> (BITS_PER_LONG - 1 - (h)))) -+#define __GENMASK(h, l) (((~_UL(0)) << (l)) & (~_UL(0) >> (__BITS_PER_LONG - 1 - (h)))) - --#define __GENMASK_ULL(h, l) (((~_ULL(0)) << (l)) & (~_ULL(0) >> (BITS_PER_LONG_LONG - 1 - (h)))) -+#define __GENMASK_ULL(h, l) (((~_ULL(0)) << (l)) & (~_ULL(0) >> (__BITS_PER_LONG_LONG - 1 - (h)))) - - #define __GENMASK_U128(h, l) \ - ((_BIT128((h)) << 1) - (_BIT128(l))) -diff -purNx .git BPI-Router-Linux-kernel/include/uapi/linux/ethtool_netlink_generated.h BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/ethtool_netlink_generated.h ---- BPI-Router-Linux-kernel/include/uapi/linux/ethtool_netlink_generated.h 2025-10-22 13:53:23.575327401 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/ethtool_netlink_generated.h 2025-10-22 13:53:56.763167945 -0400 -@@ -6,8 +6,8 @@ - #ifndef _UAPI_LINUX_ETHTOOL_NETLINK_GENERATED_H - #define _UAPI_LINUX_ETHTOOL_NETLINK_GENERATED_H - --#define ETHTOOL_FAMILY_NAME "ethtool" --#define ETHTOOL_FAMILY_VERSION 1 -+#define ETHTOOL_GENL_NAME "ethtool" -+#define ETHTOOL_GENL_VERSION 1 - - enum { - ETHTOOL_UDP_TUNNEL_TYPE_VXLAN, -diff -purNx .git BPI-Router-Linux-kernel/include/uapi/linux/ethtool_netlink.h BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/ethtool_netlink.h ---- BPI-Router-Linux-kernel/include/uapi/linux/ethtool_netlink.h 2025-10-22 13:53:23.575327401 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/ethtool_netlink.h 2025-10-22 13:53:56.763167945 -0400 -@@ -208,10 +208,6 @@ enum { - ETHTOOL_A_STATS_PHY_MAX = (__ETHTOOL_A_STATS_PHY_CNT - 1) - }; - --/* generic netlink info */ --#define ETHTOOL_GENL_NAME "ethtool" --#define ETHTOOL_GENL_VERSION 1 -- - #define ETHTOOL_MCGRP_MONITOR_NAME "monitor" - - #endif /* _UAPI_LINUX_ETHTOOL_NETLINK_H_ */ -diff -purNx .git BPI-Router-Linux-kernel/include/uapi/linux/in6.h BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/in6.h ---- BPI-Router-Linux-kernel/include/uapi/linux/in6.h 2025-10-22 13:53:23.575327401 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/in6.h 2025-10-22 13:53:56.763167945 -0400 -@@ -152,7 +152,6 @@ struct in6_flowlabel_req { - /* - * IPV6 socket options - */ --#if __UAPI_DEF_IPV6_OPTIONS - #define IPV6_ADDRFORM 1 - #define IPV6_2292PKTINFO 2 - #define IPV6_2292HOPOPTS 3 -@@ -169,8 +168,10 @@ struct in6_flowlabel_req { - #define IPV6_MULTICAST_IF 17 - #define IPV6_MULTICAST_HOPS 18 - #define IPV6_MULTICAST_LOOP 19 -+#if __UAPI_DEF_IPV6_OPTIONS - #define IPV6_ADD_MEMBERSHIP 20 - #define IPV6_DROP_MEMBERSHIP 21 -+#endif - #define IPV6_ROUTER_ALERT 22 - #define IPV6_MTU_DISCOVER 23 - #define IPV6_MTU 24 -@@ -203,7 +204,6 @@ struct in6_flowlabel_req { - #define IPV6_IPSEC_POLICY 34 - #define IPV6_XFRM_POLICY 35 - #define IPV6_HDRINCL 36 --#endif - - /* - * Multicast: -diff -purNx .git BPI-Router-Linux-kernel/include/uapi/linux/io_uring.h BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/io_uring.h ---- BPI-Router-Linux-kernel/include/uapi/linux/io_uring.h 2025-10-22 13:53:23.575327401 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/io_uring.h 2025-10-22 13:53:56.763167945 -0400 -@@ -50,7 +50,7 @@ struct io_uring_sqe { - }; - __u32 len; /* buffer size or number of iovecs */ - union { -- __kernel_rwf_t rw_flags; -+ __u32 rw_flags; - __u32 fsync_flags; - __u16 poll_events; /* compatibility */ - __u32 poll32_events; /* word-reversed for BE */ -diff -purNx .git BPI-Router-Linux-kernel/include/uapi/linux/kvm.h BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/kvm.h ---- BPI-Router-Linux-kernel/include/uapi/linux/kvm.h 2025-10-22 13:53:23.575327401 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/kvm.h 2025-10-22 13:53:56.763167945 -0400 -@@ -178,6 +178,7 @@ struct kvm_xen_exit { - #define KVM_EXIT_NOTIFY 37 - #define KVM_EXIT_LOONGARCH_IOCSR 38 - #define KVM_EXIT_MEMORY_FAULT 39 -+#define KVM_EXIT_TDX 40 - - /* For KVM_EXIT_INTERNAL_ERROR */ - /* Emulate instruction failed. */ -@@ -447,6 +448,31 @@ struct kvm_run { - __u64 gpa; - __u64 size; - } memory_fault; -+ /* KVM_EXIT_TDX */ -+ struct { -+ __u64 flags; -+ __u64 nr; -+ union { -+ struct { -+ __u64 ret; -+ __u64 data[5]; -+ } unknown; -+ struct { -+ __u64 ret; -+ __u64 gpa; -+ __u64 size; -+ } get_quote; -+ struct { -+ __u64 ret; -+ __u64 leaf; -+ __u64 r11, r12, r13, r14; -+ } get_tdvmcall_info; -+ struct { -+ __u64 ret; -+ __u64 vector; -+ } setup_event_notify; -+ }; -+ } tdx; - /* Fix the size of the union. */ - char padding[256]; - }; -diff -purNx .git BPI-Router-Linux-kernel/include/uapi/linux/mptcp.h BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/mptcp.h ---- BPI-Router-Linux-kernel/include/uapi/linux/mptcp.h 2025-10-22 13:53:23.575327401 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/mptcp.h 2025-10-22 13:53:56.763167945 -0400 -@@ -31,6 +31,8 @@ - #define MPTCP_INFO_FLAG_FALLBACK _BITUL(0) - #define MPTCP_INFO_FLAG_REMOTE_KEY_RECEIVED _BITUL(1) - -+#define MPTCP_PM_EV_FLAG_DENY_JOIN_ID0 _BITUL(0) -+ - #define MPTCP_PM_ADDR_FLAG_SIGNAL (1 << 0) - #define MPTCP_PM_ADDR_FLAG_SUBFLOW (1 << 1) - #define MPTCP_PM_ADDR_FLAG_BACKUP (1 << 2) -diff -purNx .git BPI-Router-Linux-kernel/include/uapi/linux/mptcp_pm.h BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/mptcp_pm.h ---- BPI-Router-Linux-kernel/include/uapi/linux/mptcp_pm.h 2025-10-22 13:53:23.575327401 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/mptcp_pm.h 2025-10-22 13:53:56.763167945 -0400 -@@ -16,10 +16,10 @@ - * good time to allocate memory and send ADD_ADDR if needed. Depending on the - * traffic-patterns it can take a long time until the MPTCP_EVENT_ESTABLISHED - * is sent. Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6, -- * sport, dport, server-side. -+ * sport, dport, server-side, [flags]. - * @MPTCP_EVENT_ESTABLISHED: A MPTCP connection is established (can start new - * subflows). Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6, -- * sport, dport, server-side. -+ * sport, dport, server-side, [flags]. - * @MPTCP_EVENT_CLOSED: A MPTCP connection has stopped. Attribute: token. - * @MPTCP_EVENT_ANNOUNCED: A new address has been announced by the peer. - * Attributes: token, rem_id, family, daddr4 | daddr6 [, dport]. -@@ -27,14 +27,14 @@ - * token, rem_id. - * @MPTCP_EVENT_SUB_ESTABLISHED: A new subflow has been established. 'error' - * should not be set. Attributes: token, family, loc_id, rem_id, saddr4 | -- * saddr6, daddr4 | daddr6, sport, dport, backup, if_idx [, error]. -+ * saddr6, daddr4 | daddr6, sport, dport, backup, if-idx [, error]. - * @MPTCP_EVENT_SUB_CLOSED: A subflow has been closed. An error (copy of - * sk_err) could be set if an error has been detected for this subflow. - * Attributes: token, family, loc_id, rem_id, saddr4 | saddr6, daddr4 | -- * daddr6, sport, dport, backup, if_idx [, error]. -+ * daddr6, sport, dport, backup, if-idx [, error]. - * @MPTCP_EVENT_SUB_PRIORITY: The priority of a subflow has changed. 'error' - * should not be set. Attributes: token, family, loc_id, rem_id, saddr4 | -- * saddr6, daddr4 | daddr6, sport, dport, backup, if_idx [, error]. -+ * saddr6, daddr4 | daddr6, sport, dport, backup, if-idx [, error]. - * @MPTCP_EVENT_LISTENER_CREATED: A new PM listener is created. Attributes: - * family, sport, saddr4 | saddr6. - * @MPTCP_EVENT_LISTENER_CLOSED: A PM listener is closed. Attributes: family, -diff -purNx .git BPI-Router-Linux-kernel/include/uapi/linux/netfilter/nfnetlink.h BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/netfilter/nfnetlink.h ---- BPI-Router-Linux-kernel/include/uapi/linux/netfilter/nfnetlink.h 2025-10-22 13:53:23.575327401 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/netfilter/nfnetlink.h 2025-10-22 13:53:56.763167945 -0400 -@@ -25,8 +25,6 @@ enum nfnetlink_groups { - #define NFNLGRP_ACCT_QUOTA NFNLGRP_ACCT_QUOTA - NFNLGRP_NFTRACE, - #define NFNLGRP_NFTRACE NFNLGRP_NFTRACE -- NFNLGRP_NFT_DEV, --#define NFNLGRP_NFT_DEV NFNLGRP_NFT_DEV - __NFNLGRP_MAX, - }; - #define NFNLGRP_MAX (__NFNLGRP_MAX - 1) -diff -purNx .git BPI-Router-Linux-kernel/include/uapi/linux/netfilter/nf_tables.h BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/netfilter/nf_tables.h ---- BPI-Router-Linux-kernel/include/uapi/linux/netfilter/nf_tables.h 2025-10-22 13:53:23.575327401 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/netfilter/nf_tables.h 2025-10-22 13:53:56.763167945 -0400 -@@ -142,8 +142,6 @@ enum nf_tables_msg_types { - NFT_MSG_DESTROYOBJ, - NFT_MSG_DESTROYFLOWTABLE, - NFT_MSG_GETSETELEM_RESET, -- NFT_MSG_NEWDEV, -- NFT_MSG_DELDEV, - NFT_MSG_MAX, - }; - -@@ -1786,18 +1784,12 @@ enum nft_synproxy_attributes { - * enum nft_device_attributes - nf_tables device netlink attributes - * - * @NFTA_DEVICE_NAME: name of this device (NLA_STRING) -- * @NFTA_DEVICE_TABLE: table containing the flowtable or chain hooking into the device (NLA_STRING) -- * @NFTA_DEVICE_FLOWTABLE: flowtable hooking into the device (NLA_STRING) -- * @NFTA_DEVICE_CHAIN: chain hooking into the device (NLA_STRING) -- * @NFTA_DEVICE_SPEC: hook spec matching the device (NLA_STRING) -+ * @NFTA_DEVICE_PREFIX: device name prefix, a simple wildcard (NLA_STRING) - */ - enum nft_devices_attributes { - NFTA_DEVICE_UNSPEC, - NFTA_DEVICE_NAME, -- NFTA_DEVICE_TABLE, -- NFTA_DEVICE_FLOWTABLE, -- NFTA_DEVICE_CHAIN, -- NFTA_DEVICE_SPEC, -+ NFTA_DEVICE_PREFIX, - __NFTA_DEVICE_MAX - }; - #define NFTA_DEVICE_MAX (__NFTA_DEVICE_MAX - 1) -diff -purNx .git BPI-Router-Linux-kernel/include/uapi/linux/pfrut.h BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/pfrut.h ---- BPI-Router-Linux-kernel/include/uapi/linux/pfrut.h 2025-10-22 13:53:23.575327401 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/pfrut.h 2025-10-22 13:53:56.763167945 -0400 -@@ -89,6 +89,7 @@ struct pfru_payload_hdr { - __u32 hw_ver; - __u32 rt_ver; - __u8 platform_id[16]; -+ __u32 svn_ver; - }; - - enum pfru_dsm_status { -diff -purNx .git BPI-Router-Linux-kernel/include/uapi/linux/raid/md_p.h BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/raid/md_p.h ---- BPI-Router-Linux-kernel/include/uapi/linux/raid/md_p.h 2025-10-22 13:53:23.575327401 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/raid/md_p.h 2025-10-22 13:53:56.763167945 -0400 -@@ -173,7 +173,7 @@ typedef struct mdp_superblock_s { - #else - #error unspecified endianness - #endif -- __u32 recovery_cp; /* 11 recovery checkpoint sector count */ -+ __u32 recovery_cp; /* 11 resync checkpoint sector count */ - /* There are only valid for minor_version > 90 */ - __u64 reshape_position; /* 12,13 next address in array-space for reshape */ - __u32 new_level; /* 14 new level we are reshaping to */ -diff -purNx .git BPI-Router-Linux-kernel/include/uapi/linux/ublk_cmd.h BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/ublk_cmd.h ---- BPI-Router-Linux-kernel/include/uapi/linux/ublk_cmd.h 2025-10-22 13:53:23.575327401 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/ublk_cmd.h 2025-10-22 13:53:56.763167945 -0400 -@@ -135,8 +135,28 @@ - #define UBLKSRV_IO_BUF_TOTAL_SIZE (1ULL << UBLKSRV_IO_BUF_TOTAL_BITS) - - /* -- * zero copy requires 4k block size, and can remap ublk driver's io -- * request into ublksrv's vm space -+ * ublk server can register data buffers for incoming I/O requests with a sparse -+ * io_uring buffer table. The request buffer can then be used as the data buffer -+ * for io_uring operations via the fixed buffer index. -+ * Note that the ublk server can never directly access the request data memory. -+ * -+ * To use this feature, the ublk server must first register a sparse buffer -+ * table on an io_uring instance. -+ * When an incoming ublk request is received, the ublk server submits a -+ * UBLK_U_IO_REGISTER_IO_BUF command to that io_uring instance. The -+ * ublksrv_io_cmd's q_id and tag specify the request whose buffer to register -+ * and addr is the index in the io_uring's buffer table to install the buffer. -+ * SQEs can now be submitted to the io_uring to read/write the request's buffer -+ * by enabling fixed buffers (e.g. using IORING_OP_{READ,WRITE}_FIXED or -+ * IORING_URING_CMD_FIXED) and passing the registered buffer index in buf_index. -+ * Once the last io_uring operation using the request's buffer has completed, -+ * the ublk server submits a UBLK_U_IO_UNREGISTER_IO_BUF command with q_id, tag, -+ * and addr again specifying the request buffer to unregister. -+ * The ublk request is completed when its buffer is unregistered from all -+ * io_uring instances and the ublk server issues UBLK_U_IO_COMMIT_AND_FETCH_REQ. -+ * -+ * Not available for UBLK_F_UNPRIVILEGED_DEV, as a ublk server can leak -+ * uninitialized kernel memory by not reading into the full request buffer. - */ - #define UBLK_F_SUPPORT_ZERO_COPY (1ULL << 0) - -@@ -450,10 +470,10 @@ static inline struct ublk_auto_buf_reg u - __u64 sqe_addr) - { - struct ublk_auto_buf_reg reg = { -- .index = sqe_addr & 0xffff, -- .flags = (sqe_addr >> 16) & 0xff, -- .reserved0 = (sqe_addr >> 24) & 0xff, -- .reserved1 = sqe_addr >> 32, -+ .index = (__u16)sqe_addr, -+ .flags = (__u8)(sqe_addr >> 16), -+ .reserved0 = (__u8)(sqe_addr >> 24), -+ .reserved1 = (__u32)(sqe_addr >> 32), - }; - - return reg; -diff -purNx .git BPI-Router-Linux-kernel/include/uapi/linux/vfio.h BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/vfio.h ---- BPI-Router-Linux-kernel/include/uapi/linux/vfio.h 2025-10-22 13:53:23.575327401 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/vfio.h 2025-10-22 13:53:56.763167945 -0400 -@@ -905,10 +905,12 @@ struct vfio_device_feature { - * VFIO_DEVICE_BIND_IOMMUFD - _IOR(VFIO_TYPE, VFIO_BASE + 18, - * struct vfio_device_bind_iommufd) - * @argsz: User filled size of this data. -- * @flags: Must be 0. -+ * @flags: Must be 0 or a bit flags of VFIO_DEVICE_BIND_* - * @iommufd: iommufd to bind. - * @out_devid: The device id generated by this bind. devid is a handle for - * this device/iommufd bond and can be used in IOMMUFD commands. -+ * @token_uuid_ptr: Valid if VFIO_DEVICE_BIND_FLAG_TOKEN. Points to a 16 byte -+ * UUID in the same format as VFIO_DEVICE_FEATURE_PCI_VF_TOKEN. - * - * Bind a vfio_device to the specified iommufd. - * -@@ -917,13 +919,21 @@ struct vfio_device_feature { - * - * Unbind is automatically conducted when device fd is closed. - * -+ * A token is sometimes required to open the device, unless this is known to be -+ * needed VFIO_DEVICE_BIND_FLAG_TOKEN should not be set and token_uuid_ptr is -+ * ignored. The only case today is a PF/VF relationship where the VF bind must -+ * be provided the same token as VFIO_DEVICE_FEATURE_PCI_VF_TOKEN provided to -+ * the PF. -+ * - * Return: 0 on success, -errno on failure. - */ - struct vfio_device_bind_iommufd { - __u32 argsz; - __u32 flags; -+#define VFIO_DEVICE_BIND_FLAG_TOKEN (1 << 0) - __s32 iommufd; - __u32 out_devid; -+ __aligned_u64 token_uuid_ptr; - }; - - #define VFIO_DEVICE_BIND_IOMMUFD _IO(VFIO_TYPE, VFIO_BASE + 18) -diff -purNx .git BPI-Router-Linux-kernel/include/uapi/linux/vhost.h BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/vhost.h ---- BPI-Router-Linux-kernel/include/uapi/linux/vhost.h 2025-10-22 13:53:23.575327401 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/vhost.h 2025-10-22 13:53:56.763167945 -0400 -@@ -235,4 +235,33 @@ - */ - #define VHOST_VDPA_GET_VRING_SIZE _IOWR(VHOST_VIRTIO, 0x82, \ - struct vhost_vring_state) -+ -+/* fork_owner values for vhost */ -+#define VHOST_FORK_OWNER_KTHREAD 0 -+#define VHOST_FORK_OWNER_TASK 1 -+ -+/** -+ * VHOST_SET_FORK_FROM_OWNER - Set the fork_owner flag for the vhost device, -+ * This ioctl must called before VHOST_SET_OWNER. -+ * Only available when CONFIG_VHOST_ENABLE_FORK_OWNER_CONTROL=y -+ * -+ * @param fork_owner: An 8-bit value that determines the vhost thread mode -+ * -+ * When fork_owner is set to VHOST_FORK_OWNER_TASK(default value): -+ * - Vhost will create vhost worker as tasks forked from the owner, -+ * inheriting all of the owner's attributes. -+ * -+ * When fork_owner is set to VHOST_FORK_OWNER_KTHREAD: -+ * - Vhost will create vhost workers as kernel threads. -+ */ -+#define VHOST_SET_FORK_FROM_OWNER _IOW(VHOST_VIRTIO, 0x84, __u8) -+ -+/** -+ * VHOST_GET_FORK_OWNER - Get the current fork_owner flag for the vhost device. -+ * Only available when CONFIG_VHOST_ENABLE_FORK_OWNER_CONTROL=y -+ * -+ * @return: An 8-bit value indicating the current thread mode. -+ */ -+#define VHOST_GET_FORK_FROM_OWNER _IOR(VHOST_VIRTIO, 0x85, __u8) -+ - #endif -diff -purNx .git BPI-Router-Linux-kernel/include/uapi/linux/vm_sockets.h BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/vm_sockets.h ---- BPI-Router-Linux-kernel/include/uapi/linux/vm_sockets.h 2025-10-22 13:53:23.575327401 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/include/uapi/linux/vm_sockets.h 2025-10-22 13:53:56.763167945 -0400 -@@ -17,6 +17,10 @@ - #ifndef _UAPI_VM_SOCKETS_H - #define _UAPI_VM_SOCKETS_H - -+#ifndef __KERNEL__ -+#include /* for struct sockaddr and sa_family_t */ -+#endif -+ - #include - #include - -diff -purNx .git BPI-Router-Linux-kernel/init/initramfs.c BPI-Router-Linux-kernel-6.16.12/init/initramfs.c ---- BPI-Router-Linux-kernel/init/initramfs.c 2025-10-22 13:53:23.579327383 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/init/initramfs.c 2025-10-22 13:53:56.767167926 -0400 -@@ -1,6 +1,7 @@ - // SPDX-License-Identifier: GPL-2.0 - #include - #include -+#include - #include - #include - #include -diff -purNx .git BPI-Router-Linux-kernel/init/Kconfig BPI-Router-Linux-kernel-6.16.12/init/Kconfig ---- BPI-Router-Linux-kernel/init/Kconfig 2025-10-22 13:53:23.579327383 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/init/Kconfig 2025-10-22 13:53:56.767167926 -0400 -@@ -1716,9 +1716,13 @@ config FUTEX_PI - depends on FUTEX && RT_MUTEXES - default y - -+# -+# marked broken for performance reasons; gives us one more cycle to sort things out. -+# - config FUTEX_PRIVATE_HASH - bool - depends on FUTEX && !BASE_SMALL && MMU -+ depends on BROKEN - default y - - config FUTEX_MPOL -@@ -1790,7 +1794,7 @@ config IO_URING - - config GCOV_PROFILE_URING - bool "Enable GCOV profiling on the io_uring subsystem" -- depends on GCOV_KERNEL -+ depends on IO_URING && GCOV_KERNEL - help - Enable GCOV profiling on the io_uring subsystem, to facilitate - code coverage testing. -diff -purNx .git BPI-Router-Linux-kernel/init/main.c BPI-Router-Linux-kernel-6.16.12/init/main.c ---- BPI-Router-Linux-kernel/init/main.c 2025-10-22 13:53:23.579327383 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/init/main.c 2025-10-22 13:53:56.767167926 -0400 -@@ -13,6 +13,7 @@ - #define DEBUG /* Enable initcall_debug */ - - #include -+#include - #include - #include - #include -diff -purNx .git BPI-Router-Linux-kernel/io_uring/fdinfo.c BPI-Router-Linux-kernel-6.16.12/io_uring/fdinfo.c ---- BPI-Router-Linux-kernel/io_uring/fdinfo.c 2025-10-22 13:53:23.579327383 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/io_uring/fdinfo.c 2025-10-22 13:53:56.767167926 -0400 -@@ -141,18 +141,26 @@ static void __io_uring_show_fdinfo(struc - - if (ctx->flags & IORING_SETUP_SQPOLL) { - struct io_sq_data *sq = ctx->sq_data; -+ struct task_struct *tsk; - -+ rcu_read_lock(); -+ tsk = rcu_dereference(sq->thread); - /* - * sq->thread might be NULL if we raced with the sqpoll - * thread termination. - */ -- if (sq->thread) { -+ if (tsk) { -+ get_task_struct(tsk); -+ rcu_read_unlock(); -+ getrusage(tsk, RUSAGE_SELF, &sq_usage); -+ put_task_struct(tsk); - sq_pid = sq->task_pid; - sq_cpu = sq->sq_cpu; -- getrusage(sq->thread, RUSAGE_SELF, &sq_usage); - sq_total_time = (sq_usage.ru_stime.tv_sec * 1000000 - + sq_usage.ru_stime.tv_usec); - sq_work_time = sq->work_time; -+ } else { -+ rcu_read_unlock(); - } - } - -diff -purNx .git BPI-Router-Linux-kernel/io_uring/futex.c BPI-Router-Linux-kernel-6.16.12/io_uring/futex.c ---- BPI-Router-Linux-kernel/io_uring/futex.c 2025-10-22 13:53:23.579327383 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/io_uring/futex.c 2025-10-22 13:53:56.767167926 -0400 -@@ -288,6 +288,7 @@ int io_futex_wait(struct io_kiocb *req, - goto done_unlock; - } - -+ req->flags |= REQ_F_ASYNC_DATA; - req->async_data = ifd; - ifd->q = futex_q_init; - ifd->q.bitset = iof->futex_mask; -@@ -309,6 +310,8 @@ done: - if (ret < 0) - req_set_fail(req); - io_req_set_res(req, ret, 0); -+ req->async_data = NULL; -+ req->flags &= ~REQ_F_ASYNC_DATA; - kfree(ifd); - return IOU_COMPLETE; - } -diff -purNx .git BPI-Router-Linux-kernel/io_uring/io_uring.c BPI-Router-Linux-kernel-6.16.12/io_uring/io_uring.c ---- BPI-Router-Linux-kernel/io_uring/io_uring.c 2025-10-22 13:53:23.579327383 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/io_uring/io_uring.c 2025-10-22 13:53:56.767167926 -0400 -@@ -290,7 +290,6 @@ static void io_free_alloc_caches(struct - io_alloc_cache_free(&ctx->netmsg_cache, io_netmsg_cache_free); - io_alloc_cache_free(&ctx->rw_cache, io_rw_cache_free); - io_alloc_cache_free(&ctx->cmd_cache, io_cmd_cache_free); -- io_alloc_cache_free(&ctx->msg_cache, kfree); - io_futex_cache_free(ctx); - io_rsrc_cache_free(ctx); - } -@@ -337,9 +336,6 @@ static __cold struct io_ring_ctx *io_rin - ret |= io_alloc_cache_init(&ctx->cmd_cache, IO_ALLOC_CACHE_MAX, - sizeof(struct io_async_cmd), - sizeof(struct io_async_cmd)); -- spin_lock_init(&ctx->msg_lock); -- ret |= io_alloc_cache_init(&ctx->msg_cache, IO_ALLOC_CACHE_MAX, -- sizeof(struct io_kiocb), 0); - ret |= io_futex_cache_init(ctx); - ret |= io_rsrc_cache_init(ctx); - if (ret) -@@ -1371,8 +1367,10 @@ static void io_req_task_cancel(struct io - - void io_req_task_submit(struct io_kiocb *req, io_tw_token_t tw) - { -- io_tw_lock(req->ctx, tw); -- if (unlikely(io_should_terminate_tw())) -+ struct io_ring_ctx *ctx = req->ctx; -+ -+ io_tw_lock(ctx, tw); -+ if (unlikely(io_should_terminate_tw(ctx))) - io_req_defer_failed(req, -EFAULT); - else if (req->flags & REQ_F_FORCE_ASYNC) - io_queue_iowq(req); -@@ -1523,6 +1521,9 @@ static __cold void io_iopoll_try_reap_ev - } - } - mutex_unlock(&ctx->uring_lock); -+ -+ if (ctx->flags & IORING_SETUP_DEFER_TASKRUN) -+ io_move_task_work_from_local(ctx); - } - - static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned int min_events) -@@ -2906,7 +2907,7 @@ static __cold void io_ring_exit_work(str - struct task_struct *tsk; - - io_sq_thread_park(sqd); -- tsk = sqd->thread; -+ tsk = sqpoll_task_locked(sqd); - if (tsk && tsk->io_uring && tsk->io_uring->io_wq) - io_wq_cancel_cb(tsk->io_uring->io_wq, - io_cancel_ctx_cb, ctx, true); -@@ -3142,7 +3143,7 @@ __cold void io_uring_cancel_generic(bool - s64 inflight; - DEFINE_WAIT(wait); - -- WARN_ON_ONCE(sqd && sqd->thread != current); -+ WARN_ON_ONCE(sqd && sqpoll_task_locked(sqd) != current); - - if (!current->io_uring) - return; -diff -purNx .git BPI-Router-Linux-kernel/io_uring/io_uring.h BPI-Router-Linux-kernel-6.16.12/io_uring/io_uring.h ---- BPI-Router-Linux-kernel/io_uring/io_uring.h 2025-10-22 13:53:23.579327383 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/io_uring/io_uring.h 2025-10-22 13:53:56.767167926 -0400 -@@ -98,8 +98,6 @@ struct llist_node *io_handle_tw_list(str - struct llist_node *tctx_task_work_run(struct io_uring_task *tctx, unsigned int max_entries, unsigned int *count); - void tctx_task_work(struct callback_head *cb); - __cold void io_uring_cancel_generic(bool cancel_all, struct io_sq_data *sqd); --int io_uring_alloc_task_context(struct task_struct *task, -- struct io_ring_ctx *ctx); - - int io_ring_add_registered_file(struct io_uring_task *tctx, struct file *file, - int start, int end); -@@ -472,9 +470,9 @@ static inline bool io_allowed_run_tw(str - * 2) PF_KTHREAD is set, in which case the invoker of the task_work is - * our fallback task_work. - */ --static inline bool io_should_terminate_tw(void) -+static inline bool io_should_terminate_tw(struct io_ring_ctx *ctx) - { -- return current->flags & (PF_KTHREAD | PF_EXITING); -+ return (current->flags & (PF_KTHREAD | PF_EXITING)) || percpu_ref_is_dying(&ctx->refs); - } - - static inline void io_req_queue_tw_complete(struct io_kiocb *req, s32 res) -diff -purNx .git BPI-Router-Linux-kernel/io_uring/io-wq.c BPI-Router-Linux-kernel-6.16.12/io_uring/io-wq.c ---- BPI-Router-Linux-kernel/io_uring/io-wq.c 2025-10-22 13:53:23.579327383 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/io_uring/io-wq.c 2025-10-22 13:53:56.767167926 -0400 -@@ -352,11 +352,18 @@ static void create_worker_cb(struct call - struct io_wq *wq; - - struct io_wq_acct *acct; -- bool do_create = false; -+ bool activated_free_worker, do_create = false; - - worker = container_of(cb, struct io_worker, create_work); - wq = worker->wq; - acct = worker->acct; -+ -+ rcu_read_lock(); -+ activated_free_worker = io_acct_activate_free_worker(acct); -+ rcu_read_unlock(); -+ if (activated_free_worker) -+ goto no_need_create; -+ - raw_spin_lock(&acct->workers_lock); - - if (acct->nr_workers < acct->max_workers) { -@@ -367,6 +374,7 @@ static void create_worker_cb(struct call - if (do_create) { - create_io_worker(wq, acct); - } else { -+no_need_create: - atomic_dec(&acct->nr_running); - io_worker_ref_put(wq); - } -@@ -1259,8 +1267,10 @@ struct io_wq *io_wq_create(unsigned boun - atomic_set(&wq->worker_refs, 1); - init_completion(&wq->worker_done); - ret = cpuhp_state_add_instance_nocalls(io_wq_online, &wq->cpuhp_node); -- if (ret) -+ if (ret) { -+ put_task_struct(wq->task); - goto err; -+ } - - return wq; - err: -diff -purNx .git BPI-Router-Linux-kernel/io_uring/kbuf.c BPI-Router-Linux-kernel-6.16.12/io_uring/kbuf.c ---- BPI-Router-Linux-kernel/io_uring/kbuf.c 2025-10-22 13:53:23.579327383 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/io_uring/kbuf.c 2025-10-22 13:53:56.767167926 -0400 -@@ -36,15 +36,19 @@ static bool io_kbuf_inc_commit(struct io - { - while (len) { - struct io_uring_buf *buf; -- u32 this_len; -+ u32 buf_len, this_len; - - buf = io_ring_head_to_buf(bl->buf_ring, bl->head, bl->mask); -- this_len = min_t(int, len, buf->len); -- buf->len -= this_len; -- if (buf->len) { -+ buf_len = READ_ONCE(buf->len); -+ this_len = min_t(u32, len, buf_len); -+ buf_len -= this_len; -+ /* Stop looping for invalid buffer length of 0 */ -+ if (buf_len || !this_len) { - buf->addr += this_len; -+ buf->len = buf_len; - return false; - } -+ buf->len = 0; - bl->head++; - len -= this_len; - } -@@ -159,6 +163,7 @@ static void __user *io_ring_buffer_selec - __u16 tail, head = bl->head; - struct io_uring_buf *buf; - void __user *ret; -+ u32 buf_len; - - tail = smp_load_acquire(&br->tail); - if (unlikely(tail == head)) -@@ -168,8 +173,9 @@ static void __user *io_ring_buffer_selec - req->flags |= REQ_F_BL_EMPTY; - - buf = io_ring_head_to_buf(br, head, bl->mask); -- if (*len == 0 || *len > buf->len) -- *len = buf->len; -+ buf_len = READ_ONCE(buf->len); -+ if (*len == 0 || *len > buf_len) -+ *len = buf_len; - req->flags |= REQ_F_BUFFER_RING | REQ_F_BUFFERS_COMMIT; - req->buf_list = bl; - req->buf_index = buf->bid; -@@ -265,13 +271,17 @@ static int io_ring_buffers_peek(struct i - - req->buf_index = buf->bid; - do { -- u32 len = buf->len; -+ u32 len = READ_ONCE(buf->len); - - /* truncate end piece, if needed, for non partial buffers */ - if (len > arg->max_len) { - len = arg->max_len; -- if (!(bl->flags & IOBL_INC)) -+ if (!(bl->flags & IOBL_INC)) { -+ arg->partial_map = 1; -+ if (iov != arg->iovs) -+ break; - buf->len = len; -+ } - } - - iov->iov_base = u64_to_user_ptr(buf->addr); -diff -purNx .git BPI-Router-Linux-kernel/io_uring/kbuf.h BPI-Router-Linux-kernel-6.16.12/io_uring/kbuf.h ---- BPI-Router-Linux-kernel/io_uring/kbuf.h 2025-10-22 13:53:23.579327383 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/io_uring/kbuf.h 2025-10-22 13:53:56.767167926 -0400 -@@ -58,7 +58,8 @@ struct buf_sel_arg { - size_t max_len; - unsigned short nr_iovs; - unsigned short mode; -- unsigned buf_group; -+ unsigned short buf_group; -+ unsigned short partial_map; - }; - - void __user *io_buffer_select(struct io_kiocb *req, size_t *len, -diff -purNx .git BPI-Router-Linux-kernel/io_uring/memmap.c BPI-Router-Linux-kernel-6.16.12/io_uring/memmap.c ---- BPI-Router-Linux-kernel/io_uring/memmap.c 2025-10-22 13:53:23.579327383 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/io_uring/memmap.c 2025-10-22 13:53:56.767167926 -0400 -@@ -156,7 +156,7 @@ static int io_region_allocate_pages(stru - unsigned long mmap_offset) - { - gfp_t gfp = GFP_KERNEL_ACCOUNT | __GFP_ZERO | __GFP_NOWARN; -- unsigned long size = mr->nr_pages << PAGE_SHIFT; -+ size_t size = (size_t) mr->nr_pages << PAGE_SHIFT; - unsigned long nr_allocated; - struct page **pages; - void *p; -diff -purNx .git BPI-Router-Linux-kernel/io_uring/msg_ring.c BPI-Router-Linux-kernel-6.16.12/io_uring/msg_ring.c ---- BPI-Router-Linux-kernel/io_uring/msg_ring.c 2025-10-22 13:53:23.579327383 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/io_uring/msg_ring.c 2025-10-22 13:53:56.767167926 -0400 -@@ -11,7 +11,6 @@ - #include "io_uring.h" - #include "rsrc.h" - #include "filetable.h" --#include "alloc_cache.h" - #include "msg_ring.h" - - /* All valid masks for MSG_RING */ -@@ -76,13 +75,7 @@ static void io_msg_tw_complete(struct io - struct io_ring_ctx *ctx = req->ctx; - - io_add_aux_cqe(ctx, req->cqe.user_data, req->cqe.res, req->cqe.flags); -- if (spin_trylock(&ctx->msg_lock)) { -- if (io_alloc_cache_put(&ctx->msg_cache, req)) -- req = NULL; -- spin_unlock(&ctx->msg_lock); -- } -- if (req) -- kmem_cache_free(req_cachep, req); -+ kfree_rcu(req, rcu_head); - percpu_ref_put(&ctx->refs); - } - -@@ -90,7 +83,7 @@ static int io_msg_remote_post(struct io_ - int res, u32 cflags, u64 user_data) - { - if (!READ_ONCE(ctx->submitter_task)) { -- kmem_cache_free(req_cachep, req); -+ kfree_rcu(req, rcu_head); - return -EOWNERDEAD; - } - req->opcode = IORING_OP_NOP; -@@ -104,26 +97,13 @@ static int io_msg_remote_post(struct io_ - return 0; - } - --static struct io_kiocb *io_msg_get_kiocb(struct io_ring_ctx *ctx) --{ -- struct io_kiocb *req = NULL; -- -- if (spin_trylock(&ctx->msg_lock)) { -- req = io_alloc_cache_get(&ctx->msg_cache); -- spin_unlock(&ctx->msg_lock); -- if (req) -- return req; -- } -- return kmem_cache_alloc(req_cachep, GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO); --} -- - static int io_msg_data_remote(struct io_ring_ctx *target_ctx, - struct io_msg *msg) - { - struct io_kiocb *target; - u32 flags = 0; - -- target = io_msg_get_kiocb(target_ctx); -+ target = kmem_cache_alloc(req_cachep, GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO) ; - if (unlikely(!target)) - return -ENOMEM; - -diff -purNx .git BPI-Router-Linux-kernel/io_uring/net.c BPI-Router-Linux-kernel-6.16.12/io_uring/net.c ---- BPI-Router-Linux-kernel/io_uring/net.c 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/io_uring/net.c 2025-10-22 13:53:56.767167926 -0400 -@@ -75,12 +75,17 @@ struct io_sr_msg { - u16 flags; - /* initialised and used only by !msg send variants */ - u16 buf_group; -- bool retry; -+ unsigned short retry_flags; - void __user *msg_control; - /* used only for send zerocopy */ - struct io_kiocb *notif; - }; - -+enum sr_retry_flags { -+ IO_SR_MSG_RETRY = 1, -+ IO_SR_MSG_PARTIAL_MAP = 2, -+}; -+ - /* - * Number of times we'll try and do receives if there's more data. If we - * exceed this limit, then add us to the back of the queue and retry from -@@ -187,7 +192,7 @@ static inline void io_mshot_prep_retry(s - - req->flags &= ~REQ_F_BL_EMPTY; - sr->done_io = 0; -- sr->retry = false; -+ sr->retry_flags = 0; - sr->len = 0; /* get from the provided buffer */ - } - -@@ -397,7 +402,7 @@ int io_sendmsg_prep(struct io_kiocb *req - struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg); - - sr->done_io = 0; -- sr->retry = false; -+ sr->retry_flags = 0; - sr->len = READ_ONCE(sqe->len); - sr->flags = READ_ONCE(sqe->ioprio); - if (sr->flags & ~SENDMSG_FLAGS) -@@ -472,6 +477,15 @@ static int io_bundle_nbufs(struct io_asy - return nbufs; - } - -+static int io_net_kbuf_recyle(struct io_kiocb *req, -+ struct io_async_msghdr *kmsg, int len) -+{ -+ req->flags |= REQ_F_BL_NO_RECYCLE; -+ if (req->flags & REQ_F_BUFFERS_COMMIT) -+ io_kbuf_commit(req, req->buf_list, len, io_bundle_nbufs(kmsg, len)); -+ return IOU_RETRY; -+} -+ - static inline bool io_send_finish(struct io_kiocb *req, int *ret, - struct io_async_msghdr *kmsg, - unsigned issue_flags) -@@ -540,8 +554,7 @@ int io_sendmsg(struct io_kiocb *req, uns - kmsg->msg.msg_controllen = 0; - kmsg->msg.msg_control = NULL; - sr->done_io += ret; -- req->flags |= REQ_F_BL_NO_RECYCLE; -- return -EAGAIN; -+ return io_net_kbuf_recyle(req, kmsg, ret); - } - if (ret == -ERESTARTSYS) - ret = -EINTR; -@@ -652,8 +665,7 @@ retry_bundle: - sr->len -= ret; - sr->buf += ret; - sr->done_io += ret; -- req->flags |= REQ_F_BL_NO_RECYCLE; -- return -EAGAIN; -+ return io_net_kbuf_recyle(req, kmsg, ret); - } - if (ret == -ERESTARTSYS) - ret = -EINTR; -@@ -751,7 +763,7 @@ int io_recvmsg_prep(struct io_kiocb *req - struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg); - - sr->done_io = 0; -- sr->retry = false; -+ sr->retry_flags = 0; - - if (unlikely(sqe->file_index || sqe->addr2)) - return -EINVAL; -@@ -821,9 +833,9 @@ static inline bool io_recv_finish(struct - if (sr->flags & IORING_RECVSEND_BUNDLE) { - size_t this_ret = *ret - sr->done_io; - -- cflags |= io_put_kbufs(req, *ret, io_bundle_nbufs(kmsg, this_ret), -+ cflags |= io_put_kbufs(req, this_ret, io_bundle_nbufs(kmsg, this_ret), - issue_flags); -- if (sr->retry) -+ if (sr->retry_flags & IO_SR_MSG_RETRY) - cflags = req->cqe.flags | (cflags & CQE_F_MASK); - /* bundle with no more immediate buffers, we're done */ - if (req->flags & REQ_F_BL_EMPTY) -@@ -832,12 +844,12 @@ static inline bool io_recv_finish(struct - * If more is available AND it was a full transfer, retry and - * append to this one - */ -- if (!sr->retry && kmsg->msg.msg_inq > 1 && this_ret > 0 && -+ if (!sr->retry_flags && kmsg->msg.msg_inq > 1 && this_ret > 0 && - !iov_iter_count(&kmsg->msg.msg_iter)) { - req->cqe.flags = cflags & ~CQE_F_MASK; - sr->len = kmsg->msg.msg_inq; - sr->done_io += this_ret; -- sr->retry = true; -+ sr->retry_flags |= IO_SR_MSG_RETRY; - return false; - } - } else { -@@ -1021,8 +1033,7 @@ retry_multishot: - } - if (ret > 0 && io_net_retry(sock, flags)) { - sr->done_io += ret; -- req->flags |= REQ_F_BL_NO_RECYCLE; -- return IOU_RETRY; -+ return io_net_kbuf_recyle(req, kmsg, ret); - } - if (ret == -ERESTARTSYS) - ret = -EINTR; -@@ -1077,6 +1088,14 @@ static int io_recv_buf_select(struct io_ - if (unlikely(ret < 0)) - return ret; - -+ if (arg.iovs != &kmsg->fast_iov && arg.iovs != kmsg->vec.iovec) { -+ kmsg->vec.nr = ret; -+ kmsg->vec.iovec = arg.iovs; -+ req->flags |= REQ_F_NEED_CLEANUP; -+ } -+ if (arg.partial_map) -+ sr->retry_flags |= IO_SR_MSG_PARTIAL_MAP; -+ - /* special case 1 vec, can be a fast path */ - if (ret == 1) { - sr->buf = arg.iovs[0].iov_base; -@@ -1085,11 +1104,6 @@ static int io_recv_buf_select(struct io_ - } - iov_iter_init(&kmsg->msg.msg_iter, ITER_DEST, arg.iovs, ret, - arg.out_len); -- if (arg.iovs != &kmsg->fast_iov && arg.iovs != kmsg->vec.iovec) { -- kmsg->vec.nr = ret; -- kmsg->vec.iovec = arg.iovs; -- req->flags |= REQ_F_NEED_CLEANUP; -- } - } else { - void __user *buf; - -@@ -1160,8 +1174,7 @@ retry_multishot: - sr->len -= ret; - sr->buf += ret; - sr->done_io += ret; -- req->flags |= REQ_F_BL_NO_RECYCLE; -- return -EAGAIN; -+ return io_net_kbuf_recyle(req, kmsg, ret); - } - if (ret == -ERESTARTSYS) - ret = -EINTR; -@@ -1275,7 +1288,7 @@ int io_send_zc_prep(struct io_kiocb *req - int ret; - - zc->done_io = 0; -- zc->retry = false; -+ zc->retry_flags = 0; - - if (unlikely(READ_ONCE(sqe->__pad2[0]) || READ_ONCE(sqe->addr3))) - return -EINVAL; -@@ -1442,8 +1455,7 @@ int io_send_zc(struct io_kiocb *req, uns - zc->len -= ret; - zc->buf += ret; - zc->done_io += ret; -- req->flags |= REQ_F_BL_NO_RECYCLE; -- return -EAGAIN; -+ return io_net_kbuf_recyle(req, kmsg, ret); - } - if (ret == -ERESTARTSYS) - ret = -EINTR; -@@ -1513,8 +1525,7 @@ int io_sendmsg_zc(struct io_kiocb *req, - - if (ret > 0 && io_net_retry(sock, flags)) { - sr->done_io += ret; -- req->flags |= REQ_F_BL_NO_RECYCLE; -- return -EAGAIN; -+ return io_net_kbuf_recyle(req, kmsg, ret); - } - if (ret == -ERESTARTSYS) - ret = -EINTR; -@@ -1730,9 +1741,11 @@ int io_connect(struct io_kiocb *req, uns - int ret; - bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK; - -- if (unlikely(req->flags & REQ_F_FAIL)) { -- ret = -ECONNRESET; -- goto out; -+ if (connect->in_progress) { -+ struct poll_table_struct pt = { ._key = EPOLLERR }; -+ -+ if (vfs_poll(req->file, &pt) & EPOLLERR) -+ goto get_sock_err; - } - - file_flags = force_nonblock ? O_NONBLOCK : 0; -@@ -1757,8 +1770,10 @@ int io_connect(struct io_kiocb *req, uns - * which means the previous result is good. For both of these, - * grab the sock_error() and use that for the completion. - */ -- if (ret == -EBADFD || ret == -EISCONN) -+ if (ret == -EBADFD || ret == -EISCONN) { -+get_sock_err: - ret = sock_error(sock_from_file(req->file)->sk); -+ } - } - if (ret == -ERESTARTSYS) - ret = -EINTR; -diff -purNx .git BPI-Router-Linux-kernel/io_uring/notif.c BPI-Router-Linux-kernel-6.16.12/io_uring/notif.c ---- BPI-Router-Linux-kernel/io_uring/notif.c 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/io_uring/notif.c 2025-10-22 13:53:56.767167926 -0400 -@@ -85,7 +85,7 @@ static int io_link_skb(struct sk_buff *s - return -EEXIST; - - prev_nd = container_of(prev_uarg, struct io_notif_data, uarg); -- prev_notif = cmd_to_io_kiocb(nd); -+ prev_notif = cmd_to_io_kiocb(prev_nd); - - /* make sure all noifications can be finished in the same task_work */ - if (unlikely(notif->ctx != prev_notif->ctx || -diff -purNx .git BPI-Router-Linux-kernel/io_uring/opdef.c BPI-Router-Linux-kernel-6.16.12/io_uring/opdef.c ---- BPI-Router-Linux-kernel/io_uring/opdef.c 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/io_uring/opdef.c 2025-10-22 13:53:56.767167926 -0400 -@@ -216,6 +216,7 @@ const struct io_issue_def io_issue_defs[ - }, - [IORING_OP_FALLOCATE] = { - .needs_file = 1, -+ .hash_reg_file = 1, - .prep = io_fallocate_prep, - .issue = io_fallocate, - }, -diff -purNx .git BPI-Router-Linux-kernel/io_uring/poll.c BPI-Router-Linux-kernel-6.16.12/io_uring/poll.c ---- BPI-Router-Linux-kernel/io_uring/poll.c 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/io_uring/poll.c 2025-10-22 13:53:56.767167926 -0400 -@@ -224,7 +224,7 @@ static int io_poll_check_events(struct i - { - int v; - -- if (unlikely(io_should_terminate_tw())) -+ if (unlikely(io_should_terminate_tw(req->ctx))) - return -ECANCELED; - - do { -@@ -273,8 +273,6 @@ static int io_poll_check_events(struct i - return IOU_POLL_REISSUE; - } - } -- if (unlikely(req->cqe.res & EPOLLERR)) -- req_set_fail(req); - if (req->apoll_events & EPOLLONESHOT) - return IOU_POLL_DONE; - -diff -purNx .git BPI-Router-Linux-kernel/io_uring/register.c BPI-Router-Linux-kernel-6.16.12/io_uring/register.c ---- BPI-Router-Linux-kernel/io_uring/register.c 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/io_uring/register.c 2025-10-22 13:53:56.767167926 -0400 -@@ -273,6 +273,8 @@ static __cold int io_register_iowq_max_w - if (ctx->flags & IORING_SETUP_SQPOLL) { - sqd = ctx->sq_data; - if (sqd) { -+ struct task_struct *tsk; -+ - /* - * Observe the correct sqd->lock -> ctx->uring_lock - * ordering. Fine to drop uring_lock here, we hold -@@ -282,8 +284,9 @@ static __cold int io_register_iowq_max_w - mutex_unlock(&ctx->uring_lock); - mutex_lock(&sqd->lock); - mutex_lock(&ctx->uring_lock); -- if (sqd->thread) -- tctx = sqd->thread->io_uring; -+ tsk = sqpoll_task_locked(sqd); -+ if (tsk) -+ tctx = tsk->io_uring; - } - } else { - tctx = current->io_uring; -diff -purNx .git BPI-Router-Linux-kernel/io_uring/rsrc.c BPI-Router-Linux-kernel-6.16.12/io_uring/rsrc.c ---- BPI-Router-Linux-kernel/io_uring/rsrc.c 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/io_uring/rsrc.c 2025-10-22 13:53:56.767167926 -0400 -@@ -55,7 +55,7 @@ int __io_account_mem(struct user_struct - return 0; - } - --static void io_unaccount_mem(struct io_ring_ctx *ctx, unsigned long nr_pages) -+void io_unaccount_mem(struct io_ring_ctx *ctx, unsigned long nr_pages) - { - if (ctx->user) - __io_unaccount_mem(ctx->user, nr_pages); -@@ -64,7 +64,7 @@ static void io_unaccount_mem(struct io_r - atomic64_sub(nr_pages, &ctx->mm_account->pinned_vm); - } - --static int io_account_mem(struct io_ring_ctx *ctx, unsigned long nr_pages) -+int io_account_mem(struct io_ring_ctx *ctx, unsigned long nr_pages) - { - int ret; - -@@ -112,8 +112,11 @@ static void io_release_ubuf(void *priv) - struct io_mapped_ubuf *imu = priv; - unsigned int i; - -- for (i = 0; i < imu->nr_bvecs; i++) -- unpin_user_page(imu->bvec[i].bv_page); -+ for (i = 0; i < imu->nr_bvecs; i++) { -+ struct folio *folio = page_folio(imu->bvec[i].bv_page); -+ -+ unpin_user_folio(folio, 1); -+ } - } - - static struct io_mapped_ubuf *io_alloc_imu(struct io_ring_ctx *ctx, -@@ -731,6 +734,7 @@ bool io_check_coalesce_buffer(struct pag - - data->nr_pages_mid = folio_nr_pages(folio); - data->folio_shift = folio_shift(folio); -+ data->first_folio_page_idx = folio_page_idx(folio, page_array[0]); - - /* - * Check if pages are contiguous inside a folio, and all folios have -@@ -809,10 +813,8 @@ static struct io_rsrc_node *io_sqe_buffe - - imu->nr_bvecs = nr_pages; - ret = io_buffer_account_pin(ctx, pages, nr_pages, imu, last_hpage); -- if (ret) { -- unpin_user_pages(pages, nr_pages); -+ if (ret) - goto done; -- } - - size = iov->iov_len; - /* store original address for later verification */ -@@ -826,7 +828,11 @@ static struct io_rsrc_node *io_sqe_buffe - if (coalesced) - imu->folio_shift = data.folio_shift; - refcount_set(&imu->refs, 1); -- off = (unsigned long) iov->iov_base & ((1UL << imu->folio_shift) - 1); -+ -+ off = (unsigned long)iov->iov_base & ~PAGE_MASK; -+ if (coalesced) -+ off += data.first_folio_page_idx << PAGE_SHIFT; -+ - node->buf = imu; - ret = 0; - -@@ -842,6 +848,10 @@ done: - if (ret) { - if (imu) - io_free_imu(ctx, imu); -+ if (pages) { -+ for (i = 0; i < nr_pages; i++) -+ unpin_user_folio(page_folio(pages[i]), 1); -+ } - io_cache_free(&ctx->node_cache, node); - node = ERR_PTR(ret); - } -@@ -1177,6 +1187,8 @@ static int io_clone_buffers(struct io_ri - return -EINVAL; - if (check_add_overflow(arg->nr, arg->dst_off, &nbufs)) - return -EOVERFLOW; -+ if (nbufs > IORING_MAX_REG_BUFFERS) -+ return -EINVAL; - - ret = io_rsrc_data_alloc(&data, max(nbufs, ctx->buf_table.nr)); - if (ret) -@@ -1327,7 +1339,6 @@ static int io_vec_fill_bvec(int ddir, st - { - unsigned long folio_size = 1 << imu->folio_shift; - unsigned long folio_mask = folio_size - 1; -- u64 folio_addr = imu->ubuf & ~folio_mask; - struct bio_vec *res_bvec = vec->bvec; - size_t total_len = 0; - unsigned bvec_idx = 0; -@@ -1349,8 +1360,13 @@ static int io_vec_fill_bvec(int ddir, st - if (unlikely(check_add_overflow(total_len, iov_len, &total_len))) - return -EOVERFLOW; - -- /* by using folio address it also accounts for bvec offset */ -- offset = buf_addr - folio_addr; -+ offset = buf_addr - imu->ubuf; -+ /* -+ * Only the first bvec can have non zero bv_offset, account it -+ * here and work with full folios below. -+ */ -+ offset += imu->bvec[0].bv_offset; -+ - src_bvec = imu->bvec + (offset >> imu->folio_shift); - offset &= folio_mask; - -diff -purNx .git BPI-Router-Linux-kernel/io_uring/rsrc.h BPI-Router-Linux-kernel-6.16.12/io_uring/rsrc.h ---- BPI-Router-Linux-kernel/io_uring/rsrc.h 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/io_uring/rsrc.h 2025-10-22 13:53:56.767167926 -0400 -@@ -49,6 +49,7 @@ struct io_imu_folio_data { - unsigned int nr_pages_mid; - unsigned int folio_shift; - unsigned int nr_folios; -+ unsigned long first_folio_page_idx; - }; - - bool io_rsrc_cache_init(struct io_ring_ctx *ctx); -@@ -119,6 +120,8 @@ int io_files_update(struct io_kiocb *req - int io_files_update_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe); - - int __io_account_mem(struct user_struct *user, unsigned long nr_pages); -+int io_account_mem(struct io_ring_ctx *ctx, unsigned long nr_pages); -+void io_unaccount_mem(struct io_ring_ctx *ctx, unsigned long nr_pages); - - static inline void __io_unaccount_mem(struct user_struct *user, - unsigned long nr_pages) -diff -purNx .git BPI-Router-Linux-kernel/io_uring/rw.c BPI-Router-Linux-kernel-6.16.12/io_uring/rw.c ---- BPI-Router-Linux-kernel/io_uring/rw.c 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/io_uring/rw.c 2025-10-22 13:53:56.767167926 -0400 -@@ -288,7 +288,7 @@ static int __io_prep_rw(struct io_kiocb - - rw->addr = READ_ONCE(sqe->addr); - rw->len = READ_ONCE(sqe->len); -- rw->flags = READ_ONCE(sqe->rw_flags); -+ rw->flags = (__force rwf_t) READ_ONCE(sqe->rw_flags); - - attr_type_mask = READ_ONCE(sqe->attr_type_mask); - if (attr_type_mask) { -@@ -886,6 +886,9 @@ static int io_rw_init_file(struct io_kio - if (req->flags & REQ_F_HAS_METADATA) { - struct io_async_rw *io = req->async_data; - -+ if (!(file->f_mode & FMODE_HAS_METADATA)) -+ return -EINVAL; -+ - /* - * We have a union of meta fields with wpq used for buffered-io - * in io_async_rw, so fail it here. -diff -purNx .git BPI-Router-Linux-kernel/io_uring/sqpoll.c BPI-Router-Linux-kernel-6.16.12/io_uring/sqpoll.c ---- BPI-Router-Linux-kernel/io_uring/sqpoll.c 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/io_uring/sqpoll.c 2025-10-22 13:53:56.767167926 -0400 -@@ -16,6 +16,7 @@ - #include - - #include "io_uring.h" -+#include "tctx.h" - #include "napi.h" - #include "sqpoll.h" - -@@ -30,7 +31,7 @@ enum { - void io_sq_thread_unpark(struct io_sq_data *sqd) - __releases(&sqd->lock) - { -- WARN_ON_ONCE(sqd->thread == current); -+ WARN_ON_ONCE(sqpoll_task_locked(sqd) == current); - - /* - * Do the dance but not conditional clear_bit() because it'd race with -@@ -46,24 +47,32 @@ void io_sq_thread_unpark(struct io_sq_da - void io_sq_thread_park(struct io_sq_data *sqd) - __acquires(&sqd->lock) - { -- WARN_ON_ONCE(data_race(sqd->thread) == current); -+ struct task_struct *tsk; - - atomic_inc(&sqd->park_pending); - set_bit(IO_SQ_THREAD_SHOULD_PARK, &sqd->state); - mutex_lock(&sqd->lock); -- if (sqd->thread) -- wake_up_process(sqd->thread); -+ -+ tsk = sqpoll_task_locked(sqd); -+ if (tsk) { -+ WARN_ON_ONCE(tsk == current); -+ wake_up_process(tsk); -+ } - } - - void io_sq_thread_stop(struct io_sq_data *sqd) - { -- WARN_ON_ONCE(sqd->thread == current); -+ struct task_struct *tsk; -+ - WARN_ON_ONCE(test_bit(IO_SQ_THREAD_SHOULD_STOP, &sqd->state)); - - set_bit(IO_SQ_THREAD_SHOULD_STOP, &sqd->state); - mutex_lock(&sqd->lock); -- if (sqd->thread) -- wake_up_process(sqd->thread); -+ tsk = sqpoll_task_locked(sqd); -+ if (tsk) { -+ WARN_ON_ONCE(tsk == current); -+ wake_up_process(tsk); -+ } - mutex_unlock(&sqd->lock); - wait_for_completion(&sqd->exited); - } -@@ -270,7 +279,8 @@ static int io_sq_thread(void *data) - /* offload context creation failed, just exit */ - if (!current->io_uring) { - mutex_lock(&sqd->lock); -- sqd->thread = NULL; -+ rcu_assign_pointer(sqd->thread, NULL); -+ put_task_struct(current); - mutex_unlock(&sqd->lock); - goto err_out; - } -@@ -379,7 +389,8 @@ static int io_sq_thread(void *data) - io_sq_tw(&retry_list, UINT_MAX); - - io_uring_cancel_generic(true, sqd); -- sqd->thread = NULL; -+ rcu_assign_pointer(sqd->thread, NULL); -+ put_task_struct(current); - list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) - atomic_or(IORING_SQ_NEED_WAKEUP, &ctx->rings->sq_flags); - io_run_task_work(); -@@ -409,7 +420,6 @@ void io_sqpoll_wait_sq(struct io_ring_ct - __cold int io_sq_offload_create(struct io_ring_ctx *ctx, - struct io_uring_params *p) - { -- struct task_struct *task_to_put = NULL; - int ret; - - /* Retain compatibility with failing for an invalid attach attempt */ -@@ -484,8 +494,11 @@ __cold int io_sq_offload_create(struct i - goto err_sqpoll; - } - -- sqd->thread = tsk; -- task_to_put = get_task_struct(tsk); -+ mutex_lock(&sqd->lock); -+ rcu_assign_pointer(sqd->thread, tsk); -+ mutex_unlock(&sqd->lock); -+ -+ get_task_struct(tsk); - ret = io_uring_alloc_task_context(tsk, ctx); - wake_up_new_task(tsk); - if (ret) -@@ -495,16 +508,11 @@ __cold int io_sq_offload_create(struct i - ret = -EINVAL; - goto err; - } -- -- if (task_to_put) -- put_task_struct(task_to_put); - return 0; - err_sqpoll: - complete(&ctx->sq_data->exited); - err: - io_sq_thread_finish(ctx); -- if (task_to_put) -- put_task_struct(task_to_put); - return ret; - } - -@@ -515,10 +523,13 @@ __cold int io_sqpoll_wq_cpu_affinity(str - int ret = -EINVAL; - - if (sqd) { -+ struct task_struct *tsk; -+ - io_sq_thread_park(sqd); - /* Don't set affinity for a dying thread */ -- if (sqd->thread) -- ret = io_wq_cpu_affinity(sqd->thread->io_uring, mask); -+ tsk = sqpoll_task_locked(sqd); -+ if (tsk) -+ ret = io_wq_cpu_affinity(tsk->io_uring, mask); - io_sq_thread_unpark(sqd); - } - -diff -purNx .git BPI-Router-Linux-kernel/io_uring/sqpoll.h BPI-Router-Linux-kernel-6.16.12/io_uring/sqpoll.h ---- BPI-Router-Linux-kernel/io_uring/sqpoll.h 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/io_uring/sqpoll.h 2025-10-22 13:53:56.767167926 -0400 -@@ -8,7 +8,7 @@ struct io_sq_data { - /* ctx's that are using this sqd */ - struct list_head ctx_list; - -- struct task_struct *thread; -+ struct task_struct __rcu *thread; - struct wait_queue_head wait; - - unsigned sq_thread_idle; -@@ -29,3 +29,9 @@ void io_sq_thread_unpark(struct io_sq_da - void io_put_sq_data(struct io_sq_data *sqd); - void io_sqpoll_wait_sq(struct io_ring_ctx *ctx); - int io_sqpoll_wq_cpu_affinity(struct io_ring_ctx *ctx, cpumask_var_t mask); -+ -+static inline struct task_struct *sqpoll_task_locked(struct io_sq_data *sqd) -+{ -+ return rcu_dereference_protected(sqd->thread, -+ lockdep_is_held(&sqd->lock)); -+} -diff -purNx .git BPI-Router-Linux-kernel/io_uring/timeout.c BPI-Router-Linux-kernel-6.16.12/io_uring/timeout.c ---- BPI-Router-Linux-kernel/io_uring/timeout.c 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/io_uring/timeout.c 2025-10-22 13:53:56.767167926 -0400 -@@ -324,7 +324,7 @@ static void io_req_task_link_timeout(str - int ret; - - if (prev) { -- if (!io_should_terminate_tw()) { -+ if (!io_should_terminate_tw(req->ctx)) { - struct io_cancel_data cd = { - .ctx = req->ctx, - .data = prev->cqe.user_data, -diff -purNx .git BPI-Router-Linux-kernel/io_uring/uring_cmd.c BPI-Router-Linux-kernel-6.16.12/io_uring/uring_cmd.c ---- BPI-Router-Linux-kernel/io_uring/uring_cmd.c 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/io_uring/uring_cmd.c 2025-10-22 13:53:56.767167926 -0400 -@@ -123,7 +123,7 @@ static void io_uring_cmd_work(struct io_ - struct io_uring_cmd *ioucmd = io_kiocb_to_cmd(req, struct io_uring_cmd); - unsigned int flags = IO_URING_F_COMPLETE_DEFER; - -- if (io_should_terminate_tw()) -+ if (io_should_terminate_tw(req->ctx)) - flags |= IO_URING_F_TASK_DEAD; - - /* task_work executor checks the deffered list completion */ -diff -purNx .git BPI-Router-Linux-kernel/io_uring/zcrx.c BPI-Router-Linux-kernel-6.16.12/io_uring/zcrx.c ---- BPI-Router-Linux-kernel/io_uring/zcrx.c 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/io_uring/zcrx.c 2025-10-22 13:53:56.767167926 -0400 -@@ -76,6 +76,8 @@ static int io_import_dmabuf(struct io_zc - int dmabuf_fd = area_reg->dmabuf_fd; - int i, ret; - -+ if (off) -+ return -EINVAL; - if (WARN_ON_ONCE(!ifq->dev)) - return -EFAULT; - if (!IS_ENABLED(CONFIG_DMA_SHARED_BUFFER)) -@@ -106,8 +108,10 @@ static int io_import_dmabuf(struct io_zc - for_each_sgtable_dma_sg(mem->sgt, sg, i) - total_size += sg_dma_len(sg); - -- if (total_size < off + len) -- return -EINVAL; -+ if (total_size != len) { -+ ret = -EINVAL; -+ goto err; -+ } - - mem->dmabuf_offset = off; - mem->size = len; -@@ -148,12 +152,29 @@ static int io_zcrx_map_area_dmabuf(struc - return niov_idx; - } - -+static unsigned long io_count_account_pages(struct page **pages, unsigned nr_pages) -+{ -+ struct folio *last_folio = NULL; -+ unsigned long res = 0; -+ int i; -+ -+ for (i = 0; i < nr_pages; i++) { -+ struct folio *folio = page_folio(pages[i]); -+ -+ if (folio == last_folio) -+ continue; -+ last_folio = folio; -+ res += 1UL << folio_order(folio); -+ } -+ return res; -+} -+ - static int io_import_umem(struct io_zcrx_ifq *ifq, - struct io_zcrx_mem *mem, - struct io_uring_zcrx_area_reg *area_reg) - { - struct page **pages; -- int nr_pages; -+ int nr_pages, ret; - - if (area_reg->dmabuf_fd) - return -EINVAL; -@@ -164,10 +185,15 @@ static int io_import_umem(struct io_zcrx - if (IS_ERR(pages)) - return PTR_ERR(pages); - -+ mem->account_pages = io_count_account_pages(pages, nr_pages); -+ ret = io_account_mem(ifq->ctx, mem->account_pages); -+ if (ret < 0) -+ mem->account_pages = 0; -+ - mem->pages = pages; - mem->nr_folios = nr_pages; - mem->size = area_reg->len; -- return 0; -+ return ret; - } - - static void io_release_area_mem(struct io_zcrx_mem *mem) -@@ -366,10 +392,12 @@ static void io_free_rbuf_ring(struct io_ - - static void io_zcrx_free_area(struct io_zcrx_area *area) - { -- if (area->ifq) -- io_zcrx_unmap_area(area->ifq, area); -+ io_zcrx_unmap_area(area->ifq, area); - io_release_area_mem(&area->mem); - -+ if (area->mem.account_pages) -+ io_unaccount_mem(area->ifq->ctx, area->mem.account_pages); -+ - kvfree(area->freelist); - kvfree(area->nia.niovs); - kvfree(area->user_refs); -@@ -397,6 +425,7 @@ static int io_zcrx_create_area(struct io - area = kzalloc(sizeof(*area), GFP_KERNEL); - if (!area) - goto err; -+ area->ifq = ifq; - - ret = io_import_area(ifq, &area->mem, area_reg); - if (ret) -@@ -431,7 +460,6 @@ static int io_zcrx_create_area(struct io - } - - area->free_count = nr_iovs; -- area->ifq = ifq; - /* we're only supporting one area per ifq for now */ - area->area_id = 0; - area_reg->rq_area_token = (u64)area->area_id << IORING_ZCRX_AREA_SHIFT; -@@ -861,10 +889,7 @@ static int io_pp_zc_init(struct page_poo - static void io_pp_zc_destroy(struct page_pool *pp) - { - struct io_zcrx_ifq *ifq = io_pp_to_ifq(pp); -- struct io_zcrx_area *area = ifq->area; - -- if (WARN_ON_ONCE(area->free_count != area->nia.num_niovs)) -- return; - percpu_ref_put(&ifq->ctx->refs); - } - -diff -purNx .git BPI-Router-Linux-kernel/io_uring/zcrx.h BPI-Router-Linux-kernel-6.16.12/io_uring/zcrx.h ---- BPI-Router-Linux-kernel/io_uring/zcrx.h 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/io_uring/zcrx.h 2025-10-22 13:53:56.767167926 -0400 -@@ -14,6 +14,7 @@ struct io_zcrx_mem { - - struct page **pages; - unsigned long nr_folios; -+ unsigned long account_pages; - - struct dma_buf_attachment *attach; - struct dma_buf *dmabuf; -diff -purNx .git BPI-Router-Linux-kernel/kernel/auditfilter.c BPI-Router-Linux-kernel-6.16.12/kernel/auditfilter.c ---- BPI-Router-Linux-kernel/kernel/auditfilter.c 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/auditfilter.c 2025-10-22 13:53:56.767167926 -0400 -@@ -1326,7 +1326,7 @@ int audit_compare_dname_path(const struc - - /* handle trailing slashes */ - pathlen -= parentlen; -- while (p[pathlen - 1] == '/') -+ while (pathlen > 0 && p[pathlen - 1] == '/') - pathlen--; - - if (pathlen != dlen) -diff -purNx .git BPI-Router-Linux-kernel/kernel/audit.h BPI-Router-Linux-kernel-6.16.12/kernel/audit.h ---- BPI-Router-Linux-kernel/kernel/audit.h 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/audit.h 2025-10-22 13:53:56.767167926 -0400 -@@ -200,7 +200,7 @@ struct audit_context { - int argc; - } execve; - struct { -- char *name; -+ const char *name; - } module; - struct { - struct audit_ntp_data ntp_data; -diff -purNx .git BPI-Router-Linux-kernel/kernel/auditsc.c BPI-Router-Linux-kernel-6.16.12/kernel/auditsc.c ---- BPI-Router-Linux-kernel/kernel/auditsc.c 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/auditsc.c 2025-10-22 13:53:56.767167926 -0400 -@@ -2864,7 +2864,7 @@ void __audit_openat2_how(struct open_how - context->type = AUDIT_OPENAT2; - } - --void __audit_log_kern_module(char *name) -+void __audit_log_kern_module(const char *name) - { - struct audit_context *context = audit_context(); - -diff -purNx .git BPI-Router-Linux-kernel/kernel/audit_tree.c BPI-Router-Linux-kernel-6.16.12/kernel/audit_tree.c ---- BPI-Router-Linux-kernel/kernel/audit_tree.c 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/audit_tree.c 2025-10-22 13:53:56.767167926 -0400 -@@ -668,12 +668,6 @@ int audit_remove_tree_rule(struct audit_ - return 0; - } - --static int compare_root(struct vfsmount *mnt, void *arg) --{ -- return inode_to_key(d_backing_inode(mnt->mnt_root)) == -- (unsigned long)arg; --} -- - void audit_trim_trees(void) - { - struct list_head cursor; -@@ -683,8 +677,9 @@ void audit_trim_trees(void) - while (cursor.next != &tree_list) { - struct audit_tree *tree; - struct path path; -- struct vfsmount *root_mnt; - struct audit_node *node; -+ struct path *paths; -+ struct path array[16]; - int err; - - tree = container_of(cursor.next, struct audit_tree, list); -@@ -696,9 +691,9 @@ void audit_trim_trees(void) - if (err) - goto skip_it; - -- root_mnt = collect_mounts(&path); -+ paths = collect_paths(&path, array, 16); - path_put(&path); -- if (IS_ERR(root_mnt)) -+ if (IS_ERR(paths)) - goto skip_it; - - spin_lock(&hash_lock); -@@ -706,14 +701,17 @@ void audit_trim_trees(void) - struct audit_chunk *chunk = find_chunk(node); - /* this could be NULL if the watch is dying else where... */ - node->index |= 1U<<31; -- if (iterate_mounts(compare_root, -- (void *)(chunk->key), -- root_mnt)) -- node->index &= ~(1U<<31); -+ for (struct path *p = paths; p->dentry; p++) { -+ struct inode *inode = p->dentry->d_inode; -+ if (inode_to_key(inode) == chunk->key) { -+ node->index &= ~(1U<<31); -+ break; -+ } -+ } - } - spin_unlock(&hash_lock); - trim_marked(tree); -- drop_collected_mounts(root_mnt); -+ drop_collected_paths(paths, array); - skip_it: - put_tree(tree); - mutex_lock(&audit_filter_mutex); -@@ -742,9 +740,14 @@ void audit_put_tree(struct audit_tree *t - put_tree(tree); - } - --static int tag_mount(struct vfsmount *mnt, void *arg) -+static int tag_mounts(struct path *paths, struct audit_tree *tree) - { -- return tag_chunk(d_backing_inode(mnt->mnt_root), arg); -+ for (struct path *p = paths; p->dentry; p++) { -+ int err = tag_chunk(p->dentry->d_inode, tree); -+ if (err) -+ return err; -+ } -+ return 0; - } - - /* -@@ -801,7 +804,8 @@ int audit_add_tree_rule(struct audit_kru - { - struct audit_tree *seed = rule->tree, *tree; - struct path path; -- struct vfsmount *mnt; -+ struct path array[16]; -+ struct path *paths; - int err; - - rule->tree = NULL; -@@ -828,16 +832,16 @@ int audit_add_tree_rule(struct audit_kru - err = kern_path(tree->pathname, 0, &path); - if (err) - goto Err; -- mnt = collect_mounts(&path); -+ paths = collect_paths(&path, array, 16); - path_put(&path); -- if (IS_ERR(mnt)) { -- err = PTR_ERR(mnt); -+ if (IS_ERR(paths)) { -+ err = PTR_ERR(paths); - goto Err; - } - - get_tree(tree); -- err = iterate_mounts(tag_mount, tree, mnt); -- drop_collected_mounts(mnt); -+ err = tag_mounts(paths, tree); -+ drop_collected_paths(paths, array); - - if (!err) { - struct audit_node *node; -@@ -872,20 +876,21 @@ int audit_tag_tree(char *old, char *new) - struct list_head cursor, barrier; - int failed = 0; - struct path path1, path2; -- struct vfsmount *tagged; -+ struct path array[16]; -+ struct path *paths; - int err; - - err = kern_path(new, 0, &path2); - if (err) - return err; -- tagged = collect_mounts(&path2); -+ paths = collect_paths(&path2, array, 16); - path_put(&path2); -- if (IS_ERR(tagged)) -- return PTR_ERR(tagged); -+ if (IS_ERR(paths)) -+ return PTR_ERR(paths); - - err = kern_path(old, 0, &path1); - if (err) { -- drop_collected_mounts(tagged); -+ drop_collected_paths(paths, array); - return err; - } - -@@ -914,7 +919,7 @@ int audit_tag_tree(char *old, char *new) - continue; - } - -- failed = iterate_mounts(tag_mount, tree, tagged); -+ failed = tag_mounts(paths, tree); - if (failed) { - put_tree(tree); - mutex_lock(&audit_filter_mutex); -@@ -955,7 +960,7 @@ int audit_tag_tree(char *old, char *new) - list_del(&cursor); - mutex_unlock(&audit_filter_mutex); - path_put(&path1); -- drop_collected_mounts(tagged); -+ drop_collected_paths(paths, array); - return failed; - } - -diff -purNx .git BPI-Router-Linux-kernel/kernel/bpf/bpf_lru_list.c BPI-Router-Linux-kernel-6.16.12/kernel/bpf/bpf_lru_list.c ---- BPI-Router-Linux-kernel/kernel/bpf/bpf_lru_list.c 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/bpf/bpf_lru_list.c 2025-10-22 13:53:56.767167926 -0400 -@@ -337,12 +337,12 @@ static void bpf_lru_list_pop_free_to_loc - list) { - __bpf_lru_node_move_to_free(l, node, local_free_list(loc_l), - BPF_LRU_LOCAL_LIST_T_FREE); -- if (++nfree == LOCAL_FREE_TARGET) -+ if (++nfree == lru->target_free) - break; - } - -- if (nfree < LOCAL_FREE_TARGET) -- __bpf_lru_list_shrink(lru, l, LOCAL_FREE_TARGET - nfree, -+ if (nfree < lru->target_free) -+ __bpf_lru_list_shrink(lru, l, lru->target_free - nfree, - local_free_list(loc_l), - BPF_LRU_LOCAL_LIST_T_FREE); - -@@ -577,6 +577,9 @@ static void bpf_common_lru_populate(stru - list_add(&node->list, &l->lists[BPF_LRU_LIST_T_FREE]); - buf += elem_size; - } -+ -+ lru->target_free = clamp((nr_elems / num_possible_cpus()) / 2, -+ 1, LOCAL_FREE_TARGET); - } - - static void bpf_percpu_lru_populate(struct bpf_lru *lru, void *buf, -diff -purNx .git BPI-Router-Linux-kernel/kernel/bpf/bpf_lru_list.h BPI-Router-Linux-kernel-6.16.12/kernel/bpf/bpf_lru_list.h ---- BPI-Router-Linux-kernel/kernel/bpf/bpf_lru_list.h 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/bpf/bpf_lru_list.h 2025-10-22 13:53:56.767167926 -0400 -@@ -58,6 +58,7 @@ struct bpf_lru { - del_from_htab_func del_from_htab; - void *del_arg; - unsigned int hash_offset; -+ unsigned int target_free; - unsigned int nr_scans; - bool percpu; - }; -diff -purNx .git BPI-Router-Linux-kernel/kernel/bpf/cgroup.c BPI-Router-Linux-kernel-6.16.12/kernel/bpf/cgroup.c ---- BPI-Router-Linux-kernel/kernel/bpf/cgroup.c 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/bpf/cgroup.c 2025-10-22 13:53:56.767167926 -0400 -@@ -2134,7 +2134,7 @@ static const struct bpf_func_proto bpf_s - .gpl_only = false, - .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_CTX, -- .arg2_type = ARG_PTR_TO_MEM, -+ .arg2_type = ARG_PTR_TO_MEM | MEM_WRITE, - .arg3_type = ARG_CONST_SIZE, - .arg4_type = ARG_ANYTHING, - }; -@@ -2440,22 +2440,22 @@ static bool cg_sockopt_is_valid_access(i - } - - switch (off) { -- case offsetof(struct bpf_sockopt, sk): -+ case bpf_ctx_range_ptr(struct bpf_sockopt, sk): - if (size != sizeof(__u64)) - return false; - info->reg_type = PTR_TO_SOCKET; - break; -- case offsetof(struct bpf_sockopt, optval): -+ case bpf_ctx_range_ptr(struct bpf_sockopt, optval): - if (size != sizeof(__u64)) - return false; - info->reg_type = PTR_TO_PACKET; - break; -- case offsetof(struct bpf_sockopt, optval_end): -+ case bpf_ctx_range_ptr(struct bpf_sockopt, optval_end): - if (size != sizeof(__u64)) - return false; - info->reg_type = PTR_TO_PACKET_END; - break; -- case offsetof(struct bpf_sockopt, retval): -+ case bpf_ctx_range(struct bpf_sockopt, retval): - if (size != size_default) - return false; - return prog->expected_attach_type == BPF_CGROUP_GETSOCKOPT; -diff -purNx .git BPI-Router-Linux-kernel/kernel/bpf/core.c BPI-Router-Linux-kernel-6.16.12/kernel/bpf/core.c ---- BPI-Router-Linux-kernel/kernel/bpf/core.c 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/bpf/core.c 2025-10-22 13:53:56.767167926 -0400 -@@ -778,7 +778,10 @@ bool is_bpf_text_address(unsigned long a - - struct bpf_prog *bpf_prog_ksym_find(unsigned long addr) - { -- struct bpf_ksym *ksym = bpf_ksym_find(addr); -+ struct bpf_ksym *ksym; -+ -+ WARN_ON_ONCE(!rcu_read_lock_held()); -+ ksym = bpf_ksym_find(addr); - - return ksym && ksym->prog ? - container_of(ksym, struct bpf_prog_aux, ksym)->prog : -@@ -2351,8 +2354,7 @@ static unsigned int __bpf_prog_ret0_warn - const struct bpf_insn *insn) - { - /* If this handler ever gets executed, then BPF_JIT_ALWAYS_ON -- * is not working properly, or interpreter is being used when -- * prog->jit_requested is not 0, so warn about it! -+ * is not working properly, so warn about it! - */ - WARN_ON_ONCE(1); - return 0; -@@ -2362,28 +2364,44 @@ static bool __bpf_prog_map_compatible(st - const struct bpf_prog *fp) - { - enum bpf_prog_type prog_type = resolve_prog_type(fp); -- bool ret; - struct bpf_prog_aux *aux = fp->aux; -+ enum bpf_cgroup_storage_type i; -+ bool ret = false; -+ u64 cookie; - - if (fp->kprobe_override) -- return false; -+ return ret; - -- spin_lock(&map->owner.lock); -- if (!map->owner.type) { -- /* There's no owner yet where we could check for -- * compatibility. -- */ -- map->owner.type = prog_type; -- map->owner.jited = fp->jited; -- map->owner.xdp_has_frags = aux->xdp_has_frags; -- map->owner.attach_func_proto = aux->attach_func_proto; -+ spin_lock(&map->owner_lock); -+ /* There's no owner yet where we could check for compatibility. */ -+ if (!map->owner) { -+ map->owner = bpf_map_owner_alloc(map); -+ if (!map->owner) -+ goto err; -+ map->owner->type = prog_type; -+ map->owner->jited = fp->jited; -+ map->owner->xdp_has_frags = aux->xdp_has_frags; -+ map->owner->attach_func_proto = aux->attach_func_proto; -+ for_each_cgroup_storage_type(i) { -+ map->owner->storage_cookie[i] = -+ aux->cgroup_storage[i] ? -+ aux->cgroup_storage[i]->cookie : 0; -+ } - ret = true; - } else { -- ret = map->owner.type == prog_type && -- map->owner.jited == fp->jited && -- map->owner.xdp_has_frags == aux->xdp_has_frags; -+ ret = map->owner->type == prog_type && -+ map->owner->jited == fp->jited && -+ map->owner->xdp_has_frags == aux->xdp_has_frags; -+ for_each_cgroup_storage_type(i) { -+ if (!ret) -+ break; -+ cookie = aux->cgroup_storage[i] ? -+ aux->cgroup_storage[i]->cookie : 0; -+ ret = map->owner->storage_cookie[i] == cookie || -+ !cookie; -+ } - if (ret && -- map->owner.attach_func_proto != aux->attach_func_proto) { -+ map->owner->attach_func_proto != aux->attach_func_proto) { - switch (prog_type) { - case BPF_PROG_TYPE_TRACING: - case BPF_PROG_TYPE_LSM: -@@ -2396,8 +2414,8 @@ static bool __bpf_prog_map_compatible(st - } - } - } -- spin_unlock(&map->owner.lock); -- -+err: -+ spin_unlock(&map->owner_lock); - return ret; - } - -@@ -2437,8 +2455,9 @@ out: - return ret; - } - --static void bpf_prog_select_func(struct bpf_prog *fp) -+static bool bpf_prog_select_interpreter(struct bpf_prog *fp) - { -+ bool select_interpreter = false; - #ifndef CONFIG_BPF_JIT_ALWAYS_ON - u32 stack_depth = max_t(u32, fp->aux->stack_depth, 1); - u32 idx = (round_up(stack_depth, 32) / 32) - 1; -@@ -2447,15 +2466,16 @@ static void bpf_prog_select_func(struct - * But for non-JITed programs, we don't need bpf_func, so no bounds - * check needed. - */ -- if (!fp->jit_requested && -- !WARN_ON_ONCE(idx >= ARRAY_SIZE(interpreters))) { -+ if (idx < ARRAY_SIZE(interpreters)) { - fp->bpf_func = interpreters[idx]; -+ select_interpreter = true; - } else { - fp->bpf_func = __bpf_prog_ret0_warn; - } - #else - fp->bpf_func = __bpf_prog_ret0_warn; - #endif -+ return select_interpreter; - } - - /** -@@ -2474,7 +2494,7 @@ struct bpf_prog *bpf_prog_select_runtime - /* In case of BPF to BPF calls, verifier did all the prep - * work with regards to JITing, etc. - */ -- bool jit_needed = fp->jit_requested; -+ bool jit_needed = false; - - if (fp->bpf_func) - goto finalize; -@@ -2483,7 +2503,8 @@ struct bpf_prog *bpf_prog_select_runtime - bpf_prog_has_kfunc_call(fp)) - jit_needed = true; - -- bpf_prog_select_func(fp); -+ if (!bpf_prog_select_interpreter(fp)) -+ jit_needed = true; - - /* eBPF JITs can rewrite the program in case constant - * blinding is active. However, in case of error during -@@ -2992,7 +3013,10 @@ EXPORT_SYMBOL_GPL(bpf_event_output); - - /* Always built-in helper functions. */ - const struct bpf_func_proto bpf_tail_call_proto = { -- .func = NULL, -+ /* func is unused for tail_call, we set it to pass the -+ * get_helper_proto check -+ */ -+ .func = BPF_PTR_POISON, - .gpl_only = false, - .ret_type = RET_VOID, - .arg1_type = ARG_PTR_TO_CTX, -diff -purNx .git BPI-Router-Linux-kernel/kernel/bpf/cpumap.c BPI-Router-Linux-kernel-6.16.12/kernel/bpf/cpumap.c ---- BPI-Router-Linux-kernel/kernel/bpf/cpumap.c 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/bpf/cpumap.c 2025-10-22 13:53:56.767167926 -0400 -@@ -186,7 +186,6 @@ static int cpu_map_bpf_prog_run_xdp(stru - struct xdp_buff xdp; - int i, nframes = 0; - -- xdp_set_return_frame_no_direct(); - xdp.rxq = &rxq; - - for (i = 0; i < n; i++) { -@@ -231,7 +230,6 @@ static int cpu_map_bpf_prog_run_xdp(stru - } - } - -- xdp_clear_return_frame_no_direct(); - stats->pass += nframes; - - return nframes; -@@ -255,6 +253,7 @@ static void cpu_map_bpf_prog_run(struct - - rcu_read_lock(); - bpf_net_ctx = bpf_net_ctx_set(&__bpf_net_ctx); -+ xdp_set_return_frame_no_direct(); - - ret->xdp_n = cpu_map_bpf_prog_run_xdp(rcpu, frames, ret->xdp_n, stats); - if (unlikely(ret->skb_n)) -@@ -264,6 +263,7 @@ static void cpu_map_bpf_prog_run(struct - if (stats->redirect) - xdp_do_flush(); - -+ xdp_clear_return_frame_no_direct(); - bpf_net_ctx_clear(bpf_net_ctx); - rcu_read_unlock(); - -diff -purNx .git BPI-Router-Linux-kernel/kernel/bpf/crypto.c BPI-Router-Linux-kernel-6.16.12/kernel/bpf/crypto.c ---- BPI-Router-Linux-kernel/kernel/bpf/crypto.c 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/bpf/crypto.c 2025-10-22 13:53:56.767167926 -0400 -@@ -278,7 +278,7 @@ static int bpf_crypto_crypt(const struct - siv_len = siv ? __bpf_dynptr_size(siv) : 0; - src_len = __bpf_dynptr_size(src); - dst_len = __bpf_dynptr_size(dst); -- if (!src_len || !dst_len) -+ if (!src_len || !dst_len || src_len > dst_len) - return -EINVAL; - - if (siv_len != ctx->siv_len) -diff -purNx .git BPI-Router-Linux-kernel/kernel/bpf/helpers.c BPI-Router-Linux-kernel-6.16.12/kernel/bpf/helpers.c ---- BPI-Router-Linux-kernel/kernel/bpf/helpers.c 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/bpf/helpers.c 2025-10-22 13:53:56.771167907 -0400 -@@ -884,6 +884,13 @@ int bpf_bprintf_prepare(char *fmt, u32 f - if (fmt[i] == 'p') { - sizeof_cur_arg = sizeof(long); - -+ if (fmt[i + 1] == 0 || isspace(fmt[i + 1]) || -+ ispunct(fmt[i + 1])) { -+ if (tmp_buf) -+ cur_arg = raw_args[num_spec]; -+ goto nocopy_fmt; -+ } -+ - if ((fmt[i + 1] == 'k' || fmt[i + 1] == 'u') && - fmt[i + 2] == 's') { - fmt_ptype = fmt[i + 1]; -@@ -891,11 +898,9 @@ int bpf_bprintf_prepare(char *fmt, u32 f - goto fmt_str; - } - -- if (fmt[i + 1] == 0 || isspace(fmt[i + 1]) || -- ispunct(fmt[i + 1]) || fmt[i + 1] == 'K' || -+ if (fmt[i + 1] == 'K' || - fmt[i + 1] == 'x' || fmt[i + 1] == 's' || - fmt[i + 1] == 'S') { -- /* just kernel pointers */ - if (tmp_buf) - cur_arg = raw_args[num_spec]; - i++; -@@ -1272,8 +1277,11 @@ static int __bpf_async_init(struct bpf_a - goto out; - } - -- /* allocate hrtimer via map_kmalloc to use memcg accounting */ -- cb = bpf_map_kmalloc_node(map, size, GFP_ATOMIC, map->numa_node); -+ /* Allocate via bpf_map_kmalloc_node() for memcg accounting. Until -+ * kmalloc_nolock() is available, avoid locking issues by using -+ * __GFP_HIGH (GFP_ATOMIC & ~__GFP_RECLAIM). -+ */ -+ cb = bpf_map_kmalloc_node(map, size, __GFP_HIGH, map->numa_node); - if (!cb) { - ret = -ENOMEM; - goto out; -@@ -2938,9 +2946,16 @@ static bool bpf_stack_walker(void *cooki - struct bpf_throw_ctx *ctx = cookie; - struct bpf_prog *prog; - -- if (!is_bpf_text_address(ip)) -- return !ctx->cnt; -+ /* -+ * The RCU read lock is held to safely traverse the latch tree, but we -+ * don't need its protection when accessing the prog, since it has an -+ * active stack frame on the current stack trace, and won't disappear. -+ */ -+ rcu_read_lock(); - prog = bpf_prog_ksym_find(ip); -+ rcu_read_unlock(); -+ if (!prog) -+ return !ctx->cnt; - ctx->cnt++; - if (bpf_is_subprog(prog)) - return true; -diff -purNx .git BPI-Router-Linux-kernel/kernel/bpf/Makefile BPI-Router-Linux-kernel-6.16.12/kernel/bpf/Makefile ---- BPI-Router-Linux-kernel/kernel/bpf/Makefile 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/bpf/Makefile 2025-10-22 13:53:56.767167926 -0400 -@@ -62,3 +62,4 @@ CFLAGS_REMOVE_bpf_lru_list.o = $(CC_FLAG - CFLAGS_REMOVE_queue_stack_maps.o = $(CC_FLAGS_FTRACE) - CFLAGS_REMOVE_lpm_trie.o = $(CC_FLAGS_FTRACE) - CFLAGS_REMOVE_ringbuf.o = $(CC_FLAGS_FTRACE) -+CFLAGS_REMOVE_rqspinlock.o = $(CC_FLAGS_FTRACE) -diff -purNx .git BPI-Router-Linux-kernel/kernel/bpf/preload/Kconfig BPI-Router-Linux-kernel-6.16.12/kernel/bpf/preload/Kconfig ---- BPI-Router-Linux-kernel/kernel/bpf/preload/Kconfig 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/bpf/preload/Kconfig 2025-10-22 13:53:56.771167907 -0400 -@@ -10,7 +10,6 @@ menuconfig BPF_PRELOAD - # The dependency on !COMPILE_TEST prevents it from being enabled - # in allmodconfig or allyesconfig configurations - depends on !COMPILE_TEST -- select USERMODE_DRIVER - help - This builds kernel module with several embedded BPF programs that are - pinned into BPF FS mount point as human readable files that are -diff -purNx .git BPI-Router-Linux-kernel/kernel/bpf/rqspinlock.c BPI-Router-Linux-kernel-6.16.12/kernel/bpf/rqspinlock.c ---- BPI-Router-Linux-kernel/kernel/bpf/rqspinlock.c 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/bpf/rqspinlock.c 2025-10-22 13:53:56.771167907 -0400 -@@ -471,7 +471,7 @@ queue: - * any MCS node. This is not the most elegant solution, but is - * simple enough. - */ -- if (unlikely(idx >= _Q_MAX_NODES)) { -+ if (unlikely(idx >= _Q_MAX_NODES || in_nmi())) { - lockevent_inc(lock_no_node); - RES_RESET_TIMEOUT(ts, RES_DEF_TIMEOUT); - while (!queued_spin_trylock(lock)) { -diff -purNx .git BPI-Router-Linux-kernel/kernel/bpf/syscall.c BPI-Router-Linux-kernel-6.16.12/kernel/bpf/syscall.c ---- BPI-Router-Linux-kernel/kernel/bpf/syscall.c 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/bpf/syscall.c 2025-10-22 13:53:56.771167907 -0400 -@@ -37,6 +37,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -53,6 +54,7 @@ - #define BPF_OBJ_FLAG_MASK (BPF_F_RDONLY | BPF_F_WRONLY) - - DEFINE_PER_CPU(int, bpf_prog_active); -+DEFINE_COOKIE(bpf_map_cookie); - static DEFINE_IDR(prog_idr); - static DEFINE_SPINLOCK(prog_idr_lock); - static DEFINE_IDR(map_idr); -@@ -885,6 +887,7 @@ static void bpf_map_free_deferred(struct - - security_bpf_map_free(map); - bpf_map_release_memcg(map); -+ bpf_map_owner_free(map); - bpf_map_free(map); - } - -@@ -979,12 +982,12 @@ static void bpf_map_show_fdinfo(struct s - struct bpf_map *map = filp->private_data; - u32 type = 0, jited = 0; - -- if (map_type_contains_progs(map)) { -- spin_lock(&map->owner.lock); -- type = map->owner.type; -- jited = map->owner.jited; -- spin_unlock(&map->owner.lock); -+ spin_lock(&map->owner_lock); -+ if (map->owner) { -+ type = map->owner->type; -+ jited = map->owner->jited; - } -+ spin_unlock(&map->owner_lock); - - seq_printf(m, - "map_type:\t%u\n" -@@ -1487,10 +1490,14 @@ static int map_create(union bpf_attr *at - if (err < 0) - goto free_map; - -+ preempt_disable(); -+ map->cookie = gen_cookie_next(&bpf_map_cookie); -+ preempt_enable(); -+ - atomic64_set(&map->refcnt, 1); - atomic64_set(&map->usercnt, 1); - mutex_init(&map->freeze_mutex); -- spin_lock_init(&map->owner.lock); -+ spin_lock_init(&map->owner_lock); - - if (attr->btf_key_type_id || attr->btf_value_type_id || - /* Even the map's value is a kernel's struct, -diff -purNx .git BPI-Router-Linux-kernel/kernel/bpf/sysfs_btf.c BPI-Router-Linux-kernel-6.16.12/kernel/bpf/sysfs_btf.c ---- BPI-Router-Linux-kernel/kernel/bpf/sysfs_btf.c 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/bpf/sysfs_btf.c 2025-10-22 13:53:56.771167907 -0400 -@@ -21,7 +21,7 @@ static int btf_sysfs_vmlinux_mmap(struct - { - unsigned long pages = PAGE_ALIGN(attr->size) >> PAGE_SHIFT; - size_t vm_size = vma->vm_end - vma->vm_start; -- phys_addr_t addr = virt_to_phys(__start_BTF); -+ phys_addr_t addr = __pa_symbol(__start_BTF); - unsigned long pfn = addr >> PAGE_SHIFT; - - if (attr->private != __start_BTF || !PAGE_ALIGNED(addr)) -diff -purNx .git BPI-Router-Linux-kernel/kernel/bpf/verifier.c BPI-Router-Linux-kernel-6.16.12/kernel/bpf/verifier.c ---- BPI-Router-Linux-kernel/kernel/bpf/verifier.c 2025-10-22 13:53:23.587327344 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/bpf/verifier.c 2025-10-22 13:53:56.771167907 -0400 -@@ -405,7 +405,8 @@ static bool reg_not_null(const struct bp - type == PTR_TO_MAP_KEY || - type == PTR_TO_SOCK_COMMON || - (type == PTR_TO_BTF_ID && is_trusted_reg(reg)) || -- type == PTR_TO_MEM; -+ type == PTR_TO_MEM || -+ type == CONST_PTR_TO_MAP; - } - - static struct btf_record *reg_btf_record(const struct bpf_reg_state *reg) -@@ -7027,8 +7028,7 @@ BTF_TYPE_SAFE_TRUSTED(struct file) { - struct inode *f_inode; - }; - --BTF_TYPE_SAFE_TRUSTED(struct dentry) { -- /* no negative dentry-s in places where bpf can see it */ -+BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct dentry) { - struct inode *d_inode; - }; - -@@ -7066,7 +7066,6 @@ static bool type_is_trusted(struct bpf_v - BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct bpf_iter__task)); - BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct linux_binprm)); - BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct file)); -- BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct dentry)); - - return btf_nested_type_is_trusted(&env->log, reg, field_name, btf_id, "__safe_trusted"); - } -@@ -7076,6 +7075,7 @@ static bool type_is_trusted_or_null(stru - const char *field_name, u32 btf_id) - { - BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct socket)); -+ BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct dentry)); - - return btf_nested_type_is_trusted(&env->log, reg, field_name, btf_id, - "__safe_trusted_or_null"); -@@ -8405,6 +8405,10 @@ static int process_timer_func(struct bpf - verifier_bug(env, "Two map pointers in a timer helper"); - return -EFAULT; - } -+ if (IS_ENABLED(CONFIG_PREEMPT_RT)) { -+ verbose(env, "bpf_timer cannot be used for PREEMPT_RT.\n"); -+ return -EOPNOTSUPP; -+ } - meta->map_uid = reg->map_uid; - meta->map_ptr = map; - return 0; -@@ -11206,7 +11210,7 @@ static int get_helper_proto(struct bpf_v - return -EINVAL; - - *ptr = env->ops->get_func_proto(func_id, env->prog); -- return *ptr ? 0 : -EINVAL; -+ return *ptr && (*ptr)->func ? 0 : -EINVAL; - } - - static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn, -@@ -16029,6 +16033,10 @@ static void regs_refine_cond_op(struct b - if (!is_reg_const(reg2, is_jmp32)) - break; - val = reg_const_value(reg2, is_jmp32); -+ /* Forget the ranges before narrowing tnums, to avoid invariant -+ * violations if we're on a dead branch. -+ */ -+ __mark_reg_unbounded(reg1); - if (is_jmp32) { - t = tnum_and(tnum_subreg(reg1->var_off), tnum_const(~val)); - reg1->var_off = tnum_with_subreg(reg1->var_off, t); -@@ -23672,6 +23680,7 @@ static bool can_jump(struct bpf_insn *in - case BPF_JSLT: - case BPF_JSLE: - case BPF_JCOND: -+ case BPF_JSET: - return true; - } - -diff -purNx .git BPI-Router-Linux-kernel/kernel/cgroup/cgroup.c BPI-Router-Linux-kernel-6.16.12/kernel/cgroup/cgroup.c ---- BPI-Router-Linux-kernel/kernel/cgroup/cgroup.c 2025-10-22 13:53:23.587327344 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/cgroup/cgroup.c 2025-10-22 13:53:56.771167907 -0400 -@@ -126,8 +126,31 @@ DEFINE_PERCPU_RWSEM(cgroup_threadgroup_r - * of concurrent destructions. Use a separate workqueue so that cgroup - * destruction work items don't end up filling up max_active of system_wq - * which may lead to deadlock. -- */ --static struct workqueue_struct *cgroup_destroy_wq; -+ * -+ * A cgroup destruction should enqueue work sequentially to: -+ * cgroup_offline_wq: use for css offline work -+ * cgroup_release_wq: use for css release work -+ * cgroup_free_wq: use for free work -+ * -+ * Rationale for using separate workqueues: -+ * The cgroup root free work may depend on completion of other css offline -+ * operations. If all tasks were enqueued to a single workqueue, this could -+ * create a deadlock scenario where: -+ * - Free work waits for other css offline work to complete. -+ * - But other css offline work is queued after free work in the same queue. -+ * -+ * Example deadlock scenario with single workqueue (cgroup_destroy_wq): -+ * 1. umount net_prio -+ * 2. net_prio root destruction enqueues work to cgroup_destroy_wq (CPUx) -+ * 3. perf_event CSS A offline enqueues work to same cgroup_destroy_wq (CPUx) -+ * 4. net_prio cgroup_destroy_root->cgroup_lock_and_drain_offline. -+ * 5. net_prio root destruction blocks waiting for perf_event CSS A offline, -+ * which can never complete as it's behind in the same queue and -+ * workqueue's max_active is 1. -+ */ -+static struct workqueue_struct *cgroup_offline_wq; -+static struct workqueue_struct *cgroup_release_wq; -+static struct workqueue_struct *cgroup_free_wq; - - /* generate an array of cgroup subsystem pointers */ - #define SUBSYS(_x) [_x ## _cgrp_id] = &_x ## _cgrp_subsys, -@@ -5553,7 +5576,7 @@ static void css_release_work_fn(struct w - cgroup_unlock(); - - INIT_RCU_WORK(&css->destroy_rwork, css_free_rwork_fn); -- queue_rcu_work(cgroup_destroy_wq, &css->destroy_rwork); -+ queue_rcu_work(cgroup_free_wq, &css->destroy_rwork); - } - - static void css_release(struct percpu_ref *ref) -@@ -5562,7 +5585,7 @@ static void css_release(struct percpu_re - container_of(ref, struct cgroup_subsys_state, refcnt); - - INIT_WORK(&css->destroy_work, css_release_work_fn); -- queue_work(cgroup_destroy_wq, &css->destroy_work); -+ queue_work(cgroup_release_wq, &css->destroy_work); - } - - static void init_and_link_css(struct cgroup_subsys_state *css, -@@ -5696,7 +5719,7 @@ err_list_del: - list_del_rcu(&css->sibling); - err_free_css: - INIT_RCU_WORK(&css->destroy_rwork, css_free_rwork_fn); -- queue_rcu_work(cgroup_destroy_wq, &css->destroy_rwork); -+ queue_rcu_work(cgroup_free_wq, &css->destroy_rwork); - return ERR_PTR(err); - } - -@@ -5934,7 +5957,7 @@ static void css_killed_ref_fn(struct per - - if (atomic_dec_and_test(&css->online_cnt)) { - INIT_WORK(&css->destroy_work, css_killed_work_fn); -- queue_work(cgroup_destroy_wq, &css->destroy_work); -+ queue_work(cgroup_offline_wq, &css->destroy_work); - } - } - -@@ -6320,8 +6343,14 @@ static int __init cgroup_wq_init(void) - * We would prefer to do this in cgroup_init() above, but that - * is called before init_workqueues(): so leave this until after. - */ -- cgroup_destroy_wq = alloc_workqueue("cgroup_destroy", 0, 1); -- BUG_ON(!cgroup_destroy_wq); -+ cgroup_offline_wq = alloc_workqueue("cgroup_offline", 0, 1); -+ BUG_ON(!cgroup_offline_wq); -+ -+ cgroup_release_wq = alloc_workqueue("cgroup_release", 0, 1); -+ BUG_ON(!cgroup_release_wq); -+ -+ cgroup_free_wq = alloc_workqueue("cgroup_free", 0, 1); -+ BUG_ON(!cgroup_free_wq); - return 0; - } - core_initcall(cgroup_wq_init); -diff -purNx .git BPI-Router-Linux-kernel/kernel/cgroup/cgroup-v1.c BPI-Router-Linux-kernel-6.16.12/kernel/cgroup/cgroup-v1.c ---- BPI-Router-Linux-kernel/kernel/cgroup/cgroup-v1.c 2025-10-22 13:53:23.587327344 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/cgroup/cgroup-v1.c 2025-10-22 13:53:56.771167907 -0400 -@@ -32,6 +32,9 @@ static u16 cgroup_no_v1_mask; - /* disable named v1 mounts */ - static bool cgroup_no_v1_named; - -+/* Show unavailable controllers in /proc/cgroups */ -+static bool proc_show_all; -+ - /* - * pidlist destructions need to be flushed on cgroup destruction. Use a - * separate workqueue as flush domain. -@@ -683,10 +686,11 @@ int proc_cgroupstats_show(struct seq_fil - */ - - for_each_subsys(ss, i) { -- if (cgroup1_subsys_absent(ss)) -- continue; - cgrp_v1_visible |= ss->root != &cgrp_dfl_root; - -+ if (!proc_show_all && cgroup1_subsys_absent(ss)) -+ continue; -+ - seq_printf(m, "%s\t%d\t%d\t%d\n", - ss->legacy_name, ss->root->hierarchy_id, - atomic_read(&ss->root->nr_cgrps), -@@ -1359,3 +1363,9 @@ static int __init cgroup_no_v1(char *str - return 1; - } - __setup("cgroup_no_v1=", cgroup_no_v1); -+ -+static int __init cgroup_v1_proc(char *str) -+{ -+ return (kstrtobool(str, &proc_show_all) == 0); -+} -+__setup("cgroup_v1_proc=", cgroup_v1_proc); -diff -purNx .git BPI-Router-Linux-kernel/kernel/cgroup/cpuset.c BPI-Router-Linux-kernel-6.16.12/kernel/cgroup/cpuset.c ---- BPI-Router-Linux-kernel/kernel/cgroup/cpuset.c 2025-10-22 13:53:23.587327344 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/cgroup/cpuset.c 2025-10-22 13:53:56.771167907 -0400 -@@ -280,7 +280,7 @@ static inline void check_insane_mems_con - { - if (!cpusets_insane_config() && - movable_only_nodes(nodes)) { -- static_branch_enable(&cpusets_insane_config_key); -+ static_branch_enable_cpuslocked(&cpusets_insane_config_key); - pr_info("Unsupported (movable nodes only) cpuset configuration detected (nmask=%*pbl)!\n" - "Cpuset allocations might fail even with a lot of memory available.\n", - nodemask_pr_args(nodes)); -@@ -1843,7 +1843,7 @@ static int update_parent_effective_cpuma - if (is_partition_valid(cs)) - adding = cpumask_and(tmp->addmask, - xcpus, parent->effective_xcpus); -- } else if (is_partition_invalid(cs) && -+ } else if (is_partition_invalid(cs) && !cpumask_empty(xcpus) && - cpumask_subset(xcpus, parent->effective_xcpus)) { - struct cgroup_subsys_state *css; - struct cpuset *child; -@@ -3870,9 +3870,10 @@ retry: - partcmd = partcmd_invalidate; - /* - * On the other hand, an invalid partition root may be transitioned -- * back to a regular one. -+ * back to a regular one with a non-empty effective xcpus. - */ -- else if (is_partition_valid(parent) && is_partition_invalid(cs)) -+ else if (is_partition_valid(parent) && is_partition_invalid(cs) && -+ !cpumask_empty(cs->effective_xcpus)) - partcmd = partcmd_update; - - if (partcmd >= 0) { -diff -purNx .git BPI-Router-Linux-kernel/kernel/cgroup/legacy_freezer.c BPI-Router-Linux-kernel-6.16.12/kernel/cgroup/legacy_freezer.c ---- BPI-Router-Linux-kernel/kernel/cgroup/legacy_freezer.c 2025-10-22 13:53:23.587327344 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/cgroup/legacy_freezer.c 2025-10-22 13:53:56.771167907 -0400 -@@ -66,15 +66,9 @@ static struct freezer *parent_freezer(st - bool cgroup_freezing(struct task_struct *task) - { - bool ret; -- unsigned int state; - - rcu_read_lock(); -- /* Check if the cgroup is still FREEZING, but not FROZEN. The extra -- * !FROZEN check is required, because the FREEZING bit is not cleared -- * when the state FROZEN is reached. -- */ -- state = task_freezer(task)->state; -- ret = (state & CGROUP_FREEZING) && !(state & CGROUP_FROZEN); -+ ret = task_freezer(task)->state & CGROUP_FREEZING; - rcu_read_unlock(); - - return ret; -@@ -188,13 +182,12 @@ static void freezer_attach(struct cgroup - if (!(freezer->state & CGROUP_FREEZING)) { - __thaw_task(task); - } else { -- freeze_task(task); -- - /* clear FROZEN and propagate upwards */ - while (freezer && (freezer->state & CGROUP_FROZEN)) { - freezer->state &= ~CGROUP_FROZEN; - freezer = parent_freezer(freezer); - } -+ freeze_task(task); - } - } - -diff -purNx .git BPI-Router-Linux-kernel/kernel/cgroup/rstat.c BPI-Router-Linux-kernel-6.16.12/kernel/cgroup/rstat.c ---- BPI-Router-Linux-kernel/kernel/cgroup/rstat.c 2025-10-22 13:53:23.587327344 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/cgroup/rstat.c 2025-10-22 13:53:56.771167907 -0400 -@@ -488,6 +488,9 @@ void css_rstat_exit(struct cgroup_subsys - if (!css_uses_rstat(css)) - return; - -+ if (!css->rstat_cpu) -+ return; -+ - css_rstat_flush(css); - - /* sanity check */ -diff -purNx .git BPI-Router-Linux-kernel/kernel/dma/contiguous.c BPI-Router-Linux-kernel-6.16.12/kernel/dma/contiguous.c ---- BPI-Router-Linux-kernel/kernel/dma/contiguous.c 2025-10-22 13:53:23.587327344 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/dma/contiguous.c 2025-10-22 13:53:56.771167907 -0400 -@@ -222,7 +222,10 @@ void __init dma_contiguous_reserve(phys_ - if (size_cmdline != -1) { - selected_size = size_cmdline; - selected_base = base_cmdline; -- selected_limit = min_not_zero(limit_cmdline, limit); -+ -+ /* Hornor the user setup dma address limit */ -+ selected_limit = limit_cmdline ?: limit; -+ - if (base_cmdline + size_cmdline == limit_cmdline) - fixed = true; - } else { -@@ -480,8 +483,6 @@ static int __init rmem_cma_setup(struct - pr_err("Reserved memory: unable to setup CMA region\n"); - return err; - } -- /* Architecture specific contiguous memory fixup. */ -- dma_contiguous_early_fixup(rmem->base, rmem->size); - - if (default_cma) - dma_contiguous_default_area = cma; -diff -purNx .git BPI-Router-Linux-kernel/kernel/dma/debug.c BPI-Router-Linux-kernel-6.16.12/kernel/dma/debug.c ---- BPI-Router-Linux-kernel/kernel/dma/debug.c 2025-10-22 13:53:23.587327344 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/dma/debug.c 2025-10-22 13:53:56.771167907 -0400 -@@ -39,6 +39,7 @@ enum { - dma_debug_sg, - dma_debug_coherent, - dma_debug_resource, -+ dma_debug_noncoherent, - }; - - enum map_err_types { -@@ -141,6 +142,7 @@ static const char *type2name[] = { - [dma_debug_sg] = "scatter-gather", - [dma_debug_coherent] = "coherent", - [dma_debug_resource] = "resource", -+ [dma_debug_noncoherent] = "noncoherent", - }; - - static const char *dir2name[] = { -@@ -993,7 +995,8 @@ static void check_unmap(struct dma_debug - "[mapped as %s] [unmapped as %s]\n", - ref->dev_addr, ref->size, - type2name[entry->type], type2name[ref->type]); -- } else if (entry->type == dma_debug_coherent && -+ } else if ((entry->type == dma_debug_coherent || -+ entry->type == dma_debug_noncoherent) && - ref->paddr != entry->paddr) { - err_printk(ref->dev, entry, "device driver frees " - "DMA memory with different CPU address " -@@ -1581,6 +1584,49 @@ void debug_dma_sync_sg_for_device(struct - } - } - -+void debug_dma_alloc_pages(struct device *dev, struct page *page, -+ size_t size, int direction, -+ dma_addr_t dma_addr, -+ unsigned long attrs) -+{ -+ struct dma_debug_entry *entry; -+ -+ if (unlikely(dma_debug_disabled())) -+ return; -+ -+ entry = dma_entry_alloc(); -+ if (!entry) -+ return; -+ -+ entry->type = dma_debug_noncoherent; -+ entry->dev = dev; -+ entry->paddr = page_to_phys(page); -+ entry->size = size; -+ entry->dev_addr = dma_addr; -+ entry->direction = direction; -+ -+ add_dma_entry(entry, attrs); -+} -+ -+void debug_dma_free_pages(struct device *dev, struct page *page, -+ size_t size, int direction, -+ dma_addr_t dma_addr) -+{ -+ struct dma_debug_entry ref = { -+ .type = dma_debug_noncoherent, -+ .dev = dev, -+ .paddr = page_to_phys(page), -+ .dev_addr = dma_addr, -+ .size = size, -+ .direction = direction, -+ }; -+ -+ if (unlikely(dma_debug_disabled())) -+ return; -+ -+ check_unmap(&ref); -+} -+ - static int __init dma_debug_driver_setup(char *str) - { - int i; -diff -purNx .git BPI-Router-Linux-kernel/kernel/dma/debug.h BPI-Router-Linux-kernel-6.16.12/kernel/dma/debug.h ---- BPI-Router-Linux-kernel/kernel/dma/debug.h 2025-10-22 13:53:23.591327325 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/dma/debug.h 2025-10-22 13:53:56.771167907 -0400 -@@ -54,6 +54,13 @@ extern void debug_dma_sync_sg_for_cpu(st - extern void debug_dma_sync_sg_for_device(struct device *dev, - struct scatterlist *sg, - int nelems, int direction); -+extern void debug_dma_alloc_pages(struct device *dev, struct page *page, -+ size_t size, int direction, -+ dma_addr_t dma_addr, -+ unsigned long attrs); -+extern void debug_dma_free_pages(struct device *dev, struct page *page, -+ size_t size, int direction, -+ dma_addr_t dma_addr); - #else /* CONFIG_DMA_API_DEBUG */ - static inline void debug_dma_map_page(struct device *dev, struct page *page, - size_t offset, size_t size, -@@ -126,5 +133,18 @@ static inline void debug_dma_sync_sg_for - int nelems, int direction) - { - } -+ -+static inline void debug_dma_alloc_pages(struct device *dev, struct page *page, -+ size_t size, int direction, -+ dma_addr_t dma_addr, -+ unsigned long attrs) -+{ -+} -+ -+static inline void debug_dma_free_pages(struct device *dev, struct page *page, -+ size_t size, int direction, -+ dma_addr_t dma_addr) -+{ -+} - #endif /* CONFIG_DMA_API_DEBUG */ - #endif /* _KERNEL_DMA_DEBUG_H */ -diff -purNx .git BPI-Router-Linux-kernel/kernel/dma/mapping.c BPI-Router-Linux-kernel-6.16.12/kernel/dma/mapping.c ---- BPI-Router-Linux-kernel/kernel/dma/mapping.c 2025-10-22 13:53:23.591327325 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/dma/mapping.c 2025-10-22 13:53:56.775167887 -0400 -@@ -712,7 +712,7 @@ struct page *dma_alloc_pages(struct devi - if (page) { - trace_dma_alloc_pages(dev, page_to_virt(page), *dma_handle, - size, dir, gfp, 0); -- debug_dma_map_page(dev, page, 0, size, dir, *dma_handle, 0); -+ debug_dma_alloc_pages(dev, page, size, dir, *dma_handle, 0); - } else { - trace_dma_alloc_pages(dev, NULL, 0, size, dir, gfp, 0); - } -@@ -738,7 +738,7 @@ void dma_free_pages(struct device *dev, - dma_addr_t dma_handle, enum dma_data_direction dir) - { - trace_dma_free_pages(dev, page_to_virt(page), dma_handle, size, dir, 0); -- debug_dma_unmap_page(dev, dma_handle, size, dir); -+ debug_dma_free_pages(dev, page, size, dir, dma_handle); - __dma_free_pages(dev, size, page, dma_handle, dir); - } - EXPORT_SYMBOL_GPL(dma_free_pages); -diff -purNx .git BPI-Router-Linux-kernel/kernel/dma/pool.c BPI-Router-Linux-kernel-6.16.12/kernel/dma/pool.c ---- BPI-Router-Linux-kernel/kernel/dma/pool.c 2025-10-22 13:53:23.591327325 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/dma/pool.c 2025-10-22 13:53:56.775167887 -0400 -@@ -102,8 +102,8 @@ static int atomic_pool_expand(struct gen - - #ifdef CONFIG_DMA_DIRECT_REMAP - addr = dma_common_contiguous_remap(page, pool_size, -- pgprot_dmacoherent(PAGE_KERNEL), -- __builtin_return_address(0)); -+ pgprot_decrypted(pgprot_dmacoherent(PAGE_KERNEL)), -+ __builtin_return_address(0)); - if (!addr) - goto free_page; - #else -diff -purNx .git BPI-Router-Linux-kernel/kernel/events/core.c BPI-Router-Linux-kernel-6.16.12/kernel/events/core.c ---- BPI-Router-Linux-kernel/kernel/events/core.c 2025-10-22 13:53:23.591327325 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/events/core.c 2025-10-22 13:53:56.775167887 -0400 -@@ -207,6 +207,19 @@ static void perf_ctx_unlock(struct perf_ - __perf_ctx_unlock(&cpuctx->ctx); - } - -+typedef struct { -+ struct perf_cpu_context *cpuctx; -+ struct perf_event_context *ctx; -+} class_perf_ctx_lock_t; -+ -+static inline void class_perf_ctx_lock_destructor(class_perf_ctx_lock_t *_T) -+{ perf_ctx_unlock(_T->cpuctx, _T->ctx); } -+ -+static inline class_perf_ctx_lock_t -+class_perf_ctx_lock_constructor(struct perf_cpu_context *cpuctx, -+ struct perf_event_context *ctx) -+{ perf_ctx_lock(cpuctx, ctx); return (class_perf_ctx_lock_t){ cpuctx, ctx }; } -+ - #define TASK_TOMBSTONE ((void *)-1L) - - static bool is_kernel_event(struct perf_event *event) -@@ -938,13 +951,19 @@ static void perf_cgroup_switch(struct ta - if (READ_ONCE(cpuctx->cgrp) == NULL) - return; - -- WARN_ON_ONCE(cpuctx->ctx.nr_cgroups == 0); -- - cgrp = perf_cgroup_from_task(task, NULL); - if (READ_ONCE(cpuctx->cgrp) == cgrp) - return; - -- perf_ctx_lock(cpuctx, cpuctx->task_ctx); -+ guard(perf_ctx_lock)(cpuctx, cpuctx->task_ctx); -+ /* -+ * Re-check, could've raced vs perf_remove_from_context(). -+ */ -+ if (READ_ONCE(cpuctx->cgrp) == NULL) -+ return; -+ -+ WARN_ON_ONCE(cpuctx->ctx.nr_cgroups == 0); -+ - perf_ctx_disable(&cpuctx->ctx, true); - - ctx_sched_out(&cpuctx->ctx, NULL, EVENT_ALL|EVENT_CGROUP); -@@ -962,7 +981,6 @@ static void perf_cgroup_switch(struct ta - ctx_sched_in(&cpuctx->ctx, NULL, EVENT_ALL|EVENT_CGROUP); - - perf_ctx_enable(&cpuctx->ctx, true); -- perf_ctx_unlock(cpuctx, cpuctx->task_ctx); - } - - static int perf_cgroup_ensure_storage(struct perf_event *event, -@@ -2120,18 +2138,6 @@ list_del_event(struct perf_event *event, - if (event->group_leader == event) - del_event_from_groups(event, ctx); - -- /* -- * If event was in error state, then keep it -- * that way, otherwise bogus counts will be -- * returned on read(). The only way to get out -- * of error state is by explicit re-enabling -- * of the event -- */ -- if (event->state > PERF_EVENT_STATE_OFF) { -- perf_cgroup_event_disable(event, ctx); -- perf_event_set_state(event, PERF_EVENT_STATE_OFF); -- } -- - ctx->generation++; - event->pmu_ctx->nr_events--; - } -@@ -2149,8 +2155,9 @@ perf_aux_output_match(struct perf_event - } - - static void put_event(struct perf_event *event); --static void event_sched_out(struct perf_event *event, -- struct perf_event_context *ctx); -+static void __event_disable(struct perf_event *event, -+ struct perf_event_context *ctx, -+ enum perf_event_state state); - - static void perf_put_aux_event(struct perf_event *event) - { -@@ -2183,8 +2190,7 @@ static void perf_put_aux_event(struct pe - * state so that we don't try to schedule it again. Note - * that perf_event_enable() will clear the ERROR status. - */ -- event_sched_out(iter, ctx); -- perf_event_set_state(event, PERF_EVENT_STATE_ERROR); -+ __event_disable(iter, ctx, PERF_EVENT_STATE_ERROR); - } - } - -@@ -2242,18 +2248,6 @@ static inline struct list_head *get_even - &event->pmu_ctx->flexible_active; - } - --/* -- * Events that have PERF_EV_CAP_SIBLING require being part of a group and -- * cannot exist on their own, schedule them out and move them into the ERROR -- * state. Also see _perf_event_enable(), it will not be able to recover -- * this ERROR state. -- */ --static inline void perf_remove_sibling_event(struct perf_event *event) --{ -- event_sched_out(event, event->ctx); -- perf_event_set_state(event, PERF_EVENT_STATE_ERROR); --} -- - static void perf_group_detach(struct perf_event *event) - { - struct perf_event *leader = event->group_leader; -@@ -2289,8 +2283,15 @@ static void perf_group_detach(struct per - */ - list_for_each_entry_safe(sibling, tmp, &event->sibling_list, sibling_list) { - -+ /* -+ * Events that have PERF_EV_CAP_SIBLING require being part of -+ * a group and cannot exist on their own, schedule them out -+ * and move them into the ERROR state. Also see -+ * _perf_event_enable(), it will not be able to recover this -+ * ERROR state. -+ */ - if (sibling->event_caps & PERF_EV_CAP_SIBLING) -- perf_remove_sibling_event(sibling); -+ __event_disable(sibling, ctx, PERF_EVENT_STATE_ERROR); - - sibling->group_leader = sibling; - list_del_init(&sibling->sibling_list); -@@ -2493,11 +2494,14 @@ __perf_remove_from_context(struct perf_e - state = PERF_EVENT_STATE_EXIT; - if (flags & DETACH_REVOKE) - state = PERF_EVENT_STATE_REVOKED; -- if (flags & DETACH_DEAD) { -- event->pending_disable = 1; -+ if (flags & DETACH_DEAD) - state = PERF_EVENT_STATE_DEAD; -- } -+ - event_sched_out(event, ctx); -+ -+ if (event->state > PERF_EVENT_STATE_OFF) -+ perf_cgroup_event_disable(event, ctx); -+ - perf_event_set_state(event, min(event->state, state)); - - if (flags & DETACH_GROUP) -@@ -2562,6 +2566,15 @@ static void perf_remove_from_context(str - event_function_call(event, __perf_remove_from_context, (void *)flags); - } - -+static void __event_disable(struct perf_event *event, -+ struct perf_event_context *ctx, -+ enum perf_event_state state) -+{ -+ event_sched_out(event, ctx); -+ perf_cgroup_event_disable(event, ctx); -+ perf_event_set_state(event, state); -+} -+ - /* - * Cross CPU call to disable a performance event - */ -@@ -2576,13 +2589,18 @@ static void __perf_event_disable(struct - perf_pmu_disable(event->pmu_ctx->pmu); - ctx_time_update_event(ctx, event); - -+ /* -+ * When disabling a group leader, the whole group becomes ineligible -+ * to run, so schedule out the full group. -+ */ - if (event == event->group_leader) - group_sched_out(event, ctx); -- else -- event_sched_out(event, ctx); - -- perf_event_set_state(event, PERF_EVENT_STATE_OFF); -- perf_cgroup_event_disable(event, ctx); -+ /* -+ * But only mark the leader OFF; the siblings will remain -+ * INACTIVE. -+ */ -+ __event_disable(event, ctx, PERF_EVENT_STATE_OFF); - - perf_pmu_enable(event->pmu_ctx->pmu); - } -@@ -2647,6 +2665,9 @@ static void perf_log_itrace_start(struct - - static void perf_event_unthrottle(struct perf_event *event, bool start) - { -+ if (event->state != PERF_EVENT_STATE_ACTIVE) -+ return; -+ - event->hw.interrupts = 0; - if (start) - event->pmu->start(event, 0); -@@ -2656,8 +2677,11 @@ static void perf_event_unthrottle(struct - - static void perf_event_throttle(struct perf_event *event) - { -- event->pmu->stop(event, 0); -+ if (event->state != PERF_EVENT_STATE_ACTIVE) -+ return; -+ - event->hw.interrupts = MAX_INTERRUPTS; -+ event->pmu->stop(event, 0); - if (event == event->group_leader) - perf_log_throttle(event, 0); - } -@@ -6824,10 +6848,20 @@ static vm_fault_t perf_mmap_pfn_mkwrite( - return vmf->pgoff == 0 ? 0 : VM_FAULT_SIGBUS; - } - -+static int perf_mmap_may_split(struct vm_area_struct *vma, unsigned long addr) -+{ -+ /* -+ * Forbid splitting perf mappings to prevent refcount leaks due to -+ * the resulting non-matching offsets and sizes. See open()/close(). -+ */ -+ return -EINVAL; -+} -+ - static const struct vm_operations_struct perf_mmap_vmops = { - .open = perf_mmap_open, - .close = perf_mmap_close, /* non mergeable */ - .pfn_mkwrite = perf_mmap_pfn_mkwrite, -+ .may_split = perf_mmap_may_split, - }; - - static int map_range(struct perf_buffer *rb, struct vm_area_struct *vma) -@@ -7033,8 +7067,6 @@ static int perf_mmap(struct file *file, - ret = 0; - goto unlock; - } -- -- atomic_set(&rb->aux_mmap_count, 1); - } - - user_lock_limit = sysctl_perf_event_mlock >> (PAGE_SHIFT - 10); -@@ -7097,15 +7129,16 @@ static int perf_mmap(struct file *file, - perf_event_update_time(event); - perf_event_init_userpage(event); - perf_event_update_userpage(event); -+ ret = 0; - } else { - ret = rb_alloc_aux(rb, event, vma->vm_pgoff, nr_pages, - event->attr.aux_watermark, flags); -- if (!ret) -+ if (!ret) { -+ atomic_set(&rb->aux_mmap_count, 1); - rb->aux_mmap_locked = extra; -+ } - } - -- ret = 0; -- - unlock: - if (!ret) { - atomic_long_add(user_extra, &user->locked_vm); -@@ -7113,6 +7146,7 @@ unlock: - - atomic_inc(&event->mmap_count); - } else if (rb) { -+ /* AUX allocation failed */ - atomic_dec(&rb->mmap_count); - } - aux_unlock: -@@ -7120,6 +7154,9 @@ aux_unlock: - mutex_unlock(aux_mutex); - mutex_unlock(&event->mmap_mutex); - -+ if (ret) -+ return ret; -+ - /* - * Since pinned accounting is per vm we cannot allow fork() to copy our - * vma. -@@ -7127,13 +7164,20 @@ aux_unlock: - vm_flags_set(vma, VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP); - vma->vm_ops = &perf_mmap_vmops; - -- if (!ret) -- ret = map_range(rb, vma); -- - mapped = get_mapped(event, event_mapped); - if (mapped) - mapped(event, vma->vm_mm); - -+ /* -+ * Try to map it into the page table. On fail, invoke -+ * perf_mmap_close() to undo the above, as the callsite expects -+ * full cleanup in this case and therefore does not invoke -+ * vmops::close(). -+ */ -+ ret = map_range(rb, vma); -+ if (ret) -+ perf_mmap_close(vma); -+ - return ret; - } - -@@ -7186,18 +7230,18 @@ void perf_event_wakeup(struct perf_event - static void perf_sigtrap(struct perf_event *event) - { - /* -- * We'd expect this to only occur if the irq_work is delayed and either -- * ctx->task or current has changed in the meantime. This can be the -- * case on architectures that do not implement arch_irq_work_raise(). -+ * Both perf_pending_task() and perf_pending_irq() can race with the -+ * task exiting. - */ -- if (WARN_ON_ONCE(event->ctx->task != current)) -+ if (current->flags & PF_EXITING) - return; - - /* -- * Both perf_pending_task() and perf_pending_irq() can race with the -- * task exiting. -+ * We'd expect this to only occur if the irq_work is delayed and either -+ * ctx->task or current has changed in the meantime. This can be the -+ * case on architectures that do not implement arch_irq_work_raise(). - */ -- if (current->flags & PF_EXITING) -+ if (WARN_ON_ONCE(event->ctx->task != current)) - return; - - send_sig_perf((void __user *)event->pending_addr, -@@ -7233,15 +7277,15 @@ static void __perf_pending_disable(struc - * CPU-A CPU-B - * - * perf_event_disable_inatomic() -- * @pending_disable = CPU-A; -+ * @pending_disable = 1; - * irq_work_queue(); - * - * sched-out -- * @pending_disable = -1; -+ * @pending_disable = 0; - * - * sched-in - * perf_event_disable_inatomic() -- * @pending_disable = CPU-B; -+ * @pending_disable = 1; - * irq_work_queue(); // FAILS - * - * irq_work_run() -@@ -7439,6 +7483,10 @@ perf_sample_ustack_size(u16 stack_size, - if (!regs) - return 0; - -+ /* No mm, no stack, no dump. */ -+ if (!current->mm) -+ return 0; -+ - /* - * Check if we fit in with the requested stack size into the: - * - TASK_SIZE -@@ -8150,6 +8198,9 @@ perf_callchain(struct perf_event *event, - const u32 max_stack = event->attr.sample_max_stack; - struct perf_callchain_entry *callchain; - -+ if (!current->mm) -+ user = false; -+ - if (!kernel && !user) - return &__empty_callchain; - -@@ -10279,6 +10330,7 @@ static int __perf_event_overflow(struct - ret = 1; - event->pending_kill = POLL_HUP; - perf_event_disable_inatomic(event); -+ event->pmu->stop(event, 0); - } - - if (event->attr.sigtrap) { -@@ -11091,7 +11143,7 @@ static int perf_uprobe_event_init(struct - if (event->attr.type != perf_uprobe.type) - return -ENOENT; - -- if (!perfmon_capable()) -+ if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - - /* -@@ -11749,7 +11801,12 @@ static void perf_swevent_cancel_hrtimer( - { - struct hw_perf_event *hwc = &event->hw; - -- if (is_sampling_event(event)) { -+ /* -+ * The throttle can be triggered in the hrtimer handler. -+ * The HRTIMER_NORESTART should be used to stop the timer, -+ * rather than hrtimer_cancel(). See perf_swevent_hrtimer() -+ */ -+ if (is_sampling_event(event) && (hwc->interrupts != MAX_INTERRUPTS)) { - ktime_t remaining = hrtimer_get_remaining(&hwc->hrtimer); - local64_set(&hwc->period_left, ktime_to_ns(remaining)); - -@@ -11804,7 +11861,8 @@ static void cpu_clock_event_start(struct - static void cpu_clock_event_stop(struct perf_event *event, int flags) - { - perf_swevent_cancel_hrtimer(event); -- cpu_clock_event_update(event); -+ if (flags & PERF_EF_UPDATE) -+ cpu_clock_event_update(event); - } - - static int cpu_clock_event_add(struct perf_event *event, int flags) -@@ -11882,7 +11940,8 @@ static void task_clock_event_start(struc - static void task_clock_event_stop(struct perf_event *event, int flags) - { - perf_swevent_cancel_hrtimer(event); -- task_clock_event_update(event, event->ctx->time); -+ if (flags & PERF_EF_UPDATE) -+ task_clock_event_update(event, event->ctx->time); - } - - static int task_clock_event_add(struct perf_event *event, int flags) -diff -purNx .git BPI-Router-Linux-kernel/kernel/events/ring_buffer.c BPI-Router-Linux-kernel-6.16.12/kernel/events/ring_buffer.c ---- BPI-Router-Linux-kernel/kernel/events/ring_buffer.c 2025-10-22 13:53:23.591327325 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/events/ring_buffer.c 2025-10-22 13:53:56.775167887 -0400 -@@ -441,7 +441,7 @@ void *perf_aux_output_begin(struct perf_ - * store that will be enabled on successful return - */ - if (!handle->size) { /* A, matches D */ -- event->pending_disable = smp_processor_id(); -+ perf_event_disable_inatomic(handle->event); - perf_output_wakeup(handle); - WRITE_ONCE(rb->aux_nest, 0); - goto err_put; -@@ -526,7 +526,7 @@ void perf_aux_output_end(struct perf_out - - if (wakeup) { - if (handle->aux_flags & PERF_AUX_FLAG_TRUNCATED) -- handle->event->pending_disable = smp_processor_id(); -+ perf_event_disable_inatomic(handle->event); - perf_output_wakeup(handle); - } - -diff -purNx .git BPI-Router-Linux-kernel/kernel/events/uprobes.c BPI-Router-Linux-kernel-6.16.12/kernel/events/uprobes.c ---- BPI-Router-Linux-kernel/kernel/events/uprobes.c 2025-10-22 13:53:23.591327325 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/events/uprobes.c 2025-10-22 13:53:56.775167887 -0400 -@@ -581,8 +581,8 @@ retry: - - out: - /* Revert back reference counter if instruction update failed. */ -- if (ret < 0 && is_register && ref_ctr_updated) -- update_ref_ctr(uprobe, mm, -1); -+ if (ret < 0 && ref_ctr_updated) -+ update_ref_ctr(uprobe, mm, is_register ? -1 : 1); - - /* try collapse pmd for compound page */ - if (ret > 0) -diff -purNx .git BPI-Router-Linux-kernel/kernel/exit.c BPI-Router-Linux-kernel-6.16.12/kernel/exit.c ---- BPI-Router-Linux-kernel/kernel/exit.c 2025-10-22 13:53:23.591327325 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/exit.c 2025-10-22 13:53:56.775167887 -0400 -@@ -940,6 +940,15 @@ void __noreturn do_exit(long code) - taskstats_exit(tsk, group_dead); - trace_sched_process_exit(tsk, group_dead); - -+ /* -+ * Since sampling can touch ->mm, make sure to stop everything before we -+ * tear it down. -+ * -+ * Also flushes inherited counters to the parent - before the parent -+ * gets woken up by child-exit notifications. -+ */ -+ perf_event_exit_task(tsk); -+ - exit_mm(); - - if (group_dead) -@@ -955,14 +964,6 @@ void __noreturn do_exit(long code) - exit_task_work(tsk); - exit_thread(tsk); - -- /* -- * Flush inherited counters to the parent - before the parent -- * gets woken up by child-exit notifications. -- * -- * because of cgroup mode, must be called before cgroup_exit() -- */ -- perf_event_exit_task(tsk); -- - sched_autogroup_exit_task(tsk); - cgroup_exit(tsk); - -diff -purNx .git BPI-Router-Linux-kernel/kernel/fork.c BPI-Router-Linux-kernel-6.16.12/kernel/fork.c ---- BPI-Router-Linux-kernel/kernel/fork.c 2025-10-22 13:53:23.591327325 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/fork.c 2025-10-22 13:53:56.775167887 -0400 -@@ -2289,7 +2289,7 @@ __latent_entropy struct task_struct *cop - if (need_futex_hash_allocate_default(clone_flags)) { - retval = futex_hash_allocate_default(); - if (retval) -- goto bad_fork_core_free; -+ goto bad_fork_cancel_cgroup; - /* - * If we fail beyond this point we don't free the allocated - * futex hash map. We assume that another thread will be created -diff -purNx .git BPI-Router-Linux-kernel/kernel/freezer.c BPI-Router-Linux-kernel-6.16.12/kernel/freezer.c ---- BPI-Router-Linux-kernel/kernel/freezer.c 2025-10-22 13:53:23.591327325 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/freezer.c 2025-10-22 13:53:56.775167887 -0400 -@@ -201,18 +201,9 @@ static int __restore_freezer_state(struc - - void __thaw_task(struct task_struct *p) - { -- unsigned long flags; -- -- spin_lock_irqsave(&freezer_lock, flags); -- if (WARN_ON_ONCE(freezing(p))) -- goto unlock; -- -- if (!frozen(p) || task_call_func(p, __restore_freezer_state, NULL)) -- goto unlock; -- -- wake_up_state(p, TASK_FROZEN); --unlock: -- spin_unlock_irqrestore(&freezer_lock, flags); -+ guard(spinlock_irqsave)(&freezer_lock); -+ if (frozen(p) && !task_call_func(p, __restore_freezer_state, NULL)) -+ wake_up_state(p, TASK_FROZEN); - } - - /** -diff -purNx .git BPI-Router-Linux-kernel/kernel/futex/core.c BPI-Router-Linux-kernel-6.16.12/kernel/futex/core.c ---- BPI-Router-Linux-kernel/kernel/futex/core.c 2025-10-22 13:53:23.591327325 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/futex/core.c 2025-10-22 13:53:56.775167887 -0400 -@@ -583,8 +583,8 @@ int get_futex_key(u32 __user *uaddr, uns - if (futex_get_value(&node, naddr)) - return -EFAULT; - -- if (node != FUTEX_NO_NODE && -- (node >= MAX_NUMNODES || !node_possible(node))) -+ if ((node != FUTEX_NO_NODE) && -+ ((unsigned int)node >= MAX_NUMNODES || !node_possible(node))) - return -EINVAL; - } - -@@ -1629,6 +1629,16 @@ again: - mm->futex_phash_new = NULL; - - if (fph) { -+ if (cur && (!cur->hash_mask || cur->immutable)) { -+ /* -+ * If two threads simultaneously request the global -+ * hash then the first one performs the switch, -+ * the second one returns here. -+ */ -+ free = fph; -+ mm->futex_phash_new = new; -+ return -EBUSY; -+ } - if (cur && !new) { - /* - * If we have an existing hash, but do not yet have -diff -purNx .git BPI-Router-Linux-kernel/kernel/futex/futex.h BPI-Router-Linux-kernel-6.16.12/kernel/futex/futex.h ---- BPI-Router-Linux-kernel/kernel/futex/futex.h 2025-10-22 13:53:23.591327325 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/futex/futex.h 2025-10-22 13:53:56.775167887 -0400 -@@ -321,13 +321,13 @@ static __always_inline int futex_put_val - { - if (can_do_masked_user_access()) - to = masked_user_access_begin(to); -- else if (!user_read_access_begin(to, sizeof(*to))) -+ else if (!user_write_access_begin(to, sizeof(*to))) - return -EFAULT; - unsafe_put_user(val, to, Efault); -- user_read_access_end(); -+ user_write_access_end(); - return 0; - Efault: -- user_read_access_end(); -+ user_write_access_end(); - return -EFAULT; - } - -diff -purNx .git BPI-Router-Linux-kernel/kernel/futex/requeue.c BPI-Router-Linux-kernel-6.16.12/kernel/futex/requeue.c ---- BPI-Router-Linux-kernel/kernel/futex/requeue.c 2025-10-22 13:53:23.591327325 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/futex/requeue.c 2025-10-22 13:53:56.775167887 -0400 -@@ -230,8 +230,9 @@ static inline - void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key, - struct futex_hash_bucket *hb) - { -- q->key = *key; -+ struct task_struct *task; - -+ q->key = *key; - __futex_unqueue(q); - - WARN_ON(!q->rt_waiter); -@@ -243,10 +244,11 @@ void requeue_pi_wake_futex(struct futex_ - futex_hash_get(hb); - q->drop_hb_ref = true; - q->lock_ptr = &hb->lock; -+ task = READ_ONCE(q->task); - - /* Signal locked state to the waiter */ - futex_requeue_pi_complete(q, 1); -- wake_up_state(q->task, TASK_NORMAL); -+ wake_up_state(task, TASK_NORMAL); - } - - /** -diff -purNx .git BPI-Router-Linux-kernel/kernel/gen_kheaders.sh BPI-Router-Linux-kernel-6.16.12/kernel/gen_kheaders.sh ---- BPI-Router-Linux-kernel/kernel/gen_kheaders.sh 2025-10-22 13:53:23.591327325 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/gen_kheaders.sh 2025-10-22 13:53:56.775167887 -0400 -@@ -4,79 +4,33 @@ - # This script generates an archive consisting of kernel headers - # for CONFIG_IKHEADERS. - set -e --sfile="$(readlink -f "$0")" --outdir="$(pwd)" - tarfile=$1 --tmpdir=$outdir/${tarfile%/*}/.tmp_dir -+srclist=$2 -+objlist=$3 - --dir_list=" --include/ --arch/$SRCARCH/include/ --" -- --# Support incremental builds by skipping archive generation --# if timestamps of files being archived are not changed. -- --# This block is useful for debugging the incremental builds. --# Uncomment it for debugging. --# if [ ! -f /tmp/iter ]; then iter=1; echo 1 > /tmp/iter; --# else iter=$(($(cat /tmp/iter) + 1)); echo $iter > /tmp/iter; fi --# find $all_dirs -name "*.h" | xargs ls -l > /tmp/ls-$iter -- --all_dirs= --if [ "$building_out_of_srctree" ]; then -- for d in $dir_list; do -- all_dirs="$all_dirs $srctree/$d" -- done --fi --all_dirs="$all_dirs $dir_list" -- --# include/generated/utsversion.h is ignored because it is generated after this --# script is executed. (utsversion.h is unneeded for kheaders) --# --# When Kconfig regenerates include/generated/autoconf.h, its timestamp is --# updated, but the contents might be still the same. When any CONFIG option is --# changed, Kconfig touches the corresponding timestamp file include/config/*. --# Hence, the md5sum detects the configuration change anyway. We do not need to --# check include/generated/autoconf.h explicitly. --# --# Ignore them for md5 calculation to avoid pointless regeneration. --headers_md5="$(find $all_dirs -name "*.h" -a \ -- ! -path include/generated/utsversion.h -a \ -- ! -path include/generated/autoconf.h | -- xargs ls -l | md5sum | cut -d ' ' -f1)" -- --# Any changes to this script will also cause a rebuild of the archive. --this_file_md5="$(ls -l $sfile | md5sum | cut -d ' ' -f1)" --if [ -f $tarfile ]; then tarfile_md5="$(md5sum $tarfile | cut -d ' ' -f1)"; fi --if [ -f kernel/kheaders.md5 ] && -- [ "$(head -n 1 kernel/kheaders.md5)" = "$headers_md5" ] && -- [ "$(head -n 2 kernel/kheaders.md5 | tail -n 1)" = "$this_file_md5" ] && -- [ "$(tail -n 1 kernel/kheaders.md5)" = "$tarfile_md5" ]; then -- exit --fi -+dir=$(dirname "${tarfile}") -+tmpdir=${dir}/.tmp_dir -+depfile=${dir}/.$(basename "${tarfile}").d -+ -+# generate dependency list. -+{ -+ echo -+ echo "deps_${tarfile} := \\" -+ sed 's:\(.*\): \1 \\:' "${srclist}" -+ sed -n '/^include\/generated\/autoconf\.h$/!s:\(.*\): \1 \\:p' "${objlist}" -+ echo -+ echo "${tarfile}: \$(deps_${tarfile})" -+ echo -+ echo "\$(deps_${tarfile}):" - --echo " GEN $tarfile" -+} > "${depfile}" - - rm -rf "${tmpdir}" - mkdir "${tmpdir}" - --if [ "$building_out_of_srctree" ]; then -- ( -- cd $srctree -- for f in $dir_list -- do find "$f" -name "*.h"; -- done | tar -c -f - -T - | tar -xf - -C "${tmpdir}" -- ) --fi -- --for f in $dir_list; -- do find "$f" -name "*.h"; --done | tar -c -f - -T - | tar -xf - -C "${tmpdir}" -- --# Always exclude include/generated/utsversion.h --# Otherwise, the contents of the tarball may vary depending on the build steps. --rm -f "${tmpdir}/include/generated/utsversion.h" -+# shellcheck disable=SC2154 # srctree is passed as an env variable -+sed "s:^${srctree}/::" "${srclist}" | tar -c -f - -C "${srctree}" -T - | tar -xf - -C "${tmpdir}" -+tar -c -f - -T "${objlist}" | tar -xf - -C "${tmpdir}" - - # Remove comments except SDPX lines - # Use a temporary file to store directory contents to prevent find/xargs from -@@ -92,8 +46,4 @@ tar "${KBUILD_BUILD_TIMESTAMP:+--mtime=$ - --owner=0 --group=0 --sort=name --numeric-owner --mode=u=rw,go=r,a+X \ - -I $XZ -cf $tarfile -C "${tmpdir}/" . > /dev/null - --echo $headers_md5 > kernel/kheaders.md5 --echo "$this_file_md5" >> kernel/kheaders.md5 --echo "$(md5sum $tarfile | cut -d ' ' -f1)" >> kernel/kheaders.md5 -- - rm -rf "${tmpdir}" -diff -purNx .git BPI-Router-Linux-kernel/kernel/.gitignore BPI-Router-Linux-kernel-6.16.12/kernel/.gitignore ---- BPI-Router-Linux-kernel/kernel/.gitignore 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/.gitignore 2025-10-22 13:53:56.767167926 -0400 -@@ -1,3 +1,5 @@ - # SPDX-License-Identifier: GPL-2.0-only - /config_data - /kheaders.md5 -+/kheaders-objlist -+/kheaders-srclist -diff -purNx .git BPI-Router-Linux-kernel/kernel/irq/chip.c BPI-Router-Linux-kernel-6.16.12/kernel/irq/chip.c ---- BPI-Router-Linux-kernel/kernel/irq/chip.c 2025-10-22 13:53:23.591327325 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/irq/chip.c 2025-10-22 13:53:56.775167887 -0400 -@@ -205,6 +205,14 @@ __irq_startup_managed(struct irq_desc *d - - void irq_startup_managed(struct irq_desc *desc) - { -+ struct irq_data *d = irq_desc_get_irq_data(desc); -+ -+ /* -+ * Clear managed-shutdown flag, so we don't repeat managed-startup for -+ * multiple hotplugs, and cause imbalanced disable depth. -+ */ -+ irqd_clr_managed_shutdown(d); -+ - /* - * Only start it up when the disable depth is 1, so that a disable, - * hotunplug, hotplug sequence does not end up enabling it during -diff -purNx .git BPI-Router-Linux-kernel/kernel/irq/cpuhotplug.c BPI-Router-Linux-kernel-6.16.12/kernel/irq/cpuhotplug.c ---- BPI-Router-Linux-kernel/kernel/irq/cpuhotplug.c 2025-10-22 13:53:23.591327325 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/irq/cpuhotplug.c 2025-10-22 13:53:56.775167887 -0400 -@@ -210,13 +210,6 @@ static void irq_restore_affinity_of_irq( - !irq_data_get_irq_chip(data) || !cpumask_test_cpu(cpu, affinity)) - return; - -- /* -- * Don't restore suspended interrupts here when a system comes back -- * from S3. They are reenabled via resume_device_irqs(). -- */ -- if (desc->istate & IRQS_SUSPENDED) -- return; -- - if (irqd_is_managed_and_shutdown(data)) - irq_startup_managed(desc); - -diff -purNx .git BPI-Router-Linux-kernel/kernel/irq/irq_sim.c BPI-Router-Linux-kernel-6.16.12/kernel/irq/irq_sim.c ---- BPI-Router-Linux-kernel/kernel/irq/irq_sim.c 2025-10-22 13:53:23.591327325 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/irq/irq_sim.c 2025-10-22 13:53:56.775167887 -0400 -@@ -202,7 +202,7 @@ struct irq_domain *irq_domain_create_sim - void *data) - { - struct irq_sim_work_ctx *work_ctx __free(kfree) = -- kmalloc(sizeof(*work_ctx), GFP_KERNEL); -+ kzalloc(sizeof(*work_ctx), GFP_KERNEL); - - if (!work_ctx) - return ERR_PTR(-ENOMEM); -diff -purNx .git BPI-Router-Linux-kernel/kernel/Kconfig.kexec BPI-Router-Linux-kernel-6.16.12/kernel/Kconfig.kexec ---- BPI-Router-Linux-kernel/kernel/Kconfig.kexec 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/Kconfig.kexec 2025-10-22 13:53:56.767167926 -0400 -@@ -97,6 +97,7 @@ config KEXEC_JUMP - config KEXEC_HANDOVER - bool "kexec handover" - depends on ARCH_SUPPORTS_KEXEC_HANDOVER && ARCH_SUPPORTS_KEXEC_FILE -+ depends on !DEFERRED_STRUCT_PAGE_INIT - select MEMBLOCK_KHO_SCRATCH - select KEXEC_FILE - select DEBUG_FS -@@ -134,6 +135,7 @@ config CRASH_DM_CRYPT - depends on KEXEC_FILE - depends on CRASH_DUMP - depends on DM_CRYPT -+ depends on KEYS - help - With this option enabled, user space can intereact with - /sys/kernel/config/crash_dm_crypt_keys to make the dm crypt keys -diff -purNx .git BPI-Router-Linux-kernel/kernel/kcsan/kcsan_test.c BPI-Router-Linux-kernel-6.16.12/kernel/kcsan/kcsan_test.c ---- BPI-Router-Linux-kernel/kernel/kcsan/kcsan_test.c 2025-10-22 13:53:23.591327325 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/kcsan/kcsan_test.c 2025-10-22 13:53:56.775167887 -0400 -@@ -533,7 +533,7 @@ static void test_barrier_nothreads(struc - struct kcsan_scoped_access *reorder_access = NULL; - #endif - arch_spinlock_t arch_spinlock = __ARCH_SPIN_LOCK_UNLOCKED; -- atomic_t dummy; -+ atomic_t dummy = ATOMIC_INIT(0); - - KCSAN_TEST_REQUIRES(test, reorder_access != NULL); - KCSAN_TEST_REQUIRES(test, IS_ENABLED(CONFIG_SMP)); -diff -purNx .git BPI-Router-Linux-kernel/kernel/kexec_core.c BPI-Router-Linux-kernel-6.16.12/kernel/kexec_core.c ---- BPI-Router-Linux-kernel/kernel/kexec_core.c 2025-10-22 13:53:23.591327325 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/kexec_core.c 2025-10-22 13:53:56.775167887 -0400 -@@ -1080,7 +1080,7 @@ int kernel_kexec(void) - console_suspend_all(); - error = dpm_suspend_start(PMSG_FREEZE); - if (error) -- goto Resume_console; -+ goto Resume_devices; - /* - * dpm_suspend_end() must be called after dpm_suspend_start() - * to complete the transition, like in the hibernation flows -@@ -1135,7 +1135,7 @@ int kernel_kexec(void) - dpm_resume_start(PMSG_RESTORE); - Resume_devices: - dpm_resume_end(PMSG_RESTORE); -- Resume_console: -+ pm_restore_gfp_mask(); - console_resume_all(); - thaw_processes(); - Restore_console: -diff -purNx .git BPI-Router-Linux-kernel/kernel/kexec_handover.c BPI-Router-Linux-kernel-6.16.12/kernel/kexec_handover.c ---- BPI-Router-Linux-kernel/kernel/kexec_handover.c 2025-10-22 13:53:23.591327325 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/kexec_handover.c 2025-10-22 13:53:56.775167887 -0400 -@@ -144,14 +144,34 @@ static int __kho_preserve_order(struct k - unsigned int order) - { - struct kho_mem_phys_bits *bits; -- struct kho_mem_phys *physxa; -+ struct kho_mem_phys *physxa, *new_physxa; - const unsigned long pfn_high = pfn >> order; - - might_sleep(); - -- physxa = xa_load_or_alloc(&track->orders, order, sizeof(*physxa)); -- if (IS_ERR(physxa)) -- return PTR_ERR(physxa); -+ physxa = xa_load(&track->orders, order); -+ if (!physxa) { -+ int err; -+ -+ new_physxa = kzalloc(sizeof(*physxa), GFP_KERNEL); -+ if (!new_physxa) -+ return -ENOMEM; -+ -+ xa_init(&new_physxa->phys_bits); -+ physxa = xa_cmpxchg(&track->orders, order, NULL, new_physxa, -+ GFP_KERNEL); -+ -+ err = xa_err(physxa); -+ if (err || physxa) { -+ xa_destroy(&new_physxa->phys_bits); -+ kfree(new_physxa); -+ -+ if (err) -+ return err; -+ } else { -+ physxa = new_physxa; -+ } -+ } - - bits = xa_load_or_alloc(&physxa->phys_bits, pfn_high / PRESERVE_BITS, - sizeof(*bits)); -@@ -164,11 +184,21 @@ static int __kho_preserve_order(struct k - } - - /* almost as free_reserved_page(), just don't free the page */ --static void kho_restore_page(struct page *page) -+static void kho_restore_page(struct page *page, unsigned int order) - { -- ClearPageReserved(page); -- init_page_count(page); -- adjust_managed_page_count(page, 1); -+ unsigned int nr_pages = (1 << order); -+ -+ /* Head page gets refcount of 1. */ -+ set_page_count(page, 1); -+ -+ /* For higher order folios, tail pages get a page count of zero. */ -+ for (unsigned int i = 1; i < nr_pages; i++) -+ set_page_count(page + i, 0); -+ -+ if (order > 0) -+ prep_compound_page(page, order); -+ -+ adjust_managed_page_count(page, nr_pages); - } - - /** -@@ -186,15 +216,10 @@ struct folio *kho_restore_folio(phys_add - return NULL; - - order = page->private; -- if (order) { -- if (order > MAX_PAGE_ORDER) -- return NULL; -- -- prep_compound_page(page, order); -- } else { -- kho_restore_page(page); -- } -+ if (order > MAX_PAGE_ORDER) -+ return NULL; - -+ kho_restore_page(page, order); - return page_folio(page); - } - EXPORT_SYMBOL_GPL(kho_restore_folio); -@@ -539,6 +564,7 @@ err_free_scratch_areas: - err_free_scratch_desc: - memblock_free(kho_scratch, kho_scratch_cnt * sizeof(*kho_scratch)); - err_disable_kho: -+ pr_warn("Failed to reserve scratch area, disabling kexec handover\n"); - kho_enable = false; - } - -diff -purNx .git BPI-Router-Linux-kernel/kernel/kthread.c BPI-Router-Linux-kernel-6.16.12/kernel/kthread.c ---- BPI-Router-Linux-kernel/kernel/kthread.c 2025-10-22 13:53:23.591327325 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/kthread.c 2025-10-22 13:53:56.775167887 -0400 -@@ -894,6 +894,7 @@ out: - - return ret; - } -+EXPORT_SYMBOL_GPL(kthread_affine_preferred); - - /* - * Re-affine kthreads according to their preferences -diff -purNx .git BPI-Router-Linux-kernel/kernel/Makefile BPI-Router-Linux-kernel-6.16.12/kernel/Makefile ---- BPI-Router-Linux-kernel/kernel/Makefile 2025-10-22 13:53:23.583327364 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/Makefile 2025-10-22 13:53:56.767167926 -0400 -@@ -158,11 +158,48 @@ filechk_cat = cat $< - $(obj)/config_data: $(KCONFIG_CONFIG) FORCE - $(call filechk,cat) - -+# kheaders_data.tar.xz - $(obj)/kheaders.o: $(obj)/kheaders_data.tar.xz - --quiet_cmd_genikh = CHK $(obj)/kheaders_data.tar.xz -- cmd_genikh = $(CONFIG_SHELL) $(srctree)/kernel/gen_kheaders.sh $@ --$(obj)/kheaders_data.tar.xz: FORCE -- $(call cmd,genikh) -+quiet_cmd_kheaders_data = GEN $@ -+ cmd_kheaders_data = "$<" "$@" "$(obj)/kheaders-srclist" "$(obj)/kheaders-objlist" -+ cmd_kheaders_data_dep = cat $(depfile) >> $(dot-target).cmd; rm -f $(depfile) - --clean-files := kheaders_data.tar.xz kheaders.md5 -+define rule_kheaders_data -+ $(call cmd_and_savecmd,kheaders_data) -+ $(call cmd,kheaders_data_dep) -+endef -+ -+targets += kheaders_data.tar.xz -+$(obj)/kheaders_data.tar.xz: $(src)/gen_kheaders.sh $(obj)/kheaders-srclist $(obj)/kheaders-objlist $(obj)/kheaders.md5 FORCE -+ $(call if_changed_rule,kheaders_data) -+ -+# generated headers in objtree -+# -+# include/generated/utsversion.h is ignored because it is generated -+# after gen_kheaders.sh is executed. (utsversion.h is unneeded for kheaders) -+filechk_kheaders_objlist = \ -+ for d in include "arch/$(SRCARCH)/include"; do \ -+ find "$${d}/generated" ! -path "include/generated/utsversion.h" -a -name "*.h" -print; \ -+ done -+ -+$(obj)/kheaders-objlist: FORCE -+ $(call filechk,kheaders_objlist) -+ -+# non-generated headers in srctree -+filechk_kheaders_srclist = \ -+ for d in include "arch/$(SRCARCH)/include"; do \ -+ find "$(srctree)/$${d}" -path "$(srctree)/$${d}/generated" -prune -o -name "*.h" -print; \ -+ done -+ -+$(obj)/kheaders-srclist: FORCE -+ $(call filechk,kheaders_srclist) -+ -+# Some files are symlinks. If symlinks are changed, kheaders_data.tar.xz should -+# be rebuilt. -+filechk_kheaders_md5sum = xargs -r -a $< stat -c %N | md5sum -+ -+$(obj)/kheaders.md5: $(obj)/kheaders-srclist FORCE -+ $(call filechk,kheaders_md5sum) -+ -+clean-files := kheaders.md5 kheaders-srclist kheaders-objlist -diff -purNx .git BPI-Router-Linux-kernel/kernel/module/main.c BPI-Router-Linux-kernel-6.16.12/kernel/module/main.c ---- BPI-Router-Linux-kernel/kernel/module/main.c 2025-10-22 13:53:23.591327325 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/module/main.c 2025-10-22 13:53:56.775167887 -0400 -@@ -751,14 +751,16 @@ SYSCALL_DEFINE2(delete_module, const cha - struct module *mod; - char name[MODULE_NAME_LEN]; - char buf[MODULE_FLAGS_BUF_SIZE]; -- int ret, forced = 0; -+ int ret, len, forced = 0; - - if (!capable(CAP_SYS_MODULE) || modules_disabled) - return -EPERM; - -- if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0) -- return -EFAULT; -- name[MODULE_NAME_LEN-1] = '\0'; -+ len = strncpy_from_user(name, name_user, MODULE_NAME_LEN); -+ if (len == 0 || len == MODULE_NAME_LEN) -+ return -ENOENT; -+ if (len < 0) -+ return len; - - audit_log_kern_module(name); - -@@ -1573,8 +1575,14 @@ static int apply_relocations(struct modu - if (infosec >= info->hdr->e_shnum) - continue; - -- /* Don't bother with non-allocated sections */ -- if (!(info->sechdrs[infosec].sh_flags & SHF_ALLOC)) -+ /* -+ * Don't bother with non-allocated sections. -+ * An exception is the percpu section, which has separate allocations -+ * for individual CPUs. We relocate the percpu section in the initial -+ * ELF template and subsequently copy it to the per-CPU destinations. -+ */ -+ if (!(info->sechdrs[infosec].sh_flags & SHF_ALLOC) && -+ (!infosec || infosec != info->index.pcpu)) - continue; - - if (info->sechdrs[i].sh_flags & SHF_RELA_LIVEPATCH) -@@ -2696,9 +2704,8 @@ static int find_module_sections(struct m - - static int move_module(struct module *mod, struct load_info *info) - { -- int i; -- enum mod_mem_type t = 0; -- int ret = -ENOMEM; -+ int i, ret; -+ enum mod_mem_type t = MOD_MEM_NUM_TYPES; - bool codetag_section_found = false; - - for_each_mod_mem_type(type) { -@@ -2776,7 +2783,7 @@ static int move_module(struct module *mo - return 0; - out_err: - module_memory_restore_rox(mod); -- for (t--; t >= 0; t--) -+ while (t--) - module_memory_free(mod, t); - if (codetag_section_found) - codetag_free_module_sections(mod); -@@ -3368,7 +3375,7 @@ static int load_module(struct load_info - - module_allocated = true; - -- audit_log_kern_module(mod->name); -+ audit_log_kern_module(info->name); - - /* Reserve our place in the list. */ - err = add_unformed_module(mod); -@@ -3532,8 +3539,10 @@ static int load_module(struct load_info - * failures once the proper module was allocated and - * before that. - */ -- if (!module_allocated) -+ if (!module_allocated) { -+ audit_log_kern_module(info->name ? info->name : "?"); - mod_stat_bump_becoming(info, flags); -+ } - free_copy(info, flags); - return err; - } -diff -purNx .git BPI-Router-Linux-kernel/kernel/padata.c BPI-Router-Linux-kernel-6.16.12/kernel/padata.c ---- BPI-Router-Linux-kernel/kernel/padata.c 2025-10-22 13:53:23.595327306 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/padata.c 2025-10-22 13:53:56.775167887 -0400 -@@ -261,20 +261,17 @@ EXPORT_SYMBOL(padata_do_parallel); - * be parallel processed by another cpu and is not yet present in - * the cpu's reorder queue. - */ --static struct padata_priv *padata_find_next(struct parallel_data *pd, -- bool remove_object) -+static struct padata_priv *padata_find_next(struct parallel_data *pd, int cpu, -+ unsigned int processed) - { - struct padata_priv *padata; - struct padata_list *reorder; -- int cpu = pd->cpu; - - reorder = per_cpu_ptr(pd->reorder_list, cpu); - - spin_lock(&reorder->lock); -- if (list_empty(&reorder->list)) { -- spin_unlock(&reorder->lock); -- return NULL; -- } -+ if (list_empty(&reorder->list)) -+ goto notfound; - - padata = list_entry(reorder->list.next, struct padata_priv, list); - -@@ -282,97 +279,52 @@ static struct padata_priv *padata_find_n - * Checks the rare case where two or more parallel jobs have hashed to - * the same CPU and one of the later ones finishes first. - */ -- if (padata->seq_nr != pd->processed) { -- spin_unlock(&reorder->lock); -- return NULL; -- } -- -- if (remove_object) { -- list_del_init(&padata->list); -- ++pd->processed; -- pd->cpu = cpumask_next_wrap(cpu, pd->cpumask.pcpu); -- } -+ if (padata->seq_nr != processed) -+ goto notfound; - -+ list_del_init(&padata->list); - spin_unlock(&reorder->lock); - return padata; -+ -+notfound: -+ pd->processed = processed; -+ pd->cpu = cpu; -+ spin_unlock(&reorder->lock); -+ return NULL; - } - --static void padata_reorder(struct parallel_data *pd) -+static void padata_reorder(struct padata_priv *padata) - { -+ struct parallel_data *pd = padata->pd; - struct padata_instance *pinst = pd->ps->pinst; -- int cb_cpu; -- struct padata_priv *padata; -- struct padata_serial_queue *squeue; -- struct padata_list *reorder; -+ unsigned int processed; -+ int cpu; - -- /* -- * We need to ensure that only one cpu can work on dequeueing of -- * the reorder queue the time. Calculating in which percpu reorder -- * queue the next object will arrive takes some time. A spinlock -- * would be highly contended. Also it is not clear in which order -- * the objects arrive to the reorder queues. So a cpu could wait to -- * get the lock just to notice that there is nothing to do at the -- * moment. Therefore we use a trylock and let the holder of the lock -- * care for all the objects enqueued during the holdtime of the lock. -- */ -- if (!spin_trylock_bh(&pd->lock)) -- return; -+ processed = pd->processed; -+ cpu = pd->cpu; - -- while (1) { -- padata = padata_find_next(pd, true); -+ do { -+ struct padata_serial_queue *squeue; -+ int cb_cpu; - -- /* -- * If the next object that needs serialization is parallel -- * processed by another cpu and is still on it's way to the -- * cpu's reorder queue, nothing to do for now. -- */ -- if (!padata) -- break; -+ cpu = cpumask_next_wrap(cpu, pd->cpumask.pcpu); -+ processed++; - - cb_cpu = padata->cb_cpu; - squeue = per_cpu_ptr(pd->squeue, cb_cpu); - - spin_lock(&squeue->serial.lock); - list_add_tail(&padata->list, &squeue->serial.list); -- spin_unlock(&squeue->serial.lock); -- - queue_work_on(cb_cpu, pinst->serial_wq, &squeue->work); -- } - -- spin_unlock_bh(&pd->lock); -- -- /* -- * The next object that needs serialization might have arrived to -- * the reorder queues in the meantime. -- * -- * Ensure reorder queue is read after pd->lock is dropped so we see -- * new objects from another task in padata_do_serial. Pairs with -- * smp_mb in padata_do_serial. -- */ -- smp_mb(); -- -- reorder = per_cpu_ptr(pd->reorder_list, pd->cpu); -- if (!list_empty(&reorder->list) && padata_find_next(pd, false)) { - /* -- * Other context(eg. the padata_serial_worker) can finish the request. -- * To avoid UAF issue, add pd ref here, and put pd ref after reorder_work finish. -+ * If the next object that needs serialization is parallel -+ * processed by another cpu and is still on it's way to the -+ * cpu's reorder queue, end the loop. - */ -- padata_get_pd(pd); -- if (!queue_work(pinst->serial_wq, &pd->reorder_work)) -- padata_put_pd(pd); -- } --} -- --static void invoke_padata_reorder(struct work_struct *work) --{ -- struct parallel_data *pd; -- -- local_bh_disable(); -- pd = container_of(work, struct parallel_data, reorder_work); -- padata_reorder(pd); -- local_bh_enable(); -- /* Pairs with putting the reorder_work in the serial_wq */ -- padata_put_pd(pd); -+ padata = padata_find_next(pd, cpu, processed); -+ spin_unlock(&squeue->serial.lock); -+ } while (padata); - } - - static void padata_serial_worker(struct work_struct *serial_work) -@@ -423,6 +375,7 @@ void padata_do_serial(struct padata_priv - struct padata_list *reorder = per_cpu_ptr(pd->reorder_list, hashed_cpu); - struct padata_priv *cur; - struct list_head *pos; -+ bool gotit = true; - - spin_lock(&reorder->lock); - /* Sort in ascending order of sequence number. */ -@@ -432,17 +385,14 @@ void padata_do_serial(struct padata_priv - if ((signed int)(cur->seq_nr - padata->seq_nr) < 0) - break; - } -- list_add(&padata->list, pos); -+ if (padata->seq_nr != pd->processed) { -+ gotit = false; -+ list_add(&padata->list, pos); -+ } - spin_unlock(&reorder->lock); - -- /* -- * Ensure the addition to the reorder list is ordered correctly -- * with the trylock of pd->lock in padata_reorder. Pairs with smp_mb -- * in padata_reorder. -- */ -- smp_mb(); -- -- padata_reorder(pd); -+ if (gotit) -+ padata_reorder(padata); - } - EXPORT_SYMBOL(padata_do_serial); - -@@ -632,9 +582,7 @@ static struct parallel_data *padata_allo - padata_init_squeues(pd); - pd->seq_nr = -1; - refcount_set(&pd->refcnt, 1); -- spin_lock_init(&pd->lock); - pd->cpu = cpumask_first(pd->cpumask.pcpu); -- INIT_WORK(&pd->reorder_work, invoke_padata_reorder); - - return pd; - -@@ -1144,12 +1092,6 @@ void padata_free_shell(struct padata_she - if (!ps) - return; - -- /* -- * Wait for all _do_serial calls to finish to avoid touching -- * freed pd's and ps's. -- */ -- synchronize_rcu(); -- - mutex_lock(&ps->pinst->lock); - list_del(&ps->list); - pd = rcu_dereference_protected(ps->pd, 1); -diff -purNx .git BPI-Router-Linux-kernel/kernel/power/console.c BPI-Router-Linux-kernel-6.16.12/kernel/power/console.c ---- BPI-Router-Linux-kernel/kernel/power/console.c 2025-10-22 13:53:23.595327306 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/power/console.c 2025-10-22 13:53:56.775167887 -0400 -@@ -16,6 +16,7 @@ - #define SUSPEND_CONSOLE (MAX_NR_CONSOLES-1) - - static int orig_fgconsole, orig_kmsg; -+static bool vt_switch_done; - - static DEFINE_MUTEX(vt_switch_mutex); - -@@ -136,17 +137,21 @@ void pm_prepare_console(void) - if (orig_fgconsole < 0) - return; - -+ vt_switch_done = true; -+ - orig_kmsg = vt_kmsg_redirect(SUSPEND_CONSOLE); - return; - } - - void pm_restore_console(void) - { -- if (!pm_vt_switch()) -+ if (!pm_vt_switch() && !vt_switch_done) - return; - - if (orig_fgconsole >= 0) { - vt_move_to_console(orig_fgconsole, 0); - vt_kmsg_redirect(orig_kmsg); - } -+ -+ vt_switch_done = false; - } -diff -purNx .git BPI-Router-Linux-kernel/kernel/power/energy_model.c BPI-Router-Linux-kernel-6.16.12/kernel/power/energy_model.c ---- BPI-Router-Linux-kernel/kernel/power/energy_model.c 2025-10-22 13:53:23.595327306 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/power/energy_model.c 2025-10-22 13:53:56.775167887 -0400 -@@ -553,6 +553,30 @@ int em_dev_register_perf_domain(struct d - const struct em_data_callback *cb, - const cpumask_t *cpus, bool microwatts) - { -+ int ret = em_dev_register_pd_no_update(dev, nr_states, cb, cpus, microwatts); -+ -+ if (_is_cpu_device(dev)) -+ em_check_capacity_update(); -+ -+ return ret; -+} -+EXPORT_SYMBOL_GPL(em_dev_register_perf_domain); -+ -+/** -+ * em_dev_register_pd_no_update() - Register a perf domain for a device -+ * @dev : Device to register the PD for -+ * @nr_states : Number of performance states in the new PD -+ * @cb : Callback functions for populating the energy model -+ * @cpus : CPUs to include in the new PD (mandatory if @dev is a CPU device) -+ * @microwatts : Whether or not the power values in the EM will be in uW -+ * -+ * Like em_dev_register_perf_domain(), but does not trigger a CPU capacity -+ * update after registering the PD, even if @dev is a CPU device. -+ */ -+int em_dev_register_pd_no_update(struct device *dev, unsigned int nr_states, -+ const struct em_data_callback *cb, -+ const cpumask_t *cpus, bool microwatts) -+{ - struct em_perf_table *em_table; - unsigned long cap, prev_cap = 0; - unsigned long flags = 0; -@@ -636,12 +660,9 @@ int em_dev_register_perf_domain(struct d - unlock: - mutex_unlock(&em_pd_mutex); - -- if (_is_cpu_device(dev)) -- em_check_capacity_update(); -- - return ret; - } --EXPORT_SYMBOL_GPL(em_dev_register_perf_domain); -+EXPORT_SYMBOL_GPL(em_dev_register_pd_no_update); - - /** - * em_dev_unregister_perf_domain() - Unregister Energy Model (EM) for a device -diff -purNx .git BPI-Router-Linux-kernel/kernel/power/hibernate.c BPI-Router-Linux-kernel-6.16.12/kernel/power/hibernate.c ---- BPI-Router-Linux-kernel/kernel/power/hibernate.c 2025-10-22 13:53:23.595327306 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/power/hibernate.c 2025-10-22 13:53:56.775167887 -0400 -@@ -559,7 +559,6 @@ int hibernation_restore(int platform_mod - - pm_prepare_console(); - console_suspend_all(); -- pm_restrict_gfp_mask(); - error = dpm_suspend_start(PMSG_QUIESCE); - if (!error) { - error = resume_target_kernel(platform_mode); -@@ -571,7 +570,6 @@ int hibernation_restore(int platform_mod - BUG_ON(!error); - } - dpm_resume_end(PMSG_RECOVER); -- pm_restore_gfp_mask(); - console_resume_all(); - pm_restore_console(); - return error; -diff -purNx .git BPI-Router-Linux-kernel/kernel/power/power.h BPI-Router-Linux-kernel-6.16.12/kernel/power/power.h ---- BPI-Router-Linux-kernel/kernel/power/power.h 2025-10-22 13:53:23.595327306 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/power/power.h 2025-10-22 13:53:56.775167887 -0400 -@@ -239,11 +239,6 @@ static inline void suspend_test_finish(c - /* kernel/power/main.c */ - extern int pm_notifier_call_chain_robust(unsigned long val_up, unsigned long val_down); - extern int pm_notifier_call_chain(unsigned long val); --void pm_restrict_gfp_mask(void); --void pm_restore_gfp_mask(void); --#else --static inline void pm_restrict_gfp_mask(void) {} --static inline void pm_restore_gfp_mask(void) {} - #endif - - #ifdef CONFIG_HIGHMEM -diff -purNx .git BPI-Router-Linux-kernel/kernel/power/suspend.c BPI-Router-Linux-kernel-6.16.12/kernel/power/suspend.c ---- BPI-Router-Linux-kernel/kernel/power/suspend.c 2025-10-22 13:53:23.595327306 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/power/suspend.c 2025-10-22 13:53:56.775167887 -0400 -@@ -384,6 +384,7 @@ static int suspend_prepare(suspend_state - return 0; - - dpm_save_failed_step(SUSPEND_FREEZE); -+ filesystems_thaw(); - pm_notifier_call_chain(PM_POST_SUSPEND); - Restore: - pm_restore_console(); -@@ -592,8 +593,6 @@ static int enter_state(suspend_state_t s - ksys_sync_helper(); - trace_suspend_resume(TPS("sync_filesystems"), 0, false); - } -- if (filesystem_freeze_enabled) -- filesystems_freeze(); - - pm_pr_dbg("Preparing system for sleep (%s)\n", mem_sleep_labels[state]); - pm_suspend_clear_flags(); -@@ -606,16 +605,13 @@ static int enter_state(suspend_state_t s - - trace_suspend_resume(TPS("suspend_enter"), state, false); - pm_pr_dbg("Suspending system (%s)\n", mem_sleep_labels[state]); -- pm_restrict_gfp_mask(); - error = suspend_devices_and_enter(state); -- pm_restore_gfp_mask(); - - Finish: - events_check_enabled = false; - pm_pr_dbg("Finishing wakeup.\n"); - suspend_finish(); - Unlock: -- filesystems_thaw(); - mutex_unlock(&system_transition_mutex); - return error; - } -diff -purNx .git BPI-Router-Linux-kernel/kernel/printk/nbcon.c BPI-Router-Linux-kernel-6.16.12/kernel/printk/nbcon.c ---- BPI-Router-Linux-kernel/kernel/printk/nbcon.c 2025-10-22 13:53:23.595327306 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/printk/nbcon.c 2025-10-22 13:53:56.775167887 -0400 -@@ -214,8 +214,9 @@ static void nbcon_seq_try_update(struct - - /** - * nbcon_context_try_acquire_direct - Try to acquire directly -- * @ctxt: The context of the caller -- * @cur: The current console state -+ * @ctxt: The context of the caller -+ * @cur: The current console state -+ * @is_reacquire: This acquire is a reacquire - * - * Acquire the console when it is released. Also acquire the console when - * the current owner has a lower priority and the console is in a safe state. -@@ -225,17 +226,17 @@ static void nbcon_seq_try_update(struct - * - * Errors: - * -- * -EPERM: A panic is in progress and this is not the panic CPU. -- * Or the current owner or waiter has the same or higher -- * priority. No acquire method can be successful in -- * this case. -+ * -EPERM: A panic is in progress and this is neither the panic -+ * CPU nor is this a reacquire. Or the current owner or -+ * waiter has the same or higher priority. No acquire -+ * method can be successful in these cases. - * - * -EBUSY: The current owner has a lower priority but the console - * in an unsafe state. The caller should try using - * the handover acquire method. - */ - static int nbcon_context_try_acquire_direct(struct nbcon_context *ctxt, -- struct nbcon_state *cur) -+ struct nbcon_state *cur, bool is_reacquire) - { - unsigned int cpu = smp_processor_id(); - struct console *con = ctxt->console; -@@ -243,14 +244,20 @@ static int nbcon_context_try_acquire_dir - - do { - /* -- * Panic does not imply that the console is owned. However, it -- * is critical that non-panic CPUs during panic are unable to -- * acquire ownership in order to satisfy the assumptions of -- * nbcon_waiter_matches(). In particular, the assumption that -- * lower priorities are ignored during panic. -+ * Panic does not imply that the console is owned. However, -+ * since all non-panic CPUs are stopped during panic(), it -+ * is safer to have them avoid gaining console ownership. -+ * -+ * If this acquire is a reacquire (and an unsafe takeover -+ * has not previously occurred) then it is allowed to attempt -+ * a direct acquire in panic. This gives console drivers an -+ * opportunity to perform any necessary cleanup if they were -+ * interrupted by the panic CPU while printing. - */ -- if (other_cpu_in_panic()) -+ if (other_cpu_in_panic() && -+ (!is_reacquire || cur->unsafe_takeover)) { - return -EPERM; -+ } - - if (ctxt->prio <= cur->prio || ctxt->prio <= cur->req_prio) - return -EPERM; -@@ -301,8 +308,9 @@ static bool nbcon_waiter_matches(struct - * Event #1 implies this context is EMERGENCY. - * Event #2 implies the new context is PANIC. - * Event #3 occurs when panic() has flushed the console. -- * Events #4 and #5 are not possible due to the other_cpu_in_panic() -- * check in nbcon_context_try_acquire_direct(). -+ * Event #4 occurs when a non-panic CPU reacquires. -+ * Event #5 is not possible due to the other_cpu_in_panic() check -+ * in nbcon_context_try_acquire_handover(). - */ - - return (cur->req_prio == expected_prio); -@@ -431,6 +439,16 @@ static int nbcon_context_try_acquire_han - WARN_ON_ONCE(ctxt->prio <= cur->prio || ctxt->prio <= cur->req_prio); - WARN_ON_ONCE(!cur->unsafe); - -+ /* -+ * Panic does not imply that the console is owned. However, it -+ * is critical that non-panic CPUs during panic are unable to -+ * wait for a handover in order to satisfy the assumptions of -+ * nbcon_waiter_matches(). In particular, the assumption that -+ * lower priorities are ignored during panic. -+ */ -+ if (other_cpu_in_panic()) -+ return -EPERM; -+ - /* Handover is not possible on the same CPU. */ - if (cur->cpu == cpu) - return -EBUSY; -@@ -558,7 +576,8 @@ static struct printk_buffers panic_nbcon - - /** - * nbcon_context_try_acquire - Try to acquire nbcon console -- * @ctxt: The context of the caller -+ * @ctxt: The context of the caller -+ * @is_reacquire: This acquire is a reacquire - * - * Context: Under @ctxt->con->device_lock() or local_irq_save(). - * Return: True if the console was acquired. False otherwise. -@@ -568,7 +587,7 @@ static struct printk_buffers panic_nbcon - * in an unsafe state. Otherwise, on success the caller may assume - * the console is not in an unsafe state. - */ --static bool nbcon_context_try_acquire(struct nbcon_context *ctxt) -+static bool nbcon_context_try_acquire(struct nbcon_context *ctxt, bool is_reacquire) - { - unsigned int cpu = smp_processor_id(); - struct console *con = ctxt->console; -@@ -577,7 +596,7 @@ static bool nbcon_context_try_acquire(st - - nbcon_state_read(con, &cur); - try_again: -- err = nbcon_context_try_acquire_direct(ctxt, &cur); -+ err = nbcon_context_try_acquire_direct(ctxt, &cur, is_reacquire); - if (err != -EBUSY) - goto out; - -@@ -913,7 +932,7 @@ void nbcon_reacquire_nobuf(struct nbcon_ - { - struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); - -- while (!nbcon_context_try_acquire(ctxt)) -+ while (!nbcon_context_try_acquire(ctxt, true)) - cpu_relax(); - - nbcon_write_context_set_buf(wctxt, NULL, 0); -@@ -1101,7 +1120,7 @@ static bool nbcon_emit_one(struct nbcon_ - cant_migrate(); - } - -- if (!nbcon_context_try_acquire(ctxt)) -+ if (!nbcon_context_try_acquire(ctxt, false)) - goto out; - - /* -@@ -1486,7 +1505,7 @@ static int __nbcon_atomic_flush_pending_ - ctxt->prio = nbcon_get_default_prio(); - ctxt->allow_unsafe_takeover = allow_unsafe_takeover; - -- if (!nbcon_context_try_acquire(ctxt)) -+ if (!nbcon_context_try_acquire(ctxt, false)) - return -EPERM; - - while (nbcon_seq_read(con) < stop_seq) { -@@ -1762,7 +1781,7 @@ bool nbcon_device_try_acquire(struct con - ctxt->console = con; - ctxt->prio = NBCON_PRIO_NORMAL; - -- if (!nbcon_context_try_acquire(ctxt)) -+ if (!nbcon_context_try_acquire(ctxt, false)) - return false; - - if (!nbcon_context_enter_unsafe(ctxt)) -diff -purNx .git BPI-Router-Linux-kernel/kernel/rcu/rcutorture.c BPI-Router-Linux-kernel-6.16.12/kernel/rcu/rcutorture.c ---- BPI-Router-Linux-kernel/kernel/rcu/rcutorture.c 2025-10-22 13:53:23.595327306 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/rcu/rcutorture.c 2025-10-22 13:53:56.779167868 -0400 -@@ -464,7 +464,7 @@ rcu_read_delay(struct torture_random_sta - !(torture_random(rrsp) % (nrealreaders * 2000 * longdelay_ms))) { - started = cur_ops->get_gp_seq(); - ts = rcu_trace_clock_local(); -- if (preempt_count() & (SOFTIRQ_MASK | HARDIRQ_MASK)) -+ if ((preempt_count() & HARDIRQ_MASK) || softirq_count()) - longdelay_ms = 5; /* Avoid triggering BH limits. */ - mdelay(longdelay_ms); - rtrsp->rt_delay_ms = longdelay_ms; -@@ -1930,7 +1930,7 @@ static void rcutorture_one_extend_check( - return; - - WARN_ONCE((curstate & (RCUTORTURE_RDR_BH | RCUTORTURE_RDR_RBH)) && -- !(preempt_count() & SOFTIRQ_MASK), ROEC_ARGS); -+ !softirq_count(), ROEC_ARGS); - WARN_ONCE((curstate & (RCUTORTURE_RDR_PREEMPT | RCUTORTURE_RDR_SCHED)) && - !(preempt_count() & PREEMPT_MASK), ROEC_ARGS); - WARN_ONCE(cur_ops->readlock_nesting && -@@ -1944,7 +1944,7 @@ static void rcutorture_one_extend_check( - - WARN_ONCE(cur_ops->extendables && - !(curstate & (RCUTORTURE_RDR_BH | RCUTORTURE_RDR_RBH)) && -- (preempt_count() & SOFTIRQ_MASK), ROEC_ARGS); -+ softirq_count(), ROEC_ARGS); - - /* - * non-preemptible RCU in a preemptible kernel uses preempt_disable() -@@ -1965,6 +1965,9 @@ static void rcutorture_one_extend_check( - if (!IS_ENABLED(CONFIG_PREEMPT_RCU)) - mask |= RCUTORTURE_RDR_PREEMPT | RCUTORTURE_RDR_SCHED; - -+ if (IS_ENABLED(CONFIG_PREEMPT_RT) && softirq_count()) -+ mask |= RCUTORTURE_RDR_BH | RCUTORTURE_RDR_RBH; -+ - WARN_ONCE(cur_ops->readlock_nesting && !(curstate & mask) && - cur_ops->readlock_nesting() > 0, ROEC_ARGS); - } -diff -purNx .git BPI-Router-Linux-kernel/kernel/rcu/refscale.c BPI-Router-Linux-kernel-6.16.12/kernel/rcu/refscale.c ---- BPI-Router-Linux-kernel/kernel/rcu/refscale.c 2025-10-22 13:53:23.595327306 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/rcu/refscale.c 2025-10-22 13:53:56.779167868 -0400 -@@ -85,7 +85,7 @@ torture_param(int, holdoff, IS_BUILTIN(C - // Number of typesafe_lookup structures, that is, the degree of concurrency. - torture_param(long, lookup_instances, 0, "Number of typesafe_lookup structures."); - // Number of loops per experiment, all readers execute operations concurrently. --torture_param(long, loops, 10000, "Number of loops per experiment."); -+torture_param(int, loops, 10000, "Number of loops per experiment."); - // Number of readers, with -1 defaulting to about 75% of the CPUs. - torture_param(int, nreaders, -1, "Number of readers, -1 for 75% of CPUs."); - // Number of runs. -@@ -1140,7 +1140,7 @@ static void - ref_scale_print_module_parms(const struct ref_scale_ops *cur_ops, const char *tag) - { - pr_alert("%s" SCALE_FLAG -- "--- %s: verbose=%d verbose_batched=%d shutdown=%d holdoff=%d lookup_instances=%ld loops=%ld nreaders=%d nruns=%d readdelay=%d\n", scale_type, tag, -+ "--- %s: verbose=%d verbose_batched=%d shutdown=%d holdoff=%d lookup_instances=%ld loops=%d nreaders=%d nruns=%d readdelay=%d\n", scale_type, tag, - verbose, verbose_batched, shutdown, holdoff, lookup_instances, loops, nreaders, nruns, readdelay); - } - -@@ -1238,12 +1238,16 @@ ref_scale_init(void) - // Reader tasks (default to ~75% of online CPUs). - if (nreaders < 0) - nreaders = (num_online_cpus() >> 1) + (num_online_cpus() >> 2); -- if (WARN_ONCE(loops <= 0, "%s: loops = %ld, adjusted to 1\n", __func__, loops)) -+ if (WARN_ONCE(loops <= 0, "%s: loops = %d, adjusted to 1\n", __func__, loops)) - loops = 1; - if (WARN_ONCE(nreaders <= 0, "%s: nreaders = %d, adjusted to 1\n", __func__, nreaders)) - nreaders = 1; - if (WARN_ONCE(nruns <= 0, "%s: nruns = %d, adjusted to 1\n", __func__, nruns)) - nruns = 1; -+ if (WARN_ONCE(loops > INT_MAX / nreaders, -+ "%s: nreaders * loops will overflow, adjusted loops to %d", -+ __func__, INT_MAX / nreaders)) -+ loops = INT_MAX / nreaders; - reader_tasks = kcalloc(nreaders, sizeof(reader_tasks[0]), - GFP_KERNEL); - if (!reader_tasks) { -diff -purNx .git BPI-Router-Linux-kernel/kernel/rcu/tree.c BPI-Router-Linux-kernel-6.16.12/kernel/rcu/tree.c ---- BPI-Router-Linux-kernel/kernel/rcu/tree.c 2025-10-22 13:53:23.595327306 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/rcu/tree.c 2025-10-22 13:53:56.779167868 -0400 -@@ -3072,6 +3072,10 @@ __call_rcu_common(struct rcu_head *head, - /* Misaligned rcu_head! */ - WARN_ON_ONCE((unsigned long)head & (sizeof(void *) - 1)); - -+ /* Avoid NULL dereference if callback is NULL. */ -+ if (WARN_ON_ONCE(!func)) -+ return; -+ - if (debug_rcu_head_queue(head)) { - /* - * Probable double call_rcu(), so leak the callback. -@@ -4229,6 +4233,8 @@ int rcutree_prepare_cpu(unsigned int cpu - rdp->rcu_iw_gp_seq = rdp->gp_seq - 1; - trace_rcu_grace_period(rcu_state.name, rdp->gp_seq, TPS("cpuonl")); - raw_spin_unlock_irqrestore_rcu_node(rnp, flags); -+ -+ rcu_preempt_deferred_qs_init(rdp); - rcu_spawn_rnp_kthreads(rnp); - rcu_spawn_cpu_nocb_kthread(cpu); - ASSERT_EXCLUSIVE_WRITER(rcu_state.n_online_cpus); -diff -purNx .git BPI-Router-Linux-kernel/kernel/rcu/tree.h BPI-Router-Linux-kernel-6.16.12/kernel/rcu/tree.h ---- BPI-Router-Linux-kernel/kernel/rcu/tree.h 2025-10-22 13:53:23.595327306 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/rcu/tree.h 2025-10-22 13:53:56.779167868 -0400 -@@ -174,6 +174,17 @@ struct rcu_snap_record { - unsigned long jiffies; /* Track jiffies value */ - }; - -+/* -+ * An IRQ work (deferred_qs_iw) is used by RCU to get the scheduler's attention. -+ * to report quiescent states at the soonest possible time. -+ * The request can be in one of the following states: -+ * - DEFER_QS_IDLE: An IRQ work is yet to be scheduled. -+ * - DEFER_QS_PENDING: An IRQ work was scheduled but either not yet run, or it -+ * ran and we still haven't reported a quiescent state. -+ */ -+#define DEFER_QS_IDLE 0 -+#define DEFER_QS_PENDING 1 -+ - /* Per-CPU data for read-copy update. */ - struct rcu_data { - /* 1) quiescent-state and grace-period handling : */ -@@ -192,7 +203,7 @@ struct rcu_data { - /* during and after the last grace */ - /* period it is aware of. */ - struct irq_work defer_qs_iw; /* Obtain later scheduler attention. */ -- bool defer_qs_iw_pending; /* Scheduler attention pending? */ -+ int defer_qs_iw_pending; /* Scheduler attention pending? */ - struct work_struct strict_work; /* Schedule readers for strict GPs. */ - - /* 2) batch handling */ -@@ -477,6 +488,7 @@ static int rcu_print_task_exp_stall(stru - static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp); - static void rcu_flavor_sched_clock_irq(int user); - static void dump_blkd_tasks(struct rcu_node *rnp, int ncheck); -+static void rcu_preempt_deferred_qs_init(struct rcu_data *rdp); - static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags); - static void rcu_preempt_boost_start_gp(struct rcu_node *rnp); - static bool rcu_is_callbacks_kthread(struct rcu_data *rdp); -diff -purNx .git BPI-Router-Linux-kernel/kernel/rcu/tree_nocb.h BPI-Router-Linux-kernel-6.16.12/kernel/rcu/tree_nocb.h ---- BPI-Router-Linux-kernel/kernel/rcu/tree_nocb.h 2025-10-22 13:53:23.595327306 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/rcu/tree_nocb.h 2025-10-22 13:53:56.779167868 -0400 -@@ -276,7 +276,7 @@ static void wake_nocb_gp_defer(struct rc - * callback storms, no need to wake up too early. - */ - if (waketype == RCU_NOCB_WAKE_LAZY && -- rdp->nocb_defer_wakeup == RCU_NOCB_WAKE_NOT) { -+ rdp_gp->nocb_defer_wakeup == RCU_NOCB_WAKE_NOT) { - mod_timer(&rdp_gp->nocb_timer, jiffies + rcu_get_jiffies_lazy_flush()); - WRITE_ONCE(rdp_gp->nocb_defer_wakeup, waketype); - } else if (waketype == RCU_NOCB_WAKE_BYPASS) { -@@ -1146,7 +1146,6 @@ static bool rcu_nocb_rdp_offload_wait_co - static int rcu_nocb_rdp_offload(struct rcu_data *rdp) - { - int wake_gp; -- struct rcu_data *rdp_gp = rdp->nocb_gp_rdp; - - WARN_ON_ONCE(cpu_online(rdp->cpu)); - /* -@@ -1156,7 +1155,7 @@ static int rcu_nocb_rdp_offload(struct r - if (!rdp->nocb_gp_rdp) - return -EINVAL; - -- if (WARN_ON_ONCE(!rdp_gp->nocb_gp_kthread)) -+ if (WARN_ON_ONCE(!rdp->nocb_gp_kthread)) - return -EINVAL; - - pr_info("Offloading %d\n", rdp->cpu); -@@ -1166,7 +1165,7 @@ static int rcu_nocb_rdp_offload(struct r - - wake_gp = rcu_nocb_queue_toggle_rdp(rdp); - if (wake_gp) -- wake_up_process(rdp_gp->nocb_gp_kthread); -+ wake_up_process(rdp->nocb_gp_kthread); - - swait_event_exclusive(rdp->nocb_state_wq, - rcu_nocb_rdp_offload_wait_cond(rdp)); -diff -purNx .git BPI-Router-Linux-kernel/kernel/rcu/tree_plugin.h BPI-Router-Linux-kernel-6.16.12/kernel/rcu/tree_plugin.h ---- BPI-Router-Linux-kernel/kernel/rcu/tree_plugin.h 2025-10-22 13:53:23.595327306 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/rcu/tree_plugin.h 2025-10-22 13:53:56.779167868 -0400 -@@ -486,13 +486,16 @@ rcu_preempt_deferred_qs_irqrestore(struc - struct rcu_node *rnp; - union rcu_special special; - -+ rdp = this_cpu_ptr(&rcu_data); -+ if (rdp->defer_qs_iw_pending == DEFER_QS_PENDING) -+ rdp->defer_qs_iw_pending = DEFER_QS_IDLE; -+ - /* - * If RCU core is waiting for this CPU to exit its critical section, - * report the fact that it has exited. Because irqs are disabled, - * t->rcu_read_unlock_special cannot change. - */ - special = t->rcu_read_unlock_special; -- rdp = this_cpu_ptr(&rcu_data); - if (!special.s && !rdp->cpu_no_qs.b.exp) { - local_irq_restore(flags); - return; -@@ -624,10 +627,29 @@ notrace void rcu_preempt_deferred_qs(str - */ - static void rcu_preempt_deferred_qs_handler(struct irq_work *iwp) - { -+ unsigned long flags; - struct rcu_data *rdp; - - rdp = container_of(iwp, struct rcu_data, defer_qs_iw); -- rdp->defer_qs_iw_pending = false; -+ local_irq_save(flags); -+ -+ /* -+ * If the IRQ work handler happens to run in the middle of RCU read-side -+ * critical section, it could be ineffective in getting the scheduler's -+ * attention to report a deferred quiescent state (the whole point of the -+ * IRQ work). For this reason, requeue the IRQ work. -+ * -+ * Basically, we want to avoid following situation: -+ * 1. rcu_read_unlock() queues IRQ work (state -> DEFER_QS_PENDING) -+ * 2. CPU enters new rcu_read_lock() -+ * 3. IRQ work runs but cannot report QS due to rcu_preempt_depth() > 0 -+ * 4. rcu_read_unlock() does not re-queue work (state still PENDING) -+ * 5. Deferred QS reporting does not happen. -+ */ -+ if (rcu_preempt_depth() > 0) -+ WRITE_ONCE(rdp->defer_qs_iw_pending, DEFER_QS_IDLE); -+ -+ local_irq_restore(flags); - } - - /* -@@ -673,17 +695,11 @@ static void rcu_read_unlock_special(stru - set_tsk_need_resched(current); - set_preempt_need_resched(); - if (IS_ENABLED(CONFIG_IRQ_WORK) && irqs_were_disabled && -- expboost && !rdp->defer_qs_iw_pending && cpu_online(rdp->cpu)) { -+ expboost && rdp->defer_qs_iw_pending != DEFER_QS_PENDING && -+ cpu_online(rdp->cpu)) { - // Get scheduler to re-evaluate and call hooks. - // If !IRQ_WORK, FQS scan will eventually IPI. -- if (IS_ENABLED(CONFIG_RCU_STRICT_GRACE_PERIOD) && -- IS_ENABLED(CONFIG_PREEMPT_RT)) -- rdp->defer_qs_iw = IRQ_WORK_INIT_HARD( -- rcu_preempt_deferred_qs_handler); -- else -- init_irq_work(&rdp->defer_qs_iw, -- rcu_preempt_deferred_qs_handler); -- rdp->defer_qs_iw_pending = true; -+ rdp->defer_qs_iw_pending = DEFER_QS_PENDING; - irq_work_queue_on(&rdp->defer_qs_iw, rdp->cpu); - } - } -@@ -822,6 +838,10 @@ dump_blkd_tasks(struct rcu_node *rnp, in - } - } - -+static void rcu_preempt_deferred_qs_init(struct rcu_data *rdp) -+{ -+ rdp->defer_qs_iw = IRQ_WORK_INIT_HARD(rcu_preempt_deferred_qs_handler); -+} - #else /* #ifdef CONFIG_PREEMPT_RCU */ - - /* -@@ -1021,6 +1041,8 @@ dump_blkd_tasks(struct rcu_node *rnp, in - WARN_ON_ONCE(!list_empty(&rnp->blkd_tasks)); - } - -+static void rcu_preempt_deferred_qs_init(struct rcu_data *rdp) { } -+ - #endif /* #else #ifdef CONFIG_PREEMPT_RCU */ - - /* -diff -purNx .git BPI-Router-Linux-kernel/kernel/resource.c BPI-Router-Linux-kernel-6.16.12/kernel/resource.c ---- BPI-Router-Linux-kernel/kernel/resource.c 2025-10-22 13:53:23.595327306 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/resource.c 2025-10-22 13:53:56.779167868 -0400 -@@ -1279,8 +1279,9 @@ static int __request_region_locked(struc - * become unavailable to other users. Conflicts are - * not expected. Warn to aid debugging if encountered. - */ -- if (conflict->desc == IORES_DESC_DEVICE_PRIVATE_MEMORY) { -- pr_warn("Unaddressable device %s %pR conflicts with %pR", -+ if (parent == &iomem_resource && -+ conflict->desc == IORES_DESC_DEVICE_PRIVATE_MEMORY) { -+ pr_warn("Unaddressable device %s %pR conflicts with %pR\n", - conflict->name, conflict, res); - } - if (conflict != parent) { -diff -purNx .git BPI-Router-Linux-kernel/kernel/sched/core.c BPI-Router-Linux-kernel-6.16.12/kernel/sched/core.c ---- BPI-Router-Linux-kernel/kernel/sched/core.c 2025-10-22 13:53:23.595327306 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/sched/core.c 2025-10-22 13:53:56.779167868 -0400 -@@ -3362,10 +3362,6 @@ void set_task_cpu(struct task_struct *p, - #ifdef CONFIG_NUMA_BALANCING - static void __migrate_swap_task(struct task_struct *p, int cpu) - { -- __schedstat_inc(p->stats.numa_task_swapped); -- count_vm_numa_event(NUMA_TASK_SWAP); -- count_memcg_event_mm(p->mm, NUMA_TASK_SWAP); -- - if (task_on_rq_queued(p)) { - struct rq *src_rq, *dst_rq; - struct rq_flags srf, drf; -@@ -3943,6 +3939,11 @@ static inline bool ttwu_queue_cond(struc - if (!scx_allow_ttwu_queue(p)) - return false; - -+#ifdef CONFIG_SMP -+ if (p->sched_class == &stop_sched_class) -+ return false; -+#endif -+ - /* - * Do not complicate things with the async wake_list while the CPU is - * in hotplug state. -@@ -7663,7 +7664,7 @@ const char *preempt_model_str(void) - - if (IS_ENABLED(CONFIG_PREEMPT_DYNAMIC)) { - seq_buf_printf(&s, "(%s)%s", -- preempt_dynamic_mode > 0 ? -+ preempt_dynamic_mode >= 0 ? - preempt_modes[preempt_dynamic_mode] : "undef", - brace ? "}" : ""); - return seq_buf_str(&s); -@@ -7934,9 +7935,8 @@ int migrate_task_to(struct task_struct * - if (!cpumask_test_cpu(target_cpu, p->cpus_ptr)) - return -EINVAL; - -- __schedstat_inc(p->stats.numa_task_migrated); -- count_vm_numa_event(NUMA_TASK_MIGRATE); -- count_memcg_event_mm(p->mm, NUMA_TASK_MIGRATE); -+ /* TODO: This is not properly updating schedstats */ -+ - trace_sched_move_numa(p, curr_cpu, target_cpu); - return stop_one_cpu(curr_cpu, migration_cpu_stop, &arg); - } -@@ -8545,7 +8545,7 @@ void __init sched_init(void) - init_cfs_bandwidth(&root_task_group.cfs_bandwidth, NULL); - #endif /* CONFIG_FAIR_GROUP_SCHED */ - #ifdef CONFIG_EXT_GROUP_SCHED -- root_task_group.scx_weight = CGROUP_WEIGHT_DFL; -+ scx_tg_init(&root_task_group); - #endif /* CONFIG_EXT_GROUP_SCHED */ - #ifdef CONFIG_RT_GROUP_SCHED - root_task_group.rt_se = (struct sched_rt_entity **)ptr; -@@ -8985,7 +8985,7 @@ struct task_group *sched_create_group(st - if (!alloc_rt_sched_group(tg, parent)) - goto err; - -- scx_group_set_weight(tg, CGROUP_WEIGHT_DFL); -+ scx_tg_init(tg); - alloc_uclamp_sched_group(tg, parent); - - return tg; -diff -purNx .git BPI-Router-Linux-kernel/kernel/sched/deadline.c BPI-Router-Linux-kernel-6.16.12/kernel/sched/deadline.c ---- BPI-Router-Linux-kernel/kernel/sched/deadline.c 2025-10-22 13:53:23.599327286 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/sched/deadline.c 2025-10-22 13:53:56.779167868 -0400 -@@ -1504,7 +1504,9 @@ static void update_curr_dl_se(struct rq - if (dl_entity_is_special(dl_se)) - return; - -- scaled_delta_exec = dl_scaled_delta_exec(rq, dl_se, delta_exec); -+ scaled_delta_exec = delta_exec; -+ if (!dl_server(dl_se)) -+ scaled_delta_exec = dl_scaled_delta_exec(rq, dl_se, delta_exec); - - dl_se->runtime -= scaled_delta_exec; - -@@ -1611,7 +1613,7 @@ throttle: - */ - void dl_server_update_idle_time(struct rq *rq, struct task_struct *p) - { -- s64 delta_exec, scaled_delta_exec; -+ s64 delta_exec; - - if (!rq->fair_server.dl_defer) - return; -@@ -1624,9 +1626,7 @@ void dl_server_update_idle_time(struct r - if (delta_exec < 0) - return; - -- scaled_delta_exec = dl_scaled_delta_exec(rq, &rq->fair_server, delta_exec); -- -- rq->fair_server.runtime -= scaled_delta_exec; -+ rq->fair_server.runtime -= delta_exec; - - if (rq->fair_server.runtime < 0) { - rq->fair_server.dl_defer_running = 0; -@@ -2976,7 +2976,14 @@ void dl_clear_root_domain(struct root_do - int i; - - guard(raw_spinlock_irqsave)(&rd->dl_bw.lock); -+ -+ /* -+ * Reset total_bw to zero and extra_bw to max_bw so that next -+ * loop will add dl-servers contributions back properly, -+ */ - rd->dl_bw.total_bw = 0; -+ for_each_cpu(i, rd->span) -+ cpu_rq(i)->dl.extra_bw = cpu_rq(i)->dl.max_bw; - - /* - * dl_servers are not tasks. Since dl_add_task_root_domain ignores -@@ -3242,6 +3249,9 @@ void sched_dl_do_global(void) - if (global_rt_runtime() != RUNTIME_INF) - new_bw = to_ratio(global_rt_period(), global_rt_runtime()); - -+ for_each_possible_cpu(cpu) -+ init_dl_rq_bw_ratio(&cpu_rq(cpu)->dl); -+ - for_each_possible_cpu(cpu) { - rcu_read_lock_sched(); - -@@ -3257,7 +3267,6 @@ void sched_dl_do_global(void) - raw_spin_unlock_irqrestore(&dl_b->lock, flags); - - rcu_read_unlock_sched(); -- init_dl_rq_bw_ratio(&cpu_rq(cpu)->dl); - } - } - -diff -purNx .git BPI-Router-Linux-kernel/kernel/sched/debug.c BPI-Router-Linux-kernel-6.16.12/kernel/sched/debug.c ---- BPI-Router-Linux-kernel/kernel/sched/debug.c 2025-10-22 13:53:23.599327286 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/sched/debug.c 2025-10-22 13:53:56.779167868 -0400 -@@ -1210,10 +1210,6 @@ void proc_sched_show_task(struct task_st - P_SCHEDSTAT(nr_failed_migrations_running); - P_SCHEDSTAT(nr_failed_migrations_hot); - P_SCHEDSTAT(nr_forced_migrations); --#ifdef CONFIG_NUMA_BALANCING -- P_SCHEDSTAT(numa_task_migrated); -- P_SCHEDSTAT(numa_task_swapped); --#endif - P_SCHEDSTAT(nr_wakeups); - P_SCHEDSTAT(nr_wakeups_sync); - P_SCHEDSTAT(nr_wakeups_migrate); -diff -purNx .git BPI-Router-Linux-kernel/kernel/sched/ext.c BPI-Router-Linux-kernel-6.16.12/kernel/sched/ext.c ---- BPI-Router-Linux-kernel/kernel/sched/ext.c 2025-10-22 13:53:23.599327286 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/sched/ext.c 2025-10-22 13:53:56.779167868 -0400 -@@ -1272,7 +1272,8 @@ static inline struct rq *scx_locked_rq(v - - #define SCX_CALL_OP(sch, mask, op, rq, args...) \ - do { \ -- update_locked_rq(rq); \ -+ if (rq) \ -+ update_locked_rq(rq); \ - if (mask) { \ - scx_kf_allow(mask); \ - (sch)->ops.op(args); \ -@@ -1280,14 +1281,16 @@ do { \ - } else { \ - (sch)->ops.op(args); \ - } \ -- update_locked_rq(NULL); \ -+ if (rq) \ -+ update_locked_rq(NULL); \ - } while (0) - - #define SCX_CALL_OP_RET(sch, mask, op, rq, args...) \ - ({ \ - __typeof__((sch)->ops.op(args)) __ret; \ - \ -- update_locked_rq(rq); \ -+ if (rq) \ -+ update_locked_rq(rq); \ - if (mask) { \ - scx_kf_allow(mask); \ - __ret = (sch)->ops.op(args); \ -@@ -1295,7 +1298,8 @@ do { \ - } else { \ - __ret = (sch)->ops.op(args); \ - } \ -- update_locked_rq(NULL); \ -+ if (rq) \ -+ update_locked_rq(NULL); \ - __ret; \ - }) - -@@ -4092,6 +4096,11 @@ bool scx_can_stop_tick(struct rq *rq) - DEFINE_STATIC_PERCPU_RWSEM(scx_cgroup_rwsem); - static bool scx_cgroup_enabled; - -+void scx_tg_init(struct task_group *tg) -+{ -+ tg->scx_weight = CGROUP_WEIGHT_DFL; -+} -+ - int scx_tg_online(struct task_group *tg) - { - struct scx_sched *sch = scx_root; -@@ -4241,12 +4250,12 @@ void scx_group_set_weight(struct task_gr - - percpu_down_read(&scx_cgroup_rwsem); - -- if (scx_cgroup_enabled && tg->scx_weight != weight) { -- if (SCX_HAS_OP(sch, cgroup_set_weight)) -- SCX_CALL_OP(sch, SCX_KF_UNLOCKED, cgroup_set_weight, NULL, -- tg_cgrp(tg), weight); -- tg->scx_weight = weight; -- } -+ if (scx_cgroup_enabled && SCX_HAS_OP(sch, cgroup_set_weight) && -+ tg->scx_weight != weight) -+ SCX_CALL_OP(sch, SCX_KF_UNLOCKED, cgroup_set_weight, NULL, -+ tg_cgrp(tg), weight); -+ -+ tg->scx_weight = weight; - - percpu_up_read(&scx_cgroup_rwsem); - } -@@ -5685,6 +5694,9 @@ static int scx_enable(struct sched_ext_o - __setscheduler_class(p->policy, p->prio); - struct sched_enq_and_set_ctx ctx; - -+ if (!tryget_task_struct(p)) -+ continue; -+ - if (old_class != new_class && p->se.sched_delayed) - dequeue_task(task_rq(p), p, DEQUEUE_SLEEP | DEQUEUE_DELAYED); - -@@ -5697,6 +5709,7 @@ static int scx_enable(struct sched_ext_o - sched_enq_and_set_task(&ctx); - - check_class_changed(task_rq(p), p, old_class, p->prio); -+ put_task_struct(p); - } - scx_task_iter_stop(&sti); - percpu_up_write(&scx_fork_rwsem); -@@ -6781,12 +6794,8 @@ __bpf_kfunc u32 scx_bpf_reenqueue_local( - * CPUs disagree, they use %ENQUEUE_RESTORE which is bypassed to - * the current local DSQ for running tasks and thus are not - * visible to the BPF scheduler. -- * -- * Also skip re-enqueueing tasks that can only run on this -- * CPU, as they would just be re-added to the same local -- * DSQ without any benefit. - */ -- if (p->migration_pending || is_migration_disabled(p) || p->nr_cpus_allowed == 1) -+ if (p->migration_pending) - continue; - - dispatch_dequeue(rq, p); -diff -purNx .git BPI-Router-Linux-kernel/kernel/sched/ext.h BPI-Router-Linux-kernel-6.16.12/kernel/sched/ext.h ---- BPI-Router-Linux-kernel/kernel/sched/ext.h 2025-10-22 13:53:23.599327286 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/sched/ext.h 2025-10-22 13:53:56.779167868 -0400 -@@ -79,6 +79,7 @@ static inline void scx_update_idle(struc - - #ifdef CONFIG_CGROUP_SCHED - #ifdef CONFIG_EXT_GROUP_SCHED -+void scx_tg_init(struct task_group *tg); - int scx_tg_online(struct task_group *tg); - void scx_tg_offline(struct task_group *tg); - int scx_cgroup_can_attach(struct cgroup_taskset *tset); -@@ -88,6 +89,7 @@ void scx_cgroup_cancel_attach(struct cgr - void scx_group_set_weight(struct task_group *tg, unsigned long cgrp_weight); - void scx_group_set_idle(struct task_group *tg, bool idle); - #else /* CONFIG_EXT_GROUP_SCHED */ -+static inline void scx_tg_init(struct task_group *tg) {} - static inline int scx_tg_online(struct task_group *tg) { return 0; } - static inline void scx_tg_offline(struct task_group *tg) {} - static inline int scx_cgroup_can_attach(struct cgroup_taskset *tset) { return 0; } -diff -purNx .git BPI-Router-Linux-kernel/kernel/sched/ext_idle.c BPI-Router-Linux-kernel-6.16.12/kernel/sched/ext_idle.c ---- BPI-Router-Linux-kernel/kernel/sched/ext_idle.c 2025-10-22 13:53:23.599327286 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/sched/ext_idle.c 2025-10-22 13:53:56.779167868 -0400 -@@ -75,7 +75,7 @@ static int scx_cpu_node_if_enabled(int c - return cpu_to_node(cpu); - } - --bool scx_idle_test_and_clear_cpu(int cpu) -+static bool scx_idle_test_and_clear_cpu(int cpu) - { - int node = scx_cpu_node_if_enabled(cpu); - struct cpumask *idle_cpus = idle_cpumask(node)->cpu; -@@ -198,7 +198,7 @@ pick_idle_cpu_from_online_nodes(const st - /* - * Find an idle CPU in the system, starting from @node. - */ --s32 scx_pick_idle_cpu(const struct cpumask *cpus_allowed, int node, u64 flags) -+static s32 scx_pick_idle_cpu(const struct cpumask *cpus_allowed, int node, u64 flags) - { - s32 cpu; - -@@ -794,6 +794,16 @@ static void reset_idle_masks(struct sche - cpumask_and(idle_cpumask(node)->smt, cpu_online_mask, node_mask); - } - } -+#else /* !CONFIG_SMP */ -+static bool scx_idle_test_and_clear_cpu(int cpu) -+{ -+ return -EBUSY; -+} -+ -+static s32 scx_pick_idle_cpu(const struct cpumask *cpus_allowed, int node, u64 flags) -+{ -+ return -EBUSY; -+} - #endif /* CONFIG_SMP */ - - void scx_idle_enable(struct sched_ext_ops *ops) -@@ -860,8 +870,34 @@ static bool check_builtin_idle_enabled(v - return false; - } - --s32 select_cpu_from_kfunc(struct task_struct *p, s32 prev_cpu, u64 wake_flags, -- const struct cpumask *allowed, u64 flags) -+/* -+ * Determine whether @p is a migration-disabled task in the context of BPF -+ * code. -+ * -+ * We can't simply check whether @p->migration_disabled is set in a -+ * sched_ext callback, because migration is always disabled for the current -+ * task while running BPF code. -+ * -+ * The prolog (__bpf_prog_enter) and epilog (__bpf_prog_exit) respectively -+ * disable and re-enable migration. For this reason, the current task -+ * inside a sched_ext callback is always a migration-disabled task. -+ * -+ * Therefore, when @p->migration_disabled == 1, check whether @p is the -+ * current task or not: if it is, then migration was not disabled before -+ * entering the callback, otherwise migration was disabled. -+ * -+ * Returns true if @p is migration-disabled, false otherwise. -+ */ -+static bool is_bpf_migration_disabled(const struct task_struct *p) -+{ -+ if (p->migration_disabled == 1) -+ return p != current; -+ else -+ return p->migration_disabled; -+} -+ -+static s32 select_cpu_from_kfunc(struct task_struct *p, s32 prev_cpu, u64 wake_flags, -+ const struct cpumask *allowed, u64 flags) - { - struct rq *rq; - struct rq_flags rf; -@@ -903,7 +939,7 @@ s32 select_cpu_from_kfunc(struct task_st - * selection optimizations and simply check whether the previously - * used CPU is idle and within the allowed cpumask. - */ -- if (p->nr_cpus_allowed == 1) { -+ if (p->nr_cpus_allowed == 1 || is_bpf_migration_disabled(p)) { - if (cpumask_test_cpu(prev_cpu, allowed ?: p->cpus_ptr) && - scx_idle_test_and_clear_cpu(prev_cpu)) - cpu = prev_cpu; -@@ -1125,10 +1161,10 @@ __bpf_kfunc bool scx_bpf_test_and_clear_ - if (!check_builtin_idle_enabled()) - return false; - -- if (kf_cpu_valid(cpu, NULL)) -- return scx_idle_test_and_clear_cpu(cpu); -- else -+ if (!kf_cpu_valid(cpu, NULL)) - return false; -+ -+ return scx_idle_test_and_clear_cpu(cpu); - } - - /** -diff -purNx .git BPI-Router-Linux-kernel/kernel/sched/ext_idle.h BPI-Router-Linux-kernel-6.16.12/kernel/sched/ext_idle.h ---- BPI-Router-Linux-kernel/kernel/sched/ext_idle.h 2025-10-22 13:53:23.599327286 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/sched/ext_idle.h 2025-10-22 13:53:56.779167868 -0400 -@@ -15,16 +15,9 @@ struct sched_ext_ops; - #ifdef CONFIG_SMP - void scx_idle_update_selcpu_topology(struct sched_ext_ops *ops); - void scx_idle_init_masks(void); --bool scx_idle_test_and_clear_cpu(int cpu); --s32 scx_pick_idle_cpu(const struct cpumask *cpus_allowed, int node, u64 flags); - #else /* !CONFIG_SMP */ - static inline void scx_idle_update_selcpu_topology(struct sched_ext_ops *ops) {} - static inline void scx_idle_init_masks(void) {} --static inline bool scx_idle_test_and_clear_cpu(int cpu) { return false; } --static inline s32 scx_pick_idle_cpu(const struct cpumask *cpus_allowed, int node, u64 flags) --{ -- return -EBUSY; --} - #endif /* CONFIG_SMP */ - - s32 scx_select_cpu_dfl(struct task_struct *p, s32 prev_cpu, u64 wake_flags, -diff -purNx .git BPI-Router-Linux-kernel/kernel/sched/fair.c BPI-Router-Linux-kernel-6.16.12/kernel/sched/fair.c ---- BPI-Router-Linux-kernel/kernel/sched/fair.c 2025-10-22 13:53:23.599327286 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/sched/fair.c 2025-10-22 13:53:56.783167849 -0400 -@@ -12174,8 +12174,14 @@ static inline bool update_newidle_cost(s - /* - * Track max cost of a domain to make sure to not delay the - * next wakeup on the CPU. -+ * -+ * sched_balance_newidle() bumps the cost whenever newidle -+ * balance fails, and we don't want things to grow out of -+ * control. Use the sysctl_sched_migration_cost as the upper -+ * limit, plus a litle extra to avoid off by ones. - */ -- sd->max_newidle_lb_cost = cost; -+ sd->max_newidle_lb_cost = -+ min(cost, sysctl_sched_migration_cost + 200); - sd->last_decay_max_lb_cost = jiffies; - } else if (time_after(jiffies, sd->last_decay_max_lb_cost + HZ)) { - /* -@@ -12867,10 +12873,17 @@ static int sched_balance_newidle(struct - - t1 = sched_clock_cpu(this_cpu); - domain_cost = t1 - t0; -- update_newidle_cost(sd, domain_cost); -- - curr_cost += domain_cost; - t0 = t1; -+ -+ /* -+ * Failing newidle means it is not effective; -+ * bump the cost so we end up doing less of it. -+ */ -+ if (!pulled_task) -+ domain_cost = (3 * sd->max_newidle_lb_cost) / 2; -+ -+ update_newidle_cost(sd, domain_cost); - } - - /* -diff -purNx .git BPI-Router-Linux-kernel/kernel/sched/loadavg.c BPI-Router-Linux-kernel-6.16.12/kernel/sched/loadavg.c ---- BPI-Router-Linux-kernel/kernel/sched/loadavg.c 2025-10-22 13:53:23.599327286 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/sched/loadavg.c 2025-10-22 13:53:56.783167849 -0400 -@@ -80,7 +80,7 @@ long calc_load_fold_active(struct rq *th - long nr_active, delta = 0; - - nr_active = this_rq->nr_running - adjust; -- nr_active += (int)this_rq->nr_uninterruptible; -+ nr_active += (long)this_rq->nr_uninterruptible; - - if (nr_active != this_rq->calc_load_active) { - delta = nr_active - this_rq->calc_load_active; -diff -purNx .git BPI-Router-Linux-kernel/kernel/sched/psi.c BPI-Router-Linux-kernel-6.16.12/kernel/sched/psi.c ---- BPI-Router-Linux-kernel/kernel/sched/psi.c 2025-10-22 13:53:23.599327286 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/sched/psi.c 2025-10-22 13:53:56.783167849 -0400 -@@ -172,17 +172,35 @@ struct psi_group psi_system = { - .pcpu = &system_group_pcpu, - }; - -+static DEFINE_PER_CPU(seqcount_t, psi_seq) = SEQCNT_ZERO(psi_seq); -+ -+static inline void psi_write_begin(int cpu) -+{ -+ write_seqcount_begin(per_cpu_ptr(&psi_seq, cpu)); -+} -+ -+static inline void psi_write_end(int cpu) -+{ -+ write_seqcount_end(per_cpu_ptr(&psi_seq, cpu)); -+} -+ -+static inline u32 psi_read_begin(int cpu) -+{ -+ return read_seqcount_begin(per_cpu_ptr(&psi_seq, cpu)); -+} -+ -+static inline bool psi_read_retry(int cpu, u32 seq) -+{ -+ return read_seqcount_retry(per_cpu_ptr(&psi_seq, cpu), seq); -+} -+ - static void psi_avgs_work(struct work_struct *work); - - static void poll_timer_fn(struct timer_list *t); - - static void group_init(struct psi_group *group) - { -- int cpu; -- - group->enabled = true; -- for_each_possible_cpu(cpu) -- seqcount_init(&per_cpu_ptr(group->pcpu, cpu)->seq); - group->avg_last_update = sched_clock(); - group->avg_next_update = group->avg_last_update + psi_period; - mutex_init(&group->avgs_lock); -@@ -262,14 +280,14 @@ static void get_recent_times(struct psi_ - - /* Snapshot a coherent view of the CPU state */ - do { -- seq = read_seqcount_begin(&groupc->seq); -+ seq = psi_read_begin(cpu); - now = cpu_clock(cpu); - memcpy(times, groupc->times, sizeof(groupc->times)); - state_mask = groupc->state_mask; - state_start = groupc->state_start; - if (cpu == current_cpu) - memcpy(tasks, groupc->tasks, sizeof(groupc->tasks)); -- } while (read_seqcount_retry(&groupc->seq, seq)); -+ } while (psi_read_retry(cpu, seq)); - - /* Calculate state time deltas against the previous snapshot */ - for (s = 0; s < NR_PSI_STATES; s++) { -@@ -768,31 +786,21 @@ static void record_times(struct psi_grou - groupc->times[PSI_NONIDLE] += delta; - } - -+#define for_each_group(iter, group) \ -+ for (typeof(group) iter = group; iter; iter = iter->parent) -+ - static void psi_group_change(struct psi_group *group, int cpu, - unsigned int clear, unsigned int set, -- bool wake_clock) -+ u64 now, bool wake_clock) - { - struct psi_group_cpu *groupc; - unsigned int t, m; - u32 state_mask; -- u64 now; - - lockdep_assert_rq_held(cpu_rq(cpu)); - groupc = per_cpu_ptr(group->pcpu, cpu); - - /* -- * First we update the task counts according to the state -- * change requested through the @clear and @set bits. -- * -- * Then if the cgroup PSI stats accounting enabled, we -- * assess the aggregate resource states this CPU's tasks -- * have been in since the last change, and account any -- * SOME and FULL time these may have resulted in. -- */ -- write_seqcount_begin(&groupc->seq); -- now = cpu_clock(cpu); -- -- /* - * Start with TSK_ONCPU, which doesn't have a corresponding - * task count - it's just a boolean flag directly encoded in - * the state mask. Clear, set, or carry the current state if -@@ -843,7 +851,6 @@ static void psi_group_change(struct psi_ - - groupc->state_mask = state_mask; - -- write_seqcount_end(&groupc->seq); - return; - } - -@@ -864,8 +871,6 @@ static void psi_group_change(struct psi_ - - groupc->state_mask = state_mask; - -- write_seqcount_end(&groupc->seq); -- - if (state_mask & group->rtpoll_states) - psi_schedule_rtpoll_work(group, 1, false); - -@@ -900,24 +905,29 @@ static void psi_flags_change(struct task - void psi_task_change(struct task_struct *task, int clear, int set) - { - int cpu = task_cpu(task); -- struct psi_group *group; -+ u64 now; - - if (!task->pid) - return; - - psi_flags_change(task, clear, set); - -- group = task_psi_group(task); -- do { -- psi_group_change(group, cpu, clear, set, true); -- } while ((group = group->parent)); -+ psi_write_begin(cpu); -+ now = cpu_clock(cpu); -+ for_each_group(group, task_psi_group(task)) -+ psi_group_change(group, cpu, clear, set, now, true); -+ psi_write_end(cpu); - } - - void psi_task_switch(struct task_struct *prev, struct task_struct *next, - bool sleep) - { -- struct psi_group *group, *common = NULL; -+ struct psi_group *common = NULL; - int cpu = task_cpu(prev); -+ u64 now; -+ -+ psi_write_begin(cpu); -+ now = cpu_clock(cpu); - - if (next->pid) { - psi_flags_change(next, 0, TSK_ONCPU); -@@ -926,16 +936,15 @@ void psi_task_switch(struct task_struct - * ancestors with @prev, those will already have @prev's - * TSK_ONCPU bit set, and we can stop the iteration there. - */ -- group = task_psi_group(next); -- do { -- if (per_cpu_ptr(group->pcpu, cpu)->state_mask & -- PSI_ONCPU) { -+ for_each_group(group, task_psi_group(next)) { -+ struct psi_group_cpu *groupc = per_cpu_ptr(group->pcpu, cpu); -+ -+ if (groupc->state_mask & PSI_ONCPU) { - common = group; - break; - } -- -- psi_group_change(group, cpu, 0, TSK_ONCPU, true); -- } while ((group = group->parent)); -+ psi_group_change(group, cpu, 0, TSK_ONCPU, now, true); -+ } - } - - if (prev->pid) { -@@ -968,12 +977,11 @@ void psi_task_switch(struct task_struct - - psi_flags_change(prev, clear, set); - -- group = task_psi_group(prev); -- do { -+ for_each_group(group, task_psi_group(prev)) { - if (group == common) - break; -- psi_group_change(group, cpu, clear, set, wake_clock); -- } while ((group = group->parent)); -+ psi_group_change(group, cpu, clear, set, now, wake_clock); -+ } - - /* - * TSK_ONCPU is handled up to the common ancestor. If there are -@@ -983,20 +991,21 @@ void psi_task_switch(struct task_struct - */ - if ((prev->psi_flags ^ next->psi_flags) & ~TSK_ONCPU) { - clear &= ~TSK_ONCPU; -- for (; group; group = group->parent) -- psi_group_change(group, cpu, clear, set, wake_clock); -+ for_each_group(group, common) -+ psi_group_change(group, cpu, clear, set, now, wake_clock); - } - } -+ psi_write_end(cpu); - } - - #ifdef CONFIG_IRQ_TIME_ACCOUNTING - void psi_account_irqtime(struct rq *rq, struct task_struct *curr, struct task_struct *prev) - { - int cpu = task_cpu(curr); -- struct psi_group *group; - struct psi_group_cpu *groupc; - s64 delta; - u64 irq; -+ u64 now; - - if (static_branch_likely(&psi_disabled) || !irqtime_enabled()) - return; -@@ -1005,8 +1014,7 @@ void psi_account_irqtime(struct rq *rq, - return; - - lockdep_assert_rq_held(rq); -- group = task_psi_group(curr); -- if (prev && task_psi_group(prev) == group) -+ if (prev && task_psi_group(prev) == task_psi_group(curr)) - return; - - irq = irq_time_read(cpu); -@@ -1015,25 +1023,22 @@ void psi_account_irqtime(struct rq *rq, - return; - rq->psi_irq_time = irq; - -- do { -- u64 now; -+ psi_write_begin(cpu); -+ now = cpu_clock(cpu); - -+ for_each_group(group, task_psi_group(curr)) { - if (!group->enabled) - continue; - - groupc = per_cpu_ptr(group->pcpu, cpu); - -- write_seqcount_begin(&groupc->seq); -- now = cpu_clock(cpu); -- - record_times(groupc, now); - groupc->times[PSI_IRQ_FULL] += delta; - -- write_seqcount_end(&groupc->seq); -- - if (group->rtpoll_states & (1 << PSI_IRQ_FULL)) - psi_schedule_rtpoll_work(group, 1, false); -- } while ((group = group->parent)); -+ } -+ psi_write_end(cpu); - } - #endif - -@@ -1221,12 +1226,14 @@ void psi_cgroup_restart(struct psi_group - return; - - for_each_possible_cpu(cpu) { -- struct rq *rq = cpu_rq(cpu); -- struct rq_flags rf; -+ u64 now; - -- rq_lock_irq(rq, &rf); -- psi_group_change(group, cpu, 0, 0, true); -- rq_unlock_irq(rq, &rf); -+ guard(rq_lock_irq)(cpu_rq(cpu)); -+ -+ psi_write_begin(cpu); -+ now = cpu_clock(cpu); -+ psi_group_change(group, cpu, 0, 0, now, true); -+ psi_write_end(cpu); - } - } - #endif /* CONFIG_CGROUPS */ -diff -purNx .git BPI-Router-Linux-kernel/kernel/sched/rt.c BPI-Router-Linux-kernel-6.16.12/kernel/sched/rt.c ---- BPI-Router-Linux-kernel/kernel/sched/rt.c 2025-10-22 13:53:23.599327286 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/sched/rt.c 2025-10-22 13:53:56.783167849 -0400 -@@ -2951,6 +2951,12 @@ undo: - sched_domains_mutex_unlock(); - mutex_unlock(&mutex); - -+ /* -+ * After changing maximum available bandwidth for DEADLINE, we need to -+ * recompute per root domain and per cpus variables accordingly. -+ */ -+ rebuild_sched_domains(); -+ - return ret; - } - -diff -purNx .git BPI-Router-Linux-kernel/kernel/sched/sched.h BPI-Router-Linux-kernel-6.16.12/kernel/sched/sched.h ---- BPI-Router-Linux-kernel/kernel/sched/sched.h 2025-10-22 13:53:23.599327286 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/sched/sched.h 2025-10-22 13:53:56.783167849 -0400 -@@ -1149,7 +1149,7 @@ struct rq { - * one CPU and if it got migrated afterwards it may decrease - * it on another CPU. Always updated under the runqueue lock: - */ -- unsigned int nr_uninterruptible; -+ unsigned long nr_uninterruptible; - - union { - struct task_struct __rcu *donor; /* Scheduler context */ -diff -purNx .git BPI-Router-Linux-kernel/kernel/sched/topology.c BPI-Router-Linux-kernel-6.16.12/kernel/sched/topology.c ---- BPI-Router-Linux-kernel/kernel/sched/topology.c 2025-10-22 13:53:23.599327286 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/sched/topology.c 2025-10-22 13:53:56.783167849 -0400 -@@ -2212,6 +2212,8 @@ int sched_numa_find_nth_cpu(const struct - goto unlock; - - hop_masks = bsearch(&k, k.masks, sched_domains_numa_levels, sizeof(k.masks[0]), hop_cmp); -+ if (!hop_masks) -+ goto unlock; - hop = hop_masks - k.masks; - - ret = hop ? -diff -purNx .git BPI-Router-Linux-kernel/kernel/signal.c BPI-Router-Linux-kernel-6.16.12/kernel/signal.c ---- BPI-Router-Linux-kernel/kernel/signal.c 2025-10-22 13:53:23.599327286 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/signal.c 2025-10-22 13:53:56.783167849 -0400 -@@ -4067,6 +4067,7 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, - { - struct pid *pid; - enum pid_type type; -+ int ret; - - /* Enforce flags be set to 0 until we add an extension. */ - if (flags & ~PIDFD_SEND_SIGNAL_FLAGS) -@@ -4108,7 +4109,10 @@ SYSCALL_DEFINE4(pidfd_send_signal, int, - } - } - -- return do_pidfd_send_signal(pid, sig, type, info, flags); -+ ret = do_pidfd_send_signal(pid, sig, type, info, flags); -+ put_pid(pid); -+ -+ return ret; - } - - static int -diff -purNx .git BPI-Router-Linux-kernel/kernel/stop_machine.c BPI-Router-Linux-kernel-6.16.12/kernel/stop_machine.c ---- BPI-Router-Linux-kernel/kernel/stop_machine.c 2025-10-22 13:53:23.599327286 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/stop_machine.c 2025-10-22 13:53:56.783167849 -0400 -@@ -82,18 +82,15 @@ static void cpu_stop_signal_done(struct - } - - static void __cpu_stop_queue_work(struct cpu_stopper *stopper, -- struct cpu_stop_work *work, -- struct wake_q_head *wakeq) -+ struct cpu_stop_work *work) - { - list_add_tail(&work->list, &stopper->works); -- wake_q_add(wakeq, stopper->thread); - } - - /* queue @work to @stopper. if offline, @work is completed immediately */ - static bool cpu_stop_queue_work(unsigned int cpu, struct cpu_stop_work *work) - { - struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu); -- DEFINE_WAKE_Q(wakeq); - unsigned long flags; - bool enabled; - -@@ -101,12 +98,13 @@ static bool cpu_stop_queue_work(unsigned - raw_spin_lock_irqsave(&stopper->lock, flags); - enabled = stopper->enabled; - if (enabled) -- __cpu_stop_queue_work(stopper, work, &wakeq); -+ __cpu_stop_queue_work(stopper, work); - else if (work->done) - cpu_stop_signal_done(work->done); - raw_spin_unlock_irqrestore(&stopper->lock, flags); - -- wake_up_q(&wakeq); -+ if (enabled) -+ wake_up_process(stopper->thread); - preempt_enable(); - - return enabled; -@@ -264,7 +262,6 @@ static int cpu_stop_queue_two_works(int - { - struct cpu_stopper *stopper1 = per_cpu_ptr(&cpu_stopper, cpu1); - struct cpu_stopper *stopper2 = per_cpu_ptr(&cpu_stopper, cpu2); -- DEFINE_WAKE_Q(wakeq); - int err; - - retry: -@@ -300,8 +297,8 @@ retry: - } - - err = 0; -- __cpu_stop_queue_work(stopper1, work1, &wakeq); -- __cpu_stop_queue_work(stopper2, work2, &wakeq); -+ __cpu_stop_queue_work(stopper1, work1); -+ __cpu_stop_queue_work(stopper2, work2); - - unlock: - raw_spin_unlock(&stopper2->lock); -@@ -316,7 +313,10 @@ unlock: - goto retry; - } - -- wake_up_q(&wakeq); -+ if (!err) { -+ wake_up_process(stopper1->thread); -+ wake_up_process(stopper2->thread); -+ } - preempt_enable(); - - return err; -diff -purNx .git BPI-Router-Linux-kernel/kernel/time/hrtimer.c BPI-Router-Linux-kernel-6.16.12/kernel/time/hrtimer.c ---- BPI-Router-Linux-kernel/kernel/time/hrtimer.c 2025-10-22 13:53:23.599327286 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/time/hrtimer.c 2025-10-22 13:53:56.783167849 -0400 -@@ -787,10 +787,10 @@ static void retrigger_next_event(void *a - * of the next expiring timer is enough. The return from the SMP - * function call will take care of the reprogramming in case the - * CPU was in a NOHZ idle sleep. -+ * -+ * In periodic low resolution mode, the next softirq expiration -+ * must also be updated. - */ -- if (!hrtimer_hres_active(base) && !tick_nohz_active) -- return; -- - raw_spin_lock(&base->lock); - hrtimer_update_base(base); - if (hrtimer_hres_active(base)) -@@ -2295,11 +2295,6 @@ int hrtimers_cpu_dying(unsigned int dyin - &new_base->clock_base[i]); - } - -- /* -- * The migration might have changed the first expiring softirq -- * timer on this CPU. Update it. -- */ -- __hrtimer_get_next_event(new_base, HRTIMER_ACTIVE_SOFT); - /* Tell the other CPU to retrigger the next event */ - smp_call_function_single(ncpu, retrigger_next_event, NULL, 0); - -diff -purNx .git BPI-Router-Linux-kernel/kernel/time/posix-cpu-timers.c BPI-Router-Linux-kernel-6.16.12/kernel/time/posix-cpu-timers.c ---- BPI-Router-Linux-kernel/kernel/time/posix-cpu-timers.c 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/time/posix-cpu-timers.c 2025-10-22 13:53:56.783167849 -0400 -@@ -1406,6 +1406,15 @@ void run_posix_cpu_timers(void) - lockdep_assert_irqs_disabled(); - - /* -+ * Ensure that release_task(tsk) can't happen while -+ * handle_posix_cpu_timers() is running. Otherwise, a concurrent -+ * posix_cpu_timer_del() may fail to lock_task_sighand(tsk) and -+ * miss timer->it.cpu.firing != 0. -+ */ -+ if (tsk->exit_state) -+ return; -+ -+ /* - * If the actual expiry is deferred to task work context and the - * work is already scheduled there is no point to do anything here. - */ -diff -purNx .git BPI-Router-Linux-kernel/kernel/time/timekeeping.c BPI-Router-Linux-kernel-6.16.12/kernel/time/timekeeping.c ---- BPI-Router-Linux-kernel/kernel/time/timekeeping.c 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/time/timekeeping.c 2025-10-22 13:53:56.783167849 -0400 -@@ -1256,7 +1256,7 @@ int get_device_system_crosststamp(int (* - struct system_time_snapshot *history_begin, - struct system_device_crosststamp *xtstamp) - { -- struct system_counterval_t system_counterval; -+ struct system_counterval_t system_counterval = {}; - struct timekeeper *tk = &tk_core.timekeeper; - u64 cycles, now, interval_start; - unsigned int clock_was_set_seq = 0; -diff -purNx .git BPI-Router-Linux-kernel/kernel/trace/fgraph.c BPI-Router-Linux-kernel-6.16.12/kernel/trace/fgraph.c ---- BPI-Router-Linux-kernel/kernel/trace/fgraph.c 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/trace/fgraph.c 2025-10-22 13:53:56.783167849 -0400 -@@ -815,6 +815,7 @@ __ftrace_return_to_handler(struct ftrace - unsigned long bitmap; - unsigned long ret; - int offset; -+ int bit; - int i; - - ret_stack = ftrace_pop_return_trace(&trace, &ret, frame_pointer, &offset); -@@ -829,6 +830,15 @@ __ftrace_return_to_handler(struct ftrace - if (fregs) - ftrace_regs_set_instruction_pointer(fregs, ret); - -+ bit = ftrace_test_recursion_trylock(trace.func, ret); -+ /* -+ * This can fail because ftrace_test_recursion_trylock() allows one nest -+ * call. If we are already in a nested call, then we don't probe this and -+ * just return the original return address. -+ */ -+ if (unlikely(bit < 0)) -+ goto out; -+ - #ifdef CONFIG_FUNCTION_GRAPH_RETVAL - trace.retval = ftrace_regs_get_return_value(fregs); - #endif -@@ -852,6 +862,8 @@ __ftrace_return_to_handler(struct ftrace - } - } - -+ ftrace_test_recursion_unlock(bit); -+out: - /* - * The ftrace_graph_return() may still access the current - * ret_stack structure, we need to make sure the update of -@@ -1393,6 +1405,8 @@ error: - ftrace_graph_active--; - gops->saved_func = NULL; - fgraph_lru_release_index(i); -+ if (!ftrace_graph_active) -+ unregister_pm_notifier(&ftrace_suspend_notifier); - } - return ret; - } -diff -purNx .git BPI-Router-Linux-kernel/kernel/trace/fprobe.c BPI-Router-Linux-kernel-6.16.12/kernel/trace/fprobe.c ---- BPI-Router-Linux-kernel/kernel/trace/fprobe.c 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/trace/fprobe.c 2025-10-22 13:53:56.783167849 -0400 -@@ -352,7 +352,7 @@ static void fprobe_return(struct ftrace_ - size_words = SIZE_IN_LONG(size); - ret_ip = ftrace_regs_get_instruction_pointer(fregs); - -- preempt_disable(); -+ preempt_disable_notrace(); - - curr = 0; - while (size_words > curr) { -@@ -368,7 +368,7 @@ static void fprobe_return(struct ftrace_ - } - curr += size; - } -- preempt_enable(); -+ preempt_enable_notrace(); - } - NOKPROBE_SYMBOL(fprobe_return); - -@@ -428,8 +428,9 @@ static int fprobe_addr_list_add(struct f - { - unsigned long *addrs; - -- if (alist->index >= alist->size) -- return -ENOMEM; -+ /* Previously we failed to expand the list. */ -+ if (alist->index == alist->size) -+ return -ENOSPC; - - alist->addrs[alist->index++] = addr; - if (alist->index < alist->size) -@@ -489,7 +490,7 @@ static int fprobe_module_callback(struct - for (i = 0; i < FPROBE_IP_TABLE_SIZE; i++) - fprobe_remove_node_in_module(mod, &fprobe_ip_table[i], &alist); - -- if (alist.index < alist.size && alist.index > 0) -+ if (alist.index > 0) - ftrace_set_filter_ips(&fprobe_graph_ops.ops, - alist.addrs, alist.index, 1, 0); - mutex_unlock(&fprobe_mutex); -diff -purNx .git BPI-Router-Linux-kernel/kernel/trace/ftrace.c BPI-Router-Linux-kernel-6.16.12/kernel/trace/ftrace.c ---- BPI-Router-Linux-kernel/kernel/trace/ftrace.c 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/trace/ftrace.c 2025-10-22 13:53:56.783167849 -0400 -@@ -4665,13 +4665,17 @@ ftrace_regex_open(struct ftrace_ops *ops - } else { - iter->hash = alloc_and_copy_ftrace_hash(size_bits, hash); - } -+ } else { -+ if (hash) -+ iter->hash = alloc_and_copy_ftrace_hash(hash->size_bits, hash); -+ else -+ iter->hash = EMPTY_HASH; -+ } - -- if (!iter->hash) { -- trace_parser_put(&iter->parser); -- goto out_unlock; -- } -- } else -- iter->hash = hash; -+ if (!iter->hash) { -+ trace_parser_put(&iter->parser); -+ goto out_unlock; -+ } - - ret = 0; - -@@ -6547,9 +6551,6 @@ int ftrace_regex_release(struct inode *i - ftrace_hash_move_and_update_ops(iter->ops, orig_hash, - iter->hash, filter_hash); - mutex_unlock(&ftrace_lock); -- } else { -- /* For read only, the hash is the ops hash */ -- iter->hash = NULL; - } - - mutex_unlock(&iter->ops->func_hash->regex_lock); -diff -purNx .git BPI-Router-Linux-kernel/kernel/trace/power-traces.c BPI-Router-Linux-kernel-6.16.12/kernel/trace/power-traces.c ---- BPI-Router-Linux-kernel/kernel/trace/power-traces.c 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/trace/power-traces.c 2025-10-22 13:53:56.783167849 -0400 -@@ -17,5 +17,4 @@ - EXPORT_TRACEPOINT_SYMBOL_GPL(suspend_resume); - EXPORT_TRACEPOINT_SYMBOL_GPL(cpu_idle); - EXPORT_TRACEPOINT_SYMBOL_GPL(cpu_frequency); --EXPORT_TRACEPOINT_SYMBOL_GPL(powernv_throttle); - -diff -purNx .git BPI-Router-Linux-kernel/kernel/trace/preemptirq_delay_test.c BPI-Router-Linux-kernel-6.16.12/kernel/trace/preemptirq_delay_test.c ---- BPI-Router-Linux-kernel/kernel/trace/preemptirq_delay_test.c 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/trace/preemptirq_delay_test.c 2025-10-22 13:53:56.783167849 -0400 -@@ -117,12 +117,15 @@ static int preemptirq_delay_run(void *da - { - int i; - int s = MIN(burst_size, NR_TEST_FUNCS); -- struct cpumask cpu_mask; -+ cpumask_var_t cpu_mask; -+ -+ if (!alloc_cpumask_var(&cpu_mask, GFP_KERNEL)) -+ return -ENOMEM; - - if (cpu_affinity > -1) { -- cpumask_clear(&cpu_mask); -- cpumask_set_cpu(cpu_affinity, &cpu_mask); -- if (set_cpus_allowed_ptr(current, &cpu_mask)) -+ cpumask_clear(cpu_mask); -+ cpumask_set_cpu(cpu_affinity, cpu_mask); -+ if (set_cpus_allowed_ptr(current, cpu_mask)) - pr_err("cpu_affinity:%d, failed\n", cpu_affinity); - } - -@@ -139,6 +142,8 @@ static int preemptirq_delay_run(void *da - - __set_current_state(TASK_RUNNING); - -+ free_cpumask_var(cpu_mask); -+ - return 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/kernel/trace/ring_buffer.c BPI-Router-Linux-kernel-6.16.12/kernel/trace/ring_buffer.c ---- BPI-Router-Linux-kernel/kernel/trace/ring_buffer.c 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/trace/ring_buffer.c 2025-10-22 13:53:56.787167830 -0400 -@@ -5846,24 +5846,20 @@ ring_buffer_consume(struct trace_buffer - EXPORT_SYMBOL_GPL(ring_buffer_consume); - - /** -- * ring_buffer_read_prepare - Prepare for a non consuming read of the buffer -+ * ring_buffer_read_start - start a non consuming read of the buffer - * @buffer: The ring buffer to read from - * @cpu: The cpu buffer to iterate over - * @flags: gfp flags to use for memory allocation - * -- * This performs the initial preparations necessary to iterate -- * through the buffer. Memory is allocated, buffer resizing -- * is disabled, and the iterator pointer is returned to the caller. -- * -- * After a sequence of ring_buffer_read_prepare calls, the user is -- * expected to make at least one call to ring_buffer_read_prepare_sync. -- * Afterwards, ring_buffer_read_start is invoked to get things going -- * for real. -+ * This creates an iterator to allow non-consuming iteration through -+ * the buffer. If the buffer is disabled for writing, it will produce -+ * the same information each time, but if the buffer is still writing -+ * then the first hit of a write will cause the iteration to stop. - * -- * This overall must be paired with ring_buffer_read_finish. -+ * Must be paired with ring_buffer_read_finish. - */ - struct ring_buffer_iter * --ring_buffer_read_prepare(struct trace_buffer *buffer, int cpu, gfp_t flags) -+ring_buffer_read_start(struct trace_buffer *buffer, int cpu, gfp_t flags) - { - struct ring_buffer_per_cpu *cpu_buffer; - struct ring_buffer_iter *iter; -@@ -5889,51 +5885,12 @@ ring_buffer_read_prepare(struct trace_bu - - atomic_inc(&cpu_buffer->resize_disabled); - -- return iter; --} --EXPORT_SYMBOL_GPL(ring_buffer_read_prepare); -- --/** -- * ring_buffer_read_prepare_sync - Synchronize a set of prepare calls -- * -- * All previously invoked ring_buffer_read_prepare calls to prepare -- * iterators will be synchronized. Afterwards, read_buffer_read_start -- * calls on those iterators are allowed. -- */ --void --ring_buffer_read_prepare_sync(void) --{ -- synchronize_rcu(); --} --EXPORT_SYMBOL_GPL(ring_buffer_read_prepare_sync); -- --/** -- * ring_buffer_read_start - start a non consuming read of the buffer -- * @iter: The iterator returned by ring_buffer_read_prepare -- * -- * This finalizes the startup of an iteration through the buffer. -- * The iterator comes from a call to ring_buffer_read_prepare and -- * an intervening ring_buffer_read_prepare_sync must have been -- * performed. -- * -- * Must be paired with ring_buffer_read_finish. -- */ --void --ring_buffer_read_start(struct ring_buffer_iter *iter) --{ -- struct ring_buffer_per_cpu *cpu_buffer; -- unsigned long flags; -- -- if (!iter) -- return; -- -- cpu_buffer = iter->cpu_buffer; -- -- raw_spin_lock_irqsave(&cpu_buffer->reader_lock, flags); -+ guard(raw_spinlock_irqsave)(&cpu_buffer->reader_lock); - arch_spin_lock(&cpu_buffer->lock); - rb_iter_reset(iter); - arch_spin_unlock(&cpu_buffer->lock); -- raw_spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); -+ -+ return iter; - } - EXPORT_SYMBOL_GPL(ring_buffer_read_start); - -@@ -7223,7 +7180,7 @@ int ring_buffer_map(struct trace_buffer - atomic_dec(&cpu_buffer->resize_disabled); - } - -- return 0; -+ return err; - } - - int ring_buffer_unmap(struct trace_buffer *buffer, int cpu) -diff -purNx .git BPI-Router-Linux-kernel/kernel/trace/rv/monitors/scpd/Kconfig BPI-Router-Linux-kernel-6.16.12/kernel/trace/rv/monitors/scpd/Kconfig ---- BPI-Router-Linux-kernel/kernel/trace/rv/monitors/scpd/Kconfig 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/trace/rv/monitors/scpd/Kconfig 2025-10-22 13:53:56.787167830 -0400 -@@ -2,7 +2,7 @@ - # - config RV_MON_SCPD - depends on RV -- depends on PREEMPT_TRACER -+ depends on TRACE_PREEMPT_TOGGLE - depends on RV_MON_SCHED - default y - select DA_MON_EVENTS_IMPLICIT -diff -purNx .git BPI-Router-Linux-kernel/kernel/trace/rv/monitors/sncid/Kconfig BPI-Router-Linux-kernel-6.16.12/kernel/trace/rv/monitors/sncid/Kconfig ---- BPI-Router-Linux-kernel/kernel/trace/rv/monitors/sncid/Kconfig 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/trace/rv/monitors/sncid/Kconfig 2025-10-22 13:53:56.787167830 -0400 -@@ -2,7 +2,7 @@ - # - config RV_MON_SNCID - depends on RV -- depends on IRQSOFF_TRACER -+ depends on TRACE_IRQFLAGS - depends on RV_MON_SCHED - default y - select DA_MON_EVENTS_IMPLICIT -diff -purNx .git BPI-Router-Linux-kernel/kernel/trace/rv/monitors/snep/Kconfig BPI-Router-Linux-kernel-6.16.12/kernel/trace/rv/monitors/snep/Kconfig ---- BPI-Router-Linux-kernel/kernel/trace/rv/monitors/snep/Kconfig 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/trace/rv/monitors/snep/Kconfig 2025-10-22 13:53:56.787167830 -0400 -@@ -2,7 +2,7 @@ - # - config RV_MON_SNEP - depends on RV -- depends on PREEMPT_TRACER -+ depends on TRACE_PREEMPT_TOGGLE - depends on RV_MON_SCHED - default y - select DA_MON_EVENTS_IMPLICIT -diff -purNx .git BPI-Router-Linux-kernel/kernel/trace/rv/monitors/wip/Kconfig BPI-Router-Linux-kernel-6.16.12/kernel/trace/rv/monitors/wip/Kconfig ---- BPI-Router-Linux-kernel/kernel/trace/rv/monitors/wip/Kconfig 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/trace/rv/monitors/wip/Kconfig 2025-10-22 13:53:56.787167830 -0400 -@@ -2,7 +2,7 @@ - # - config RV_MON_WIP - depends on RV -- depends on PREEMPT_TRACER -+ depends on TRACE_PREEMPT_TOGGLE - select DA_MON_EVENTS_IMPLICIT - bool "wip monitor" - help -diff -purNx .git BPI-Router-Linux-kernel/kernel/trace/rv/rv_trace.h BPI-Router-Linux-kernel-6.16.12/kernel/trace/rv/rv_trace.h ---- BPI-Router-Linux-kernel/kernel/trace/rv/rv_trace.h 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/trace/rv/rv_trace.h 2025-10-22 13:53:56.787167830 -0400 -@@ -16,24 +16,24 @@ DECLARE_EVENT_CLASS(event_da_monitor, - TP_ARGS(state, event, next_state, final_state), - - TP_STRUCT__entry( -- __array( char, state, MAX_DA_NAME_LEN ) -- __array( char, event, MAX_DA_NAME_LEN ) -- __array( char, next_state, MAX_DA_NAME_LEN ) -- __field( bool, final_state ) -+ __string( state, state ) -+ __string( event, event ) -+ __string( next_state, next_state ) -+ __field( bool, final_state ) - ), - - TP_fast_assign( -- memcpy(__entry->state, state, MAX_DA_NAME_LEN); -- memcpy(__entry->event, event, MAX_DA_NAME_LEN); -- memcpy(__entry->next_state, next_state, MAX_DA_NAME_LEN); -- __entry->final_state = final_state; -+ __assign_str(state); -+ __assign_str(event); -+ __assign_str(next_state); -+ __entry->final_state = final_state; - ), - -- TP_printk("%s x %s -> %s %s", -- __entry->state, -- __entry->event, -- __entry->next_state, -- __entry->final_state ? "(final)" : "") -+ TP_printk("%s x %s -> %s%s", -+ __get_str(state), -+ __get_str(event), -+ __get_str(next_state), -+ __entry->final_state ? " (final)" : "") - ); - - DECLARE_EVENT_CLASS(error_da_monitor, -@@ -43,18 +43,18 @@ DECLARE_EVENT_CLASS(error_da_monitor, - TP_ARGS(state, event), - - TP_STRUCT__entry( -- __array( char, state, MAX_DA_NAME_LEN ) -- __array( char, event, MAX_DA_NAME_LEN ) -+ __string( state, state ) -+ __string( event, event ) - ), - - TP_fast_assign( -- memcpy(__entry->state, state, MAX_DA_NAME_LEN); -- memcpy(__entry->event, event, MAX_DA_NAME_LEN); -+ __assign_str(state); -+ __assign_str(event); - ), - - TP_printk("event %s not expected in the state %s", -- __entry->event, -- __entry->state) -+ __get_str(event), -+ __get_str(state)) - ); - - #include -@@ -75,27 +75,27 @@ DECLARE_EVENT_CLASS(event_da_monitor_id, - TP_ARGS(id, state, event, next_state, final_state), - - TP_STRUCT__entry( -- __field( int, id ) -- __array( char, state, MAX_DA_NAME_LEN ) -- __array( char, event, MAX_DA_NAME_LEN ) -- __array( char, next_state, MAX_DA_NAME_LEN ) -- __field( bool, final_state ) -+ __field( int, id ) -+ __string( state, state ) -+ __string( event, event ) -+ __string( next_state, next_state ) -+ __field( bool, final_state ) - ), - - TP_fast_assign( -- memcpy(__entry->state, state, MAX_DA_NAME_LEN); -- memcpy(__entry->event, event, MAX_DA_NAME_LEN); -- memcpy(__entry->next_state, next_state, MAX_DA_NAME_LEN); -- __entry->id = id; -- __entry->final_state = final_state; -+ __assign_str(state); -+ __assign_str(event); -+ __assign_str(next_state); -+ __entry->id = id; -+ __entry->final_state = final_state; - ), - -- TP_printk("%d: %s x %s -> %s %s", -+ TP_printk("%d: %s x %s -> %s%s", - __entry->id, -- __entry->state, -- __entry->event, -- __entry->next_state, -- __entry->final_state ? "(final)" : "") -+ __get_str(state), -+ __get_str(event), -+ __get_str(next_state), -+ __entry->final_state ? " (final)" : "") - ); - - DECLARE_EVENT_CLASS(error_da_monitor_id, -@@ -105,21 +105,21 @@ DECLARE_EVENT_CLASS(error_da_monitor_id, - TP_ARGS(id, state, event), - - TP_STRUCT__entry( -- __field( int, id ) -- __array( char, state, MAX_DA_NAME_LEN ) -- __array( char, event, MAX_DA_NAME_LEN ) -+ __field( int, id ) -+ __string( state, state ) -+ __string( event, event ) - ), - - TP_fast_assign( -- memcpy(__entry->state, state, MAX_DA_NAME_LEN); -- memcpy(__entry->event, event, MAX_DA_NAME_LEN); -- __entry->id = id; -+ __assign_str(state); -+ __assign_str(event); -+ __entry->id = id; - ), - - TP_printk("%d: event %s not expected in the state %s", - __entry->id, -- __entry->event, -- __entry->state) -+ __get_str(event), -+ __get_str(state)) - ); - - #include -@@ -129,8 +129,9 @@ DECLARE_EVENT_CLASS(error_da_monitor_id, - #endif /* CONFIG_DA_MON_EVENTS_ID */ - #endif /* _TRACE_RV_H */ - --/* This part ust be outside protection */ -+/* This part must be outside protection */ - #undef TRACE_INCLUDE_PATH - #define TRACE_INCLUDE_PATH . -+#undef TRACE_INCLUDE_FILE - #define TRACE_INCLUDE_FILE rv_trace - #include -diff -purNx .git BPI-Router-Linux-kernel/kernel/trace/trace.c BPI-Router-Linux-kernel-6.16.12/kernel/trace/trace.c ---- BPI-Router-Linux-kernel/kernel/trace/trace.c 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/trace/trace.c 2025-10-22 13:53:56.787167830 -0400 -@@ -846,7 +846,10 @@ int trace_pid_write(struct trace_pid_lis - /* copy the current bits to the new max */ - ret = trace_pid_list_first(filtered_pids, &pid); - while (!ret) { -- trace_pid_list_set(pid_list, pid); -+ ret = trace_pid_list_set(pid_list, pid); -+ if (ret < 0) -+ goto out; -+ - ret = trace_pid_list_next(filtered_pids, pid + 1, &pid); - nr_pids++; - } -@@ -883,6 +886,7 @@ int trace_pid_write(struct trace_pid_lis - trace_parser_clear(&parser); - ret = 0; - } -+ out: - trace_parser_put(&parser); - - if (ret < 0) { -@@ -1846,7 +1850,7 @@ int trace_get_user(struct trace_parser * - - ret = get_user(ch, ubuf++); - if (ret) -- goto out; -+ goto fail; - - read++; - cnt--; -@@ -1860,7 +1864,7 @@ int trace_get_user(struct trace_parser * - while (cnt && isspace(ch)) { - ret = get_user(ch, ubuf++); - if (ret) -- goto out; -+ goto fail; - read++; - cnt--; - } -@@ -1870,8 +1874,7 @@ int trace_get_user(struct trace_parser * - /* only spaces were written */ - if (isspace(ch) || !ch) { - *ppos += read; -- ret = read; -- goto out; -+ return read; - } - } - -@@ -1881,11 +1884,12 @@ int trace_get_user(struct trace_parser * - parser->buffer[parser->idx++] = ch; - else { - ret = -EINVAL; -- goto out; -+ goto fail; - } -+ - ret = get_user(ch, ubuf++); - if (ret) -- goto out; -+ goto fail; - read++; - cnt--; - } -@@ -1901,13 +1905,13 @@ int trace_get_user(struct trace_parser * - parser->buffer[parser->idx] = 0; - } else { - ret = -EINVAL; -- goto out; -+ goto fail; - } - - *ppos += read; -- ret = read; -- --out: -+ return read; -+fail: -+ trace_parser_fail(parser); - return ret; - } - -@@ -2410,10 +2414,10 @@ int __init register_tracer(struct tracer - mutex_unlock(&trace_types_lock); - - if (ret || !default_bootup_tracer) -- goto out_unlock; -+ return ret; - - if (strncmp(default_bootup_tracer, type->name, MAX_TRACER_SIZE)) -- goto out_unlock; -+ return 0; - - printk(KERN_INFO "Starting tracer '%s'\n", type->name); - /* Do we want this tracer to start on bootup? */ -@@ -2425,8 +2429,7 @@ int __init register_tracer(struct tracer - /* disable other selftests, since this will break it. */ - disable_tracing_selftest("running a tracer"); - -- out_unlock: -- return ret; -+ return 0; - } - - static void tracing_reset_cpu(struct array_buffer *buf, int cpu) -@@ -4735,21 +4738,15 @@ __tracing_open(struct inode *inode, stru - if (iter->cpu_file == RING_BUFFER_ALL_CPUS) { - for_each_tracing_cpu(cpu) { - iter->buffer_iter[cpu] = -- ring_buffer_read_prepare(iter->array_buffer->buffer, -- cpu, GFP_KERNEL); -- } -- ring_buffer_read_prepare_sync(); -- for_each_tracing_cpu(cpu) { -- ring_buffer_read_start(iter->buffer_iter[cpu]); -+ ring_buffer_read_start(iter->array_buffer->buffer, -+ cpu, GFP_KERNEL); - tracing_iter_reset(iter, cpu); - } - } else { - cpu = iter->cpu_file; - iter->buffer_iter[cpu] = -- ring_buffer_read_prepare(iter->array_buffer->buffer, -- cpu, GFP_KERNEL); -- ring_buffer_read_prepare_sync(); -- ring_buffer_read_start(iter->buffer_iter[cpu]); -+ ring_buffer_read_start(iter->array_buffer->buffer, -+ cpu, GFP_KERNEL); - tracing_iter_reset(iter, cpu); - } - -@@ -7271,7 +7268,7 @@ static ssize_t write_marker_to_buffer(st - entry = ring_buffer_event_data(event); - entry->ip = ip; - -- len = __copy_from_user_inatomic(&entry->buf, ubuf, cnt); -+ len = copy_from_user_nofault(&entry->buf, ubuf, cnt); - if (len) { - memcpy(&entry->buf, FAULTED_STR, FAULTED_SIZE); - cnt = FAULTED_SIZE; -@@ -7368,7 +7365,7 @@ static ssize_t write_raw_marker_to_buffe - - entry = ring_buffer_event_data(event); - -- len = __copy_from_user_inatomic(&entry->id, ubuf, cnt); -+ len = copy_from_user_nofault(&entry->id, ubuf, cnt); - if (len) { - entry->id = -1; - memcpy(&entry->buf, FAULTED_STR, FAULTED_SIZE); -@@ -8960,12 +8957,12 @@ ftrace_trace_snapshot_callback(struct tr - out_reg: - ret = tracing_arm_snapshot(tr); - if (ret < 0) -- goto out; -+ return ret; - - ret = register_ftrace_function_probe(glob, tr, ops, count); - if (ret < 0) - tracing_disarm_snapshot(tr); -- out: -+ - return ret < 0 ? ret : 0; - } - -@@ -10707,10 +10704,10 @@ static void ftrace_dump_one(struct trace - ret = print_trace_line(&iter); - if (ret != TRACE_TYPE_NO_CONSUME) - trace_consume(&iter); -+ -+ trace_printk_seq(&iter.seq); - } - touch_nmi_watchdog(); -- -- trace_printk_seq(&iter.seq); - } - - if (!cnt) -@@ -11063,7 +11060,7 @@ __init static int tracer_alloc_buffers(v - BUILD_BUG_ON(TRACE_ITER_LAST_BIT > TRACE_FLAGS_MAX_SIZE); - - if (!alloc_cpumask_var(&tracing_buffer_mask, GFP_KERNEL)) -- goto out; -+ return -ENOMEM; - - if (!alloc_cpumask_var(&global_trace.tracing_cpumask, GFP_KERNEL)) - goto out_free_buffer_mask; -@@ -11181,7 +11178,6 @@ out_free_cpumask: - free_cpumask_var(global_trace.tracing_cpumask); - out_free_buffer_mask: - free_cpumask_var(tracing_buffer_mask); --out: - return ret; - } - -diff -purNx .git BPI-Router-Linux-kernel/kernel/trace/trace_dynevent.c BPI-Router-Linux-kernel-6.16.12/kernel/trace/trace_dynevent.c ---- BPI-Router-Linux-kernel/kernel/trace/trace_dynevent.c 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/trace/trace_dynevent.c 2025-10-22 13:53:56.787167830 -0400 -@@ -230,6 +230,10 @@ static int dyn_event_open(struct inode * - { - int ret; - -+ ret = security_locked_down(LOCKDOWN_TRACEFS); -+ if (ret) -+ return ret; -+ - ret = tracing_check_open_get_tr(NULL); - if (ret) - return ret; -diff -purNx .git BPI-Router-Linux-kernel/kernel/trace/trace_events.c BPI-Router-Linux-kernel-6.16.12/kernel/trace/trace_events.c ---- BPI-Router-Linux-kernel/kernel/trace/trace_events.c 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/trace/trace_events.c 2025-10-22 13:53:56.787167830 -0400 -@@ -3136,7 +3136,10 @@ __register_event(struct trace_event_call - if (ret < 0) - return ret; - -+ down_write(&trace_event_sem); - list_add(&call->list, &ftrace_events); -+ up_write(&trace_event_sem); -+ - if (call->flags & TRACE_EVENT_FL_DYNAMIC) - atomic_set(&call->refcnt, 0); - else -@@ -3750,6 +3753,8 @@ __trace_add_event_dirs(struct trace_arra - struct trace_event_call *call; - int ret; - -+ lockdep_assert_held(&trace_event_sem); -+ - list_for_each_entry(call, &ftrace_events, list) { - ret = __trace_add_new_event(call, tr); - if (ret < 0) -diff -purNx .git BPI-Router-Linux-kernel/kernel/trace/trace_events_filter.c BPI-Router-Linux-kernel-6.16.12/kernel/trace/trace_events_filter.c ---- BPI-Router-Linux-kernel/kernel/trace/trace_events_filter.c 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/trace/trace_events_filter.c 2025-10-22 13:53:56.787167830 -0400 -@@ -1344,13 +1344,14 @@ struct filter_list { - - struct filter_head { - struct list_head list; -- struct rcu_head rcu; -+ union { -+ struct rcu_head rcu; -+ struct rcu_work rwork; -+ }; - }; - -- --static void free_filter_list(struct rcu_head *rhp) -+static void free_filter_list(struct filter_head *filter_list) - { -- struct filter_head *filter_list = container_of(rhp, struct filter_head, rcu); - struct filter_list *filter_item, *tmp; - - list_for_each_entry_safe(filter_item, tmp, &filter_list->list, list) { -@@ -1361,9 +1362,20 @@ static void free_filter_list(struct rcu_ - kfree(filter_list); - } - -+static void free_filter_list_work(struct work_struct *work) -+{ -+ struct filter_head *filter_list; -+ -+ filter_list = container_of(to_rcu_work(work), struct filter_head, rwork); -+ free_filter_list(filter_list); -+} -+ - static void free_filter_list_tasks(struct rcu_head *rhp) - { -- call_rcu(rhp, free_filter_list); -+ struct filter_head *filter_list = container_of(rhp, struct filter_head, rcu); -+ -+ INIT_RCU_WORK(&filter_list->rwork, free_filter_list_work); -+ queue_rcu_work(system_wq, &filter_list->rwork); - } - - /* -@@ -1436,15 +1448,6 @@ static void filter_free_subsystem_filter - - INIT_LIST_HEAD(&head->list); - -- item = kmalloc(sizeof(*item), GFP_KERNEL); -- if (!item) { -- kfree(head); -- goto free_now; -- } -- -- item->filter = filter; -- list_add_tail(&item->list, &head->list); -- - list_for_each_entry(file, &tr->events, list) { - if (file->system != dir) - continue; -@@ -1456,13 +1459,20 @@ static void filter_free_subsystem_filter - event_clear_filter(file); - } - -+ item = kmalloc(sizeof(*item), GFP_KERNEL); -+ if (!item) -+ goto free_now; -+ -+ item->filter = filter; -+ list_add_tail(&item->list, &head->list); -+ - delay_free_filter(head); - return; - free_now: - tracepoint_synchronize_unregister(); - - if (head) -- free_filter_list(&head->rcu); -+ free_filter_list(head); - - list_for_each_entry(file, &tr->events, list) { - if (file->system != dir || !file->filter) -@@ -2307,7 +2317,7 @@ static int process_system_preds(struct t - return 0; - fail: - /* No call succeeded */ -- free_filter_list(&filter_list->rcu); -+ free_filter_list(filter_list); - parse_error(pe, FILT_ERR_BAD_SUBSYS_FILTER, 0); - return -EINVAL; - fail_mem: -@@ -2317,7 +2327,7 @@ static int process_system_preds(struct t - if (!fail) - delay_free_filter(filter_list); - else -- free_filter_list(&filter_list->rcu); -+ free_filter_list(filter_list); - - return -ENOMEM; - } -diff -purNx .git BPI-Router-Linux-kernel/kernel/trace/trace_functions_graph.c BPI-Router-Linux-kernel-6.16.12/kernel/trace/trace_functions_graph.c ---- BPI-Router-Linux-kernel/kernel/trace/trace_functions_graph.c 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/trace/trace_functions_graph.c 2025-10-22 13:53:56.787167830 -0400 -@@ -27,14 +27,21 @@ struct fgraph_cpu_data { - unsigned long enter_funcs[FTRACE_RETFUNC_DEPTH]; - }; - -+struct fgraph_ent_args { -+ struct ftrace_graph_ent_entry ent; -+ /* Force the sizeof of args[] to have FTRACE_REGS_MAX_ARGS entries */ -+ unsigned long args[FTRACE_REGS_MAX_ARGS]; -+}; -+ - struct fgraph_data { - struct fgraph_cpu_data __percpu *cpu_data; - - /* Place to preserve last processed entry. */ - union { -- struct ftrace_graph_ent_entry ent; -+ struct fgraph_ent_args ent; -+ /* TODO allow retaddr to have args */ - struct fgraph_retaddr_ent_entry rent; -- } ent; -+ }; - struct ftrace_graph_ret_entry ret; - int failed; - int cpu; -@@ -455,10 +462,16 @@ static int graph_trace_init(struct trace - return 0; - } - -+static struct tracer graph_trace; -+ - static int ftrace_graph_trace_args(struct trace_array *tr, int set) - { - trace_func_graph_ent_t entry; - -+ /* Do nothing if the current tracer is not this tracer */ -+ if (tr->current_trace != &graph_trace) -+ return 0; -+ - if (set) - entry = trace_graph_entry_args; - else -@@ -621,10 +634,13 @@ get_return_for_leaf(struct trace_iterato - * Save current and next entries for later reference - * if the output fails. - */ -- if (unlikely(curr->ent.type == TRACE_GRAPH_RETADDR_ENT)) -- data->ent.rent = *(struct fgraph_retaddr_ent_entry *)curr; -- else -- data->ent.ent = *curr; -+ if (unlikely(curr->ent.type == TRACE_GRAPH_RETADDR_ENT)) { -+ data->rent = *(struct fgraph_retaddr_ent_entry *)curr; -+ } else { -+ int size = min((int)sizeof(data->ent), (int)iter->ent_size); -+ -+ memcpy(&data->ent, curr, size); -+ } - /* - * If the next event is not a return type, then - * we only care about what type it is. Otherwise we can -diff -purNx .git BPI-Router-Linux-kernel/kernel/trace/trace.h BPI-Router-Linux-kernel-6.16.12/kernel/trace/trace.h ---- BPI-Router-Linux-kernel/kernel/trace/trace.h 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/trace/trace.h 2025-10-22 13:53:56.787167830 -0400 -@@ -1292,6 +1292,7 @@ bool ftrace_event_is_function(struct tra - */ - struct trace_parser { - bool cont; -+ bool fail; - char *buffer; - unsigned idx; - unsigned size; -@@ -1299,7 +1300,7 @@ struct trace_parser { - - static inline bool trace_parser_loaded(struct trace_parser *parser) - { -- return (parser->idx != 0); -+ return !parser->fail && parser->idx != 0; - } - - static inline bool trace_parser_cont(struct trace_parser *parser) -@@ -1313,6 +1314,11 @@ static inline void trace_parser_clear(st - parser->idx = 0; - } - -+static inline void trace_parser_fail(struct trace_parser *parser) -+{ -+ parser->fail = true; -+} -+ - extern int trace_parser_get_init(struct trace_parser *parser, int size); - extern void trace_parser_put(struct trace_parser *parser); - extern int trace_get_user(struct trace_parser *parser, const char __user *ubuf, -@@ -2204,7 +2210,7 @@ static inline bool is_good_system_name(c - static inline void sanitize_event_name(char *name) - { - while (*name++ != '\0') -- if (*name == ':' || *name == '.') -+ if (*name == ':' || *name == '.' || *name == '*') - *name = '_'; - } - -diff -purNx .git BPI-Router-Linux-kernel/kernel/trace/trace_kdb.c BPI-Router-Linux-kernel-6.16.12/kernel/trace/trace_kdb.c ---- BPI-Router-Linux-kernel/kernel/trace/trace_kdb.c 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/trace/trace_kdb.c 2025-10-22 13:53:56.787167830 -0400 -@@ -43,17 +43,15 @@ static void ftrace_dump_buf(int skip_ent - if (cpu_file == RING_BUFFER_ALL_CPUS) { - for_each_tracing_cpu(cpu) { - iter.buffer_iter[cpu] = -- ring_buffer_read_prepare(iter.array_buffer->buffer, -- cpu, GFP_ATOMIC); -- ring_buffer_read_start(iter.buffer_iter[cpu]); -+ ring_buffer_read_start(iter.array_buffer->buffer, -+ cpu, GFP_ATOMIC); - tracing_iter_reset(&iter, cpu); - } - } else { - iter.cpu_file = cpu_file; - iter.buffer_iter[cpu_file] = -- ring_buffer_read_prepare(iter.array_buffer->buffer, -+ ring_buffer_read_start(iter.array_buffer->buffer, - cpu_file, GFP_ATOMIC); -- ring_buffer_read_start(iter.buffer_iter[cpu_file]); - tracing_iter_reset(&iter, cpu_file); - } - -diff -purNx .git BPI-Router-Linux-kernel/kernel/trace/trace_osnoise.c BPI-Router-Linux-kernel-6.16.12/kernel/trace/trace_osnoise.c ---- BPI-Router-Linux-kernel/kernel/trace/trace_osnoise.c 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/trace/trace_osnoise.c 2025-10-22 13:53:56.787167830 -0400 -@@ -637,8 +637,8 @@ __timerlat_dump_stack(struct trace_buffe - - entry = ring_buffer_event_data(event); - -- memcpy(&entry->caller, fstack->calls, size); - entry->size = fstack->nr_entries; -+ memcpy(&entry->caller, fstack->calls, size); - - trace_buffer_unlock_commit_nostack(buffer, event); - } -@@ -2322,12 +2322,16 @@ osnoise_cpus_write(struct file *filp, co - int running, err; - char *buf __free(kfree) = NULL; - -- buf = kmalloc(count, GFP_KERNEL); -+ if (count < 1) -+ return 0; -+ -+ buf = kmalloc(count + 1, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - if (copy_from_user(buf, ubuf, count)) - return -EFAULT; -+ buf[count] = '\0'; - - if (!zalloc_cpumask_var(&osnoise_cpumask_new, GFP_KERNEL)) - return -ENOMEM; -diff -purNx .git BPI-Router-Linux-kernel/kernel/trace/trace_probe.c BPI-Router-Linux-kernel-6.16.12/kernel/trace/trace_probe.c ---- BPI-Router-Linux-kernel/kernel/trace/trace_probe.c 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/trace/trace_probe.c 2025-10-22 13:53:56.787167830 -0400 -@@ -657,7 +657,7 @@ static int parse_btf_arg(char *varname, - ret = query_btf_context(ctx); - if (ret < 0 || ctx->nr_params == 0) { - trace_probe_log_err(ctx->offset, NO_BTF_ENTRY); -- return PTR_ERR(params); -+ return -ENOENT; - } - } - params = ctx->params; -diff -purNx .git BPI-Router-Linux-kernel/kernel/ucount.c BPI-Router-Linux-kernel-6.16.12/kernel/ucount.c ---- BPI-Router-Linux-kernel/kernel/ucount.c 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/ucount.c 2025-10-22 13:53:56.787167830 -0400 -@@ -199,7 +199,7 @@ void put_ucounts(struct ucounts *ucounts - } - } - --static inline bool atomic_long_inc_below(atomic_long_t *v, int u) -+static inline bool atomic_long_inc_below(atomic_long_t *v, long u) - { - long c, old; - c = atomic_long_read(v); -diff -purNx .git BPI-Router-Linux-kernel/kernel/vhost_task.c BPI-Router-Linux-kernel-6.16.12/kernel/vhost_task.c ---- BPI-Router-Linux-kernel/kernel/vhost_task.c 2025-10-22 13:53:23.603327268 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/vhost_task.c 2025-10-22 13:53:56.787167830 -0400 -@@ -100,6 +100,7 @@ void vhost_task_stop(struct vhost_task * - * freeing it below. - */ - wait_for_completion(&vtsk->exited); -+ put_task_struct(vtsk->task); - kfree(vtsk); - } - EXPORT_SYMBOL_GPL(vhost_task_stop); -@@ -148,7 +149,7 @@ struct vhost_task *vhost_task_create(boo - return ERR_PTR(PTR_ERR(tsk)); - } - -- vtsk->task = tsk; -+ vtsk->task = get_task_struct(tsk); - return vtsk; - } - EXPORT_SYMBOL_GPL(vhost_task_create); -diff -purNx .git BPI-Router-Linux-kernel/kernel/workqueue.c BPI-Router-Linux-kernel-6.16.12/kernel/workqueue.c ---- BPI-Router-Linux-kernel/kernel/workqueue.c 2025-10-22 13:53:23.607327249 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/kernel/workqueue.c 2025-10-22 13:53:56.787167830 -0400 -@@ -7767,7 +7767,8 @@ void __init workqueue_init_early(void) - restrict_unbound_cpumask("workqueue.unbound_cpus", &wq_cmdline_cpumask); - - cpumask_copy(wq_requested_unbound_cpumask, wq_unbound_cpumask); -- -+ cpumask_andnot(wq_isolated_cpumask, cpu_possible_mask, -+ housekeeping_cpumask(HK_TYPE_DOMAIN)); - pwq_cache = KMEM_CACHE(pool_workqueue, SLAB_PANIC); - - unbound_wq_update_pwq_attrs_buf = alloc_workqueue_attrs(); -diff -purNx .git BPI-Router-Linux-kernel/lib/alloc_tag.c BPI-Router-Linux-kernel-6.16.12/lib/alloc_tag.c ---- BPI-Router-Linux-kernel/lib/alloc_tag.c 2025-10-22 13:53:23.607327249 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/lib/alloc_tag.c 2025-10-22 13:53:56.787167830 -0400 -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - - #define ALLOCINFO_FILE_NAME "allocinfo" - #define MODULE_ALLOC_TAG_VMAP_SIZE (100000UL * sizeof(struct alloc_tag)) -@@ -134,6 +135,9 @@ size_t alloc_tag_top_users(struct codeta - struct codetag_bytes n; - unsigned int i, nr = 0; - -+ if (IS_ERR_OR_NULL(alloc_tag_cttype)) -+ return 0; -+ - if (can_sleep) - codetag_lock_module_list(alloc_tag_cttype, true); - else if (!codetag_trylock_module_list(alloc_tag_cttype)) -@@ -632,8 +636,13 @@ static int load_module(struct module *mo - mod->name); - return -ENOMEM; - } -- } - -+ /* -+ * Avoid a kmemleak false positive. The pointer to the counters is stored -+ * in the alloc_tag section of the module and cannot be directly accessed. -+ */ -+ kmemleak_ignore_percpu(tag->counters); -+ } - return 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/lib/crypto/aescfb.c BPI-Router-Linux-kernel-6.16.12/lib/crypto/aescfb.c ---- BPI-Router-Linux-kernel/lib/crypto/aescfb.c 2025-10-22 13:53:23.607327249 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/lib/crypto/aescfb.c 2025-10-22 13:53:56.787167830 -0400 -@@ -106,11 +106,11 @@ MODULE_LICENSE("GPL"); - */ - - static struct { -- u8 ptext[64]; -- u8 ctext[64]; -+ u8 ptext[64] __nonstring; -+ u8 ctext[64] __nonstring; - -- u8 key[AES_MAX_KEY_SIZE]; -- u8 iv[AES_BLOCK_SIZE]; -+ u8 key[AES_MAX_KEY_SIZE] __nonstring; -+ u8 iv[AES_BLOCK_SIZE] __nonstring; - - int klen; - int len; -diff -purNx .git BPI-Router-Linux-kernel/lib/crypto/aesgcm.c BPI-Router-Linux-kernel-6.16.12/lib/crypto/aesgcm.c ---- BPI-Router-Linux-kernel/lib/crypto/aesgcm.c 2025-10-22 13:53:23.607327249 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/lib/crypto/aesgcm.c 2025-10-22 13:53:56.787167830 -0400 -@@ -205,19 +205,19 @@ MODULE_LICENSE("GPL"); - * Test code below. Vectors taken from crypto/testmgr.h - */ - --static const u8 __initconst ctext0[16] = -+static const u8 __initconst ctext0[16] __nonstring = - "\x58\xe2\xfc\xce\xfa\x7e\x30\x61" - "\x36\x7f\x1d\x57\xa4\xe7\x45\x5a"; - - static const u8 __initconst ptext1[16]; - --static const u8 __initconst ctext1[32] = -+static const u8 __initconst ctext1[32] __nonstring = - "\x03\x88\xda\xce\x60\xb6\xa3\x92" - "\xf3\x28\xc2\xb9\x71\xb2\xfe\x78" - "\xab\x6e\x47\xd4\x2c\xec\x13\xbd" - "\xf5\x3a\x67\xb2\x12\x57\xbd\xdf"; - --static const u8 __initconst ptext2[64] = -+static const u8 __initconst ptext2[64] __nonstring = - "\xd9\x31\x32\x25\xf8\x84\x06\xe5" - "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" - "\x86\xa7\xa9\x53\x15\x34\xf7\xda" -@@ -227,7 +227,7 @@ static const u8 __initconst ptext2[64] = - "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" - "\xba\x63\x7b\x39\x1a\xaf\xd2\x55"; - --static const u8 __initconst ctext2[80] = -+static const u8 __initconst ctext2[80] __nonstring = - "\x42\x83\x1e\xc2\x21\x77\x74\x24" - "\x4b\x72\x21\xb7\x84\xd0\xd4\x9c" - "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0" -@@ -239,7 +239,7 @@ static const u8 __initconst ctext2[80] = - "\x4d\x5c\x2a\xf3\x27\xcd\x64\xa6" - "\x2c\xf3\x5a\xbd\x2b\xa6\xfa\xb4"; - --static const u8 __initconst ptext3[60] = -+static const u8 __initconst ptext3[60] __nonstring = - "\xd9\x31\x32\x25\xf8\x84\x06\xe5" - "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" - "\x86\xa7\xa9\x53\x15\x34\xf7\xda" -@@ -249,7 +249,7 @@ static const u8 __initconst ptext3[60] = - "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" - "\xba\x63\x7b\x39"; - --static const u8 __initconst ctext3[76] = -+static const u8 __initconst ctext3[76] __nonstring = - "\x42\x83\x1e\xc2\x21\x77\x74\x24" - "\x4b\x72\x21\xb7\x84\xd0\xd4\x9c" - "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0" -@@ -261,17 +261,17 @@ static const u8 __initconst ctext3[76] = - "\x5b\xc9\x4f\xbc\x32\x21\xa5\xdb" - "\x94\xfa\xe9\x5a\xe7\x12\x1a\x47"; - --static const u8 __initconst ctext4[16] = -+static const u8 __initconst ctext4[16] __nonstring = - "\xcd\x33\xb2\x8a\xc7\x73\xf7\x4b" - "\xa0\x0e\xd1\xf3\x12\x57\x24\x35"; - --static const u8 __initconst ctext5[32] = -+static const u8 __initconst ctext5[32] __nonstring = - "\x98\xe7\x24\x7c\x07\xf0\xfe\x41" - "\x1c\x26\x7e\x43\x84\xb0\xf6\x00" - "\x2f\xf5\x8d\x80\x03\x39\x27\xab" - "\x8e\xf4\xd4\x58\x75\x14\xf0\xfb"; - --static const u8 __initconst ptext6[64] = -+static const u8 __initconst ptext6[64] __nonstring = - "\xd9\x31\x32\x25\xf8\x84\x06\xe5" - "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" - "\x86\xa7\xa9\x53\x15\x34\xf7\xda" -@@ -281,7 +281,7 @@ static const u8 __initconst ptext6[64] = - "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" - "\xba\x63\x7b\x39\x1a\xaf\xd2\x55"; - --static const u8 __initconst ctext6[80] = -+static const u8 __initconst ctext6[80] __nonstring = - "\x39\x80\xca\x0b\x3c\x00\xe8\x41" - "\xeb\x06\xfa\xc4\x87\x2a\x27\x57" - "\x85\x9e\x1c\xea\xa6\xef\xd9\x84" -@@ -293,17 +293,17 @@ static const u8 __initconst ctext6[80] = - "\x99\x24\xa7\xc8\x58\x73\x36\xbf" - "\xb1\x18\x02\x4d\xb8\x67\x4a\x14"; - --static const u8 __initconst ctext7[16] = -+static const u8 __initconst ctext7[16] __nonstring = - "\x53\x0f\x8a\xfb\xc7\x45\x36\xb9" - "\xa9\x63\xb4\xf1\xc4\xcb\x73\x8b"; - --static const u8 __initconst ctext8[32] = -+static const u8 __initconst ctext8[32] __nonstring = - "\xce\xa7\x40\x3d\x4d\x60\x6b\x6e" - "\x07\x4e\xc5\xd3\xba\xf3\x9d\x18" - "\xd0\xd1\xc8\xa7\x99\x99\x6b\xf0" - "\x26\x5b\x98\xb5\xd4\x8a\xb9\x19"; - --static const u8 __initconst ptext9[64] = -+static const u8 __initconst ptext9[64] __nonstring = - "\xd9\x31\x32\x25\xf8\x84\x06\xe5" - "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" - "\x86\xa7\xa9\x53\x15\x34\xf7\xda" -@@ -313,7 +313,7 @@ static const u8 __initconst ptext9[64] = - "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" - "\xba\x63\x7b\x39\x1a\xaf\xd2\x55"; - --static const u8 __initconst ctext9[80] = -+static const u8 __initconst ctext9[80] __nonstring = - "\x52\x2d\xc1\xf0\x99\x56\x7d\x07" - "\xf4\x7f\x37\xa3\x2a\x84\x42\x7d" - "\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9" -@@ -325,7 +325,7 @@ static const u8 __initconst ctext9[80] = - "\xb0\x94\xda\xc5\xd9\x34\x71\xbd" - "\xec\x1a\x50\x22\x70\xe3\xcc\x6c"; - --static const u8 __initconst ptext10[60] = -+static const u8 __initconst ptext10[60] __nonstring = - "\xd9\x31\x32\x25\xf8\x84\x06\xe5" - "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" - "\x86\xa7\xa9\x53\x15\x34\xf7\xda" -@@ -335,7 +335,7 @@ static const u8 __initconst ptext10[60] - "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" - "\xba\x63\x7b\x39"; - --static const u8 __initconst ctext10[76] = -+static const u8 __initconst ctext10[76] __nonstring = - "\x52\x2d\xc1\xf0\x99\x56\x7d\x07" - "\xf4\x7f\x37\xa3\x2a\x84\x42\x7d" - "\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9" -@@ -347,7 +347,7 @@ static const u8 __initconst ctext10[76] - "\x76\xfc\x6e\xce\x0f\x4e\x17\x68" - "\xcd\xdf\x88\x53\xbb\x2d\x55\x1b"; - --static const u8 __initconst ptext11[60] = -+static const u8 __initconst ptext11[60] __nonstring = - "\xd9\x31\x32\x25\xf8\x84\x06\xe5" - "\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" - "\x86\xa7\xa9\x53\x15\x34\xf7\xda" -@@ -357,7 +357,7 @@ static const u8 __initconst ptext11[60] - "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57" - "\xba\x63\x7b\x39"; - --static const u8 __initconst ctext11[76] = -+static const u8 __initconst ctext11[76] __nonstring = - "\x39\x80\xca\x0b\x3c\x00\xe8\x41" - "\xeb\x06\xfa\xc4\x87\x2a\x27\x57" - "\x85\x9e\x1c\xea\xa6\xef\xd9\x84" -@@ -369,7 +369,7 @@ static const u8 __initconst ctext11[76] - "\x25\x19\x49\x8e\x80\xf1\x47\x8f" - "\x37\xba\x55\xbd\x6d\x27\x61\x8c"; - --static const u8 __initconst ptext12[719] = -+static const u8 __initconst ptext12[719] __nonstring = - "\x42\xc1\xcc\x08\x48\x6f\x41\x3f" - "\x2f\x11\x66\x8b\x2a\x16\xf0\xe0" - "\x58\x83\xf0\xc3\x70\x14\xc0\x5b" -@@ -461,7 +461,7 @@ static const u8 __initconst ptext12[719] - "\x59\xfa\xfa\xaa\x44\x04\x01\xa7" - "\xa4\x78\xdb\x74\x3d\x8b\xb5"; - --static const u8 __initconst ctext12[735] = -+static const u8 __initconst ctext12[735] __nonstring = - "\x84\x0b\xdb\xd5\xb7\xa8\xfe\x20" - "\xbb\xb1\x12\x7f\x41\xea\xb3\xc0" - "\xa2\xb4\x37\x19\x11\x58\xb6\x0b" -@@ -559,9 +559,9 @@ static struct { - const u8 *ptext; - const u8 *ctext; - -- u8 key[AES_MAX_KEY_SIZE]; -- u8 iv[GCM_AES_IV_SIZE]; -- u8 assoc[20]; -+ u8 key[AES_MAX_KEY_SIZE] __nonstring; -+ u8 iv[GCM_AES_IV_SIZE] __nonstring; -+ u8 assoc[20] __nonstring; - - int klen; - int clen; -diff -purNx .git BPI-Router-Linux-kernel/lib/crypto/Makefile BPI-Router-Linux-kernel-6.16.12/lib/crypto/Makefile ---- BPI-Router-Linux-kernel/lib/crypto/Makefile 2025-10-22 13:53:23.607327249 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/lib/crypto/Makefile 2025-10-22 13:53:56.787167830 -0400 -@@ -35,6 +35,10 @@ obj-$(CONFIG_CRYPTO_LIB_CURVE25519_GENER - libcurve25519-generic-y := curve25519-fiat32.o - libcurve25519-generic-$(CONFIG_ARCH_SUPPORTS_INT128) := curve25519-hacl64.o - libcurve25519-generic-y += curve25519-generic.o -+# clang versions prior to 18 may blow out the stack with KASAN -+ifeq ($(call clang-min-version, 180000),) -+KASAN_SANITIZE_curve25519-hacl64.o := n -+endif - - obj-$(CONFIG_CRYPTO_LIB_CURVE25519) += libcurve25519.o - libcurve25519-y += curve25519.o -@@ -62,7 +66,7 @@ libsha256-generic-y := sha256-generic - - obj-$(CONFIG_MPILIB) += mpi/ - --obj-$(CONFIG_CRYPTO_SELFTESTS) += simd.o -+obj-$(CONFIG_CRYPTO_SELFTESTS_FULL) += simd.o - - obj-$(CONFIG_CRYPTO_LIB_SM3) += libsm3.o - libsm3-y := sm3.o -diff -purNx .git BPI-Router-Linux-kernel/lib/group_cpus.c BPI-Router-Linux-kernel-6.16.12/lib/group_cpus.c ---- BPI-Router-Linux-kernel/lib/group_cpus.c 2025-10-22 13:53:23.607327249 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/lib/group_cpus.c 2025-10-22 13:53:56.787167830 -0400 -@@ -352,6 +352,9 @@ struct cpumask *group_cpus_evenly(unsign - int ret = -ENOMEM; - struct cpumask *masks = NULL; - -+ if (numgrps == 0) -+ return NULL; -+ - if (!zalloc_cpumask_var(&nmsk, GFP_KERNEL)) - return NULL; - -@@ -426,8 +429,12 @@ struct cpumask *group_cpus_evenly(unsign - #else /* CONFIG_SMP */ - struct cpumask *group_cpus_evenly(unsigned int numgrps) - { -- struct cpumask *masks = kcalloc(numgrps, sizeof(*masks), GFP_KERNEL); -+ struct cpumask *masks; - -+ if (numgrps == 0) -+ return NULL; -+ -+ masks = kcalloc(numgrps, sizeof(*masks), GFP_KERNEL); - if (!masks) - return NULL; - -diff -purNx .git BPI-Router-Linux-kernel/lib/Kconfig BPI-Router-Linux-kernel-6.16.12/lib/Kconfig ---- BPI-Router-Linux-kernel/lib/Kconfig 2025-10-22 13:53:23.607327249 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/lib/Kconfig 2025-10-22 13:53:56.787167830 -0400 -@@ -716,6 +716,7 @@ config GENERIC_LIB_DEVMEM_IS_ALLOWED - - config PLDMFW - bool -+ select CRC32 - default n - - config ASN1_ENCODER -diff -purNx .git BPI-Router-Linux-kernel/lib/maple_tree.c BPI-Router-Linux-kernel-6.16.12/lib/maple_tree.c ---- BPI-Router-Linux-kernel/lib/maple_tree.c 2025-10-22 13:53:23.607327249 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/lib/maple_tree.c 2025-10-22 13:53:56.787167830 -0400 -@@ -5319,6 +5319,7 @@ static void mt_destroy_walk(struct maple - struct maple_enode *start; - - if (mte_is_leaf(enode)) { -+ mte_set_node_dead(enode); - node->type = mte_node_type(enode); - goto free_leaf; - } -@@ -5527,8 +5528,9 @@ int mas_preallocate(struct ma_state *mas - mas->store_type = mas_wr_store_type(&wr_mas); - request = mas_prealloc_calc(&wr_mas, entry); - if (!request) -- return ret; -+ goto set_flag; - -+ mas->mas_flags &= ~MA_STATE_PREALLOC; - mas_node_count_gfp(mas, request, gfp); - if (mas_is_err(mas)) { - mas_set_alloc_req(mas, 0); -@@ -5538,6 +5540,7 @@ int mas_preallocate(struct ma_state *mas - return ret; - } - -+set_flag: - mas->mas_flags |= MA_STATE_PREALLOC; - return ret; - } -diff -purNx .git BPI-Router-Linux-kernel/lib/raid6/rvv.c BPI-Router-Linux-kernel-6.16.12/lib/raid6/rvv.c ---- BPI-Router-Linux-kernel/lib/raid6/rvv.c 2025-10-22 13:53:23.607327249 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/lib/raid6/rvv.c 2025-10-22 13:53:56.787167830 -0400 -@@ -26,9 +26,9 @@ static int rvv_has_vector(void) - static void raid6_rvv1_gen_syndrome_real(int disks, unsigned long bytes, void **ptrs) - { - u8 **dptr = (u8 **)ptrs; -- unsigned long d; -- int z, z0; - u8 *p, *q; -+ unsigned long vl, d; -+ int z, z0; - - z0 = disks - 3; /* Highest data disk */ - p = dptr[z0 + 1]; /* XOR parity */ -@@ -36,8 +36,9 @@ static void raid6_rvv1_gen_syndrome_real - - asm volatile (".option push\n" - ".option arch,+v\n" -- "vsetvli t0, x0, e8, m1, ta, ma\n" -+ "vsetvli %0, x0, e8, m1, ta, ma\n" - ".option pop\n" -+ : "=&r" (vl) - ); - - /* v0:wp0, v1:wq0, v2:wd0/w20, v3:w10 */ -@@ -99,7 +100,7 @@ static void raid6_rvv1_xor_syndrome_real - { - u8 **dptr = (u8 **)ptrs; - u8 *p, *q; -- unsigned long d; -+ unsigned long vl, d; - int z, z0; - - z0 = stop; /* P/Q right side optimization */ -@@ -108,8 +109,9 @@ static void raid6_rvv1_xor_syndrome_real - - asm volatile (".option push\n" - ".option arch,+v\n" -- "vsetvli t0, x0, e8, m1, ta, ma\n" -+ "vsetvli %0, x0, e8, m1, ta, ma\n" - ".option pop\n" -+ : "=&r" (vl) - ); - - /* v0:wp0, v1:wq0, v2:wd0/w20, v3:w10 */ -@@ -195,9 +197,9 @@ static void raid6_rvv1_xor_syndrome_real - static void raid6_rvv2_gen_syndrome_real(int disks, unsigned long bytes, void **ptrs) - { - u8 **dptr = (u8 **)ptrs; -- unsigned long d; -- int z, z0; - u8 *p, *q; -+ unsigned long vl, d; -+ int z, z0; - - z0 = disks - 3; /* Highest data disk */ - p = dptr[z0 + 1]; /* XOR parity */ -@@ -205,8 +207,9 @@ static void raid6_rvv2_gen_syndrome_real - - asm volatile (".option push\n" - ".option arch,+v\n" -- "vsetvli t0, x0, e8, m1, ta, ma\n" -+ "vsetvli %0, x0, e8, m1, ta, ma\n" - ".option pop\n" -+ : "=&r" (vl) - ); - - /* -@@ -287,7 +290,7 @@ static void raid6_rvv2_xor_syndrome_real - { - u8 **dptr = (u8 **)ptrs; - u8 *p, *q; -- unsigned long d; -+ unsigned long vl, d; - int z, z0; - - z0 = stop; /* P/Q right side optimization */ -@@ -296,8 +299,9 @@ static void raid6_rvv2_xor_syndrome_real - - asm volatile (".option push\n" - ".option arch,+v\n" -- "vsetvli t0, x0, e8, m1, ta, ma\n" -+ "vsetvli %0, x0, e8, m1, ta, ma\n" - ".option pop\n" -+ : "=&r" (vl) - ); - - /* -@@ -413,9 +417,9 @@ static void raid6_rvv2_xor_syndrome_real - static void raid6_rvv4_gen_syndrome_real(int disks, unsigned long bytes, void **ptrs) - { - u8 **dptr = (u8 **)ptrs; -- unsigned long d; -- int z, z0; - u8 *p, *q; -+ unsigned long vl, d; -+ int z, z0; - - z0 = disks - 3; /* Highest data disk */ - p = dptr[z0 + 1]; /* XOR parity */ -@@ -423,8 +427,9 @@ static void raid6_rvv4_gen_syndrome_real - - asm volatile (".option push\n" - ".option arch,+v\n" -- "vsetvli t0, x0, e8, m1, ta, ma\n" -+ "vsetvli %0, x0, e8, m1, ta, ma\n" - ".option pop\n" -+ : "=&r" (vl) - ); - - /* -@@ -539,7 +544,7 @@ static void raid6_rvv4_xor_syndrome_real - { - u8 **dptr = (u8 **)ptrs; - u8 *p, *q; -- unsigned long d; -+ unsigned long vl, d; - int z, z0; - - z0 = stop; /* P/Q right side optimization */ -@@ -548,8 +553,9 @@ static void raid6_rvv4_xor_syndrome_real - - asm volatile (".option push\n" - ".option arch,+v\n" -- "vsetvli t0, x0, e8, m1, ta, ma\n" -+ "vsetvli %0, x0, e8, m1, ta, ma\n" - ".option pop\n" -+ : "=&r" (vl) - ); - - /* -@@ -721,9 +727,9 @@ static void raid6_rvv4_xor_syndrome_real - static void raid6_rvv8_gen_syndrome_real(int disks, unsigned long bytes, void **ptrs) - { - u8 **dptr = (u8 **)ptrs; -- unsigned long d; -- int z, z0; - u8 *p, *q; -+ unsigned long vl, d; -+ int z, z0; - - z0 = disks - 3; /* Highest data disk */ - p = dptr[z0 + 1]; /* XOR parity */ -@@ -731,8 +737,9 @@ static void raid6_rvv8_gen_syndrome_real - - asm volatile (".option push\n" - ".option arch,+v\n" -- "vsetvli t0, x0, e8, m1, ta, ma\n" -+ "vsetvli %0, x0, e8, m1, ta, ma\n" - ".option pop\n" -+ : "=&r" (vl) - ); - - /* -@@ -915,7 +922,7 @@ static void raid6_rvv8_xor_syndrome_real - { - u8 **dptr = (u8 **)ptrs; - u8 *p, *q; -- unsigned long d; -+ unsigned long vl, d; - int z, z0; - - z0 = stop; /* P/Q right side optimization */ -@@ -924,8 +931,9 @@ static void raid6_rvv8_xor_syndrome_real - - asm volatile (".option push\n" - ".option arch,+v\n" -- "vsetvli t0, x0, e8, m1, ta, ma\n" -+ "vsetvli %0, x0, e8, m1, ta, ma\n" - ".option pop\n" -+ : "=&r" (vl) - ); - - /* -diff -purNx .git BPI-Router-Linux-kernel/lib/sbitmap.c BPI-Router-Linux-kernel-6.16.12/lib/sbitmap.c ---- BPI-Router-Linux-kernel/lib/sbitmap.c 2025-10-22 13:53:23.607327249 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/lib/sbitmap.c 2025-10-22 13:53:56.791167810 -0400 -@@ -208,8 +208,28 @@ static int sbitmap_find_bit_in_word(stru - return nr; - } - -+static unsigned int __map_depth_with_shallow(const struct sbitmap *sb, -+ int index, -+ unsigned int shallow_depth) -+{ -+ u64 shallow_word_depth; -+ unsigned int word_depth, reminder; -+ -+ word_depth = __map_depth(sb, index); -+ if (shallow_depth >= sb->depth) -+ return word_depth; -+ -+ shallow_word_depth = word_depth * shallow_depth; -+ reminder = do_div(shallow_word_depth, sb->depth); -+ -+ if (reminder >= (index + 1) * word_depth) -+ shallow_word_depth++; -+ -+ return (unsigned int)shallow_word_depth; -+} -+ - static int sbitmap_find_bit(struct sbitmap *sb, -- unsigned int depth, -+ unsigned int shallow_depth, - unsigned int index, - unsigned int alloc_hint, - bool wrap) -@@ -218,12 +238,12 @@ static int sbitmap_find_bit(struct sbitm - int nr = -1; - - for (i = 0; i < sb->map_nr; i++) { -- nr = sbitmap_find_bit_in_word(&sb->map[index], -- min_t(unsigned int, -- __map_depth(sb, index), -- depth), -- alloc_hint, wrap); -+ unsigned int depth = __map_depth_with_shallow(sb, index, -+ shallow_depth); - -+ if (depth) -+ nr = sbitmap_find_bit_in_word(&sb->map[index], depth, -+ alloc_hint, wrap); - if (nr != -1) { - nr += index << sb->shift; - break; -@@ -406,27 +426,9 @@ EXPORT_SYMBOL_GPL(sbitmap_bitmap_show); - static unsigned int sbq_calc_wake_batch(struct sbitmap_queue *sbq, - unsigned int depth) - { -- unsigned int wake_batch; -- unsigned int shallow_depth; -- -- /* -- * Each full word of the bitmap has bits_per_word bits, and there might -- * be a partial word. There are depth / bits_per_word full words and -- * depth % bits_per_word bits left over. In bitwise arithmetic: -- * -- * bits_per_word = 1 << shift -- * depth / bits_per_word = depth >> shift -- * depth % bits_per_word = depth & ((1 << shift) - 1) -- * -- * Each word can be limited to sbq->min_shallow_depth bits. -- */ -- shallow_depth = min(1U << sbq->sb.shift, sbq->min_shallow_depth); -- depth = ((depth >> sbq->sb.shift) * shallow_depth + -- min(depth & ((1U << sbq->sb.shift) - 1), shallow_depth)); -- wake_batch = clamp_t(unsigned int, depth / SBQ_WAIT_QUEUES, 1, -- SBQ_WAKE_BATCH); -- -- return wake_batch; -+ return clamp_t(unsigned int, -+ min(depth, sbq->min_shallow_depth) / SBQ_WAIT_QUEUES, -+ 1, SBQ_WAKE_BATCH); - } - - int sbitmap_queue_init_node(struct sbitmap_queue *sbq, unsigned int depth, -diff -purNx .git BPI-Router-Linux-kernel/lib/scatterlist.c BPI-Router-Linux-kernel-6.16.12/lib/scatterlist.c ---- BPI-Router-Linux-kernel/lib/scatterlist.c 2025-10-22 13:53:23.607327249 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/lib/scatterlist.c 2025-10-22 13:53:56.791167810 -0400 -@@ -73,9 +73,9 @@ EXPORT_SYMBOL(sg_nents_for_len); - * Should only be used casually, it (currently) scans the entire list - * to get the last entry. - * -- * Note that the @sgl@ pointer passed in need not be the first one, -- * the important bit is that @nents@ denotes the number of entries that -- * exist from @sgl@. -+ * Note that the @sgl pointer passed in need not be the first one, -+ * the important bit is that @nents denotes the number of entries that -+ * exist from @sgl. - * - **/ - struct scatterlist *sg_last(struct scatterlist *sgl, unsigned int nents) -@@ -345,7 +345,7 @@ EXPORT_SYMBOL(__sg_alloc_table); - * @gfp_mask: GFP allocation mask - * - * Description: -- * Allocate and initialize an sg table. If @nents@ is larger than -+ * Allocate and initialize an sg table. If @nents is larger than - * SG_MAX_SINGLE_ALLOC a chained sg table will be setup. - * - **/ -diff -purNx .git BPI-Router-Linux-kernel/lib/test_objagg.c BPI-Router-Linux-kernel-6.16.12/lib/test_objagg.c ---- BPI-Router-Linux-kernel/lib/test_objagg.c 2025-10-22 13:53:23.607327249 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/lib/test_objagg.c 2025-10-22 13:53:56.791167810 -0400 -@@ -899,8 +899,10 @@ static int check_expect_hints_stats(stru - int err; - - stats = objagg_hints_stats_get(objagg_hints); -- if (IS_ERR(stats)) -+ if (IS_ERR(stats)) { -+ *errmsg = "objagg_hints_stats_get() failed."; - return PTR_ERR(stats); -+ } - err = __check_expect_stats(stats, expect_stats, errmsg); - objagg_stats_put(stats); - return err; -diff -purNx .git BPI-Router-Linux-kernel/lib/tests/fortify_kunit.c BPI-Router-Linux-kernel-6.16.12/lib/tests/fortify_kunit.c ---- BPI-Router-Linux-kernel/lib/tests/fortify_kunit.c 2025-10-22 13:53:23.607327249 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/lib/tests/fortify_kunit.c 2025-10-22 13:53:56.791167810 -0400 -@@ -1003,8 +1003,8 @@ static void fortify_test_memcmp(struct k - { - char one[] = "My mind is going ..."; - char two[] = "My mind is going ... I can feel it."; -- size_t one_len = sizeof(one) - 1; -- size_t two_len = sizeof(two) - 1; -+ volatile size_t one_len = sizeof(one) - 1; -+ volatile size_t two_len = sizeof(two) - 1; - - OPTIMIZER_HIDE_VAR(one_len); - OPTIMIZER_HIDE_VAR(two_len); -diff -purNx .git BPI-Router-Linux-kernel/.mailmap BPI-Router-Linux-kernel-6.16.12/.mailmap ---- BPI-Router-Linux-kernel/.mailmap 2025-10-22 13:53:23.031330005 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/.mailmap 2025-10-22 13:53:56.267170337 -0400 -@@ -197,6 +197,7 @@ Daniel Borkmann < - Daniel Borkmann - Daniel Borkmann - Daniel Borkmann -+Danilo Krummrich - David Brownell - David Collins - David Heidelberg -@@ -222,6 +223,8 @@ Dmitry Safonov <0x7f454c46@gmail.com> - Domen Puncer - Douglas Gilbert -+Drew Fustini -+ - Ed L. Cashin - Elliot Berman - Enric Balletbo i Serra -@@ -282,6 +285,7 @@ Gustavo Padovan - Hamza Mahfooz - Hanjun Guo -+Hans de Goede - Hans Verkuil - Hans Verkuil - Harry Yoo <42.hyeyoo@gmail.com> -@@ -412,6 +416,7 @@ Kenneth W Chen - Kiran Gunda - Kirill Tkhai -+Kirill A. Shutemov - Kishon Vijay Abraham I - Konrad Dybcio - Konrad Dybcio -@@ -426,6 +431,9 @@ Krzysztof WilczyÅ„ski - Kshitiz Godara - Kuninori Morimoto -+Kuniyuki Iwashima -+Kuniyuki Iwashima -+Kuniyuki Iwashima - Kuogee Hsieh - Lee Jones - Lee Jones -@@ -686,11 +694,16 @@ Sedat Dilek - Serge Hallyn - Serge Hallyn -+Sergey Senozhatsky -+Sergey Senozhatsky -+Sergey Senozhatsky -+Sergey Senozhatsky - Seth Forshee - Shakeel Butt --Shannon Nelson --Shannon Nelson --Shannon Nelson -+Shannon Nelson -+Shannon Nelson -+Shannon Nelson -+Shannon Nelson - Sharath Chandra Vurukala - Shiraz Hashim - Shuah Khan -@@ -719,6 +732,7 @@ Srinivas Ramana - Sriram Yagnaraman - Stanislav Fomichev -+Stanislav Fomichev - Stefan Wahren - Stéphane Witzmann - Stephen Hemminger -@@ -823,3 +837,6 @@ Yosry Ahmed - Zack Rusin - Zhu Yanjun -+Zijun Hu -+Zijun Hu -+Zijun Hu -diff -purNx .git BPI-Router-Linux-kernel/MAINTAINERS BPI-Router-Linux-kernel-6.16.12/MAINTAINERS ---- BPI-Router-Linux-kernel/MAINTAINERS 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/MAINTAINERS 2025-10-22 13:53:56.279170279 -0400 -@@ -207,7 +207,7 @@ X: arch/*/include/uapi/ - X: include/uapi/ - - ABIT UGURU 1,2 HARDWARE MONITOR DRIVER --M: Hans de Goede -+M: Hans de Goede - L: linux-hwmon@vger.kernel.org - S: Maintained - F: drivers/hwmon/abituguru.c -@@ -371,7 +371,7 @@ S: Maintained - F: drivers/platform/x86/quickstart.c - - ACPI SERIAL MULTI INSTANTIATE DRIVER --M: Hans de Goede -+M: Hans de Goede - L: platform-driver-x86@vger.kernel.org - S: Maintained - F: drivers/platform/x86/serial-multi-instantiate.c -@@ -1157,7 +1157,6 @@ F: arch/x86/include/asm/amd/node.h - F: arch/x86/kernel/amd_node.c - - AMD PDS CORE DRIVER --M: Shannon Nelson - M: Brett Creeley - L: netdev@vger.kernel.org - S: Maintained -@@ -3551,7 +3550,7 @@ F: arch/arm64/boot/Makefile - F: scripts/make_fit.py - - ARM64 PLATFORM DRIVERS --M: Hans de Goede -+M: Hans de Goede - M: Ilpo Järvinen - R: Bryan O'Donoghue - L: platform-driver-x86@vger.kernel.org -@@ -3712,7 +3711,7 @@ F: drivers/platform/x86/asus*.c - F: drivers/platform/x86/eeepc*.c - - ASUS TF103C DOCK DRIVER --M: Hans de Goede -+M: Hans de Goede - L: platform-driver-x86@vger.kernel.org - S: Maintained - T: git git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git -@@ -4182,6 +4181,7 @@ F: include/linux/cpumask_types.h - F: include/linux/find.h - F: include/linux/nodemask.h - F: include/linux/nodemask_types.h -+F: include/uapi/linux/bits.h - F: include/vdso/bits.h - F: lib/bitmap-str.c - F: lib/bitmap.c -@@ -4194,6 +4194,7 @@ F: tools/include/linux/bitfield.h - F: tools/include/linux/bitmap.h - F: tools/include/linux/bits.h - F: tools/include/linux/find.h -+F: tools/include/uapi/linux/bits.h - F: tools/include/vdso/bits.h - F: tools/lib/bitmap.c - F: tools/lib/find_bit.c -@@ -4555,6 +4556,7 @@ BPF [NETWORKING] (tcx & tc BPF, sock_add - M: Martin KaFai Lau - M: Daniel Borkmann - R: John Fastabend -+R: Stanislav Fomichev - L: bpf@vger.kernel.org - L: netdev@vger.kernel.org - S: Maintained -@@ -5568,6 +5570,7 @@ T: git git://git.kernel.org/pub/scm/linu - F: drivers/char/ - F: drivers/misc/ - F: include/linux/miscdevice.h -+F: rust/kernel/miscdevice.rs - F: samples/rust/rust_misc_device.rs - X: drivers/char/agp/ - X: drivers/char/hw_random/ -@@ -5613,14 +5616,14 @@ T: git git://git.kernel.org/pub/scm/linu - F: drivers/usb/chipidea/ - - CHIPONE ICN8318 I2C TOUCHSCREEN DRIVER --M: Hans de Goede -+M: Hans de Goede - L: linux-input@vger.kernel.org - S: Maintained - F: Documentation/devicetree/bindings/input/touchscreen/chipone,icn8318.yaml - F: drivers/input/touchscreen/chipone_icn8318.c - - CHIPONE ICN8505 I2C TOUCHSCREEN DRIVER --M: Hans de Goede -+M: Hans de Goede - L: linux-input@vger.kernel.org - S: Maintained - F: drivers/input/touchscreen/chipone_icn8505.c -@@ -6254,6 +6257,7 @@ F: include/linux/cpuhotplug.h - F: include/linux/smpboot.h - F: kernel/cpu.c - F: kernel/smpboot.* -+F: rust/helper/cpu.c - F: rust/kernel/cpu.rs - - CPU IDLE TIME MANAGEMENT FRAMEWORK -@@ -6917,7 +6921,7 @@ F: include/dt-bindings/pmu/exynos_ppmu.h - F: include/linux/devfreq-event.h - - DEVICE RESOURCE MANAGEMENT HELPERS --M: Hans de Goede -+M: Hans de Goede - R: Matti Vaittinen - S: Maintained - F: include/linux/devm-helpers.h -@@ -7516,7 +7520,7 @@ F: drivers/gpu/drm/gud/ - F: include/drm/gud.h - - DRM DRIVER FOR GRAIN MEDIA GM12U320 PROJECTORS --M: Hans de Goede -+M: Hans de Goede - S: Maintained - T: git https://gitlab.freedesktop.org/drm/misc/kernel.git - F: drivers/gpu/drm/tiny/gm12u320.c -@@ -7916,7 +7920,7 @@ F: drivers/gpu/drm/ci/xfails/vkms* - F: drivers/gpu/drm/vkms/ - - DRM DRIVER FOR VIRTUALBOX VIRTUAL GPU --M: Hans de Goede -+M: Hans de Goede - L: dri-devel@lists.freedesktop.org - S: Maintained - T: git https://gitlab.freedesktop.org/drm/misc/kernel.git -@@ -8317,7 +8321,7 @@ F: drivers/gpu/drm/panel/ - F: include/drm/drm_panel.h - - DRM PRIVACY-SCREEN CLASS --M: Hans de Goede -+M: Hans de Goede - L: dri-devel@lists.freedesktop.org - S: Maintained - T: git https://gitlab.freedesktop.org/drm/misc/kernel.git -@@ -9940,7 +9944,6 @@ F: drivers/fwctl/mlx5/ - - FWCTL PDS DRIVER - M: Brett Creeley --R: Shannon Nelson - L: linux-kernel@vger.kernel.org - S: Maintained - F: drivers/fwctl/pds/ -@@ -10221,7 +10224,7 @@ S: Maintained - F: Documentation/devicetree/bindings/connector/gocontroll,moduline-module-slot.yaml - - GOODIX TOUCHSCREEN --M: Hans de Goede -+M: Hans de Goede - L: linux-input@vger.kernel.org - S: Maintained - F: drivers/input/touchscreen/goodix* -@@ -10260,7 +10263,7 @@ F: include/dt-bindings/clock/google,gs10 - K: [gG]oogle.?[tT]ensor - - GPD POCKET FAN DRIVER --M: Hans de Goede -+M: Hans de Goede - L: platform-driver-x86@vger.kernel.org - S: Maintained - F: drivers/platform/x86/gpd-pocket-fan.c -@@ -10504,7 +10507,7 @@ S: Maintained - F: block/partitions/efi.* - - HABANALABS PCI DRIVER --M: Ofir Bitton -+M: Yaron Avizrat - L: dri-devel@lists.freedesktop.org - S: Supported - C: irc://irc.oftc.net/dri-devel -@@ -10839,7 +10842,7 @@ S: Maintained - F: drivers/dma/hisi_dma.c - - HISILICON GPIO DRIVER --M: Jay Fang -+M: Yang Shen - L: linux-gpio@vger.kernel.org - S: Maintained - F: Documentation/devicetree/bindings/gpio/hisilicon,ascend910-gpio.yaml -@@ -11006,7 +11009,8 @@ F: Documentation/ABI/testing/debugfs-his - F: drivers/crypto/hisilicon/zip/ - - HMM - Heterogeneous Memory Management --M: Jérôme Glisse -+M: Jason Gunthorpe -+M: Leon Romanovsky - L: linux-mm@kvack.org - S: Maintained - F: Documentation/mm/hmm.rst -@@ -11155,7 +11159,8 @@ F: include/linux/platform_data/huawei-ga - - HUGETLB SUBSYSTEM - M: Muchun Song --R: Oscar Salvador -+M: Oscar Salvador -+R: David Hildenbrand - L: linux-mm@kvack.org - S: Maintained - F: Documentation/ABI/testing/sysfs-kernel-mm-hugepages -@@ -11166,6 +11171,7 @@ F: fs/hugetlbfs/ - F: include/linux/hugetlb.h - F: include/trace/events/hugetlbfs.h - F: mm/hugetlb.c -+F: mm/hugetlb_cgroup.c - F: mm/hugetlb_cma.c - F: mm/hugetlb_cma.h - F: mm/hugetlb_vmemmap.c -@@ -11421,7 +11427,7 @@ F: drivers/i2c/busses/i2c-via.c - F: drivers/i2c/busses/i2c-viapro.c - - I2C/SMBUS INTEL CHT WHISKEY COVE PMIC DRIVER --M: Hans de Goede -+M: Hans de Goede - L: linux-i2c@vger.kernel.org - S: Maintained - F: drivers/i2c/busses/i2c-cht-wc.c -@@ -12011,13 +12017,13 @@ S: Supported - F: sound/soc/intel/ - - INTEL ATOMISP2 DUMMY / POWER-MANAGEMENT DRIVER --M: Hans de Goede -+M: Hans de Goede - L: platform-driver-x86@vger.kernel.org - S: Maintained - F: drivers/platform/x86/intel/atomisp2/pm.c - - INTEL ATOMISP2 LED DRIVER --M: Hans de Goede -+M: Hans de Goede - L: platform-driver-x86@vger.kernel.org - S: Maintained - F: drivers/platform/x86/intel/atomisp2/led.c -@@ -12183,9 +12189,8 @@ F: drivers/dma/idxd/* - F: include/uapi/linux/idxd.h - - INTEL IN FIELD SCAN (IFS) DEVICE --M: Jithu Joseph -+M: Tony Luck - R: Ashok Raj --R: Tony Luck - S: Maintained - F: drivers/platform/x86/intel/ifs - F: include/trace/events/intel_ifs.h -@@ -12525,8 +12530,7 @@ T: git git://git.kernel.org/pub/scm/linu - F: drivers/net/wireless/intel/iwlwifi/ - - INTEL WMI SLIM BOOTLOADER (SBL) FIRMWARE UPDATE DRIVER --M: Jithu Joseph --S: Maintained -+S: Orphan - W: https://slimbootloader.github.io/security/firmware-update.html - F: drivers/platform/x86/intel/wmi/sbl-fw-update.c - -@@ -13345,6 +13349,7 @@ M: Alexander Graf - M: Mike Rapoport - M: Changyuan Lyu - L: kexec@lists.infradead.org -+L: linux-mm@kvack.org - S: Maintained - F: Documentation/admin-guide/mm/kho.rst - F: Documentation/core-api/kho/* -@@ -13678,7 +13683,7 @@ S: Maintained - F: drivers/platform/x86/lenovo-wmi-hotkey-utilities.c - - LETSKETCH HID TABLET DRIVER --M: Hans de Goede -+M: Hans de Goede - L: linux-input@vger.kernel.org - S: Maintained - T: git git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git -@@ -13728,7 +13733,7 @@ F: drivers/ata/sata_gemini.c - F: drivers/ata/sata_gemini.h - - LIBATA SATA AHCI PLATFORM devices support --M: Hans de Goede -+M: Hans de Goede - L: linux-ide@vger.kernel.org - S: Maintained - F: drivers/ata/ahci_platform.c -@@ -13798,7 +13803,7 @@ M: Oliver O'Halloran - L: nvdimm@lists.linux.dev - S: Supported - Q: https://patchwork.kernel.org/project/linux-nvdimm/list/ --F: Documentation/devicetree/bindings/pmem/pmem-region.txt -+F: Documentation/devicetree/bindings/pmem/pmem-region.yaml - F: drivers/nvdimm/of_pmem.c - - LIBNVDIMM: NON-VOLATILE MEMORY DEVICE SUBSYSTEM -@@ -14098,7 +14103,7 @@ F: Documentation/admin-guide/ldm.rst - F: block/partitions/ldm.* - - LOGITECH HID GAMING KEYBOARDS --M: Hans de Goede -+M: Hans de Goede - L: linux-input@vger.kernel.org - S: Maintained - T: git git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git -@@ -14780,7 +14785,7 @@ F: Documentation/devicetree/bindings/pow - F: drivers/power/supply/max17040_battery.c - - MAXIM MAX17042 FAMILY FUEL GAUGE DRIVERS --R: Hans de Goede -+R: Hans de Goede - R: Krzysztof Kozlowski - R: Marek Szyprowski - R: Sebastian Krzyszkowiak -@@ -15549,6 +15554,7 @@ F: drivers/net/ethernet/mellanox/mlx4/en - MELLANOX ETHERNET DRIVER (mlx5e) - M: Saeed Mahameed - M: Tariq Toukan -+M: Mark Bloch - L: netdev@vger.kernel.org - S: Maintained - W: https://www.nvidia.com/networking/ -@@ -15584,7 +15590,7 @@ Q: https://patchwork.kernel.org/project/ - F: drivers/net/ethernet/mellanox/mlxfw/ - - MELLANOX HARDWARE PLATFORM SUPPORT --M: Hans de Goede -+M: Hans de Goede - M: Ilpo Järvinen - M: Vadim Pasternak - L: platform-driver-x86@vger.kernel.org -@@ -15618,6 +15624,7 @@ MELLANOX MLX5 core VPI driver - M: Saeed Mahameed - M: Leon Romanovsky - M: Tariq Toukan -+M: Mark Bloch - L: netdev@vger.kernel.org - L: linux-rdma@vger.kernel.org - S: Maintained -@@ -15675,11 +15682,16 @@ MEMBLOCK AND MEMORY MANAGEMENT INITIALIZ - M: Mike Rapoport - L: linux-mm@kvack.org - S: Maintained -+T: git git://git.kernel.org/pub/scm/linux/kernel/git/rppt/memblock.git for-next -+T: git git://git.kernel.org/pub/scm/linux/kernel/git/rppt/memblock.git fixes - F: Documentation/core-api/boot-time-mm.rst - F: Documentation/core-api/kho/bindings/memblock/* - F: include/linux/memblock.h -+F: mm/bootmem_info.c - F: mm/memblock.c -+F: mm/memtest.c - F: mm/mm_init.c -+F: mm/rodata_test.c - F: tools/testing/memblock/ - - MEMORY ALLOCATION PROFILING -@@ -15734,7 +15746,6 @@ F: Documentation/admin-guide/mm/ - F: Documentation/mm/ - F: include/linux/gfp.h - F: include/linux/gfp_types.h --F: include/linux/memfd.h - F: include/linux/memory_hotplug.h - F: include/linux/memory-tiers.h - F: include/linux/mempolicy.h -@@ -15794,6 +15805,10 @@ S: Maintained - W: http://www.linux-mm.org - T: git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm - F: mm/gup.c -+F: mm/gup_test.c -+F: mm/gup_test.h -+F: tools/testing/selftests/mm/gup_longterm.c -+F: tools/testing/selftests/mm/gup_test.c - - MEMORY MANAGEMENT - KSM (Kernel Samepage Merging) - M: Andrew Morton -@@ -15841,6 +15856,17 @@ F: mm/numa.c - F: mm/numa_emulation.c - F: mm/numa_memblks.c - -+MEMORY MANAGEMENT - OOM KILLER -+M: Michal Hocko -+R: David Rientjes -+R: Shakeel Butt -+L: linux-mm@kvack.org -+S: Maintained -+F: include/linux/oom.h -+F: include/trace/events/oom.h -+F: include/uapi/linux/oom.h -+F: mm/oom_kill.c -+ - MEMORY MANAGEMENT - PAGE ALLOCATOR - M: Andrew Morton - M: Vlastimil Babka -@@ -15855,8 +15881,17 @@ F: include/linux/compaction.h - F: include/linux/gfp.h - F: include/linux/page-isolation.h - F: mm/compaction.c -+F: mm/debug_page_alloc.c -+F: mm/fail_page_alloc.c - F: mm/page_alloc.c -+F: mm/page_ext.c -+F: mm/page_frag_cache.c - F: mm/page_isolation.c -+F: mm/page_owner.c -+F: mm/page_poison.c -+F: mm/page_reporting.c -+F: mm/show_mem.c -+F: mm/shuffle.c - - MEMORY MANAGEMENT - RECLAIM - M: Andrew Morton -@@ -15870,6 +15905,7 @@ L: linux-mm@kvack.org - S: Maintained - F: mm/pt_reclaim.c - F: mm/vmscan.c -+F: mm/workingset.c - - MEMORY MANAGEMENT - RMAP (REVERSE MAPPING) - M: Andrew Morton -@@ -15882,6 +15918,7 @@ R: Harry Yoo - L: linux-mm@kvack.org - S: Maintained - F: include/linux/rmap.h -+F: mm/page_vma_mapped.c - F: mm/rmap.c - - MEMORY MANAGEMENT - SECRETMEM -@@ -15914,13 +15951,14 @@ F: mm/swapfile.c - MEMORY MANAGEMENT - THP (TRANSPARENT HUGE PAGE) - M: Andrew Morton - M: David Hildenbrand -+M: Lorenzo Stoakes - R: Zi Yan - R: Baolin Wang --R: Lorenzo Stoakes - R: Liam R. Howlett - R: Nico Pache - R: Ryan Roberts - R: Dev Jain -+R: Barry Song - L: linux-mm@kvack.org - S: Maintained - W: http://www.linux-mm.org -@@ -15973,11 +16011,14 @@ S: Maintained - W: http://www.linux-mm.org - T: git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm - F: include/trace/events/mmap.h -+F: mm/mincore.c - F: mm/mlock.c - F: mm/mmap.c - F: mm/mprotect.c - F: mm/mremap.c - F: mm/mseal.c -+F: mm/msync.c -+F: mm/nommu.c - F: mm/vma.c - F: mm/vma.h - F: mm/vma_exec.c -@@ -16540,7 +16581,7 @@ S: Maintained - F: drivers/platform/surface/surface_gpe.c - - MICROSOFT SURFACE HARDWARE PLATFORM SUPPORT --M: Hans de Goede -+M: Hans de Goede - M: Ilpo Järvinen - M: Maximilian Luz - L: platform-driver-x86@vger.kernel.org -@@ -16785,8 +16826,8 @@ F: include/dt-bindings/clock/mobileye,ey - MODULE SUPPORT - M: Luis Chamberlain - M: Petr Pavlu -+M: Daniel Gomez - R: Sami Tolvanen --R: Daniel Gomez - L: linux-modules@vger.kernel.org - L: linux-kernel@vger.kernel.org - S: Maintained -@@ -17185,10 +17226,10 @@ F: drivers/rtc/rtc-ntxec.c - F: include/linux/mfd/ntxec.h - - NETRONOME ETHERNET DRIVERS --M: Louis Peens - R: Jakub Kicinski -+R: Simon Horman - L: oss-drivers@corigine.com --S: Maintained -+S: Odd Fixes - F: drivers/net/ethernet/netronome/ - - NETWORK BLOCK DEVICE (NBD) -@@ -17345,6 +17386,7 @@ F: include/linux/ethtool.h - F: include/linux/framer/framer-provider.h - F: include/linux/framer/framer.h - F: include/linux/in.h -+F: include/linux/in6.h - F: include/linux/indirect_call_wrapper.h - F: include/linux/inet.h - F: include/linux/inet_diag.h -@@ -17495,7 +17537,7 @@ F: tools/testing/selftests/net/srv6* - NETWORKING [TCP] - M: Eric Dumazet - M: Neal Cardwell --R: Kuniyuki Iwashima -+R: Kuniyuki Iwashima - L: netdev@vger.kernel.org - S: Maintained - F: Documentation/networking/net_cachelines/tcp_sock.rst -@@ -17525,7 +17567,7 @@ F: net/tls/* - - NETWORKING [SOCKETS] - M: Eric Dumazet --M: Kuniyuki Iwashima -+M: Kuniyuki Iwashima - M: Paolo Abeni - M: Willem de Bruijn - S: Maintained -@@ -17540,7 +17582,7 @@ F: net/core/scm.c - F: net/socket.c - - NETWORKING [UNIX SOCKETS] --M: Kuniyuki Iwashima -+M: Kuniyuki Iwashima - S: Maintained - F: include/net/af_unix.h - F: include/net/netns/unix.h -@@ -17708,7 +17750,7 @@ F: tools/include/nolibc/ - F: tools/testing/selftests/nolibc/ - - NOVATEK NVT-TS I2C TOUCHSCREEN DRIVER --M: Hans de Goede -+M: Hans de Goede - L: linux-input@vger.kernel.org - S: Maintained - F: Documentation/devicetree/bindings/input/touchscreen/novatek,nvt-ts.yaml -@@ -19378,7 +19420,7 @@ F: crypto/pcrypt.c - F: include/crypto/pcrypt.h - - PDS DSC VIRTIO DATA PATH ACCELERATOR --R: Shannon Nelson -+R: Brett Creeley - F: drivers/vdpa/pds/ - - PECI HARDWARE MONITORING DRIVERS -@@ -19400,7 +19442,6 @@ F: include/linux/peci-cpu.h - F: include/linux/peci.h - - PENSANDO ETHERNET DRIVERS --M: Shannon Nelson - M: Brett Creeley - L: netdev@vger.kernel.org - S: Maintained -@@ -19565,8 +19606,7 @@ T: git git://git.kernel.org/pub/scm/linu - F: drivers/pinctrl/intel/ - - PIN CONTROLLER - KEEMBAY --M: Lakshmi Sowjanya D --S: Supported -+S: Orphan - F: drivers/pinctrl/pinctrl-keembay* - - PIN CONTROLLER - MEDIATEK -@@ -20119,21 +20159,15 @@ S: Supported - F: Documentation/devicetree/bindings/soc/qcom/qcom,apr* - F: Documentation/devicetree/bindings/sound/qcom,* - F: drivers/soc/qcom/apr.c --F: include/dt-bindings/sound/qcom,wcd9335.h --F: include/dt-bindings/sound/qcom,wcd934x.h --F: sound/soc/codecs/lpass-rx-macro.* --F: sound/soc/codecs/lpass-tx-macro.* --F: sound/soc/codecs/lpass-va-macro.c --F: sound/soc/codecs/lpass-wsa-macro.* -+F: drivers/soundwire/qcom.c -+F: include/dt-bindings/sound/qcom,wcd93* -+F: sound/soc/codecs/lpass-*.* - F: sound/soc/codecs/msm8916-wcd-analog.c - F: sound/soc/codecs/msm8916-wcd-digital.c - F: sound/soc/codecs/wcd-clsh-v2.* - F: sound/soc/codecs/wcd-mbhc-v2.* --F: sound/soc/codecs/wcd9335.* --F: sound/soc/codecs/wcd934x.c --F: sound/soc/codecs/wsa881x.c --F: sound/soc/codecs/wsa883x.c --F: sound/soc/codecs/wsa884x.c -+F: sound/soc/codecs/wcd93*.* -+F: sound/soc/codecs/wsa88*.* - F: sound/soc/qcom/ - - QCOM EMBEDDED USB DEBUGGER (EUD) -@@ -21164,7 +21198,7 @@ M: Lad Prabhakar -+M: Drew Fustini - M: Guo Ren - M: Fu Wei - L: linux-riscv@lists.infradead.org -@@ -22173,7 +22207,7 @@ R: Tejun Heo - R: David Vernet - R: Andrea Righi - R: Changwoo Min --L: linux-kernel@vger.kernel.org -+L: sched-ext@lists.linux.dev - S: Maintained - W: https://github.com/sched-ext/scx - T: git://git.kernel.org/pub/scm/linux/kernel/git/tj/sched_ext.git -@@ -22552,9 +22586,11 @@ S: Maintained - F: drivers/misc/sgi-xp/ - - SHARED MEMORY COMMUNICATIONS (SMC) SOCKETS -+M: D. Wythe -+M: Dust Li -+M: Sidraya Jayagond - M: Wenjia Zhang --M: Jan Karcher --R: D. Wythe -+R: Mahanta Jambigi - R: Tony Lu - R: Wen Gu - L: linux-rdma@vger.kernel.org -@@ -22710,7 +22746,7 @@ K: fu[57]40 - K: [^@]sifive - - SILEAD TOUCHSCREEN DRIVER --M: Hans de Goede -+M: Hans de Goede - L: linux-input@vger.kernel.org - L: platform-driver-x86@vger.kernel.org - S: Maintained -@@ -22743,7 +22779,7 @@ F: Documentation/devicetree/bindings/i3c - F: drivers/i3c/master/svc-i3c-master.c - - SIMPLEFB FB DRIVER --M: Hans de Goede -+M: Hans de Goede - L: linux-fbdev@vger.kernel.org - S: Maintained - F: Documentation/devicetree/bindings/display/simple-framebuffer.yaml -@@ -22872,7 +22908,7 @@ F: Documentation/hwmon/emc2103.rst - F: drivers/hwmon/emc2103.c - - SMSC SCH5627 HARDWARE MONITOR DRIVER --M: Hans de Goede -+M: Hans de Goede - L: linux-hwmon@vger.kernel.org - S: Supported - F: Documentation/hwmon/sch5627.rst -@@ -23527,7 +23563,7 @@ S: Supported - F: Documentation/process/stable-kernel-rules.rst - - STAGING - ATOMISP DRIVER --M: Hans de Goede -+M: Hans de Goede - M: Mauro Carvalho Chehab - R: Sakari Ailus - L: linux-media@vger.kernel.org -@@ -23663,7 +23699,6 @@ F: include/dt-bindings/clock/starfive?jh - - STARFIVE JH71X0 PINCTRL DRIVERS - M: Emil Renner Berthing --M: Jianlong Huang - M: Hal Feng - L: linux-gpio@vger.kernel.org - S: Maintained -@@ -23824,7 +23859,7 @@ F: arch/m68k/sun3*/ - F: drivers/net/ethernet/i825xx/sun3* - - SUN4I LOW RES ADC ATTACHED TABLET KEYS DRIVER --M: Hans de Goede -+M: Hans de Goede - L: linux-input@vger.kernel.org - S: Maintained - F: Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml -@@ -24066,6 +24101,7 @@ M: Bin Du - L: linux-i2c@vger.kernel.org - S: Maintained - F: drivers/i2c/busses/i2c-designware-amdisp.c -+F: include/linux/soc/amd/isp4_misc.h - - SYNOPSYS DESIGNWARE MMC/SD/SDIO DRIVER - M: Jaehoon Chung -@@ -25030,8 +25066,11 @@ M: Hugh Dickins - R: Baolin Wang - L: linux-mm@kvack.org - S: Maintained -+F: include/linux/memfd.h - F: include/linux/shmem_fs.h -+F: mm/memfd.c - F: mm/shmem.c -+F: mm/shmem_quota.c - - TOMOYO SECURITY MODULE - M: Kentaro Takeda -@@ -25592,7 +25631,7 @@ F: Documentation/hid/hiddev.rst - F: drivers/hid/usbhid/ - - USB INTEL XHCI ROLE MUX DRIVER --M: Hans de Goede -+M: Hans de Goede - L: linux-usb@vger.kernel.org - S: Maintained - F: drivers/usb/roles/intel-xhci-usb-role-switch.c -@@ -25783,7 +25822,7 @@ F: Documentation/firmware-guide/acpi/int - F: drivers/usb/typec/mux/intel_pmc_mux.c - - USB TYPEC PI3USB30532 MUX DRIVER --M: Hans de Goede -+M: Hans de Goede - L: linux-usb@vger.kernel.org - S: Maintained - F: drivers/usb/typec/mux/pi3usb30532.c -@@ -25812,7 +25851,7 @@ F: drivers/usb/host/uhci* - - USB VIDEO CLASS - M: Laurent Pinchart --M: Hans de Goede -+M: Hans de Goede - L: linux-media@vger.kernel.org - S: Maintained - W: http://www.ideasonboard.org/uvc/ -@@ -25866,6 +25905,8 @@ F: fs/hostfs/ - - USERSPACE COPYIN/COPYOUT (UIOVEC) - M: Alexander Viro -+L: linux-block@vger.kernel.org -+L: linux-fsdevel@vger.kernel.org - S: Maintained - F: include/linux/uio.h - F: lib/iov_iter.c -@@ -26343,7 +26384,7 @@ F: include/uapi/linux/virtio_snd.h - F: sound/virtio/* - - VIRTUAL BOX GUEST DEVICE DRIVER --M: Hans de Goede -+M: Hans de Goede - M: Arnd Bergmann - M: Greg Kroah-Hartman - S: Maintained -@@ -26352,7 +26393,7 @@ F: include/linux/vbox_utils.h - F: include/uapi/linux/vbox*.h - - VIRTUAL BOX SHARED FOLDER VFS DRIVER --M: Hans de Goede -+M: Hans de Goede - L: linux-fsdevel@vger.kernel.org - S: Maintained - F: fs/vboxsf/* -@@ -26606,7 +26647,7 @@ F: drivers/mmc/host/wbsd.* - - WACOM PROTOCOL 4 SERIAL TABLETS - M: Julian Squires --M: Hans de Goede -+M: Hans de Goede - L: linux-input@vger.kernel.org - S: Maintained - F: drivers/input/tablet/wacom_serial4.c -@@ -26773,7 +26814,7 @@ F: include/linux/wwan.h - F: include/uapi/linux/wwan.h - - X-POWERS AXP288 PMIC DRIVERS --M: Hans de Goede -+M: Hans de Goede - S: Maintained - F: drivers/acpi/pmic/intel_pmic_xpower.c - N: axp288 -@@ -26865,14 +26906,14 @@ T: git git://git.kernel.org/pub/scm/linu - F: arch/x86/mm/ - - X86 PLATFORM ANDROID TABLETS DSDT FIXUP DRIVER --M: Hans de Goede -+M: Hans de Goede - L: platform-driver-x86@vger.kernel.org - S: Maintained - T: git git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git - F: drivers/platform/x86/x86-android-tablets/ - - X86 PLATFORM DRIVERS --M: Hans de Goede -+M: Hans de Goede - M: Ilpo Järvinen - L: platform-driver-x86@vger.kernel.org - S: Maintained -@@ -26903,7 +26944,7 @@ F: arch/x86/kernel/stacktrace.c - F: arch/x86/kernel/unwind_*.c - - X86 TRUST DOMAIN EXTENSIONS (TDX) --M: Kirill A. Shutemov -+M: Kirill A. Shutemov - R: Dave Hansen - L: x86@kernel.org - L: linux-coco@lists.linux.dev -@@ -26969,6 +27010,7 @@ M: David S. Miller - M: Jakub Kicinski - M: Jesper Dangaard Brouer - M: John Fastabend -+R: Stanislav Fomichev - L: netdev@vger.kernel.org - L: bpf@vger.kernel.org - S: Supported -@@ -26990,6 +27032,7 @@ M: Björn Töpel - M: Magnus Karlsson - M: Maciej Fijalkowski - R: Jonathan Lemon -+R: Stanislav Fomichev - L: netdev@vger.kernel.org - L: bpf@vger.kernel.org - S: Maintained -@@ -27270,13 +27313,6 @@ S: Supported - W: http://www.marvell.com - F: drivers/i2c/busses/i2c-xlp9xx.c - --XRA1403 GPIO EXPANDER --M: Nandor Han --L: linux-gpio@vger.kernel.org --S: Maintained --F: Documentation/devicetree/bindings/gpio/gpio-xra1403.txt --F: drivers/gpio/gpio-xra1403.c -- - XTENSA XTFPGA PLATFORM SUPPORT - M: Max Filippov - S: Maintained -diff -purNx .git BPI-Router-Linux-kernel/Makefile BPI-Router-Linux-kernel-6.16.12/Makefile ---- BPI-Router-Linux-kernel/Makefile 2025-10-22 13:53:23.047329929 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/Makefile 2025-10-22 13:53:56.279170279 -0400 -@@ -1,8 +1,8 @@ - # SPDX-License-Identifier: GPL-2.0 - VERSION = 6 - PATCHLEVEL = 16 --SUBLEVEL = 0 --EXTRAVERSION = -rc1 -+SUBLEVEL = 12 -+EXTRAVERSION = - NAME = Baby Opossum Posse - - # *DOCUMENTATION* -@@ -1134,7 +1134,7 @@ KBUILD_USERCFLAGS += $(filter -m32 -m64 - KBUILD_USERLDFLAGS += $(filter -m32 -m64 --target=%, $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS)) - - # userspace programs are linked via the compiler, use the correct linker --ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_LD_IS_LLD),yy) -+ifdef CONFIG_CC_IS_CLANG - KBUILD_USERLDFLAGS += --ld-path=$(LD) - endif - -@@ -1832,12 +1832,9 @@ rustfmtcheck: rustfmt - # Misc - # --------------------------------------------------------------------------- - --# Run misc checks when ${KBUILD_EXTRA_WARN} contains 1 - PHONY += misc-check --ifneq ($(findstring 1,$(KBUILD_EXTRA_WARN)),) - misc-check: - $(Q)$(srctree)/scripts/misc-check --endif - - all: misc-check - -diff -purNx .git BPI-Router-Linux-kernel/mm/damon/core.c BPI-Router-Linux-kernel-6.16.12/mm/damon/core.c ---- BPI-Router-Linux-kernel/mm/damon/core.c 2025-10-22 13:53:23.607327249 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/damon/core.c 2025-10-22 13:53:56.791167810 -0400 -@@ -754,6 +754,19 @@ static struct damos_quota_goal *damos_nt - return NULL; - } - -+static void damos_commit_quota_goal_union( -+ struct damos_quota_goal *dst, struct damos_quota_goal *src) -+{ -+ switch (dst->metric) { -+ case DAMOS_QUOTA_NODE_MEM_USED_BP: -+ case DAMOS_QUOTA_NODE_MEM_FREE_BP: -+ dst->nid = src->nid; -+ break; -+ default: -+ break; -+ } -+} -+ - static void damos_commit_quota_goal( - struct damos_quota_goal *dst, struct damos_quota_goal *src) - { -@@ -762,6 +775,7 @@ static void damos_commit_quota_goal( - if (dst->metric == DAMOS_QUOTA_USER_INPUT) - dst->current_value = src->current_value; - /* keep last_psi_total as is, since it will be updated in next cycle */ -+ damos_commit_quota_goal_union(dst, src); - } - - /** -@@ -795,6 +809,7 @@ int damos_commit_quota_goals(struct damo - src_goal->metric, src_goal->target_value); - if (!new_goal) - return -ENOMEM; -+ damos_commit_quota_goal_union(new_goal, src_goal); - damos_add_quota_goal(dst, new_goal); - } - return 0; -@@ -828,6 +843,18 @@ static struct damos_filter *damos_nth_fi - return NULL; - } - -+static struct damos_filter *damos_nth_ops_filter(int n, struct damos *s) -+{ -+ struct damos_filter *filter; -+ int i = 0; -+ -+ damos_for_each_ops_filter(filter, s) { -+ if (i++ == n) -+ return filter; -+ } -+ return NULL; -+} -+ - static void damos_commit_filter_arg( - struct damos_filter *dst, struct damos_filter *src) - { -@@ -854,6 +881,7 @@ static void damos_commit_filter( - { - dst->type = src->type; - dst->matching = src->matching; -+ dst->allow = src->allow; - damos_commit_filter_arg(dst, src); - } - -@@ -891,7 +919,7 @@ static int damos_commit_ops_filters(stru - int i = 0, j = 0; - - damos_for_each_ops_filter_safe(dst_filter, next, dst) { -- src_filter = damos_nth_filter(i++, src); -+ src_filter = damos_nth_ops_filter(i++, src); - if (src_filter) - damos_commit_filter(dst_filter, src_filter); - else -@@ -978,6 +1006,7 @@ static int damos_commit(struct damos *ds - return err; - - dst->wmarks = src->wmarks; -+ dst->target_nid = src->target_nid; - - err = damos_commit_filters(dst, src); - return err; -@@ -1449,6 +1478,7 @@ static unsigned long damon_get_intervals - } - } - target_access_events = max_access_events * goal_bp / 10000; -+ target_access_events = target_access_events ? : 1; - return access_events * 10000 / target_access_events; - } - -@@ -2020,6 +2050,10 @@ static void damos_adjust_quota(struct da - if (!quota->ms && !quota->sz && list_empty("a->goals)) - return; - -+ /* First charge window */ -+ if (!quota->total_charged_sz && !quota->charged_from) -+ quota->charged_from = jiffies; -+ - /* New charge window starts */ - if (time_after_eq(jiffies, quota->charged_from + - msecs_to_jiffies(quota->reset_interval))) { -@@ -2355,9 +2389,8 @@ static void kdamond_usleep(unsigned long - * - * If there is a &struct damon_call_control request that registered via - * &damon_call() on @ctx, do or cancel the invocation of the function depending -- * on @cancel. @cancel is set when the kdamond is deactivated by DAMOS -- * watermarks, or the kdamond is already out of the main loop and therefore -- * will be terminated. -+ * on @cancel. @cancel is set when the kdamond is already out of the main loop -+ * and therefore will be terminated. - */ - static void kdamond_call(struct damon_ctx *ctx, bool cancel) - { -@@ -2405,7 +2438,7 @@ static int kdamond_wait_activation(struc - if (ctx->callback.after_wmarks_check && - ctx->callback.after_wmarks_check(ctx)) - break; -- kdamond_call(ctx, true); -+ kdamond_call(ctx, false); - damos_walk_cancel(ctx); - } - return -EBUSY; -diff -purNx .git BPI-Router-Linux-kernel/mm/damon/Kconfig BPI-Router-Linux-kernel-6.16.12/mm/damon/Kconfig ---- BPI-Router-Linux-kernel/mm/damon/Kconfig 2025-10-22 13:53:23.607327249 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/damon/Kconfig 2025-10-22 13:53:56.791167810 -0400 -@@ -4,7 +4,6 @@ menu "Data Access Monitoring" - - config DAMON - bool "DAMON: Data Access Monitoring Framework" -- default y - help - This builds a framework that allows kernel subsystems to monitor - access frequency of each memory region. The information can be useful -diff -purNx .git BPI-Router-Linux-kernel/mm/damon/lru_sort.c BPI-Router-Linux-kernel-6.16.12/mm/damon/lru_sort.c ---- BPI-Router-Linux-kernel/mm/damon/lru_sort.c 2025-10-22 13:53:23.607327249 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/damon/lru_sort.c 2025-10-22 13:53:56.791167810 -0400 -@@ -198,6 +198,11 @@ static int damon_lru_sort_apply_paramete - if (err) - return err; - -+ if (!damon_lru_sort_mon_attrs.sample_interval) { -+ err = -EINVAL; -+ goto out; -+ } -+ - err = damon_set_attrs(ctx, &damon_lru_sort_mon_attrs); - if (err) - goto out; -diff -purNx .git BPI-Router-Linux-kernel/mm/damon/paddr.c BPI-Router-Linux-kernel-6.16.12/mm/damon/paddr.c ---- BPI-Router-Linux-kernel/mm/damon/paddr.c 2025-10-22 13:53:23.607327249 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/damon/paddr.c 2025-10-22 13:53:56.791167810 -0400 -@@ -476,6 +476,10 @@ static unsigned long damon_pa_migrate_pa - if (list_empty(folio_list)) - return nr_migrated; - -+ if (target_nid < 0 || target_nid >= MAX_NUMNODES || -+ !node_state(target_nid, N_MEMORY)) -+ return nr_migrated; -+ - noreclaim_flag = memalloc_noreclaim_save(); - - nid = folio_nid(lru_to_folio(folio_list)); -diff -purNx .git BPI-Router-Linux-kernel/mm/damon/reclaim.c BPI-Router-Linux-kernel-6.16.12/mm/damon/reclaim.c ---- BPI-Router-Linux-kernel/mm/damon/reclaim.c 2025-10-22 13:53:23.607327249 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/damon/reclaim.c 2025-10-22 13:53:56.791167810 -0400 -@@ -194,6 +194,11 @@ static int damon_reclaim_apply_parameter - if (err) - return err; - -+ if (!damon_reclaim_mon_attrs.aggr_interval) { -+ err = -EINVAL; -+ goto out; -+ } -+ - err = damon_set_attrs(ctx, &damon_reclaim_mon_attrs); - if (err) - goto out; -diff -purNx .git BPI-Router-Linux-kernel/mm/damon/sysfs.c BPI-Router-Linux-kernel-6.16.12/mm/damon/sysfs.c ---- BPI-Router-Linux-kernel/mm/damon/sysfs.c 2025-10-22 13:53:23.607327249 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/damon/sysfs.c 2025-10-22 13:53:56.791167810 -0400 -@@ -1243,14 +1243,18 @@ static ssize_t state_show(struct kobject - { - struct damon_sysfs_kdamond *kdamond = container_of(kobj, - struct damon_sysfs_kdamond, kobj); -- struct damon_ctx *ctx = kdamond->damon_ctx; -- bool running; -+ struct damon_ctx *ctx; -+ bool running = false; - -- if (!ctx) -- running = false; -- else -+ if (!mutex_trylock(&damon_sysfs_lock)) -+ return -EBUSY; -+ -+ ctx = kdamond->damon_ctx; -+ if (ctx) - running = damon_sysfs_ctx_running(ctx); - -+ mutex_unlock(&damon_sysfs_lock); -+ - return sysfs_emit(buf, "%s\n", running ? - damon_sysfs_cmd_strs[DAMON_SYSFS_CMD_ON] : - damon_sysfs_cmd_strs[DAMON_SYSFS_CMD_OFF]); -@@ -1572,12 +1576,14 @@ static int damon_sysfs_damon_call(int (* - struct damon_sysfs_kdamond *kdamond) - { - struct damon_call_control call_control = {}; -+ int err; - - if (!kdamond->damon_ctx) - return -EINVAL; - call_control.fn = fn; - call_control.data = kdamond; -- return damon_call(kdamond->damon_ctx, &call_control); -+ err = damon_call(kdamond->damon_ctx, &call_control); -+ return err ? err : call_control.return_code; - } - - struct damon_sysfs_schemes_walk_data { -diff -purNx .git BPI-Router-Linux-kernel/mm/damon/sysfs-schemes.c BPI-Router-Linux-kernel-6.16.12/mm/damon/sysfs-schemes.c ---- BPI-Router-Linux-kernel/mm/damon/sysfs-schemes.c 2025-10-22 13:53:23.607327249 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/damon/sysfs-schemes.c 2025-10-22 13:53:56.791167810 -0400 -@@ -472,6 +472,7 @@ static ssize_t memcg_path_store(struct k - return -ENOMEM; - - strscpy(path, buf, count + 1); -+ kfree(filter->memcg_path); - filter->memcg_path = path; - return count; - } -diff -purNx .git BPI-Router-Linux-kernel/mm/debug_vm_pgtable.c BPI-Router-Linux-kernel-6.16.12/mm/debug_vm_pgtable.c ---- BPI-Router-Linux-kernel/mm/debug_vm_pgtable.c 2025-10-22 13:53:23.607327249 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/debug_vm_pgtable.c 2025-10-22 13:53:56.791167810 -0400 -@@ -1041,29 +1041,34 @@ static void __init destroy_args(struct p - - /* Free page table entries */ - if (args->start_ptep) { -+ pmd_clear(args->pmdp); - pte_free(args->mm, args->start_ptep); - mm_dec_nr_ptes(args->mm); - } - - if (args->start_pmdp) { -+ pud_clear(args->pudp); - pmd_free(args->mm, args->start_pmdp); - mm_dec_nr_pmds(args->mm); - } - - if (args->start_pudp) { -+ p4d_clear(args->p4dp); - pud_free(args->mm, args->start_pudp); - mm_dec_nr_puds(args->mm); - } - -- if (args->start_p4dp) -+ if (args->start_p4dp) { -+ pgd_clear(args->pgdp); - p4d_free(args->mm, args->start_p4dp); -+ } - - /* Free vma and mm struct */ - if (args->vma) - vm_area_free(args->vma); - - if (args->mm) -- mmdrop(args->mm); -+ mmput(args->mm); - } - - static struct page * __init -diff -purNx .git BPI-Router-Linux-kernel/mm/execmem.c BPI-Router-Linux-kernel-6.16.12/mm/execmem.c ---- BPI-Router-Linux-kernel/mm/execmem.c 2025-10-22 13:53:23.607327249 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/execmem.c 2025-10-22 13:53:56.791167810 -0400 -@@ -254,34 +254,6 @@ out_unlock: - return ptr; - } - --static bool execmem_cache_rox = false; -- --void execmem_cache_make_ro(void) --{ -- struct maple_tree *free_areas = &execmem_cache.free_areas; -- struct maple_tree *busy_areas = &execmem_cache.busy_areas; -- MA_STATE(mas_free, free_areas, 0, ULONG_MAX); -- MA_STATE(mas_busy, busy_areas, 0, ULONG_MAX); -- struct mutex *mutex = &execmem_cache.mutex; -- void *area; -- -- execmem_cache_rox = true; -- -- mutex_lock(mutex); -- -- mas_for_each(&mas_free, area, ULONG_MAX) { -- unsigned long pages = mas_range_len(&mas_free) >> PAGE_SHIFT; -- set_memory_ro(mas_free.index, pages); -- } -- -- mas_for_each(&mas_busy, area, ULONG_MAX) { -- unsigned long pages = mas_range_len(&mas_busy) >> PAGE_SHIFT; -- set_memory_ro(mas_busy.index, pages); -- } -- -- mutex_unlock(mutex); --} -- - static int execmem_cache_populate(struct execmem_range *range, size_t size) - { - unsigned long vm_flags = VM_ALLOW_HUGE_VMAP; -@@ -302,15 +274,9 @@ static int execmem_cache_populate(struct - /* fill memory with instructions that will trap */ - execmem_fill_trapping_insns(p, alloc_size, /* writable = */ true); - -- if (execmem_cache_rox) { -- err = set_memory_rox((unsigned long)p, vm->nr_pages); -- if (err) -- goto err_free_mem; -- } else { -- err = set_memory_x((unsigned long)p, vm->nr_pages); -- if (err) -- goto err_free_mem; -- } -+ err = set_memory_rox((unsigned long)p, vm->nr_pages); -+ if (err) -+ goto err_free_mem; - - err = execmem_cache_add(p, alloc_size); - if (err) -diff -purNx .git BPI-Router-Linux-kernel/mm/filemap.c BPI-Router-Linux-kernel-6.16.12/mm/filemap.c ---- BPI-Router-Linux-kernel/mm/filemap.c 2025-10-22 13:53:23.607327249 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/filemap.c 2025-10-22 13:53:56.791167810 -0400 -@@ -1778,8 +1778,9 @@ pgoff_t page_cache_next_miss(struct addr - pgoff_t index, unsigned long max_scan) - { - XA_STATE(xas, &mapping->i_pages, index); -+ unsigned long nr = max_scan; - -- while (max_scan--) { -+ while (nr--) { - void *entry = xas_next(&xas); - if (!entry || xa_is_value(entry)) - return xas.xa_index; -diff -purNx .git BPI-Router-Linux-kernel/mm/gup.c BPI-Router-Linux-kernel-6.16.12/mm/gup.c ---- BPI-Router-Linux-kernel/mm/gup.c 2025-10-22 13:53:23.611327229 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/gup.c 2025-10-22 13:53:56.791167810 -0400 -@@ -2300,27 +2300,51 @@ static void pofs_unpin(struct pages_or_f - unpin_user_pages(pofs->pages, pofs->nr_entries); - } - -+static struct folio *pofs_next_folio(struct folio *folio, -+ struct pages_or_folios *pofs, long *index_ptr) -+{ -+ long i = *index_ptr + 1; -+ -+ if (!pofs->has_folios && folio_test_large(folio)) { -+ const unsigned long start_pfn = folio_pfn(folio); -+ const unsigned long end_pfn = start_pfn + folio_nr_pages(folio); -+ -+ for (; i < pofs->nr_entries; i++) { -+ unsigned long pfn = page_to_pfn(pofs->pages[i]); -+ -+ /* Is this page part of this folio? */ -+ if (pfn < start_pfn || pfn >= end_pfn) -+ break; -+ } -+ } -+ -+ if (unlikely(i == pofs->nr_entries)) -+ return NULL; -+ *index_ptr = i; -+ -+ return pofs_get_folio(pofs, i); -+} -+ - /* - * Returns the number of collected folios. Return value is always >= 0. - */ --static void collect_longterm_unpinnable_folios( -+static unsigned long collect_longterm_unpinnable_folios( - struct list_head *movable_folio_list, - struct pages_or_folios *pofs) - { -- struct folio *prev_folio = NULL; -- bool drain_allow = true; -- unsigned long i; -- -- for (i = 0; i < pofs->nr_entries; i++) { -- struct folio *folio = pofs_get_folio(pofs, i); -+ unsigned long collected = 0; -+ struct folio *folio; -+ int drained = 0; -+ long i = 0; - -- if (folio == prev_folio) -- continue; -- prev_folio = folio; -+ for (folio = pofs_get_folio(pofs, i); folio; -+ folio = pofs_next_folio(folio, pofs, &i)) { - - if (folio_is_longterm_pinnable(folio)) - continue; - -+ collected++; -+ - if (folio_is_device_coherent(folio)) - continue; - -@@ -2329,9 +2353,17 @@ static void collect_longterm_unpinnable_ - continue; - } - -- if (!folio_test_lru(folio) && drain_allow) { -+ if (drained == 0 && folio_may_be_lru_cached(folio) && -+ folio_ref_count(folio) != -+ folio_expected_ref_count(folio) + 1) { -+ lru_add_drain(); -+ drained = 1; -+ } -+ if (drained == 1 && folio_may_be_lru_cached(folio) && -+ folio_ref_count(folio) != -+ folio_expected_ref_count(folio) + 1) { - lru_add_drain_all(); -- drain_allow = false; -+ drained = 2; - } - - if (!folio_isolate_lru(folio)) -@@ -2342,6 +2374,8 @@ static void collect_longterm_unpinnable_ - NR_ISOLATED_ANON + folio_is_file_lru(folio), - folio_nr_pages(folio)); - } -+ -+ return collected; - } - - /* -@@ -2418,9 +2452,11 @@ static long - check_and_migrate_movable_pages_or_folios(struct pages_or_folios *pofs) - { - LIST_HEAD(movable_folio_list); -+ unsigned long collected; - -- collect_longterm_unpinnable_folios(&movable_folio_list, pofs); -- if (list_empty(&movable_folio_list)) -+ collected = collect_longterm_unpinnable_folios(&movable_folio_list, -+ pofs); -+ if (!collected) - return 0; - - return migrate_longterm_unpinnable_folios(&movable_folio_list, pofs); -diff -purNx .git BPI-Router-Linux-kernel/mm/hmm.c BPI-Router-Linux-kernel-6.16.12/mm/hmm.c ---- BPI-Router-Linux-kernel/mm/hmm.c 2025-10-22 13:53:23.611327229 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/hmm.c 2025-10-22 13:53:56.791167810 -0400 -@@ -183,6 +183,7 @@ static inline unsigned long hmm_pfn_flag - return order << HMM_PFN_ORDER_SHIFT; - } - -+#ifdef CONFIG_TRANSPARENT_HUGEPAGE - static inline unsigned long pmd_to_hmm_pfn_flags(struct hmm_range *range, - pmd_t pmd) - { -@@ -193,7 +194,6 @@ static inline unsigned long pmd_to_hmm_p - hmm_pfn_flags_order(PMD_SHIFT - PAGE_SHIFT); - } - --#ifdef CONFIG_TRANSPARENT_HUGEPAGE - static int hmm_vma_handle_pmd(struct mm_walk *walk, unsigned long addr, - unsigned long end, unsigned long hmm_pfns[], - pmd_t pmd) -diff -purNx .git BPI-Router-Linux-kernel/mm/huge_memory.c BPI-Router-Linux-kernel-6.16.12/mm/huge_memory.c ---- BPI-Router-Linux-kernel/mm/huge_memory.c 2025-10-22 13:53:23.611327229 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/huge_memory.c 2025-10-22 13:53:56.791167810 -0400 -@@ -1516,10 +1516,9 @@ static pud_t maybe_pud_mkwrite(pud_t pud - } - - static void insert_pfn_pud(struct vm_area_struct *vma, unsigned long addr, -- pud_t *pud, pfn_t pfn, bool write) -+ pud_t *pud, pfn_t pfn, pgprot_t prot, bool write) - { - struct mm_struct *mm = vma->vm_mm; -- pgprot_t prot = vma->vm_page_prot; - pud_t entry; - - if (!pud_none(*pud)) { -@@ -1581,7 +1580,7 @@ vm_fault_t vmf_insert_pfn_pud(struct vm_ - pfnmap_setup_cachemode_pfn(pfn_t_to_pfn(pfn), &pgprot); - - ptl = pud_lock(vma->vm_mm, vmf->pud); -- insert_pfn_pud(vma, addr, vmf->pud, pfn, write); -+ insert_pfn_pud(vma, addr, vmf->pud, pfn, pgprot, write); - spin_unlock(ptl); - - return VM_FAULT_NOPAGE; -@@ -1625,7 +1624,7 @@ vm_fault_t vmf_insert_folio_pud(struct v - add_mm_counter(mm, mm_counter_file(folio), HPAGE_PUD_NR); - } - insert_pfn_pud(vma, addr, vmf->pud, pfn_to_pfn_t(folio_pfn(folio)), -- write); -+ vma->vm_page_prot, write); - spin_unlock(ptl); - - return VM_FAULT_NOPAGE; -diff -purNx .git BPI-Router-Linux-kernel/mm/hugetlb.c BPI-Router-Linux-kernel-6.16.12/mm/hugetlb.c ---- BPI-Router-Linux-kernel/mm/hugetlb.c 2025-10-22 13:53:23.611327229 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/hugetlb.c 2025-10-22 13:53:56.791167810 -0400 -@@ -2340,12 +2340,15 @@ struct folio *alloc_hugetlb_folio_reserv - struct folio *folio; - - spin_lock_irq(&hugetlb_lock); -+ if (!h->resv_huge_pages) { -+ spin_unlock_irq(&hugetlb_lock); -+ return NULL; -+ } -+ - folio = dequeue_hugetlb_folio_nodemask(h, gfp_mask, preferred_nid, - nmask); -- if (folio) { -- VM_BUG_ON(!h->resv_huge_pages); -+ if (folio) - h->resv_huge_pages--; -- } - - spin_unlock_irq(&hugetlb_lock); - return folio; -@@ -2787,20 +2790,24 @@ void restore_reserve_on_error(struct hst - /* - * alloc_and_dissolve_hugetlb_folio - Allocate a new folio and dissolve - * the old one -- * @h: struct hstate old page belongs to - * @old_folio: Old folio to dissolve - * @list: List to isolate the page in case we need to - * Returns 0 on success, otherwise negated error. - */ --static int alloc_and_dissolve_hugetlb_folio(struct hstate *h, -- struct folio *old_folio, struct list_head *list) -+static int alloc_and_dissolve_hugetlb_folio(struct folio *old_folio, -+ struct list_head *list) - { -- gfp_t gfp_mask = htlb_alloc_mask(h) | __GFP_THISNODE; -+ gfp_t gfp_mask; -+ struct hstate *h; - int nid = folio_nid(old_folio); - struct folio *new_folio = NULL; - int ret = 0; - - retry: -+ /* -+ * The old_folio might have been dissolved from under our feet, so make sure -+ * to carefully check the state under the lock. -+ */ - spin_lock_irq(&hugetlb_lock); - if (!folio_test_hugetlb(old_folio)) { - /* -@@ -2829,8 +2836,10 @@ retry: - cond_resched(); - goto retry; - } else { -+ h = folio_hstate(old_folio); - if (!new_folio) { - spin_unlock_irq(&hugetlb_lock); -+ gfp_mask = htlb_alloc_mask(h) | __GFP_THISNODE; - new_folio = alloc_buddy_hugetlb_folio(h, gfp_mask, nid, - NULL, NULL); - if (!new_folio) -@@ -2874,35 +2883,24 @@ free_new: - - int isolate_or_dissolve_huge_folio(struct folio *folio, struct list_head *list) - { -- struct hstate *h; - int ret = -EBUSY; - -- /* -- * The page might have been dissolved from under our feet, so make sure -- * to carefully check the state under the lock. -- * Return success when racing as if we dissolved the page ourselves. -- */ -- spin_lock_irq(&hugetlb_lock); -- if (folio_test_hugetlb(folio)) { -- h = folio_hstate(folio); -- } else { -- spin_unlock_irq(&hugetlb_lock); -+ /* Not to disrupt normal path by vainly holding hugetlb_lock */ -+ if (!folio_test_hugetlb(folio)) - return 0; -- } -- spin_unlock_irq(&hugetlb_lock); - - /* - * Fence off gigantic pages as there is a cyclic dependency between - * alloc_contig_range and them. Return -ENOMEM as this has the effect - * of bailing out right away without further retrying. - */ -- if (hstate_is_gigantic(h)) -+ if (folio_order(folio) > MAX_PAGE_ORDER) - return -ENOMEM; - - if (folio_ref_count(folio) && folio_isolate_hugetlb(folio, list)) - ret = 0; - else if (!folio_ref_count(folio)) -- ret = alloc_and_dissolve_hugetlb_folio(h, folio, list); -+ ret = alloc_and_dissolve_hugetlb_folio(folio, list); - - return ret; - } -@@ -2916,7 +2914,6 @@ int isolate_or_dissolve_huge_folio(struc - */ - int replace_free_hugepage_folios(unsigned long start_pfn, unsigned long end_pfn) - { -- struct hstate *h; - struct folio *folio; - int ret = 0; - -@@ -2925,23 +2922,9 @@ int replace_free_hugepage_folios(unsigne - while (start_pfn < end_pfn) { - folio = pfn_folio(start_pfn); - -- /* -- * The folio might have been dissolved from under our feet, so make sure -- * to carefully check the state under the lock. -- */ -- spin_lock_irq(&hugetlb_lock); -- if (folio_test_hugetlb(folio)) { -- h = folio_hstate(folio); -- } else { -- spin_unlock_irq(&hugetlb_lock); -- start_pfn++; -- continue; -- } -- spin_unlock_irq(&hugetlb_lock); -- -- if (!folio_ref_count(folio)) { -- ret = alloc_and_dissolve_hugetlb_folio(h, folio, -- &isolate_list); -+ /* Not to disrupt normal path by vainly holding hugetlb_lock */ -+ if (folio_test_hugetlb(folio) && !folio_ref_count(folio)) { -+ ret = alloc_and_dissolve_hugetlb_folio(folio, &isolate_list); - if (ret) - break; - -@@ -5872,7 +5855,7 @@ void __unmap_hugepage_range(struct mmu_g - spinlock_t *ptl; - struct hstate *h = hstate_vma(vma); - unsigned long sz = huge_page_size(h); -- bool adjust_reservation = false; -+ bool adjust_reservation; - unsigned long last_addr_mask; - bool force_flush = false; - -@@ -5965,6 +5948,7 @@ void __unmap_hugepage_range(struct mmu_g - sz); - hugetlb_count_sub(pages_per_huge_page(h), mm); - hugetlb_remove_rmap(folio); -+ spin_unlock(ptl); - - /* - * Restore the reservation for anonymous page, otherwise the -@@ -5972,14 +5956,16 @@ void __unmap_hugepage_range(struct mmu_g - * If there we are freeing a surplus, do not set the restore - * reservation bit. - */ -+ adjust_reservation = false; -+ -+ spin_lock_irq(&hugetlb_lock); - if (!h->surplus_huge_pages && __vma_private_lock(vma) && - folio_test_anon(folio)) { - folio_set_hugetlb_restore_reserve(folio); - /* Reservation to be adjusted after the spin lock */ - adjust_reservation = true; - } -- -- spin_unlock(ptl); -+ spin_unlock_irq(&hugetlb_lock); - - /* - * Adjust the reservation for the region that will have the -diff -purNx .git BPI-Router-Linux-kernel/mm/kasan/init.c BPI-Router-Linux-kernel-6.16.12/mm/kasan/init.c ---- BPI-Router-Linux-kernel/mm/kasan/init.c 2025-10-22 13:53:23.611327229 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/kasan/init.c 2025-10-22 13:53:56.791167810 -0400 -@@ -13,9 +13,9 @@ - #include - #include - #include -+#include - - #include --#include - - #include "kasan.h" - -@@ -191,7 +191,7 @@ static int __ref zero_p4d_populate(pgd_t - pud_t *pud; - pmd_t *pmd; - -- p4d_populate(&init_mm, p4d, -+ p4d_populate_kernel(addr, p4d, - lm_alias(kasan_early_shadow_pud)); - pud = pud_offset(p4d, addr); - pud_populate(&init_mm, pud, -@@ -212,7 +212,7 @@ static int __ref zero_p4d_populate(pgd_t - } else { - p = early_alloc(PAGE_SIZE, NUMA_NO_NODE); - pud_init(p); -- p4d_populate(&init_mm, p4d, p); -+ p4d_populate_kernel(addr, p4d, p); - } - } - zero_pud_populate(p4d, addr, next); -@@ -251,10 +251,10 @@ int __ref kasan_populate_early_shadow(co - * puds,pmds, so pgd_populate(), pud_populate() - * is noops. - */ -- pgd_populate(&init_mm, pgd, -+ pgd_populate_kernel(addr, pgd, - lm_alias(kasan_early_shadow_p4d)); - p4d = p4d_offset(pgd, addr); -- p4d_populate(&init_mm, p4d, -+ p4d_populate_kernel(addr, p4d, - lm_alias(kasan_early_shadow_pud)); - pud = pud_offset(p4d, addr); - pud_populate(&init_mm, pud, -@@ -273,7 +273,7 @@ int __ref kasan_populate_early_shadow(co - if (!p) - return -ENOMEM; - } else { -- pgd_populate(&init_mm, pgd, -+ pgd_populate_kernel(addr, pgd, - early_alloc(PAGE_SIZE, NUMA_NO_NODE)); - } - } -diff -purNx .git BPI-Router-Linux-kernel/mm/kasan/kasan_test_c.c BPI-Router-Linux-kernel-6.16.12/mm/kasan/kasan_test_c.c ---- BPI-Router-Linux-kernel/mm/kasan/kasan_test_c.c 2025-10-22 13:53:23.611327229 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/kasan/kasan_test_c.c 2025-10-22 13:53:56.791167810 -0400 -@@ -47,7 +47,7 @@ static struct { - * Some tests use these global variables to store return values from function - * calls that could otherwise be eliminated by the compiler as dead code. - */ --static volatile void *kasan_ptr_result; -+static void *volatile kasan_ptr_result; - static volatile int kasan_int_result; - - /* Probe for console output: obtains test_status lines of interest. */ -@@ -1578,9 +1578,11 @@ static void kasan_strings(struct kunit * - - ptr = kmalloc(size, GFP_KERNEL | __GFP_ZERO); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr); -+ OPTIMIZER_HIDE_VAR(ptr); - - src = kmalloc(KASAN_GRANULE_SIZE, GFP_KERNEL | __GFP_ZERO); - strscpy(src, "f0cacc1a0000000", KASAN_GRANULE_SIZE); -+ OPTIMIZER_HIDE_VAR(src); - - /* - * Make sure that strscpy() does not trigger KASAN if it overreads into -diff -purNx .git BPI-Router-Linux-kernel/mm/kasan/report.c BPI-Router-Linux-kernel-6.16.12/mm/kasan/report.c ---- BPI-Router-Linux-kernel/mm/kasan/report.c 2025-10-22 13:53:23.611327229 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/kasan/report.c 2025-10-22 13:53:56.791167810 -0400 -@@ -370,36 +370,6 @@ static inline bool init_task_stack_addr( - sizeof(init_thread_union.stack)); - } - --/* -- * This function is invoked with report_lock (a raw_spinlock) held. A -- * PREEMPT_RT kernel cannot call find_vm_area() as it will acquire a sleeping -- * rt_spinlock. -- * -- * For !RT kernel, the PROVE_RAW_LOCK_NESTING config option will print a -- * lockdep warning for this raw_spinlock -> spinlock dependency. This config -- * option is enabled by default to ensure better test coverage to expose this -- * kind of RT kernel problem. This lockdep splat, however, can be suppressed -- * by using DEFINE_WAIT_OVERRIDE_MAP() if it serves a useful purpose and the -- * invalid PREEMPT_RT case has been taken care of. -- */ --static inline struct vm_struct *kasan_find_vm_area(void *addr) --{ -- static DEFINE_WAIT_OVERRIDE_MAP(vmalloc_map, LD_WAIT_SLEEP); -- struct vm_struct *va; -- -- if (IS_ENABLED(CONFIG_PREEMPT_RT)) -- return NULL; -- -- /* -- * Suppress lockdep warning and fetch vmalloc area of the -- * offending address. -- */ -- lock_map_acquire_try(&vmalloc_map); -- va = find_vm_area(addr); -- lock_map_release(&vmalloc_map); -- return va; --} -- - static void print_address_description(void *addr, u8 tag, - struct kasan_report_info *info) - { -@@ -429,19 +399,10 @@ static void print_address_description(vo - } - - if (is_vmalloc_addr(addr)) { -- struct vm_struct *va = kasan_find_vm_area(addr); -- -- if (va) { -- pr_err("The buggy address belongs to the virtual mapping at\n" -- " [%px, %px) created by:\n" -- " %pS\n", -- va->addr, va->addr + va->size, va->caller); -- pr_err("\n"); -- -- page = vmalloc_to_page(addr); -- } else { -- pr_err("The buggy address %px belongs to a vmalloc virtual mapping\n", addr); -- } -+ pr_err("The buggy address belongs to a"); -+ if (!vmalloc_dump_obj(addr)) -+ pr_cont(" vmalloc virtual mapping\n"); -+ page = vmalloc_to_page(addr); - } - - if (page) { -diff -purNx .git BPI-Router-Linux-kernel/mm/kasan/shadow.c BPI-Router-Linux-kernel-6.16.12/mm/kasan/shadow.c ---- BPI-Router-Linux-kernel/mm/kasan/shadow.c 2025-10-22 13:53:23.611327229 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/kasan/shadow.c 2025-10-22 13:53:56.791167810 -0400 -@@ -335,13 +335,13 @@ static void ___free_pages_bulk(struct pa - } - } - --static int ___alloc_pages_bulk(struct page **pages, int nr_pages) -+static int ___alloc_pages_bulk(struct page **pages, int nr_pages, gfp_t gfp_mask) - { - unsigned long nr_populated, nr_total = nr_pages; - struct page **page_array = pages; - - while (nr_pages) { -- nr_populated = alloc_pages_bulk(GFP_KERNEL, nr_pages, pages); -+ nr_populated = alloc_pages_bulk(gfp_mask, nr_pages, pages); - if (!nr_populated) { - ___free_pages_bulk(page_array, nr_total - nr_pages); - return -ENOMEM; -@@ -353,25 +353,42 @@ static int ___alloc_pages_bulk(struct pa - return 0; - } - --static int __kasan_populate_vmalloc(unsigned long start, unsigned long end) -+static int __kasan_populate_vmalloc(unsigned long start, unsigned long end, gfp_t gfp_mask) - { - unsigned long nr_pages, nr_total = PFN_UP(end - start); - struct vmalloc_populate_data data; -+ unsigned int flags; - int ret = 0; - -- data.pages = (struct page **)__get_free_page(GFP_KERNEL | __GFP_ZERO); -+ data.pages = (struct page **)__get_free_page(gfp_mask | __GFP_ZERO); - if (!data.pages) - return -ENOMEM; - - while (nr_total) { - nr_pages = min(nr_total, PAGE_SIZE / sizeof(data.pages[0])); -- ret = ___alloc_pages_bulk(data.pages, nr_pages); -+ ret = ___alloc_pages_bulk(data.pages, nr_pages, gfp_mask); - if (ret) - break; - - data.start = start; -+ -+ /* -+ * page tables allocations ignore external gfp mask, enforce it -+ * by the scope API -+ */ -+ if ((gfp_mask & (__GFP_FS | __GFP_IO)) == __GFP_IO) -+ flags = memalloc_nofs_save(); -+ else if ((gfp_mask & (__GFP_FS | __GFP_IO)) == 0) -+ flags = memalloc_noio_save(); -+ - ret = apply_to_page_range(&init_mm, start, nr_pages * PAGE_SIZE, - kasan_populate_vmalloc_pte, &data); -+ -+ if ((gfp_mask & (__GFP_FS | __GFP_IO)) == __GFP_IO) -+ memalloc_nofs_restore(flags); -+ else if ((gfp_mask & (__GFP_FS | __GFP_IO)) == 0) -+ memalloc_noio_restore(flags); -+ - ___free_pages_bulk(data.pages, nr_pages); - if (ret) - break; -@@ -385,7 +402,7 @@ static int __kasan_populate_vmalloc(unsi - return ret; - } - --int kasan_populate_vmalloc(unsigned long addr, unsigned long size) -+int kasan_populate_vmalloc(unsigned long addr, unsigned long size, gfp_t gfp_mask) - { - unsigned long shadow_start, shadow_end; - int ret; -@@ -414,7 +431,7 @@ int kasan_populate_vmalloc(unsigned long - shadow_start = PAGE_ALIGN_DOWN(shadow_start); - shadow_end = PAGE_ALIGN(shadow_end); - -- ret = __kasan_populate_vmalloc(shadow_start, shadow_end); -+ ret = __kasan_populate_vmalloc(shadow_start, shadow_end, gfp_mask); - if (ret) - return ret; - -diff -purNx .git BPI-Router-Linux-kernel/mm/khugepaged.c BPI-Router-Linux-kernel-6.16.12/mm/khugepaged.c ---- BPI-Router-Linux-kernel/mm/khugepaged.c 2025-10-22 13:53:23.611327229 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/khugepaged.c 2025-10-22 13:53:56.791167810 -0400 -@@ -1400,8 +1400,8 @@ static int hpage_collapse_scan_pmd(struc - */ - if (cc->is_khugepaged && - (pte_young(pteval) || folio_test_young(folio) || -- folio_test_referenced(folio) || mmu_notifier_test_young(vma->vm_mm, -- address))) -+ folio_test_referenced(folio) || -+ mmu_notifier_test_young(vma->vm_mm, _address))) - referenced++; - } - if (!writable) { -diff -purNx .git BPI-Router-Linux-kernel/mm/kmemleak.c BPI-Router-Linux-kernel-6.16.12/mm/kmemleak.c ---- BPI-Router-Linux-kernel/mm/kmemleak.c 2025-10-22 13:53:23.611327229 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/kmemleak.c 2025-10-22 13:53:56.791167810 -0400 -@@ -437,9 +437,15 @@ static struct kmemleak_object *__lookup_ - else if (untagged_objp == untagged_ptr || alias) - return object; - else { -+ /* -+ * Printk deferring due to the kmemleak_lock held. -+ * This is done to avoid deadlock. -+ */ -+ printk_deferred_enter(); - kmemleak_warn("Found object by alias at 0x%08lx\n", - ptr); - dump_object_info(object); -+ printk_deferred_exit(); - break; - } - } -@@ -470,6 +476,7 @@ static struct kmemleak_object *mem_pool_ - { - unsigned long flags; - struct kmemleak_object *object; -+ bool warn = false; - - /* try the slab allocator first */ - if (object_cache) { -@@ -488,8 +495,10 @@ static struct kmemleak_object *mem_pool_ - else if (mem_pool_free_count) - object = &mem_pool[--mem_pool_free_count]; - else -- pr_warn_once("Memory pool empty, consider increasing CONFIG_DEBUG_KMEMLEAK_MEM_POOL_SIZE\n"); -+ warn = true; - raw_spin_unlock_irqrestore(&kmemleak_lock, flags); -+ if (warn) -+ pr_warn_once("Memory pool empty, consider increasing CONFIG_DEBUG_KMEMLEAK_MEM_POOL_SIZE\n"); - - return object; - } -@@ -733,6 +742,11 @@ static int __link_object(struct kmemleak - else if (untagged_objp + parent->size <= untagged_ptr) - link = &parent->rb_node.rb_right; - else { -+ /* -+ * Printk deferring due to the kmemleak_lock held. -+ * This is done to avoid deadlock. -+ */ -+ printk_deferred_enter(); - kmemleak_stop("Cannot insert 0x%lx into the object search tree (overlaps existing)\n", - ptr); - /* -@@ -740,6 +754,7 @@ static int __link_object(struct kmemleak - * be freed while the kmemleak_lock is held. - */ - dump_object_info(parent); -+ printk_deferred_exit(); - return -EEXIST; - } - } -@@ -853,13 +868,8 @@ static void delete_object_part(unsigned - - raw_spin_lock_irqsave(&kmemleak_lock, flags); - object = __find_and_remove_object(ptr, 1, objflags); -- if (!object) { --#ifdef DEBUG -- kmemleak_warn("Partially freeing unknown object at 0x%08lx (size %zu)\n", -- ptr, size); --#endif -+ if (!object) - goto unlock; -- } - - /* - * Create one or two objects that may result from the memory block -@@ -879,8 +889,14 @@ static void delete_object_part(unsigned - - unlock: - raw_spin_unlock_irqrestore(&kmemleak_lock, flags); -- if (object) -+ if (object) { - __delete_object(object); -+ } else { -+#ifdef DEBUG -+ kmemleak_warn("Partially freeing unknown object at 0x%08lx (size %zu)\n", -+ ptr, size); -+#endif -+ } - - out: - if (object_l) -@@ -1247,6 +1263,20 @@ void __ref kmemleak_transient_leak(const - EXPORT_SYMBOL(kmemleak_transient_leak); - - /** -+ * kmemleak_ignore_percpu - similar to kmemleak_ignore but taking a percpu -+ * address argument -+ * @ptr: percpu address of the object -+ */ -+void __ref kmemleak_ignore_percpu(const void __percpu *ptr) -+{ -+ pr_debug("%s(0x%px)\n", __func__, ptr); -+ -+ if (kmemleak_enabled && ptr && !IS_ERR_PCPU(ptr)) -+ make_black_object((unsigned long)ptr, OBJECT_PERCPU); -+} -+EXPORT_SYMBOL_GPL(kmemleak_ignore_percpu); -+ -+/** - * kmemleak_ignore - ignore an allocated object - * @ptr: pointer to beginning of the object - * -@@ -2167,6 +2197,7 @@ static const struct file_operations kmem - static void __kmemleak_do_cleanup(void) - { - struct kmemleak_object *object, *tmp; -+ unsigned int cnt = 0; - - /* - * Kmemleak has already been disabled, no need for RCU list traversal -@@ -2175,6 +2206,10 @@ static void __kmemleak_do_cleanup(void) - list_for_each_entry_safe(object, tmp, &object_list, object_list) { - __remove_object(object); - __delete_object(object); -+ -+ /* Call cond_resched() once per 64 iterations to avoid soft lockup */ -+ if (!(++cnt & 0x3f)) -+ cond_resched(); - } - } - -diff -purNx .git BPI-Router-Linux-kernel/mm/kmsan/core.c BPI-Router-Linux-kernel-6.16.12/mm/kmsan/core.c ---- BPI-Router-Linux-kernel/mm/kmsan/core.c 2025-10-22 13:53:23.611327229 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/kmsan/core.c 2025-10-22 13:53:56.791167810 -0400 -@@ -195,7 +195,8 @@ void kmsan_internal_set_shadow_origin(vo - u32 origin, bool checked) - { - u64 address = (u64)addr; -- u32 *shadow_start, *origin_start; -+ void *shadow_start; -+ u32 *aligned_shadow, *origin_start; - size_t pad = 0; - - KMSAN_WARN_ON(!kmsan_metadata_is_contiguous(addr, size)); -@@ -214,9 +215,12 @@ void kmsan_internal_set_shadow_origin(vo - } - __memset(shadow_start, b, size); - -- if (!IS_ALIGNED(address, KMSAN_ORIGIN_SIZE)) { -+ if (IS_ALIGNED(address, KMSAN_ORIGIN_SIZE)) { -+ aligned_shadow = shadow_start; -+ } else { - pad = address % KMSAN_ORIGIN_SIZE; - address -= pad; -+ aligned_shadow = shadow_start - pad; - size += pad; - } - size = ALIGN(size, KMSAN_ORIGIN_SIZE); -@@ -230,7 +234,7 @@ void kmsan_internal_set_shadow_origin(vo - * corresponding shadow slot is zero. - */ - for (int i = 0; i < size / KMSAN_ORIGIN_SIZE; i++) { -- if (origin || !shadow_start[i]) -+ if (origin || !aligned_shadow[i]) - origin_start[i] = origin; - } - } -diff -purNx .git BPI-Router-Linux-kernel/mm/kmsan/kmsan_test.c BPI-Router-Linux-kernel-6.16.12/mm/kmsan/kmsan_test.c ---- BPI-Router-Linux-kernel/mm/kmsan/kmsan_test.c 2025-10-22 13:53:23.611327229 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/kmsan/kmsan_test.c 2025-10-22 13:53:56.791167810 -0400 -@@ -556,6 +556,21 @@ DEFINE_TEST_MEMSETXX(16) - DEFINE_TEST_MEMSETXX(32) - DEFINE_TEST_MEMSETXX(64) - -+/* Test case: ensure that KMSAN does not access shadow memory out of bounds. */ -+static void test_memset_on_guarded_buffer(struct kunit *test) -+{ -+ void *buf = vmalloc(PAGE_SIZE); -+ -+ kunit_info(test, -+ "memset() on ends of guarded buffer should not crash\n"); -+ -+ for (size_t size = 0; size <= 128; size++) { -+ memset(buf, 0xff, size); -+ memset(buf + PAGE_SIZE - size, 0xff, size); -+ } -+ vfree(buf); -+} -+ - static noinline void fibonacci(int *array, int size, int start) - { - if (start < 2 || (start == size)) -@@ -677,6 +692,7 @@ static struct kunit_case kmsan_test_case - KUNIT_CASE(test_memset16), - KUNIT_CASE(test_memset32), - KUNIT_CASE(test_memset64), -+ KUNIT_CASE(test_memset_on_guarded_buffer), - KUNIT_CASE(test_long_origin_chain), - KUNIT_CASE(test_stackdepot_roundtrip), - KUNIT_CASE(test_unpoison_memory), -diff -purNx .git BPI-Router-Linux-kernel/mm/ksm.c BPI-Router-Linux-kernel-6.16.12/mm/ksm.c ---- BPI-Router-Linux-kernel/mm/ksm.c 2025-10-22 13:53:23.611327229 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/ksm.c 2025-10-22 13:53:56.795167791 -0400 -@@ -3669,10 +3669,10 @@ static ssize_t advisor_mode_show(struct - { - const char *output; - -- if (ksm_advisor == KSM_ADVISOR_NONE) -- output = "[none] scan-time"; -- else if (ksm_advisor == KSM_ADVISOR_SCAN_TIME) -+ if (ksm_advisor == KSM_ADVISOR_SCAN_TIME) - output = "none [scan-time]"; -+ else -+ output = "[none] scan-time"; - - return sysfs_emit(buf, "%s\n", output); - } -diff -purNx .git BPI-Router-Linux-kernel/mm/madvise.c BPI-Router-Linux-kernel-6.16.12/mm/madvise.c ---- BPI-Router-Linux-kernel/mm/madvise.c 2025-10-22 13:53:23.611327229 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/madvise.c 2025-10-22 13:53:56.795167791 -0400 -@@ -508,6 +508,7 @@ restart: - pte_offset_map_lock(mm, pmd, addr, &ptl); - if (!start_pte) - break; -+ flush_tlb_batched_pending(mm); - arch_enter_lazy_mmu_mode(); - if (!err) - nr = 0; -@@ -741,6 +742,7 @@ static int madvise_free_pte_range(pmd_t - start_pte = pte; - if (!start_pte) - break; -+ flush_tlb_batched_pending(mm); - arch_enter_lazy_mmu_mode(); - if (!err) - nr = 0; -diff -purNx .git BPI-Router-Linux-kernel/mm/memcontrol.c BPI-Router-Linux-kernel-6.16.12/mm/memcontrol.c ---- BPI-Router-Linux-kernel/mm/memcontrol.c 2025-10-22 13:53:23.611327229 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/memcontrol.c 2025-10-22 13:53:56.795167791 -0400 -@@ -474,8 +474,6 @@ static const unsigned int memcg_vm_event - NUMA_PAGE_MIGRATE, - NUMA_PTE_UPDATES, - NUMA_HINT_FAULTS, -- NUMA_TASK_MIGRATE, -- NUMA_TASK_SWAP, - #endif - }; - -diff -purNx .git BPI-Router-Linux-kernel/mm/memory.c BPI-Router-Linux-kernel-6.16.12/mm/memory.c ---- BPI-Router-Linux-kernel/mm/memory.c 2025-10-22 13:53:23.611327229 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/memory.c 2025-10-22 13:53:56.795167791 -0400 -@@ -4315,26 +4315,6 @@ static struct folio *__alloc_swap_folio( - } - - #ifdef CONFIG_TRANSPARENT_HUGEPAGE --static inline int non_swapcache_batch(swp_entry_t entry, int max_nr) --{ -- struct swap_info_struct *si = swp_swap_info(entry); -- pgoff_t offset = swp_offset(entry); -- int i; -- -- /* -- * While allocating a large folio and doing swap_read_folio, which is -- * the case the being faulted pte doesn't have swapcache. We need to -- * ensure all PTEs have no cache as well, otherwise, we might go to -- * swap devices while the content is in swapcache. -- */ -- for (i = 0; i < max_nr; i++) { -- if ((si->swap_map[offset + i] & SWAP_HAS_CACHE)) -- return i; -- } -- -- return i; --} -- - /* - * Check if the PTEs within a range are contiguous swap entries - * and have consistent swapcache, zeromap. -diff -purNx .git BPI-Router-Linux-kernel/mm/memory-failure.c BPI-Router-Linux-kernel-6.16.12/mm/memory-failure.c ---- BPI-Router-Linux-kernel/mm/memory-failure.c 2025-10-22 13:53:23.611327229 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/memory-failure.c 2025-10-22 13:53:56.795167791 -0400 -@@ -847,9 +847,17 @@ static int hwpoison_hugetlb_range(pte_t - #define hwpoison_hugetlb_range NULL - #endif - -+static int hwpoison_test_walk(unsigned long start, unsigned long end, -+ struct mm_walk *walk) -+{ -+ /* We also want to consider pages mapped into VM_PFNMAP. */ -+ return 0; -+} -+ - static const struct mm_walk_ops hwpoison_walk_ops = { - .pmd_entry = hwpoison_pte_range, - .hugetlb_entry = hwpoison_hugetlb_range, -+ .test_walk = hwpoison_test_walk, - .walk_lock = PGWALK_RDLOCK, - }; - -@@ -942,7 +950,7 @@ static const char * const action_page_ty - [MF_MSG_BUDDY] = "free buddy page", - [MF_MSG_DAX] = "dax page", - [MF_MSG_UNSPLIT_THP] = "unsplit thp", -- [MF_MSG_ALREADY_POISONED] = "already poisoned", -+ [MF_MSG_ALREADY_POISONED] = "already poisoned page", - [MF_MSG_UNKNOWN] = "unknown page", - }; - -@@ -1335,9 +1343,10 @@ static int action_result(unsigned long p - { - trace_memory_failure_event(pfn, type, result); - -- num_poisoned_pages_inc(pfn); -- -- update_per_node_mf_stats(pfn, result); -+ if (type != MF_MSG_ALREADY_POISONED) { -+ num_poisoned_pages_inc(pfn); -+ update_per_node_mf_stats(pfn, result); -+ } - - pr_err("%#lx: recovery action for %s: %s\n", - pfn, action_page_types[type], action_name[result]); -@@ -1561,6 +1570,10 @@ static int get_hwpoison_page(struct page - return ret; - } - -+/* -+ * The caller must guarantee the folio isn't large folio, except hugetlb. -+ * try_to_unmap() can't handle it. -+ */ - int unmap_poisoned_folio(struct folio *folio, unsigned long pfn, bool must_kill) - { - enum ttu_flags ttu = TTU_IGNORE_MLOCK | TTU_SYNC | TTU_HWPOISON; -@@ -2076,12 +2089,11 @@ retry: - *hugetlb = 0; - return 0; - } else if (res == -EHWPOISON) { -- pr_err("%#lx: already hardware poisoned\n", pfn); - if (flags & MF_ACTION_REQUIRED) { - folio = page_folio(p); - res = kill_accessing_process(current, folio_pfn(folio), flags); -- action_result(pfn, MF_MSG_ALREADY_POISONED, MF_FAILED); - } -+ action_result(pfn, MF_MSG_ALREADY_POISONED, MF_FAILED); - return res; - } else if (res == -EBUSY) { - if (!(flags & MF_NO_RETRY)) { -@@ -2267,7 +2279,6 @@ try_again: - goto unlock_mutex; - - if (TestSetPageHWPoison(p)) { -- pr_err("%#lx: already hardware poisoned\n", pfn); - res = -EHWPOISON; - if (flags & MF_ACTION_REQUIRED) - res = kill_accessing_process(current, pfn, flags); -@@ -2564,10 +2575,9 @@ int unpoison_memory(unsigned long pfn) - static DEFINE_RATELIMIT_STATE(unpoison_rs, DEFAULT_RATELIMIT_INTERVAL, - DEFAULT_RATELIMIT_BURST); - -- if (!pfn_valid(pfn)) -- return -ENXIO; -- -- p = pfn_to_page(pfn); -+ p = pfn_to_online_page(pfn); -+ if (!p) -+ return -EIO; - folio = page_folio(p); - - mutex_lock(&mf_mutex); -diff -purNx .git BPI-Router-Linux-kernel/mm/migrate.c BPI-Router-Linux-kernel-6.16.12/mm/migrate.c ---- BPI-Router-Linux-kernel/mm/migrate.c 2025-10-22 13:53:23.615327210 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/migrate.c 2025-10-22 13:53:56.795167791 -0400 -@@ -2399,6 +2399,7 @@ set_status: - - static int get_compat_pages_array(const void __user *chunk_pages[], - const void __user * __user *pages, -+ unsigned long chunk_offset, - unsigned long chunk_nr) - { - compat_uptr_t __user *pages32 = (compat_uptr_t __user *)pages; -@@ -2406,7 +2407,7 @@ static int get_compat_pages_array(const - int i; - - for (i = 0; i < chunk_nr; i++) { -- if (get_user(p, pages32 + i)) -+ if (get_user(p, pages32 + chunk_offset + i)) - return -EFAULT; - chunk_pages[i] = compat_ptr(p); - } -@@ -2425,27 +2426,28 @@ static int do_pages_stat(struct mm_struc - #define DO_PAGES_STAT_CHUNK_NR 16UL - const void __user *chunk_pages[DO_PAGES_STAT_CHUNK_NR]; - int chunk_status[DO_PAGES_STAT_CHUNK_NR]; -+ unsigned long chunk_offset = 0; - - while (nr_pages) { - unsigned long chunk_nr = min(nr_pages, DO_PAGES_STAT_CHUNK_NR); - - if (in_compat_syscall()) { - if (get_compat_pages_array(chunk_pages, pages, -- chunk_nr)) -+ chunk_offset, chunk_nr)) - break; - } else { -- if (copy_from_user(chunk_pages, pages, -+ if (copy_from_user(chunk_pages, pages + chunk_offset, - chunk_nr * sizeof(*chunk_pages))) - break; - } - - do_pages_stat_array(mm, chunk_nr, chunk_pages, chunk_status); - -- if (copy_to_user(status, chunk_status, chunk_nr * sizeof(*status))) -+ if (copy_to_user(status + chunk_offset, chunk_status, -+ chunk_nr * sizeof(*status))) - break; - -- pages += chunk_nr; -- status += chunk_nr; -+ chunk_offset += chunk_nr; - nr_pages -= chunk_nr; - } - return nr_pages ? -EFAULT : 0; -diff -purNx .git BPI-Router-Linux-kernel/mm/mlock.c BPI-Router-Linux-kernel-6.16.12/mm/mlock.c ---- BPI-Router-Linux-kernel/mm/mlock.c 2025-10-22 13:53:23.615327210 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/mlock.c 2025-10-22 13:53:56.795167791 -0400 -@@ -255,7 +255,7 @@ void mlock_folio(struct folio *folio) - - folio_get(folio); - if (!folio_batch_add(fbatch, mlock_lru(folio)) || -- folio_test_large(folio) || lru_cache_disabled()) -+ !folio_may_be_lru_cached(folio) || lru_cache_disabled()) - mlock_folio_batch(fbatch); - local_unlock(&mlock_fbatch.lock); - } -@@ -278,7 +278,7 @@ void mlock_new_folio(struct folio *folio - - folio_get(folio); - if (!folio_batch_add(fbatch, mlock_new(folio)) || -- folio_test_large(folio) || lru_cache_disabled()) -+ !folio_may_be_lru_cached(folio) || lru_cache_disabled()) - mlock_folio_batch(fbatch); - local_unlock(&mlock_fbatch.lock); - } -@@ -299,7 +299,7 @@ void munlock_folio(struct folio *folio) - */ - folio_get(folio); - if (!folio_batch_add(fbatch, folio) || -- folio_test_large(folio) || lru_cache_disabled()) -+ !folio_may_be_lru_cached(folio) || lru_cache_disabled()) - mlock_folio_batch(fbatch); - local_unlock(&mlock_fbatch.lock); - } -diff -purNx .git BPI-Router-Linux-kernel/mm/mmap_lock.c BPI-Router-Linux-kernel-6.16.12/mm/mmap_lock.c ---- BPI-Router-Linux-kernel/mm/mmap_lock.c 2025-10-22 13:53:23.615327210 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/mmap_lock.c 2025-10-22 13:53:56.795167791 -0400 -@@ -164,8 +164,7 @@ retry: - */ - - /* Check if the vma we locked is the right one. */ -- if (unlikely(vma->vm_mm != mm || -- address < vma->vm_start || address >= vma->vm_end)) -+ if (unlikely(address < vma->vm_start || address >= vma->vm_end)) - goto inval_end_read; - - rcu_read_unlock(); -diff -purNx .git BPI-Router-Linux-kernel/mm/mremap.c BPI-Router-Linux-kernel-6.16.12/mm/mremap.c ---- BPI-Router-Linux-kernel/mm/mremap.c 2025-10-22 13:53:23.615327210 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/mremap.c 2025-10-22 13:53:56.795167791 -0400 -@@ -294,6 +294,25 @@ static inline bool arch_supports_page_ta - } - #endif - -+static inline bool uffd_supports_page_table_move(struct pagetable_move_control *pmc) -+{ -+ /* -+ * If we are moving a VMA that has uffd-wp registered but with -+ * remap events disabled (new VMA will not be registered with uffd), we -+ * need to ensure that the uffd-wp state is cleared from all pgtables. -+ * This means recursing into lower page tables in move_page_tables(). -+ * -+ * We might get called with VMAs reversed when recovering from a -+ * failed page table move. In that case, the -+ * "old"-but-actually-"originally new" VMA during recovery will not have -+ * a uffd context. Recursing into lower page tables during the original -+ * move but not during the recovery move will cause trouble, because we -+ * run into already-existing page tables. So check both VMAs. -+ */ -+ return !vma_has_uffd_without_event_remap(pmc->old) && -+ !vma_has_uffd_without_event_remap(pmc->new); -+} -+ - #ifdef CONFIG_HAVE_MOVE_PMD - static bool move_normal_pmd(struct pagetable_move_control *pmc, - pmd_t *old_pmd, pmd_t *new_pmd) -@@ -306,6 +325,8 @@ static bool move_normal_pmd(struct paget - - if (!arch_supports_page_table_move()) - return false; -+ if (!uffd_supports_page_table_move(pmc)) -+ return false; - /* - * The destination pmd shouldn't be established, free_pgtables() - * should have released it. -@@ -332,15 +353,6 @@ static bool move_normal_pmd(struct paget - if (WARN_ON_ONCE(!pmd_none(*new_pmd))) - return false; - -- /* If this pmd belongs to a uffd vma with remap events disabled, we need -- * to ensure that the uffd-wp state is cleared from all pgtables. This -- * means recursing into lower page tables in move_page_tables(), and we -- * can reuse the existing code if we simply treat the entry as "not -- * moved". -- */ -- if (vma_has_uffd_without_event_remap(vma)) -- return false; -- - /* - * We don't have to worry about the ordering of src and dst - * ptlocks because exclusive mmap_lock prevents deadlock. -@@ -389,6 +401,8 @@ static bool move_normal_pud(struct paget - - if (!arch_supports_page_table_move()) - return false; -+ if (!uffd_supports_page_table_move(pmc)) -+ return false; - /* - * The destination pud shouldn't be established, free_pgtables() - * should have released it. -@@ -396,15 +410,6 @@ static bool move_normal_pud(struct paget - if (WARN_ON_ONCE(!pud_none(*new_pud))) - return false; - -- /* If this pud belongs to a uffd vma with remap events disabled, we need -- * to ensure that the uffd-wp state is cleared from all pgtables. This -- * means recursing into lower page tables in move_page_tables(), and we -- * can reuse the existing code if we simply treat the entry as "not -- * moved". -- */ -- if (vma_has_uffd_without_event_remap(vma)) -- return false; -- - /* - * We don't have to worry about the ordering of src and dst - * ptlocks because exclusive mmap_lock prevents deadlock. -diff -purNx .git BPI-Router-Linux-kernel/mm/percpu.c BPI-Router-Linux-kernel-6.16.12/mm/percpu.c ---- BPI-Router-Linux-kernel/mm/percpu.c 2025-10-22 13:53:23.615327210 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/percpu.c 2025-10-22 13:53:56.795167791 -0400 -@@ -3108,7 +3108,7 @@ out_free: - #endif /* BUILD_EMBED_FIRST_CHUNK */ - - #ifdef BUILD_PAGE_FIRST_CHUNK --#include -+#include - - #ifndef P4D_TABLE_SIZE - #define P4D_TABLE_SIZE PAGE_SIZE -@@ -3134,13 +3134,13 @@ void __init __weak pcpu_populate_pte(uns - - if (pgd_none(*pgd)) { - p4d = memblock_alloc_or_panic(P4D_TABLE_SIZE, P4D_TABLE_SIZE); -- pgd_populate(&init_mm, pgd, p4d); -+ pgd_populate_kernel(addr, pgd, p4d); - } - - p4d = p4d_offset(pgd, addr); - if (p4d_none(*p4d)) { - pud = memblock_alloc_or_panic(PUD_TABLE_SIZE, PUD_TABLE_SIZE); -- p4d_populate(&init_mm, p4d, pud); -+ p4d_populate_kernel(addr, p4d, pud); - } - - pud = pud_offset(p4d, addr); -diff -purNx .git BPI-Router-Linux-kernel/mm/ptdump.c BPI-Router-Linux-kernel-6.16.12/mm/ptdump.c ---- BPI-Router-Linux-kernel/mm/ptdump.c 2025-10-22 13:53:23.615327210 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/ptdump.c 2025-10-22 13:53:56.795167791 -0400 -@@ -175,6 +175,7 @@ void ptdump_walk_pgd(struct ptdump_state - { - const struct ptdump_range *range = st->range; - -+ get_online_mems(); - mmap_write_lock(mm); - while (range->start != range->end) { - walk_page_range_novma(mm, range->start, range->end, -@@ -182,6 +183,7 @@ void ptdump_walk_pgd(struct ptdump_state - range++; - } - mmap_write_unlock(mm); -+ put_online_mems(); - - /* Flush out the last page */ - st->note_page_flush(st); -diff -purNx .git BPI-Router-Linux-kernel/mm/rmap.c BPI-Router-Linux-kernel-6.16.12/mm/rmap.c ---- BPI-Router-Linux-kernel/mm/rmap.c 2025-10-22 13:53:23.615327210 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/rmap.c 2025-10-22 13:53:56.795167791 -0400 -@@ -1845,23 +1845,32 @@ void folio_remove_rmap_pud(struct folio - #endif - } - --/* We support batch unmapping of PTEs for lazyfree large folios */ --static inline bool can_batch_unmap_folio_ptes(unsigned long addr, -- struct folio *folio, pte_t *ptep) -+static inline unsigned int folio_unmap_pte_batch(struct folio *folio, -+ struct page_vma_mapped_walk *pvmw, -+ enum ttu_flags flags, pte_t pte) - { - const fpb_t fpb_flags = FPB_IGNORE_DIRTY | FPB_IGNORE_SOFT_DIRTY; -- int max_nr = folio_nr_pages(folio); -- pte_t pte = ptep_get(ptep); -+ unsigned long end_addr, addr = pvmw->address; -+ struct vm_area_struct *vma = pvmw->vma; -+ unsigned int max_nr; -+ -+ if (flags & TTU_HWPOISON) -+ return 1; -+ if (!folio_test_large(folio)) -+ return 1; -+ -+ /* We may only batch within a single VMA and a single page table. */ -+ end_addr = pmd_addr_end(addr, vma->vm_end); -+ max_nr = (end_addr - addr) >> PAGE_SHIFT; - -+ /* We only support lazyfree batching for now ... */ - if (!folio_test_anon(folio) || folio_test_swapbacked(folio)) -- return false; -+ return 1; - if (pte_unused(pte)) -- return false; -- if (pte_pfn(pte) != folio_pfn(folio)) -- return false; -+ return 1; - -- return folio_pte_batch(folio, addr, ptep, pte, max_nr, fpb_flags, NULL, -- NULL, NULL) == max_nr; -+ return folio_pte_batch(folio, addr, pvmw->pte, pte, max_nr, fpb_flags, -+ NULL, NULL, NULL); - } - - /* -@@ -2024,9 +2033,7 @@ static bool try_to_unmap_one(struct foli - if (pte_dirty(pteval)) - folio_mark_dirty(folio); - } else if (likely(pte_present(pteval))) { -- if (folio_test_large(folio) && !(flags & TTU_HWPOISON) && -- can_batch_unmap_folio_ptes(address, folio, pvmw.pte)) -- nr_pages = folio_nr_pages(folio); -+ nr_pages = folio_unmap_pte_batch(folio, &pvmw, flags, pteval); - end_addr = address + nr_pages * PAGE_SIZE; - flush_cache_range(vma, address, end_addr); - -@@ -2206,13 +2213,16 @@ discard: - hugetlb_remove_rmap(folio); - } else { - folio_remove_rmap_ptes(folio, subpage, nr_pages, vma); -- folio_ref_sub(folio, nr_pages - 1); - } - if (vma->vm_flags & VM_LOCKED) - mlock_drain_local(); -- folio_put(folio); -- /* We have already batched the entire folio */ -- if (nr_pages > 1) -+ folio_put_refs(folio, nr_pages); -+ -+ /* -+ * If we are sure that we batched the entire folio and cleared -+ * all PTEs, we can just optimize and stop right here. -+ */ -+ if (nr_pages == folio_nr_pages(folio)) - goto walk_done; - continue; - walk_abort: -diff -purNx .git BPI-Router-Linux-kernel/mm/secretmem.c BPI-Router-Linux-kernel-6.16.12/mm/secretmem.c ---- BPI-Router-Linux-kernel/mm/secretmem.c 2025-10-22 13:53:23.615327210 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/secretmem.c 2025-10-22 13:53:56.795167791 -0400 -@@ -195,18 +195,11 @@ static struct file *secretmem_file_creat - struct file *file; - struct inode *inode; - const char *anon_name = "[secretmem]"; -- int err; - -- inode = alloc_anon_inode(secretmem_mnt->mnt_sb); -+ inode = anon_inode_make_secure_inode(secretmem_mnt->mnt_sb, anon_name, NULL); - if (IS_ERR(inode)) - return ERR_CAST(inode); - -- err = security_inode_init_security_anon(inode, &QSTR(anon_name), NULL); -- if (err) { -- file = ERR_PTR(err); -- goto err_free_inode; -- } -- - file = alloc_file_pseudo(inode, secretmem_mnt, "secretmem", - O_RDWR, &secretmem_fops); - if (IS_ERR(file)) -@@ -268,7 +261,15 @@ err_put_fd: - - static int secretmem_init_fs_context(struct fs_context *fc) - { -- return init_pseudo(fc, SECRETMEM_MAGIC) ? 0 : -ENOMEM; -+ struct pseudo_fs_context *ctx; -+ -+ ctx = init_pseudo(fc, SECRETMEM_MAGIC); -+ if (!ctx) -+ return -ENOMEM; -+ -+ fc->s_iflags |= SB_I_NOEXEC; -+ fc->s_iflags |= SB_I_NODEV; -+ return 0; - } - - static struct file_system_type secretmem_fs = { -@@ -286,9 +287,6 @@ static int __init secretmem_init(void) - if (IS_ERR(secretmem_mnt)) - return PTR_ERR(secretmem_mnt); - -- /* prevent secretmem mappings from ever getting PROT_EXEC */ -- secretmem_mnt->mnt_flags |= MNT_NOEXEC; -- - return 0; - } - fs_initcall(secretmem_init); -diff -purNx .git BPI-Router-Linux-kernel/mm/shmem.c BPI-Router-Linux-kernel-6.16.12/mm/shmem.c ---- BPI-Router-Linux-kernel/mm/shmem.c 2025-10-22 13:53:23.615327210 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/shmem.c 2025-10-22 13:53:56.795167791 -0400 -@@ -884,7 +884,9 @@ static int shmem_add_to_page_cache(struc - pgoff_t index, void *expected, gfp_t gfp) - { - XA_STATE_ORDER(xas, &mapping->i_pages, index, folio_order(folio)); -- long nr = folio_nr_pages(folio); -+ unsigned long nr = folio_nr_pages(folio); -+ swp_entry_t iter, swap; -+ void *entry; - - VM_BUG_ON_FOLIO(index != round_down(index, nr), folio); - VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio); -@@ -896,14 +898,25 @@ static int shmem_add_to_page_cache(struc - - gfp &= GFP_RECLAIM_MASK; - folio_throttle_swaprate(folio, gfp); -+ swap = radix_to_swp_entry(expected); - - do { -+ iter = swap; - xas_lock_irq(&xas); -- if (expected != xas_find_conflict(&xas)) { -- xas_set_err(&xas, -EEXIST); -- goto unlock; -+ xas_for_each_conflict(&xas, entry) { -+ /* -+ * The range must either be empty, or filled with -+ * expected swap entries. Shmem swap entries are never -+ * partially freed without split of both entry and -+ * folio, so there shouldn't be any holes. -+ */ -+ if (!expected || entry != swp_to_radix_entry(iter)) { -+ xas_set_err(&xas, -EEXIST); -+ goto unlock; -+ } -+ iter.val += 1 << xas_get_order(&xas); - } -- if (expected && xas_find_conflict(&xas)) { -+ if (expected && iter.val - nr != swap.val) { - xas_set_err(&xas, -EEXIST); - goto unlock; - } -@@ -2259,6 +2272,7 @@ static int shmem_swapin_folio(struct ino - folio = swap_cache_get_folio(swap, NULL, 0); - order = xa_get_order(&mapping->i_pages, index); - if (!folio) { -+ int nr_pages = 1 << order; - bool fallback_order0 = false; - - /* Or update major stats only when swapin succeeds?? */ -@@ -2272,9 +2286,12 @@ static int shmem_swapin_folio(struct ino - * If uffd is active for the vma, we need per-page fault - * fidelity to maintain the uffd semantics, then fallback - * to swapin order-0 folio, as well as for zswap case. -+ * Any existing sub folio in the swap cache also blocks -+ * mTHP swapin. - */ - if (order > 0 && ((vma && unlikely(userfaultfd_armed(vma))) || -- !zswap_never_enabled())) -+ !zswap_never_enabled() || -+ non_swapcache_batch(swap, nr_pages) != nr_pages)) - fallback_order0 = true; - - /* Skip swapcache for synchronous device. */ -@@ -2323,7 +2340,7 @@ static int shmem_swapin_folio(struct ino - error = -ENOMEM; - goto failed; - } -- } else if (order != folio_order(folio)) { -+ } else if (order > folio_order(folio)) { - /* - * Swap readahead may swap in order 0 folios into swapcache - * asynchronously, while the shmem mapping can still stores -@@ -2348,15 +2365,23 @@ static int shmem_swapin_folio(struct ino - - swap = swp_entry(swp_type(swap), swp_offset(swap) + offset); - } -+ } else if (order < folio_order(folio)) { -+ swap.val = round_down(swap.val, 1 << folio_order(folio)); -+ index = round_down(index, 1 << folio_order(folio)); - } - - alloced: -- /* We have to do this with folio locked to prevent races */ -+ /* -+ * We have to do this with the folio locked to prevent races. -+ * The shmem_confirm_swap below only checks if the first swap -+ * entry matches the folio, that's enough to ensure the folio -+ * is not used outside of shmem, as shmem swap entries -+ * and swap cache folios are never partially freed. -+ */ - folio_lock(folio); - if ((!skip_swapcache && !folio_test_swapcache(folio)) || -- folio->swap.val != swap.val || - !shmem_confirm_swap(mapping, index, swap) || -- xa_get_order(&mapping->i_pages, index) != folio_order(folio)) { -+ folio->swap.val != swap.val) { - error = -EEXIST; - goto unlock; - } -@@ -5924,8 +5949,8 @@ struct folio *shmem_read_folio_gfp(struc - struct folio *folio; - int error; - -- error = shmem_get_folio_gfp(inode, index, 0, &folio, SGP_CACHE, -- gfp, NULL, NULL); -+ error = shmem_get_folio_gfp(inode, index, i_size_read(inode), -+ &folio, SGP_CACHE, gfp, NULL, NULL); - if (error) - return ERR_PTR(error); - -diff -purNx .git BPI-Router-Linux-kernel/mm/slub.c BPI-Router-Linux-kernel-6.16.12/mm/slub.c ---- BPI-Router-Linux-kernel/mm/slub.c 2025-10-22 13:53:23.615327210 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/slub.c 2025-10-22 13:53:56.795167791 -0400 -@@ -926,19 +926,19 @@ static struct track *get_track(struct km - } - - #ifdef CONFIG_STACKDEPOT --static noinline depot_stack_handle_t set_track_prepare(void) -+static noinline depot_stack_handle_t set_track_prepare(gfp_t gfp_flags) - { - depot_stack_handle_t handle; - unsigned long entries[TRACK_ADDRS_COUNT]; - unsigned int nr_entries; - - nr_entries = stack_trace_save(entries, ARRAY_SIZE(entries), 3); -- handle = stack_depot_save(entries, nr_entries, GFP_NOWAIT); -+ handle = stack_depot_save(entries, nr_entries, gfp_flags); - - return handle; - } - #else --static inline depot_stack_handle_t set_track_prepare(void) -+static inline depot_stack_handle_t set_track_prepare(gfp_t gfp_flags) - { - return 0; - } -@@ -960,9 +960,9 @@ static void set_track_update(struct kmem - } - - static __always_inline void set_track(struct kmem_cache *s, void *object, -- enum track_item alloc, unsigned long addr) -+ enum track_item alloc, unsigned long addr, gfp_t gfp_flags) - { -- depot_stack_handle_t handle = set_track_prepare(); -+ depot_stack_handle_t handle = set_track_prepare(gfp_flags); - - set_track_update(s, object, alloc, addr, handle); - } -@@ -1104,7 +1104,12 @@ static void object_err(struct kmem_cache - return; - - slab_bug(s, reason); -- print_trailer(s, slab, object); -+ if (!object || !check_valid_pointer(s, slab, object)) { -+ print_slab_info(slab); -+ pr_err("Invalid pointer 0x%p\n", object); -+ } else { -+ print_trailer(s, slab, object); -+ } - add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE); - - WARN_ON(1); -@@ -1885,9 +1890,9 @@ static inline bool free_debug_processing - static inline void slab_pad_check(struct kmem_cache *s, struct slab *slab) {} - static inline int check_object(struct kmem_cache *s, struct slab *slab, - void *object, u8 val) { return 1; } --static inline depot_stack_handle_t set_track_prepare(void) { return 0; } -+static inline depot_stack_handle_t set_track_prepare(gfp_t gfp_flags) { return 0; } - static inline void set_track(struct kmem_cache *s, void *object, -- enum track_item alloc, unsigned long addr) {} -+ enum track_item alloc, unsigned long addr, gfp_t gfp_flags) {} - static inline void add_full(struct kmem_cache *s, struct kmem_cache_node *n, - struct slab *slab) {} - static inline void remove_full(struct kmem_cache *s, struct kmem_cache_node *n, -@@ -3844,9 +3849,14 @@ new_objects: - * For debug caches here we had to go through - * alloc_single_from_partial() so just store the - * tracking info and return the object. -+ * -+ * Due to disabled preemption we need to disallow -+ * blocking. The flags are further adjusted by -+ * gfp_nested_mask() in stack_depot itself. - */ - if (s->flags & SLAB_STORE_USER) -- set_track(s, freelist, TRACK_ALLOC, addr); -+ set_track(s, freelist, TRACK_ALLOC, addr, -+ gfpflags & ~(__GFP_DIRECT_RECLAIM)); - - return freelist; - } -@@ -3878,7 +3888,8 @@ new_objects: - goto new_objects; - - if (s->flags & SLAB_STORE_USER) -- set_track(s, freelist, TRACK_ALLOC, addr); -+ set_track(s, freelist, TRACK_ALLOC, addr, -+ gfpflags & ~(__GFP_DIRECT_RECLAIM)); - - return freelist; - } -@@ -4269,7 +4280,12 @@ static void *___kmalloc_large_node(size_ - flags = kmalloc_fix_flags(flags); - - flags |= __GFP_COMP; -- folio = (struct folio *)alloc_pages_node_noprof(node, flags, order); -+ -+ if (node == NUMA_NO_NODE) -+ folio = (struct folio *)alloc_pages_noprof(flags, order); -+ else -+ folio = (struct folio *)__alloc_pages_noprof(flags, order, node, NULL); -+ - if (folio) { - ptr = folio_address(folio); - lruvec_stat_mod_folio(folio, NR_SLAB_UNRECLAIMABLE_B, -@@ -4384,8 +4400,12 @@ static noinline void free_to_partial_lis - unsigned long flags; - depot_stack_handle_t handle = 0; - -+ /* -+ * We cannot use GFP_NOWAIT as there are callsites where waking up -+ * kswapd could deadlock -+ */ - if (s->flags & SLAB_STORE_USER) -- handle = set_track_prepare(); -+ handle = set_track_prepare(__GFP_NOWARN); - - spin_lock_irqsave(&n->list_lock, flags); - -@@ -4930,12 +4950,12 @@ alloc_new: - * When slub_debug_orig_size() is off, krealloc() only knows about the bucket - * size of an allocation (but not the exact size it was allocated with) and - * hence implements the following semantics for shrinking and growing buffers -- * with __GFP_ZERO. -+ * with __GFP_ZERO:: - * -- * new bucket -- * 0 size size -- * |--------|----------------| -- * | keep | zero | -+ * new bucket -+ * 0 size size -+ * |--------|----------------| -+ * | keep | zero | - * - * Otherwise, the original allocation size 'orig_size' could be used to - * precisely clear the requested size, and the new size will also be stored -diff -purNx .git BPI-Router-Linux-kernel/mm/sparse.c BPI-Router-Linux-kernel-6.16.12/mm/sparse.c ---- BPI-Router-Linux-kernel/mm/sparse.c 2025-10-22 13:53:23.615327210 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/sparse.c 2025-10-22 13:53:56.795167791 -0400 -@@ -454,9 +454,6 @@ static void __init sparse_buffer_init(un - */ - sparsemap_buf = memmap_alloc(size, section_map_size(), addr, nid, true); - sparsemap_buf_end = sparsemap_buf + size; --#ifndef CONFIG_SPARSEMEM_VMEMMAP -- memmap_boot_pages_add(DIV_ROUND_UP(size, PAGE_SIZE)); --#endif - } - - static void __init sparse_buffer_fini(void) -@@ -567,6 +564,8 @@ static void __init sparse_init_nid(int n - sparse_buffer_fini(); - goto failed; - } -+ memmap_boot_pages_add(DIV_ROUND_UP(PAGES_PER_SECTION * sizeof(struct page), -+ PAGE_SIZE)); - sparse_init_early_section(nid, map, pnum, 0); - } - } -@@ -680,7 +679,6 @@ static void depopulate_section_memmap(un - unsigned long start = (unsigned long) pfn_to_page(pfn); - unsigned long end = start + nr_pages * sizeof(struct page); - -- memmap_pages_add(-1L * (DIV_ROUND_UP(end - start, PAGE_SIZE))); - vmemmap_free(start, end, altmap); - } - static void free_map_bootmem(struct page *memmap) -@@ -856,10 +854,14 @@ static void section_deactivate(unsigned - * The memmap of early sections is always fully populated. See - * section_activate() and pfn_valid() . - */ -- if (!section_is_early) -+ if (!section_is_early) { -+ memmap_pages_add(-1L * (DIV_ROUND_UP(nr_pages * sizeof(struct page), PAGE_SIZE))); - depopulate_section_memmap(pfn, nr_pages, altmap); -- else if (memmap) -+ } else if (memmap) { -+ memmap_boot_pages_add(-1L * (DIV_ROUND_UP(nr_pages * sizeof(struct page), -+ PAGE_SIZE))); - free_map_bootmem(memmap); -+ } - - if (empty) - ms->section_mem_map = (unsigned long)NULL; -@@ -904,6 +906,7 @@ static struct page * __meminit section_a - section_deactivate(pfn, nr_pages, altmap); - return ERR_PTR(-ENOMEM); - } -+ memmap_pages_add(DIV_ROUND_UP(nr_pages * sizeof(struct page), PAGE_SIZE)); - - return memmap; - } -diff -purNx .git BPI-Router-Linux-kernel/mm/sparse-vmemmap.c BPI-Router-Linux-kernel-6.16.12/mm/sparse-vmemmap.c ---- BPI-Router-Linux-kernel/mm/sparse-vmemmap.c 2025-10-22 13:53:23.615327210 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/sparse-vmemmap.c 2025-10-22 13:53:56.795167791 -0400 -@@ -27,9 +27,9 @@ - #include - #include - #include -+#include - - #include --#include - #include - - #include "hugetlb_vmemmap.h" -@@ -229,7 +229,7 @@ p4d_t * __meminit vmemmap_p4d_populate(p - if (!p) - return NULL; - pud_init(p); -- p4d_populate(&init_mm, p4d, p); -+ p4d_populate_kernel(addr, p4d, p); - } - return p4d; - } -@@ -241,7 +241,7 @@ pgd_t * __meminit vmemmap_pgd_populate(u - void *p = vmemmap_alloc_block_zero(PAGE_SIZE, node); - if (!p) - return NULL; -- pgd_populate(&init_mm, pgd, p); -+ pgd_populate_kernel(addr, pgd, p); - } - return pgd; - } -@@ -578,11 +578,6 @@ struct page * __meminit __populate_secti - if (r < 0) - return NULL; - -- if (system_state == SYSTEM_BOOTING) -- memmap_boot_pages_add(DIV_ROUND_UP(end - start, PAGE_SIZE)); -- else -- memmap_pages_add(DIV_ROUND_UP(end - start, PAGE_SIZE)); -- - return pfn_to_page(pfn); - } - -diff -purNx .git BPI-Router-Linux-kernel/mm/swap.c BPI-Router-Linux-kernel-6.16.12/mm/swap.c ---- BPI-Router-Linux-kernel/mm/swap.c 2025-10-22 13:53:23.615327210 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/swap.c 2025-10-22 13:53:56.795167791 -0400 -@@ -164,6 +164,10 @@ static void folio_batch_move_lru(struct - for (i = 0; i < folio_batch_count(fbatch); i++) { - struct folio *folio = fbatch->folios[i]; - -+ /* block memcg migration while the folio moves between lru */ -+ if (move_fn != lru_add && !folio_test_clear_lru(folio)) -+ continue; -+ - folio_lruvec_relock_irqsave(folio, &lruvec, &flags); - move_fn(lruvec, folio); - -@@ -176,14 +180,10 @@ static void folio_batch_move_lru(struct - } - - static void __folio_batch_add_and_move(struct folio_batch __percpu *fbatch, -- struct folio *folio, move_fn_t move_fn, -- bool on_lru, bool disable_irq) -+ struct folio *folio, move_fn_t move_fn, bool disable_irq) - { - unsigned long flags; - -- if (on_lru && !folio_test_clear_lru(folio)) -- return; -- - folio_get(folio); - - if (disable_irq) -@@ -191,8 +191,8 @@ static void __folio_batch_add_and_move(s - else - local_lock(&cpu_fbatches.lock); - -- if (!folio_batch_add(this_cpu_ptr(fbatch), folio) || folio_test_large(folio) || -- lru_cache_disabled()) -+ if (!folio_batch_add(this_cpu_ptr(fbatch), folio) || -+ !folio_may_be_lru_cached(folio) || lru_cache_disabled()) - folio_batch_move_lru(this_cpu_ptr(fbatch), move_fn); - - if (disable_irq) -@@ -201,13 +201,13 @@ static void __folio_batch_add_and_move(s - local_unlock(&cpu_fbatches.lock); - } - --#define folio_batch_add_and_move(folio, op, on_lru) \ -- __folio_batch_add_and_move( \ -- &cpu_fbatches.op, \ -- folio, \ -- op, \ -- on_lru, \ -- offsetof(struct cpu_fbatches, op) >= offsetof(struct cpu_fbatches, lock_irq) \ -+#define folio_batch_add_and_move(folio, op) \ -+ __folio_batch_add_and_move( \ -+ &cpu_fbatches.op, \ -+ folio, \ -+ op, \ -+ offsetof(struct cpu_fbatches, op) >= \ -+ offsetof(struct cpu_fbatches, lock_irq) \ - ) - - static void lru_move_tail(struct lruvec *lruvec, struct folio *folio) -@@ -231,10 +231,10 @@ static void lru_move_tail(struct lruvec - void folio_rotate_reclaimable(struct folio *folio) - { - if (folio_test_locked(folio) || folio_test_dirty(folio) || -- folio_test_unevictable(folio)) -+ folio_test_unevictable(folio) || !folio_test_lru(folio)) - return; - -- folio_batch_add_and_move(folio, lru_move_tail, true); -+ folio_batch_add_and_move(folio, lru_move_tail); - } - - void lru_note_cost(struct lruvec *lruvec, bool file, -@@ -323,10 +323,11 @@ static void folio_activate_drain(int cpu - - void folio_activate(struct folio *folio) - { -- if (folio_test_active(folio) || folio_test_unevictable(folio)) -+ if (folio_test_active(folio) || folio_test_unevictable(folio) || -+ !folio_test_lru(folio)) - return; - -- folio_batch_add_and_move(folio, lru_activate, true); -+ folio_batch_add_and_move(folio, lru_activate); - } - - #else -@@ -502,7 +503,7 @@ void folio_add_lru(struct folio *folio) - lru_gen_in_fault() && !(current->flags & PF_MEMALLOC)) - folio_set_active(folio); - -- folio_batch_add_and_move(folio, lru_add, false); -+ folio_batch_add_and_move(folio, lru_add); - } - EXPORT_SYMBOL(folio_add_lru); - -@@ -680,13 +681,13 @@ void lru_add_drain_cpu(int cpu) - void deactivate_file_folio(struct folio *folio) - { - /* Deactivating an unevictable folio will not accelerate reclaim */ -- if (folio_test_unevictable(folio)) -+ if (folio_test_unevictable(folio) || !folio_test_lru(folio)) - return; - - if (lru_gen_enabled() && lru_gen_clear_refs(folio)) - return; - -- folio_batch_add_and_move(folio, lru_deactivate_file, true); -+ folio_batch_add_and_move(folio, lru_deactivate_file); - } - - /* -@@ -699,13 +700,13 @@ void deactivate_file_folio(struct folio - */ - void folio_deactivate(struct folio *folio) - { -- if (folio_test_unevictable(folio)) -+ if (folio_test_unevictable(folio) || !folio_test_lru(folio)) - return; - - if (lru_gen_enabled() ? lru_gen_clear_refs(folio) : !folio_test_active(folio)) - return; - -- folio_batch_add_and_move(folio, lru_deactivate, true); -+ folio_batch_add_and_move(folio, lru_deactivate); - } - - /** -@@ -718,10 +719,11 @@ void folio_deactivate(struct folio *foli - void folio_mark_lazyfree(struct folio *folio) - { - if (!folio_test_anon(folio) || !folio_test_swapbacked(folio) || -+ !folio_test_lru(folio) || - folio_test_swapcache(folio) || folio_test_unevictable(folio)) - return; - -- folio_batch_add_and_move(folio, lru_lazyfree, true); -+ folio_batch_add_and_move(folio, lru_lazyfree); - } - - void lru_add_drain(void) -diff -purNx .git BPI-Router-Linux-kernel/mm/swapfile.c BPI-Router-Linux-kernel-6.16.12/mm/swapfile.c ---- BPI-Router-Linux-kernel/mm/swapfile.c 2025-10-22 13:53:23.615327210 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/swapfile.c 2025-10-22 13:53:56.799167772 -0400 -@@ -1115,6 +1115,7 @@ static void swap_range_alloc(struct swap - if (vm_swap_full()) - schedule_work(&si->reclaim_work); - } -+ atomic_long_sub(nr_entries, &nr_swap_pages); - } - - static void swap_range_free(struct swap_info_struct *si, unsigned long offset, -@@ -1313,7 +1314,6 @@ int folio_alloc_swap(struct folio *folio - if (add_to_swap_cache(folio, entry, gfp | __GFP_NOMEMALLOC, NULL)) - goto out_free; - -- atomic_long_sub(size, &nr_swap_pages); - return 0; - - out_free: -@@ -2244,6 +2244,8 @@ static int unuse_mm(struct mm_struct *mm - VMA_ITERATOR(vmi, mm, 0); - - mmap_read_lock(mm); -+ if (check_stable_address_space(mm)) -+ goto unlock; - for_each_vma(vmi, vma) { - if (vma->anon_vma && !is_vm_hugetlb_page(vma)) { - ret = unuse_vma(vma, type); -@@ -2253,6 +2255,7 @@ static int unuse_mm(struct mm_struct *mm - - cond_resched(); - } -+unlock: - mmap_read_unlock(mm); - return ret; - } -@@ -3141,43 +3144,30 @@ static unsigned long read_swap_header(st - return maxpages; - } - --static int setup_swap_map_and_extents(struct swap_info_struct *si, -- union swap_header *swap_header, -- unsigned char *swap_map, -- unsigned long maxpages, -- sector_t *span) -+static int setup_swap_map(struct swap_info_struct *si, -+ union swap_header *swap_header, -+ unsigned char *swap_map, -+ unsigned long maxpages) - { -- unsigned int nr_good_pages; - unsigned long i; -- int nr_extents; -- -- nr_good_pages = maxpages - 1; /* omit header page */ - -+ swap_map[0] = SWAP_MAP_BAD; /* omit header page */ - for (i = 0; i < swap_header->info.nr_badpages; i++) { - unsigned int page_nr = swap_header->info.badpages[i]; - if (page_nr == 0 || page_nr > swap_header->info.last_page) - return -EINVAL; - if (page_nr < maxpages) { - swap_map[page_nr] = SWAP_MAP_BAD; -- nr_good_pages--; -+ si->pages--; - } - } - -- if (nr_good_pages) { -- swap_map[0] = SWAP_MAP_BAD; -- si->max = maxpages; -- si->pages = nr_good_pages; -- nr_extents = setup_swap_extents(si, span); -- if (nr_extents < 0) -- return nr_extents; -- nr_good_pages = si->pages; -- } -- if (!nr_good_pages) { -+ if (!si->pages) { - pr_warn("Empty swap-file\n"); - return -EINVAL; - } - -- return nr_extents; -+ return 0; - } - - #define SWAP_CLUSTER_INFO_COLS \ -@@ -3217,13 +3207,17 @@ static struct swap_cluster_info *setup_c - * Mark unusable pages as unavailable. The clusters aren't - * marked free yet, so no list operations are involved yet. - * -- * See setup_swap_map_and_extents(): header page, bad pages, -+ * See setup_swap_map(): header page, bad pages, - * and the EOF part of the last cluster. - */ - inc_cluster_info_page(si, cluster_info, 0); -- for (i = 0; i < swap_header->info.nr_badpages; i++) -- inc_cluster_info_page(si, cluster_info, -- swap_header->info.badpages[i]); -+ for (i = 0; i < swap_header->info.nr_badpages; i++) { -+ unsigned int page_nr = swap_header->info.badpages[i]; -+ -+ if (page_nr >= maxpages) -+ continue; -+ inc_cluster_info_page(si, cluster_info, page_nr); -+ } - for (i = maxpages; i < round_up(maxpages, SWAPFILE_CLUSTER); i++) - inc_cluster_info_page(si, cluster_info, i); - -@@ -3363,6 +3357,21 @@ SYSCALL_DEFINE2(swapon, const char __use - goto bad_swap_unlock_inode; - } - -+ si->max = maxpages; -+ si->pages = maxpages - 1; -+ nr_extents = setup_swap_extents(si, &span); -+ if (nr_extents < 0) { -+ error = nr_extents; -+ goto bad_swap_unlock_inode; -+ } -+ if (si->pages != si->max - 1) { -+ pr_err("swap:%u != (max:%u - 1)\n", si->pages, si->max); -+ error = -EINVAL; -+ goto bad_swap_unlock_inode; -+ } -+ -+ maxpages = si->max; -+ - /* OK, set up the swap map and apply the bad block list */ - swap_map = vzalloc(maxpages); - if (!swap_map) { -@@ -3374,12 +3383,9 @@ SYSCALL_DEFINE2(swapon, const char __use - if (error) - goto bad_swap_unlock_inode; - -- nr_extents = setup_swap_map_and_extents(si, swap_header, swap_map, -- maxpages, &span); -- if (unlikely(nr_extents < 0)) { -- error = nr_extents; -+ error = setup_swap_map(si, swap_header, swap_map, maxpages); -+ if (error) - goto bad_swap_unlock_inode; -- } - - /* - * Use kvmalloc_array instead of bitmap_zalloc as the allocation order might -diff -purNx .git BPI-Router-Linux-kernel/mm/swap.h BPI-Router-Linux-kernel-6.16.12/mm/swap.h ---- BPI-Router-Linux-kernel/mm/swap.h 2025-10-22 13:53:23.615327210 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/swap.h 2025-10-22 13:53:56.799167772 -0400 -@@ -106,6 +106,25 @@ static inline int swap_zeromap_batch(swp - return find_next_bit(sis->zeromap, end, start) - start; - } - -+static inline int non_swapcache_batch(swp_entry_t entry, int max_nr) -+{ -+ struct swap_info_struct *si = swp_swap_info(entry); -+ pgoff_t offset = swp_offset(entry); -+ int i; -+ -+ /* -+ * While allocating a large folio and doing mTHP swapin, we need to -+ * ensure all entries are not cached, otherwise, the mTHP folio will -+ * be in conflict with the folio in swap cache. -+ */ -+ for (i = 0; i < max_nr; i++) { -+ if ((si->swap_map[offset + i] & SWAP_HAS_CACHE)) -+ return i; -+ } -+ -+ return i; -+} -+ - #else /* CONFIG_SWAP */ - struct swap_iocb; - static inline void swap_read_folio(struct folio *folio, struct swap_iocb **plug) -@@ -199,6 +218,10 @@ static inline int swap_zeromap_batch(swp - return 0; - } - -+static inline int non_swapcache_batch(swp_entry_t entry, int max_nr) -+{ -+ return 0; -+} - #endif /* CONFIG_SWAP */ - - /** -diff -purNx .git BPI-Router-Linux-kernel/mm/userfaultfd.c BPI-Router-Linux-kernel-6.16.12/mm/userfaultfd.c ---- BPI-Router-Linux-kernel/mm/userfaultfd.c 2025-10-22 13:53:23.615327210 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/userfaultfd.c 2025-10-22 13:53:56.799167772 -0400 -@@ -1084,8 +1084,18 @@ static int move_swap_pte(struct mm_struc - pte_t orig_dst_pte, pte_t orig_src_pte, - pmd_t *dst_pmd, pmd_t dst_pmdval, - spinlock_t *dst_ptl, spinlock_t *src_ptl, -- struct folio *src_folio) -+ struct folio *src_folio, -+ struct swap_info_struct *si, swp_entry_t entry) - { -+ /* -+ * Check if the folio still belongs to the target swap entry after -+ * acquiring the lock. Folio can be freed in the swap cache while -+ * not locked. -+ */ -+ if (src_folio && unlikely(!folio_test_swapcache(src_folio) || -+ entry.val != src_folio->swap.val)) -+ return -EAGAIN; -+ - double_pt_lock(dst_ptl, src_ptl); - - if (!is_pte_pages_stable(dst_pte, src_pte, orig_dst_pte, orig_src_pte, -@@ -1102,6 +1112,25 @@ static int move_swap_pte(struct mm_struc - if (src_folio) { - folio_move_anon_rmap(src_folio, dst_vma); - src_folio->index = linear_page_index(dst_vma, dst_addr); -+ } else { -+ /* -+ * Check if the swap entry is cached after acquiring the src_pte -+ * lock. Otherwise, we might miss a newly loaded swap cache folio. -+ * -+ * Check swap_map directly to minimize overhead, READ_ONCE is sufficient. -+ * We are trying to catch newly added swap cache, the only possible case is -+ * when a folio is swapped in and out again staying in swap cache, using the -+ * same entry before the PTE check above. The PTL is acquired and released -+ * twice, each time after updating the swap_map's flag. So holding -+ * the PTL here ensures we see the updated value. False positive is possible, -+ * e.g. SWP_SYNCHRONOUS_IO swapin may set the flag without touching the -+ * cache, or during the tiny synchronization window between swap cache and -+ * swap_map, but it will be gone very quickly, worst result is retry jitters. -+ */ -+ if (READ_ONCE(si->swap_map[swp_offset(entry)]) & SWAP_HAS_CACHE) { -+ double_pt_unlock(dst_ptl, src_ptl); -+ return -EAGAIN; -+ } - } - - orig_src_pte = ptep_get_and_clear(mm, src_addr, src_pte); -@@ -1412,7 +1441,7 @@ retry: - } - err = move_swap_pte(mm, dst_vma, dst_addr, src_addr, dst_pte, src_pte, - orig_dst_pte, orig_src_pte, dst_pmd, dst_pmdval, -- dst_ptl, src_ptl, src_folio); -+ dst_ptl, src_ptl, src_folio, si, entry); - } - - out: -@@ -1424,10 +1453,15 @@ out: - folio_unlock(src_folio); - folio_put(src_folio); - } -- if (dst_pte) -- pte_unmap(dst_pte); -+ /* -+ * Unmap in reverse order (LIFO) to maintain proper kmap_local -+ * index ordering when CONFIG_HIGHPTE is enabled. We mapped dst_pte -+ * first, then src_pte, so we must unmap src_pte first, then dst_pte. -+ */ - if (src_pte) - pte_unmap(src_pte); -+ if (dst_pte) -+ pte_unmap(dst_pte); - mmu_notifier_invalidate_range_end(&range); - if (si) - put_swap_device(si); -@@ -1800,13 +1834,16 @@ ssize_t move_pages(struct userfaultfd_ct - /* Check if we can move the pmd without splitting it. */ - if (move_splits_huge_pmd(dst_addr, src_addr, src_start + len) || - !pmd_none(dst_pmdval)) { -- struct folio *folio = pmd_folio(*src_pmd); -- -- if (!folio || (!is_huge_zero_folio(folio) && -- !PageAnonExclusive(&folio->page))) { -- spin_unlock(ptl); -- err = -EBUSY; -- break; -+ /* Can be a migration entry */ -+ if (pmd_present(*src_pmd)) { -+ struct folio *folio = pmd_folio(*src_pmd); -+ -+ if (!is_huge_zero_folio(folio) && -+ !PageAnonExclusive(&folio->page)) { -+ spin_unlock(ptl); -+ err = -EBUSY; -+ break; -+ } - } - - spin_unlock(ptl); -diff -purNx .git BPI-Router-Linux-kernel/mm/util.c BPI-Router-Linux-kernel-6.16.12/mm/util.c ---- BPI-Router-Linux-kernel/mm/util.c 2025-10-22 13:53:23.615327210 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/util.c 2025-10-22 13:53:56.799167772 -0400 -@@ -1131,3 +1131,43 @@ void flush_dcache_folio(struct folio *fo - } - EXPORT_SYMBOL(flush_dcache_folio); - #endif -+ -+/** -+ * compat_vma_mmap_prepare() - Apply the file's .mmap_prepare() hook to an -+ * existing VMA -+ * @file: The file which possesss an f_op->mmap_prepare() hook -+ * @vma: The VMA to apply the .mmap_prepare() hook to. -+ * -+ * Ordinarily, .mmap_prepare() is invoked directly upon mmap(). However, certain -+ * 'wrapper' file systems invoke a nested mmap hook of an underlying file. -+ * -+ * Until all filesystems are converted to use .mmap_prepare(), we must be -+ * conservative and continue to invoke these 'wrapper' filesystems using the -+ * deprecated .mmap() hook. -+ * -+ * However we have a problem if the underlying file system possesses an -+ * .mmap_prepare() hook, as we are in a different context when we invoke the -+ * .mmap() hook, already having a VMA to deal with. -+ * -+ * compat_vma_mmap_prepare() is a compatibility function that takes VMA state, -+ * establishes a struct vm_area_desc descriptor, passes to the underlying -+ * .mmap_prepare() hook and applies any changes performed by it. -+ * -+ * Once the conversion of filesystems is complete this function will no longer -+ * be required and will be removed. -+ * -+ * Returns: 0 on success or error. -+ */ -+int compat_vma_mmap_prepare(struct file *file, struct vm_area_struct *vma) -+{ -+ struct vm_area_desc desc; -+ int err; -+ -+ err = file->f_op->mmap_prepare(vma_to_desc(vma, &desc)); -+ if (err) -+ return err; -+ set_vma_from_desc(vma, &desc); -+ -+ return 0; -+} -+EXPORT_SYMBOL(compat_vma_mmap_prepare); -diff -purNx .git BPI-Router-Linux-kernel/mm/vma.c BPI-Router-Linux-kernel-6.16.12/mm/vma.c ---- BPI-Router-Linux-kernel/mm/vma.c 2025-10-22 13:53:23.615327210 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/vma.c 2025-10-22 13:53:56.799167772 -0400 -@@ -967,26 +967,9 @@ static __must_check struct vm_area_struc - err = dup_anon_vma(next, middle, &anon_dup); - } - -- if (err) -+ if (err || commit_merge(vmg)) - goto abort; - -- err = commit_merge(vmg); -- if (err) { -- VM_WARN_ON(err != -ENOMEM); -- -- if (anon_dup) -- unlink_anon_vmas(anon_dup); -- -- /* -- * We've cleaned up any cloned anon_vma's, no VMAs have been -- * modified, no harm no foul if the user requests that we not -- * report this and just give up, leaving the VMAs unmerged. -- */ -- if (!vmg->give_up_on_oom) -- vmg->state = VMA_MERGE_ERROR_NOMEM; -- return NULL; -- } -- - khugepaged_enter_vma(vmg->target, vmg->flags); - vmg->state = VMA_MERGE_SUCCESS; - return vmg->target; -@@ -995,6 +978,9 @@ abort: - vma_iter_set(vmg->vmi, start); - vma_iter_load(vmg->vmi); - -+ if (anon_dup) -+ unlink_anon_vmas(anon_dup); -+ - /* - * This means we have failed to clone anon_vma's correctly, but no - * actual changes to VMAs have occurred, so no harm no foul - if the -@@ -3127,7 +3113,6 @@ int __vm_munmap(unsigned long start, siz - return ret; - } - -- - /* Insert vm structure into process list sorted by address - * and into the inode's i_mmap tree. If vm_file is non-NULL - * then i_mmap_rwsem is taken here. -diff -purNx .git BPI-Router-Linux-kernel/mm/vma.h BPI-Router-Linux-kernel-6.16.12/mm/vma.h ---- BPI-Router-Linux-kernel/mm/vma.h 2025-10-22 13:53:23.619327191 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/vma.h 2025-10-22 13:53:56.799167772 -0400 -@@ -222,6 +222,53 @@ static inline int vma_iter_store_gfp(str - return 0; - } - -+ -+/* -+ * Temporary helper functions for file systems which wrap an invocation of -+ * f_op->mmap() but which might have an underlying file system which implements -+ * f_op->mmap_prepare(). -+ */ -+ -+static inline struct vm_area_desc *vma_to_desc(struct vm_area_struct *vma, -+ struct vm_area_desc *desc) -+{ -+ desc->mm = vma->vm_mm; -+ desc->start = vma->vm_start; -+ desc->end = vma->vm_end; -+ -+ desc->pgoff = vma->vm_pgoff; -+ desc->file = vma->vm_file; -+ desc->vm_flags = vma->vm_flags; -+ desc->page_prot = vma->vm_page_prot; -+ -+ desc->vm_ops = NULL; -+ desc->private_data = NULL; -+ -+ return desc; -+} -+ -+static inline void set_vma_from_desc(struct vm_area_struct *vma, -+ struct vm_area_desc *desc) -+{ -+ /* -+ * Since we're invoking .mmap_prepare() despite having a partially -+ * established VMA, we must take care to handle setting fields -+ * correctly. -+ */ -+ -+ /* Mutable fields. Populated with initial state. */ -+ vma->vm_pgoff = desc->pgoff; -+ if (vma->vm_file != desc->file) -+ vma_set_file(vma, desc->file); -+ if (vma->vm_flags != desc->vm_flags) -+ vm_flags_set(vma, desc->vm_flags); -+ vma->vm_page_prot = desc->page_prot; -+ -+ /* User-defined fields. */ -+ vma->vm_ops = desc->vm_ops; -+ vma->vm_private_data = desc->private_data; -+} -+ - int - do_vmi_align_munmap(struct vma_iterator *vmi, struct vm_area_struct *vma, - struct mm_struct *mm, unsigned long start, -diff -purNx .git BPI-Router-Linux-kernel/mm/vmalloc.c BPI-Router-Linux-kernel-6.16.12/mm/vmalloc.c ---- BPI-Router-Linux-kernel/mm/vmalloc.c 2025-10-22 13:53:23.619327191 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/vmalloc.c 2025-10-22 13:53:56.799167772 -0400 -@@ -514,6 +514,7 @@ static int vmap_pages_pte_range(pmd_t *p - unsigned long end, pgprot_t prot, struct page **pages, int *nr, - pgtbl_mod_mask *mask) - { -+ int err = 0; - pte_t *pte; - - /* -@@ -530,12 +531,18 @@ static int vmap_pages_pte_range(pmd_t *p - do { - struct page *page = pages[*nr]; - -- if (WARN_ON(!pte_none(ptep_get(pte)))) -- return -EBUSY; -- if (WARN_ON(!page)) -- return -ENOMEM; -- if (WARN_ON(!pfn_valid(page_to_pfn(page)))) -- return -EINVAL; -+ if (WARN_ON(!pte_none(ptep_get(pte)))) { -+ err = -EBUSY; -+ break; -+ } -+ if (WARN_ON(!page)) { -+ err = -ENOMEM; -+ break; -+ } -+ if (WARN_ON(!pfn_valid(page_to_pfn(page)))) { -+ err = -EINVAL; -+ break; -+ } - - set_pte_at(&init_mm, addr, pte, mk_pte(page, prot)); - (*nr)++; -@@ -543,7 +550,8 @@ static int vmap_pages_pte_range(pmd_t *p - - arch_leave_lazy_mmu_mode(); - *mask |= PGTBL_PTE_MODIFIED; -- return 0; -+ -+ return err; - } - - static int vmap_pages_pmd_range(pud_t *pud, unsigned long addr, -@@ -2018,6 +2026,8 @@ static struct vmap_area *alloc_vmap_area - if (unlikely(!vmap_initialized)) - return ERR_PTR(-EBUSY); - -+ /* Only reclaim behaviour flags are relevant. */ -+ gfp_mask = gfp_mask & GFP_RECLAIM_MASK; - might_sleep(); - - /* -@@ -2030,8 +2040,6 @@ static struct vmap_area *alloc_vmap_area - */ - va = node_alloc(size, align, vstart, vend, &addr, &vn_id); - if (!va) { -- gfp_mask = gfp_mask & GFP_RECLAIM_MASK; -- - va = kmem_cache_alloc_node(vmap_area_cachep, gfp_mask, node); - if (unlikely(!va)) - return ERR_PTR(-ENOMEM); -@@ -2081,7 +2089,7 @@ retry: - BUG_ON(va->va_start < vstart); - BUG_ON(va->va_end > vend); - -- ret = kasan_populate_vmalloc(addr, size); -+ ret = kasan_populate_vmalloc(addr, size, gfp_mask); - if (ret) { - free_vmap_area(va); - return ERR_PTR(ret); -@@ -4818,7 +4826,7 @@ retry: - - /* populate the kasan shadow space */ - for (area = 0; area < nr_vms; area++) { -- if (kasan_populate_vmalloc(vas[area]->va_start, sizes[area])) -+ if (kasan_populate_vmalloc(vas[area]->va_start, sizes[area], GFP_KERNEL)) - goto err_free_shadow; - } - -diff -purNx .git BPI-Router-Linux-kernel/mm/vmscan.c BPI-Router-Linux-kernel-6.16.12/mm/vmscan.c ---- BPI-Router-Linux-kernel/mm/vmscan.c 2025-10-22 13:53:23.619327191 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/vmscan.c 2025-10-22 13:53:56.799167772 -0400 -@@ -1138,6 +1138,14 @@ retry: - goto keep; - - if (folio_contain_hwpoisoned_page(folio)) { -+ /* -+ * unmap_poisoned_folio() can't handle large -+ * folio, just skip it. memory_failure() will -+ * handle it if the UCE is triggered again. -+ */ -+ if (folio_test_large(folio)) -+ goto keep_locked; -+ - unmap_poisoned_folio(folio, folio_pfn(folio), false); - folio_unlock(folio); - folio_put(folio); -@@ -4497,7 +4505,7 @@ static bool sort_folio(struct lruvec *lr - } - - /* ineligible */ -- if (!folio_test_lru(folio) || zone > sc->reclaim_idx) { -+ if (zone > sc->reclaim_idx) { - gen = folio_inc_gen(lruvec, folio, false); - list_move_tail(&folio->lru, &lrugen->folios[gen][type][zone]); - return true; -diff -purNx .git BPI-Router-Linux-kernel/mm/vmstat.c BPI-Router-Linux-kernel-6.16.12/mm/vmstat.c ---- BPI-Router-Linux-kernel/mm/vmstat.c 2025-10-22 13:53:23.619327191 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/vmstat.c 2025-10-22 13:53:56.799167772 -0400 -@@ -1346,8 +1346,6 @@ const char * const vmstat_text[] = { - "numa_hint_faults", - "numa_hint_faults_local", - "numa_pages_migrated", -- "numa_task_migrated", -- "numa_task_swapped", - #endif - #ifdef CONFIG_MIGRATION - "pgmigrate_success", -diff -purNx .git BPI-Router-Linux-kernel/mm/zsmalloc.c BPI-Router-Linux-kernel-6.16.12/mm/zsmalloc.c ---- BPI-Router-Linux-kernel/mm/zsmalloc.c 2025-10-22 13:53:23.619327191 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/mm/zsmalloc.c 2025-10-22 13:53:56.799167772 -0400 -@@ -1043,6 +1043,9 @@ static struct zspage *alloc_zspage(struc - if (!zspage) - return NULL; - -+ if (!IS_ENABLED(CONFIG_COMPACTION)) -+ gfp &= ~__GFP_MOVABLE; -+ - zspage->magic = ZSPAGE_MAGIC; - zspage->pool = pool; - zspage->class = class->index; -diff -purNx .git BPI-Router-Linux-kernel/net/8021q/vlan.c BPI-Router-Linux-kernel-6.16.12/net/8021q/vlan.c ---- BPI-Router-Linux-kernel/net/8021q/vlan.c 2025-10-22 13:53:23.619327191 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/8021q/vlan.c 2025-10-22 13:53:56.799167772 -0400 -@@ -357,6 +357,35 @@ static int __vlan_device_event(struct ne - return err; - } - -+static void vlan_vid0_add(struct net_device *dev) -+{ -+ struct vlan_info *vlan_info; -+ int err; -+ -+ if (!(dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) -+ return; -+ -+ pr_info("adding VLAN 0 to HW filter on device %s\n", dev->name); -+ -+ err = vlan_vid_add(dev, htons(ETH_P_8021Q), 0); -+ if (err) -+ return; -+ -+ vlan_info = rtnl_dereference(dev->vlan_info); -+ vlan_info->auto_vid0 = true; -+} -+ -+static void vlan_vid0_del(struct net_device *dev) -+{ -+ struct vlan_info *vlan_info = rtnl_dereference(dev->vlan_info); -+ -+ if (!vlan_info || !vlan_info->auto_vid0) -+ return; -+ -+ vlan_info->auto_vid0 = false; -+ vlan_vid_del(dev, htons(ETH_P_8021Q), 0); -+} -+ - static int vlan_device_event(struct notifier_block *unused, unsigned long event, - void *ptr) - { -@@ -378,15 +407,10 @@ static int vlan_device_event(struct noti - return notifier_from_errno(err); - } - -- if ((event == NETDEV_UP) && -- (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) { -- pr_info("adding VLAN 0 to HW filter on device %s\n", -- dev->name); -- vlan_vid_add(dev, htons(ETH_P_8021Q), 0); -- } -- if (event == NETDEV_DOWN && -- (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) -- vlan_vid_del(dev, htons(ETH_P_8021Q), 0); -+ if (event == NETDEV_UP) -+ vlan_vid0_add(dev); -+ else if (event == NETDEV_DOWN) -+ vlan_vid0_del(dev); - - vlan_info = rtnl_dereference(dev->vlan_info); - if (!vlan_info) -diff -purNx .git BPI-Router-Linux-kernel/net/8021q/vlan.h BPI-Router-Linux-kernel-6.16.12/net/8021q/vlan.h ---- BPI-Router-Linux-kernel/net/8021q/vlan.h 2025-10-22 13:53:23.619327191 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/8021q/vlan.h 2025-10-22 13:53:56.799167772 -0400 -@@ -33,6 +33,7 @@ struct vlan_info { - struct vlan_group grp; - struct list_head vid_list; - unsigned int nr_vids; -+ bool auto_vid0; - struct rcu_head rcu; - }; - -diff -purNx .git BPI-Router-Linux-kernel/net/9p/trans_fd.c BPI-Router-Linux-kernel-6.16.12/net/9p/trans_fd.c ---- BPI-Router-Linux-kernel/net/9p/trans_fd.c 2025-10-22 13:53:23.619327191 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/9p/trans_fd.c 2025-10-22 13:53:56.799167772 -0400 -@@ -726,10 +726,10 @@ static int p9_fd_cancelled(struct p9_cli - p9_debug(P9_DEBUG_TRANS, "client %p req %p\n", client, req); - - spin_lock(&m->req_lock); -- /* Ignore cancelled request if message has been received -- * before lock. -- */ -- if (req->status == REQ_STATUS_RCVD) { -+ /* Ignore cancelled request if status changed since the request was -+ * processed in p9_client_flush() -+ */ -+ if (req->status != REQ_STATUS_SENT) { - spin_unlock(&m->req_lock); - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/net/appletalk/aarp.c BPI-Router-Linux-kernel-6.16.12/net/appletalk/aarp.c ---- BPI-Router-Linux-kernel/net/appletalk/aarp.c 2025-10-22 13:53:23.619327191 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/appletalk/aarp.c 2025-10-22 13:53:56.799167772 -0400 -@@ -35,6 +35,7 @@ - #include - #include - #include -+#include - - int sysctl_aarp_expiry_time = AARP_EXPIRY_TIME; - int sysctl_aarp_tick_time = AARP_TICK_TIME; -@@ -44,6 +45,7 @@ int sysctl_aarp_resolve_time = AARP_RESO - /* Lists of aarp entries */ - /** - * struct aarp_entry - AARP entry -+ * @refcnt: Reference count - * @last_sent: Last time we xmitted the aarp request - * @packet_queue: Queue of frames wait for resolution - * @status: Used for proxy AARP -@@ -55,6 +57,7 @@ int sysctl_aarp_resolve_time = AARP_RESO - * @next: Next entry in chain - */ - struct aarp_entry { -+ refcount_t refcnt; - /* These first two are only used for unresolved entries */ - unsigned long last_sent; - struct sk_buff_head packet_queue; -@@ -79,6 +82,17 @@ static DEFINE_RWLOCK(aarp_lock); - /* Used to walk the list and purge/kick entries. */ - static struct timer_list aarp_timer; - -+static inline void aarp_entry_get(struct aarp_entry *a) -+{ -+ refcount_inc(&a->refcnt); -+} -+ -+static inline void aarp_entry_put(struct aarp_entry *a) -+{ -+ if (refcount_dec_and_test(&a->refcnt)) -+ kfree(a); -+} -+ - /* - * Delete an aarp queue - * -@@ -87,7 +101,7 @@ static struct timer_list aarp_timer; - static void __aarp_expire(struct aarp_entry *a) - { - skb_queue_purge(&a->packet_queue); -- kfree(a); -+ aarp_entry_put(a); - } - - /* -@@ -380,9 +394,11 @@ static void aarp_purge(void) - static struct aarp_entry *aarp_alloc(void) - { - struct aarp_entry *a = kmalloc(sizeof(*a), GFP_ATOMIC); -+ if (!a) -+ return NULL; - -- if (a) -- skb_queue_head_init(&a->packet_queue); -+ refcount_set(&a->refcnt, 1); -+ skb_queue_head_init(&a->packet_queue); - return a; - } - -@@ -477,6 +493,7 @@ int aarp_proxy_probe_network(struct atal - entry->dev = atif->dev; - - write_lock_bh(&aarp_lock); -+ aarp_entry_get(entry); - - hash = sa->s_node % (AARP_HASH_SIZE - 1); - entry->next = proxies[hash]; -@@ -502,6 +519,7 @@ int aarp_proxy_probe_network(struct atal - retval = 1; - } - -+ aarp_entry_put(entry); - write_unlock_bh(&aarp_lock); - out: - return retval; -diff -purNx .git BPI-Router-Linux-kernel/net/appletalk/atalk_proc.c BPI-Router-Linux-kernel-6.16.12/net/appletalk/atalk_proc.c ---- BPI-Router-Linux-kernel/net/appletalk/atalk_proc.c 2025-10-22 13:53:23.619327191 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/appletalk/atalk_proc.c 2025-10-22 13:53:56.799167772 -0400 -@@ -181,7 +181,7 @@ static int atalk_seq_socket_show(struct - sk_wmem_alloc_get(s), - sk_rmem_alloc_get(s), - s->sk_state, -- from_kuid_munged(seq_user_ns(seq), sock_i_uid(s))); -+ from_kuid_munged(seq_user_ns(seq), sk_uid(s))); - out: - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/net/appletalk/ddp.c BPI-Router-Linux-kernel-6.16.12/net/appletalk/ddp.c ---- BPI-Router-Linux-kernel/net/appletalk/ddp.c 2025-10-22 13:53:23.619327191 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/appletalk/ddp.c 2025-10-22 13:53:56.799167772 -0400 -@@ -576,6 +576,7 @@ static int atrtr_create(struct rtentry * - - /* Fill in the routing entry */ - rt->target = ta->sat_addr; -+ dev_put(rt->dev); /* Release old device */ - dev_hold(devhint); - rt->dev = devhint; - rt->flags = r->rt_flags; -diff -purNx .git BPI-Router-Linux-kernel/net/atm/clip.c BPI-Router-Linux-kernel-6.16.12/net/atm/clip.c ---- BPI-Router-Linux-kernel/net/atm/clip.c 2025-10-22 13:53:23.619327191 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/atm/clip.c 2025-10-22 13:53:56.799167772 -0400 -@@ -45,7 +45,8 @@ - #include - - static struct net_device *clip_devs; --static struct atm_vcc *atmarpd; -+static struct atm_vcc __rcu *atmarpd; -+static DEFINE_MUTEX(atmarpd_lock); - static struct timer_list idle_timer; - static const struct neigh_ops clip_neigh_ops; - -@@ -53,24 +54,35 @@ static int to_atmarpd(enum atmarp_ctrl_t - { - struct sock *sk; - struct atmarp_ctrl *ctrl; -+ struct atm_vcc *vcc; - struct sk_buff *skb; -+ int err = 0; - - pr_debug("(%d)\n", type); -- if (!atmarpd) -- return -EUNATCH; -+ -+ rcu_read_lock(); -+ vcc = rcu_dereference(atmarpd); -+ if (!vcc) { -+ err = -EUNATCH; -+ goto unlock; -+ } - skb = alloc_skb(sizeof(struct atmarp_ctrl), GFP_ATOMIC); -- if (!skb) -- return -ENOMEM; -+ if (!skb) { -+ err = -ENOMEM; -+ goto unlock; -+ } - ctrl = skb_put(skb, sizeof(struct atmarp_ctrl)); - ctrl->type = type; - ctrl->itf_num = itf; - ctrl->ip = ip; -- atm_force_charge(atmarpd, skb->truesize); -+ atm_force_charge(vcc, skb->truesize); - -- sk = sk_atm(atmarpd); -+ sk = sk_atm(vcc); - skb_queue_tail(&sk->sk_receive_queue, skb); - sk->sk_data_ready(sk); -- return 0; -+unlock: -+ rcu_read_unlock(); -+ return err; - } - - static void link_vcc(struct clip_vcc *clip_vcc, struct atmarp_entry *entry) -@@ -193,12 +205,6 @@ static void clip_push(struct atm_vcc *vc - - pr_debug("\n"); - -- if (!clip_devs) { -- atm_return(vcc, skb->truesize); -- kfree_skb(skb); -- return; -- } -- - if (!skb) { - pr_debug("removing VCC %p\n", clip_vcc); - if (clip_vcc->entry) -@@ -208,6 +214,11 @@ static void clip_push(struct atm_vcc *vc - return; - } - atm_return(vcc, skb->truesize); -+ if (!clip_devs) { -+ kfree_skb(skb); -+ return; -+ } -+ - skb->dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : clip_devs; - /* clip_vcc->entry == NULL if we don't have an IP address yet */ - if (!skb->dev) { -@@ -418,6 +429,8 @@ static int clip_mkip(struct atm_vcc *vcc - - if (!vcc->push) - return -EBADFD; -+ if (vcc->user_back) -+ return -EINVAL; - clip_vcc = kmalloc(sizeof(struct clip_vcc), GFP_KERNEL); - if (!clip_vcc) - return -ENOMEM; -@@ -608,17 +621,27 @@ static void atmarpd_close(struct atm_vcc - { - pr_debug("\n"); - -- rtnl_lock(); -- atmarpd = NULL; -+ mutex_lock(&atmarpd_lock); -+ RCU_INIT_POINTER(atmarpd, NULL); -+ mutex_unlock(&atmarpd_lock); -+ -+ synchronize_rcu(); - skb_queue_purge(&sk_atm(vcc)->sk_receive_queue); -- rtnl_unlock(); - - pr_debug("(done)\n"); - module_put(THIS_MODULE); - } - -+static int atmarpd_send(struct atm_vcc *vcc, struct sk_buff *skb) -+{ -+ atm_return_tx(vcc, skb); -+ dev_kfree_skb_any(skb); -+ return 0; -+} -+ - static const struct atmdev_ops atmarpd_dev_ops = { -- .close = atmarpd_close -+ .close = atmarpd_close, -+ .send = atmarpd_send - }; - - -@@ -632,15 +655,18 @@ static struct atm_dev atmarpd_dev = { - - static int atm_init_atmarp(struct atm_vcc *vcc) - { -- rtnl_lock(); -+ if (vcc->push == clip_push) -+ return -EINVAL; -+ -+ mutex_lock(&atmarpd_lock); - if (atmarpd) { -- rtnl_unlock(); -+ mutex_unlock(&atmarpd_lock); - return -EADDRINUSE; - } - - mod_timer(&idle_timer, jiffies + CLIP_CHECK_INTERVAL * HZ); - -- atmarpd = vcc; -+ rcu_assign_pointer(atmarpd, vcc); - set_bit(ATM_VF_META, &vcc->flags); - set_bit(ATM_VF_READY, &vcc->flags); - /* allow replies and avoid getting closed if signaling dies */ -@@ -649,13 +675,14 @@ static int atm_init_atmarp(struct atm_vc - vcc->push = NULL; - vcc->pop = NULL; /* crash */ - vcc->push_oam = NULL; /* crash */ -- rtnl_unlock(); -+ mutex_unlock(&atmarpd_lock); - return 0; - } - - static int clip_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) - { - struct atm_vcc *vcc = ATM_SD(sock); -+ struct sock *sk = sock->sk; - int err = 0; - - switch (cmd) { -@@ -676,14 +703,18 @@ static int clip_ioctl(struct socket *soc - err = clip_create(arg); - break; - case ATMARPD_CTRL: -+ lock_sock(sk); - err = atm_init_atmarp(vcc); - if (!err) { - sock->state = SS_CONNECTED; - __module_get(THIS_MODULE); - } -+ release_sock(sk); - break; - case ATMARP_MKIP: -+ lock_sock(sk); - err = clip_mkip(vcc, arg); -+ release_sock(sk); - break; - case ATMARP_SETENTRY: - err = clip_setentry(vcc, (__force __be32)arg); -diff -purNx .git BPI-Router-Linux-kernel/net/atm/common.c BPI-Router-Linux-kernel-6.16.12/net/atm/common.c ---- BPI-Router-Linux-kernel/net/atm/common.c 2025-10-22 13:53:23.619327191 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/atm/common.c 2025-10-22 13:53:56.799167772 -0400 -@@ -635,17 +635,27 @@ int vcc_sendmsg(struct socket *sock, str - - skb->dev = NULL; /* for paths shared with net_device interfaces */ - if (!copy_from_iter_full(skb_put(skb, size), size, &m->msg_iter)) { -- kfree_skb(skb); - error = -EFAULT; -- goto out; -+ goto free_skb; - } - if (eff != size) - memset(skb->data + size, 0, eff-size); -+ -+ if (vcc->dev->ops->pre_send) { -+ error = vcc->dev->ops->pre_send(vcc, skb); -+ if (error) -+ goto free_skb; -+ } -+ - error = vcc->dev->ops->send(vcc, skb); - error = error ? error : size; - out: - release_sock(sk); - return error; -+free_skb: -+ atm_return_tx(vcc, skb); -+ kfree_skb(skb); -+ goto out; - } - - __poll_t vcc_poll(struct file *file, struct socket *sock, poll_table *wait) -diff -purNx .git BPI-Router-Linux-kernel/net/atm/lec.c BPI-Router-Linux-kernel-6.16.12/net/atm/lec.c ---- BPI-Router-Linux-kernel/net/atm/lec.c 2025-10-22 13:53:23.619327191 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/atm/lec.c 2025-10-22 13:53:56.799167772 -0400 -@@ -124,6 +124,7 @@ static unsigned char bus_mac[ETH_ALEN] = - - /* Device structures */ - static struct net_device *dev_lec[MAX_LEC_ITF]; -+static DEFINE_MUTEX(lec_mutex); - - #if IS_ENABLED(CONFIG_BRIDGE) - static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev) -@@ -685,6 +686,7 @@ static int lec_vcc_attach(struct atm_vcc - int bytes_left; - struct atmlec_ioc ioc_data; - -+ lockdep_assert_held(&lec_mutex); - /* Lecd must be up in this case */ - bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmlec_ioc)); - if (bytes_left != 0) -@@ -710,6 +712,7 @@ static int lec_vcc_attach(struct atm_vcc - - static int lec_mcast_attach(struct atm_vcc *vcc, int arg) - { -+ lockdep_assert_held(&lec_mutex); - if (arg < 0 || arg >= MAX_LEC_ITF) - return -EINVAL; - arg = array_index_nospec(arg, MAX_LEC_ITF); -@@ -725,6 +728,7 @@ static int lecd_attach(struct atm_vcc *v - int i; - struct lec_priv *priv; - -+ lockdep_assert_held(&lec_mutex); - if (arg < 0) - arg = 0; - if (arg >= MAX_LEC_ITF) -@@ -742,6 +746,7 @@ static int lecd_attach(struct atm_vcc *v - snprintf(dev_lec[i]->name, IFNAMSIZ, "lec%d", i); - if (register_netdev(dev_lec[i])) { - free_netdev(dev_lec[i]); -+ dev_lec[i] = NULL; - return -EINVAL; - } - -@@ -904,7 +909,6 @@ static void *lec_itf_walk(struct lec_sta - v = (dev && netdev_priv(dev)) ? - lec_priv_walk(state, l, netdev_priv(dev)) : NULL; - if (!v && dev) { -- dev_put(dev); - /* Partial state reset for the next time we get called */ - dev = NULL; - } -@@ -928,6 +932,7 @@ static void *lec_seq_start(struct seq_fi - { - struct lec_state *state = seq->private; - -+ mutex_lock(&lec_mutex); - state->itf = 0; - state->dev = NULL; - state->locked = NULL; -@@ -945,8 +950,9 @@ static void lec_seq_stop(struct seq_file - if (state->dev) { - spin_unlock_irqrestore(&state->locked->lec_arp_lock, - state->flags); -- dev_put(state->dev); -+ state->dev = NULL; - } -+ mutex_unlock(&lec_mutex); - } - - static void *lec_seq_next(struct seq_file *seq, void *v, loff_t *pos) -@@ -1003,6 +1009,7 @@ static int lane_ioctl(struct socket *soc - return -ENOIOCTLCMD; - } - -+ mutex_lock(&lec_mutex); - switch (cmd) { - case ATMLEC_CTRL: - err = lecd_attach(vcc, (int)arg); -@@ -1017,6 +1024,7 @@ static int lane_ioctl(struct socket *soc - break; - } - -+ mutex_unlock(&lec_mutex); - return err; - } - -diff -purNx .git BPI-Router-Linux-kernel/net/atm/raw.c BPI-Router-Linux-kernel-6.16.12/net/atm/raw.c ---- BPI-Router-Linux-kernel/net/atm/raw.c 2025-10-22 13:53:23.619327191 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/atm/raw.c 2025-10-22 13:53:56.799167772 -0400 -@@ -36,7 +36,7 @@ static void atm_pop_raw(struct atm_vcc * - - pr_debug("(%d) %d -= %d\n", - vcc->vci, sk_wmem_alloc_get(sk), ATM_SKB(skb)->acct_truesize); -- WARN_ON(refcount_sub_and_test(ATM_SKB(skb)->acct_truesize, &sk->sk_wmem_alloc)); -+ atm_return_tx(vcc, skb); - dev_kfree_skb_any(skb); - sk->sk_write_space(sk); - } -diff -purNx .git BPI-Router-Linux-kernel/net/atm/resources.c BPI-Router-Linux-kernel-6.16.12/net/atm/resources.c ---- BPI-Router-Linux-kernel/net/atm/resources.c 2025-10-22 13:53:23.619327191 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/atm/resources.c 2025-10-22 13:53:56.799167772 -0400 -@@ -112,7 +112,9 @@ struct atm_dev *atm_dev_register(const c - - if (atm_proc_dev_register(dev) < 0) { - pr_err("atm_proc_dev_register failed for dev %s\n", type); -- goto out_fail; -+ mutex_unlock(&atm_dev_mutex); -+ kfree(dev); -+ return NULL; - } - - if (atm_register_sysfs(dev, parent) < 0) { -@@ -128,7 +130,7 @@ out: - return dev; - - out_fail: -- kfree(dev); -+ put_device(&dev->class_dev); - dev = NULL; - goto out; - } -@@ -146,11 +148,10 @@ void atm_dev_deregister(struct atm_dev * - */ - mutex_lock(&atm_dev_mutex); - list_del(&dev->dev_list); -- mutex_unlock(&atm_dev_mutex); -- - atm_dev_release_vccs(dev); - atm_unregister_sysfs(dev); - atm_proc_dev_deregister(dev); -+ mutex_unlock(&atm_dev_mutex); - - atm_dev_put(dev); - } -diff -purNx .git BPI-Router-Linux-kernel/net/ax25/ax25_in.c BPI-Router-Linux-kernel-6.16.12/net/ax25/ax25_in.c ---- BPI-Router-Linux-kernel/net/ax25/ax25_in.c 2025-10-22 13:53:23.619327191 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ax25/ax25_in.c 2025-10-22 13:53:56.799167772 -0400 -@@ -433,6 +433,10 @@ free: - int ax25_kiss_rcv(struct sk_buff *skb, struct net_device *dev, - struct packet_type *ptype, struct net_device *orig_dev) - { -+ skb = skb_share_check(skb, GFP_ATOMIC); -+ if (!skb) -+ return NET_RX_DROP; -+ - skb_orphan(skb); - - if (!net_eq(dev_net(dev), &init_net)) { -diff -purNx .git BPI-Router-Linux-kernel/net/batman-adv/network-coding.c BPI-Router-Linux-kernel-6.16.12/net/batman-adv/network-coding.c ---- BPI-Router-Linux-kernel/net/batman-adv/network-coding.c 2025-10-22 13:53:23.619327191 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/batman-adv/network-coding.c 2025-10-22 13:53:56.803167752 -0400 -@@ -1687,7 +1687,12 @@ batadv_nc_skb_decode_packet(struct batad - - coding_len = ntohs(coded_packet_tmp.coded_len); - -- if (coding_len > skb->len) -+ /* ensure dst buffer is large enough (payload only) */ -+ if (coding_len + h_size > skb->len) -+ return NULL; -+ -+ /* ensure src buffer is large enough (payload only) */ -+ if (coding_len + h_size > nc_packet->skb->len) - return NULL; - - /* Here the magic is reversed: -diff -purNx .git BPI-Router-Linux-kernel/net/bluetooth/af_bluetooth.c BPI-Router-Linux-kernel-6.16.12/net/bluetooth/af_bluetooth.c ---- BPI-Router-Linux-kernel/net/bluetooth/af_bluetooth.c 2025-10-22 13:53:23.619327191 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bluetooth/af_bluetooth.c 2025-10-22 13:53:56.803167752 -0400 -@@ -815,7 +815,7 @@ static int bt_seq_show(struct seq_file * - refcount_read(&sk->sk_refcnt), - sk_rmem_alloc_get(sk), - sk_wmem_alloc_get(sk), -- from_kuid(seq_user_ns(seq), sock_i_uid(sk)), -+ from_kuid(seq_user_ns(seq), sk_uid(sk)), - sock_i_ino(sk), - bt->parent ? sock_i_ino(bt->parent) : 0LU); - -diff -purNx .git BPI-Router-Linux-kernel/net/bluetooth/coredump.c BPI-Router-Linux-kernel-6.16.12/net/bluetooth/coredump.c ---- BPI-Router-Linux-kernel/net/bluetooth/coredump.c 2025-10-22 13:53:23.619327191 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bluetooth/coredump.c 2025-10-22 13:53:56.803167752 -0400 -@@ -249,15 +249,15 @@ static void hci_devcd_dump(struct hci_de - - size = hdev->dump.tail - hdev->dump.head; - -- /* Emit a devcoredump with the available data */ -- dev_coredumpv(&hdev->dev, hdev->dump.head, size, GFP_KERNEL); -- - /* Send a copy to monitor as a diagnostic packet */ - skb = bt_skb_alloc(size, GFP_ATOMIC); - if (skb) { - skb_put_data(skb, hdev->dump.head, size); - hci_recv_diag(hdev, skb); - } -+ -+ /* Emit a devcoredump with the available data */ -+ dev_coredumpv(&hdev->dev, hdev->dump.head, size, GFP_KERNEL); - } - - static void hci_devcd_handle_pkt_complete(struct hci_dev *hdev, -diff -purNx .git BPI-Router-Linux-kernel/net/bluetooth/eir.c BPI-Router-Linux-kernel-6.16.12/net/bluetooth/eir.c ---- BPI-Router-Linux-kernel/net/bluetooth/eir.c 2025-10-22 13:53:23.619327191 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bluetooth/eir.c 2025-10-22 13:53:56.803167752 -0400 -@@ -242,7 +242,7 @@ u8 eir_create_per_adv_data(struct hci_de - return ad_len; - } - --u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr) -+u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr, u8 size) - { - struct adv_info *adv = NULL; - u8 ad_len = 0, flags = 0; -@@ -286,7 +286,7 @@ u8 eir_create_adv_data(struct hci_dev *h - /* If flags would still be empty, then there is no need to - * include the "Flags" AD field". - */ -- if (flags) { -+ if (flags && (ad_len + eir_precalc_len(1) <= size)) { - ptr[0] = 0x02; - ptr[1] = EIR_FLAGS; - ptr[2] = flags; -@@ -316,7 +316,8 @@ skip_flags: - } - - /* Provide Tx Power only if we can provide a valid value for it */ -- if (adv_tx_power != HCI_TX_POWER_INVALID) { -+ if (adv_tx_power != HCI_TX_POWER_INVALID && -+ (ad_len + eir_precalc_len(1) <= size)) { - ptr[0] = 0x02; - ptr[1] = EIR_TX_POWER; - ptr[2] = (u8)adv_tx_power; -@@ -366,17 +367,19 @@ u8 eir_create_scan_rsp(struct hci_dev *h - - void *eir_get_service_data(u8 *eir, size_t eir_len, u16 uuid, size_t *len) - { -- while ((eir = eir_get_data(eir, eir_len, EIR_SERVICE_DATA, len))) { -+ size_t dlen; -+ -+ while ((eir = eir_get_data(eir, eir_len, EIR_SERVICE_DATA, &dlen))) { - u16 value = get_unaligned_le16(eir); - - if (uuid == value) { - if (len) -- *len -= 2; -+ *len = dlen - 2; - return &eir[2]; - } - -- eir += *len; -- eir_len -= *len; -+ eir += dlen; -+ eir_len -= dlen; - } - - return NULL; -diff -purNx .git BPI-Router-Linux-kernel/net/bluetooth/eir.h BPI-Router-Linux-kernel-6.16.12/net/bluetooth/eir.h ---- BPI-Router-Linux-kernel/net/bluetooth/eir.h 2025-10-22 13:53:23.619327191 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bluetooth/eir.h 2025-10-22 13:53:56.803167752 -0400 -@@ -9,7 +9,7 @@ - - void eir_create(struct hci_dev *hdev, u8 *data); - --u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr); -+u8 eir_create_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr, u8 size); - u8 eir_create_scan_rsp(struct hci_dev *hdev, u8 instance, u8 *ptr); - u8 eir_create_per_adv_data(struct hci_dev *hdev, u8 instance, u8 *ptr); - -diff -purNx .git BPI-Router-Linux-kernel/net/bluetooth/hci_conn.c BPI-Router-Linux-kernel-6.16.12/net/bluetooth/hci_conn.c ---- BPI-Router-Linux-kernel/net/bluetooth/hci_conn.c 2025-10-22 13:53:23.623327171 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bluetooth/hci_conn.c 2025-10-22 13:53:56.803167752 -0400 -@@ -149,8 +149,6 @@ static void hci_conn_cleanup(struct hci_ - - hci_chan_list_flush(conn); - -- hci_conn_hash_del(hdev, conn); -- - if (HCI_CONN_HANDLE_UNSET(conn->handle)) - ida_free(&hdev->unset_handle_ida, conn->handle); - -@@ -339,7 +337,8 @@ static int hci_enhanced_setup_sync(struc - case BT_CODEC_TRANSPARENT: - if (!find_next_esco_param(conn, esco_param_msbc, - ARRAY_SIZE(esco_param_msbc))) -- return false; -+ return -EINVAL; -+ - param = &esco_param_msbc[conn->attempt - 1]; - cp.tx_coding_format.id = 0x03; - cp.rx_coding_format.id = 0x03; -@@ -785,7 +784,7 @@ static int hci_le_big_terminate(struct h - d->sync_handle = conn->sync_handle; - - if (test_and_clear_bit(HCI_CONN_PA_SYNC, &conn->flags)) { -- hci_conn_hash_list_flag(hdev, find_bis, BIS_LINK, -+ hci_conn_hash_list_flag(hdev, find_bis, PA_LINK, - HCI_CONN_PA_SYNC, d); - - if (!d->count) -@@ -830,7 +829,17 @@ static void bis_cleanup(struct hci_conn - /* Check if ISO connection is a BIS and terminate advertising - * set and BIG if there are no other connections using it. - */ -- bis = hci_conn_hash_lookup_big(hdev, conn->iso_qos.bcast.big); -+ bis = hci_conn_hash_lookup_big_state(hdev, -+ conn->iso_qos.bcast.big, -+ BT_CONNECTED, -+ HCI_ROLE_MASTER); -+ if (bis) -+ return; -+ -+ bis = hci_conn_hash_lookup_big_state(hdev, -+ conn->iso_qos.bcast.big, -+ BT_CONNECT, -+ HCI_ROLE_MASTER); - if (bis) - return; - -@@ -914,6 +923,7 @@ static struct hci_conn *__hci_conn_add(s - break; - case CIS_LINK: - case BIS_LINK: -+ case PA_LINK: - if (hdev->iso_mtu) - /* Dedicated ISO Buffer exists */ - break; -@@ -979,6 +989,7 @@ static struct hci_conn *__hci_conn_add(s - break; - case CIS_LINK: - case BIS_LINK: -+ case PA_LINK: - /* conn->src should reflect the local identity address */ - hci_copy_identity_address(hdev, &conn->src, &conn->src_type); - -@@ -1033,7 +1044,6 @@ static struct hci_conn *__hci_conn_add(s - } - - hci_conn_init_sysfs(conn); -- - return conn; - } - -@@ -1077,6 +1087,7 @@ static void hci_conn_cleanup_child(struc - break; - case CIS_LINK: - case BIS_LINK: -+ case PA_LINK: - if ((conn->state != BT_CONNECTED && - !test_bit(HCI_CONN_CREATE_CIS, &conn->flags)) || - test_bit(HCI_CONN_BIG_CREATED, &conn->flags)) -@@ -1139,27 +1150,54 @@ void hci_conn_del(struct hci_conn *conn) - disable_delayed_work_sync(&conn->auto_accept_work); - disable_delayed_work_sync(&conn->idle_work); - -- if (conn->type == ACL_LINK) { -- /* Unacked frames */ -- hdev->acl_cnt += conn->sent; -- } else if (conn->type == LE_LINK) { -- cancel_delayed_work(&conn->le_conn_timeout); -+ /* Remove the connection from the list so unacked logic can detect when -+ * a certain pool is not being utilized. -+ */ -+ hci_conn_hash_del(hdev, conn); - -- if (hdev->le_pkts) -- hdev->le_cnt += conn->sent; -+ /* Handle unacked frames: -+ * -+ * - In case there are no connection, or if restoring the buffers -+ * considered in transist would overflow, restore all buffers to the -+ * pool. -+ * - Otherwise restore just the buffers considered in transit for the -+ * hci_conn -+ */ -+ switch (conn->type) { -+ case ACL_LINK: -+ if (!hci_conn_num(hdev, ACL_LINK) || -+ hdev->acl_cnt + conn->sent > hdev->acl_pkts) -+ hdev->acl_cnt = hdev->acl_pkts; - else - hdev->acl_cnt += conn->sent; -- } else { -- /* Unacked ISO frames */ -- if (conn->type == CIS_LINK || -- conn->type == BIS_LINK) { -- if (hdev->iso_pkts) -- hdev->iso_cnt += conn->sent; -- else if (hdev->le_pkts) -+ break; -+ case LE_LINK: -+ cancel_delayed_work(&conn->le_conn_timeout); -+ -+ if (hdev->le_pkts) { -+ if (!hci_conn_num(hdev, LE_LINK) || -+ hdev->le_cnt + conn->sent > hdev->le_pkts) -+ hdev->le_cnt = hdev->le_pkts; -+ else - hdev->le_cnt += conn->sent; -+ } else { -+ if ((!hci_conn_num(hdev, LE_LINK) && -+ !hci_conn_num(hdev, ACL_LINK)) || -+ hdev->acl_cnt + conn->sent > hdev->acl_pkts) -+ hdev->acl_cnt = hdev->acl_pkts; - else - hdev->acl_cnt += conn->sent; - } -+ break; -+ case CIS_LINK: -+ case BIS_LINK: -+ case PA_LINK: -+ if (!hci_iso_count(hdev) || -+ hdev->iso_cnt + conn->sent > hdev->iso_pkts) -+ hdev->iso_cnt = hdev->iso_pkts; -+ else -+ hdev->iso_cnt += conn->sent; -+ break; - } - - skb_queue_purge(&conn->data_q); -@@ -1501,8 +1539,8 @@ static int qos_set_bis(struct hci_dev *h - - /* This function requires the caller holds hdev->lock */ - static struct hci_conn *hci_add_bis(struct hci_dev *hdev, bdaddr_t *dst, -- struct bt_iso_qos *qos, __u8 base_len, -- __u8 *base) -+ __u8 sid, struct bt_iso_qos *qos, -+ __u8 base_len, __u8 *base) - { - struct hci_conn *conn; - int err; -@@ -1543,6 +1581,7 @@ static struct hci_conn *hci_add_bis(stru - return conn; - - conn->state = BT_CONNECT; -+ conn->sid = sid; - - hci_conn_hold(conn); - return conn; -@@ -2062,7 +2101,8 @@ static int create_big_sync(struct hci_de - if (qos->bcast.bis) - sync_interval = interval * 4; - -- err = hci_start_per_adv_sync(hdev, qos->bcast.bis, conn->le_per_adv_data_len, -+ err = hci_start_per_adv_sync(hdev, qos->bcast.bis, conn->sid, -+ conn->le_per_adv_data_len, - conn->le_per_adv_data, flags, interval, - interval, sync_interval); - if (err) -@@ -2079,7 +2119,7 @@ struct hci_conn *hci_pa_create_sync(stru - - bt_dev_dbg(hdev, "dst %pMR type %d sid %d", dst, dst_type, sid); - -- conn = hci_conn_add_unset(hdev, BIS_LINK, dst, HCI_ROLE_SLAVE); -+ conn = hci_conn_add_unset(hdev, PA_LINK, dst, HCI_ROLE_SLAVE); - if (IS_ERR(conn)) - return conn; - -@@ -2134,7 +2174,7 @@ static void create_big_complete(struct h - } - } - --struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, -+struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, __u8 sid, - struct bt_iso_qos *qos, - __u8 base_len, __u8 *base) - { -@@ -2144,7 +2184,8 @@ struct hci_conn *hci_bind_bis(struct hci - struct hci_link *link; - - /* Look for any BIS that is open for rebinding */ -- conn = hci_conn_hash_lookup_big_state(hdev, qos->bcast.big, BT_OPEN); -+ conn = hci_conn_hash_lookup_big_state(hdev, qos->bcast.big, BT_OPEN, -+ HCI_ROLE_MASTER); - if (conn) { - memcpy(qos, &conn->iso_qos, sizeof(*qos)); - conn->state = BT_CONNECTED; -@@ -2156,7 +2197,7 @@ struct hci_conn *hci_bind_bis(struct hci - base, base_len); - - /* We need hci_conn object using the BDADDR_ANY as dst */ -- conn = hci_add_bis(hdev, dst, qos, base_len, eir); -+ conn = hci_add_bis(hdev, dst, sid, qos, base_len, eir); - if (IS_ERR(conn)) - return conn; - -@@ -2207,20 +2248,35 @@ static void bis_mark_per_adv(struct hci_ - } - - struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst, -- __u8 dst_type, struct bt_iso_qos *qos, -+ __u8 dst_type, __u8 sid, -+ struct bt_iso_qos *qos, - __u8 base_len, __u8 *base) - { - struct hci_conn *conn; - int err; - struct iso_list_data data; - -- conn = hci_bind_bis(hdev, dst, qos, base_len, base); -+ conn = hci_bind_bis(hdev, dst, sid, qos, base_len, base); - if (IS_ERR(conn)) - return conn; - - if (conn->state == BT_CONNECTED) - return conn; - -+ /* Check if SID needs to be allocated then search for the first -+ * available. -+ */ -+ if (conn->sid == HCI_SID_INVALID) { -+ u8 sid; -+ -+ for (sid = 0; sid <= 0x0f; sid++) { -+ if (!hci_find_adv_sid(hdev, sid)) { -+ conn->sid = sid; -+ break; -+ } -+ } -+ } -+ - data.big = qos->bcast.big; - data.bis = qos->bcast.bis; - -@@ -2962,6 +3018,7 @@ void hci_conn_tx_queue(struct hci_conn * - switch (conn->type) { - case CIS_LINK: - case BIS_LINK: -+ case PA_LINK: - case ACL_LINK: - case LE_LINK: - break; -diff -purNx .git BPI-Router-Linux-kernel/net/bluetooth/hci_core.c BPI-Router-Linux-kernel-6.16.12/net/bluetooth/hci_core.c ---- BPI-Router-Linux-kernel/net/bluetooth/hci_core.c 2025-10-22 13:53:23.623327171 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bluetooth/hci_core.c 2025-10-22 13:53:56.803167752 -0400 -@@ -64,7 +64,7 @@ static DEFINE_IDA(hci_index_ida); - - /* Get HCI device by index. - * Device is held on return. */ --struct hci_dev *hci_dev_get(int index) -+static struct hci_dev *__hci_dev_get(int index, int *srcu_index) - { - struct hci_dev *hdev = NULL, *d; - -@@ -77,6 +77,8 @@ struct hci_dev *hci_dev_get(int index) - list_for_each_entry(d, &hci_dev_list, list) { - if (d->id == index) { - hdev = hci_dev_hold(d); -+ if (srcu_index) -+ *srcu_index = srcu_read_lock(&d->srcu); - break; - } - } -@@ -84,6 +86,22 @@ struct hci_dev *hci_dev_get(int index) - return hdev; - } - -+struct hci_dev *hci_dev_get(int index) -+{ -+ return __hci_dev_get(index, NULL); -+} -+ -+static struct hci_dev *hci_dev_get_srcu(int index, int *srcu_index) -+{ -+ return __hci_dev_get(index, srcu_index); -+} -+ -+static void hci_dev_put_srcu(struct hci_dev *hdev, int srcu_index) -+{ -+ srcu_read_unlock(&hdev->srcu, srcu_index); -+ hci_dev_put(hdev); -+} -+ - /* ---- Inquiry support ---- */ - - bool hci_discovery_active(struct hci_dev *hdev) -@@ -568,9 +586,9 @@ static int hci_dev_do_reset(struct hci_d - int hci_dev_reset(__u16 dev) - { - struct hci_dev *hdev; -- int err; -+ int err, srcu_index; - -- hdev = hci_dev_get(dev); -+ hdev = hci_dev_get_srcu(dev, &srcu_index); - if (!hdev) - return -ENODEV; - -@@ -592,7 +610,7 @@ int hci_dev_reset(__u16 dev) - err = hci_dev_do_reset(hdev); - - done: -- hci_dev_put(hdev); -+ hci_dev_put_srcu(hdev, srcu_index); - return err; - } - -@@ -1585,6 +1603,19 @@ struct adv_info *hci_find_adv_instance(s - } - - /* This function requires the caller holds hdev->lock */ -+struct adv_info *hci_find_adv_sid(struct hci_dev *hdev, u8 sid) -+{ -+ struct adv_info *adv; -+ -+ list_for_each_entry(adv, &hdev->adv_instances, list) { -+ if (adv->sid == sid) -+ return adv; -+ } -+ -+ return NULL; -+} -+ -+/* This function requires the caller holds hdev->lock */ - struct adv_info *hci_get_next_instance(struct hci_dev *hdev, u8 instance) - { - struct adv_info *cur_instance; -@@ -1736,7 +1767,7 @@ struct adv_info *hci_add_adv_instance(st - } - - /* This function requires the caller holds hdev->lock */ --struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance, -+struct adv_info *hci_add_per_instance(struct hci_dev *hdev, u8 instance, u8 sid, - u32 flags, u8 data_len, u8 *data, - u32 min_interval, u32 max_interval) - { -@@ -1748,6 +1779,7 @@ struct adv_info *hci_add_per_instance(st - if (IS_ERR(adv)) - return adv; - -+ adv->sid = sid; - adv->periodic = true; - adv->per_adv_data_len = data_len; - -@@ -1877,10 +1909,8 @@ void hci_free_adv_monitor(struct hci_dev - if (monitor->handle) - idr_remove(&hdev->adv_monitors_idr, monitor->handle); - -- if (monitor->state != ADV_MONITOR_STATE_NOT_REGISTERED) { -+ if (monitor->state != ADV_MONITOR_STATE_NOT_REGISTERED) - hdev->adv_monitors_cnt--; -- mgmt_adv_monitor_removed(hdev, monitor->handle); -- } - - kfree(monitor); - } -@@ -2421,6 +2451,11 @@ struct hci_dev *hci_alloc_dev_priv(int s - if (!hdev) - return NULL; - -+ if (init_srcu_struct(&hdev->srcu)) { -+ kfree(hdev); -+ return NULL; -+ } -+ - hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1); - hdev->esco_type = (ESCO_HV1); - hdev->link_mode = (HCI_LM_ACCEPT); -@@ -2487,6 +2522,7 @@ struct hci_dev *hci_alloc_dev_priv(int s - - mutex_init(&hdev->lock); - mutex_init(&hdev->req_lock); -+ mutex_init(&hdev->mgmt_pending_lock); - - ida_init(&hdev->unset_handle_ida); - -@@ -2618,7 +2654,7 @@ int hci_register_dev(struct hci_dev *hde - /* Devices that are marked for raw-only usage are unconfigured - * and should not be included in normal operation. - */ -- if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) -+ if (hci_test_quirk(hdev, HCI_QUIRK_RAW_DEVICE)) - hci_dev_set_flag(hdev, HCI_UNCONFIGURED); - - /* Mark Remote Wakeup connection flag as supported if driver has wakeup -@@ -2665,6 +2701,9 @@ void hci_unregister_dev(struct hci_dev * - list_del(&hdev->list); - write_unlock(&hci_dev_list_lock); - -+ synchronize_srcu(&hdev->srcu); -+ cleanup_srcu_struct(&hdev->srcu); -+ - disable_work_sync(&hdev->rx_work); - disable_work_sync(&hdev->cmd_work); - disable_work_sync(&hdev->tx_work); -@@ -2745,7 +2784,7 @@ int hci_register_suspend_notifier(struct - int ret = 0; - - if (!hdev->suspend_notifier.notifier_call && -- !test_bit(HCI_QUIRK_NO_SUSPEND_NOTIFIER, &hdev->quirks)) { -+ !hci_test_quirk(hdev, HCI_QUIRK_NO_SUSPEND_NOTIFIER)) { - hdev->suspend_notifier.notifier_call = hci_suspend_notifier; - ret = register_pm_notifier(&hdev->suspend_notifier); - } -@@ -2899,12 +2938,14 @@ int hci_recv_frame(struct hci_dev *hdev, - case HCI_ACLDATA_PKT: - /* Detect if ISO packet has been sent as ACL */ - if (hci_conn_num(hdev, CIS_LINK) || -- hci_conn_num(hdev, BIS_LINK)) { -+ hci_conn_num(hdev, BIS_LINK) || -+ hci_conn_num(hdev, PA_LINK)) { - __u16 handle = __le16_to_cpu(hci_acl_hdr(skb)->handle); - __u8 type; - - type = hci_conn_lookup_type(hdev, hci_handle(handle)); -- if (type == CIS_LINK || type == BIS_LINK) -+ if (type == CIS_LINK || type == BIS_LINK || -+ type == PA_LINK) - hci_skb_pkt_type(skb) = HCI_ISODATA_PKT; - } - break; -@@ -3359,6 +3400,7 @@ static inline void hci_quote_sent(struct - break; - case CIS_LINK: - case BIS_LINK: -+ case PA_LINK: - cnt = hdev->iso_mtu ? hdev->iso_cnt : - hdev->le_mtu ? hdev->le_cnt : hdev->acl_cnt; - break; -@@ -3372,7 +3414,7 @@ static inline void hci_quote_sent(struct - } - - static struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, -- __u8 type2, int *quote) -+ int *quote) - { - struct hci_conn_hash *h = &hdev->conn_hash; - struct hci_conn *conn = NULL, *c; -@@ -3384,7 +3426,7 @@ static struct hci_conn *hci_low_sent(str - rcu_read_lock(); - - list_for_each_entry_rcu(c, &h->list, list) { -- if ((c->type != type && c->type != type2) || -+ if (c->type != type || - skb_queue_empty(&c->data_q)) - continue; - -@@ -3417,23 +3459,18 @@ static void hci_link_tx_to(struct hci_de - - bt_dev_err(hdev, "link tx timeout"); - -- rcu_read_lock(); -+ hci_dev_lock(hdev); - - /* Kill stalled connections */ -- list_for_each_entry_rcu(c, &h->list, list) { -+ list_for_each_entry(c, &h->list, list) { - if (c->type == type && c->sent) { - bt_dev_err(hdev, "killing stalled connection %pMR", - &c->dst); -- /* hci_disconnect might sleep, so, we have to release -- * the RCU read lock before calling it. -- */ -- rcu_read_unlock(); - hci_disconnect(c, HCI_ERROR_REMOTE_USER_TERM); -- rcu_read_lock(); - } - } - -- rcu_read_unlock(); -+ hci_dev_unlock(hdev); - } - - static struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type, -@@ -3593,7 +3630,7 @@ static void hci_sched_sco(struct hci_dev - else - cnt = &hdev->sco_cnt; - -- while (*cnt && (conn = hci_low_sent(hdev, type, type, "e))) { -+ while (*cnt && (conn = hci_low_sent(hdev, type, "e))) { - while (quote-- && (skb = skb_dequeue(&conn->data_q))) { - BT_DBG("skb %p len %d", skb, skb->len); - hci_send_conn_frame(hdev, conn, skb); -@@ -3712,8 +3749,8 @@ static void hci_sched_le(struct hci_dev - hci_prio_recalculate(hdev, LE_LINK); - } - --/* Schedule CIS */ --static void hci_sched_iso(struct hci_dev *hdev) -+/* Schedule iso */ -+static void hci_sched_iso(struct hci_dev *hdev, __u8 type) - { - struct hci_conn *conn; - struct sk_buff *skb; -@@ -3721,14 +3758,12 @@ static void hci_sched_iso(struct hci_dev - - BT_DBG("%s", hdev->name); - -- if (!hci_conn_num(hdev, CIS_LINK) && -- !hci_conn_num(hdev, BIS_LINK)) -+ if (!hci_conn_num(hdev, type)) - return; - - cnt = hdev->iso_pkts ? &hdev->iso_cnt : - hdev->le_pkts ? &hdev->le_cnt : &hdev->acl_cnt; -- while (*cnt && (conn = hci_low_sent(hdev, CIS_LINK, BIS_LINK, -- "e))) { -+ while (*cnt && (conn = hci_low_sent(hdev, type, "e))) { - while (quote-- && (skb = skb_dequeue(&conn->data_q))) { - BT_DBG("skb %p len %d", skb, skb->len); - hci_send_conn_frame(hdev, conn, skb); -@@ -3753,7 +3788,9 @@ static void hci_tx_work(struct work_stru - /* Schedule queues and send stuff to HCI driver */ - hci_sched_sco(hdev, SCO_LINK); - hci_sched_sco(hdev, ESCO_LINK); -- hci_sched_iso(hdev); -+ hci_sched_iso(hdev, CIS_LINK); -+ hci_sched_iso(hdev, BIS_LINK); -+ hci_sched_iso(hdev, PA_LINK); - hci_sched_acl(hdev); - hci_sched_le(hdev); - } -diff -purNx .git BPI-Router-Linux-kernel/net/bluetooth/hci_debugfs.c BPI-Router-Linux-kernel-6.16.12/net/bluetooth/hci_debugfs.c ---- BPI-Router-Linux-kernel/net/bluetooth/hci_debugfs.c 2025-10-22 13:53:23.623327171 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bluetooth/hci_debugfs.c 2025-10-22 13:53:56.803167752 -0400 -@@ -38,7 +38,7 @@ static ssize_t __name ## _read(struct fi - struct hci_dev *hdev = file->private_data; \ - char buf[3]; \ - \ -- buf[0] = test_bit(__quirk, &hdev->quirks) ? 'Y' : 'N'; \ -+ buf[0] = test_bit(__quirk, hdev->quirk_flags) ? 'Y' : 'N'; \ - buf[1] = '\n'; \ - buf[2] = '\0'; \ - return simple_read_from_buffer(user_buf, count, ppos, buf, 2); \ -@@ -59,10 +59,10 @@ static ssize_t __name ## _write(struct f - if (err) \ - return err; \ - \ -- if (enable == test_bit(__quirk, &hdev->quirks)) \ -+ if (enable == test_bit(__quirk, hdev->quirk_flags)) \ - return -EALREADY; \ - \ -- change_bit(__quirk, &hdev->quirks); \ -+ change_bit(__quirk, hdev->quirk_flags); \ - \ - return count; \ - } \ -@@ -1356,7 +1356,7 @@ static ssize_t vendor_diag_write(struct - * for the vendor callback. Instead just store the desired value and - * the setting will be programmed when the controller gets powered on. - */ -- if (test_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks) && -+ if (hci_test_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_DIAG) && - (!test_bit(HCI_RUNNING, &hdev->flags) || - hci_dev_test_flag(hdev, HCI_USER_CHANNEL))) - goto done; -diff -purNx .git BPI-Router-Linux-kernel/net/bluetooth/hci_event.c BPI-Router-Linux-kernel-6.16.12/net/bluetooth/hci_event.c ---- BPI-Router-Linux-kernel/net/bluetooth/hci_event.c 2025-10-22 13:53:23.623327171 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bluetooth/hci_event.c 2025-10-22 13:53:56.803167752 -0400 -@@ -908,8 +908,8 @@ static u8 hci_cc_read_local_ext_features - return rp->status; - - if (hdev->max_page < rp->max_page) { -- if (test_bit(HCI_QUIRK_BROKEN_LOCAL_EXT_FEATURES_PAGE_2, -- &hdev->quirks)) -+ if (hci_test_quirk(hdev, -+ HCI_QUIRK_BROKEN_LOCAL_EXT_FEATURES_PAGE_2)) - bt_dev_warn(hdev, "broken local ext features page 2"); - else - hdev->max_page = rp->max_page; -@@ -936,7 +936,7 @@ static u8 hci_cc_read_buffer_size(struct - hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); - hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); - -- if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { -+ if (hci_test_quirk(hdev, HCI_QUIRK_FIXUP_BUFFER_SIZE)) { - hdev->sco_mtu = 64; - hdev->sco_pkts = 8; - } -@@ -2150,40 +2150,6 @@ static u8 hci_cc_set_adv_param(struct hc - return rp->status; - } - --static u8 hci_cc_set_ext_adv_param(struct hci_dev *hdev, void *data, -- struct sk_buff *skb) --{ -- struct hci_rp_le_set_ext_adv_params *rp = data; -- struct hci_cp_le_set_ext_adv_params *cp; -- struct adv_info *adv_instance; -- -- bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); -- -- if (rp->status) -- return rp->status; -- -- cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_PARAMS); -- if (!cp) -- return rp->status; -- -- hci_dev_lock(hdev); -- hdev->adv_addr_type = cp->own_addr_type; -- if (!cp->handle) { -- /* Store in hdev for instance 0 */ -- hdev->adv_tx_power = rp->tx_power; -- } else { -- adv_instance = hci_find_adv_instance(hdev, cp->handle); -- if (adv_instance) -- adv_instance->tx_power = rp->tx_power; -- } -- /* Update adv data as tx power is known now */ -- hci_update_adv_data(hdev, cp->handle); -- -- hci_dev_unlock(hdev); -- -- return rp->status; --} -- - static u8 hci_cc_read_rssi(struct hci_dev *hdev, void *data, - struct sk_buff *skb) - { -@@ -2737,7 +2703,7 @@ static void hci_cs_disconnect(struct hci - if (!conn) - goto unlock; - -- if (status) { -+ if (status && status != HCI_ERROR_UNKNOWN_CONN_ID) { - mgmt_disconnect_failed(hdev, &conn->dst, conn->type, - conn->dst_type, status); - -@@ -2752,6 +2718,12 @@ static void hci_cs_disconnect(struct hci - goto done; - } - -+ /* During suspend, mark connection as closed immediately -+ * since we might not receive HCI_EV_DISCONN_COMPLETE -+ */ -+ if (hdev->suspended) -+ conn->state = BT_CLOSED; -+ - mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags); - - if (conn->type == ACL_LINK) { -@@ -3005,7 +2977,7 @@ static void hci_inquiry_complete_evt(str - * state to indicate completion. - */ - if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) || -- !test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks)) -+ !hci_test_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY)) - hci_discovery_set_state(hdev, DISCOVERY_STOPPED); - goto unlock; - } -@@ -3024,7 +2996,7 @@ static void hci_inquiry_complete_evt(str - * state to indicate completion. - */ - if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) || -- !test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks)) -+ !hci_test_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY)) - hci_discovery_set_state(hdev, DISCOVERY_STOPPED); - } - -@@ -3115,8 +3087,18 @@ static void hci_conn_complete_evt(struct - - hci_dev_lock(hdev); - -+ /* Check for existing connection: -+ * -+ * 1. If it doesn't exist then it must be receiver/slave role. -+ * 2. If it does exist confirm that it is connecting/BT_CONNECT in case -+ * of initiator/master role since there could be a collision where -+ * either side is attempting to connect or something like a fuzzing -+ * testing is trying to play tricks to destroy the hcon object before -+ * it even attempts to connect (e.g. hcon->state == BT_OPEN). -+ */ - conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); -- if (!conn) { -+ if (!conn || -+ (conn->role == HCI_ROLE_MASTER && conn->state != BT_CONNECT)) { - /* In case of error status and there is no connection pending - * just unlock as there is nothing to cleanup. - */ -@@ -3648,8 +3630,7 @@ static void hci_encrypt_change_evt(struc - /* We skip the WRITE_AUTH_PAYLOAD_TIMEOUT for ATS2851 based controllers - * to avoid unexpected SMP command errors when pairing. - */ -- if (test_bit(HCI_QUIRK_BROKEN_WRITE_AUTH_PAYLOAD_TIMEOUT, -- &hdev->quirks)) -+ if (hci_test_quirk(hdev, HCI_QUIRK_BROKEN_WRITE_AUTH_PAYLOAD_TIMEOUT)) - goto notify; - - /* Set the default Authenticated Payload Timeout after -@@ -4164,8 +4145,6 @@ static const struct hci_cc { - HCI_CC(HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS, - hci_cc_le_read_num_adv_sets, - sizeof(struct hci_rp_le_read_num_supported_adv_sets)), -- HCI_CC(HCI_OP_LE_SET_EXT_ADV_PARAMS, hci_cc_set_ext_adv_param, -- sizeof(struct hci_rp_le_set_ext_adv_params)), - HCI_CC_STATUS(HCI_OP_LE_SET_EXT_ADV_ENABLE, - hci_cc_le_set_ext_adv_enable), - HCI_CC_STATUS(HCI_OP_LE_SET_ADV_SET_RAND_ADDR, -@@ -4422,6 +4401,8 @@ static void hci_num_comp_pkts_evt(struct - - bt_dev_dbg(hdev, "num %d", ev->num); - -+ hci_dev_lock(hdev); -+ - for (i = 0; i < ev->num; i++) { - struct hci_comp_pkts_info *info = &ev->handles[i]; - struct hci_conn *conn; -@@ -4435,7 +4416,17 @@ static void hci_num_comp_pkts_evt(struct - if (!conn) - continue; - -- conn->sent -= count; -+ /* Check if there is really enough packets outstanding before -+ * attempting to decrease the sent counter otherwise it could -+ * underflow.. -+ */ -+ if (conn->sent >= count) { -+ conn->sent -= count; -+ } else { -+ bt_dev_warn(hdev, "hcon %p sent %u < count %u", -+ conn, conn->sent, count); -+ conn->sent = 0; -+ } - - for (i = 0; i < count; ++i) - hci_conn_tx_dequeue(conn); -@@ -4469,6 +4460,7 @@ static void hci_num_comp_pkts_evt(struct - - case CIS_LINK: - case BIS_LINK: -+ case PA_LINK: - if (hdev->iso_pkts) { - hdev->iso_cnt += count; - if (hdev->iso_cnt > hdev->iso_pkts) -@@ -4492,6 +4484,8 @@ static void hci_num_comp_pkts_evt(struct - } - - queue_work(hdev->workqueue, &hdev->tx_work); -+ -+ hci_dev_unlock(hdev); - } - - static void hci_mode_change_evt(struct hci_dev *hdev, void *data, -@@ -5654,8 +5648,18 @@ static void le_conn_complete_evt(struct - */ - hci_dev_clear_flag(hdev, HCI_LE_ADV); - -- conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, bdaddr); -- if (!conn) { -+ /* Check for existing connection: -+ * -+ * 1. If it doesn't exist then use the role to create a new object. -+ * 2. If it does exist confirm that it is connecting/BT_CONNECT in case -+ * of initiator/master role since there could be a collision where -+ * either side is attempting to connect or something like a fuzzing -+ * testing is trying to play tricks to destroy the hcon object before -+ * it even attempts to connect (e.g. hcon->state == BT_OPEN). -+ */ -+ conn = hci_conn_hash_lookup_role(hdev, LE_LINK, role, bdaddr); -+ if (!conn || -+ (conn->role == HCI_ROLE_MASTER && conn->state != BT_CONNECT)) { - /* In case of error status and there is no connection pending - * just unlock as there is nothing to cleanup. - */ -@@ -5950,7 +5954,7 @@ static struct hci_conn *check_pending_le - * while we have an existing one in peripheral role. - */ - if (hdev->conn_hash.le_num_peripheral > 0 && -- (test_bit(HCI_QUIRK_BROKEN_LE_STATES, &hdev->quirks) || -+ (hci_test_quirk(hdev, HCI_QUIRK_BROKEN_LE_STATES) || - !(hdev->le_states[3] & 0x10))) - return NULL; - -@@ -6276,6 +6280,11 @@ static void hci_le_adv_report_evt(struct - - static u8 ext_evt_type_to_legacy(struct hci_dev *hdev, u16 evt_type) - { -+ u16 pdu_type = evt_type & ~LE_EXT_ADV_DATA_STATUS_MASK; -+ -+ if (!pdu_type) -+ return LE_ADV_NONCONN_IND; -+ - if (evt_type & LE_EXT_ADV_LEGACY_PDU) { - switch (evt_type) { - case LE_LEGACY_ADV_IND: -@@ -6307,8 +6316,7 @@ static u8 ext_evt_type_to_legacy(struct - if (evt_type & LE_EXT_ADV_SCAN_IND) - return LE_ADV_SCAN_IND; - -- if (evt_type == LE_EXT_ADV_NON_CONN_IND || -- evt_type & LE_EXT_ADV_DIRECT_IND) -+ if (evt_type & LE_EXT_ADV_DIRECT_IND) - return LE_ADV_NONCONN_IND; - - invalid: -@@ -6346,8 +6354,8 @@ static void hci_le_ext_adv_report_evt(st - evt_type = __le16_to_cpu(info->type) & LE_EXT_ADV_EVT_TYPE_MASK; - legacy_evt_type = ext_evt_type_to_legacy(hdev, evt_type); - -- if (test_bit(HCI_QUIRK_FIXUP_LE_EXT_ADV_REPORT_PHY, -- &hdev->quirks)) { -+ if (hci_test_quirk(hdev, -+ HCI_QUIRK_FIXUP_LE_EXT_ADV_REPORT_PHY)) { - info->primary_phy &= 0x1f; - info->secondary_phy &= 0x1f; - } -@@ -6414,7 +6422,7 @@ static void hci_le_pa_sync_estabilished_ - conn->sync_handle = le16_to_cpu(ev->handle); - conn->sid = HCI_SID_INVALID; - -- mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, BIS_LINK, -+ mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, PA_LINK, - &flags); - if (!(mask & HCI_LM_ACCEPT)) { - hci_le_pa_term_sync(hdev, ev->handle); -@@ -6425,7 +6433,7 @@ static void hci_le_pa_sync_estabilished_ - goto unlock; - - /* Add connection to indicate PA sync event */ -- pa_sync = hci_conn_add_unset(hdev, BIS_LINK, BDADDR_ANY, -+ pa_sync = hci_conn_add_unset(hdev, PA_LINK, BDADDR_ANY, - HCI_ROLE_SLAVE); - - if (IS_ERR(pa_sync)) -@@ -6456,7 +6464,7 @@ static void hci_le_per_adv_report_evt(st - - hci_dev_lock(hdev); - -- mask |= hci_proto_connect_ind(hdev, BDADDR_ANY, BIS_LINK, &flags); -+ mask |= hci_proto_connect_ind(hdev, BDADDR_ANY, PA_LINK, &flags); - if (!(mask & HCI_LM_ACCEPT)) - goto unlock; - -@@ -6777,8 +6785,8 @@ static void hci_le_cis_estabilished_evt( - qos->ucast.out.latency = - DIV_ROUND_CLOSEST(get_unaligned_le24(ev->p_latency), - 1000); -- qos->ucast.in.sdu = le16_to_cpu(ev->c_mtu); -- qos->ucast.out.sdu = le16_to_cpu(ev->p_mtu); -+ qos->ucast.in.sdu = ev->c_bn ? le16_to_cpu(ev->c_mtu) : 0; -+ qos->ucast.out.sdu = ev->p_bn ? le16_to_cpu(ev->p_mtu) : 0; - qos->ucast.in.phy = ev->c_phy; - qos->ucast.out.phy = ev->p_phy; - break; -@@ -6792,8 +6800,8 @@ static void hci_le_cis_estabilished_evt( - qos->ucast.in.latency = - DIV_ROUND_CLOSEST(get_unaligned_le24(ev->p_latency), - 1000); -- qos->ucast.out.sdu = le16_to_cpu(ev->c_mtu); -- qos->ucast.in.sdu = le16_to_cpu(ev->p_mtu); -+ qos->ucast.out.sdu = ev->c_bn ? le16_to_cpu(ev->c_mtu) : 0; -+ qos->ucast.in.sdu = ev->p_bn ? le16_to_cpu(ev->p_mtu) : 0; - qos->ucast.out.phy = ev->c_phy; - qos->ucast.in.phy = ev->p_phy; - break; -@@ -6913,7 +6921,8 @@ static void hci_le_create_big_complete_e - - /* Connect all BISes that are bound to the BIG */ - while ((conn = hci_conn_hash_lookup_big_state(hdev, ev->handle, -- BT_BOUND))) { -+ BT_BOUND, -+ HCI_ROLE_MASTER))) { - if (ev->status) { - hci_connect_cfm(conn, ev->status); - hci_conn_del(conn); -@@ -6988,9 +6997,14 @@ static void hci_le_big_sync_established_ - continue; - } - -- if (ev->status != 0x42) -+ if (ev->status != 0x42) { - /* Mark PA sync as established */ - set_bit(HCI_CONN_PA_SYNC, &bis->flags); -+ /* Reset cleanup callback of PA Sync so it doesn't -+ * terminate the sync when deleting the connection. -+ */ -+ conn->cleanup = NULL; -+ } - - bis->sync_handle = conn->sync_handle; - bis->iso_qos.bcast.big = ev->handle; -@@ -7002,7 +7016,10 @@ static void hci_le_big_sync_established_ - bis->iso_qos.bcast.in.sdu = le16_to_cpu(ev->max_pdu); - - if (!ev->status) { -+ bis->state = BT_CONNECTED; - set_bit(HCI_CONN_BIG_SYNC, &bis->flags); -+ hci_debugfs_create_conn(bis); -+ hci_conn_add_sysfs(bis); - hci_iso_setup_path(bis); - } - } -@@ -7026,6 +7043,42 @@ unlock: - hci_dev_unlock(hdev); - } - -+static void hci_le_big_sync_lost_evt(struct hci_dev *hdev, void *data, -+ struct sk_buff *skb) -+{ -+ struct hci_evt_le_big_sync_lost *ev = data; -+ struct hci_conn *bis, *conn; -+ bool mgmt_conn; -+ -+ bt_dev_dbg(hdev, "big handle 0x%2.2x", ev->handle); -+ -+ hci_dev_lock(hdev); -+ -+ /* Delete the pa sync connection */ -+ bis = hci_conn_hash_lookup_pa_sync_big_handle(hdev, ev->handle); -+ if (bis) { -+ conn = hci_conn_hash_lookup_pa_sync_handle(hdev, -+ bis->sync_handle); -+ if (conn) -+ hci_conn_del(conn); -+ } -+ -+ /* Delete each bis connection */ -+ while ((bis = hci_conn_hash_lookup_big_state(hdev, ev->handle, -+ BT_CONNECTED, -+ HCI_ROLE_SLAVE))) { -+ mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &bis->flags); -+ mgmt_device_disconnected(hdev, &bis->dst, bis->type, bis->dst_type, -+ ev->reason, mgmt_conn); -+ -+ clear_bit(HCI_CONN_BIG_SYNC, &bis->flags); -+ hci_disconn_cfm(bis, ev->reason); -+ hci_conn_del(bis); -+ } -+ -+ hci_dev_unlock(hdev); -+} -+ - static void hci_le_big_info_adv_report_evt(struct hci_dev *hdev, void *data, - struct sk_buff *skb) - { -@@ -7149,6 +7202,11 @@ static const struct hci_le_ev { - hci_le_big_sync_established_evt, - sizeof(struct hci_evt_le_big_sync_estabilished), - HCI_MAX_EVENT_SIZE), -+ /* [0x1e = HCI_EVT_LE_BIG_SYNC_LOST] */ -+ HCI_LE_EV_VL(HCI_EVT_LE_BIG_SYNC_LOST, -+ hci_le_big_sync_lost_evt, -+ sizeof(struct hci_evt_le_big_sync_lost), -+ HCI_MAX_EVENT_SIZE), - /* [0x22 = HCI_EVT_LE_BIG_INFO_ADV_REPORT] */ - HCI_LE_EV_VL(HCI_EVT_LE_BIG_INFO_ADV_REPORT, - hci_le_big_info_adv_report_evt, -diff -purNx .git BPI-Router-Linux-kernel/net/bluetooth/hci_sock.c BPI-Router-Linux-kernel-6.16.12/net/bluetooth/hci_sock.c ---- BPI-Router-Linux-kernel/net/bluetooth/hci_sock.c 2025-10-22 13:53:23.623327171 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bluetooth/hci_sock.c 2025-10-22 13:53:56.803167752 -0400 -@@ -118,7 +118,7 @@ static void hci_sock_free_cookie(struct - int id = hci_pi(sk)->cookie; - - if (id) { -- hci_pi(sk)->cookie = 0xffffffff; -+ hci_pi(sk)->cookie = 0; - ida_free(&sock_cookie_ida, id); - } - } -diff -purNx .git BPI-Router-Linux-kernel/net/bluetooth/hci_sync.c BPI-Router-Linux-kernel-6.16.12/net/bluetooth/hci_sync.c ---- BPI-Router-Linux-kernel/net/bluetooth/hci_sync.c 2025-10-22 13:53:23.623327171 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bluetooth/hci_sync.c 2025-10-22 13:53:56.803167752 -0400 -@@ -393,7 +393,7 @@ static void le_scan_disable(struct work_ - if (hdev->discovery.type != DISCOV_TYPE_INTERLEAVED) - goto _return; - -- if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks)) { -+ if (hci_test_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY)) { - if (!test_bit(HCI_INQUIRY, &hdev->flags) && - hdev->discovery.state != DISCOVERY_RESOLVING) - goto discov_stopped; -@@ -1205,9 +1205,126 @@ static int hci_set_adv_set_random_addr_s - sizeof(cp), &cp, HCI_CMD_TIMEOUT); - } - -+static int -+hci_set_ext_adv_params_sync(struct hci_dev *hdev, struct adv_info *adv, -+ const struct hci_cp_le_set_ext_adv_params *cp, -+ struct hci_rp_le_set_ext_adv_params *rp) -+{ -+ struct sk_buff *skb; -+ -+ skb = __hci_cmd_sync(hdev, HCI_OP_LE_SET_EXT_ADV_PARAMS, sizeof(*cp), -+ cp, HCI_CMD_TIMEOUT); -+ -+ /* If command return a status event, skb will be set to -ENODATA */ -+ if (skb == ERR_PTR(-ENODATA)) -+ return 0; -+ -+ if (IS_ERR(skb)) { -+ bt_dev_err(hdev, "Opcode 0x%4.4x failed: %ld", -+ HCI_OP_LE_SET_EXT_ADV_PARAMS, PTR_ERR(skb)); -+ return PTR_ERR(skb); -+ } -+ -+ if (skb->len != sizeof(*rp)) { -+ bt_dev_err(hdev, "Invalid response length for 0x%4.4x: %u", -+ HCI_OP_LE_SET_EXT_ADV_PARAMS, skb->len); -+ kfree_skb(skb); -+ return -EIO; -+ } -+ -+ memcpy(rp, skb->data, sizeof(*rp)); -+ kfree_skb(skb); -+ -+ if (!rp->status) { -+ hdev->adv_addr_type = cp->own_addr_type; -+ if (!cp->handle) { -+ /* Store in hdev for instance 0 */ -+ hdev->adv_tx_power = rp->tx_power; -+ } else if (adv) { -+ adv->tx_power = rp->tx_power; -+ } -+ } -+ -+ return rp->status; -+} -+ -+static int hci_set_ext_adv_data_sync(struct hci_dev *hdev, u8 instance) -+{ -+ DEFINE_FLEX(struct hci_cp_le_set_ext_adv_data, pdu, data, length, -+ HCI_MAX_EXT_AD_LENGTH); -+ u8 len; -+ struct adv_info *adv = NULL; -+ int err; -+ -+ if (instance) { -+ adv = hci_find_adv_instance(hdev, instance); -+ if (!adv || !adv->adv_data_changed) -+ return 0; -+ } -+ -+ len = eir_create_adv_data(hdev, instance, pdu->data, -+ HCI_MAX_EXT_AD_LENGTH); -+ -+ pdu->length = len; -+ pdu->handle = adv ? adv->handle : instance; -+ pdu->operation = LE_SET_ADV_DATA_OP_COMPLETE; -+ pdu->frag_pref = LE_SET_ADV_DATA_NO_FRAG; -+ -+ err = __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_EXT_ADV_DATA, -+ struct_size(pdu, data, len), pdu, -+ HCI_CMD_TIMEOUT); -+ if (err) -+ return err; -+ -+ /* Update data if the command succeed */ -+ if (adv) { -+ adv->adv_data_changed = false; -+ } else { -+ memcpy(hdev->adv_data, pdu->data, len); -+ hdev->adv_data_len = len; -+ } -+ -+ return 0; -+} -+ -+static int hci_set_adv_data_sync(struct hci_dev *hdev, u8 instance) -+{ -+ struct hci_cp_le_set_adv_data cp; -+ u8 len; -+ -+ memset(&cp, 0, sizeof(cp)); -+ -+ len = eir_create_adv_data(hdev, instance, cp.data, sizeof(cp.data)); -+ -+ /* There's nothing to do if the data hasn't changed */ -+ if (hdev->adv_data_len == len && -+ memcmp(cp.data, hdev->adv_data, len) == 0) -+ return 0; -+ -+ memcpy(hdev->adv_data, cp.data, sizeof(cp.data)); -+ hdev->adv_data_len = len; -+ -+ cp.length = len; -+ -+ return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_ADV_DATA, -+ sizeof(cp), &cp, HCI_CMD_TIMEOUT); -+} -+ -+int hci_update_adv_data_sync(struct hci_dev *hdev, u8 instance) -+{ -+ if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) -+ return 0; -+ -+ if (ext_adv_capable(hdev)) -+ return hci_set_ext_adv_data_sync(hdev, instance); -+ -+ return hci_set_adv_data_sync(hdev, instance); -+} -+ - int hci_setup_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance) - { - struct hci_cp_le_set_ext_adv_params cp; -+ struct hci_rp_le_set_ext_adv_params rp; - bool connectable; - u32 flags; - bdaddr_t random_addr; -@@ -1228,7 +1345,7 @@ int hci_setup_ext_adv_instance_sync(stru - * Command Disallowed error, so we must first disable the - * instance if it is active. - */ -- if (adv && !adv->pending) { -+ if (adv) { - err = hci_disable_ext_adv_instance_sync(hdev, instance); - if (err) - return err; -@@ -1261,10 +1378,12 @@ int hci_setup_ext_adv_instance_sync(stru - hci_cpu_to_le24(adv->min_interval, cp.min_interval); - hci_cpu_to_le24(adv->max_interval, cp.max_interval); - cp.tx_power = adv->tx_power; -+ cp.sid = adv->sid; - } else { - hci_cpu_to_le24(hdev->le_adv_min_interval, cp.min_interval); - hci_cpu_to_le24(hdev->le_adv_max_interval, cp.max_interval); - cp.tx_power = HCI_ADV_TX_POWER_NO_PREFERENCE; -+ cp.sid = 0x00; - } - - secondary_adv = (flags & MGMT_ADV_FLAG_SEC_MASK); -@@ -1314,8 +1433,12 @@ int hci_setup_ext_adv_instance_sync(stru - cp.secondary_phy = HCI_ADV_PHY_1M; - } - -- err = __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_EXT_ADV_PARAMS, -- sizeof(cp), &cp, HCI_CMD_TIMEOUT); -+ err = hci_set_ext_adv_params_sync(hdev, adv, &cp, &rp); -+ if (err) -+ return err; -+ -+ /* Update adv data as tx power is known now */ -+ err = hci_set_ext_adv_data_sync(hdev, cp.handle); - if (err) - return err; - -@@ -1559,7 +1682,8 @@ static int hci_enable_per_advertising_sy - static int hci_adv_bcast_annoucement(struct hci_dev *hdev, struct adv_info *adv) - { - u8 bid[3]; -- u8 ad[4 + 3]; -+ u8 ad[HCI_MAX_EXT_AD_LENGTH]; -+ u8 len; - - /* Skip if NULL adv as instance 0x00 is used for general purpose - * advertising so it cannot used for the likes of Broadcast Announcement -@@ -1585,14 +1709,16 @@ static int hci_adv_bcast_annoucement(str - - /* Generate Broadcast ID */ - get_random_bytes(bid, sizeof(bid)); -- eir_append_service_data(ad, 0, 0x1852, bid, sizeof(bid)); -- hci_set_adv_instance_data(hdev, adv->instance, sizeof(ad), ad, 0, NULL); -+ len = eir_append_service_data(ad, 0, 0x1852, bid, sizeof(bid)); -+ memcpy(ad + len, adv->adv_data, adv->adv_data_len); -+ hci_set_adv_instance_data(hdev, adv->instance, len + adv->adv_data_len, -+ ad, 0, NULL); - - return hci_update_adv_data_sync(hdev, adv->instance); - } - --int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 data_len, -- u8 *data, u32 flags, u16 min_interval, -+int hci_start_per_adv_sync(struct hci_dev *hdev, u8 instance, u8 sid, -+ u8 data_len, u8 *data, u32 flags, u16 min_interval, - u16 max_interval, u16 sync_interval) - { - struct adv_info *adv = NULL; -@@ -1603,9 +1729,28 @@ int hci_start_per_adv_sync(struct hci_de - - if (instance) { - adv = hci_find_adv_instance(hdev, instance); -- /* Create an instance if that could not be found */ -- if (!adv) { -- adv = hci_add_per_instance(hdev, instance, flags, -+ if (adv) { -+ if (sid != HCI_SID_INVALID && adv->sid != sid) { -+ /* If the SID don't match attempt to find by -+ * SID. -+ */ -+ adv = hci_find_adv_sid(hdev, sid); -+ if (!adv) { -+ bt_dev_err(hdev, -+ "Unable to find adv_info"); -+ return -EINVAL; -+ } -+ } -+ -+ /* Turn it into periodic advertising */ -+ adv->periodic = true; -+ adv->per_adv_data_len = data_len; -+ if (data) -+ memcpy(adv->per_adv_data, data, data_len); -+ adv->flags = flags; -+ } else if (!adv) { -+ /* Create an instance if that could not be found */ -+ adv = hci_add_per_instance(hdev, instance, sid, flags, - data_len, data, - sync_interval, - sync_interval); -@@ -1798,78 +1943,6 @@ int hci_le_terminate_big_sync(struct hci - sizeof(cp), &cp, HCI_CMD_TIMEOUT); - } - --static int hci_set_ext_adv_data_sync(struct hci_dev *hdev, u8 instance) --{ -- DEFINE_FLEX(struct hci_cp_le_set_ext_adv_data, pdu, data, length, -- HCI_MAX_EXT_AD_LENGTH); -- u8 len; -- struct adv_info *adv = NULL; -- int err; -- -- if (instance) { -- adv = hci_find_adv_instance(hdev, instance); -- if (!adv || !adv->adv_data_changed) -- return 0; -- } -- -- len = eir_create_adv_data(hdev, instance, pdu->data); -- -- pdu->length = len; -- pdu->handle = adv ? adv->handle : instance; -- pdu->operation = LE_SET_ADV_DATA_OP_COMPLETE; -- pdu->frag_pref = LE_SET_ADV_DATA_NO_FRAG; -- -- err = __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_EXT_ADV_DATA, -- struct_size(pdu, data, len), pdu, -- HCI_CMD_TIMEOUT); -- if (err) -- return err; -- -- /* Update data if the command succeed */ -- if (adv) { -- adv->adv_data_changed = false; -- } else { -- memcpy(hdev->adv_data, pdu->data, len); -- hdev->adv_data_len = len; -- } -- -- return 0; --} -- --static int hci_set_adv_data_sync(struct hci_dev *hdev, u8 instance) --{ -- struct hci_cp_le_set_adv_data cp; -- u8 len; -- -- memset(&cp, 0, sizeof(cp)); -- -- len = eir_create_adv_data(hdev, instance, cp.data); -- -- /* There's nothing to do if the data hasn't changed */ -- if (hdev->adv_data_len == len && -- memcmp(cp.data, hdev->adv_data, len) == 0) -- return 0; -- -- memcpy(hdev->adv_data, cp.data, sizeof(cp.data)); -- hdev->adv_data_len = len; -- -- cp.length = len; -- -- return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_ADV_DATA, -- sizeof(cp), &cp, HCI_CMD_TIMEOUT); --} -- --int hci_update_adv_data_sync(struct hci_dev *hdev, u8 instance) --{ -- if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED)) -- return 0; -- -- if (ext_adv_capable(hdev)) -- return hci_set_ext_adv_data_sync(hdev, instance); -- -- return hci_set_adv_data_sync(hdev, instance); --} -- - int hci_schedule_adv_instance_sync(struct hci_dev *hdev, u8 instance, - bool force) - { -@@ -1945,13 +2018,10 @@ static int hci_clear_adv_sets_sync(struc - static int hci_clear_adv_sync(struct hci_dev *hdev, struct sock *sk, bool force) - { - struct adv_info *adv, *n; -- int err = 0; - - if (ext_adv_capable(hdev)) - /* Remove all existing sets */ -- err = hci_clear_adv_sets_sync(hdev, sk); -- if (ext_adv_capable(hdev)) -- return err; -+ return hci_clear_adv_sets_sync(hdev, sk); - - /* This is safe as long as there is no command send while the lock is - * held. -@@ -1979,13 +2049,11 @@ static int hci_clear_adv_sync(struct hci - static int hci_remove_adv_sync(struct hci_dev *hdev, u8 instance, - struct sock *sk) - { -- int err = 0; -+ int err; - - /* If we use extended advertising, instance has to be removed first. */ - if (ext_adv_capable(hdev)) -- err = hci_remove_ext_adv_instance_sync(hdev, instance, sk); -- if (ext_adv_capable(hdev)) -- return err; -+ return hci_remove_ext_adv_instance_sync(hdev, instance, sk); - - /* This is safe as long as there is no command send while the lock is - * held. -@@ -2084,16 +2152,13 @@ int hci_read_tx_power_sync(struct hci_de - int hci_disable_advertising_sync(struct hci_dev *hdev) - { - u8 enable = 0x00; -- int err = 0; - - /* If controller is not advertising we are done. */ - if (!hci_dev_test_flag(hdev, HCI_LE_ADV)) - return 0; - - if (ext_adv_capable(hdev)) -- err = hci_disable_ext_adv_instance_sync(hdev, 0x00); -- if (ext_adv_capable(hdev)) -- return err; -+ return hci_disable_ext_adv_instance_sync(hdev, 0x00); - - return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_ADV_ENABLE, - sizeof(enable), &enable, HCI_CMD_TIMEOUT); -@@ -2456,6 +2521,10 @@ static int hci_pause_advertising_sync(st - int err; - int old_state; - -+ /* If controller is not advertising we are done. */ -+ if (!hci_dev_test_flag(hdev, HCI_LE_ADV)) -+ return 0; -+ - /* If already been paused there is nothing to do. */ - if (hdev->advertising_paused) - return 0; -@@ -2525,6 +2594,13 @@ static int hci_resume_advertising_sync(s - hci_remove_ext_adv_instance_sync(hdev, adv->instance, - NULL); - } -+ -+ /* If current advertising instance is set to instance 0x00 -+ * then we need to re-enable it. -+ */ -+ if (!hdev->cur_adv_instance) -+ err = hci_enable_ext_advertising_sync(hdev, -+ hdev->cur_adv_instance); - } else { - /* Schedule for most recent instance to be restarted and begin - * the software rotation loop -@@ -2860,7 +2936,7 @@ static int hci_le_set_ext_scan_param_syn - if (sent) { - struct hci_conn *conn; - -- conn = hci_conn_hash_lookup_ba(hdev, BIS_LINK, -+ conn = hci_conn_hash_lookup_ba(hdev, PA_LINK, - &sent->bdaddr); - if (conn) { - struct bt_iso_qos *qos = &conn->iso_qos; -@@ -3275,7 +3351,7 @@ static int hci_powered_update_adv_sync(s - * advertising data. This also applies to the case - * where BR/EDR was toggled during the AUTO_OFF phase. - */ -- if (hci_dev_test_flag(hdev, HCI_ADVERTISING) || -+ if (hci_dev_test_flag(hdev, HCI_ADVERTISING) && - list_empty(&hdev->adv_instances)) { - if (ext_adv_capable(hdev)) { - err = hci_setup_ext_adv_instance_sync(hdev, 0x00); -@@ -3412,13 +3488,13 @@ int hci_update_scan_sync(struct hci_dev - return hci_write_scan_enable_sync(hdev, scan); - } - --int hci_update_name_sync(struct hci_dev *hdev) -+int hci_update_name_sync(struct hci_dev *hdev, const u8 *name) - { - struct hci_cp_write_local_name cp; - - memset(&cp, 0, sizeof(cp)); - -- memcpy(cp.name, hdev->dev_name, sizeof(cp.name)); -+ memcpy(cp.name, name, sizeof(cp.name)); - - return __hci_cmd_sync_status(hdev, HCI_OP_WRITE_LOCAL_NAME, - sizeof(cp), &cp, -@@ -3471,7 +3547,7 @@ int hci_powered_update_sync(struct hci_d - hci_write_fast_connectable_sync(hdev, false); - hci_update_scan_sync(hdev); - hci_update_class_sync(hdev); -- hci_update_name_sync(hdev); -+ hci_update_name_sync(hdev, hdev->dev_name); - hci_update_eir_sync(hdev); - } - -@@ -3518,7 +3594,7 @@ static void hci_dev_get_bd_addr_from_pro - if (ret < 0 || !bacmp(&ba, BDADDR_ANY)) - return; - -- if (test_bit(HCI_QUIRK_BDADDR_PROPERTY_BROKEN, &hdev->quirks)) -+ if (hci_test_quirk(hdev, HCI_QUIRK_BDADDR_PROPERTY_BROKEN)) - baswap(&hdev->public_addr, &ba); - else - bacpy(&hdev->public_addr, &ba); -@@ -3593,7 +3669,7 @@ static int hci_init0_sync(struct hci_dev - bt_dev_dbg(hdev, ""); - - /* Reset */ -- if (!test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) { -+ if (!hci_test_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE)) { - err = hci_reset_sync(hdev); - if (err) - return err; -@@ -3606,7 +3682,7 @@ static int hci_unconf_init_sync(struct h - { - int err; - -- if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) -+ if (hci_test_quirk(hdev, HCI_QUIRK_RAW_DEVICE)) - return 0; - - err = hci_init0_sync(hdev); -@@ -3649,7 +3725,7 @@ static int hci_read_local_cmds_sync(stru - * supported commands. - */ - if (hdev->hci_ver > BLUETOOTH_VER_1_1 && -- !test_bit(HCI_QUIRK_BROKEN_LOCAL_COMMANDS, &hdev->quirks)) -+ !hci_test_quirk(hdev, HCI_QUIRK_BROKEN_LOCAL_COMMANDS)) - return __hci_cmd_sync_status(hdev, HCI_OP_READ_LOCAL_COMMANDS, - 0, NULL, HCI_CMD_TIMEOUT); - -@@ -3663,7 +3739,7 @@ static int hci_init1_sync(struct hci_dev - bt_dev_dbg(hdev, ""); - - /* Reset */ -- if (!test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) { -+ if (!hci_test_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE)) { - err = hci_reset_sync(hdev); - if (err) - return err; -@@ -3726,7 +3802,7 @@ static int hci_set_event_filter_sync(str - if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) - return 0; - -- if (test_bit(HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL, &hdev->quirks)) -+ if (hci_test_quirk(hdev, HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL)) - return 0; - - memset(&cp, 0, sizeof(cp)); -@@ -3753,7 +3829,7 @@ static int hci_clear_event_filter_sync(s - * a hci_set_event_filter_sync() call succeeds, but we do - * the check both for parity and as a future reminder. - */ -- if (test_bit(HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL, &hdev->quirks)) -+ if (hci_test_quirk(hdev, HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL)) - return 0; - - return hci_set_event_filter_sync(hdev, HCI_FLT_CLEAR_ALL, 0x00, -@@ -3777,7 +3853,7 @@ static int hci_write_sync_flowctl_sync(s - - /* Check if the controller supports SCO and HCI_OP_WRITE_SYNC_FLOWCTL */ - if (!lmp_sco_capable(hdev) || !(hdev->commands[10] & BIT(4)) || -- !test_bit(HCI_QUIRK_SYNC_FLOWCTL_SUPPORTED, &hdev->quirks)) -+ !hci_test_quirk(hdev, HCI_QUIRK_SYNC_FLOWCTL_SUPPORTED)) - return 0; - - memset(&cp, 0, sizeof(cp)); -@@ -3852,7 +3928,7 @@ static int hci_write_inquiry_mode_sync(s - u8 mode; - - if (!lmp_inq_rssi_capable(hdev) && -- !test_bit(HCI_QUIRK_FIXUP_INQUIRY_MODE, &hdev->quirks)) -+ !hci_test_quirk(hdev, HCI_QUIRK_FIXUP_INQUIRY_MODE)) - return 0; - - /* If Extended Inquiry Result events are supported, then -@@ -4042,7 +4118,7 @@ static int hci_set_event_mask_sync(struc - } - - if (lmp_inq_rssi_capable(hdev) || -- test_bit(HCI_QUIRK_FIXUP_INQUIRY_MODE, &hdev->quirks)) -+ hci_test_quirk(hdev, HCI_QUIRK_FIXUP_INQUIRY_MODE)) - events[4] |= 0x02; /* Inquiry Result with RSSI */ - - if (lmp_ext_feat_capable(hdev)) -@@ -4094,7 +4170,7 @@ static int hci_read_stored_link_key_sync - struct hci_cp_read_stored_link_key cp; - - if (!(hdev->commands[6] & 0x20) || -- test_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks)) -+ hci_test_quirk(hdev, HCI_QUIRK_BROKEN_STORED_LINK_KEY)) - return 0; - - memset(&cp, 0, sizeof(cp)); -@@ -4143,7 +4219,7 @@ static int hci_read_def_err_data_reporti - { - if (!(hdev->commands[18] & 0x04) || - !(hdev->features[0][6] & LMP_ERR_DATA_REPORTING) || -- test_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks)) -+ hci_test_quirk(hdev, HCI_QUIRK_BROKEN_ERR_DATA_REPORTING)) - return 0; - - return __hci_cmd_sync_status(hdev, HCI_OP_READ_DEF_ERR_DATA_REPORTING, -@@ -4157,7 +4233,7 @@ static int hci_read_page_scan_type_sync( - * this command in the bit mask of supported commands. - */ - if (!(hdev->commands[13] & 0x01) || -- test_bit(HCI_QUIRK_BROKEN_READ_PAGE_SCAN_TYPE, &hdev->quirks)) -+ hci_test_quirk(hdev, HCI_QUIRK_BROKEN_READ_PAGE_SCAN_TYPE)) - return 0; - - return __hci_cmd_sync_status(hdev, HCI_OP_READ_PAGE_SCAN_TYPE, -@@ -4352,7 +4428,7 @@ static int hci_le_read_adv_tx_power_sync - static int hci_le_read_tx_power_sync(struct hci_dev *hdev) - { - if (!(hdev->commands[38] & 0x80) || -- test_bit(HCI_QUIRK_BROKEN_READ_TRANSMIT_POWER, &hdev->quirks)) -+ hci_test_quirk(hdev, HCI_QUIRK_BROKEN_READ_TRANSMIT_POWER)) - return 0; - - return __hci_cmd_sync_status(hdev, HCI_OP_LE_READ_TRANSMIT_POWER, -@@ -4395,7 +4471,7 @@ static int hci_le_set_rpa_timeout_sync(s - __le16 timeout = cpu_to_le16(hdev->rpa_timeout); - - if (!(hdev->commands[35] & 0x04) || -- test_bit(HCI_QUIRK_BROKEN_SET_RPA_TIMEOUT, &hdev->quirks)) -+ hci_test_quirk(hdev, HCI_QUIRK_BROKEN_SET_RPA_TIMEOUT)) - return 0; - - return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_RPA_TIMEOUT, -@@ -4462,14 +4538,14 @@ static int hci_le_set_host_feature_sync( - { - struct hci_cp_le_set_host_feature cp; - -- if (!cis_capable(hdev)) -+ if (!iso_capable(hdev)) - return 0; - - memset(&cp, 0, sizeof(cp)); - - /* Connected Isochronous Channels (Host Support) */ - cp.bit_number = 32; -- cp.bit_value = 1; -+ cp.bit_value = iso_enabled(hdev) ? 0x01 : 0x00; - - return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_HOST_FEATURE, - sizeof(cp), &cp, HCI_CMD_TIMEOUT); -@@ -4540,7 +4616,7 @@ static int hci_delete_stored_link_key_sy - * just disable this command. - */ - if (!(hdev->commands[6] & 0x80) || -- test_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks)) -+ hci_test_quirk(hdev, HCI_QUIRK_BROKEN_STORED_LINK_KEY)) - return 0; - - memset(&cp, 0, sizeof(cp)); -@@ -4666,7 +4742,7 @@ static int hci_set_err_data_report_sync( - - if (!(hdev->commands[18] & 0x08) || - !(hdev->features[0][6] & LMP_ERR_DATA_REPORTING) || -- test_bit(HCI_QUIRK_BROKEN_ERR_DATA_REPORTING, &hdev->quirks)) -+ hci_test_quirk(hdev, HCI_QUIRK_BROKEN_ERR_DATA_REPORTING)) - return 0; - - if (enabled == hdev->err_data_reporting) -@@ -4879,7 +4955,7 @@ static int hci_dev_setup_sync(struct hci - size_t i; - - if (!hci_dev_test_flag(hdev, HCI_SETUP) && -- !test_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks)) -+ !hci_test_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_SETUP)) - return 0; - - bt_dev_dbg(hdev, ""); -@@ -4890,7 +4966,7 @@ static int hci_dev_setup_sync(struct hci - ret = hdev->setup(hdev); - - for (i = 0; i < ARRAY_SIZE(hci_broken_table); i++) { -- if (test_bit(hci_broken_table[i].quirk, &hdev->quirks)) -+ if (hci_test_quirk(hdev, hci_broken_table[i].quirk)) - bt_dev_warn(hdev, "%s", hci_broken_table[i].desc); - } - -@@ -4898,10 +4974,10 @@ static int hci_dev_setup_sync(struct hci - * BD_ADDR invalid before creating the HCI device or in - * its setup callback. - */ -- invalid_bdaddr = test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) || -- test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); -+ invalid_bdaddr = hci_test_quirk(hdev, HCI_QUIRK_INVALID_BDADDR) || -+ hci_test_quirk(hdev, HCI_QUIRK_USE_BDADDR_PROPERTY); - if (!ret) { -- if (test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks) && -+ if (hci_test_quirk(hdev, HCI_QUIRK_USE_BDADDR_PROPERTY) && - !bacmp(&hdev->public_addr, BDADDR_ANY)) - hci_dev_get_bd_addr_from_property(hdev); - -@@ -4923,7 +4999,7 @@ static int hci_dev_setup_sync(struct hci - * In case any of them is set, the controller has to - * start up as unconfigured. - */ -- if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) || -+ if (hci_test_quirk(hdev, HCI_QUIRK_EXTERNAL_CONFIG) || - invalid_bdaddr) - hci_dev_set_flag(hdev, HCI_UNCONFIGURED); - -@@ -4983,7 +5059,7 @@ static int hci_dev_init_sync(struct hci_ - * then they need to be reprogrammed after the init procedure - * completed. - */ -- if (test_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks) && -+ if (hci_test_quirk(hdev, HCI_QUIRK_NON_PERSISTENT_DIAG) && - !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && - hci_dev_test_flag(hdev, HCI_VENDOR_DIAG) && hdev->set_diag) - ret = hdev->set_diag(hdev, true); -@@ -5240,7 +5316,7 @@ int hci_dev_close_sync(struct hci_dev *h - /* Reset device */ - skb_queue_purge(&hdev->cmd_q); - atomic_set(&hdev->cmd_cnt, 1); -- if (test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks) && -+ if (hci_test_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE) && - !auto_off && !hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) { - set_bit(HCI_INIT, &hdev->flags); - hci_reset_sync(hdev); -@@ -5424,7 +5500,7 @@ static int hci_disconnect_sync(struct hc - { - struct hci_cp_disconnect cp; - -- if (test_bit(HCI_CONN_BIG_CREATED, &conn->flags)) { -+ if (conn->type == BIS_LINK || conn->type == PA_LINK) { - /* This is a BIS connection, hci_conn_del will - * do the necessary cleanup. - */ -@@ -5493,7 +5569,7 @@ static int hci_connect_cancel_sync(struc - return HCI_ERROR_LOCAL_HOST_TERM; - } - -- if (conn->type == BIS_LINK) { -+ if (conn->type == BIS_LINK || conn->type == PA_LINK) { - /* There is no way to cancel a BIS without terminating the BIG - * which is done later on connection cleanup. - */ -@@ -5558,7 +5634,7 @@ static int hci_reject_conn_sync(struct h - if (conn->type == CIS_LINK) - return hci_le_reject_cis_sync(hdev, conn, reason); - -- if (conn->type == BIS_LINK) -+ if (conn->type == BIS_LINK || conn->type == PA_LINK) - return -EINVAL; - - if (conn->type == SCO_LINK || conn->type == ESCO_LINK) -@@ -5890,7 +5966,7 @@ static int hci_active_scan_sync(struct h - own_addr_type = ADDR_LE_DEV_PUBLIC; - - if (hci_is_adv_monitoring(hdev) || -- (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks) && -+ (hci_test_quirk(hdev, HCI_QUIRK_STRICT_DUPLICATE_FILTER) && - hdev->discovery.result_filtering)) { - /* Duplicate filter should be disabled when some advertisement - * monitor is activated, otherwise AdvMon can only receive one -@@ -5953,8 +6029,7 @@ int hci_start_discovery_sync(struct hci_ - * and LE scanning are done sequentially with separate - * timeouts. - */ -- if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, -- &hdev->quirks)) { -+ if (hci_test_quirk(hdev, HCI_QUIRK_SIMULTANEOUS_DISCOVERY)) { - timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT); - /* During simultaneous discovery, we double LE scan - * interval. We must leave some time for the controller -@@ -6031,7 +6106,7 @@ static int hci_update_event_filter_sync( - /* Some fake CSR controllers lock up after setting this type of - * filter, so avoid sending the request altogether. - */ -- if (test_bit(HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL, &hdev->quirks)) -+ if (hci_test_quirk(hdev, HCI_QUIRK_BROKEN_FILTER_CLEAR_ALL)) - return 0; - - /* Always clear event filter when starting */ -@@ -6252,6 +6327,7 @@ static int hci_le_ext_directed_advertisi - struct hci_conn *conn) - { - struct hci_cp_le_set_ext_adv_params cp; -+ struct hci_rp_le_set_ext_adv_params rp; - int err; - bdaddr_t random_addr; - u8 own_addr_type; -@@ -6293,8 +6369,12 @@ static int hci_le_ext_directed_advertisi - if (err) - return err; - -- err = __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_EXT_ADV_PARAMS, -- sizeof(cp), &cp, HCI_CMD_TIMEOUT); -+ err = hci_set_ext_adv_params_sync(hdev, NULL, &cp, &rp); -+ if (err) -+ return err; -+ -+ /* Update adv data as tx power is known now */ -+ err = hci_set_ext_adv_data_sync(hdev, cp.handle); - if (err) - return err; - -@@ -6741,8 +6821,8 @@ int hci_get_random_address(struct hci_de - return 0; - } - -- /* No privacy so use a public address. */ -- *own_addr_type = ADDR_LE_DEV_PUBLIC; -+ /* No privacy, use the current address */ -+ hci_copy_identity_address(hdev, rand_addr, own_addr_type); - - return 0; - } -@@ -6912,8 +6992,6 @@ static void create_pa_complete(struct hc - - hci_dev_lock(hdev); - -- hci_dev_clear_flag(hdev, HCI_PA_SYNC); -- - if (!hci_conn_valid(hdev, conn)) - clear_bit(HCI_CONN_CREATE_PA_SYNC, &conn->flags); - -@@ -6921,7 +6999,7 @@ static void create_pa_complete(struct hc - goto unlock; - - /* Add connection to indicate PA sync error */ -- pa_sync = hci_conn_add_unset(hdev, BIS_LINK, BDADDR_ANY, -+ pa_sync = hci_conn_add_unset(hdev, PA_LINK, BDADDR_ANY, - HCI_ROLE_SLAVE); - - if (IS_ERR(pa_sync)) -@@ -6974,10 +7052,13 @@ static int hci_le_pa_create_sync(struct - /* SID has not been set listen for HCI_EV_LE_EXT_ADV_REPORT to update - * it. - */ -- if (conn->sid == HCI_SID_INVALID) -- __hci_cmd_sync_status_sk(hdev, HCI_OP_NOP, 0, NULL, -- HCI_EV_LE_EXT_ADV_REPORT, -- conn->conn_timeout, NULL); -+ if (conn->sid == HCI_SID_INVALID) { -+ err = __hci_cmd_sync_status_sk(hdev, HCI_OP_NOP, 0, NULL, -+ HCI_EV_LE_EXT_ADV_REPORT, -+ conn->conn_timeout, NULL); -+ if (err == -ETIMEDOUT) -+ goto done; -+ } - - memset(&cp, 0, sizeof(cp)); - cp.options = qos->bcast.options; -@@ -7007,6 +7088,12 @@ static int hci_le_pa_create_sync(struct - __hci_cmd_sync_status(hdev, HCI_OP_LE_PA_CREATE_SYNC_CANCEL, - 0, NULL, HCI_CMD_TIMEOUT); - -+done: -+ hci_dev_clear_flag(hdev, HCI_PA_SYNC); -+ -+ /* Update passive scan since HCI_PA_SYNC flag has been cleared */ -+ hci_update_passive_scan_sync(hdev); -+ - return err; - } - -diff -purNx .git BPI-Router-Linux-kernel/net/bluetooth/iso.c BPI-Router-Linux-kernel-6.16.12/net/bluetooth/iso.c ---- BPI-Router-Linux-kernel/net/bluetooth/iso.c 2025-10-22 13:53:23.623327171 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bluetooth/iso.c 2025-10-22 13:53:56.803167752 -0400 -@@ -336,7 +336,7 @@ static int iso_connect_bis(struct sock * - struct hci_dev *hdev; - int err; - -- BT_DBG("%pMR", &iso_pi(sk)->src); -+ BT_DBG("%pMR (SID 0x%2.2x)", &iso_pi(sk)->src, iso_pi(sk)->bc_sid); - - hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src, - iso_pi(sk)->src_type); -@@ -365,7 +365,7 @@ static int iso_connect_bis(struct sock * - - /* Just bind if DEFER_SETUP has been set */ - if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) { -- hcon = hci_bind_bis(hdev, &iso_pi(sk)->dst, -+ hcon = hci_bind_bis(hdev, &iso_pi(sk)->dst, iso_pi(sk)->bc_sid, - &iso_pi(sk)->qos, iso_pi(sk)->base_len, - iso_pi(sk)->base); - if (IS_ERR(hcon)) { -@@ -375,12 +375,16 @@ static int iso_connect_bis(struct sock * - } else { - hcon = hci_connect_bis(hdev, &iso_pi(sk)->dst, - le_addr_type(iso_pi(sk)->dst_type), -- &iso_pi(sk)->qos, iso_pi(sk)->base_len, -- iso_pi(sk)->base); -+ iso_pi(sk)->bc_sid, &iso_pi(sk)->qos, -+ iso_pi(sk)->base_len, iso_pi(sk)->base); - if (IS_ERR(hcon)) { - err = PTR_ERR(hcon); - goto unlock; - } -+ -+ /* Update SID if it was not set */ -+ if (iso_pi(sk)->bc_sid == HCI_SID_INVALID) -+ iso_pi(sk)->bc_sid = hcon->sid; - } - - conn = iso_conn_add(hcon); -@@ -1337,10 +1341,13 @@ static int iso_sock_getname(struct socke - addr->sa_family = AF_BLUETOOTH; - - if (peer) { -+ struct hci_conn *hcon = iso_pi(sk)->conn ? -+ iso_pi(sk)->conn->hcon : NULL; -+ - bacpy(&sa->iso_bdaddr, &iso_pi(sk)->dst); - sa->iso_bdaddr_type = iso_pi(sk)->dst_type; - -- if (test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags)) { -+ if (hcon && (hcon->type == BIS_LINK || hcon->type == PA_LINK)) { - sa->iso_bc->bc_sid = iso_pi(sk)->bc_sid; - sa->iso_bc->bc_num_bis = iso_pi(sk)->bc_num_bis; - memcpy(sa->iso_bc->bc_bis, iso_pi(sk)->bc_bis, -@@ -2219,7 +2226,8 @@ done: - - static void iso_connect_cfm(struct hci_conn *hcon, __u8 status) - { -- if (hcon->type != CIS_LINK && hcon->type != BIS_LINK) { -+ if (hcon->type != CIS_LINK && hcon->type != BIS_LINK && -+ hcon->type != PA_LINK) { - if (hcon->type != LE_LINK) - return; - -@@ -2260,7 +2268,8 @@ static void iso_connect_cfm(struct hci_c - - static void iso_disconn_cfm(struct hci_conn *hcon, __u8 reason) - { -- if (hcon->type != CIS_LINK && hcon->type != BIS_LINK) -+ if (hcon->type != CIS_LINK && hcon->type != BIS_LINK && -+ hcon->type != PA_LINK) - return; - - BT_DBG("hcon %p reason %d", hcon, reason); -@@ -2448,11 +2457,11 @@ static const struct net_proto_family iso - .create = iso_sock_create, - }; - --static bool iso_inited; -+static bool inited; - --bool iso_enabled(void) -+bool iso_inited(void) - { -- return iso_inited; -+ return inited; - } - - int iso_init(void) -@@ -2461,7 +2470,7 @@ int iso_init(void) - - BUILD_BUG_ON(sizeof(struct sockaddr_iso) > sizeof(struct sockaddr)); - -- if (iso_inited) -+ if (inited) - return -EALREADY; - - err = proto_register(&iso_proto, 0); -@@ -2489,7 +2498,7 @@ int iso_init(void) - iso_debugfs = debugfs_create_file("iso", 0444, bt_debugfs, - NULL, &iso_debugfs_fops); - -- iso_inited = true; -+ inited = true; - - return 0; - -@@ -2500,7 +2509,7 @@ error: - - int iso_exit(void) - { -- if (!iso_inited) -+ if (!inited) - return -EALREADY; - - bt_procfs_cleanup(&init_net, "iso"); -@@ -2514,7 +2523,7 @@ int iso_exit(void) - - proto_unregister(&iso_proto); - -- iso_inited = false; -+ inited = false; - - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/net/bluetooth/l2cap_core.c BPI-Router-Linux-kernel-6.16.12/net/bluetooth/l2cap_core.c ---- BPI-Router-Linux-kernel/net/bluetooth/l2cap_core.c 2025-10-22 13:53:23.623327171 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bluetooth/l2cap_core.c 2025-10-22 13:53:56.803167752 -0400 -@@ -3415,7 +3415,7 @@ static int l2cap_parse_conf_req(struct l - struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC }; - struct l2cap_conf_efs efs; - u8 remote_efs = 0; -- u16 mtu = L2CAP_DEFAULT_MTU; -+ u16 mtu = 0; - u16 result = L2CAP_CONF_SUCCESS; - u16 size; - -@@ -3520,6 +3520,29 @@ done: - /* Configure output options and let the other side know - * which ones we don't like. */ - -+ /* If MTU is not provided in configure request, try adjusting it -+ * to the current output MTU if it has been set -+ * -+ * Bluetooth Core 6.1, Vol 3, Part A, Section 4.5 -+ * -+ * Each configuration parameter value (if any is present) in an -+ * L2CAP_CONFIGURATION_RSP packet reflects an ‘adjustment’ to a -+ * configuration parameter value that has been sent (or, in case -+ * of default values, implied) in the corresponding -+ * L2CAP_CONFIGURATION_REQ packet. -+ */ -+ if (!mtu) { -+ /* Only adjust for ERTM channels as for older modes the -+ * remote stack may not be able to detect that the -+ * adjustment causing it to silently drop packets. -+ */ -+ if (chan->mode == L2CAP_MODE_ERTM && -+ chan->omtu && chan->omtu != L2CAP_DEFAULT_MTU) -+ mtu = chan->omtu; -+ else -+ mtu = L2CAP_DEFAULT_MTU; -+ } -+ - if (mtu < L2CAP_DEFAULT_MIN_MTU) - result = L2CAP_CONF_UNACCEPT; - else { -diff -purNx .git BPI-Router-Linux-kernel/net/bluetooth/l2cap_sock.c BPI-Router-Linux-kernel-6.16.12/net/bluetooth/l2cap_sock.c ---- BPI-Router-Linux-kernel/net/bluetooth/l2cap_sock.c 2025-10-22 13:53:23.623327171 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bluetooth/l2cap_sock.c 2025-10-22 13:53:56.803167752 -0400 -@@ -1422,7 +1422,10 @@ static int l2cap_sock_release(struct soc - if (!sk) - return 0; - -+ lock_sock_nested(sk, L2CAP_NESTING_PARENT); - l2cap_sock_cleanup_listen(sk); -+ release_sock(sk); -+ - bt_sock_unlink(&l2cap_sk_list, sk); - - err = l2cap_sock_shutdown(sock, SHUT_RDWR); -@@ -1703,6 +1706,9 @@ static void l2cap_sock_resume_cb(struct - { - struct sock *sk = chan->data; - -+ if (!sk) -+ return; -+ - if (test_and_clear_bit(FLAG_PENDING_SECURITY, &chan->flags)) { - sk->sk_state = BT_CONNECTED; - chan->state = BT_CONNECTED; -diff -purNx .git BPI-Router-Linux-kernel/net/bluetooth/mgmt.c BPI-Router-Linux-kernel-6.16.12/net/bluetooth/mgmt.c ---- BPI-Router-Linux-kernel/net/bluetooth/mgmt.c 2025-10-22 13:53:23.623327171 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bluetooth/mgmt.c 2025-10-22 13:53:56.803167752 -0400 -@@ -464,7 +464,7 @@ static int read_index_list(struct sock * - /* Devices marked as raw-only are neither configured - * nor unconfigured controllers. - */ -- if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks)) -+ if (hci_test_quirk(d, HCI_QUIRK_RAW_DEVICE)) - continue; - - if (!hci_dev_test_flag(d, HCI_UNCONFIGURED)) { -@@ -522,7 +522,7 @@ static int read_unconf_index_list(struct - /* Devices marked as raw-only are neither configured - * nor unconfigured controllers. - */ -- if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks)) -+ if (hci_test_quirk(d, HCI_QUIRK_RAW_DEVICE)) - continue; - - if (hci_dev_test_flag(d, HCI_UNCONFIGURED)) { -@@ -576,7 +576,7 @@ static int read_ext_index_list(struct so - /* Devices marked as raw-only are neither configured - * nor unconfigured controllers. - */ -- if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks)) -+ if (hci_test_quirk(d, HCI_QUIRK_RAW_DEVICE)) - continue; - - if (hci_dev_test_flag(d, HCI_UNCONFIGURED)) -@@ -612,12 +612,12 @@ static int read_ext_index_list(struct so - - static bool is_configured(struct hci_dev *hdev) - { -- if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) && -+ if (hci_test_quirk(hdev, HCI_QUIRK_EXTERNAL_CONFIG) && - !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED)) - return false; - -- if ((test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) || -- test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks)) && -+ if ((hci_test_quirk(hdev, HCI_QUIRK_INVALID_BDADDR) || -+ hci_test_quirk(hdev, HCI_QUIRK_USE_BDADDR_PROPERTY)) && - !bacmp(&hdev->public_addr, BDADDR_ANY)) - return false; - -@@ -628,12 +628,12 @@ static __le32 get_missing_options(struct - { - u32 options = 0; - -- if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) && -+ if (hci_test_quirk(hdev, HCI_QUIRK_EXTERNAL_CONFIG) && - !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED)) - options |= MGMT_OPTION_EXTERNAL_CONFIG; - -- if ((test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) || -- test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks)) && -+ if ((hci_test_quirk(hdev, HCI_QUIRK_INVALID_BDADDR) || -+ hci_test_quirk(hdev, HCI_QUIRK_USE_BDADDR_PROPERTY)) && - !bacmp(&hdev->public_addr, BDADDR_ANY)) - options |= MGMT_OPTION_PUBLIC_ADDRESS; - -@@ -669,7 +669,7 @@ static int read_config_info(struct sock - memset(&rp, 0, sizeof(rp)); - rp.manufacturer = cpu_to_le16(hdev->manufacturer); - -- if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks)) -+ if (hci_test_quirk(hdev, HCI_QUIRK_EXTERNAL_CONFIG)) - options |= MGMT_OPTION_EXTERNAL_CONFIG; - - if (hdev->set_bdaddr) -@@ -828,8 +828,7 @@ static u32 get_supported_settings(struct - if (lmp_sc_capable(hdev)) - settings |= MGMT_SETTING_SECURE_CONN; - -- if (test_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, -- &hdev->quirks)) -+ if (hci_test_quirk(hdev, HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED)) - settings |= MGMT_SETTING_WIDEBAND_SPEECH; - } - -@@ -841,8 +840,7 @@ static u32 get_supported_settings(struct - settings |= MGMT_SETTING_ADVERTISING; - } - -- if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) || -- hdev->set_bdaddr) -+ if (hci_test_quirk(hdev, HCI_QUIRK_EXTERNAL_CONFIG) || hdev->set_bdaddr) - settings |= MGMT_SETTING_CONFIGURATION; - - if (cis_central_capable(hdev)) -@@ -924,19 +922,19 @@ static u32 get_current_settings(struct h - if (hci_dev_test_flag(hdev, HCI_WIDEBAND_SPEECH_ENABLED)) - settings |= MGMT_SETTING_WIDEBAND_SPEECH; - -- if (cis_central_capable(hdev)) -+ if (cis_central_enabled(hdev)) - settings |= MGMT_SETTING_CIS_CENTRAL; - -- if (cis_peripheral_capable(hdev)) -+ if (cis_peripheral_enabled(hdev)) - settings |= MGMT_SETTING_CIS_PERIPHERAL; - -- if (bis_capable(hdev)) -+ if (bis_enabled(hdev)) - settings |= MGMT_SETTING_ISO_BROADCASTER; - -- if (sync_recv_capable(hdev)) -+ if (sync_recv_enabled(hdev)) - settings |= MGMT_SETTING_ISO_SYNC_RECEIVER; - -- if (ll_privacy_capable(hdev)) -+ if (ll_privacy_enabled(hdev)) - settings |= MGMT_SETTING_LL_PRIVACY; - - return settings; -@@ -1080,7 +1078,8 @@ static int mesh_send_done_sync(struct hc - struct mgmt_mesh_tx *mesh_tx; - - hci_dev_clear_flag(hdev, HCI_MESH_SENDING); -- hci_disable_advertising_sync(hdev); -+ if (list_empty(&hdev->adv_instances)) -+ hci_disable_advertising_sync(hdev); - mesh_tx = mgmt_mesh_next(hdev, NULL); - - if (mesh_tx) -@@ -1324,8 +1323,7 @@ static void mgmt_set_powered_complete(st - struct mgmt_mode *cp; - - /* Make sure cmd still outstanding. */ -- if (err == -ECANCELED || -- cmd != pending_find(MGMT_OP_SET_POWERED, hdev)) -+ if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd)) - return; - - cp = cmd->param; -@@ -1352,23 +1350,29 @@ static void mgmt_set_powered_complete(st - mgmt_status(err)); - } - -- mgmt_pending_remove(cmd); -+ mgmt_pending_free(cmd); - } - - static int set_powered_sync(struct hci_dev *hdev, void *data) - { - struct mgmt_pending_cmd *cmd = data; -- struct mgmt_mode *cp; -+ struct mgmt_mode cp; -+ -+ mutex_lock(&hdev->mgmt_pending_lock); - - /* Make sure cmd still outstanding. */ -- if (cmd != pending_find(MGMT_OP_SET_POWERED, hdev)) -+ if (!__mgmt_pending_listed(hdev, cmd)) { -+ mutex_unlock(&hdev->mgmt_pending_lock); - return -ECANCELED; -+ } - -- cp = cmd->param; -+ memcpy(&cp, cmd->param, sizeof(cp)); -+ -+ mutex_unlock(&hdev->mgmt_pending_lock); - - BT_DBG("%s", hdev->name); - -- return hci_set_powered_sync(hdev, cp->val); -+ return hci_set_powered_sync(hdev, cp.val); - } - - static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data, -@@ -1447,22 +1451,17 @@ static void settings_rsp(struct mgmt_pen - - send_settings_rsp(cmd->sk, cmd->opcode, match->hdev); - -- list_del(&cmd->list); -- - if (match->sk == NULL) { - match->sk = cmd->sk; - sock_hold(match->sk); - } -- -- mgmt_pending_free(cmd); - } - - static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data) - { - u8 *status = data; - -- mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status); -- mgmt_pending_remove(cmd); -+ mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, *status); - } - - static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data) -@@ -1476,8 +1475,6 @@ static void cmd_complete_rsp(struct mgmt - - if (cmd->cmd_complete) { - cmd->cmd_complete(cmd, match->mgmt_status); -- mgmt_pending_remove(cmd); -- - return; - } - -@@ -1486,13 +1483,13 @@ static void cmd_complete_rsp(struct mgmt - - static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status) - { -- return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, -+ return mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, status, - cmd->param, cmd->param_len); - } - - static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status) - { -- return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, -+ return mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, status, - cmd->param, sizeof(struct mgmt_addr_info)); - } - -@@ -1524,15 +1521,14 @@ static void mgmt_set_discoverable_comple - bt_dev_dbg(hdev, "err %d", err); - - /* Make sure cmd still outstanding. */ -- if (err == -ECANCELED || -- cmd != pending_find(MGMT_OP_SET_DISCOVERABLE, hdev)) -+ if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd)) - return; - - hci_dev_lock(hdev); - - if (err) { - u8 mgmt_err = mgmt_status(err); -- mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err); -+ mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_err); - hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE); - goto done; - } -@@ -1547,12 +1543,15 @@ static void mgmt_set_discoverable_comple - new_settings(hdev, cmd->sk); - - done: -- mgmt_pending_remove(cmd); -+ mgmt_pending_free(cmd); - hci_dev_unlock(hdev); - } - - static int set_discoverable_sync(struct hci_dev *hdev, void *data) - { -+ if (!mgmt_pending_listed(hdev, data)) -+ return -ECANCELED; -+ - BT_DBG("%s", hdev->name); - - return hci_update_discoverable_sync(hdev); -@@ -1699,15 +1698,14 @@ static void mgmt_set_connectable_complet - bt_dev_dbg(hdev, "err %d", err); - - /* Make sure cmd still outstanding. */ -- if (err == -ECANCELED || -- cmd != pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) -+ if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd)) - return; - - hci_dev_lock(hdev); - - if (err) { - u8 mgmt_err = mgmt_status(err); -- mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err); -+ mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_err); - goto done; - } - -@@ -1715,7 +1713,7 @@ static void mgmt_set_connectable_complet - new_settings(hdev, cmd->sk); - - done: -- mgmt_pending_remove(cmd); -+ mgmt_pending_free(cmd); - - hci_dev_unlock(hdev); - } -@@ -1751,6 +1749,9 @@ static int set_connectable_update_settin - - static int set_connectable_sync(struct hci_dev *hdev, void *data) - { -+ if (!mgmt_pending_listed(hdev, data)) -+ return -ECANCELED; -+ - BT_DBG("%s", hdev->name); - - return hci_update_connectable_sync(hdev); -@@ -1927,14 +1928,17 @@ static void set_ssp_complete(struct hci_ - { - struct cmd_lookup match = { NULL, hdev }; - struct mgmt_pending_cmd *cmd = data; -- struct mgmt_mode *cp = cmd->param; -- u8 enable = cp->val; -+ struct mgmt_mode *cp; -+ u8 enable; - bool changed; - - /* Make sure cmd still outstanding. */ -- if (err == -ECANCELED || cmd != pending_find(MGMT_OP_SET_SSP, hdev)) -+ if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd)) - return; - -+ cp = cmd->param; -+ enable = cp->val; -+ - if (err) { - u8 mgmt_err = mgmt_status(err); - -@@ -1943,8 +1947,7 @@ static void set_ssp_complete(struct hci_ - new_settings(hdev, NULL); - } - -- mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp, -- &mgmt_err); -+ mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_err); - return; - } - -@@ -1954,7 +1957,7 @@ static void set_ssp_complete(struct hci_ - changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED); - } - -- mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match); -+ settings_rsp(cmd, &match); - - if (changed) - new_settings(hdev, match.sk); -@@ -1968,14 +1971,25 @@ static void set_ssp_complete(struct hci_ - static int set_ssp_sync(struct hci_dev *hdev, void *data) - { - struct mgmt_pending_cmd *cmd = data; -- struct mgmt_mode *cp = cmd->param; -+ struct mgmt_mode cp; - bool changed = false; - int err; - -- if (cp->val) -+ mutex_lock(&hdev->mgmt_pending_lock); -+ -+ if (!__mgmt_pending_listed(hdev, cmd)) { -+ mutex_unlock(&hdev->mgmt_pending_lock); -+ return -ECANCELED; -+ } -+ -+ memcpy(&cp, cmd->param, sizeof(cp)); -+ -+ mutex_unlock(&hdev->mgmt_pending_lock); -+ -+ if (cp.val) - changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED); - -- err = hci_write_ssp_mode_sync(hdev, cp->val); -+ err = hci_write_ssp_mode_sync(hdev, cp.val); - - if (!err && changed) - hci_dev_clear_flag(hdev, HCI_SSP_ENABLED); -@@ -2068,32 +2082,50 @@ static int set_hs(struct sock *sk, struc - - static void set_le_complete(struct hci_dev *hdev, void *data, int err) - { -+ struct mgmt_pending_cmd *cmd = data; - struct cmd_lookup match = { NULL, hdev }; - u8 status = mgmt_status(err); - - bt_dev_dbg(hdev, "err %d", err); - -- if (status) { -- mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp, -- &status); -+ if (err == -ECANCELED || !mgmt_pending_valid(hdev, data)) - return; -+ -+ if (status) { -+ mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, status); -+ goto done; - } - -- mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match); -+ settings_rsp(cmd, &match); - - new_settings(hdev, match.sk); - - if (match.sk) - sock_put(match.sk); -+ -+done: -+ mgmt_pending_free(cmd); - } - - static int set_le_sync(struct hci_dev *hdev, void *data) - { - struct mgmt_pending_cmd *cmd = data; -- struct mgmt_mode *cp = cmd->param; -- u8 val = !!cp->val; -+ struct mgmt_mode cp; -+ u8 val; - int err; - -+ mutex_lock(&hdev->mgmt_pending_lock); -+ -+ if (!__mgmt_pending_listed(hdev, cmd)) { -+ mutex_unlock(&hdev->mgmt_pending_lock); -+ return -ECANCELED; -+ } -+ -+ memcpy(&cp, cmd->param, sizeof(cp)); -+ val = !!cp.val; -+ -+ mutex_unlock(&hdev->mgmt_pending_lock); -+ - if (!val) { - hci_clear_adv_instance_sync(hdev, NULL, 0x00, true); - -@@ -2135,10 +2167,15 @@ static void set_mesh_complete(struct hci - { - struct mgmt_pending_cmd *cmd = data; - u8 status = mgmt_status(err); -- struct sock *sk = cmd->sk; -+ struct sock *sk; -+ -+ if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd)) -+ return; -+ -+ sk = cmd->sk; - - if (status) { -- mgmt_pending_foreach(MGMT_OP_SET_MESH_RECEIVER, hdev, -+ mgmt_pending_foreach(MGMT_OP_SET_MESH_RECEIVER, hdev, true, - cmd_status_rsp, &status); - return; - } -@@ -2150,21 +2187,37 @@ static void set_mesh_complete(struct hci - static int set_mesh_sync(struct hci_dev *hdev, void *data) - { - struct mgmt_pending_cmd *cmd = data; -- struct mgmt_cp_set_mesh *cp = cmd->param; -- size_t len = cmd->param_len; -+ struct mgmt_cp_set_mesh cp; -+ size_t len; -+ -+ mutex_lock(&hdev->mgmt_pending_lock); -+ -+ if (!__mgmt_pending_listed(hdev, cmd)) { -+ mutex_unlock(&hdev->mgmt_pending_lock); -+ return -ECANCELED; -+ } -+ -+ memcpy(&cp, cmd->param, sizeof(cp)); -+ -+ mutex_unlock(&hdev->mgmt_pending_lock); -+ -+ len = cmd->param_len; - - memset(hdev->mesh_ad_types, 0, sizeof(hdev->mesh_ad_types)); - -- if (cp->enable) -+ if (cp.enable) - hci_dev_set_flag(hdev, HCI_MESH); - else - hci_dev_clear_flag(hdev, HCI_MESH); - -- len -= sizeof(*cp); -+ hdev->le_scan_interval = __le16_to_cpu(cp.period); -+ hdev->le_scan_window = __le16_to_cpu(cp.window); -+ -+ len -= sizeof(cp); - - /* If filters don't fit, forward all adv pkts */ - if (len <= sizeof(hdev->mesh_ad_types)) -- memcpy(hdev->mesh_ad_types, cp->ad_types, len); -+ memcpy(hdev->mesh_ad_types, cp.ad_types, len); - - hci_update_passive_scan_sync(hdev); - return 0; -@@ -2174,6 +2227,7 @@ static int set_mesh(struct sock *sk, str - { - struct mgmt_cp_set_mesh *cp = data; - struct mgmt_pending_cmd *cmd; -+ __u16 period, window; - int err = 0; - - bt_dev_dbg(hdev, "sock %p", sk); -@@ -2187,6 +2241,23 @@ static int set_mesh(struct sock *sk, str - return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_MESH_RECEIVER, - MGMT_STATUS_INVALID_PARAMS); - -+ /* Keep allowed ranges in sync with set_scan_params() */ -+ period = __le16_to_cpu(cp->period); -+ -+ if (period < 0x0004 || period > 0x4000) -+ return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_MESH_RECEIVER, -+ MGMT_STATUS_INVALID_PARAMS); -+ -+ window = __le16_to_cpu(cp->window); -+ -+ if (window < 0x0004 || window > 0x4000) -+ return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_MESH_RECEIVER, -+ MGMT_STATUS_INVALID_PARAMS); -+ -+ if (window > period) -+ return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_MESH_RECEIVER, -+ MGMT_STATUS_INVALID_PARAMS); -+ - hci_dev_lock(hdev); - - cmd = mgmt_pending_add(sk, MGMT_OP_SET_MESH_RECEIVER, hdev, data, len); -@@ -2638,7 +2709,7 @@ static void mgmt_class_complete(struct h - - bt_dev_dbg(hdev, "err %d", err); - -- mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, -+ mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, - mgmt_status(err), hdev->dev_class, 3); - - mgmt_pending_free(cmd); -@@ -3224,6 +3295,7 @@ static u8 link_to_bdaddr(u8 link_type, u - switch (link_type) { - case CIS_LINK: - case BIS_LINK: -+ case PA_LINK: - case LE_LINK: - switch (addr_type) { - case ADDR_LE_DEV_PUBLIC: -@@ -3427,7 +3499,7 @@ static int pairing_complete(struct mgmt_ - bacpy(&rp.addr.bdaddr, &conn->dst); - rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type); - -- err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, -+ err = mgmt_cmd_complete(cmd->sk, cmd->hdev->id, MGMT_OP_PAIR_DEVICE, - status, &rp, sizeof(rp)); - - /* So we don't get further callbacks for this connection */ -@@ -3853,15 +3925,16 @@ static int name_changed_sync(struct hci_ - static void set_name_complete(struct hci_dev *hdev, void *data, int err) - { - struct mgmt_pending_cmd *cmd = data; -- struct mgmt_cp_set_local_name *cp = cmd->param; -+ struct mgmt_cp_set_local_name *cp; - u8 status = mgmt_status(err); - - bt_dev_dbg(hdev, "err %d", err); - -- if (err == -ECANCELED || -- cmd != pending_find(MGMT_OP_SET_LOCAL_NAME, hdev)) -+ if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd)) - return; - -+ cp = cmd->param; -+ - if (status) { - mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, - status); -@@ -3873,13 +3946,27 @@ static void set_name_complete(struct hci - hci_cmd_sync_queue(hdev, name_changed_sync, NULL, NULL); - } - -- mgmt_pending_remove(cmd); -+ mgmt_pending_free(cmd); - } - - static int set_name_sync(struct hci_dev *hdev, void *data) - { -+ struct mgmt_pending_cmd *cmd = data; -+ struct mgmt_cp_set_local_name cp; -+ -+ mutex_lock(&hdev->mgmt_pending_lock); -+ -+ if (!__mgmt_pending_listed(hdev, cmd)) { -+ mutex_unlock(&hdev->mgmt_pending_lock); -+ return -ECANCELED; -+ } -+ -+ memcpy(&cp, cmd->param, sizeof(cp)); -+ -+ mutex_unlock(&hdev->mgmt_pending_lock); -+ - if (lmp_bredr_capable(hdev)) { -- hci_update_name_sync(hdev); -+ hci_update_name_sync(hdev, cp.name); - hci_update_eir_sync(hdev); - } - -@@ -4031,12 +4118,10 @@ int mgmt_phy_configuration_changed(struc - static void set_default_phy_complete(struct hci_dev *hdev, void *data, int err) - { - struct mgmt_pending_cmd *cmd = data; -- struct sk_buff *skb = cmd->skb; -+ struct sk_buff *skb; - u8 status = mgmt_status(err); - -- if (err == -ECANCELED || -- cmd != pending_find(MGMT_OP_SET_PHY_CONFIGURATION, hdev)) -- return; -+ skb = cmd->skb; - - if (!status) { - if (!skb) -@@ -4063,7 +4148,7 @@ static void set_default_phy_complete(str - if (skb && !IS_ERR(skb)) - kfree_skb(skb); - -- mgmt_pending_remove(cmd); -+ mgmt_pending_free(cmd); - } - - static int set_default_phy_sync(struct hci_dev *hdev, void *data) -@@ -4071,7 +4156,9 @@ static int set_default_phy_sync(struct h - struct mgmt_pending_cmd *cmd = data; - struct mgmt_cp_set_phy_configuration *cp = cmd->param; - struct hci_cp_le_set_default_phy cp_phy; -- u32 selected_phys = __le32_to_cpu(cp->selected_phys); -+ u32 selected_phys; -+ -+ selected_phys = __le32_to_cpu(cp->selected_phys); - - memset(&cp_phy, 0, sizeof(cp_phy)); - -@@ -4211,7 +4298,7 @@ static int set_phy_configuration(struct - goto unlock; - } - -- cmd = mgmt_pending_add(sk, MGMT_OP_SET_PHY_CONFIGURATION, hdev, data, -+ cmd = mgmt_pending_new(sk, MGMT_OP_SET_PHY_CONFIGURATION, hdev, data, - len); - if (!cmd) - err = -ENOMEM; -@@ -4292,7 +4379,7 @@ static int set_wideband_speech(struct so - - bt_dev_dbg(hdev, "sock %p", sk); - -- if (!test_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks)) -+ if (!hci_test_quirk(hdev, HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED)) - return mgmt_cmd_status(sk, hdev->id, - MGMT_OP_SET_WIDEBAND_SPEECH, - MGMT_STATUS_NOT_SUPPORTED); -@@ -4499,7 +4586,7 @@ static int read_exp_features_info(struct - } - - if (IS_ENABLED(CONFIG_BT_LE)) { -- flags = iso_enabled() ? BIT(0) : 0; -+ flags = iso_inited() ? BIT(0) : 0; - memcpy(rp->features[idx].uuid, iso_socket_uuid, 16); - rp->features[idx].flags = cpu_to_le32(flags); - idx++; -@@ -5108,24 +5195,14 @@ static void mgmt_adv_monitor_added(struc - mgmt_event(MGMT_EV_ADV_MONITOR_ADDED, hdev, &ev, sizeof(ev), sk); - } - --void mgmt_adv_monitor_removed(struct hci_dev *hdev, u16 handle) -+static void mgmt_adv_monitor_removed(struct sock *sk, struct hci_dev *hdev, -+ __le16 handle) - { - struct mgmt_ev_adv_monitor_removed ev; -- struct mgmt_pending_cmd *cmd; -- struct sock *sk_skip = NULL; -- struct mgmt_cp_remove_adv_monitor *cp; -- -- cmd = pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev); -- if (cmd) { -- cp = cmd->param; -- -- if (cp->monitor_handle) -- sk_skip = cmd->sk; -- } - -- ev.monitor_handle = cpu_to_le16(handle); -+ ev.monitor_handle = handle; - -- mgmt_event(MGMT_EV_ADV_MONITOR_REMOVED, hdev, &ev, sizeof(ev), sk_skip); -+ mgmt_event(MGMT_EV_ADV_MONITOR_REMOVED, hdev, &ev, sizeof(ev), sk); - } - - static int read_adv_mon_features(struct sock *sk, struct hci_dev *hdev, -@@ -5182,7 +5259,17 @@ static void mgmt_add_adv_patterns_monito - { - struct mgmt_rp_add_adv_patterns_monitor rp; - struct mgmt_pending_cmd *cmd = data; -- struct adv_monitor *monitor = cmd->user_data; -+ struct adv_monitor *monitor; -+ -+ /* This is likely the result of hdev being closed and mgmt_index_removed -+ * is attempting to clean up any pending command so -+ * hci_adv_monitors_clear is about to be called which will take care of -+ * freeing the adv_monitor instances. -+ */ -+ if (status == -ECANCELED && !mgmt_pending_valid(hdev, cmd)) -+ return; -+ -+ monitor = cmd->user_data; - - hci_dev_lock(hdev); - -@@ -5196,7 +5283,7 @@ static void mgmt_add_adv_patterns_monito - hci_update_passive_scan(hdev); - } - -- mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, -+ mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, - mgmt_status(status), &rp, sizeof(rp)); - mgmt_pending_remove(cmd); - -@@ -5208,9 +5295,20 @@ static void mgmt_add_adv_patterns_monito - static int mgmt_add_adv_patterns_monitor_sync(struct hci_dev *hdev, void *data) - { - struct mgmt_pending_cmd *cmd = data; -- struct adv_monitor *monitor = cmd->user_data; -+ struct adv_monitor *mon; -+ -+ mutex_lock(&hdev->mgmt_pending_lock); -+ -+ if (!__mgmt_pending_listed(hdev, cmd)) { -+ mutex_unlock(&hdev->mgmt_pending_lock); -+ return -ECANCELED; -+ } -+ -+ mon = cmd->user_data; - -- return hci_add_adv_monitor(hdev, monitor); -+ mutex_unlock(&hdev->mgmt_pending_lock); -+ -+ return hci_add_adv_monitor(hdev, mon); - } - - static int __add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev, -@@ -5227,8 +5325,7 @@ static int __add_adv_patterns_monitor(st - - if (pending_find(MGMT_OP_SET_LE, hdev) || - pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR, hdev) || -- pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, hdev) || -- pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev)) { -+ pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, hdev)) { - status = MGMT_STATUS_BUSY; - goto unlock; - } -@@ -5398,8 +5495,7 @@ static void mgmt_remove_adv_monitor_comp - struct mgmt_pending_cmd *cmd = data; - struct mgmt_cp_remove_adv_monitor *cp; - -- if (status == -ECANCELED || -- cmd != pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev)) -+ if (status == -ECANCELED) - return; - - hci_dev_lock(hdev); -@@ -5408,12 +5504,14 @@ static void mgmt_remove_adv_monitor_comp - - rp.monitor_handle = cp->monitor_handle; - -- if (!status) -+ if (!status) { -+ mgmt_adv_monitor_removed(cmd->sk, hdev, cp->monitor_handle); - hci_update_passive_scan(hdev); -+ } - -- mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, -+ mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, - mgmt_status(status), &rp, sizeof(rp)); -- mgmt_pending_remove(cmd); -+ mgmt_pending_free(cmd); - - hci_dev_unlock(hdev); - bt_dev_dbg(hdev, "remove monitor %d complete, status %d", -@@ -5423,10 +5521,6 @@ static void mgmt_remove_adv_monitor_comp - static int mgmt_remove_adv_monitor_sync(struct hci_dev *hdev, void *data) - { - struct mgmt_pending_cmd *cmd = data; -- -- if (cmd != pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev)) -- return -ECANCELED; -- - struct mgmt_cp_remove_adv_monitor *cp = cmd->param; - u16 handle = __le16_to_cpu(cp->monitor_handle); - -@@ -5445,14 +5539,13 @@ static int remove_adv_monitor(struct soc - hci_dev_lock(hdev); - - if (pending_find(MGMT_OP_SET_LE, hdev) || -- pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev) || - pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR, hdev) || - pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, hdev)) { - status = MGMT_STATUS_BUSY; - goto unlock; - } - -- cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_ADV_MONITOR, hdev, data, len); -+ cmd = mgmt_pending_new(sk, MGMT_OP_REMOVE_ADV_MONITOR, hdev, data, len); - if (!cmd) { - status = MGMT_STATUS_NO_RESOURCES; - goto unlock; -@@ -5462,7 +5555,7 @@ static int remove_adv_monitor(struct soc - mgmt_remove_adv_monitor_complete); - - if (err) { -- mgmt_pending_remove(cmd); -+ mgmt_pending_free(cmd); - - if (err == -ENOMEM) - status = MGMT_STATUS_NO_RESOURCES; -@@ -5482,7 +5575,8 @@ unlock: - status); - } - --static void read_local_oob_data_complete(struct hci_dev *hdev, void *data, int err) -+static void read_local_oob_data_complete(struct hci_dev *hdev, void *data, -+ int err) - { - struct mgmt_rp_read_local_oob_data mgmt_rp; - size_t rp_size = sizeof(mgmt_rp); -@@ -5502,7 +5596,8 @@ static void read_local_oob_data_complete - bt_dev_dbg(hdev, "status %d", status); - - if (status) { -- mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, status); -+ mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, -+ status); - goto remove; - } - -@@ -5784,17 +5879,12 @@ static void start_discovery_complete(str - - bt_dev_dbg(hdev, "err %d", err); - -- if (err == -ECANCELED) -+ if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd)) - return; - -- if (cmd != pending_find(MGMT_OP_START_DISCOVERY, hdev) && -- cmd != pending_find(MGMT_OP_START_LIMITED_DISCOVERY, hdev) && -- cmd != pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev)) -- return; -- -- mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(err), -+ mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err), - cmd->param, 1); -- mgmt_pending_remove(cmd); -+ mgmt_pending_free(cmd); - - hci_discovery_set_state(hdev, err ? DISCOVERY_STOPPED: - DISCOVERY_FINDING); -@@ -5802,6 +5892,9 @@ static void start_discovery_complete(str - - static int start_discovery_sync(struct hci_dev *hdev, void *data) - { -+ if (!mgmt_pending_listed(hdev, data)) -+ return -ECANCELED; -+ - return hci_start_discovery_sync(hdev); - } - -@@ -6007,15 +6100,14 @@ static void stop_discovery_complete(stru - { - struct mgmt_pending_cmd *cmd = data; - -- if (err == -ECANCELED || -- cmd != pending_find(MGMT_OP_STOP_DISCOVERY, hdev)) -+ if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd)) - return; - - bt_dev_dbg(hdev, "err %d", err); - -- mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(err), -+ mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err), - cmd->param, 1); -- mgmt_pending_remove(cmd); -+ mgmt_pending_free(cmd); - - if (!err) - hci_discovery_set_state(hdev, DISCOVERY_STOPPED); -@@ -6023,6 +6115,9 @@ static void stop_discovery_complete(stru - - static int stop_discovery_sync(struct hci_dev *hdev, void *data) - { -+ if (!mgmt_pending_listed(hdev, data)) -+ return -ECANCELED; -+ - return hci_stop_discovery_sync(hdev); - } - -@@ -6232,14 +6327,18 @@ static void enable_advertising_instance( - - static void set_advertising_complete(struct hci_dev *hdev, void *data, int err) - { -+ struct mgmt_pending_cmd *cmd = data; - struct cmd_lookup match = { NULL, hdev }; - u8 instance; - struct adv_info *adv_instance; - u8 status = mgmt_status(err); - -+ if (err == -ECANCELED || !mgmt_pending_valid(hdev, data)) -+ return; -+ - if (status) { -- mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, -- cmd_status_rsp, &status); -+ mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, status); -+ mgmt_pending_free(cmd); - return; - } - -@@ -6248,8 +6347,7 @@ static void set_advertising_complete(str - else - hci_dev_clear_flag(hdev, HCI_ADVERTISING); - -- mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp, -- &match); -+ settings_rsp(cmd, &match); - - new_settings(hdev, match.sk); - -@@ -6281,10 +6379,23 @@ static void set_advertising_complete(str - static int set_adv_sync(struct hci_dev *hdev, void *data) - { - struct mgmt_pending_cmd *cmd = data; -- struct mgmt_mode *cp = cmd->param; -- u8 val = !!cp->val; -+ struct mgmt_mode cp; -+ u8 val; - -- if (cp->val == 0x02) -+ mutex_lock(&hdev->mgmt_pending_lock); -+ -+ if (!__mgmt_pending_listed(hdev, cmd)) { -+ mutex_unlock(&hdev->mgmt_pending_lock); -+ return -ECANCELED; -+ } -+ -+ memcpy(&cp, cmd->param, sizeof(cp)); -+ -+ mutex_unlock(&hdev->mgmt_pending_lock); -+ -+ val = !!cp.val; -+ -+ if (cp.val == 0x02) - hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE); - else - hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE); -@@ -6454,6 +6565,7 @@ static int set_scan_params(struct sock * - return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, - MGMT_STATUS_NOT_SUPPORTED); - -+ /* Keep allowed ranges in sync with set_mesh() */ - interval = __le16_to_cpu(cp->interval); - - if (interval < 0x0004 || interval > 0x4000) -@@ -6592,7 +6704,7 @@ static void set_bredr_complete(struct hc - */ - hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED); - -- mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err); -+ mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_err); - } else { - send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev); - new_settings(hdev, cmd->sk); -@@ -6729,7 +6841,7 @@ static void set_secure_conn_complete(str - if (err) { - u8 mgmt_err = mgmt_status(err); - -- mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err); -+ mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_err); - goto done; - } - -@@ -7176,7 +7288,7 @@ static void get_conn_info_complete(struc - rp.max_tx_power = HCI_TX_POWER_INVALID; - } - -- mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO, status, -+ mgmt_cmd_complete(cmd->sk, cmd->hdev->id, MGMT_OP_GET_CONN_INFO, status, - &rp, sizeof(rp)); - - mgmt_pending_free(cmd); -@@ -7336,7 +7448,7 @@ static void get_clock_info_complete(stru - } - - complete: -- mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp, -+ mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, status, &rp, - sizeof(rp)); - - mgmt_pending_free(cmd); -@@ -7934,7 +8046,7 @@ static int set_external_config(struct so - return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG, - MGMT_STATUS_INVALID_PARAMS); - -- if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks)) -+ if (!hci_test_quirk(hdev, HCI_QUIRK_EXTERNAL_CONFIG)) - return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG, - MGMT_STATUS_NOT_SUPPORTED); - -@@ -8036,10 +8148,6 @@ static void read_local_oob_ext_data_comp - u8 status = mgmt_status(err); - u16 eir_len; - -- if (err == -ECANCELED || -- cmd != pending_find(MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev)) -- return; -- - if (!status) { - if (!skb) - status = MGMT_STATUS_FAILED; -@@ -8146,7 +8254,7 @@ done: - kfree_skb(skb); - - kfree(mgmt_rp); -- mgmt_pending_remove(cmd); -+ mgmt_pending_free(cmd); - } - - static int read_local_ssp_oob_req(struct hci_dev *hdev, struct sock *sk, -@@ -8155,7 +8263,7 @@ static int read_local_ssp_oob_req(struct - struct mgmt_pending_cmd *cmd; - int err; - -- cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev, -+ cmd = mgmt_pending_new(sk, MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev, - cp, sizeof(*cp)); - if (!cmd) - return -ENOMEM; -@@ -8586,10 +8694,10 @@ static void add_advertising_complete(str - rp.instance = cp->instance; - - if (err) -- mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, -+ mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, - mgmt_status(err)); - else -- mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, -+ mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, - mgmt_status(err), &rp, sizeof(rp)); - - add_adv_complete(hdev, cmd->sk, cp->instance, err); -@@ -8777,10 +8885,10 @@ static void add_ext_adv_params_complete( - - hci_remove_adv_instance(hdev, cp->instance); - -- mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, -+ mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, - mgmt_status(err)); - } else { -- mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, -+ mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, - mgmt_status(err), &rp, sizeof(rp)); - } - -@@ -8927,10 +9035,10 @@ static void add_ext_adv_data_complete(st - rp.instance = cp->instance; - - if (err) -- mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, -+ mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, - mgmt_status(err)); - else -- mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, -+ mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, - mgmt_status(err), &rp, sizeof(rp)); - - mgmt_pending_free(cmd); -@@ -9089,10 +9197,10 @@ static void remove_advertising_complete( - rp.instance = cp->instance; - - if (err) -- mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, -+ mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, - mgmt_status(err)); - else -- mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, -+ mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, - MGMT_STATUS_SUCCESS, &rp, sizeof(rp)); - - mgmt_pending_free(cmd); -@@ -9337,7 +9445,7 @@ void mgmt_index_added(struct hci_dev *hd - { - struct mgmt_ev_ext_index ev; - -- if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) -+ if (hci_test_quirk(hdev, HCI_QUIRK_RAW_DEVICE)) - return; - - if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) { -@@ -9361,10 +9469,10 @@ void mgmt_index_removed(struct hci_dev * - struct mgmt_ev_ext_index ev; - struct cmd_lookup match = { NULL, hdev, MGMT_STATUS_INVALID_INDEX }; - -- if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) -+ if (hci_test_quirk(hdev, HCI_QUIRK_RAW_DEVICE)) - return; - -- mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &match); -+ mgmt_pending_foreach(0, hdev, true, cmd_complete_rsp, &match); - - if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) { - mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, -@@ -9402,7 +9510,8 @@ void mgmt_power_on(struct hci_dev *hdev, - hci_update_passive_scan(hdev); - } - -- mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); -+ mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, true, settings_rsp, -+ &match); - - new_settings(hdev, match.sk); - -@@ -9417,7 +9526,8 @@ void __mgmt_power_off(struct hci_dev *hd - struct cmd_lookup match = { NULL, hdev }; - u8 zero_cod[] = { 0, 0, 0 }; - -- mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); -+ mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, true, settings_rsp, -+ &match); - - /* If the power off is because of hdev unregistration let - * use the appropriate INVALID_INDEX status. Otherwise use -@@ -9431,7 +9541,7 @@ void __mgmt_power_off(struct hci_dev *hd - else - match.mgmt_status = MGMT_STATUS_NOT_POWERED; - -- mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &match); -+ mgmt_pending_foreach(0, hdev, true, cmd_complete_rsp, &match); - - if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0) { - mgmt_limited_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, -@@ -9672,7 +9782,6 @@ static void unpair_device_rsp(struct mgm - device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk); - - cmd->cmd_complete(cmd, 0); -- mgmt_pending_remove(cmd); - } - - bool mgmt_powering_down(struct hci_dev *hdev) -@@ -9704,7 +9813,9 @@ void mgmt_device_disconnected(struct hci - if (!mgmt_connected) - return; - -- if (link_type != ACL_LINK && link_type != LE_LINK) -+ if (link_type != ACL_LINK && -+ link_type != LE_LINK && -+ link_type != BIS_LINK) - return; - - bacpy(&ev.addr.bdaddr, bdaddr); -@@ -9728,8 +9839,8 @@ void mgmt_disconnect_failed(struct hci_d - struct mgmt_cp_disconnect *cp; - struct mgmt_pending_cmd *cmd; - -- mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp, -- hdev); -+ mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, true, -+ unpair_device_rsp, hdev); - - cmd = pending_find(MGMT_OP_DISCONNECT, hdev); - if (!cmd) -@@ -9922,7 +10033,7 @@ void mgmt_auth_enable_complete(struct hc - - if (status) { - u8 mgmt_err = mgmt_status(status); -- mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, -+ mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, true, - cmd_status_rsp, &mgmt_err); - return; - } -@@ -9932,8 +10043,8 @@ void mgmt_auth_enable_complete(struct hc - else - changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY); - -- mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp, -- &match); -+ mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, true, -+ settings_rsp, &match); - - if (changed) - new_settings(hdev, match.sk); -@@ -9957,9 +10068,12 @@ void mgmt_set_class_of_dev_complete(stru - { - struct cmd_lookup match = { NULL, hdev, mgmt_status(status) }; - -- mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match); -- mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match); -- mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match); -+ mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, false, sk_lookup, -+ &match); -+ mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, false, sk_lookup, -+ &match); -+ mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, false, sk_lookup, -+ &match); - - if (!status) { - mgmt_limited_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, -@@ -10084,7 +10198,7 @@ static bool is_filter_match(struct hci_d - if (hdev->discovery.rssi != HCI_RSSI_INVALID && - (rssi == HCI_RSSI_INVALID || - (rssi < hdev->discovery.rssi && -- !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)))) -+ !hci_test_quirk(hdev, HCI_QUIRK_STRICT_DUPLICATE_FILTER)))) - return false; - - if (hdev->discovery.uuid_count != 0) { -@@ -10102,7 +10216,7 @@ static bool is_filter_match(struct hci_d - /* If duplicate filtering does not report RSSI changes, then restart - * scanning to ensure updated result with updated RSSI values. - */ -- if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) { -+ if (hci_test_quirk(hdev, HCI_QUIRK_STRICT_DUPLICATE_FILTER)) { - /* Validate RSSI value against the RSSI threshold once more. */ - if (hdev->discovery.rssi != HCI_RSSI_INVALID && - rssi < hdev->discovery.rssi) -diff -purNx .git BPI-Router-Linux-kernel/net/bluetooth/mgmt_util.c BPI-Router-Linux-kernel-6.16.12/net/bluetooth/mgmt_util.c ---- BPI-Router-Linux-kernel/net/bluetooth/mgmt_util.c 2025-10-22 13:53:23.623327171 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bluetooth/mgmt_util.c 2025-10-22 13:53:56.803167752 -0400 -@@ -217,30 +217,47 @@ int mgmt_cmd_complete(struct sock *sk, u - struct mgmt_pending_cmd *mgmt_pending_find(unsigned short channel, u16 opcode, - struct hci_dev *hdev) - { -- struct mgmt_pending_cmd *cmd; -+ struct mgmt_pending_cmd *cmd, *tmp; -+ -+ mutex_lock(&hdev->mgmt_pending_lock); - -- list_for_each_entry(cmd, &hdev->mgmt_pending, list) { -+ list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) { - if (hci_sock_get_channel(cmd->sk) != channel) - continue; -- if (cmd->opcode == opcode) -+ -+ if (cmd->opcode == opcode) { -+ mutex_unlock(&hdev->mgmt_pending_lock); - return cmd; -+ } - } - -+ mutex_unlock(&hdev->mgmt_pending_lock); -+ - return NULL; - } - --void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, -+void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, bool remove, - void (*cb)(struct mgmt_pending_cmd *cmd, void *data), - void *data) - { - struct mgmt_pending_cmd *cmd, *tmp; - -+ mutex_lock(&hdev->mgmt_pending_lock); -+ - list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) { - if (opcode > 0 && cmd->opcode != opcode) - continue; - -+ if (remove) -+ list_del(&cmd->list); -+ - cb(cmd, data); -+ -+ if (remove) -+ mgmt_pending_free(cmd); - } -+ -+ mutex_unlock(&hdev->mgmt_pending_lock); - } - - struct mgmt_pending_cmd *mgmt_pending_new(struct sock *sk, u16 opcode, -@@ -254,7 +271,7 @@ struct mgmt_pending_cmd *mgmt_pending_ne - return NULL; - - cmd->opcode = opcode; -- cmd->index = hdev->id; -+ cmd->hdev = hdev; - - cmd->param = kmemdup(data, len, GFP_KERNEL); - if (!cmd->param) { -@@ -280,7 +297,9 @@ struct mgmt_pending_cmd *mgmt_pending_ad - if (!cmd) - return NULL; - -+ mutex_lock(&hdev->mgmt_pending_lock); - list_add_tail(&cmd->list, &hdev->mgmt_pending); -+ mutex_unlock(&hdev->mgmt_pending_lock); - - return cmd; - } -@@ -294,10 +313,59 @@ void mgmt_pending_free(struct mgmt_pendi - - void mgmt_pending_remove(struct mgmt_pending_cmd *cmd) - { -+ mutex_lock(&cmd->hdev->mgmt_pending_lock); - list_del(&cmd->list); -+ mutex_unlock(&cmd->hdev->mgmt_pending_lock); -+ - mgmt_pending_free(cmd); - } - -+bool __mgmt_pending_listed(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd) -+{ -+ struct mgmt_pending_cmd *tmp; -+ -+ lockdep_assert_held(&hdev->mgmt_pending_lock); -+ -+ if (!cmd) -+ return false; -+ -+ list_for_each_entry(tmp, &hdev->mgmt_pending, list) { -+ if (cmd == tmp) -+ return true; -+ } -+ -+ return false; -+} -+ -+bool mgmt_pending_listed(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd) -+{ -+ bool listed; -+ -+ mutex_lock(&hdev->mgmt_pending_lock); -+ listed = __mgmt_pending_listed(hdev, cmd); -+ mutex_unlock(&hdev->mgmt_pending_lock); -+ -+ return listed; -+} -+ -+bool mgmt_pending_valid(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd) -+{ -+ bool listed; -+ -+ if (!cmd) -+ return false; -+ -+ mutex_lock(&hdev->mgmt_pending_lock); -+ -+ listed = __mgmt_pending_listed(hdev, cmd); -+ if (listed) -+ list_del(&cmd->list); -+ -+ mutex_unlock(&hdev->mgmt_pending_lock); -+ -+ return listed; -+} -+ - void mgmt_mesh_foreach(struct hci_dev *hdev, - void (*cb)(struct mgmt_mesh_tx *mesh_tx, void *data), - void *data, struct sock *sk) -diff -purNx .git BPI-Router-Linux-kernel/net/bluetooth/mgmt_util.h BPI-Router-Linux-kernel-6.16.12/net/bluetooth/mgmt_util.h ---- BPI-Router-Linux-kernel/net/bluetooth/mgmt_util.h 2025-10-22 13:53:23.623327171 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bluetooth/mgmt_util.h 2025-10-22 13:53:56.803167752 -0400 -@@ -33,7 +33,7 @@ struct mgmt_mesh_tx { - struct mgmt_pending_cmd { - struct list_head list; - u16 opcode; -- int index; -+ struct hci_dev *hdev; - void *param; - size_t param_len; - struct sock *sk; -@@ -54,7 +54,7 @@ int mgmt_cmd_complete(struct sock *sk, u - - struct mgmt_pending_cmd *mgmt_pending_find(unsigned short channel, u16 opcode, - struct hci_dev *hdev); --void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, -+void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, bool remove, - void (*cb)(struct mgmt_pending_cmd *cmd, void *data), - void *data); - struct mgmt_pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode, -@@ -65,6 +65,9 @@ struct mgmt_pending_cmd *mgmt_pending_ne - void *data, u16 len); - void mgmt_pending_free(struct mgmt_pending_cmd *cmd); - void mgmt_pending_remove(struct mgmt_pending_cmd *cmd); -+bool __mgmt_pending_listed(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd); -+bool mgmt_pending_listed(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd); -+bool mgmt_pending_valid(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd); - void mgmt_mesh_foreach(struct hci_dev *hdev, - void (*cb)(struct mgmt_mesh_tx *mesh_tx, void *data), - void *data, struct sock *sk); -diff -purNx .git BPI-Router-Linux-kernel/net/bluetooth/msft.c BPI-Router-Linux-kernel-6.16.12/net/bluetooth/msft.c ---- BPI-Router-Linux-kernel/net/bluetooth/msft.c 2025-10-22 13:53:23.623327171 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bluetooth/msft.c 2025-10-22 13:53:56.803167752 -0400 -@@ -989,7 +989,7 @@ static void msft_monitor_device_evt(stru - - handle_data = msft_find_handle_data(hdev, ev->monitor_handle, false); - -- if (!test_bit(HCI_QUIRK_USE_MSFT_EXT_ADDRESS_FILTER, &hdev->quirks)) { -+ if (!hci_test_quirk(hdev, HCI_QUIRK_USE_MSFT_EXT_ADDRESS_FILTER)) { - if (!handle_data) - return; - mgmt_handle = handle_data->mgmt_handle; -diff -purNx .git BPI-Router-Linux-kernel/net/bluetooth/smp.c BPI-Router-Linux-kernel-6.16.12/net/bluetooth/smp.c ---- BPI-Router-Linux-kernel/net/bluetooth/smp.c 2025-10-22 13:53:23.623327171 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bluetooth/smp.c 2025-10-22 13:53:56.803167752 -0400 -@@ -1379,7 +1379,7 @@ static void smp_timeout(struct work_stru - - bt_dev_dbg(conn->hcon->hdev, "conn %p", conn); - -- hci_disconnect(conn->hcon, HCI_ERROR_REMOTE_USER_TERM); -+ hci_disconnect(conn->hcon, HCI_ERROR_AUTH_FAILURE); - } - - static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) -@@ -2977,8 +2977,25 @@ static int smp_sig_channel(struct l2cap_ - if (code > SMP_CMD_MAX) - goto drop; - -- if (smp && !test_and_clear_bit(code, &smp->allow_cmd)) -+ if (smp && !test_and_clear_bit(code, &smp->allow_cmd)) { -+ /* If there is a context and the command is not allowed consider -+ * it a failure so the session is cleanup properly. -+ */ -+ switch (code) { -+ case SMP_CMD_IDENT_INFO: -+ case SMP_CMD_IDENT_ADDR_INFO: -+ case SMP_CMD_SIGN_INFO: -+ /* 3.6.1. Key distribution and generation -+ * -+ * A device may reject a distributed key by sending the -+ * Pairing Failed command with the reason set to -+ * "Key Rejected". -+ */ -+ smp_failure(conn, SMP_KEY_REJECTED); -+ break; -+ } - goto drop; -+ } - - /* If we don't have a context the only allowed commands are - * pairing request and security request. -diff -purNx .git BPI-Router-Linux-kernel/net/bluetooth/smp.h BPI-Router-Linux-kernel-6.16.12/net/bluetooth/smp.h ---- BPI-Router-Linux-kernel/net/bluetooth/smp.h 2025-10-22 13:53:23.623327171 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bluetooth/smp.h 2025-10-22 13:53:56.803167752 -0400 -@@ -138,6 +138,7 @@ struct smp_cmd_keypress_notify { - #define SMP_NUMERIC_COMP_FAILED 0x0c - #define SMP_BREDR_PAIRING_IN_PROGRESS 0x0d - #define SMP_CROSS_TRANSP_NOT_ALLOWED 0x0e -+#define SMP_KEY_REJECTED 0x0f - - #define SMP_MIN_ENC_KEY_SIZE 7 - #define SMP_MAX_ENC_KEY_SIZE 16 -diff -purNx .git BPI-Router-Linux-kernel/net/bridge/br.c BPI-Router-Linux-kernel-6.16.12/net/bridge/br.c ---- BPI-Router-Linux-kernel/net/bridge/br.c 2025-10-22 13:53:23.623327171 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bridge/br.c 2025-10-22 13:53:56.803167752 -0400 -@@ -324,6 +324,13 @@ int br_boolopt_multi_toggle(struct net_b - int err = 0; - int opt_id; - -+ opt_id = find_next_bit(&bitmap, BITS_PER_LONG, BR_BOOLOPT_MAX); -+ if (opt_id != BITS_PER_LONG) { -+ NL_SET_ERR_MSG_FMT_MOD(extack, "Unknown boolean option %d", -+ opt_id); -+ return -EINVAL; -+ } -+ - for_each_set_bit(opt_id, &bitmap, BR_BOOLOPT_MAX) { - bool on = !!(bm->optval & BIT(opt_id)); - -diff -purNx .git BPI-Router-Linux-kernel/net/bridge/br_multicast.c BPI-Router-Linux-kernel-6.16.12/net/bridge/br_multicast.c ---- BPI-Router-Linux-kernel/net/bridge/br_multicast.c 2025-10-22 13:53:23.627327153 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bridge/br_multicast.c 2025-10-22 13:53:56.807167733 -0400 -@@ -2015,10 +2015,19 @@ void br_multicast_port_ctx_init(struct n - - void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pmctx) - { -+ struct net_bridge *br = pmctx->port->br; -+ bool del = false; -+ - #if IS_ENABLED(CONFIG_IPV6) - timer_delete_sync(&pmctx->ip6_mc_router_timer); - #endif - timer_delete_sync(&pmctx->ip4_mc_router_timer); -+ -+ spin_lock_bh(&br->multicast_lock); -+ del |= br_ip6_multicast_rport_del(pmctx); -+ del |= br_ip4_multicast_rport_del(pmctx); -+ br_multicast_rport_del_notify(pmctx, del); -+ spin_unlock_bh(&br->multicast_lock); - } - - int br_multicast_add_port(struct net_bridge_port *port) -@@ -4809,6 +4818,14 @@ void br_multicast_set_query_intvl(struct - intvl_jiffies = BR_MULTICAST_QUERY_INTVL_MIN; - } - -+ if (intvl_jiffies > BR_MULTICAST_QUERY_INTVL_MAX) { -+ br_info(brmctx->br, -+ "trying to set multicast query interval above maximum, setting to %lu (%ums)\n", -+ jiffies_to_clock_t(BR_MULTICAST_QUERY_INTVL_MAX), -+ jiffies_to_msecs(BR_MULTICAST_QUERY_INTVL_MAX)); -+ intvl_jiffies = BR_MULTICAST_QUERY_INTVL_MAX; -+ } -+ - brmctx->multicast_query_interval = intvl_jiffies; - } - -@@ -4825,6 +4842,14 @@ void br_multicast_set_startup_query_intv - intvl_jiffies = BR_MULTICAST_STARTUP_QUERY_INTVL_MIN; - } - -+ if (intvl_jiffies > BR_MULTICAST_STARTUP_QUERY_INTVL_MAX) { -+ br_info(brmctx->br, -+ "trying to set multicast startup query interval above maximum, setting to %lu (%ums)\n", -+ jiffies_to_clock_t(BR_MULTICAST_STARTUP_QUERY_INTVL_MAX), -+ jiffies_to_msecs(BR_MULTICAST_STARTUP_QUERY_INTVL_MAX)); -+ intvl_jiffies = BR_MULTICAST_STARTUP_QUERY_INTVL_MAX; -+ } -+ - brmctx->multicast_startup_query_interval = intvl_jiffies; - } - -diff -purNx .git BPI-Router-Linux-kernel/net/bridge/br_netfilter_hooks.c BPI-Router-Linux-kernel-6.16.12/net/bridge/br_netfilter_hooks.c ---- BPI-Router-Linux-kernel/net/bridge/br_netfilter_hooks.c 2025-10-22 13:53:23.627327153 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bridge/br_netfilter_hooks.c 2025-10-22 13:53:56.807167733 -0400 -@@ -626,9 +626,6 @@ static unsigned int br_nf_local_in(void - break; - } - -- ct = container_of(nfct, struct nf_conn, ct_general); -- WARN_ON_ONCE(!nf_ct_is_confirmed(ct)); -- - return ret; - } - #endif -diff -purNx .git BPI-Router-Linux-kernel/net/bridge/br_private.h BPI-Router-Linux-kernel-6.16.12/net/bridge/br_private.h ---- BPI-Router-Linux-kernel/net/bridge/br_private.h 2025-10-22 13:53:23.627327153 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bridge/br_private.h 2025-10-22 13:53:56.807167733 -0400 -@@ -31,6 +31,8 @@ - #define BR_MULTICAST_DEFAULT_HASH_MAX 4096 - #define BR_MULTICAST_QUERY_INTVL_MIN msecs_to_jiffies(1000) - #define BR_MULTICAST_STARTUP_QUERY_INTVL_MIN BR_MULTICAST_QUERY_INTVL_MIN -+#define BR_MULTICAST_QUERY_INTVL_MAX msecs_to_jiffies(86400000) /* 24 hours */ -+#define BR_MULTICAST_STARTUP_QUERY_INTVL_MAX BR_MULTICAST_QUERY_INTVL_MAX - - #define BR_HWDOM_MAX BITS_PER_LONG - -diff -purNx .git BPI-Router-Linux-kernel/net/bridge/br_switchdev.c BPI-Router-Linux-kernel-6.16.12/net/bridge/br_switchdev.c ---- BPI-Router-Linux-kernel/net/bridge/br_switchdev.c 2025-10-22 13:53:23.627327153 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/bridge/br_switchdev.c 2025-10-22 13:53:56.807167733 -0400 -@@ -17,6 +17,9 @@ static bool nbp_switchdev_can_offload_tx - if (!static_branch_unlikely(&br_switchdev_tx_fwd_offload)) - return false; - -+ if (br_multicast_igmp_type(skb)) -+ return false; -+ - return (p->flags & BR_TX_FWD_OFFLOAD) && - (p->hwdom != BR_INPUT_SKB_CB(skb)->src_hwdom); - } -diff -purNx .git BPI-Router-Linux-kernel/net/caif/cfctrl.c BPI-Router-Linux-kernel-6.16.12/net/caif/cfctrl.c ---- BPI-Router-Linux-kernel/net/caif/cfctrl.c 2025-10-22 13:53:23.627327153 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/caif/cfctrl.c 2025-10-22 13:53:56.807167733 -0400 -@@ -351,17 +351,154 @@ int cfctrl_cancel_req(struct cflayer *la - return found; - } - -+static int cfctrl_link_setup(struct cfctrl *cfctrl, struct cfpkt *pkt, u8 cmdrsp) -+{ -+ u8 len; -+ u8 linkid = 0; -+ enum cfctrl_srv serv; -+ enum cfctrl_srv servtype; -+ u8 endpoint; -+ u8 physlinkid; -+ u8 prio; -+ u8 tmp; -+ u8 *cp; -+ int i; -+ struct cfctrl_link_param linkparam; -+ struct cfctrl_request_info rsp, *req; -+ -+ memset(&linkparam, 0, sizeof(linkparam)); -+ -+ tmp = cfpkt_extr_head_u8(pkt); -+ -+ serv = tmp & CFCTRL_SRV_MASK; -+ linkparam.linktype = serv; -+ -+ servtype = tmp >> 4; -+ linkparam.chtype = servtype; -+ -+ tmp = cfpkt_extr_head_u8(pkt); -+ physlinkid = tmp & 0x07; -+ prio = tmp >> 3; -+ -+ linkparam.priority = prio; -+ linkparam.phyid = physlinkid; -+ endpoint = cfpkt_extr_head_u8(pkt); -+ linkparam.endpoint = endpoint & 0x03; -+ -+ switch (serv) { -+ case CFCTRL_SRV_VEI: -+ case CFCTRL_SRV_DBG: -+ if (CFCTRL_ERR_BIT & cmdrsp) -+ break; -+ /* Link ID */ -+ linkid = cfpkt_extr_head_u8(pkt); -+ break; -+ case CFCTRL_SRV_VIDEO: -+ tmp = cfpkt_extr_head_u8(pkt); -+ linkparam.u.video.connid = tmp; -+ if (CFCTRL_ERR_BIT & cmdrsp) -+ break; -+ /* Link ID */ -+ linkid = cfpkt_extr_head_u8(pkt); -+ break; -+ -+ case CFCTRL_SRV_DATAGRAM: -+ linkparam.u.datagram.connid = cfpkt_extr_head_u32(pkt); -+ if (CFCTRL_ERR_BIT & cmdrsp) -+ break; -+ /* Link ID */ -+ linkid = cfpkt_extr_head_u8(pkt); -+ break; -+ case CFCTRL_SRV_RFM: -+ /* Construct a frame, convert -+ * DatagramConnectionID -+ * to network format long and copy it out... -+ */ -+ linkparam.u.rfm.connid = cfpkt_extr_head_u32(pkt); -+ cp = (u8 *) linkparam.u.rfm.volume; -+ for (tmp = cfpkt_extr_head_u8(pkt); -+ cfpkt_more(pkt) && tmp != '\0'; -+ tmp = cfpkt_extr_head_u8(pkt)) -+ *cp++ = tmp; -+ *cp = '\0'; -+ -+ if (CFCTRL_ERR_BIT & cmdrsp) -+ break; -+ /* Link ID */ -+ linkid = cfpkt_extr_head_u8(pkt); -+ -+ break; -+ case CFCTRL_SRV_UTIL: -+ /* Construct a frame, convert -+ * DatagramConnectionID -+ * to network format long and copy it out... -+ */ -+ /* Fifosize KB */ -+ linkparam.u.utility.fifosize_kb = cfpkt_extr_head_u16(pkt); -+ /* Fifosize bufs */ -+ linkparam.u.utility.fifosize_bufs = cfpkt_extr_head_u16(pkt); -+ /* name */ -+ cp = (u8 *) linkparam.u.utility.name; -+ caif_assert(sizeof(linkparam.u.utility.name) -+ >= UTILITY_NAME_LENGTH); -+ for (i = 0; i < UTILITY_NAME_LENGTH && cfpkt_more(pkt); i++) { -+ tmp = cfpkt_extr_head_u8(pkt); -+ *cp++ = tmp; -+ } -+ /* Length */ -+ len = cfpkt_extr_head_u8(pkt); -+ linkparam.u.utility.paramlen = len; -+ /* Param Data */ -+ cp = linkparam.u.utility.params; -+ while (cfpkt_more(pkt) && len--) { -+ tmp = cfpkt_extr_head_u8(pkt); -+ *cp++ = tmp; -+ } -+ if (CFCTRL_ERR_BIT & cmdrsp) -+ break; -+ /* Link ID */ -+ linkid = cfpkt_extr_head_u8(pkt); -+ /* Length */ -+ len = cfpkt_extr_head_u8(pkt); -+ /* Param Data */ -+ cfpkt_extr_head(pkt, NULL, len); -+ break; -+ default: -+ pr_warn("Request setup, invalid type (%d)\n", serv); -+ return -1; -+ } -+ -+ rsp.cmd = CFCTRL_CMD_LINK_SETUP; -+ rsp.param = linkparam; -+ spin_lock_bh(&cfctrl->info_list_lock); -+ req = cfctrl_remove_req(cfctrl, &rsp); -+ -+ if (CFCTRL_ERR_BIT == (CFCTRL_ERR_BIT & cmdrsp) || -+ cfpkt_erroneous(pkt)) { -+ pr_err("Invalid O/E bit or parse error " -+ "on CAIF control channel\n"); -+ cfctrl->res.reject_rsp(cfctrl->serv.layer.up, 0, -+ req ? req->client_layer : NULL); -+ } else { -+ cfctrl->res.linksetup_rsp(cfctrl->serv.layer.up, linkid, -+ serv, physlinkid, -+ req ? req->client_layer : NULL); -+ } -+ -+ kfree(req); -+ -+ spin_unlock_bh(&cfctrl->info_list_lock); -+ -+ return 0; -+} -+ - static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) - { - u8 cmdrsp; - u8 cmd; -- int ret = -1; -- u8 len; -- u8 param[255]; -+ int ret = 0; - u8 linkid = 0; - struct cfctrl *cfctrl = container_obj(layer); -- struct cfctrl_request_info rsp, *req; -- - - cmdrsp = cfpkt_extr_head_u8(pkt); - cmd = cmdrsp & CFCTRL_CMD_MASK; -@@ -374,150 +511,7 @@ static int cfctrl_recv(struct cflayer *l - - switch (cmd) { - case CFCTRL_CMD_LINK_SETUP: -- { -- enum cfctrl_srv serv; -- enum cfctrl_srv servtype; -- u8 endpoint; -- u8 physlinkid; -- u8 prio; -- u8 tmp; -- u8 *cp; -- int i; -- struct cfctrl_link_param linkparam; -- memset(&linkparam, 0, sizeof(linkparam)); -- -- tmp = cfpkt_extr_head_u8(pkt); -- -- serv = tmp & CFCTRL_SRV_MASK; -- linkparam.linktype = serv; -- -- servtype = tmp >> 4; -- linkparam.chtype = servtype; -- -- tmp = cfpkt_extr_head_u8(pkt); -- physlinkid = tmp & 0x07; -- prio = tmp >> 3; -- -- linkparam.priority = prio; -- linkparam.phyid = physlinkid; -- endpoint = cfpkt_extr_head_u8(pkt); -- linkparam.endpoint = endpoint & 0x03; -- -- switch (serv) { -- case CFCTRL_SRV_VEI: -- case CFCTRL_SRV_DBG: -- if (CFCTRL_ERR_BIT & cmdrsp) -- break; -- /* Link ID */ -- linkid = cfpkt_extr_head_u8(pkt); -- break; -- case CFCTRL_SRV_VIDEO: -- tmp = cfpkt_extr_head_u8(pkt); -- linkparam.u.video.connid = tmp; -- if (CFCTRL_ERR_BIT & cmdrsp) -- break; -- /* Link ID */ -- linkid = cfpkt_extr_head_u8(pkt); -- break; -- -- case CFCTRL_SRV_DATAGRAM: -- linkparam.u.datagram.connid = -- cfpkt_extr_head_u32(pkt); -- if (CFCTRL_ERR_BIT & cmdrsp) -- break; -- /* Link ID */ -- linkid = cfpkt_extr_head_u8(pkt); -- break; -- case CFCTRL_SRV_RFM: -- /* Construct a frame, convert -- * DatagramConnectionID -- * to network format long and copy it out... -- */ -- linkparam.u.rfm.connid = -- cfpkt_extr_head_u32(pkt); -- cp = (u8 *) linkparam.u.rfm.volume; -- for (tmp = cfpkt_extr_head_u8(pkt); -- cfpkt_more(pkt) && tmp != '\0'; -- tmp = cfpkt_extr_head_u8(pkt)) -- *cp++ = tmp; -- *cp = '\0'; -- -- if (CFCTRL_ERR_BIT & cmdrsp) -- break; -- /* Link ID */ -- linkid = cfpkt_extr_head_u8(pkt); -- -- break; -- case CFCTRL_SRV_UTIL: -- /* Construct a frame, convert -- * DatagramConnectionID -- * to network format long and copy it out... -- */ -- /* Fifosize KB */ -- linkparam.u.utility.fifosize_kb = -- cfpkt_extr_head_u16(pkt); -- /* Fifosize bufs */ -- linkparam.u.utility.fifosize_bufs = -- cfpkt_extr_head_u16(pkt); -- /* name */ -- cp = (u8 *) linkparam.u.utility.name; -- caif_assert(sizeof(linkparam.u.utility.name) -- >= UTILITY_NAME_LENGTH); -- for (i = 0; -- i < UTILITY_NAME_LENGTH -- && cfpkt_more(pkt); i++) { -- tmp = cfpkt_extr_head_u8(pkt); -- *cp++ = tmp; -- } -- /* Length */ -- len = cfpkt_extr_head_u8(pkt); -- linkparam.u.utility.paramlen = len; -- /* Param Data */ -- cp = linkparam.u.utility.params; -- while (cfpkt_more(pkt) && len--) { -- tmp = cfpkt_extr_head_u8(pkt); -- *cp++ = tmp; -- } -- if (CFCTRL_ERR_BIT & cmdrsp) -- break; -- /* Link ID */ -- linkid = cfpkt_extr_head_u8(pkt); -- /* Length */ -- len = cfpkt_extr_head_u8(pkt); -- /* Param Data */ -- cfpkt_extr_head(pkt, ¶m, len); -- break; -- default: -- pr_warn("Request setup, invalid type (%d)\n", -- serv); -- goto error; -- } -- -- rsp.cmd = cmd; -- rsp.param = linkparam; -- spin_lock_bh(&cfctrl->info_list_lock); -- req = cfctrl_remove_req(cfctrl, &rsp); -- -- if (CFCTRL_ERR_BIT == (CFCTRL_ERR_BIT & cmdrsp) || -- cfpkt_erroneous(pkt)) { -- pr_err("Invalid O/E bit or parse error " -- "on CAIF control channel\n"); -- cfctrl->res.reject_rsp(cfctrl->serv.layer.up, -- 0, -- req ? req->client_layer -- : NULL); -- } else { -- cfctrl->res.linksetup_rsp(cfctrl->serv. -- layer.up, linkid, -- serv, physlinkid, -- req ? req-> -- client_layer : NULL); -- } -- -- kfree(req); -- -- spin_unlock_bh(&cfctrl->info_list_lock); -- } -+ ret = cfctrl_link_setup(cfctrl, pkt, cmdrsp); - break; - case CFCTRL_CMD_LINK_DESTROY: - linkid = cfpkt_extr_head_u8(pkt); -@@ -544,9 +538,9 @@ static int cfctrl_recv(struct cflayer *l - break; - default: - pr_err("Unrecognized Control Frame\n"); -+ ret = -1; - goto error; - } -- ret = 0; - error: - cfpkt_destroy(pkt); - return ret; -diff -purNx .git BPI-Router-Linux-kernel/net/can/j1939/bus.c BPI-Router-Linux-kernel-6.16.12/net/can/j1939/bus.c ---- BPI-Router-Linux-kernel/net/can/j1939/bus.c 2025-10-22 13:53:23.627327153 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/can/j1939/bus.c 2025-10-22 13:53:56.807167733 -0400 -@@ -290,8 +290,11 @@ int j1939_local_ecu_get(struct j1939_pri - if (!ecu) - ecu = j1939_ecu_create_locked(priv, name); - err = PTR_ERR_OR_ZERO(ecu); -- if (err) -+ if (err) { -+ if (j1939_address_is_unicast(sa)) -+ priv->ents[sa].nusers--; - goto done; -+ } - - ecu->nusers++; - /* TODO: do we care if ecu->addr != sa? */ -diff -purNx .git BPI-Router-Linux-kernel/net/can/j1939/j1939-priv.h BPI-Router-Linux-kernel-6.16.12/net/can/j1939/j1939-priv.h ---- BPI-Router-Linux-kernel/net/can/j1939/j1939-priv.h 2025-10-22 13:53:23.627327153 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/can/j1939/j1939-priv.h 2025-10-22 13:53:56.807167733 -0400 -@@ -212,6 +212,7 @@ void j1939_priv_get(struct j1939_priv *p - - /* notify/alert all j1939 sockets bound to ifindex */ - void j1939_sk_netdev_event_netdown(struct j1939_priv *priv); -+void j1939_sk_netdev_event_unregister(struct j1939_priv *priv); - int j1939_cancel_active_session(struct j1939_priv *priv, struct sock *sk); - void j1939_tp_init(struct j1939_priv *priv); - -diff -purNx .git BPI-Router-Linux-kernel/net/can/j1939/main.c BPI-Router-Linux-kernel-6.16.12/net/can/j1939/main.c ---- BPI-Router-Linux-kernel/net/can/j1939/main.c 2025-10-22 13:53:23.627327153 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/can/j1939/main.c 2025-10-22 13:53:56.807167733 -0400 -@@ -377,6 +377,9 @@ static int j1939_netdev_notify(struct no - j1939_sk_netdev_event_netdown(priv); - j1939_ecu_unmap_all(priv); - break; -+ case NETDEV_UNREGISTER: -+ j1939_sk_netdev_event_unregister(priv); -+ break; - } - - j1939_priv_put(priv); -diff -purNx .git BPI-Router-Linux-kernel/net/can/j1939/socket.c BPI-Router-Linux-kernel-6.16.12/net/can/j1939/socket.c ---- BPI-Router-Linux-kernel/net/can/j1939/socket.c 2025-10-22 13:53:23.627327153 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/can/j1939/socket.c 2025-10-22 13:53:56.807167733 -0400 -@@ -520,6 +520,9 @@ static int j1939_sk_bind(struct socket * - ret = j1939_local_ecu_get(priv, jsk->addr.src_name, jsk->addr.sa); - if (ret) { - j1939_netdev_stop(priv); -+ jsk->priv = NULL; -+ synchronize_rcu(); -+ j1939_priv_put(priv); - goto out_release_sock; - } - -@@ -1299,6 +1302,55 @@ void j1939_sk_netdev_event_netdown(struc - read_unlock_bh(&priv->j1939_socks_lock); - } - -+void j1939_sk_netdev_event_unregister(struct j1939_priv *priv) -+{ -+ struct sock *sk; -+ struct j1939_sock *jsk; -+ bool wait_rcu = false; -+ -+rescan: /* The caller is holding a ref on this "priv" via j1939_priv_get_by_ndev(). */ -+ read_lock_bh(&priv->j1939_socks_lock); -+ list_for_each_entry(jsk, &priv->j1939_socks, list) { -+ /* Skip if j1939_jsk_add() is not called on this socket. */ -+ if (!(jsk->state & J1939_SOCK_BOUND)) -+ continue; -+ sk = &jsk->sk; -+ sock_hold(sk); -+ read_unlock_bh(&priv->j1939_socks_lock); -+ /* Check if j1939_jsk_del() is not yet called on this socket after holding -+ * socket's lock, for both j1939_sk_bind() and j1939_sk_release() call -+ * j1939_jsk_del() with socket's lock held. -+ */ -+ lock_sock(sk); -+ if (jsk->state & J1939_SOCK_BOUND) { -+ /* Neither j1939_sk_bind() nor j1939_sk_release() called j1939_jsk_del(). -+ * Make this socket no longer bound, by pretending as if j1939_sk_bind() -+ * dropped old references but did not get new references. -+ */ -+ j1939_jsk_del(priv, jsk); -+ j1939_local_ecu_put(priv, jsk->addr.src_name, jsk->addr.sa); -+ j1939_netdev_stop(priv); -+ /* Call j1939_priv_put() now and prevent j1939_sk_sock_destruct() from -+ * calling the corresponding j1939_priv_put(). -+ * -+ * j1939_sk_sock_destruct() is supposed to call j1939_priv_put() after -+ * an RCU grace period. But since the caller is holding a ref on this -+ * "priv", we can defer synchronize_rcu() until immediately before -+ * the caller calls j1939_priv_put(). -+ */ -+ j1939_priv_put(priv); -+ jsk->priv = NULL; -+ wait_rcu = true; -+ } -+ release_sock(sk); -+ sock_put(sk); -+ goto rescan; -+ } -+ read_unlock_bh(&priv->j1939_socks_lock); -+ if (wait_rcu) -+ synchronize_rcu(); -+} -+ - static int j1939_sk_no_ioctlcmd(struct socket *sock, unsigned int cmd, - unsigned long arg) - { -diff -purNx .git BPI-Router-Linux-kernel/net/ceph/messenger.c BPI-Router-Linux-kernel-6.16.12/net/ceph/messenger.c ---- BPI-Router-Linux-kernel/net/ceph/messenger.c 2025-10-22 13:53:23.627327153 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ceph/messenger.c 2025-10-22 13:53:56.807167733 -0400 -@@ -1524,7 +1524,7 @@ static void con_fault_finish(struct ceph - * in case we faulted due to authentication, invalidate our - * current tickets so that we can get new ones. - */ -- if (con->v1.auth_retry) { -+ if (!ceph_msgr2(from_msgr(con->msgr)) && con->v1.auth_retry) { - dout("auth_retry %d, invalidating\n", con->v1.auth_retry); - if (con->ops->invalidate_authorizer) - con->ops->invalidate_authorizer(con); -@@ -1714,9 +1714,10 @@ static void clear_standby(struct ceph_co - { - /* come back from STANDBY? */ - if (con->state == CEPH_CON_S_STANDBY) { -- dout("clear_standby %p and ++connect_seq\n", con); -+ dout("clear_standby %p\n", con); - con->state = CEPH_CON_S_PREOPEN; -- con->v1.connect_seq++; -+ if (!ceph_msgr2(from_msgr(con->msgr))) -+ con->v1.connect_seq++; - WARN_ON(ceph_con_flag_test(con, CEPH_CON_F_WRITE_PENDING)); - WARN_ON(ceph_con_flag_test(con, CEPH_CON_F_KEEPALIVE_PENDING)); - } -diff -purNx .git BPI-Router-Linux-kernel/net/core/dev.c BPI-Router-Linux-kernel-6.16.12/net/core/dev.c ---- BPI-Router-Linux-kernel/net/core/dev.c 2025-10-22 13:53:23.627327153 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/core/dev.c 2025-10-22 13:53:56.807167733 -0400 -@@ -3782,6 +3782,18 @@ static netdev_features_t gso_features_ch - features &= ~NETIF_F_TSO_MANGLEID; - } - -+ /* NETIF_F_IPV6_CSUM does not support IPv6 extension headers, -+ * so neither does TSO that depends on it. -+ */ -+ if (features & NETIF_F_IPV6_CSUM && -+ (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6 || -+ (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4 && -+ vlan_get_protocol(skb) == htons(ETH_P_IPV6))) && -+ skb_transport_header_was_set(skb) && -+ skb_network_header_len(skb) != sizeof(struct ipv6hdr) && -+ !ipv6_has_hopopt_jumbo(skb)) -+ features &= ~(NETIF_F_IPV6_CSUM | NETIF_F_TSO6 | NETIF_F_GSO_UDP_L4); -+ - return features; - } - -diff -purNx .git BPI-Router-Linux-kernel/net/core/dev_ioctl.c BPI-Router-Linux-kernel-6.16.12/net/core/dev_ioctl.c ---- BPI-Router-Linux-kernel/net/core/dev_ioctl.c 2025-10-22 13:53:23.627327153 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/core/dev_ioctl.c 2025-10-22 13:53:56.807167733 -0400 -@@ -464,8 +464,15 @@ int generic_hwtstamp_get_lower(struct ne - if (!netif_device_present(dev)) - return -ENODEV; - -- if (ops->ndo_hwtstamp_get) -- return dev_get_hwtstamp_phylib(dev, kernel_cfg); -+ if (ops->ndo_hwtstamp_get) { -+ int err; -+ -+ netdev_lock_ops(dev); -+ err = dev_get_hwtstamp_phylib(dev, kernel_cfg); -+ netdev_unlock_ops(dev); -+ -+ return err; -+ } - - /* Legacy path: unconverted lower driver */ - return generic_hwtstamp_ioctl_lower(dev, SIOCGHWTSTAMP, kernel_cfg); -@@ -481,8 +488,15 @@ int generic_hwtstamp_set_lower(struct ne - if (!netif_device_present(dev)) - return -ENODEV; - -- if (ops->ndo_hwtstamp_set) -- return dev_set_hwtstamp_phylib(dev, kernel_cfg, extack); -+ if (ops->ndo_hwtstamp_set) { -+ int err; -+ -+ netdev_lock_ops(dev); -+ err = dev_set_hwtstamp_phylib(dev, kernel_cfg, extack); -+ netdev_unlock_ops(dev); -+ -+ return err; -+ } - - /* Legacy path: unconverted lower driver */ - return generic_hwtstamp_ioctl_lower(dev, SIOCSHWTSTAMP, kernel_cfg); -diff -purNx .git BPI-Router-Linux-kernel/net/core/devmem.c BPI-Router-Linux-kernel-6.16.12/net/core/devmem.c ---- BPI-Router-Linux-kernel/net/core/devmem.c 2025-10-22 13:53:23.627327153 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/core/devmem.c 2025-10-22 13:53:56.807167733 -0400 -@@ -70,14 +70,13 @@ void __net_devmem_dmabuf_binding_free(st - gen_pool_destroy(binding->chunk_pool); - - dma_buf_unmap_attachment_unlocked(binding->attachment, binding->sgt, -- DMA_FROM_DEVICE); -+ binding->direction); - dma_buf_detach(binding->dmabuf, binding->attachment); - dma_buf_put(binding->dmabuf); - xa_destroy(&binding->bound_rxqs); - kvfree(binding->tx_vec); - kfree(binding); - } --EXPORT_SYMBOL(__net_devmem_dmabuf_binding_free); - - struct net_iov * - net_devmem_alloc_dmabuf(struct net_devmem_dmabuf_binding *binding) -@@ -208,6 +207,7 @@ net_devmem_bind_dmabuf(struct net_device - mutex_init(&binding->lock); - - binding->dmabuf = dmabuf; -+ binding->direction = direction; - - binding->attachment = dma_buf_attach(binding->dmabuf, dev->dev.parent); - if (IS_ERR(binding->attachment)) { -@@ -312,7 +312,7 @@ err_tx_vec: - kvfree(binding->tx_vec); - err_unmap: - dma_buf_unmap_attachment_unlocked(binding->attachment, binding->sgt, -- DMA_FROM_DEVICE); -+ direction); - err_detach: - dma_buf_detach(dmabuf, binding->attachment); - err_free_binding: -diff -purNx .git BPI-Router-Linux-kernel/net/core/devmem.h BPI-Router-Linux-kernel-6.16.12/net/core/devmem.h ---- BPI-Router-Linux-kernel/net/core/devmem.h 2025-10-22 13:53:23.627327153 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/core/devmem.h 2025-10-22 13:53:56.807167733 -0400 -@@ -56,6 +56,9 @@ struct net_devmem_dmabuf_binding { - */ - u32 id; - -+ /* DMA direction, FROM_DEVICE for Rx binding, TO_DEVICE for Tx. */ -+ enum dma_data_direction direction; -+ - /* Array of net_iov pointers for this binding, sorted by virtual - * address. This array is convenient to map the virtual addresses to - * net_iovs in the TX path. -@@ -165,10 +168,6 @@ static inline void net_devmem_put_net_io - { - } - --static inline void __net_devmem_dmabuf_binding_free(struct work_struct *wq) --{ --} -- - static inline struct net_devmem_dmabuf_binding * - net_devmem_bind_dmabuf(struct net_device *dev, - enum dma_data_direction direction, -diff -purNx .git BPI-Router-Linux-kernel/net/core/dst.c BPI-Router-Linux-kernel-6.16.12/net/core/dst.c ---- BPI-Router-Linux-kernel/net/core/dst.c 2025-10-22 13:53:23.627327153 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/core/dst.c 2025-10-22 13:53:56.807167733 -0400 -@@ -148,9 +148,9 @@ void dst_dev_put(struct dst_entry *dst) - dst->obsolete = DST_OBSOLETE_DEAD; - if (dst->ops->ifdown) - dst->ops->ifdown(dst, dev); -- dst->input = dst_discard; -- dst->output = dst_discard_out; -- dst->dev = blackhole_netdev; -+ WRITE_ONCE(dst->input, dst_discard); -+ WRITE_ONCE(dst->output, dst_discard_out); -+ WRITE_ONCE(dst->dev, blackhole_netdev); - netdev_ref_replace(dev, blackhole_netdev, &dst->dev_tracker, - GFP_ATOMIC); - } -@@ -263,7 +263,7 @@ unsigned int dst_blackhole_mtu(const str - { - unsigned int mtu = dst_metric_raw(dst, RTAX_MTU); - -- return mtu ? : dst->dev->mtu; -+ return mtu ? : dst_dev(dst)->mtu; - } - EXPORT_SYMBOL_GPL(dst_blackhole_mtu); - -diff -purNx .git BPI-Router-Linux-kernel/net/core/filter.c BPI-Router-Linux-kernel-6.16.12/net/core/filter.c ---- BPI-Router-Linux-kernel/net/core/filter.c 2025-10-22 13:53:23.627327153 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/core/filter.c 2025-10-22 13:53:56.807167733 -0400 -@@ -3233,6 +3233,13 @@ static const struct bpf_func_proto bpf_s - .arg1_type = ARG_PTR_TO_CTX, - }; - -+static void bpf_skb_change_protocol(struct sk_buff *skb, u16 proto) -+{ -+ skb->protocol = htons(proto); -+ if (skb_valid_dst(skb)) -+ skb_dst_drop(skb); -+} -+ - static int bpf_skb_generic_push(struct sk_buff *skb, u32 off, u32 len) - { - /* Caller already did skb_cow() with len as headroom, -@@ -3329,7 +3336,7 @@ static int bpf_skb_proto_4_to_6(struct s - } - } - -- skb->protocol = htons(ETH_P_IPV6); -+ bpf_skb_change_protocol(skb, ETH_P_IPV6); - skb_clear_hash(skb); - - return 0; -@@ -3359,7 +3366,7 @@ static int bpf_skb_proto_6_to_4(struct s - } - } - -- skb->protocol = htons(ETH_P_IP); -+ bpf_skb_change_protocol(skb, ETH_P_IP); - skb_clear_hash(skb); - - return 0; -@@ -3550,10 +3557,10 @@ static int bpf_skb_net_grow(struct sk_bu - /* Match skb->protocol to new outer l3 protocol */ - if (skb->protocol == htons(ETH_P_IP) && - flags & BPF_F_ADJ_ROOM_ENCAP_L3_IPV6) -- skb->protocol = htons(ETH_P_IPV6); -+ bpf_skb_change_protocol(skb, ETH_P_IPV6); - else if (skb->protocol == htons(ETH_P_IPV6) && - flags & BPF_F_ADJ_ROOM_ENCAP_L3_IPV4) -- skb->protocol = htons(ETH_P_IP); -+ bpf_skb_change_protocol(skb, ETH_P_IP); - } - - if (skb_is_gso(skb)) { -@@ -3606,10 +3613,10 @@ static int bpf_skb_net_shrink(struct sk_ - /* Match skb->protocol to new outer l3 protocol */ - if (skb->protocol == htons(ETH_P_IP) && - flags & BPF_F_ADJ_ROOM_DECAP_L3_IPV6) -- skb->protocol = htons(ETH_P_IPV6); -+ bpf_skb_change_protocol(skb, ETH_P_IPV6); - else if (skb->protocol == htons(ETH_P_IPV6) && - flags & BPF_F_ADJ_ROOM_DECAP_L3_IPV4) -- skb->protocol = htons(ETH_P_IP); -+ bpf_skb_change_protocol(skb, ETH_P_IP); - - if (skb_is_gso(skb)) { - struct skb_shared_info *shinfo = skb_shinfo(skb); -@@ -8683,7 +8690,7 @@ static bool bpf_skb_is_valid_access(int - if (size != sizeof(__u64)) - return false; - break; -- case offsetof(struct __sk_buff, sk): -+ case bpf_ctx_range_ptr(struct __sk_buff, sk): - if (type == BPF_WRITE || size != sizeof(__u64)) - return false; - info->reg_type = PTR_TO_SOCK_COMMON_OR_NULL; -@@ -9261,7 +9268,7 @@ static bool sock_addr_is_valid_access(in - return false; - } - break; -- case offsetof(struct bpf_sock_addr, sk): -+ case bpf_ctx_range_ptr(struct bpf_sock_addr, sk): - if (type != BPF_READ) - return false; - if (size != sizeof(__u64)) -@@ -9311,17 +9318,17 @@ static bool sock_ops_is_valid_access(int - if (size != sizeof(__u64)) - return false; - break; -- case offsetof(struct bpf_sock_ops, sk): -+ case bpf_ctx_range_ptr(struct bpf_sock_ops, sk): - if (size != sizeof(__u64)) - return false; - info->reg_type = PTR_TO_SOCKET_OR_NULL; - break; -- case offsetof(struct bpf_sock_ops, skb_data): -+ case bpf_ctx_range_ptr(struct bpf_sock_ops, skb_data): - if (size != sizeof(__u64)) - return false; - info->reg_type = PTR_TO_PACKET; - break; -- case offsetof(struct bpf_sock_ops, skb_data_end): -+ case bpf_ctx_range_ptr(struct bpf_sock_ops, skb_data_end): - if (size != sizeof(__u64)) - return false; - info->reg_type = PTR_TO_PACKET_END; -@@ -9330,7 +9337,7 @@ static bool sock_ops_is_valid_access(int - bpf_ctx_record_field_size(info, size_default); - return bpf_ctx_narrow_access_ok(off, size, - size_default); -- case offsetof(struct bpf_sock_ops, skb_hwtstamp): -+ case bpf_ctx_range(struct bpf_sock_ops, skb_hwtstamp): - if (size != sizeof(__u64)) - return false; - break; -@@ -9400,17 +9407,17 @@ static bool sk_msg_is_valid_access(int o - return false; - - switch (off) { -- case offsetof(struct sk_msg_md, data): -+ case bpf_ctx_range_ptr(struct sk_msg_md, data): - info->reg_type = PTR_TO_PACKET; - if (size != sizeof(__u64)) - return false; - break; -- case offsetof(struct sk_msg_md, data_end): -+ case bpf_ctx_range_ptr(struct sk_msg_md, data_end): - info->reg_type = PTR_TO_PACKET_END; - if (size != sizeof(__u64)) - return false; - break; -- case offsetof(struct sk_msg_md, sk): -+ case bpf_ctx_range_ptr(struct sk_msg_md, sk): - if (size != sizeof(__u64)) - return false; - info->reg_type = PTR_TO_SOCKET; -@@ -9442,6 +9449,9 @@ static bool flow_dissector_is_valid_acce - if (off < 0 || off >= sizeof(struct __sk_buff)) - return false; - -+ if (off % size != 0) -+ return false; -+ - if (type == BPF_WRITE) - return false; - -@@ -11616,7 +11626,7 @@ static bool sk_lookup_is_valid_access(in - return false; - - switch (off) { -- case offsetof(struct bpf_sk_lookup, sk): -+ case bpf_ctx_range_ptr(struct bpf_sk_lookup, sk): - info->reg_type = PTR_TO_SOCKET_OR_NULL; - return size == sizeof(__u64); - -diff -purNx .git BPI-Router-Linux-kernel/net/core/gen_estimator.c BPI-Router-Linux-kernel-6.16.12/net/core/gen_estimator.c ---- BPI-Router-Linux-kernel/net/core/gen_estimator.c 2025-10-22 13:53:23.627327153 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/core/gen_estimator.c 2025-10-22 13:53:56.807167733 -0400 -@@ -90,10 +90,12 @@ static void est_timer(struct timer_list - rate = (b_packets - est->last_packets) << (10 - est->intvl_log); - rate = (rate >> est->ewma_log) - (est->avpps >> est->ewma_log); - -+ preempt_disable_nested(); - write_seqcount_begin(&est->seq); - est->avbps += brate; - est->avpps += rate; - write_seqcount_end(&est->seq); -+ preempt_enable_nested(); - - est->last_bytes = b_bytes; - est->last_packets = b_packets; -diff -purNx .git BPI-Router-Linux-kernel/net/core/ieee8021q_helpers.c BPI-Router-Linux-kernel-6.16.12/net/core/ieee8021q_helpers.c ---- BPI-Router-Linux-kernel/net/core/ieee8021q_helpers.c 2025-10-22 13:53:23.627327153 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/core/ieee8021q_helpers.c 2025-10-22 13:53:56.807167733 -0400 -@@ -7,6 +7,11 @@ - #include - #include - -+/* verify that table covers all 8 traffic types */ -+#define TT_MAP_SIZE_OK(tbl) \ -+ compiletime_assert(ARRAY_SIZE(tbl) == IEEE8021Q_TT_MAX, \ -+ #tbl " size mismatch") -+ - /* The following arrays map Traffic Types (TT) to traffic classes (TC) for - * different number of queues as shown in the example provided by - * IEEE 802.1Q-2022 in Annex I "I.3 Traffic type to traffic class mapping" and -@@ -101,51 +106,28 @@ int ieee8021q_tt_to_tc(enum ieee8021q_tr - - switch (num_queues) { - case 8: -- compiletime_assert(ARRAY_SIZE(ieee8021q_8queue_tt_tc_map) != -- IEEE8021Q_TT_MAX - 1, -- "ieee8021q_8queue_tt_tc_map != max - 1"); -+ TT_MAP_SIZE_OK(ieee8021q_8queue_tt_tc_map); - return ieee8021q_8queue_tt_tc_map[tt]; - case 7: -- compiletime_assert(ARRAY_SIZE(ieee8021q_7queue_tt_tc_map) != -- IEEE8021Q_TT_MAX - 1, -- "ieee8021q_7queue_tt_tc_map != max - 1"); -- -+ TT_MAP_SIZE_OK(ieee8021q_7queue_tt_tc_map); - return ieee8021q_7queue_tt_tc_map[tt]; - case 6: -- compiletime_assert(ARRAY_SIZE(ieee8021q_6queue_tt_tc_map) != -- IEEE8021Q_TT_MAX - 1, -- "ieee8021q_6queue_tt_tc_map != max - 1"); -- -+ TT_MAP_SIZE_OK(ieee8021q_6queue_tt_tc_map); - return ieee8021q_6queue_tt_tc_map[tt]; - case 5: -- compiletime_assert(ARRAY_SIZE(ieee8021q_5queue_tt_tc_map) != -- IEEE8021Q_TT_MAX - 1, -- "ieee8021q_5queue_tt_tc_map != max - 1"); -- -+ TT_MAP_SIZE_OK(ieee8021q_5queue_tt_tc_map); - return ieee8021q_5queue_tt_tc_map[tt]; - case 4: -- compiletime_assert(ARRAY_SIZE(ieee8021q_4queue_tt_tc_map) != -- IEEE8021Q_TT_MAX - 1, -- "ieee8021q_4queue_tt_tc_map != max - 1"); -- -+ TT_MAP_SIZE_OK(ieee8021q_4queue_tt_tc_map); - return ieee8021q_4queue_tt_tc_map[tt]; - case 3: -- compiletime_assert(ARRAY_SIZE(ieee8021q_3queue_tt_tc_map) != -- IEEE8021Q_TT_MAX - 1, -- "ieee8021q_3queue_tt_tc_map != max - 1"); -- -+ TT_MAP_SIZE_OK(ieee8021q_3queue_tt_tc_map); - return ieee8021q_3queue_tt_tc_map[tt]; - case 2: -- compiletime_assert(ARRAY_SIZE(ieee8021q_2queue_tt_tc_map) != -- IEEE8021Q_TT_MAX - 1, -- "ieee8021q_2queue_tt_tc_map != max - 1"); -- -+ TT_MAP_SIZE_OK(ieee8021q_2queue_tt_tc_map); - return ieee8021q_2queue_tt_tc_map[tt]; - case 1: -- compiletime_assert(ARRAY_SIZE(ieee8021q_1queue_tt_tc_map) != -- IEEE8021Q_TT_MAX - 1, -- "ieee8021q_1queue_tt_tc_map != max - 1"); -- -+ TT_MAP_SIZE_OK(ieee8021q_1queue_tt_tc_map); - return ieee8021q_1queue_tt_tc_map[tt]; - } - -diff -purNx .git BPI-Router-Linux-kernel/net/core/neighbour.c BPI-Router-Linux-kernel-6.16.12/net/core/neighbour.c ---- BPI-Router-Linux-kernel/net/core/neighbour.c 2025-10-22 13:53:23.627327153 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/core/neighbour.c 2025-10-22 13:53:56.807167733 -0400 -@@ -368,6 +368,43 @@ static void pneigh_queue_purge(struct sk - } - } - -+static void neigh_flush_one(struct neighbour *n) -+{ -+ hlist_del_rcu(&n->hash); -+ hlist_del_rcu(&n->dev_list); -+ -+ write_lock(&n->lock); -+ -+ neigh_del_timer(n); -+ neigh_mark_dead(n); -+ -+ if (refcount_read(&n->refcnt) != 1) { -+ /* The most unpleasant situation. -+ * We must destroy neighbour entry, -+ * but someone still uses it. -+ * -+ * The destroy will be delayed until -+ * the last user releases us, but -+ * we must kill timers etc. and move -+ * it to safe state. -+ */ -+ __skb_queue_purge(&n->arp_queue); -+ n->arp_queue_len_bytes = 0; -+ WRITE_ONCE(n->output, neigh_blackhole); -+ -+ if (n->nud_state & NUD_VALID) -+ n->nud_state = NUD_NOARP; -+ else -+ n->nud_state = NUD_NONE; -+ -+ neigh_dbg(2, "neigh %p is stray\n", n); -+ } -+ -+ write_unlock(&n->lock); -+ -+ neigh_cleanup_and_release(n); -+} -+ - static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev, - bool skip_perm) - { -@@ -381,32 +418,24 @@ static void neigh_flush_dev(struct neigh - if (skip_perm && n->nud_state & NUD_PERMANENT) - continue; - -- hlist_del_rcu(&n->hash); -- hlist_del_rcu(&n->dev_list); -- write_lock(&n->lock); -- neigh_del_timer(n); -- neigh_mark_dead(n); -- if (refcount_read(&n->refcnt) != 1) { -- /* The most unpleasant situation. -- * We must destroy neighbour entry, -- * but someone still uses it. -- * -- * The destroy will be delayed until -- * the last user releases us, but -- * we must kill timers etc. and move -- * it to safe state. -- */ -- __skb_queue_purge(&n->arp_queue); -- n->arp_queue_len_bytes = 0; -- WRITE_ONCE(n->output, neigh_blackhole); -- if (n->nud_state & NUD_VALID) -- n->nud_state = NUD_NOARP; -- else -- n->nud_state = NUD_NONE; -- neigh_dbg(2, "neigh %p is stray\n", n); -- } -- write_unlock(&n->lock); -- neigh_cleanup_and_release(n); -+ neigh_flush_one(n); -+ } -+} -+ -+static void neigh_flush_table(struct neigh_table *tbl) -+{ -+ struct neigh_hash_table *nht; -+ int i; -+ -+ nht = rcu_dereference_protected(tbl->nht, -+ lockdep_is_held(&tbl->lock)); -+ -+ for (i = 0; i < (1 << nht->hash_shift); i++) { -+ struct hlist_node *tmp; -+ struct neighbour *n; -+ -+ neigh_for_each_in_bucket_safe(n, tmp, &nht->hash_heads[i]) -+ neigh_flush_one(n); - } - } - -@@ -422,7 +451,12 @@ static int __neigh_ifdown(struct neigh_t - bool skip_perm) - { - write_lock_bh(&tbl->lock); -- neigh_flush_dev(tbl, dev, skip_perm); -+ if (likely(dev)) { -+ neigh_flush_dev(tbl, dev, skip_perm); -+ } else { -+ DEBUG_NET_WARN_ON_ONCE(skip_perm); -+ neigh_flush_table(tbl); -+ } - pneigh_ifdown_and_unlock(tbl, dev); - pneigh_queue_purge(&tbl->proxy_queue, dev ? dev_net(dev) : NULL, - tbl->family); -diff -purNx .git BPI-Router-Linux-kernel/net/core/netclassid_cgroup.c BPI-Router-Linux-kernel-6.16.12/net/core/netclassid_cgroup.c ---- BPI-Router-Linux-kernel/net/core/netclassid_cgroup.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/core/netclassid_cgroup.c 2025-10-22 13:53:56.807167733 -0400 -@@ -21,7 +21,9 @@ static inline struct cgroup_cls_state *c - struct cgroup_cls_state *task_cls_state(struct task_struct *p) - { - return css_cls_state(task_css_check(p, net_cls_cgrp_id, -- rcu_read_lock_bh_held())); -+ rcu_read_lock_held() || -+ rcu_read_lock_bh_held() || -+ rcu_read_lock_trace_held())); - } - EXPORT_SYMBOL_GPL(task_cls_state); - -diff -purNx .git BPI-Router-Linux-kernel/net/core/netpoll.c BPI-Router-Linux-kernel-6.16.12/net/core/netpoll.c ---- BPI-Router-Linux-kernel/net/core/netpoll.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/core/netpoll.c 2025-10-22 13:53:56.807167733 -0400 -@@ -432,6 +432,7 @@ int netpoll_send_udp(struct netpoll *np, - udph->dest = htons(np->remote_port); - udph->len = htons(udp_len); - -+ udph->check = 0; - if (np->ipv6) { - udph->check = csum_ipv6_magic(&np->local_ip.in6, - &np->remote_ip.in6, -@@ -460,7 +461,6 @@ int netpoll_send_udp(struct netpoll *np, - skb_reset_mac_header(skb); - skb->protocol = eth->h_proto = htons(ETH_P_IPV6); - } else { -- udph->check = 0; - udph->check = csum_tcpudp_magic(np->local_ip.ip, - np->remote_ip.ip, - udp_len, IPPROTO_UDP, -@@ -831,6 +831,13 @@ put_noaddr: - if (err) - goto flush; - rtnl_unlock(); -+ -+ /* Make sure all NAPI polls which started before dev->npinfo -+ * was visible have exited before we start calling NAPI poll. -+ * NAPI skips locking if dev->npinfo is NULL. -+ */ -+ synchronize_rcu(); -+ - return 0; - - flush: -diff -purNx .git BPI-Router-Linux-kernel/net/core/page_pool.c BPI-Router-Linux-kernel-6.16.12/net/core/page_pool.c ---- BPI-Router-Linux-kernel/net/core/page_pool.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/core/page_pool.c 2025-10-22 13:53:56.807167733 -0400 -@@ -287,8 +287,10 @@ static int page_pool_init(struct page_po - } - - if (pool->mp_ops) { -- if (!pool->dma_map || !pool->dma_sync) -- return -EOPNOTSUPP; -+ if (!pool->dma_map || !pool->dma_sync) { -+ err = -EOPNOTSUPP; -+ goto free_ptr_ring; -+ } - - if (WARN_ON(!is_kernel_rodata((unsigned long)pool->mp_ops))) { - err = -EFAULT; -@@ -1201,6 +1203,35 @@ void page_pool_use_xdp_mem(struct page_p - pool->xdp_mem_id = mem->id; - } - -+/** -+ * page_pool_enable_direct_recycling() - mark page pool as owned by NAPI -+ * @pool: page pool to modify -+ * @napi: NAPI instance to associate the page pool with -+ * -+ * Associate a page pool with a NAPI instance for lockless page recycling. -+ * This is useful when a new page pool has to be added to a NAPI instance -+ * without disabling that NAPI instance, to mark the point at which control -+ * path "hands over" the page pool to the NAPI instance. In most cases driver -+ * can simply set the @napi field in struct page_pool_params, and does not -+ * have to call this helper. -+ * -+ * The function is idempotent, but does not implement any refcounting. -+ * Single page_pool_disable_direct_recycling() will disable recycling, -+ * no matter how many times enable was called. -+ */ -+void page_pool_enable_direct_recycling(struct page_pool *pool, -+ struct napi_struct *napi) -+{ -+ if (READ_ONCE(pool->p.napi) == napi) -+ return; -+ WARN_ON(!napi || pool->p.napi); -+ -+ mutex_lock(&page_pools_lock); -+ WRITE_ONCE(pool->p.napi, napi); -+ mutex_unlock(&page_pools_lock); -+} -+EXPORT_SYMBOL(page_pool_enable_direct_recycling); -+ - void page_pool_disable_direct_recycling(struct page_pool *pool) - { - /* Disable direct recycling based on pool->cpuid. -diff -purNx .git BPI-Router-Linux-kernel/net/core/selftests.c BPI-Router-Linux-kernel-6.16.12/net/core/selftests.c ---- BPI-Router-Linux-kernel/net/core/selftests.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/core/selftests.c 2025-10-22 13:53:56.807167733 -0400 -@@ -160,8 +160,9 @@ static struct sk_buff *net_test_get_skb( - skb->csum = 0; - skb->ip_summed = CHECKSUM_PARTIAL; - if (attr->tcp) { -- thdr->check = ~tcp_v4_check(skb->len, ihdr->saddr, -- ihdr->daddr, 0); -+ int l4len = skb->len - skb_transport_offset(skb); -+ -+ thdr->check = ~tcp_v4_check(l4len, ihdr->saddr, ihdr->daddr, 0); - skb->csum_start = skb_transport_header(skb) - skb->head; - skb->csum_offset = offsetof(struct tcphdr, check); - } else { -diff -purNx .git BPI-Router-Linux-kernel/net/core/skbuff.c BPI-Router-Linux-kernel-6.16.12/net/core/skbuff.c ---- BPI-Router-Linux-kernel/net/core/skbuff.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/core/skbuff.c 2025-10-22 13:53:56.811167714 -0400 -@@ -6261,9 +6261,6 @@ int skb_ensure_writable(struct sk_buff * - if (!pskb_may_pull(skb, write_len)) - return -ENOMEM; - -- if (!skb_frags_readable(skb)) -- return -EFAULT; -- - if (!skb_cloned(skb) || skb_clone_writable(skb, write_len)) - return 0; - -@@ -6670,7 +6667,7 @@ struct sk_buff *alloc_skb_with_frags(uns - return NULL; - - while (data_len) { -- if (nr_frags == MAX_SKB_FRAGS - 1) -+ if (nr_frags == MAX_SKB_FRAGS) - goto failure; - while (order && PAGE_ALIGN(data_len) < (PAGE_SIZE << order)) - order--; -diff -purNx .git BPI-Router-Linux-kernel/net/core/skmsg.c BPI-Router-Linux-kernel-6.16.12/net/core/skmsg.c ---- BPI-Router-Linux-kernel/net/core/skmsg.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/core/skmsg.c 2025-10-22 13:53:56.811167714 -0400 -@@ -656,6 +656,13 @@ static void sk_psock_backlog(struct work - bool ingress; - int ret; - -+ /* If sk is quickly removed from the map and then added back, the old -+ * psock should not be scheduled, because there are now two psocks -+ * pointing to the same sk. -+ */ -+ if (!sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) -+ return; -+ - /* Increment the psock refcnt to synchronize with close(fd) path in - * sock_map_close(), ensuring we wait for backlog thread completion - * before sk_socket freed. If refcnt increment fails, it indicates -diff -purNx .git BPI-Router-Linux-kernel/net/core/sock.c BPI-Router-Linux-kernel-6.16.12/net/core/sock.c ---- BPI-Router-Linux-kernel/net/core/sock.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/core/sock.c 2025-10-22 13:53:56.811167714 -0400 -@@ -2602,8 +2602,8 @@ static u32 sk_dst_gso_max_size(struct so - !ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr)); - #endif - /* pairs with the WRITE_ONCE() in netif_set_gso(_ipv4)_max_size() */ -- max_size = is_ipv6 ? READ_ONCE(dst->dev->gso_max_size) : -- READ_ONCE(dst->dev->gso_ipv4_max_size); -+ max_size = is_ipv6 ? READ_ONCE(dst_dev(dst)->gso_max_size) : -+ READ_ONCE(dst_dev(dst)->gso_ipv4_max_size); - if (max_size > GSO_LEGACY_MAX_SIZE && !sk_is_tcp(sk)) - max_size = GSO_LEGACY_MAX_SIZE; - -@@ -2614,7 +2614,7 @@ void sk_setup_caps(struct sock *sk, stru - { - u32 max_segs = 1; - -- sk->sk_route_caps = dst->dev->features; -+ sk->sk_route_caps = dst_dev(dst)->features; - if (sk_is_tcp(sk)) { - struct inet_connection_sock *icsk = inet_csk(sk); - -@@ -2632,7 +2632,7 @@ void sk_setup_caps(struct sock *sk, stru - sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM; - sk->sk_gso_max_size = sk_dst_gso_max_size(sk, dst); - /* pairs with the WRITE_ONCE() in netif_set_gso_max_segs() */ -- max_segs = max_t(u32, READ_ONCE(dst->dev->gso_max_segs), 1); -+ max_segs = max_t(u32, READ_ONCE(dst_dev(dst)->gso_max_segs), 1); - } - } - sk->sk_gso_max_segs = max_segs; -@@ -2788,39 +2788,6 @@ void sock_pfree(struct sk_buff *skb) - EXPORT_SYMBOL(sock_pfree); - #endif /* CONFIG_INET */ - --kuid_t sock_i_uid(struct sock *sk) --{ -- kuid_t uid; -- -- read_lock_bh(&sk->sk_callback_lock); -- uid = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : GLOBAL_ROOT_UID; -- read_unlock_bh(&sk->sk_callback_lock); -- return uid; --} --EXPORT_SYMBOL(sock_i_uid); -- --unsigned long __sock_i_ino(struct sock *sk) --{ -- unsigned long ino; -- -- read_lock(&sk->sk_callback_lock); -- ino = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_ino : 0; -- read_unlock(&sk->sk_callback_lock); -- return ino; --} --EXPORT_SYMBOL(__sock_i_ino); -- --unsigned long sock_i_ino(struct sock *sk) --{ -- unsigned long ino; -- -- local_bh_disable(); -- ino = __sock_i_ino(sk); -- local_bh_enable(); -- return ino; --} --EXPORT_SYMBOL(sock_i_ino); -- - /* - * Allocate a skb from the socket's send buffer. - */ -diff -purNx .git BPI-Router-Linux-kernel/net/devlink/port.c BPI-Router-Linux-kernel-6.16.12/net/devlink/port.c ---- BPI-Router-Linux-kernel/net/devlink/port.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/devlink/port.c 2025-10-22 13:53:56.811167714 -0400 -@@ -1519,7 +1519,7 @@ static int __devlink_port_phys_port_name - struct devlink_port_attrs *attrs = &devlink_port->attrs; - int n = 0; - -- if (!devlink_port->attrs_set) -+ if (!devlink_port->attrs_set || devlink_port->attrs.no_phys_port_name) - return -EOPNOTSUPP; - - switch (attrs->flavour) { -diff -purNx .git BPI-Router-Linux-kernel/net/ethtool/ioctl.c BPI-Router-Linux-kernel-6.16.12/net/ethtool/ioctl.c ---- BPI-Router-Linux-kernel/net/ethtool/ioctl.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ethtool/ioctl.c 2025-10-22 13:53:56.811167714 -0400 -@@ -1083,7 +1083,8 @@ static noinline_for_stack int ethtool_se - ethtool_get_flow_spec_ring(info.fs.ring_cookie)) - return -EINVAL; - -- if (!xa_load(&dev->ethtool->rss_ctx, info.rss_context)) -+ if (info.rss_context && -+ !xa_load(&dev->ethtool->rss_ctx, info.rss_context)) - return -EINVAL; - } - -diff -purNx .git BPI-Router-Linux-kernel/net/hsr/hsr_device.c BPI-Router-Linux-kernel-6.16.12/net/hsr/hsr_device.c ---- BPI-Router-Linux-kernel/net/hsr/hsr_device.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/hsr/hsr_device.c 2025-10-22 13:53:56.811167714 -0400 -@@ -49,7 +49,7 @@ static bool hsr_check_carrier(struct hsr - - ASSERT_RTNL(); - -- hsr_for_each_port(master->hsr, port) { -+ hsr_for_each_port_rtnl(master->hsr, port) { - if (port->type != HSR_PT_MASTER && is_slave_up(port->dev)) { - netif_carrier_on(master->dev); - return true; -@@ -105,7 +105,7 @@ int hsr_get_max_mtu(struct hsr_priv *hsr - struct hsr_port *port; - - mtu_max = ETH_DATA_LEN; -- hsr_for_each_port(hsr, port) -+ hsr_for_each_port_rtnl(hsr, port) - if (port->type != HSR_PT_MASTER) - mtu_max = min(port->dev->mtu, mtu_max); - -@@ -139,7 +139,7 @@ static int hsr_dev_open(struct net_devic - - hsr = netdev_priv(dev); - -- hsr_for_each_port(hsr, port) { -+ hsr_for_each_port_rtnl(hsr, port) { - if (port->type == HSR_PT_MASTER) - continue; - switch (port->type) { -@@ -172,7 +172,7 @@ static int hsr_dev_close(struct net_devi - struct hsr_priv *hsr; - - hsr = netdev_priv(dev); -- hsr_for_each_port(hsr, port) { -+ hsr_for_each_port_rtnl(hsr, port) { - if (port->type == HSR_PT_MASTER) - continue; - switch (port->type) { -@@ -205,7 +205,7 @@ static netdev_features_t hsr_features_re - * may become enabled. - */ - features &= ~NETIF_F_ONE_FOR_ALL; -- hsr_for_each_port(hsr, port) -+ hsr_for_each_port_rtnl(hsr, port) - features = netdev_increment_features(features, - port->dev->features, - mask); -@@ -226,6 +226,7 @@ static netdev_tx_t hsr_dev_xmit(struct s - struct hsr_priv *hsr = netdev_priv(dev); - struct hsr_port *master; - -+ rcu_read_lock(); - master = hsr_port_get_hsr(hsr, HSR_PT_MASTER); - if (master) { - skb->dev = master->dev; -@@ -238,6 +239,8 @@ static netdev_tx_t hsr_dev_xmit(struct s - dev_core_stats_tx_dropped_inc(dev); - dev_kfree_skb_any(skb); - } -+ rcu_read_unlock(); -+ - return NETDEV_TX_OK; - } - -@@ -484,7 +487,7 @@ static void hsr_set_rx_mode(struct net_d - - hsr = netdev_priv(dev); - -- hsr_for_each_port(hsr, port) { -+ hsr_for_each_port_rtnl(hsr, port) { - if (port->type == HSR_PT_MASTER) - continue; - switch (port->type) { -@@ -506,7 +509,7 @@ static void hsr_change_rx_flags(struct n - - hsr = netdev_priv(dev); - -- hsr_for_each_port(hsr, port) { -+ hsr_for_each_port_rtnl(hsr, port) { - if (port->type == HSR_PT_MASTER) - continue; - switch (port->type) { -@@ -534,7 +537,7 @@ static int hsr_ndo_vlan_rx_add_vid(struc - - hsr = netdev_priv(dev); - -- hsr_for_each_port(hsr, port) { -+ hsr_for_each_port_rtnl(hsr, port) { - if (port->type == HSR_PT_MASTER || - port->type == HSR_PT_INTERLINK) - continue; -@@ -580,7 +583,7 @@ static int hsr_ndo_vlan_rx_kill_vid(stru - - hsr = netdev_priv(dev); - -- hsr_for_each_port(hsr, port) { -+ hsr_for_each_port_rtnl(hsr, port) { - switch (port->type) { - case HSR_PT_SLAVE_A: - case HSR_PT_SLAVE_B: -@@ -672,9 +675,14 @@ struct net_device *hsr_get_port_ndev(str - struct hsr_priv *hsr = netdev_priv(ndev); - struct hsr_port *port; - -+ rcu_read_lock(); - hsr_for_each_port(hsr, port) -- if (port->type == pt) -+ if (port->type == pt) { -+ dev_hold(port->dev); -+ rcu_read_unlock(); - return port->dev; -+ } -+ rcu_read_unlock(); - return NULL; - } - EXPORT_SYMBOL(hsr_get_port_ndev); -diff -purNx .git BPI-Router-Linux-kernel/net/hsr/hsr_main.c BPI-Router-Linux-kernel-6.16.12/net/hsr/hsr_main.c ---- BPI-Router-Linux-kernel/net/hsr/hsr_main.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/hsr/hsr_main.c 2025-10-22 13:53:56.811167714 -0400 -@@ -22,7 +22,7 @@ static bool hsr_slave_empty(struct hsr_p - { - struct hsr_port *port; - -- hsr_for_each_port(hsr, port) -+ hsr_for_each_port_rtnl(hsr, port) - if (port->type != HSR_PT_MASTER) - return false; - return true; -@@ -134,7 +134,7 @@ struct hsr_port *hsr_port_get_hsr(struct - { - struct hsr_port *port; - -- hsr_for_each_port(hsr, port) -+ hsr_for_each_port_rtnl(hsr, port) - if (port->type == pt) - return port; - return NULL; -diff -purNx .git BPI-Router-Linux-kernel/net/hsr/hsr_main.h BPI-Router-Linux-kernel-6.16.12/net/hsr/hsr_main.h ---- BPI-Router-Linux-kernel/net/hsr/hsr_main.h 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/hsr/hsr_main.h 2025-10-22 13:53:56.811167714 -0400 -@@ -224,6 +224,9 @@ struct hsr_priv { - #define hsr_for_each_port(hsr, port) \ - list_for_each_entry_rcu((port), &(hsr)->ports, port_list) - -+#define hsr_for_each_port_rtnl(hsr, port) \ -+ list_for_each_entry_rcu((port), &(hsr)->ports, port_list, lockdep_rtnl_is_held()) -+ - struct hsr_port *hsr_port_get_hsr(struct hsr_priv *hsr, enum hsr_port_type pt); - - /* Caller must ensure skb is a valid HSR frame */ -diff -purNx .git BPI-Router-Linux-kernel/net/hsr/hsr_slave.c BPI-Router-Linux-kernel-6.16.12/net/hsr/hsr_slave.c ---- BPI-Router-Linux-kernel/net/hsr/hsr_slave.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/hsr/hsr_slave.c 2025-10-22 13:53:56.811167714 -0400 -@@ -63,8 +63,14 @@ static rx_handler_result_t hsr_handle_fr - skb_push(skb, ETH_HLEN); - skb_reset_mac_header(skb); - if ((!hsr->prot_version && protocol == htons(ETH_P_PRP)) || -- protocol == htons(ETH_P_HSR)) -+ protocol == htons(ETH_P_HSR)) { -+ if (!pskb_may_pull(skb, ETH_HLEN + HSR_HLEN)) { -+ kfree_skb(skb); -+ goto finish_consume; -+ } -+ - skb_set_network_header(skb, ETH_HLEN + HSR_HLEN); -+ } - skb_reset_mac_len(skb); - - /* Only the frames received over the interlink port will assign a -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/devinet.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/devinet.c ---- BPI-Router-Linux-kernel/net/ipv4/devinet.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/devinet.c 2025-10-22 13:53:56.811167714 -0400 -@@ -340,14 +340,13 @@ static void inetdev_destroy(struct in_de - - static int __init inet_blackhole_dev_init(void) - { -- int err = 0; -+ struct in_device *in_dev; - - rtnl_lock(); -- if (!inetdev_init(blackhole_netdev)) -- err = -ENOMEM; -+ in_dev = inetdev_init(blackhole_netdev); - rtnl_unlock(); - -- return err; -+ return PTR_ERR_OR_ZERO(in_dev); - } - late_initcall(inet_blackhole_dev_init); - -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/icmp.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/icmp.c ---- BPI-Router-Linux-kernel/net/ipv4/icmp.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/icmp.c 2025-10-22 13:53:56.811167714 -0400 -@@ -797,11 +797,12 @@ void icmp_ndo_send(struct sk_buff *skb_i - struct sk_buff *cloned_skb = NULL; - struct ip_options opts = { 0 }; - enum ip_conntrack_info ctinfo; -+ enum ip_conntrack_dir dir; - struct nf_conn *ct; - __be32 orig_ip; - - ct = nf_ct_get(skb_in, &ctinfo); -- if (!ct || !(ct->status & IPS_SRC_NAT)) { -+ if (!ct || !(READ_ONCE(ct->status) & IPS_NAT_MASK)) { - __icmp_send(skb_in, type, code, info, &opts); - return; - } -@@ -816,7 +817,8 @@ void icmp_ndo_send(struct sk_buff *skb_i - goto out; - - orig_ip = ip_hdr(skb_in)->saddr; -- ip_hdr(skb_in)->saddr = ct->tuplehash[0].tuple.src.u3.ip; -+ dir = CTINFO2DIR(ctinfo); -+ ip_hdr(skb_in)->saddr = ct->tuplehash[dir].tuple.src.u3.ip; - __icmp_send(skb_in, type, code, info, &opts); - ip_hdr(skb_in)->saddr = orig_ip; - out: -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/inet_connection_sock.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/inet_connection_sock.c ---- BPI-Router-Linux-kernel/net/ipv4/inet_connection_sock.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/inet_connection_sock.c 2025-10-22 13:53:56.811167714 -0400 -@@ -168,7 +168,7 @@ static bool inet_use_bhash2_on_bind(cons - } - - static bool inet_bind_conflict(const struct sock *sk, struct sock *sk2, -- kuid_t sk_uid, bool relax, -+ kuid_t uid, bool relax, - bool reuseport_cb_ok, bool reuseport_ok) - { - int bound_dev_if2; -@@ -185,12 +185,12 @@ static bool inet_bind_conflict(const str - if (!relax || (!reuseport_ok && sk->sk_reuseport && - sk2->sk_reuseport && reuseport_cb_ok && - (sk2->sk_state == TCP_TIME_WAIT || -- uid_eq(sk_uid, sock_i_uid(sk2))))) -+ uid_eq(uid, sk_uid(sk2))))) - return true; - } else if (!reuseport_ok || !sk->sk_reuseport || - !sk2->sk_reuseport || !reuseport_cb_ok || - (sk2->sk_state != TCP_TIME_WAIT && -- !uid_eq(sk_uid, sock_i_uid(sk2)))) { -+ !uid_eq(uid, sk_uid(sk2)))) { - return true; - } - } -@@ -198,7 +198,7 @@ static bool inet_bind_conflict(const str - } - - static bool __inet_bhash2_conflict(const struct sock *sk, struct sock *sk2, -- kuid_t sk_uid, bool relax, -+ kuid_t uid, bool relax, - bool reuseport_cb_ok, bool reuseport_ok) - { - if (ipv6_only_sock(sk2)) { -@@ -211,20 +211,20 @@ static bool __inet_bhash2_conflict(const - #endif - } - -- return inet_bind_conflict(sk, sk2, sk_uid, relax, -+ return inet_bind_conflict(sk, sk2, uid, relax, - reuseport_cb_ok, reuseport_ok); - } - - static bool inet_bhash2_conflict(const struct sock *sk, - const struct inet_bind2_bucket *tb2, -- kuid_t sk_uid, -+ kuid_t uid, - bool relax, bool reuseport_cb_ok, - bool reuseport_ok) - { - struct sock *sk2; - - sk_for_each_bound(sk2, &tb2->owners) { -- if (__inet_bhash2_conflict(sk, sk2, sk_uid, relax, -+ if (__inet_bhash2_conflict(sk, sk2, uid, relax, - reuseport_cb_ok, reuseport_ok)) - return true; - } -@@ -242,8 +242,8 @@ static int inet_csk_bind_conflict(const - const struct inet_bind2_bucket *tb2, /* may be null */ - bool relax, bool reuseport_ok) - { -- kuid_t uid = sock_i_uid((struct sock *)sk); - struct sock_reuseport *reuseport_cb; -+ kuid_t uid = sk_uid(sk); - bool reuseport_cb_ok; - struct sock *sk2; - -@@ -287,11 +287,11 @@ static int inet_csk_bind_conflict(const - static bool inet_bhash2_addr_any_conflict(const struct sock *sk, int port, int l3mdev, - bool relax, bool reuseport_ok) - { -- kuid_t uid = sock_i_uid((struct sock *)sk); - const struct net *net = sock_net(sk); - struct sock_reuseport *reuseport_cb; - struct inet_bind_hashbucket *head2; - struct inet_bind2_bucket *tb2; -+ kuid_t uid = sk_uid(sk); - bool conflict = false; - bool reuseport_cb_ok; - -@@ -425,15 +425,13 @@ success: - static inline int sk_reuseport_match(struct inet_bind_bucket *tb, - struct sock *sk) - { -- kuid_t uid = sock_i_uid(sk); -- - if (tb->fastreuseport <= 0) - return 0; - if (!sk->sk_reuseport) - return 0; - if (rcu_access_pointer(sk->sk_reuseport_cb)) - return 0; -- if (!uid_eq(tb->fastuid, uid)) -+ if (!uid_eq(tb->fastuid, sk_uid(sk))) - return 0; - /* We only need to check the rcv_saddr if this tb was once marked - * without fastreuseport and then was reset, as we can only know that -@@ -458,14 +456,13 @@ static inline int sk_reuseport_match(str - void inet_csk_update_fastreuse(struct inet_bind_bucket *tb, - struct sock *sk) - { -- kuid_t uid = sock_i_uid(sk); - bool reuse = sk->sk_reuse && sk->sk_state != TCP_LISTEN; - - if (hlist_empty(&tb->bhash2)) { - tb->fastreuse = reuse; - if (sk->sk_reuseport) { - tb->fastreuseport = FASTREUSEPORT_ANY; -- tb->fastuid = uid; -+ tb->fastuid = sk_uid(sk); - tb->fast_rcv_saddr = sk->sk_rcv_saddr; - tb->fast_ipv6_only = ipv6_only_sock(sk); - tb->fast_sk_family = sk->sk_family; -@@ -492,7 +489,7 @@ void inet_csk_update_fastreuse(struct in - */ - if (!sk_reuseport_match(tb, sk)) { - tb->fastreuseport = FASTREUSEPORT_STRICT; -- tb->fastuid = uid; -+ tb->fastuid = sk_uid(sk); - tb->fast_rcv_saddr = sk->sk_rcv_saddr; - tb->fast_ipv6_only = ipv6_only_sock(sk); - tb->fast_sk_family = sk->sk_family; -@@ -812,7 +809,7 @@ struct dst_entry *inet_csk_route_req(con - sk->sk_protocol, inet_sk_flowi_flags(sk), - (opt && opt->opt.srr) ? opt->opt.faddr : ireq->ir_rmt_addr, - ireq->ir_loc_addr, ireq->ir_rmt_port, -- htons(ireq->ir_num), sk->sk_uid); -+ htons(ireq->ir_num), sk_uid(sk)); - security_req_classify_flow(req, flowi4_to_flowi_common(fl4)); - rt = ip_route_output_flow(net, fl4, sk); - if (IS_ERR(rt)) -@@ -849,7 +846,7 @@ struct dst_entry *inet_csk_route_child_s - sk->sk_protocol, inet_sk_flowi_flags(sk), - (opt && opt->opt.srr) ? opt->opt.faddr : ireq->ir_rmt_addr, - ireq->ir_loc_addr, ireq->ir_rmt_port, -- htons(ireq->ir_num), sk->sk_uid); -+ htons(ireq->ir_num), sk_uid(sk)); - security_req_classify_flow(req, flowi4_to_flowi_common(fl4)); - rt = ip_route_output_flow(net, fl4, sk); - if (IS_ERR(rt)) -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/inet_diag.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/inet_diag.c ---- BPI-Router-Linux-kernel/net/ipv4/inet_diag.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/inet_diag.c 2025-10-22 13:53:56.811167714 -0400 -@@ -181,7 +181,7 @@ int inet_diag_msg_attrs_fill(struct sock - goto errout; - #endif - -- r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk)); -+ r->idiag_uid = from_kuid_munged(user_ns, sk_uid(sk)); - r->idiag_inode = sock_i_ino(sk); - - memset(&inet_sockopt, 0, sizeof(inet_sockopt)); -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/inet_hashtables.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/inet_hashtables.c ---- BPI-Router-Linux-kernel/net/ipv4/inet_hashtables.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/inet_hashtables.c 2025-10-22 13:53:56.811167714 -0400 -@@ -721,8 +721,8 @@ static int inet_reuseport_add_sock(struc - { - struct inet_bind_bucket *tb = inet_csk(sk)->icsk_bind_hash; - const struct hlist_nulls_node *node; -+ kuid_t uid = sk_uid(sk); - struct sock *sk2; -- kuid_t uid = sock_i_uid(sk); - - sk_nulls_for_each_rcu(sk2, node, &ilb->nulls_head) { - if (sk2 != sk && -@@ -730,7 +730,7 @@ static int inet_reuseport_add_sock(struc - ipv6_only_sock(sk2) == ipv6_only_sock(sk) && - sk2->sk_bound_dev_if == sk->sk_bound_dev_if && - inet_csk(sk2)->icsk_bind_hash == tb && -- sk2->sk_reuseport && uid_eq(uid, sock_i_uid(sk2)) && -+ sk2->sk_reuseport && uid_eq(uid, sk_uid(sk2)) && - inet_rcv_saddr_equal(sk, sk2, false)) - return reuseport_add_sock(sk, sk2, - inet_rcv_saddr_any(sk)); -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/ipcomp.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/ipcomp.c ---- BPI-Router-Linux-kernel/net/ipv4/ipcomp.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/ipcomp.c 2025-10-22 13:53:56.811167714 -0400 -@@ -54,6 +54,7 @@ static int ipcomp4_err(struct sk_buff *s - } - - /* We always hold one tunnel user reference to indicate a tunnel */ -+static struct lock_class_key xfrm_state_lock_key; - static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x) - { - struct net *net = xs_net(x); -@@ -62,6 +63,7 @@ static struct xfrm_state *ipcomp_tunnel_ - t = xfrm_state_alloc(net); - if (!t) - goto out; -+ lockdep_set_class(&t->lock, &xfrm_state_lock_key); - - t->id.proto = IPPROTO_IPIP; - t->id.spi = x->props.saddr.a4; -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/ip_input.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/ip_input.c ---- BPI-Router-Linux-kernel/net/ipv4/ip_input.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/ip_input.c 2025-10-22 13:53:56.811167714 -0400 -@@ -319,8 +319,8 @@ static int ip_rcv_finish_core(struct net - const struct sk_buff *hint) - { - const struct iphdr *iph = ip_hdr(skb); -- int err, drop_reason; - struct rtable *rt; -+ int drop_reason; - - if (ip_can_use_hint(skb, iph, hint)) { - drop_reason = ip_route_use_hint(skb, iph->daddr, iph->saddr, -@@ -345,9 +345,10 @@ static int ip_rcv_finish_core(struct net - break; - case IPPROTO_UDP: - if (READ_ONCE(net->ipv4.sysctl_udp_early_demux)) { -- err = udp_v4_early_demux(skb); -- if (unlikely(err)) -+ drop_reason = udp_v4_early_demux(skb); -+ if (unlikely(drop_reason)) - goto drop_error; -+ drop_reason = SKB_DROP_REASON_NOT_SPECIFIED; - - /* must reload iph, skb->head might have changed */ - iph = ip_hdr(skb); -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/ip_tunnel_core.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/ip_tunnel_core.c ---- BPI-Router-Linux-kernel/net/ipv4/ip_tunnel_core.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/ip_tunnel_core.c 2025-10-22 13:53:56.811167714 -0400 -@@ -204,6 +204,9 @@ static int iptunnel_pmtud_build_icmp(str - if (!pskb_may_pull(skb, ETH_HLEN + sizeof(struct iphdr))) - return -EINVAL; - -+ if (skb_is_gso(skb)) -+ skb_gso_reset(skb); -+ - skb_copy_bits(skb, skb_mac_offset(skb), &eh, ETH_HLEN); - pskb_pull(skb, ETH_HLEN); - skb_reset_network_header(skb); -@@ -298,6 +301,9 @@ static int iptunnel_pmtud_build_icmpv6(s - if (!pskb_may_pull(skb, ETH_HLEN + sizeof(struct ipv6hdr))) - return -EINVAL; - -+ if (skb_is_gso(skb)) -+ skb_gso_reset(skb); -+ - skb_copy_bits(skb, skb_mac_offset(skb), &eh, ETH_HLEN); - pskb_pull(skb, ETH_HLEN); - skb_reset_network_header(skb); -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/netfilter/nf_reject_ipv4.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/netfilter/nf_reject_ipv4.c ---- BPI-Router-Linux-kernel/net/ipv4/netfilter/nf_reject_ipv4.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/netfilter/nf_reject_ipv4.c 2025-10-22 13:53:56.811167714 -0400 -@@ -247,8 +247,7 @@ void nf_send_reset(struct net *net, stru - if (!oth) - return; - -- if ((hook == NF_INET_PRE_ROUTING || hook == NF_INET_INGRESS) && -- nf_reject_fill_skb_dst(oldskb) < 0) -+ if (!skb_dst(oldskb) && nf_reject_fill_skb_dst(oldskb) < 0) - return; - - if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) -@@ -321,8 +320,7 @@ void nf_send_unreach(struct sk_buff *skb - if (iph->frag_off & htons(IP_OFFSET)) - return; - -- if ((hook == NF_INET_PRE_ROUTING || hook == NF_INET_INGRESS) && -- nf_reject_fill_skb_dst(skb_in) < 0) -+ if (!skb_dst(skb_in) && nf_reject_fill_skb_dst(skb_in) < 0) - return; - - if (skb_csum_unnecessary(skb_in) || -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/nexthop.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/nexthop.c ---- BPI-Router-Linux-kernel/net/ipv4/nexthop.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/nexthop.c 2025-10-22 13:53:56.811167714 -0400 -@@ -2400,6 +2400,13 @@ static int replace_nexthop_single(struct - return -EINVAL; - } - -+ if (!list_empty(&old->grp_list) && -+ rtnl_dereference(new->nh_info)->fdb_nh != -+ rtnl_dereference(old->nh_info)->fdb_nh) { -+ NL_SET_ERR_MSG(extack, "Cannot change nexthop FDB status while in a group"); -+ return -EINVAL; -+ } -+ - err = call_nexthop_notifiers(net, NEXTHOP_EVENT_REPLACE, new, extack); - if (err) - return err; -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/ping.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/ping.c ---- BPI-Router-Linux-kernel/net/ipv4/ping.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/ping.c 2025-10-22 13:53:56.811167714 -0400 -@@ -781,7 +781,7 @@ static int ping_v4_sendmsg(struct sock * - flowi4_init_output(&fl4, ipc.oif, ipc.sockc.mark, - ipc.tos & INET_DSCP_MASK, scope, - sk->sk_protocol, inet_sk_flowi_flags(sk), faddr, -- saddr, 0, 0, sk->sk_uid); -+ saddr, 0, 0, sk_uid(sk)); - - fl4.fl4_icmp_type = user_icmph.type; - fl4.fl4_icmp_code = user_icmph.code; -@@ -1116,7 +1116,7 @@ static void ping_v4_format_sock(struct s - sk_wmem_alloc_get(sp), - sk_rmem_alloc_get(sp), - 0, 0L, 0, -- from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)), -+ from_kuid_munged(seq_user_ns(f), sk_uid(sp)), - 0, sock_i_ino(sp), - refcount_read(&sp->sk_refcnt), sp, - atomic_read(&sp->sk_drops)); -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/raw.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/raw.c ---- BPI-Router-Linux-kernel/net/ipv4/raw.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/raw.c 2025-10-22 13:53:56.811167714 -0400 -@@ -610,7 +610,7 @@ static int raw_sendmsg(struct sock *sk, - hdrincl ? ipc.protocol : sk->sk_protocol, - inet_sk_flowi_flags(sk) | - (hdrincl ? FLOWI_FLAG_KNOWN_NH : 0), -- daddr, saddr, 0, 0, sk->sk_uid); -+ daddr, saddr, 0, 0, sk_uid(sk)); - - fl4.fl4_icmp_type = 0; - fl4.fl4_icmp_code = 0; -@@ -1043,7 +1043,7 @@ static void raw_sock_seq_show(struct seq - sk_wmem_alloc_get(sp), - sk_rmem_alloc_get(sp), - 0, 0L, 0, -- from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)), -+ from_kuid_munged(seq_user_ns(seq), sk_uid(sp)), - 0, sock_i_ino(sp), - refcount_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops)); - } -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/route.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/route.c ---- BPI-Router-Linux-kernel/net/ipv4/route.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/route.c 2025-10-22 13:53:56.811167714 -0400 -@@ -556,7 +556,8 @@ static void build_sk_flow_key(struct flo - inet_test_bit(HDRINCL, sk) ? - IPPROTO_RAW : sk->sk_protocol, - inet_sk_flowi_flags(sk), -- daddr, inet->inet_saddr, 0, 0, sk->sk_uid); -+ daddr, inet->inet_saddr, 0, 0, -+ sk_uid(sk)); - rcu_read_unlock(); - } - -@@ -1684,8 +1685,8 @@ struct rtable *rt_dst_clone(struct net_d - else if (rt->rt_gw_family == AF_INET6) - new_rt->rt_gw6 = rt->rt_gw6; - -- new_rt->dst.input = rt->dst.input; -- new_rt->dst.output = rt->dst.output; -+ new_rt->dst.input = READ_ONCE(rt->dst.input); -+ new_rt->dst.output = READ_ONCE(rt->dst.output); - new_rt->dst.error = rt->dst.error; - new_rt->dst.lastuse = jiffies; - new_rt->dst.lwtstate = lwtstate_get(rt->dst.lwtstate); -@@ -2572,12 +2573,16 @@ static struct rtable *__mkroute_output(c - !netif_is_l3_master(dev_out)) - return ERR_PTR(-EINVAL); - -- if (ipv4_is_lbcast(fl4->daddr)) -+ if (ipv4_is_lbcast(fl4->daddr)) { - type = RTN_BROADCAST; -- else if (ipv4_is_multicast(fl4->daddr)) -+ -+ /* reset fi to prevent gateway resolution */ -+ fi = NULL; -+ } else if (ipv4_is_multicast(fl4->daddr)) { - type = RTN_MULTICAST; -- else if (ipv4_is_zeronet(fl4->daddr)) -+ } else if (ipv4_is_zeronet(fl4->daddr)) { - return ERR_PTR(-EINVAL); -+ } - - if (dev_out->flags & IFF_LOOPBACK) - flags |= RTCF_LOCAL; -@@ -2585,7 +2590,6 @@ static struct rtable *__mkroute_output(c - do_cache = true; - if (type == RTN_BROADCAST) { - flags |= RTCF_BROADCAST | RTCF_LOCAL; -- fi = NULL; - } else if (type == RTN_MULTICAST) { - flags |= RTCF_MULTICAST | RTCF_LOCAL; - if (!ip_check_mc_rcu(in_dev, fl4->daddr, fl4->saddr, -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/syncookies.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/syncookies.c ---- BPI-Router-Linux-kernel/net/ipv4/syncookies.c 2025-10-22 13:53:23.631327134 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/syncookies.c 2025-10-22 13:53:56.811167714 -0400 -@@ -454,7 +454,8 @@ struct sock *cookie_v4_check(struct sock - ip_sock_rt_tos(sk), ip_sock_rt_scope(sk), - IPPROTO_TCP, inet_sk_flowi_flags(sk), - opt->srr ? opt->faddr : ireq->ir_rmt_addr, -- ireq->ir_loc_addr, th->source, th->dest, sk->sk_uid); -+ ireq->ir_loc_addr, th->source, th->dest, -+ sk_uid(sk)); - security_req_classify_flow(req, flowi4_to_flowi_common(&fl4)); - rt = ip_route_output_key(net, &fl4); - if (IS_ERR(rt)) { -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/tcp_ao.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/tcp_ao.c ---- BPI-Router-Linux-kernel/net/ipv4/tcp_ao.c 2025-10-22 13:53:23.635327115 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/tcp_ao.c 2025-10-22 13:53:56.811167714 -0400 -@@ -1178,7 +1178,9 @@ void tcp_ao_finish_connect(struct sock * - if (!ao) - return; - -- WRITE_ONCE(ao->risn, tcp_hdr(skb)->seq); -+ /* sk with TCP_REPAIR_ON does not have skb in tcp_finish_connect */ -+ if (skb) -+ WRITE_ONCE(ao->risn, tcp_hdr(skb)->seq); - ao->rcv_sne = 0; - - hlist_for_each_entry_rcu(key, &ao->head, node, lockdep_sock_is_held(sk)) -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/tcp_bpf.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/tcp_bpf.c ---- BPI-Router-Linux-kernel/net/ipv4/tcp_bpf.c 2025-10-22 13:53:23.635327115 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/tcp_bpf.c 2025-10-22 13:53:56.811167714 -0400 -@@ -408,8 +408,11 @@ more_data: - if (!psock->cork) { - psock->cork = kzalloc(sizeof(*psock->cork), - GFP_ATOMIC | __GFP_NOWARN); -- if (!psock->cork) -+ if (!psock->cork) { -+ sk_msg_free(sk, msg); -+ *copied = 0; - return -ENOMEM; -+ } - } - memcpy(psock->cork, msg, sizeof(*msg)); - return 0; -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/tcp.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/tcp.c ---- BPI-Router-Linux-kernel/net/ipv4/tcp.c 2025-10-22 13:53:23.635327115 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/tcp.c 2025-10-22 13:53:56.811167714 -0400 -@@ -1176,7 +1176,7 @@ restart: - goto do_error; - - while (msg_data_left(msg)) { -- ssize_t copy = 0; -+ int copy = 0; - - skb = tcp_write_queue_tail(sk); - if (skb) -@@ -3330,6 +3330,7 @@ int tcp_disconnect(struct sock *sk, int - struct inet_connection_sock *icsk = inet_csk(sk); - struct tcp_sock *tp = tcp_sk(sk); - int old_state = sk->sk_state; -+ struct request_sock *req; - u32 seq; - - if (old_state != TCP_CLOSE) -@@ -3445,6 +3446,10 @@ int tcp_disconnect(struct sock *sk, int - - - /* Clean up fastopen related fields */ -+ req = rcu_dereference_protected(tp->fastopen_rsk, -+ lockdep_sock_is_held(sk)); -+ if (req) -+ reqsk_fastopen_remove(sk, req, false); - tcp_free_fastopen_req(tp); - inet_clear_bit(DEFER_CONNECT, sk); - tp->fastopen_client_fail = 0; -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/tcp_fastopen.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/tcp_fastopen.c ---- BPI-Router-Linux-kernel/net/ipv4/tcp_fastopen.c 2025-10-22 13:53:23.635327115 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/tcp_fastopen.c 2025-10-22 13:53:56.811167714 -0400 -@@ -3,6 +3,7 @@ - #include - #include - #include -+#include - - void tcp_fastopen_init_key_once(struct net *net) - { -@@ -279,6 +280,8 @@ static struct sock *tcp_fastopen_create_ - - refcount_set(&req->rsk_refcnt, 2); - -+ sk_mark_napi_id_set(child, skb); -+ - /* Now finish processing the fastopen child socket. */ - tcp_init_transfer(child, BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB, skb); - -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/tcp_input.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/tcp_input.c ---- BPI-Router-Linux-kernel/net/ipv4/tcp_input.c 2025-10-22 13:53:23.635327115 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/tcp_input.c 2025-10-22 13:53:56.815167695 -0400 -@@ -2479,20 +2479,33 @@ static inline bool tcp_packet_delayed(co - { - const struct sock *sk = (const struct sock *)tp; - -- if (tp->retrans_stamp && -- tcp_tsopt_ecr_before(tp, tp->retrans_stamp)) -- return true; /* got echoed TS before first retransmission */ -- -- /* Check if nothing was retransmitted (retrans_stamp==0), which may -- * happen in fast recovery due to TSQ. But we ignore zero retrans_stamp -- * in TCP_SYN_SENT, since when we set FLAG_SYN_ACKED we also clear -- * retrans_stamp even if we had retransmitted the SYN. -- */ -- if (!tp->retrans_stamp && /* no record of a retransmit/SYN? */ -- sk->sk_state != TCP_SYN_SENT) /* not the FLAG_SYN_ACKED case? */ -- return true; /* nothing was retransmitted */ -+ /* Received an echoed timestamp before the first retransmission? */ -+ if (tp->retrans_stamp) -+ return tcp_tsopt_ecr_before(tp, tp->retrans_stamp); -+ -+ /* We set tp->retrans_stamp upon the first retransmission of a loss -+ * recovery episode, so normally if tp->retrans_stamp is 0 then no -+ * retransmission has happened yet (likely due to TSQ, which can cause -+ * fast retransmits to be delayed). So if snd_una advanced while -+ * (tp->retrans_stamp is 0 then apparently a packet was merely delayed, -+ * not lost. But there are exceptions where we retransmit but then -+ * clear tp->retrans_stamp, so we check for those exceptions. -+ */ - -- return false; -+ /* (1) For non-SACK connections, tcp_is_non_sack_preventing_reopen() -+ * clears tp->retrans_stamp when snd_una == high_seq. -+ */ -+ if (!tcp_is_sack(tp) && !before(tp->snd_una, tp->high_seq)) -+ return false; -+ -+ /* (2) In TCP_SYN_SENT tcp_clean_rtx_queue() clears tp->retrans_stamp -+ * when setting FLAG_SYN_ACKED is set, even if the SYN was -+ * retransmitted. -+ */ -+ if (sk->sk_state == TCP_SYN_SENT) -+ return false; -+ -+ return true; /* tp->retrans_stamp is zero; no retransmit yet */ - } - - /* Undo procedures. */ -@@ -4972,8 +4985,9 @@ static void tcp_ofo_queue(struct sock *s - - if (before(TCP_SKB_CB(skb)->seq, dsack_high)) { - __u32 dsack = dsack_high; -+ - if (before(TCP_SKB_CB(skb)->end_seq, dsack_high)) -- dsack_high = TCP_SKB_CB(skb)->end_seq; -+ dsack = TCP_SKB_CB(skb)->end_seq; - tcp_dsack_extend(sk, TCP_SKB_CB(skb)->seq, dsack); - } - p = rb_next(p); -@@ -5041,6 +5055,7 @@ static void tcp_data_queue_ofo(struct so - return; - } - -+ tcp_measure_rcv_mss(sk, skb); - /* Disable header prediction. */ - tp->pred_flags = 0; - inet_csk_schedule_ack(sk); -@@ -5168,7 +5183,9 @@ end: - skb_condense(skb); - skb_set_owner_r(skb, sk); - } -- tcp_rcvbuf_grow(sk); -+ /* do not grow rcvbuf for not-yet-accepted or orphaned sockets. */ -+ if (sk->sk_socket) -+ tcp_rcvbuf_grow(sk); - } - - static int __must_check tcp_queue_rcv(struct sock *sk, struct sk_buff *skb, -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/tcp_ipv4.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/tcp_ipv4.c ---- BPI-Router-Linux-kernel/net/ipv4/tcp_ipv4.c 2025-10-22 13:53:23.635327115 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/tcp_ipv4.c 2025-10-22 13:53:56.815167695 -0400 -@@ -2896,7 +2896,7 @@ static void get_openreq4(const struct re - jiffies_delta_to_clock_t(delta), - req->num_timeout, - from_kuid_munged(seq_user_ns(f), -- sock_i_uid(req->rsk_listener)), -+ sk_uid(req->rsk_listener)), - 0, /* non standard timer */ - 0, /* open_requests have no inode */ - 0, -@@ -2954,7 +2954,7 @@ static void get_tcp4_sock(struct sock *s - timer_active, - jiffies_delta_to_clock_t(timer_expires - jiffies), - icsk->icsk_retransmits, -- from_kuid_munged(seq_user_ns(f), sock_i_uid(sk)), -+ from_kuid_munged(seq_user_ns(f), sk_uid(sk)), - icsk->icsk_probes_out, - sock_i_ino(sk), - refcount_read(&sk->sk_refcnt), sk, -@@ -3246,9 +3246,9 @@ static int bpf_iter_tcp_seq_show(struct - const struct request_sock *req = v; - - uid = from_kuid_munged(seq_user_ns(seq), -- sock_i_uid(req->rsk_listener)); -+ sk_uid(req->rsk_listener)); - } else { -- uid = from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)); -+ uid = from_kuid_munged(seq_user_ns(seq), sk_uid(sk)); - } - - meta.seq = seq; -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/tcp_offload.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/tcp_offload.c ---- BPI-Router-Linux-kernel/net/ipv4/tcp_offload.c 2025-10-22 13:53:23.635327115 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/tcp_offload.c 2025-10-22 13:53:56.815167695 -0400 -@@ -359,6 +359,7 @@ struct sk_buff *tcp_gro_receive(struct l - flush |= skb->ip_summed != p->ip_summed; - flush |= skb->csum_level != p->csum_level; - flush |= NAPI_GRO_CB(p)->count >= 64; -+ skb_set_network_header(skb, skb_gro_receive_network_offset(skb)); - - if (flush || skb_gro_receive_list(p, skb)) - mss = 1; -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/udp.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/udp.c ---- BPI-Router-Linux-kernel/net/ipv4/udp.c 2025-10-22 13:53:23.635327115 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/udp.c 2025-10-22 13:53:56.815167695 -0400 -@@ -145,8 +145,8 @@ static int udp_lib_lport_inuse(struct ne - unsigned long *bitmap, - struct sock *sk, unsigned int log) - { -+ kuid_t uid = sk_uid(sk); - struct sock *sk2; -- kuid_t uid = sock_i_uid(sk); - - sk_for_each(sk2, &hslot->head) { - if (net_eq(sock_net(sk2), net) && -@@ -158,7 +158,7 @@ static int udp_lib_lport_inuse(struct ne - inet_rcv_saddr_equal(sk, sk2, true)) { - if (sk2->sk_reuseport && sk->sk_reuseport && - !rcu_access_pointer(sk->sk_reuseport_cb) && -- uid_eq(uid, sock_i_uid(sk2))) { -+ uid_eq(uid, sk_uid(sk2))) { - if (!bitmap) - return 0; - } else { -@@ -180,8 +180,8 @@ static int udp_lib_lport_inuse2(struct n - struct udp_hslot *hslot2, - struct sock *sk) - { -+ kuid_t uid = sk_uid(sk); - struct sock *sk2; -- kuid_t uid = sock_i_uid(sk); - int res = 0; - - spin_lock(&hslot2->lock); -@@ -195,7 +195,7 @@ static int udp_lib_lport_inuse2(struct n - inet_rcv_saddr_equal(sk, sk2, true)) { - if (sk2->sk_reuseport && sk->sk_reuseport && - !rcu_access_pointer(sk->sk_reuseport_cb) && -- uid_eq(uid, sock_i_uid(sk2))) { -+ uid_eq(uid, sk_uid(sk2))) { - res = 0; - } else { - res = 1; -@@ -210,7 +210,7 @@ static int udp_lib_lport_inuse2(struct n - static int udp_reuseport_add_sock(struct sock *sk, struct udp_hslot *hslot) - { - struct net *net = sock_net(sk); -- kuid_t uid = sock_i_uid(sk); -+ kuid_t uid = sk_uid(sk); - struct sock *sk2; - - sk_for_each(sk2, &hslot->head) { -@@ -220,7 +220,7 @@ static int udp_reuseport_add_sock(struct - ipv6_only_sock(sk2) == ipv6_only_sock(sk) && - (udp_sk(sk2)->udp_port_hash == udp_sk(sk)->udp_port_hash) && - (sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && -- sk2->sk_reuseport && uid_eq(uid, sock_i_uid(sk2)) && -+ sk2->sk_reuseport && uid_eq(uid, sk_uid(sk2)) && - inet_rcv_saddr_equal(sk, sk2, false)) { - return reuseport_add_sock(sk, sk2, - inet_rcv_saddr_any(sk)); -@@ -1445,7 +1445,8 @@ int udp_sendmsg(struct sock *sk, struct - flowi4_init_output(fl4, ipc.oif, ipc.sockc.mark, - ipc.tos & INET_DSCP_MASK, scope, - sk->sk_protocol, flow_flags, faddr, saddr, -- dport, inet->inet_sport, sk->sk_uid); -+ dport, inet->inet_sport, -+ sk_uid(sk)); - - security_sk_classify_flow(sk, flowi4_to_flowi_common(fl4)); - rt = ip_route_output_flow(net, fl4, sk); -@@ -3386,7 +3387,7 @@ static void udp4_format_sock(struct sock - sk_wmem_alloc_get(sp), - udp_rqueue_get(sp), - 0, 0L, 0, -- from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)), -+ from_kuid_munged(seq_user_ns(f), sk_uid(sp)), - 0, sock_i_ino(sp), - refcount_read(&sp->sk_refcnt), sp, - atomic_read(&sp->sk_drops)); -@@ -3629,7 +3630,7 @@ static int bpf_iter_udp_seq_show(struct - goto unlock; - } - -- uid = from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)); -+ uid = from_kuid_munged(seq_user_ns(seq), sk_uid(sk)); - meta.seq = seq; - prog = bpf_iter_get_info(&meta, false); - ret = udp_prog_seq_show(prog, &meta, v, uid, state->bucket); -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/udp_offload.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/udp_offload.c ---- BPI-Router-Linux-kernel/net/ipv4/udp_offload.c 2025-10-22 13:53:23.635327115 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/udp_offload.c 2025-10-22 13:53:56.815167695 -0400 -@@ -224,7 +224,7 @@ static struct sk_buff *__skb_udp_tunnel_ - remcsum = !!(skb_shinfo(skb)->gso_type & SKB_GSO_TUNNEL_REMCSUM); - skb->remcsum_offload = remcsum; - -- need_ipsec = skb_dst(skb) && dst_xfrm(skb_dst(skb)); -+ need_ipsec = (skb_dst(skb) && dst_xfrm(skb_dst(skb))) || skb_sec_path(skb); - /* Try to offload checksum if possible */ - offload_csum = !!(need_csum && - !need_ipsec && -@@ -767,6 +767,7 @@ static struct sk_buff *udp_gro_receive_s - NAPI_GRO_CB(skb)->flush = 1; - return NULL; - } -+ skb_set_network_header(skb, skb_gro_receive_network_offset(skb)); - ret = skb_gro_receive_list(p, skb); - } else { - skb_gro_postpull_rcsum(skb, uh, -diff -purNx .git BPI-Router-Linux-kernel/net/ipv4/xfrm4_input.c BPI-Router-Linux-kernel-6.16.12/net/ipv4/xfrm4_input.c ---- BPI-Router-Linux-kernel/net/ipv4/xfrm4_input.c 2025-10-22 13:53:23.635327115 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv4/xfrm4_input.c 2025-10-22 13:53:56.815167695 -0400 -@@ -202,6 +202,9 @@ struct sk_buff *xfrm4_gro_udp_encap_rcv( - if (len <= sizeof(struct ip_esp_hdr) || udpdata32[0] == 0) - goto out; - -+ /* set the transport header to ESP */ -+ skb_set_transport_header(skb, offset); -+ - NAPI_GRO_CB(skb)->proto = IPPROTO_UDP; - - pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); -diff -purNx .git BPI-Router-Linux-kernel/net/ipv6/addrconf.c BPI-Router-Linux-kernel-6.16.12/net/ipv6/addrconf.c ---- BPI-Router-Linux-kernel/net/ipv6/addrconf.c 2025-10-22 13:53:23.635327115 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv6/addrconf.c 2025-10-22 13:53:56.815167695 -0400 -@@ -2229,13 +2229,12 @@ errdad: - in6_ifa_put(ifp); - } - --/* Join to solicited addr multicast group. -- * caller must hold RTNL */ -+/* Join to solicited addr multicast group. */ - void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr) - { - struct in6_addr maddr; - -- if (dev->flags&(IFF_LOOPBACK|IFF_NOARP)) -+ if (READ_ONCE(dev->flags) & (IFF_LOOPBACK | IFF_NOARP)) - return; - - addrconf_addr_solict_mult(addr, &maddr); -@@ -3525,11 +3524,9 @@ static void addrconf_gre_config(struct n - - ASSERT_RTNL(); - -- idev = ipv6_find_idev(dev); -- if (IS_ERR(idev)) { -- pr_debug("%s: add_dev failed\n", __func__); -+ idev = addrconf_add_dev(dev); -+ if (IS_ERR(idev)) - return; -- } - - /* Generate the IPv6 link-local address using addrconf_addr_gen(), - * unless we have an IPv4 GRE device not bound to an IP address and -@@ -3543,9 +3540,6 @@ static void addrconf_gre_config(struct n - } - - add_v4_addrs(idev); -- -- if (dev->flags & IFF_POINTOPOINT) -- addrconf_add_mroute(dev); - } - #endif - -@@ -3865,7 +3859,7 @@ static int addrconf_ifdown(struct net_de - * Do not dev_put! - */ - if (unregister) { -- idev->dead = 1; -+ WRITE_ONCE(idev->dead, 1); - - /* protected by rtnl_lock */ - RCU_INIT_POINTER(dev->ip6_ptr, NULL); -diff -purNx .git BPI-Router-Linux-kernel/net/ipv6/af_inet6.c BPI-Router-Linux-kernel-6.16.12/net/ipv6/af_inet6.c ---- BPI-Router-Linux-kernel/net/ipv6/af_inet6.c 2025-10-22 13:53:23.635327115 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv6/af_inet6.c 2025-10-22 13:53:56.815167695 -0400 -@@ -842,7 +842,7 @@ int inet6_sk_rebuild_header(struct sock - fl6.flowi6_mark = sk->sk_mark; - fl6.fl6_dport = inet->inet_dport; - fl6.fl6_sport = inet->inet_sport; -- fl6.flowi6_uid = sk->sk_uid; -+ fl6.flowi6_uid = sk_uid(sk); - security_sk_classify_flow(sk, flowi6_to_flowi_common(&fl6)); - - rcu_read_lock(); -diff -purNx .git BPI-Router-Linux-kernel/net/ipv6/calipso.c BPI-Router-Linux-kernel-6.16.12/net/ipv6/calipso.c ---- BPI-Router-Linux-kernel/net/ipv6/calipso.c 2025-10-22 13:53:23.635327115 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv6/calipso.c 2025-10-22 13:53:56.815167695 -0400 -@@ -1207,6 +1207,10 @@ static int calipso_req_setattr(struct re - struct ipv6_opt_hdr *old, *new; - struct sock *sk = sk_to_full_sk(req_to_sk(req)); - -+ /* sk is NULL for SYN+ACK w/ SYN Cookie */ -+ if (!sk) -+ return -ENOMEM; -+ - if (req_inet->ipv6_opt && req_inet->ipv6_opt->hopopt) - old = req_inet->ipv6_opt->hopopt; - else -@@ -1247,6 +1251,10 @@ static void calipso_req_delattr(struct r - struct ipv6_txoptions *txopts; - struct sock *sk = sk_to_full_sk(req_to_sk(req)); - -+ /* sk is NULL for SYN+ACK w/ SYN Cookie */ -+ if (!sk) -+ return; -+ - if (!req_inet->ipv6_opt || !req_inet->ipv6_opt->hopopt) - return; - -diff -purNx .git BPI-Router-Linux-kernel/net/ipv6/datagram.c BPI-Router-Linux-kernel-6.16.12/net/ipv6/datagram.c ---- BPI-Router-Linux-kernel/net/ipv6/datagram.c 2025-10-22 13:53:23.635327115 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv6/datagram.c 2025-10-22 13:53:56.815167695 -0400 -@@ -53,7 +53,7 @@ static void ip6_datagram_flow_key_init(s - fl6->fl6_dport = inet->inet_dport; - fl6->fl6_sport = inet->inet_sport; - fl6->flowlabel = ip6_make_flowinfo(np->tclass, np->flow_label); -- fl6->flowi6_uid = sk->sk_uid; -+ fl6->flowi6_uid = sk_uid(sk); - - if (!oif) - oif = np->sticky_pktinfo.ipi6_ifindex; -@@ -1064,7 +1064,7 @@ void __ip6_dgram_sock_seq_show(struct se - sk_wmem_alloc_get(sp), - rqueue, - 0, 0L, 0, -- from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)), -+ from_kuid_munged(seq_user_ns(seq), sk_uid(sp)), - 0, - sock_i_ino(sp), - refcount_read(&sp->sk_refcnt), sp, -diff -purNx .git BPI-Router-Linux-kernel/net/ipv6/inet6_connection_sock.c BPI-Router-Linux-kernel-6.16.12/net/ipv6/inet6_connection_sock.c ---- BPI-Router-Linux-kernel/net/ipv6/inet6_connection_sock.c 2025-10-22 13:53:23.635327115 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv6/inet6_connection_sock.c 2025-10-22 13:53:56.815167695 -0400 -@@ -45,7 +45,7 @@ struct dst_entry *inet6_csk_route_req(co - fl6->flowi6_mark = ireq->ir_mark; - fl6->fl6_dport = ireq->ir_rmt_port; - fl6->fl6_sport = htons(ireq->ir_num); -- fl6->flowi6_uid = sk->sk_uid; -+ fl6->flowi6_uid = sk_uid(sk); - security_req_classify_flow(req, flowi6_to_flowi_common(fl6)); - - dst = ip6_dst_lookup_flow(sock_net(sk), sk, fl6, final_p); -@@ -79,7 +79,7 @@ static struct dst_entry *inet6_csk_route - fl6->flowi6_mark = sk->sk_mark; - fl6->fl6_sport = inet->inet_sport; - fl6->fl6_dport = inet->inet_dport; -- fl6->flowi6_uid = sk->sk_uid; -+ fl6->flowi6_uid = sk_uid(sk); - security_sk_classify_flow(sk, flowi6_to_flowi_common(fl6)); - - rcu_read_lock(); -diff -purNx .git BPI-Router-Linux-kernel/net/ipv6/ip6_fib.c BPI-Router-Linux-kernel-6.16.12/net/ipv6/ip6_fib.c ---- BPI-Router-Linux-kernel/net/ipv6/ip6_fib.c 2025-10-22 13:53:23.635327115 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv6/ip6_fib.c 2025-10-22 13:53:56.815167695 -0400 -@@ -445,15 +445,17 @@ struct fib6_dump_arg { - static int fib6_rt_dump(struct fib6_info *rt, struct fib6_dump_arg *arg) - { - enum fib_event_type fib_event = FIB_EVENT_ENTRY_REPLACE; -+ unsigned int nsiblings; - int err; - - if (!rt || rt == arg->net->ipv6.fib6_null_entry) - return 0; - -- if (rt->fib6_nsiblings) -+ nsiblings = READ_ONCE(rt->fib6_nsiblings); -+ if (nsiblings) - err = call_fib6_multipath_entry_notifier(arg->nb, fib_event, - rt, -- rt->fib6_nsiblings, -+ nsiblings, - arg->extack); - else - err = call_fib6_entry_notifier(arg->nb, fib_event, rt, -@@ -1138,7 +1140,7 @@ static int fib6_add_rt2node(struct fib6_ - - if (rt6_duplicate_nexthop(iter, rt)) { - if (rt->fib6_nsiblings) -- rt->fib6_nsiblings = 0; -+ WRITE_ONCE(rt->fib6_nsiblings, 0); - if (!(iter->fib6_flags & RTF_EXPIRES)) - return -EEXIST; - if (!(rt->fib6_flags & RTF_EXPIRES)) { -@@ -1167,7 +1169,8 @@ static int fib6_add_rt2node(struct fib6_ - */ - if (rt_can_ecmp && - rt6_qualify_for_ecmp(iter)) -- rt->fib6_nsiblings++; -+ WRITE_ONCE(rt->fib6_nsiblings, -+ rt->fib6_nsiblings + 1); - } - - if (iter->fib6_metric > rt->fib6_metric) -@@ -1217,7 +1220,8 @@ next_iter: - fib6_nsiblings = 0; - list_for_each_entry_safe(sibling, temp_sibling, - &rt->fib6_siblings, fib6_siblings) { -- sibling->fib6_nsiblings++; -+ WRITE_ONCE(sibling->fib6_nsiblings, -+ sibling->fib6_nsiblings + 1); - BUG_ON(sibling->fib6_nsiblings != rt->fib6_nsiblings); - fib6_nsiblings++; - } -@@ -1264,8 +1268,9 @@ add: - list_for_each_entry_safe(sibling, next_sibling, - &rt->fib6_siblings, - fib6_siblings) -- sibling->fib6_nsiblings--; -- rt->fib6_nsiblings = 0; -+ WRITE_ONCE(sibling->fib6_nsiblings, -+ sibling->fib6_nsiblings - 1); -+ WRITE_ONCE(rt->fib6_nsiblings, 0); - list_del_rcu(&rt->fib6_siblings); - rcu_read_lock(); - rt6_multipath_rebalance(next_sibling); -@@ -2014,8 +2019,9 @@ static void fib6_del_route(struct fib6_t - notify_del = true; - list_for_each_entry_safe(sibling, next_sibling, - &rt->fib6_siblings, fib6_siblings) -- sibling->fib6_nsiblings--; -- rt->fib6_nsiblings = 0; -+ WRITE_ONCE(sibling->fib6_nsiblings, -+ sibling->fib6_nsiblings - 1); -+ WRITE_ONCE(rt->fib6_nsiblings, 0); - list_del_rcu(&rt->fib6_siblings); - rt6_multipath_rebalance(next_sibling); - } -diff -purNx .git BPI-Router-Linux-kernel/net/ipv6/ip6_icmp.c BPI-Router-Linux-kernel-6.16.12/net/ipv6/ip6_icmp.c ---- BPI-Router-Linux-kernel/net/ipv6/ip6_icmp.c 2025-10-22 13:53:23.635327115 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv6/ip6_icmp.c 2025-10-22 13:53:56.815167695 -0400 -@@ -54,11 +54,12 @@ void icmpv6_ndo_send(struct sk_buff *skb - struct inet6_skb_parm parm = { 0 }; - struct sk_buff *cloned_skb = NULL; - enum ip_conntrack_info ctinfo; -+ enum ip_conntrack_dir dir; - struct in6_addr orig_ip; - struct nf_conn *ct; - - ct = nf_ct_get(skb_in, &ctinfo); -- if (!ct || !(ct->status & IPS_SRC_NAT)) { -+ if (!ct || !(READ_ONCE(ct->status) & IPS_NAT_MASK)) { - __icmpv6_send(skb_in, type, code, info, &parm); - return; - } -@@ -73,7 +74,8 @@ void icmpv6_ndo_send(struct sk_buff *skb - goto out; - - orig_ip = ipv6_hdr(skb_in)->saddr; -- ipv6_hdr(skb_in)->saddr = ct->tuplehash[0].tuple.src.u3.in6; -+ dir = CTINFO2DIR(ctinfo); -+ ipv6_hdr(skb_in)->saddr = ct->tuplehash[dir].tuple.src.u3.in6; - __icmpv6_send(skb_in, type, code, info, &parm); - ipv6_hdr(skb_in)->saddr = orig_ip; - out: -diff -purNx .git BPI-Router-Linux-kernel/net/ipv6/ip6mr.c BPI-Router-Linux-kernel-6.16.12/net/ipv6/ip6mr.c ---- BPI-Router-Linux-kernel/net/ipv6/ip6mr.c 2025-10-22 13:53:23.635327115 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv6/ip6mr.c 2025-10-22 13:53:56.815167695 -0400 -@@ -2039,6 +2039,7 @@ static int ip6mr_forward2(struct net *ne - struct sk_buff *skb, int vifi) - { - struct vif_device *vif = &mrt->vif_table[vifi]; -+ struct net_device *indev = skb->dev; - struct net_device *vif_dev; - struct ipv6hdr *ipv6h; - struct dst_entry *dst; -@@ -2101,7 +2102,7 @@ static int ip6mr_forward2(struct net *ne - IP6CB(skb)->flags |= IP6SKB_FORWARDED; - - return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD, -- net, NULL, skb, skb->dev, vif_dev, -+ net, NULL, skb, indev, skb->dev, - ip6mr_forward2_finish); - - out_free: -diff -purNx .git BPI-Router-Linux-kernel/net/ipv6/ip6_offload.c BPI-Router-Linux-kernel-6.16.12/net/ipv6/ip6_offload.c ---- BPI-Router-Linux-kernel/net/ipv6/ip6_offload.c 2025-10-22 13:53:23.635327115 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv6/ip6_offload.c 2025-10-22 13:53:56.815167695 -0400 -@@ -148,7 +148,9 @@ static struct sk_buff *ipv6_gso_segment( - - ops = rcu_dereference(inet6_offloads[proto]); - if (likely(ops && ops->callbacks.gso_segment)) { -- skb_reset_transport_header(skb); -+ if (!skb_reset_transport_header_careful(skb)) -+ goto out; -+ - segs = ops->callbacks.gso_segment(skb, features); - if (!segs) - skb->network_header = skb_mac_header(skb) + nhoff - skb->head; -diff -purNx .git BPI-Router-Linux-kernel/net/ipv6/ipcomp6.c BPI-Router-Linux-kernel-6.16.12/net/ipv6/ipcomp6.c ---- BPI-Router-Linux-kernel/net/ipv6/ipcomp6.c 2025-10-22 13:53:23.635327115 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv6/ipcomp6.c 2025-10-22 13:53:56.815167695 -0400 -@@ -71,6 +71,7 @@ static int ipcomp6_err(struct sk_buff *s - return 0; - } - -+static struct lock_class_key xfrm_state_lock_key; - static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x) - { - struct net *net = xs_net(x); -@@ -79,6 +80,7 @@ static struct xfrm_state *ipcomp6_tunnel - t = xfrm_state_alloc(net); - if (!t) - goto out; -+ lockdep_set_class(&t->lock, &xfrm_state_lock_key); - - t->id.proto = IPPROTO_IPV6; - t->id.spi = xfrm6_tunnel_alloc_spi(net, (xfrm_address_t *)&x->props.saddr); -diff -purNx .git BPI-Router-Linux-kernel/net/ipv6/mcast.c BPI-Router-Linux-kernel-6.16.12/net/ipv6/mcast.c ---- BPI-Router-Linux-kernel/net/ipv6/mcast.c 2025-10-22 13:53:23.635327115 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv6/mcast.c 2025-10-22 13:53:56.815167695 -0400 -@@ -807,8 +807,8 @@ static void mld_del_delrec(struct inet6_ - } else { - im->mca_crcount = idev->mc_qrv; - } -- in6_dev_put(pmc->idev); - ip6_mc_clear_src(pmc); -+ in6_dev_put(pmc->idev); - kfree_rcu(pmc, rcu); - } - } -@@ -945,23 +945,22 @@ error: - static int __ipv6_dev_mc_inc(struct net_device *dev, - const struct in6_addr *addr, unsigned int mode) - { -- struct ifmcaddr6 *mc; - struct inet6_dev *idev; -- -- ASSERT_RTNL(); -+ struct ifmcaddr6 *mc; - - /* we need to take a reference on idev */ - idev = in6_dev_get(dev); -- - if (!idev) - return -EINVAL; - -- if (idev->dead) { -+ mutex_lock(&idev->mc_lock); -+ -+ if (READ_ONCE(idev->dead)) { -+ mutex_unlock(&idev->mc_lock); - in6_dev_put(idev); - return -ENODEV; - } - -- mutex_lock(&idev->mc_lock); - for_each_mc_mclock(idev, mc) { - if (ipv6_addr_equal(&mc->mca_addr, addr)) { - mc->mca_users++; -diff -purNx .git BPI-Router-Linux-kernel/net/ipv6/netfilter/nf_reject_ipv6.c BPI-Router-Linux-kernel-6.16.12/net/ipv6/netfilter/nf_reject_ipv6.c ---- BPI-Router-Linux-kernel/net/ipv6/netfilter/nf_reject_ipv6.c 2025-10-22 13:53:23.635327115 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv6/netfilter/nf_reject_ipv6.c 2025-10-22 13:53:56.815167695 -0400 -@@ -293,7 +293,7 @@ void nf_send_reset6(struct net *net, str - fl6.fl6_sport = otcph->dest; - fl6.fl6_dport = otcph->source; - -- if (hook == NF_INET_PRE_ROUTING || hook == NF_INET_INGRESS) { -+ if (!skb_dst(oldskb)) { - nf_ip6_route(net, &dst, flowi6_to_flowi(&fl6), false); - if (!dst) - return; -@@ -397,8 +397,7 @@ void nf_send_unreach6(struct net *net, s - if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL) - skb_in->dev = net->loopback_dev; - -- if ((hooknum == NF_INET_PRE_ROUTING || hooknum == NF_INET_INGRESS) && -- nf_reject6_fill_skb_dst(skb_in) < 0) -+ if (!skb_dst(skb_in) && nf_reject6_fill_skb_dst(skb_in) < 0) - return; - - icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0); -diff -purNx .git BPI-Router-Linux-kernel/net/ipv6/ping.c BPI-Router-Linux-kernel-6.16.12/net/ipv6/ping.c ---- BPI-Router-Linux-kernel/net/ipv6/ping.c 2025-10-22 13:53:23.635327115 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv6/ping.c 2025-10-22 13:53:56.815167695 -0400 -@@ -142,7 +142,7 @@ static int ping_v6_sendmsg(struct sock * - fl6.saddr = np->saddr; - fl6.daddr = *daddr; - fl6.flowi6_mark = ipc6.sockc.mark; -- fl6.flowi6_uid = sk->sk_uid; -+ fl6.flowi6_uid = sk_uid(sk); - fl6.fl6_icmp_type = user_icmph.icmp6_type; - fl6.fl6_icmp_code = user_icmph.icmp6_code; - security_sk_classify_flow(sk, flowi6_to_flowi_common(&fl6)); -diff -purNx .git BPI-Router-Linux-kernel/net/ipv6/raw.c BPI-Router-Linux-kernel-6.16.12/net/ipv6/raw.c ---- BPI-Router-Linux-kernel/net/ipv6/raw.c 2025-10-22 13:53:23.639327095 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv6/raw.c 2025-10-22 13:53:56.815167695 -0400 -@@ -777,7 +777,7 @@ static int rawv6_sendmsg(struct sock *sk - memset(&fl6, 0, sizeof(fl6)); - - fl6.flowi6_mark = ipc6.sockc.mark; -- fl6.flowi6_uid = sk->sk_uid; -+ fl6.flowi6_uid = sk_uid(sk); - - if (sin6) { - if (addr_len < SIN6_LEN_RFC2133) -diff -purNx .git BPI-Router-Linux-kernel/net/ipv6/route.c BPI-Router-Linux-kernel-6.16.12/net/ipv6/route.c ---- BPI-Router-Linux-kernel/net/ipv6/route.c 2025-10-22 13:53:23.639327095 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv6/route.c 2025-10-22 13:53:56.815167695 -0400 -@@ -3010,7 +3010,7 @@ void ip6_sk_update_pmtu(struct sk_buff * - oif = l3mdev_master_ifindex(skb->dev); - - ip6_update_pmtu(skb, sock_net(sk), mtu, oif, READ_ONCE(sk->sk_mark), -- sk->sk_uid); -+ sk_uid(sk)); - - dst = __sk_dst_get(sk); - if (!dst || !dst->obsolete || -@@ -3232,7 +3232,7 @@ void ip6_redirect_no_header(struct sk_bu - void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk) - { - ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, -- READ_ONCE(sk->sk_mark), sk->sk_uid); -+ READ_ONCE(sk->sk_mark), sk_uid(sk)); - } - EXPORT_SYMBOL_GPL(ip6_sk_redirect); - -@@ -3737,6 +3737,53 @@ void fib6_nh_release_dsts(struct fib6_nh - } - } - -+static int fib6_config_validate(struct fib6_config *cfg, -+ struct netlink_ext_ack *extack) -+{ -+ /* RTF_PCPU is an internal flag; can not be set by userspace */ -+ if (cfg->fc_flags & RTF_PCPU) { -+ NL_SET_ERR_MSG(extack, "Userspace can not set RTF_PCPU"); -+ goto errout; -+ } -+ -+ /* RTF_CACHE is an internal flag; can not be set by userspace */ -+ if (cfg->fc_flags & RTF_CACHE) { -+ NL_SET_ERR_MSG(extack, "Userspace can not set RTF_CACHE"); -+ goto errout; -+ } -+ -+ if (cfg->fc_type > RTN_MAX) { -+ NL_SET_ERR_MSG(extack, "Invalid route type"); -+ goto errout; -+ } -+ -+ if (cfg->fc_dst_len > 128) { -+ NL_SET_ERR_MSG(extack, "Invalid prefix length"); -+ goto errout; -+ } -+ -+#ifdef CONFIG_IPV6_SUBTREES -+ if (cfg->fc_src_len > 128) { -+ NL_SET_ERR_MSG(extack, "Invalid source address length"); -+ goto errout; -+ } -+ -+ if (cfg->fc_nh_id && cfg->fc_src_len) { -+ NL_SET_ERR_MSG(extack, "Nexthops can not be used with source routing"); -+ goto errout; -+ } -+#else -+ if (cfg->fc_src_len) { -+ NL_SET_ERR_MSG(extack, -+ "Specifying source address requires IPV6_SUBTREES to be enabled"); -+ goto errout; -+ } -+#endif -+ return 0; -+errout: -+ return -EINVAL; -+} -+ - static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg, - gfp_t gfp_flags, - struct netlink_ext_ack *extack) -@@ -3886,6 +3933,10 @@ int ip6_route_add(struct fib6_config *cf - struct fib6_info *rt; - int err; - -+ err = fib6_config_validate(cfg, extack); -+ if (err) -+ return err; -+ - rt = ip6_route_info_create(cfg, gfp_flags, extack); - if (IS_ERR(rt)) - return PTR_ERR(rt); -@@ -4479,53 +4530,6 @@ void rt6_purge_dflt_routers(struct net * - rcu_read_unlock(); - } - --static int fib6_config_validate(struct fib6_config *cfg, -- struct netlink_ext_ack *extack) --{ -- /* RTF_PCPU is an internal flag; can not be set by userspace */ -- if (cfg->fc_flags & RTF_PCPU) { -- NL_SET_ERR_MSG(extack, "Userspace can not set RTF_PCPU"); -- goto errout; -- } -- -- /* RTF_CACHE is an internal flag; can not be set by userspace */ -- if (cfg->fc_flags & RTF_CACHE) { -- NL_SET_ERR_MSG(extack, "Userspace can not set RTF_CACHE"); -- goto errout; -- } -- -- if (cfg->fc_type > RTN_MAX) { -- NL_SET_ERR_MSG(extack, "Invalid route type"); -- goto errout; -- } -- -- if (cfg->fc_dst_len > 128) { -- NL_SET_ERR_MSG(extack, "Invalid prefix length"); -- goto errout; -- } -- --#ifdef CONFIG_IPV6_SUBTREES -- if (cfg->fc_src_len > 128) { -- NL_SET_ERR_MSG(extack, "Invalid source address length"); -- goto errout; -- } -- -- if (cfg->fc_nh_id && cfg->fc_src_len) { -- NL_SET_ERR_MSG(extack, "Nexthops can not be used with source routing"); -- goto errout; -- } --#else -- if (cfg->fc_src_len) { -- NL_SET_ERR_MSG(extack, -- "Specifying source address requires IPV6_SUBTREES to be enabled"); -- goto errout; -- } --#endif -- return 0; --errout: -- return -EINVAL; --} -- - static void rtmsg_to_fib6_config(struct net *net, - struct in6_rtmsg *rtmsg, - struct fib6_config *cfg) -@@ -4563,10 +4567,6 @@ int ipv6_route_ioctl(struct net *net, un - - switch (cmd) { - case SIOCADDRT: -- err = fib6_config_validate(&cfg, NULL); -- if (err) -- break; -- - /* Only do the default setting of fc_metric in route adding */ - if (cfg.fc_metric == 0) - cfg.fc_metric = IP6_RT_PRIO_USER; -@@ -5346,7 +5346,8 @@ static void ip6_route_mpath_notify(struc - */ - rcu_read_lock(); - -- if ((nlflags & NLM_F_APPEND) && rt_last && rt_last->fib6_nsiblings) { -+ if ((nlflags & NLM_F_APPEND) && rt_last && -+ READ_ONCE(rt_last->fib6_nsiblings)) { - rt = list_first_or_null_rcu(&rt_last->fib6_siblings, - struct fib6_info, - fib6_siblings); -@@ -5402,6 +5403,10 @@ static int ip6_route_multipath_add(struc - int nhn = 0; - int err; - -+ err = fib6_config_validate(cfg, extack); -+ if (err) -+ return err; -+ - replace = (cfg->fc_nlinfo.nlh && - (cfg->fc_nlinfo.nlh->nlmsg_flags & NLM_F_REPLACE)); - -@@ -5636,10 +5641,6 @@ static int inet6_rtm_newroute(struct sk_ - if (err < 0) - return err; - -- err = fib6_config_validate(&cfg, extack); -- if (err) -- return err; -- - if (cfg.fc_metric == 0) - cfg.fc_metric = IP6_RT_PRIO_USER; - -@@ -5670,32 +5671,34 @@ static int rt6_nh_nlmsg_size(struct fib6 - - static size_t rt6_nlmsg_size(struct fib6_info *f6i) - { -+ struct fib6_info *sibling; -+ struct fib6_nh *nh; - int nexthop_len; - - if (f6i->nh) { - nexthop_len = nla_total_size(4); /* RTA_NH_ID */ - nexthop_for_each_fib6_nh(f6i->nh, rt6_nh_nlmsg_size, - &nexthop_len); -- } else { -- struct fib6_nh *nh = f6i->fib6_nh; -- struct fib6_info *sibling; -+ goto common; -+ } - -- nexthop_len = 0; -- if (f6i->fib6_nsiblings) { -- rt6_nh_nlmsg_size(nh, &nexthop_len); -- -- rcu_read_lock(); -- -- list_for_each_entry_rcu(sibling, &f6i->fib6_siblings, -- fib6_siblings) { -- rt6_nh_nlmsg_size(sibling->fib6_nh, &nexthop_len); -- } -+ rcu_read_lock(); -+retry: -+ nh = f6i->fib6_nh; -+ nexthop_len = 0; -+ if (READ_ONCE(f6i->fib6_nsiblings)) { -+ rt6_nh_nlmsg_size(nh, &nexthop_len); - -- rcu_read_unlock(); -+ list_for_each_entry_rcu(sibling, &f6i->fib6_siblings, -+ fib6_siblings) { -+ rt6_nh_nlmsg_size(sibling->fib6_nh, &nexthop_len); -+ if (!READ_ONCE(f6i->fib6_nsiblings)) -+ goto retry; - } -- nexthop_len += lwtunnel_get_encap_size(nh->fib_nh_lws); - } -- -+ rcu_read_unlock(); -+ nexthop_len += lwtunnel_get_encap_size(nh->fib_nh_lws); -+common: - return NLMSG_ALIGN(sizeof(struct rtmsg)) - + nla_total_size(16) /* RTA_SRC */ - + nla_total_size(16) /* RTA_DST */ -@@ -5854,7 +5857,7 @@ static int rt6_fill_node(struct net *net - if (dst->lwtstate && - lwtunnel_fill_encap(skb, dst->lwtstate, RTA_ENCAP, RTA_ENCAP_TYPE) < 0) - goto nla_put_failure; -- } else if (rt->fib6_nsiblings) { -+ } else if (READ_ONCE(rt->fib6_nsiblings)) { - struct fib6_info *sibling; - struct nlattr *mp; - -@@ -5956,16 +5959,21 @@ static bool fib6_info_uses_dev(const str - if (f6i->fib6_nh->fib_nh_dev == dev) - return true; - -- if (f6i->fib6_nsiblings) { -- struct fib6_info *sibling, *next_sibling; -+ if (READ_ONCE(f6i->fib6_nsiblings)) { -+ const struct fib6_info *sibling; - -- list_for_each_entry_safe(sibling, next_sibling, -- &f6i->fib6_siblings, fib6_siblings) { -- if (sibling->fib6_nh->fib_nh_dev == dev) -+ rcu_read_lock(); -+ list_for_each_entry_rcu(sibling, &f6i->fib6_siblings, -+ fib6_siblings) { -+ if (sibling->fib6_nh->fib_nh_dev == dev) { -+ rcu_read_unlock(); - return true; -+ } -+ if (!READ_ONCE(f6i->fib6_nsiblings)) -+ break; - } -+ rcu_read_unlock(); - } -- - return false; - } - -@@ -6321,8 +6329,9 @@ errout: - void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info, - unsigned int nlm_flags) - { -- struct sk_buff *skb; - struct net *net = info->nl_net; -+ struct sk_buff *skb; -+ size_t sz; - u32 seq; - int err; - -@@ -6330,17 +6339,21 @@ void inet6_rt_notify(int event, struct f - seq = info->nlh ? info->nlh->nlmsg_seq : 0; - - rcu_read_lock(); -- -- skb = nlmsg_new(rt6_nlmsg_size(rt), GFP_ATOMIC); -+ sz = rt6_nlmsg_size(rt); -+retry: -+ skb = nlmsg_new(sz, GFP_ATOMIC); - if (!skb) - goto errout; - - err = rt6_fill_node(net, skb, rt, NULL, NULL, NULL, 0, - event, info->portid, seq, nlm_flags); - if (err < 0) { -- /* -EMSGSIZE implies BUG in rt6_nlmsg_size() */ -- WARN_ON(err == -EMSGSIZE); - kfree_skb(skb); -+ /* -EMSGSIZE implies needed space grew under us. */ -+ if (err == -EMSGSIZE) { -+ sz = max(rt6_nlmsg_size(rt), sz << 1); -+ goto retry; -+ } - goto errout; - } - -diff -purNx .git BPI-Router-Linux-kernel/net/ipv6/rpl_iptunnel.c BPI-Router-Linux-kernel-6.16.12/net/ipv6/rpl_iptunnel.c ---- BPI-Router-Linux-kernel/net/ipv6/rpl_iptunnel.c 2025-10-22 13:53:23.639327095 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv6/rpl_iptunnel.c 2025-10-22 13:53:56.815167695 -0400 -@@ -129,13 +129,13 @@ static int rpl_do_srh_inline(struct sk_b - struct dst_entry *cache_dst) - { - struct ipv6_rpl_sr_hdr *isrh, *csrh; -- const struct ipv6hdr *oldhdr; -+ struct ipv6hdr oldhdr; - struct ipv6hdr *hdr; - unsigned char *buf; - size_t hdrlen; - int err; - -- oldhdr = ipv6_hdr(skb); -+ memcpy(&oldhdr, ipv6_hdr(skb), sizeof(oldhdr)); - - buf = kcalloc(struct_size(srh, segments.addr, srh->segments_left), 2, GFP_ATOMIC); - if (!buf) -@@ -147,7 +147,7 @@ static int rpl_do_srh_inline(struct sk_b - memcpy(isrh, srh, sizeof(*isrh)); - memcpy(isrh->rpl_segaddr, &srh->rpl_segaddr[1], - (srh->segments_left - 1) * 16); -- isrh->rpl_segaddr[srh->segments_left - 1] = oldhdr->daddr; -+ isrh->rpl_segaddr[srh->segments_left - 1] = oldhdr.daddr; - - ipv6_rpl_srh_compress(csrh, isrh, &srh->rpl_segaddr[0], - isrh->segments_left - 1); -@@ -169,7 +169,7 @@ static int rpl_do_srh_inline(struct sk_b - skb_mac_header_rebuild(skb); - - hdr = ipv6_hdr(skb); -- memmove(hdr, oldhdr, sizeof(*hdr)); -+ memmove(hdr, &oldhdr, sizeof(*hdr)); - isrh = (void *)hdr + sizeof(*hdr); - memcpy(isrh, csrh, hdrlen); - -diff -purNx .git BPI-Router-Linux-kernel/net/ipv6/seg6_hmac.c BPI-Router-Linux-kernel-6.16.12/net/ipv6/seg6_hmac.c ---- BPI-Router-Linux-kernel/net/ipv6/seg6_hmac.c 2025-10-22 13:53:23.639327095 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv6/seg6_hmac.c 2025-10-22 13:53:56.815167695 -0400 -@@ -35,6 +35,7 @@ - #include - - #include -+#include - #include - #include - #include -@@ -280,7 +281,7 @@ bool seg6_hmac_validate_skb(struct sk_bu - if (seg6_hmac_compute(hinfo, srh, &ipv6_hdr(skb)->saddr, hmac_output)) - return false; - -- if (memcmp(hmac_output, tlv->hmac, SEG6_HMAC_FIELD_LEN) != 0) -+ if (crypto_memneq(hmac_output, tlv->hmac, SEG6_HMAC_FIELD_LEN)) - return false; - - return true; -@@ -304,6 +305,9 @@ int seg6_hmac_info_add(struct net *net, - struct seg6_pernet_data *sdata = seg6_pernet(net); - int err; - -+ if (!__hmac_get_algo(hinfo->alg_id)) -+ return -EINVAL; -+ - err = rhashtable_lookup_insert_fast(&sdata->hmac_infos, &hinfo->node, - rht_params); - -diff -purNx .git BPI-Router-Linux-kernel/net/ipv6/syncookies.c BPI-Router-Linux-kernel-6.16.12/net/ipv6/syncookies.c ---- BPI-Router-Linux-kernel/net/ipv6/syncookies.c 2025-10-22 13:53:23.639327095 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv6/syncookies.c 2025-10-22 13:53:56.815167695 -0400 -@@ -236,7 +236,7 @@ struct sock *cookie_v6_check(struct sock - fl6.flowi6_mark = ireq->ir_mark; - fl6.fl6_dport = ireq->ir_rmt_port; - fl6.fl6_sport = inet_sk(sk)->inet_sport; -- fl6.flowi6_uid = sk->sk_uid; -+ fl6.flowi6_uid = sk_uid(sk); - security_req_classify_flow(req, flowi6_to_flowi_common(&fl6)); - - dst = ip6_dst_lookup_flow(net, sk, &fl6, final_p); -diff -purNx .git BPI-Router-Linux-kernel/net/ipv6/tcp_ipv6.c BPI-Router-Linux-kernel-6.16.12/net/ipv6/tcp_ipv6.c ---- BPI-Router-Linux-kernel/net/ipv6/tcp_ipv6.c 2025-10-22 13:53:23.639327095 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv6/tcp_ipv6.c 2025-10-22 13:53:56.819167675 -0400 -@@ -269,7 +269,7 @@ static int tcp_v6_connect(struct sock *s - fl6.fl6_sport = inet->inet_sport; - if (IS_ENABLED(CONFIG_IP_ROUTE_MULTIPATH) && !fl6.fl6_sport) - fl6.flowi6_flags = FLOWI_FLAG_ANY_SPORT; -- fl6.flowi6_uid = sk->sk_uid; -+ fl6.flowi6_uid = sk_uid(sk); - - opt = rcu_dereference_protected(np->opt, lockdep_sock_is_held(sk)); - final_p = fl6_update_dst(&fl6, opt, &final); -@@ -1431,17 +1431,17 @@ static struct sock *tcp_v6_syn_recv_sock - ireq = inet_rsk(req); - - if (sk_acceptq_is_full(sk)) -- goto out_overflow; -+ goto exit_overflow; - - if (!dst) { - dst = inet6_csk_route_req(sk, &fl6, req, IPPROTO_TCP); - if (!dst) -- goto out; -+ goto exit; - } - - newsk = tcp_create_openreq_child(sk, req, skb); - if (!newsk) -- goto out_nonewsk; -+ goto exit_nonewsk; - - /* - * No need to charge this sock to the relevant IPv6 refcnt debug socks -@@ -1525,25 +1525,19 @@ static struct sock *tcp_v6_syn_recv_sock - const union tcp_md5_addr *addr; - - addr = (union tcp_md5_addr *)&newsk->sk_v6_daddr; -- if (tcp_md5_key_copy(newsk, addr, AF_INET6, 128, l3index, key)) { -- inet_csk_prepare_forced_close(newsk); -- tcp_done(newsk); -- goto out; -- } -+ if (tcp_md5_key_copy(newsk, addr, AF_INET6, 128, l3index, key)) -+ goto put_and_exit; - } - } - #endif - #ifdef CONFIG_TCP_AO - /* Copy over tcp_ao_info if any */ - if (tcp_ao_copy_all_matching(sk, newsk, req, skb, AF_INET6)) -- goto out; /* OOM */ -+ goto put_and_exit; /* OOM */ - #endif - -- if (__inet_inherit_port(sk, newsk) < 0) { -- inet_csk_prepare_forced_close(newsk); -- tcp_done(newsk); -- goto out; -- } -+ if (__inet_inherit_port(sk, newsk) < 0) -+ goto put_and_exit; - *own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash), - &found_dup_sk); - if (*own_req) { -@@ -1570,13 +1564,17 @@ static struct sock *tcp_v6_syn_recv_sock - - return newsk; - --out_overflow: -+exit_overflow: - __NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); --out_nonewsk: -+exit_nonewsk: - dst_release(dst); --out: -+exit: - tcp_listendrop(sk); - return NULL; -+put_and_exit: -+ inet_csk_prepare_forced_close(newsk); -+ tcp_done(newsk); -+ goto exit; - } - - INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *, -@@ -2168,7 +2166,7 @@ static void get_openreq6(struct seq_file - jiffies_to_clock_t(ttd), - req->num_timeout, - from_kuid_munged(seq_user_ns(seq), -- sock_i_uid(req->rsk_listener)), -+ sk_uid(req->rsk_listener)), - 0, /* non standard timer */ - 0, /* open_requests have no inode */ - 0, req); -@@ -2234,7 +2232,7 @@ static void get_tcp6_sock(struct seq_fil - timer_active, - jiffies_delta_to_clock_t(timer_expires - jiffies), - icsk->icsk_retransmits, -- from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)), -+ from_kuid_munged(seq_user_ns(seq), sk_uid(sp)), - icsk->icsk_probes_out, - sock_i_ino(sp), - refcount_read(&sp->sk_refcnt), sp, -diff -purNx .git BPI-Router-Linux-kernel/net/ipv6/udp.c BPI-Router-Linux-kernel-6.16.12/net/ipv6/udp.c ---- BPI-Router-Linux-kernel/net/ipv6/udp.c 2025-10-22 13:53:23.639327095 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv6/udp.c 2025-10-22 13:53:56.819167675 -0400 -@@ -750,7 +750,8 @@ int __udp6_lib_err(struct sk_buff *skb, - if (type == NDISC_REDIRECT) { - if (tunnel) { - ip6_redirect(skb, sock_net(sk), inet6_iif(skb), -- READ_ONCE(sk->sk_mark), sk->sk_uid); -+ READ_ONCE(sk->sk_mark), -+ sk_uid(sk)); - } else { - ip6_sk_redirect(skb, sk); - } -@@ -1620,7 +1621,7 @@ do_udp_sendmsg: - if (!fl6->flowi6_oif) - fl6->flowi6_oif = np->sticky_pktinfo.ipi6_ifindex; - -- fl6->flowi6_uid = sk->sk_uid; -+ fl6->flowi6_uid = sk_uid(sk); - - if (msg->msg_controllen) { - opt = &opt_space; -diff -purNx .git BPI-Router-Linux-kernel/net/ipv6/xfrm6_input.c BPI-Router-Linux-kernel-6.16.12/net/ipv6/xfrm6_input.c ---- BPI-Router-Linux-kernel/net/ipv6/xfrm6_input.c 2025-10-22 13:53:23.639327095 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv6/xfrm6_input.c 2025-10-22 13:53:56.819167675 -0400 -@@ -202,6 +202,9 @@ struct sk_buff *xfrm6_gro_udp_encap_rcv( - if (len <= sizeof(struct ip_esp_hdr) || udpdata32[0] == 0) - goto out; - -+ /* set the transport header to ESP */ -+ skb_set_transport_header(skb, offset); -+ - NAPI_GRO_CB(skb)->proto = IPPROTO_UDP; - - pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); -diff -purNx .git BPI-Router-Linux-kernel/net/ipv6/xfrm6_tunnel.c BPI-Router-Linux-kernel-6.16.12/net/ipv6/xfrm6_tunnel.c ---- BPI-Router-Linux-kernel/net/ipv6/xfrm6_tunnel.c 2025-10-22 13:53:23.639327095 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ipv6/xfrm6_tunnel.c 2025-10-22 13:53:56.819167675 -0400 -@@ -334,8 +334,8 @@ static void __net_exit xfrm6_tunnel_net_ - struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net); - unsigned int i; - -+ xfrm_state_flush(net, 0, false); - xfrm_flush_gc(); -- xfrm_state_flush(net, 0, false, true); - - for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++) - WARN_ON_ONCE(!hlist_empty(&xfrm6_tn->spi_byaddr[i])); -diff -purNx .git BPI-Router-Linux-kernel/net/kcm/kcmsock.c BPI-Router-Linux-kernel-6.16.12/net/kcm/kcmsock.c ---- BPI-Router-Linux-kernel/net/kcm/kcmsock.c 2025-10-22 13:53:23.639327095 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/kcm/kcmsock.c 2025-10-22 13:53:56.819167675 -0400 -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -429,7 +430,7 @@ static void psock_write_space(struct soc - - /* Check if the socket is reserved so someone is waiting for sending. */ - kcm = psock->tx_kcm; -- if (kcm && !unlikely(kcm->tx_stopped)) -+ if (kcm) - queue_work(kcm_wq, &kcm->tx_work); - - spin_unlock_bh(&mux->lock); -@@ -1030,6 +1031,11 @@ static ssize_t kcm_splice_read(struct so - ssize_t copied; - struct sk_buff *skb; - -+ if (sock->file->f_flags & O_NONBLOCK || flags & SPLICE_F_NONBLOCK) -+ flags = MSG_DONTWAIT; -+ else -+ flags = 0; -+ - /* Only support splice for SOCKSEQPACKET */ - - skb = skb_recv_datagram(sk, flags, &err); -@@ -1688,12 +1694,6 @@ static int kcm_release(struct socket *so - */ - __skb_queue_purge(&sk->sk_write_queue); - -- /* Set tx_stopped. This is checked when psock is bound to a kcm and we -- * get a writespace callback. This prevents further work being queued -- * from the callback (unbinding the psock occurs after canceling work. -- */ -- kcm->tx_stopped = 1; -- - release_sock(sk); - - spin_lock_bh(&mux->lock); -@@ -1709,7 +1709,7 @@ static int kcm_release(struct socket *so - /* Cancel work. After this point there should be no outside references - * to the kcm socket. - */ -- cancel_work_sync(&kcm->tx_work); -+ disable_work_sync(&kcm->tx_work); - - lock_sock(sk); - psock = kcm->tx_psock; -diff -purNx .git BPI-Router-Linux-kernel/net/key/af_key.c BPI-Router-Linux-kernel-6.16.12/net/key/af_key.c ---- BPI-Router-Linux-kernel/net/key/af_key.c 2025-10-22 13:53:23.639327095 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/key/af_key.c 2025-10-22 13:53:56.819167675 -0400 -@@ -1766,7 +1766,7 @@ static int pfkey_flush(struct sock *sk, - if (proto == 0) - return -EINVAL; - -- err = xfrm_state_flush(net, proto, true, false); -+ err = xfrm_state_flush(net, proto, true); - err2 = unicast_flush_resp(sk, hdr); - if (err || err2) { - if (err == -ESRCH) /* empty table - go quietly */ -@@ -3788,7 +3788,7 @@ static int pfkey_seq_show(struct seq_fil - refcount_read(&s->sk_refcnt), - sk_rmem_alloc_get(s), - sk_wmem_alloc_get(s), -- from_kuid_munged(seq_user_ns(f), sock_i_uid(s)), -+ from_kuid_munged(seq_user_ns(f), sk_uid(s)), - sock_i_ino(s) - ); - return 0; -diff -purNx .git BPI-Router-Linux-kernel/net/l2tp/l2tp_ip6.c BPI-Router-Linux-kernel-6.16.12/net/l2tp/l2tp_ip6.c ---- BPI-Router-Linux-kernel/net/l2tp/l2tp_ip6.c 2025-10-22 13:53:23.639327095 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/l2tp/l2tp_ip6.c 2025-10-22 13:53:56.819167675 -0400 -@@ -545,7 +545,7 @@ static int l2tp_ip6_sendmsg(struct sock - memset(&fl6, 0, sizeof(fl6)); - - fl6.flowi6_mark = READ_ONCE(sk->sk_mark); -- fl6.flowi6_uid = sk->sk_uid; -+ fl6.flowi6_uid = sk_uid(sk); - - ipcm6_init_sk(&ipc6, sk); - -diff -purNx .git BPI-Router-Linux-kernel/net/l2tp/l2tp_ppp.c BPI-Router-Linux-kernel-6.16.12/net/l2tp/l2tp_ppp.c ---- BPI-Router-Linux-kernel/net/l2tp/l2tp_ppp.c 2025-10-22 13:53:23.639327095 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/l2tp/l2tp_ppp.c 2025-10-22 13:53:56.819167675 -0400 -@@ -129,22 +129,12 @@ static const struct ppp_channel_ops pppo - - static const struct proto_ops pppol2tp_ops; - --/* Retrieves the pppol2tp socket associated to a session. -- * A reference is held on the returned socket, so this function must be paired -- * with sock_put(). -- */ -+/* Retrieves the pppol2tp socket associated to a session. */ - static struct sock *pppol2tp_session_get_sock(struct l2tp_session *session) - { - struct pppol2tp_session *ps = l2tp_session_priv(session); -- struct sock *sk; -- -- rcu_read_lock(); -- sk = rcu_dereference(ps->sk); -- if (sk) -- sock_hold(sk); -- rcu_read_unlock(); - -- return sk; -+ return rcu_dereference(ps->sk); - } - - /* Helpers to obtain tunnel/session contexts from sockets. -@@ -206,14 +196,13 @@ end: - - static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int data_len) - { -- struct pppol2tp_session *ps = l2tp_session_priv(session); -- struct sock *sk = NULL; -+ struct sock *sk; - - /* If the socket is bound, send it in to PPP's input queue. Otherwise - * queue it on the session socket. - */ - rcu_read_lock(); -- sk = rcu_dereference(ps->sk); -+ sk = pppol2tp_session_get_sock(session); - if (!sk) - goto no_sock; - -@@ -510,13 +499,14 @@ static void pppol2tp_show(struct seq_fil - struct l2tp_session *session = arg; - struct sock *sk; - -+ rcu_read_lock(); - sk = pppol2tp_session_get_sock(session); - if (sk) { - struct pppox_sock *po = pppox_sk(sk); - - seq_printf(m, " interface %s\n", ppp_dev_name(&po->chan)); -- sock_put(sk); - } -+ rcu_read_unlock(); - } - - static void pppol2tp_session_init(struct l2tp_session *session) -@@ -1530,6 +1520,7 @@ static void pppol2tp_seq_session_show(st - port = ntohs(inet->inet_sport); - } - -+ rcu_read_lock(); - sk = pppol2tp_session_get_sock(session); - if (sk) { - state = sk->sk_state; -@@ -1565,8 +1556,8 @@ static void pppol2tp_seq_session_show(st - struct pppox_sock *po = pppox_sk(sk); - - seq_printf(m, " interface %s\n", ppp_dev_name(&po->chan)); -- sock_put(sk); - } -+ rcu_read_unlock(); - } - - static int pppol2tp_seq_show(struct seq_file *m, void *v) -diff -purNx .git BPI-Router-Linux-kernel/net/llc/llc_proc.c BPI-Router-Linux-kernel-6.16.12/net/llc/llc_proc.c ---- BPI-Router-Linux-kernel/net/llc/llc_proc.c 2025-10-22 13:53:23.643327076 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/llc/llc_proc.c 2025-10-22 13:53:56.819167675 -0400 -@@ -151,7 +151,7 @@ static int llc_seq_socket_show(struct se - sk_wmem_alloc_get(sk), - sk_rmem_alloc_get(sk) - llc->copied_seq, - sk->sk_state, -- from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), -+ from_kuid_munged(seq_user_ns(seq), sk_uid(sk)), - llc->link); - out: - return 0; -diff -purNx .git BPI-Router-Linux-kernel/net/mac80211/cfg.c BPI-Router-Linux-kernel-6.16.12/net/mac80211/cfg.c ---- BPI-Router-Linux-kernel/net/mac80211/cfg.c 2025-10-22 13:53:23.643327076 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mac80211/cfg.c 2025-10-22 13:53:56.819167675 -0400 -@@ -178,6 +178,7 @@ static int ieee80211_set_ap_mbssid_optio - - link_conf->nontransmitted = true; - link_conf->bssid_index = params->index; -+ link_conf->bssid_indicator = tx_bss_conf->bssid_indicator; - } - if (params->ema) - link_conf->ema_ap = true; -@@ -1121,13 +1122,13 @@ ieee80211_copy_rnr_beacon(u8 *pos, struc - { - int i, offset = 0; - -+ dst->cnt = src->cnt; - for (i = 0; i < src->cnt; i++) { - memcpy(pos + offset, src->elem[i].data, src->elem[i].len); - dst->elem[i].len = src->elem[i].len; - dst->elem[i].data = pos + offset; - offset += dst->elem[i].len; - } -- dst->cnt = src->cnt; - - return offset; - } -@@ -1218,8 +1219,11 @@ ieee80211_assign_beacon(struct ieee80211 - ieee80211_copy_rnr_beacon(pos, new->rnr_ies, rnr); - } - /* update bssid_indicator */ -- link_conf->bssid_indicator = -- ilog2(__roundup_pow_of_two(mbssid->cnt + 1)); -+ if (new->mbssid_ies->cnt && new->mbssid_ies->elem[0].len > 2) -+ link_conf->bssid_indicator = -+ *(new->mbssid_ies->elem[0].data + 2); -+ else -+ link_conf->bssid_indicator = 0; - } - - if (csa) { -@@ -1959,6 +1963,20 @@ static int sta_link_apply_parameters(str - ieee80211_sta_init_nss(link_sta); - - if (params->opmode_notif_used) { -+ enum nl80211_chan_width width = link->conf->chanreq.oper.width; -+ -+ switch (width) { -+ case NL80211_CHAN_WIDTH_20: -+ case NL80211_CHAN_WIDTH_40: -+ case NL80211_CHAN_WIDTH_80: -+ case NL80211_CHAN_WIDTH_160: -+ case NL80211_CHAN_WIDTH_80P80: -+ case NL80211_CHAN_WIDTH_320: /* not VHT, allowed for HE/EHT */ -+ break; -+ default: -+ return -EINVAL; -+ } -+ - /* returned value is only needed for rc update, but the - * rc isn't initialized here yet, so ignore it - */ -@@ -3742,7 +3760,7 @@ void ieee80211_csa_finish(struct ieee802 - */ - struct ieee80211_link_data *iter; - -- for_each_sdata_link(local, iter) { -+ for_each_sdata_link_rcu(local, iter) { - if (iter->sdata == sdata || - rcu_access_pointer(iter->conf->tx_bss_conf) != tx_bss_conf) - continue; -diff -purNx .git BPI-Router-Linux-kernel/net/mac80211/chan.c BPI-Router-Linux-kernel-6.16.12/net/mac80211/chan.c ---- BPI-Router-Linux-kernel/net/mac80211/chan.c 2025-10-22 13:53:23.643327076 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mac80211/chan.c 2025-10-22 13:53:56.819167675 -0400 -@@ -1381,6 +1381,7 @@ ieee80211_link_use_reserved_reassign(str - goto out; - } - -+ link->radar_required = link->reserved_radar_required; - list_move(&link->assigned_chanctx_list, &new_ctx->assigned_links); - rcu_assign_pointer(link_conf->chanctx_conf, &new_ctx->conf); - -diff -purNx .git BPI-Router-Linux-kernel/net/mac80211/debug.h BPI-Router-Linux-kernel-6.16.12/net/mac80211/debug.h ---- BPI-Router-Linux-kernel/net/mac80211/debug.h 2025-10-22 13:53:23.643327076 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mac80211/debug.h 2025-10-22 13:53:56.819167675 -0400 -@@ -1,10 +1,11 @@ - /* SPDX-License-Identifier: GPL-2.0 */ - /* - * Portions -- * Copyright (C) 2022 - 2024 Intel Corporation -+ * Copyright (C) 2022 - 2025 Intel Corporation - */ - #ifndef __MAC80211_DEBUG_H - #define __MAC80211_DEBUG_H -+#include - #include - - #ifdef CONFIG_MAC80211_OCB_DEBUG -@@ -152,6 +153,8 @@ do { \ - else \ - _sdata_err((link)->sdata, fmt, ##__VA_ARGS__); \ - } while (0) -+#define link_err_once(link, fmt, ...) \ -+ DO_ONCE_LITE(link_err, link, fmt, ##__VA_ARGS__) - #define link_id_info(sdata, link_id, fmt, ...) \ - do { \ - if (ieee80211_vif_is_mld(&sdata->vif)) \ -diff -purNx .git BPI-Router-Linux-kernel/net/mac80211/driver-ops.h BPI-Router-Linux-kernel-6.16.12/net/mac80211/driver-ops.h ---- BPI-Router-Linux-kernel/net/mac80211/driver-ops.h 2025-10-22 13:53:23.643327076 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mac80211/driver-ops.h 2025-10-22 13:53:56.819167675 -0400 -@@ -1389,7 +1389,7 @@ drv_get_ftm_responder_stats(struct ieee8 - struct ieee80211_sub_if_data *sdata, - struct cfg80211_ftm_responder_stats *ftm_stats) - { -- u32 ret = -EOPNOTSUPP; -+ int ret = -EOPNOTSUPP; - - might_sleep(); - lockdep_assert_wiphy(local->hw.wiphy); -diff -purNx .git BPI-Router-Linux-kernel/net/mac80211/ht.c BPI-Router-Linux-kernel-6.16.12/net/mac80211/ht.c ---- BPI-Router-Linux-kernel/net/mac80211/ht.c 2025-10-22 13:53:23.643327076 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mac80211/ht.c 2025-10-22 13:53:56.819167675 -0400 -@@ -9,7 +9,7 @@ - * Copyright 2007, Michael Wu - * Copyright 2007-2010, Intel Corporation - * Copyright 2017 Intel Deutschland GmbH -- * Copyright(c) 2020-2024 Intel Corporation -+ * Copyright(c) 2020-2025 Intel Corporation - */ - - #include -@@ -603,3 +603,41 @@ out: - } - /* this might change ... don't want non-open drivers using it */ - EXPORT_SYMBOL_GPL(ieee80211_request_smps); -+ -+void ieee80211_ht_handle_chanwidth_notif(struct ieee80211_local *local, -+ struct ieee80211_sub_if_data *sdata, -+ struct sta_info *sta, -+ struct link_sta_info *link_sta, -+ u8 chanwidth, enum nl80211_band band) -+{ -+ enum ieee80211_sta_rx_bandwidth max_bw, new_bw; -+ struct ieee80211_supported_band *sband; -+ struct sta_opmode_info sta_opmode = {}; -+ -+ lockdep_assert_wiphy(local->hw.wiphy); -+ -+ if (chanwidth == IEEE80211_HT_CHANWIDTH_20MHZ) -+ max_bw = IEEE80211_STA_RX_BW_20; -+ else -+ max_bw = ieee80211_sta_cap_rx_bw(link_sta); -+ -+ /* set cur_max_bandwidth and recalc sta bw */ -+ link_sta->cur_max_bandwidth = max_bw; -+ new_bw = ieee80211_sta_cur_vht_bw(link_sta); -+ -+ if (link_sta->pub->bandwidth == new_bw) -+ return; -+ -+ link_sta->pub->bandwidth = new_bw; -+ sband = local->hw.wiphy->bands[band]; -+ sta_opmode.bw = -+ ieee80211_sta_rx_bw_to_chan_width(link_sta); -+ sta_opmode.changed = STA_OPMODE_MAX_BW_CHANGED; -+ -+ rate_control_rate_update(local, sband, link_sta, -+ IEEE80211_RC_BW_CHANGED); -+ cfg80211_sta_opmode_change_notify(sdata->dev, -+ sta->addr, -+ &sta_opmode, -+ GFP_KERNEL); -+} -diff -purNx .git BPI-Router-Linux-kernel/net/mac80211/ieee80211_i.h BPI-Router-Linux-kernel-6.16.12/net/mac80211/ieee80211_i.h ---- BPI-Router-Linux-kernel/net/mac80211/ieee80211_i.h 2025-10-22 13:53:23.643327076 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mac80211/ieee80211_i.h 2025-10-22 13:53:56.819167675 -0400 -@@ -1226,6 +1226,21 @@ struct ieee80211_sub_if_data *vif_to_sda - if ((_link = wiphy_dereference((_local)->hw.wiphy, \ - ___sdata->link[___link_id]))) - -+/* -+ * for_each_sdata_link_rcu() must be used under RCU read lock. -+ */ -+#define for_each_sdata_link_rcu(_local, _link) \ -+ /* outer loop just to define the variables ... */ \ -+ for (struct ieee80211_sub_if_data *___sdata = NULL; \ -+ !___sdata; \ -+ ___sdata = (void *)~0 /* always stop */) \ -+ list_for_each_entry_rcu(___sdata, &(_local)->interfaces, list) \ -+ if (ieee80211_sdata_running(___sdata)) \ -+ for (int ___link_id = 0; \ -+ ___link_id < ARRAY_SIZE((___sdata)->link); \ -+ ___link_id++) \ -+ if ((_link = rcu_dereference((___sdata)->link[___link_id]))) -+ - #define for_each_link_data(sdata, __link) \ - struct ieee80211_sub_if_data *__sdata = sdata; \ - for (int __link_id = 0; \ -@@ -2205,6 +2220,12 @@ u8 ieee80211_mcs_to_chains(const struct - enum nl80211_smps_mode - ieee80211_smps_mode_to_smps_mode(enum ieee80211_smps_mode smps); - -+void ieee80211_ht_handle_chanwidth_notif(struct ieee80211_local *local, -+ struct ieee80211_sub_if_data *sdata, -+ struct sta_info *sta, -+ struct link_sta_info *link_sta, -+ u8 chanwidth, enum nl80211_band band); -+ - /* VHT */ - void - ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, -diff -purNx .git BPI-Router-Linux-kernel/net/mac80211/iface.c BPI-Router-Linux-kernel-6.16.12/net/mac80211/iface.c ---- BPI-Router-Linux-kernel/net/mac80211/iface.c 2025-10-22 13:53:23.643327076 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mac80211/iface.c 2025-10-22 13:53:56.823167656 -0400 -@@ -1150,6 +1150,8 @@ static void ieee80211_sdata_init(struct - { - sdata->local = local; - -+ INIT_LIST_HEAD(&sdata->key_list); -+ - /* - * Initialize the default link, so we can use link_id 0 for non-MLD, - * and that continues to work for non-MLD-aware drivers that use just -@@ -1555,6 +1557,35 @@ static void ieee80211_iface_process_skb( - } - } - } else if (ieee80211_is_action(mgmt->frame_control) && -+ mgmt->u.action.category == WLAN_CATEGORY_HT) { -+ switch (mgmt->u.action.u.ht_smps.action) { -+ case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: { -+ u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth; -+ struct ieee80211_rx_status *status; -+ struct link_sta_info *link_sta; -+ struct sta_info *sta; -+ -+ sta = sta_info_get_bss(sdata, mgmt->sa); -+ if (!sta) -+ break; -+ -+ status = IEEE80211_SKB_RXCB(skb); -+ if (!status->link_valid) -+ link_sta = &sta->deflink; -+ else -+ link_sta = rcu_dereference_protected(sta->link[status->link_id], -+ lockdep_is_held(&local->hw.wiphy->mtx)); -+ if (link_sta) -+ ieee80211_ht_handle_chanwidth_notif(local, sdata, sta, -+ link_sta, chanwidth, -+ status->band); -+ break; -+ } -+ default: -+ WARN_ON(1); -+ break; -+ } -+ } else if (ieee80211_is_action(mgmt->frame_control) && - mgmt->u.action.category == WLAN_CATEGORY_VHT) { - switch (mgmt->u.action.u.vht_group_notif.action_code) { - case WLAN_VHT_ACTION_OPMODE_NOTIF: { -@@ -2210,8 +2241,6 @@ int ieee80211_if_add(struct ieee80211_lo - - ieee80211_init_frag_cache(&sdata->frags); - -- INIT_LIST_HEAD(&sdata->key_list); -- - wiphy_delayed_work_init(&sdata->dec_tailroom_needed_wk, - ieee80211_delayed_tailroom_dec); - -diff -purNx .git BPI-Router-Linux-kernel/net/mac80211/link.c BPI-Router-Linux-kernel-6.16.12/net/mac80211/link.c ---- BPI-Router-Linux-kernel/net/mac80211/link.c 2025-10-22 13:53:23.643327076 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mac80211/link.c 2025-10-22 13:53:56.823167656 -0400 -@@ -2,7 +2,7 @@ - /* - * MLO link handling - * -- * Copyright (C) 2022-2024 Intel Corporation -+ * Copyright (C) 2022-2025 Intel Corporation - */ - #include - #include -@@ -93,9 +93,6 @@ void ieee80211_link_init(struct ieee8021 - if (link_id < 0) - link_id = 0; - -- rcu_assign_pointer(sdata->vif.link_conf[link_id], link_conf); -- rcu_assign_pointer(sdata->link[link_id], link); -- - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { - struct ieee80211_sub_if_data *ap_bss; - struct ieee80211_bss_conf *ap_bss_conf; -@@ -145,6 +142,9 @@ void ieee80211_link_init(struct ieee8021 - - ieee80211_link_debugfs_add(link); - } -+ -+ rcu_assign_pointer(sdata->vif.link_conf[link_id], link_conf); -+ rcu_assign_pointer(sdata->link[link_id], link); - } - - void ieee80211_link_stop(struct ieee80211_link_data *link) -@@ -368,6 +368,13 @@ static int ieee80211_vif_update_links(st - ieee80211_update_apvlan_links(sdata); - } - -+ /* -+ * Ignore errors if we are only removing links as removal should -+ * always succeed -+ */ -+ if (!new_links) -+ ret = 0; -+ - if (ret) { - /* restore config */ - memcpy(sdata->link, old_data, sizeof(old_data)); -diff -purNx .git BPI-Router-Linux-kernel/net/mac80211/main.c BPI-Router-Linux-kernel-6.16.12/net/mac80211/main.c ---- BPI-Router-Linux-kernel/net/mac80211/main.c 2025-10-22 13:53:23.643327076 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mac80211/main.c 2025-10-22 13:53:56.823167656 -0400 -@@ -407,9 +407,20 @@ void ieee80211_link_info_change_notify(s - - WARN_ON_ONCE(changed & BSS_CHANGED_VIF_CFG_FLAGS); - -- if (!changed || sdata->vif.type == NL80211_IFTYPE_AP_VLAN) -+ if (!changed) - return; - -+ switch (sdata->vif.type) { -+ case NL80211_IFTYPE_AP_VLAN: -+ return; -+ case NL80211_IFTYPE_MONITOR: -+ if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) -+ return; -+ break; -+ default: -+ break; -+ } -+ - if (!check_sdata_in_driver(sdata)) - return; - -@@ -1125,7 +1136,7 @@ int ieee80211_register_hw(struct ieee802 - int result, i; - enum nl80211_band band; - int channels, max_bitrates; -- bool supp_ht, supp_vht, supp_he, supp_eht; -+ bool supp_ht, supp_vht, supp_he, supp_eht, supp_s1g; - struct cfg80211_chan_def dflt_chandef = {}; - - if (ieee80211_hw_check(hw, QUEUE_CONTROL) && -@@ -1241,6 +1252,7 @@ int ieee80211_register_hw(struct ieee802 - supp_vht = false; - supp_he = false; - supp_eht = false; -+ supp_s1g = false; - for (band = 0; band < NUM_NL80211_BANDS; band++) { - const struct ieee80211_sband_iftype_data *iftd; - struct ieee80211_supported_band *sband; -@@ -1288,6 +1300,7 @@ int ieee80211_register_hw(struct ieee802 - max_bitrates = sband->n_bitrates; - supp_ht = supp_ht || sband->ht_cap.ht_supported; - supp_vht = supp_vht || sband->vht_cap.vht_supported; -+ supp_s1g = supp_s1g || sband->s1g_cap.s1g; - - for_each_sband_iftype_data(sband, i, iftd) { - u8 he_40_mhz_cap; -@@ -1421,6 +1434,9 @@ int ieee80211_register_hw(struct ieee802 - local->scan_ies_len += - 2 + sizeof(struct ieee80211_vht_cap); - -+ if (supp_s1g) -+ local->scan_ies_len += 2 + sizeof(struct ieee80211_s1g_cap); -+ - /* - * HE cap element is variable in size - set len to allow max size */ - if (supp_he) { -diff -purNx .git BPI-Router-Linux-kernel/net/mac80211/mlme.c BPI-Router-Linux-kernel-6.16.12/net/mac80211/mlme.c ---- BPI-Router-Linux-kernel/net/mac80211/mlme.c 2025-10-22 13:53:23.643327076 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mac80211/mlme.c 2025-10-22 13:53:56.823167656 -0400 -@@ -1193,6 +1193,14 @@ again: - "required MCSes not supported, disabling EHT\n"); - } - -+ if (conn->mode >= IEEE80211_CONN_MODE_EHT && -+ channel->band != NL80211_BAND_2GHZ && -+ conn->bw_limit == IEEE80211_CONN_BW_LIMIT_40) { -+ conn->mode = IEEE80211_CONN_MODE_HE; -+ link_id_info(sdata, link_id, -+ "required bandwidth not supported, disabling EHT\n"); -+ } -+ - /* the mode can only decrease, so this must terminate */ - if (ap_mode != conn->mode) { - kfree(elems); -@@ -1218,18 +1226,36 @@ EXPORT_SYMBOL_IF_MAC80211_KUNIT(ieee8021 - - static int ieee80211_config_bw(struct ieee80211_link_data *link, - struct ieee802_11_elems *elems, -- bool update, u64 *changed, -- const char *frame) -+ bool update, u64 *changed, u16 stype) - { - struct ieee80211_channel *channel = link->conf->chanreq.oper.chan; - struct ieee80211_sub_if_data *sdata = link->sdata; - struct ieee80211_chan_req chanreq = {}; - struct cfg80211_chan_def ap_chandef; - enum ieee80211_conn_mode ap_mode; -+ const char *frame; - u32 vht_cap_info = 0; - u16 ht_opmode; - int ret; - -+ switch (stype) { -+ case IEEE80211_STYPE_BEACON: -+ frame = "beacon"; -+ break; -+ case IEEE80211_STYPE_ASSOC_RESP: -+ frame = "assoc response"; -+ break; -+ case IEEE80211_STYPE_REASSOC_RESP: -+ frame = "reassoc response"; -+ break; -+ case IEEE80211_STYPE_ACTION: -+ /* the only action frame that gets here */ -+ frame = "ML reconf response"; -+ break; -+ default: -+ return -EINVAL; -+ } -+ - /* don't track any bandwidth changes in legacy/S1G modes */ - if (link->u.mgd.conn.mode == IEEE80211_CONN_MODE_LEGACY || - link->u.mgd.conn.mode == IEEE80211_CONN_MODE_S1G) -@@ -1278,7 +1304,9 @@ static int ieee80211_config_bw(struct ie - ieee80211_min_bw_limit_from_chandef(&chanreq.oper)) - ieee80211_chandef_downgrade(&chanreq.oper, NULL); - -- if (ap_chandef.chan->band == NL80211_BAND_6GHZ && -+ /* TPE element is not present in (re)assoc/ML reconfig response */ -+ if (stype == IEEE80211_STYPE_BEACON && -+ ap_chandef.chan->band == NL80211_BAND_6GHZ && - link->u.mgd.conn.mode >= IEEE80211_CONN_MODE_HE) { - ieee80211_rearrange_tpe(&elems->tpe, &ap_chandef, - &chanreq.oper); -@@ -2515,7 +2543,8 @@ ieee80211_sta_abort_chanswitch(struct ie - if (!local->ops->abort_channel_switch) - return; - -- ieee80211_link_unreserve_chanctx(link); -+ if (rcu_access_pointer(link->conf->chanctx_conf)) -+ ieee80211_link_unreserve_chanctx(link); - - ieee80211_vif_unblock_queues_csa(sdata); - -@@ -3934,6 +3963,9 @@ static void ieee80211_set_disassoc(struc - - lockdep_assert_wiphy(local->hw.wiphy); - -+ if (frame_buf) -+ memset(frame_buf, 0, IEEE80211_DEAUTH_FRAME_LEN); -+ - if (WARN_ON(!ap_sta)) - return; - -@@ -4734,6 +4766,7 @@ static void ieee80211_rx_mgmt_auth(struc - struct ieee80211_prep_tx_info info = { - .subtype = IEEE80211_STYPE_AUTH, - }; -+ bool sae_need_confirm = false; - - lockdep_assert_wiphy(sdata->local->hw.wiphy); - -@@ -4779,6 +4812,8 @@ static void ieee80211_rx_mgmt_auth(struc - jiffies + IEEE80211_AUTH_WAIT_SAE_RETRY; - ifmgd->auth_data->timeout_started = true; - run_again(sdata, ifmgd->auth_data->timeout); -+ if (auth_transaction == 1) -+ sae_need_confirm = true; - goto notify_driver; - } - -@@ -4822,6 +4857,9 @@ static void ieee80211_rx_mgmt_auth(struc - if (!ieee80211_mark_sta_auth(sdata)) - return; /* ignore frame -- wait for timeout */ - } else if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE && -+ auth_transaction == 1) { -+ sae_need_confirm = true; -+ } else if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE && - auth_transaction == 2) { - sdata_info(sdata, "SAE peer confirmed\n"); - ifmgd->auth_data->peer_confirmed = true; -@@ -4829,7 +4867,8 @@ static void ieee80211_rx_mgmt_auth(struc - - cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len); - notify_driver: -- drv_mgd_complete_tx(sdata->local, sdata, &info); -+ if (!sae_need_confirm) -+ drv_mgd_complete_tx(sdata->local, sdata, &info); - } - - #define case_WLAN(type) \ -@@ -5291,7 +5330,9 @@ static bool ieee80211_assoc_config_link( - /* check/update if AP changed anything in assoc response vs. scan */ - if (ieee80211_config_bw(link, elems, - link_id == assoc_data->assoc_link_id, -- changed, "assoc response")) { -+ changed, -+ le16_to_cpu(mgmt->frame_control) & -+ IEEE80211_FCTL_STYPE)) { - ret = false; - goto out; - } -@@ -7195,6 +7236,7 @@ static void ieee80211_rx_mgmt_beacon(str - struct ieee80211_bss_conf *bss_conf = link->conf; - struct ieee80211_vif_cfg *vif_cfg = &sdata->vif.cfg; - struct ieee80211_mgmt *mgmt = (void *) hdr; -+ struct ieee80211_ext *ext = NULL; - size_t baselen; - struct ieee802_11_elems *elems; - struct ieee80211_local *local = sdata->local; -@@ -7220,7 +7262,7 @@ static void ieee80211_rx_mgmt_beacon(str - /* Process beacon from the current BSS */ - bssid = ieee80211_get_bssid(hdr, len, sdata->vif.type); - if (ieee80211_is_s1g_beacon(mgmt->frame_control)) { -- struct ieee80211_ext *ext = (void *) mgmt; -+ ext = (void *)mgmt; - variable = ext->u.s1g_beacon.variable + - ieee80211_s1g_optional_len(ext->frame_control); - } -@@ -7407,7 +7449,9 @@ static void ieee80211_rx_mgmt_beacon(str - } - - if ((ncrc == link->u.mgd.beacon_crc && link->u.mgd.beacon_crc_valid) || -- ieee80211_is_s1g_short_beacon(mgmt->frame_control)) -+ (ext && ieee80211_is_s1g_short_beacon(ext->frame_control, -+ parse_params.start, -+ parse_params.len))) - goto free; - link->u.mgd.beacon_crc = ncrc; - link->u.mgd.beacon_crc_valid = true; -@@ -7476,7 +7520,8 @@ static void ieee80211_rx_mgmt_beacon(str - - changed |= ieee80211_recalc_twt_req(sdata, sband, link, link_sta, elems); - -- if (ieee80211_config_bw(link, elems, true, &changed, "beacon")) { -+ if (ieee80211_config_bw(link, elems, true, &changed, -+ IEEE80211_STYPE_BEACON)) { - ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, - WLAN_REASON_DEAUTH_LEAVING, - true, deauth_buf); -@@ -10699,8 +10744,8 @@ static void ieee80211_ml_epcs(struct iee - */ - for_each_mle_subelement(sub, (const u8 *)elems->ml_epcs, - elems->ml_epcs_len) { -+ struct ieee802_11_elems *link_elems __free(kfree) = NULL; - struct ieee80211_link_data *link; -- struct ieee802_11_elems *link_elems __free(kfree); - u8 *pos = (void *)sub->data; - u16 control; - ssize_t len; -diff -purNx .git BPI-Router-Linux-kernel/net/mac80211/parse.c BPI-Router-Linux-kernel-6.16.12/net/mac80211/parse.c ---- BPI-Router-Linux-kernel/net/mac80211/parse.c 2025-10-22 13:53:23.643327076 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mac80211/parse.c 2025-10-22 13:53:56.823167656 -0400 -@@ -758,7 +758,6 @@ static size_t ieee802_11_find_bssid_prof - { - const struct element *elem, *sub; - size_t profile_len = 0; -- bool found = false; - - if (!bss || !bss->transmitted_bss) - return profile_len; -@@ -809,15 +808,14 @@ static size_t ieee802_11_find_bssid_prof - index[2], - new_bssid); - if (ether_addr_equal(new_bssid, bss->bssid)) { -- found = true; - elems->bssid_index_len = index[1]; - elems->bssid_index = (void *)&index[2]; -- break; -+ return profile_len; - } - } - } - -- return found ? profile_len : 0; -+ return 0; - } - - static void -diff -purNx .git BPI-Router-Linux-kernel/net/mac80211/rx.c BPI-Router-Linux-kernel-6.16.12/net/mac80211/rx.c ---- BPI-Router-Linux-kernel/net/mac80211/rx.c 2025-10-22 13:53:23.643327076 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mac80211/rx.c 2025-10-22 13:53:56.823167656 -0400 -@@ -3576,41 +3576,18 @@ ieee80211_rx_h_action(struct ieee80211_r - goto handled; - } - case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: { -- struct ieee80211_supported_band *sband; - u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth; -- enum ieee80211_sta_rx_bandwidth max_bw, new_bw; -- struct sta_opmode_info sta_opmode = {}; -+ -+ if (chanwidth != IEEE80211_HT_CHANWIDTH_20MHZ && -+ chanwidth != IEEE80211_HT_CHANWIDTH_ANY) -+ goto invalid; - - /* If it doesn't support 40 MHz it can't change ... */ - if (!(rx->link_sta->pub->ht_cap.cap & -- IEEE80211_HT_CAP_SUP_WIDTH_20_40)) -+ IEEE80211_HT_CAP_SUP_WIDTH_20_40)) - goto handled; - -- if (chanwidth == IEEE80211_HT_CHANWIDTH_20MHZ) -- max_bw = IEEE80211_STA_RX_BW_20; -- else -- max_bw = ieee80211_sta_cap_rx_bw(rx->link_sta); -- -- /* set cur_max_bandwidth and recalc sta bw */ -- rx->link_sta->cur_max_bandwidth = max_bw; -- new_bw = ieee80211_sta_cur_vht_bw(rx->link_sta); -- -- if (rx->link_sta->pub->bandwidth == new_bw) -- goto handled; -- -- rx->link_sta->pub->bandwidth = new_bw; -- sband = rx->local->hw.wiphy->bands[status->band]; -- sta_opmode.bw = -- ieee80211_sta_rx_bw_to_chan_width(rx->link_sta); -- sta_opmode.changed = STA_OPMODE_MAX_BW_CHANGED; -- -- rate_control_rate_update(local, sband, rx->link_sta, -- IEEE80211_RC_BW_CHANGED); -- cfg80211_sta_opmode_change_notify(sdata->dev, -- rx->sta->addr, -- &sta_opmode, -- GFP_ATOMIC); -- goto handled; -+ goto queue; - } - default: - goto invalid; -@@ -4234,10 +4211,16 @@ static bool ieee80211_rx_data_set_sta(st - rx->link_sta = NULL; - } - -- if (link_id < 0) -- rx->link = &rx->sdata->deflink; -- else if (!ieee80211_rx_data_set_link(rx, link_id)) -+ if (link_id < 0) { -+ if (ieee80211_vif_is_mld(&rx->sdata->vif) && -+ sta && !sta->sta.valid_links) -+ rx->link = -+ rcu_dereference(rx->sdata->link[sta->deflink.link_id]); -+ else -+ rx->link = &rx->sdata->deflink; -+ } else if (!ieee80211_rx_data_set_link(rx, link_id)) { - return false; -+ } - - return true; - } -@@ -4432,6 +4415,10 @@ static bool ieee80211_accept_frame(struc - if (!multicast && - !ether_addr_equal(sdata->dev->dev_addr, hdr->addr1)) - return false; -+ /* reject invalid/our STA address */ -+ if (!is_valid_ether_addr(hdr->addr2) || -+ ether_addr_equal(sdata->dev->dev_addr, hdr->addr2)) -+ return false; - if (!rx->sta) { - int rate_idx; - if (status->encoding != RX_ENC_LEGACY) -diff -purNx .git BPI-Router-Linux-kernel/net/mac80211/tdls.c BPI-Router-Linux-kernel-6.16.12/net/mac80211/tdls.c ---- BPI-Router-Linux-kernel/net/mac80211/tdls.c 2025-10-22 13:53:23.643327076 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mac80211/tdls.c 2025-10-22 13:53:56.823167656 -0400 -@@ -1422,7 +1422,7 @@ int ieee80211_tdls_oper(struct wiphy *wi - if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) - return -EOPNOTSUPP; - -- if (sdata->vif.type != NL80211_IFTYPE_STATION) -+ if (sdata->vif.type != NL80211_IFTYPE_STATION || !sdata->vif.cfg.assoc) - return -EINVAL; - - switch (oper) { -diff -purNx .git BPI-Router-Linux-kernel/net/mac80211/tests/chan-mode.c BPI-Router-Linux-kernel-6.16.12/net/mac80211/tests/chan-mode.c ---- BPI-Router-Linux-kernel/net/mac80211/tests/chan-mode.c 2025-10-22 13:53:23.643327076 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mac80211/tests/chan-mode.c 2025-10-22 13:53:56.823167656 -0400 -@@ -2,7 +2,7 @@ - /* - * KUnit tests for channel mode functions - * -- * Copyright (C) 2024 Intel Corporation -+ * Copyright (C) 2024-2025 Intel Corporation - */ - #include - #include -@@ -28,6 +28,10 @@ static const struct determine_chan_mode_ - u8 vht_basic_mcs_1_4, vht_basic_mcs_5_8; - u8 he_basic_mcs_1_4, he_basic_mcs_5_8; - u8 eht_mcs7_min_nss; -+ u16 eht_disabled_subchannels; -+ u8 eht_bw; -+ enum ieee80211_conn_bw_limit conn_bw_limit; -+ enum ieee80211_conn_bw_limit expected_bw_limit; - int error; - } determine_chan_mode_cases[] = { - { -@@ -128,6 +132,14 @@ static const struct determine_chan_mode_ - .conn_mode = IEEE80211_CONN_MODE_EHT, - .eht_mcs7_min_nss = 0x15, - .error = EINVAL, -+ }, { -+ .desc = "80 MHz EHT is downgraded to 40 MHz HE due to puncturing", -+ .conn_mode = IEEE80211_CONN_MODE_EHT, -+ .expected_mode = IEEE80211_CONN_MODE_HE, -+ .conn_bw_limit = IEEE80211_CONN_BW_LIMIT_80, -+ .expected_bw_limit = IEEE80211_CONN_BW_LIMIT_40, -+ .eht_disabled_subchannels = 0x08, -+ .eht_bw = IEEE80211_EHT_OPER_CHAN_WIDTH_80MHZ, - } - }; - KUNIT_ARRAY_PARAM_DESC(determine_chan_mode, determine_chan_mode_cases, desc) -@@ -138,7 +150,7 @@ static void test_determine_chan_mode(str - struct t_sdata *t_sdata = T_SDATA(test); - struct ieee80211_conn_settings conn = { - .mode = params->conn_mode, -- .bw_limit = IEEE80211_CONN_BW_LIMIT_20, -+ .bw_limit = params->conn_bw_limit, - }; - struct cfg80211_bss cbss = { - .channel = &t_sdata->band_5ghz.channels[0], -@@ -191,14 +203,21 @@ static void test_determine_chan_mode(str - 0x7f, 0x01, 0x00, 0x88, 0x88, 0x88, 0x00, 0x00, - 0x00, - /* EHT Operation */ -- WLAN_EID_EXTENSION, 0x09, WLAN_EID_EXT_EHT_OPERATION, -- 0x01, params->eht_mcs7_min_nss ? params->eht_mcs7_min_nss : 0x11, -- 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, -+ WLAN_EID_EXTENSION, 0x0b, WLAN_EID_EXT_EHT_OPERATION, -+ 0x03, params->eht_mcs7_min_nss ? params->eht_mcs7_min_nss : 0x11, -+ 0x00, 0x00, 0x00, params->eht_bw, -+ params->eht_bw == IEEE80211_EHT_OPER_CHAN_WIDTH_80MHZ ? 42 : 36, -+ 0x00, -+ u16_get_bits(params->eht_disabled_subchannels, 0xff), -+ u16_get_bits(params->eht_disabled_subchannels, 0xff00), - }; - struct ieee80211_chan_req chanreq = {}; - struct cfg80211_chan_def ap_chandef = {}; - struct ieee802_11_elems *elems; - -+ /* To force EHT downgrade to HE on punctured 80 MHz downgraded to 40 MHz */ -+ set_bit(IEEE80211_HW_DISALLOW_PUNCTURING, t_sdata->local.hw.flags); -+ - if (params->strict) - set_bit(IEEE80211_HW_STRICT, t_sdata->local.hw.flags); - else -@@ -237,6 +256,7 @@ static void test_determine_chan_mode(str - } else { - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, elems); - KUNIT_ASSERT_EQ(test, conn.mode, params->expected_mode); -+ KUNIT_ASSERT_EQ(test, conn.bw_limit, params->expected_bw_limit); - } - } - -diff -purNx .git BPI-Router-Linux-kernel/net/mac80211/tx.c BPI-Router-Linux-kernel-6.16.12/net/mac80211/tx.c ---- BPI-Router-Linux-kernel/net/mac80211/tx.c 2025-10-22 13:53:23.647327057 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mac80211/tx.c 2025-10-22 13:53:56.823167656 -0400 -@@ -5,7 +5,7 @@ - * Copyright 2006-2007 Jiri Benc - * Copyright 2007 Johannes Berg - * Copyright 2013-2014 Intel Mobile Communications GmbH -- * Copyright (C) 2018-2024 Intel Corporation -+ * Copyright (C) 2018-2025 Intel Corporation - * - * Transmit and frame generation functions. - */ -@@ -612,6 +612,12 @@ ieee80211_tx_h_select_key(struct ieee802 - else - tx->key = NULL; - -+ if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) { -+ if (tx->key && tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) -+ info->control.hw_key = &tx->key->conf; -+ return TX_CONTINUE; -+ } -+ - if (tx->key) { - bool skip_hw = false; - -@@ -1428,7 +1434,7 @@ static void ieee80211_txq_enqueue(struct - { - struct fq *fq = &local->fq; - struct fq_tin *tin = &txqi->tin; -- u32 flow_idx = fq_flow_idx(fq, skb); -+ u32 flow_idx; - - ieee80211_set_skb_enqueue_time(skb); - -@@ -1444,6 +1450,7 @@ static void ieee80211_txq_enqueue(struct - IEEE80211_TX_INTCFL_NEED_TXPROCESSING; - __skb_queue_tail(&txqi->frags, skb); - } else { -+ flow_idx = fq_flow_idx(fq, skb); - fq_tin_enqueue(fq, tin, flow_idx, skb, - fq_skb_free_func); - } -@@ -3876,6 +3883,7 @@ begin: - * The key can be removed while the packet was queued, so need to call - * this here to get the current key. - */ -+ info->control.hw_key = NULL; - r = ieee80211_tx_h_select_key(&tx); - if (r != TX_CONTINUE) { - ieee80211_free_txskb(&local->hw, skb); -@@ -4098,7 +4106,9 @@ void __ieee80211_schedule_txq(struct iee - - spin_lock_bh(&local->active_txq_lock[txq->ac]); - -- has_queue = force || txq_has_queue(txq); -+ has_queue = force || -+ (!test_bit(IEEE80211_TXQ_STOP, &txqi->flags) && -+ txq_has_queue(txq)); - if (list_empty(&txqi->schedule_order) && - (has_queue || ieee80211_txq_keep_active(txqi))) { - /* If airtime accounting is active, always enqueue STAs at the -@@ -5016,12 +5026,25 @@ static void ieee80211_set_beacon_cntdwn( - } - } - --static u8 __ieee80211_beacon_update_cntdwn(struct beacon_data *beacon) -+static u8 __ieee80211_beacon_update_cntdwn(struct ieee80211_link_data *link, -+ struct beacon_data *beacon) - { -- beacon->cntdwn_current_counter--; -+ if (beacon->cntdwn_current_counter == 1) { -+ /* -+ * Channel switch handling is done by a worker thread while -+ * beacons get pulled from hardware timers. It's therefore -+ * possible that software threads are slow enough to not be -+ * able to complete CSA handling in a single beacon interval, -+ * in which case we get here. There isn't much to do about -+ * it, other than letting the user know that the AP isn't -+ * behaving correctly. -+ */ -+ link_err_once(link, -+ "beacon TX faster than countdown (channel/color switch) completion\n"); -+ return 0; -+ } - -- /* the counter should never reach 0 */ -- WARN_ON_ONCE(!beacon->cntdwn_current_counter); -+ beacon->cntdwn_current_counter--; - - return beacon->cntdwn_current_counter; - } -@@ -5052,7 +5075,7 @@ u8 ieee80211_beacon_update_cntdwn(struct - if (!beacon) - goto unlock; - -- count = __ieee80211_beacon_update_cntdwn(beacon); -+ count = __ieee80211_beacon_update_cntdwn(link, beacon); - - unlock: - rcu_read_unlock(); -@@ -5450,7 +5473,7 @@ __ieee80211_beacon_get(struct ieee80211_ - - if (beacon->cntdwn_counter_offsets[0]) { - if (!is_template) -- __ieee80211_beacon_update_cntdwn(beacon); -+ __ieee80211_beacon_update_cntdwn(link, beacon); - - ieee80211_set_beacon_cntdwn(sdata, beacon, link); - } -@@ -5482,7 +5505,7 @@ __ieee80211_beacon_get(struct ieee80211_ - * for now we leave it consistent with overall - * mac80211's behavior. - */ -- __ieee80211_beacon_update_cntdwn(beacon); -+ __ieee80211_beacon_update_cntdwn(link, beacon); - - ieee80211_set_beacon_cntdwn(sdata, beacon, link); - } -diff -purNx .git BPI-Router-Linux-kernel/net/mac80211/util.c BPI-Router-Linux-kernel-6.16.12/net/mac80211/util.c ---- BPI-Router-Linux-kernel/net/mac80211/util.c 2025-10-22 13:53:23.647327057 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mac80211/util.c 2025-10-22 13:53:56.823167656 -0400 -@@ -2144,11 +2144,6 @@ int ieee80211_reconfig(struct ieee80211_ - cfg80211_sched_scan_stopped_locked(local->hw.wiphy, 0); - - wake_up: -- -- if (local->virt_monitors > 0 && -- local->virt_monitors == local->open_count) -- ieee80211_add_virtual_monitor(local); -- - /* - * Clear the WLAN_STA_BLOCK_BA flag so new aggregation - * sessions can be established after a resume. -@@ -2202,6 +2197,10 @@ int ieee80211_reconfig(struct ieee80211_ - } - } - -+ if (local->virt_monitors > 0 && -+ local->virt_monitors == local->open_count) -+ ieee80211_add_virtual_monitor(local); -+ - if (!suspended) - return 0; - -@@ -3884,7 +3883,7 @@ void ieee80211_recalc_dtim(struct ieee80 - { - u64 tsf = drv_get_tsf(local, sdata); - u64 dtim_count = 0; -- u16 beacon_int = sdata->vif.bss_conf.beacon_int * 1024; -+ u32 beacon_int = sdata->vif.bss_conf.beacon_int * 1024; - u8 dtim_period = sdata->vif.bss_conf.dtim_period; - struct ps_data *ps; - u8 bcns_from_dtim; -diff -purNx .git BPI-Router-Linux-kernel/net/mctp/af_mctp.c BPI-Router-Linux-kernel-6.16.12/net/mctp/af_mctp.c ---- BPI-Router-Linux-kernel/net/mctp/af_mctp.c 2025-10-22 13:53:23.647327057 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mctp/af_mctp.c 2025-10-22 13:53:56.823167656 -0400 -@@ -73,7 +73,6 @@ static int mctp_bind(struct socket *sock - - lock_sock(sk); - -- /* TODO: allow rebind */ - if (sk_hashed(sk)) { - rc = -EADDRINUSE; - goto out_release; -@@ -347,7 +346,7 @@ static int mctp_getsockopt(struct socket - return 0; - } - -- return -EINVAL; -+ return -ENOPROTOOPT; - } - - /* helpers for reading/writing the tag ioc, handling compatibility across the -@@ -629,15 +628,36 @@ static void mctp_sk_close(struct sock *s - static int mctp_sk_hash(struct sock *sk) - { - struct net *net = sock_net(sk); -+ struct sock *existing; -+ struct mctp_sock *msk; -+ int rc; -+ -+ msk = container_of(sk, struct mctp_sock, sk); - - /* Bind lookup runs under RCU, remain live during that. */ - sock_set_flag(sk, SOCK_RCU_FREE); - - mutex_lock(&net->mctp.bind_lock); -+ -+ /* Prevent duplicate binds. */ -+ sk_for_each(existing, &net->mctp.binds) { -+ struct mctp_sock *mex = -+ container_of(existing, struct mctp_sock, sk); -+ -+ if (mex->bind_type == msk->bind_type && -+ mex->bind_addr == msk->bind_addr && -+ mex->bind_net == msk->bind_net) { -+ rc = -EADDRINUSE; -+ goto out; -+ } -+ } -+ - sk_add_node_rcu(sk, &net->mctp.binds); -- mutex_unlock(&net->mctp.bind_lock); -+ rc = 0; - -- return 0; -+out: -+ mutex_unlock(&net->mctp.bind_lock); -+ return rc; - } - - static void mctp_sk_unhash(struct sock *sk) -diff -purNx .git BPI-Router-Linux-kernel/net/mctp/route.c BPI-Router-Linux-kernel-6.16.12/net/mctp/route.c ---- BPI-Router-Linux-kernel/net/mctp/route.c 2025-10-22 13:53:23.647327057 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mctp/route.c 2025-10-22 13:53:56.823167656 -0400 -@@ -325,6 +325,7 @@ static void mctp_skb_set_flow(struct sk_ - static void mctp_flow_prepare_output(struct sk_buff *skb, struct mctp_dev *dev) {} - #endif - -+/* takes ownership of skb, both in success and failure cases */ - static int mctp_frag_queue(struct mctp_sk_key *key, struct sk_buff *skb) - { - struct mctp_hdr *hdr = mctp_hdr(skb); -@@ -334,8 +335,10 @@ static int mctp_frag_queue(struct mctp_s - & MCTP_HDR_SEQ_MASK; - - if (!key->reasm_head) { -- /* Since we're manipulating the shared frag_list, ensure it isn't -- * shared with any other SKBs. -+ /* Since we're manipulating the shared frag_list, ensure it -+ * isn't shared with any other SKBs. In the cloned case, -+ * this will free the skb; callers can no longer access it -+ * safely. - */ - key->reasm_head = skb_unshare(skb, GFP_ATOMIC); - if (!key->reasm_head) -@@ -349,10 +352,10 @@ static int mctp_frag_queue(struct mctp_s - exp_seq = (key->last_seq + 1) & MCTP_HDR_SEQ_MASK; - - if (this_seq != exp_seq) -- return -EINVAL; -+ goto err_free; - - if (key->reasm_head->len + skb->len > mctp_message_maxlen) -- return -EINVAL; -+ goto err_free; - - skb->next = NULL; - skb->sk = NULL; -@@ -366,6 +369,10 @@ static int mctp_frag_queue(struct mctp_s - key->reasm_head->truesize += skb->truesize; - - return 0; -+ -+err_free: -+ kfree_skb(skb); -+ return -EINVAL; - } - - static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb) -@@ -476,18 +483,16 @@ static int mctp_route_input(struct mctp_ - * key isn't observable yet - */ - mctp_frag_queue(key, skb); -+ skb = NULL; - - /* if the key_add fails, we've raced with another - * SOM packet with the same src, dest and tag. There's - * no way to distinguish future packets, so all we -- * can do is drop; we'll free the skb on exit from -- * this function. -+ * can do is drop. - */ - rc = mctp_key_add(key, msk); -- if (!rc) { -+ if (!rc) - trace_mctp_key_acquire(key); -- skb = NULL; -- } - - /* we don't need to release key->lock on exit, so - * clean up here and suppress the unlock via -@@ -505,8 +510,7 @@ static int mctp_route_input(struct mctp_ - key = NULL; - } else { - rc = mctp_frag_queue(key, skb); -- if (!rc) -- skb = NULL; -+ skb = NULL; - } - } - -@@ -516,17 +520,16 @@ static int mctp_route_input(struct mctp_ - */ - - /* we need to be continuing an existing reassembly... */ -- if (!key->reasm_head) -+ if (!key->reasm_head) { - rc = -EINVAL; -- else -+ } else { - rc = mctp_frag_queue(key, skb); -+ skb = NULL; -+ } - - if (rc) - goto out_unlock; - -- /* we've queued; the queue owns the skb now */ -- skb = NULL; -- - /* end of message? deliver to socket, and we're done with - * the reassembly/response key - */ -diff -purNx .git BPI-Router-Linux-kernel/net/mpls/af_mpls.c BPI-Router-Linux-kernel-6.16.12/net/mpls/af_mpls.c ---- BPI-Router-Linux-kernel/net/mpls/af_mpls.c 2025-10-22 13:53:23.647327057 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mpls/af_mpls.c 2025-10-22 13:53:56.823167656 -0400 -@@ -81,8 +81,8 @@ static struct mpls_route *mpls_route_inp - - if (index < net->mpls.platform_labels) { - struct mpls_route __rcu **platform_label = -- rcu_dereference(net->mpls.platform_label); -- rt = rcu_dereference(platform_label[index]); -+ rcu_dereference_rtnl(net->mpls.platform_label); -+ rt = rcu_dereference_rtnl(platform_label[index]); - } - return rt; - } -diff -purNx .git BPI-Router-Linux-kernel/net/mptcp/options.c BPI-Router-Linux-kernel-6.16.12/net/mptcp/options.c ---- BPI-Router-Linux-kernel/net/mptcp/options.c 2025-10-22 13:53:23.647327057 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mptcp/options.c 2025-10-22 13:53:56.823167656 -0400 -@@ -978,18 +978,19 @@ static bool check_fully_established(stru - if (subflow->mp_join) - goto reset; - subflow->mp_capable = 0; -+ if (!mptcp_try_fallback(ssk)) -+ goto reset; - pr_fallback(msk); -- mptcp_do_fallback(ssk); - return false; - } - -- if (mp_opt->deny_join_id0) -- WRITE_ONCE(msk->pm.remote_deny_join_id0, true); -- - if (unlikely(!READ_ONCE(msk->pm.server_side))) - pr_warn_once("bogus mpc option on established client sk"); - - set_fully_established: -+ if (mp_opt->deny_join_id0) -+ WRITE_ONCE(msk->pm.remote_deny_join_id0, true); -+ - mptcp_data_lock((struct sock *)msk); - __mptcp_subflow_fully_established(msk, subflow, mp_opt); - mptcp_data_unlock((struct sock *)msk); -@@ -1116,7 +1117,9 @@ static bool add_addr_hmac_valid(struct m - return hmac == mp_opt->ahmac; - } - --/* Return false if a subflow has been reset, else return true */ -+/* Return false in case of error (or subflow has been reset), -+ * else return true. -+ */ - bool mptcp_incoming_options(struct sock *sk, struct sk_buff *skb) - { - struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); -@@ -1220,7 +1223,7 @@ bool mptcp_incoming_options(struct sock - - mpext = skb_ext_add(skb, SKB_EXT_MPTCP); - if (!mpext) -- return true; -+ return false; - - memset(mpext, 0, sizeof(*mpext)); - -diff -purNx .git BPI-Router-Linux-kernel/net/mptcp/pm.c BPI-Router-Linux-kernel-6.16.12/net/mptcp/pm.c ---- BPI-Router-Linux-kernel/net/mptcp/pm.c 2025-10-22 13:53:23.647327057 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mptcp/pm.c 2025-10-22 13:53:56.823167656 -0400 -@@ -274,6 +274,7 @@ static void mptcp_pm_add_timer(struct ti - add_timer); - struct mptcp_sock *msk = entry->sock; - struct sock *sk = (struct sock *)msk; -+ unsigned int timeout; - - pr_debug("msk=%p\n", msk); - -@@ -291,6 +292,10 @@ static void mptcp_pm_add_timer(struct ti - goto out; - } - -+ timeout = mptcp_get_add_addr_timeout(sock_net(sk)); -+ if (!timeout) -+ goto out; -+ - spin_lock_bh(&msk->pm.lock); - - if (!mptcp_pm_should_add_signal_addr(msk)) { -@@ -302,7 +307,7 @@ static void mptcp_pm_add_timer(struct ti - - if (entry->retrans_times < ADD_ADDR_RETRANS_MAX) - sk_reset_timer(sk, timer, -- jiffies + mptcp_get_add_addr_timeout(sock_net(sk))); -+ jiffies + timeout); - - spin_unlock_bh(&msk->pm.lock); - -@@ -344,6 +349,7 @@ bool mptcp_pm_alloc_anno_list(struct mpt - struct mptcp_pm_add_entry *add_entry = NULL; - struct sock *sk = (struct sock *)msk; - struct net *net = sock_net(sk); -+ unsigned int timeout; - - lockdep_assert_held(&msk->pm.lock); - -@@ -353,9 +359,7 @@ bool mptcp_pm_alloc_anno_list(struct mpt - if (WARN_ON_ONCE(mptcp_pm_is_kernel(msk))) - return false; - -- sk_reset_timer(sk, &add_entry->add_timer, -- jiffies + mptcp_get_add_addr_timeout(net)); -- return true; -+ goto reset_timer; - } - - add_entry = kmalloc(sizeof(*add_entry), GFP_ATOMIC); -@@ -369,8 +373,10 @@ bool mptcp_pm_alloc_anno_list(struct mpt - add_entry->retrans_times = 0; - - timer_setup(&add_entry->add_timer, mptcp_pm_add_timer, 0); -- sk_reset_timer(sk, &add_entry->add_timer, -- jiffies + mptcp_get_add_addr_timeout(net)); -+reset_timer: -+ timeout = mptcp_get_add_addr_timeout(net); -+ if (timeout) -+ sk_reset_timer(sk, &add_entry->add_timer, jiffies + timeout); - - return true; - } -@@ -765,8 +771,14 @@ void mptcp_pm_mp_fail_received(struct so - - pr_debug("fail_seq=%llu\n", fail_seq); - -- if (!READ_ONCE(msk->allow_infinite_fallback)) -+ /* After accepting the fail, we can't create any other subflows */ -+ spin_lock_bh(&msk->fallback_lock); -+ if (!msk->allow_infinite_fallback) { -+ spin_unlock_bh(&msk->fallback_lock); - return; -+ } -+ msk->allow_subflows = false; -+ spin_unlock_bh(&msk->fallback_lock); - - if (!subflow->fail_tout) { - pr_debug("send MP_FAIL response and infinite map\n"); -diff -purNx .git BPI-Router-Linux-kernel/net/mptcp/pm_kernel.c BPI-Router-Linux-kernel-6.16.12/net/mptcp/pm_kernel.c ---- BPI-Router-Linux-kernel/net/mptcp/pm_kernel.c 2025-10-22 13:53:23.647327057 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mptcp/pm_kernel.c 2025-10-22 13:53:56.823167656 -0400 -@@ -1085,7 +1085,6 @@ static void __flush_addrs(struct list_he - static void __reset_counters(struct pm_nl_pernet *pernet) - { - WRITE_ONCE(pernet->add_addr_signal_max, 0); -- WRITE_ONCE(pernet->add_addr_accept_max, 0); - WRITE_ONCE(pernet->local_addr_max, 0); - pernet->addrs = 0; - } -diff -purNx .git BPI-Router-Linux-kernel/net/mptcp/pm_netlink.c BPI-Router-Linux-kernel-6.16.12/net/mptcp/pm_netlink.c ---- BPI-Router-Linux-kernel/net/mptcp/pm_netlink.c 2025-10-22 13:53:23.647327057 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mptcp/pm_netlink.c 2025-10-22 13:53:56.823167656 -0400 -@@ -408,6 +408,7 @@ static int mptcp_event_created(struct sk - const struct sock *ssk) - { - int err = nla_put_u32(skb, MPTCP_ATTR_TOKEN, READ_ONCE(msk->token)); -+ u16 flags = 0; - - if (err) - return err; -@@ -415,6 +416,12 @@ static int mptcp_event_created(struct sk - if (nla_put_u8(skb, MPTCP_ATTR_SERVER_SIDE, READ_ONCE(msk->pm.server_side))) - return -EMSGSIZE; - -+ if (READ_ONCE(msk->pm.remote_deny_join_id0)) -+ flags |= MPTCP_PM_EV_FLAG_DENY_JOIN_ID0; -+ -+ if (flags && nla_put_u16(skb, MPTCP_ATTR_FLAGS, flags)) -+ return -EMSGSIZE; -+ - return mptcp_event_add_subflow(skb, ssk); - } - -diff -purNx .git BPI-Router-Linux-kernel/net/mptcp/protocol.c BPI-Router-Linux-kernel-6.16.12/net/mptcp/protocol.c ---- BPI-Router-Linux-kernel/net/mptcp/protocol.c 2025-10-22 13:53:23.647327057 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mptcp/protocol.c 2025-10-22 13:53:56.827167637 -0400 -@@ -350,6 +350,20 @@ static void mptcp_close_wake_up(struct s - sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); - } - -+static void mptcp_shutdown_subflows(struct mptcp_sock *msk) -+{ -+ struct mptcp_subflow_context *subflow; -+ -+ mptcp_for_each_subflow(msk, subflow) { -+ struct sock *ssk = mptcp_subflow_tcp_sock(subflow); -+ bool slow; -+ -+ slow = lock_sock_fast(ssk); -+ tcp_shutdown(ssk, SEND_SHUTDOWN); -+ unlock_sock_fast(ssk, slow); -+ } -+} -+ - /* called under the msk socket lock */ - static bool mptcp_pending_data_fin_ack(struct sock *sk) - { -@@ -374,6 +388,7 @@ static void mptcp_check_data_fin_ack(str - break; - case TCP_CLOSING: - case TCP_LAST_ACK: -+ mptcp_shutdown_subflows(msk); - mptcp_set_state(sk, TCP_CLOSE); - break; - } -@@ -542,6 +557,7 @@ static bool mptcp_check_data_fin(struct - mptcp_set_state(sk, TCP_CLOSING); - break; - case TCP_FIN_WAIT2: -+ mptcp_shutdown_subflows(msk); - mptcp_set_state(sk, TCP_CLOSE); - break; - default: -@@ -560,10 +576,9 @@ static bool mptcp_check_data_fin(struct - - static void mptcp_dss_corruption(struct mptcp_sock *msk, struct sock *ssk) - { -- if (READ_ONCE(msk->allow_infinite_fallback)) { -+ if (mptcp_try_fallback(ssk)) { - MPTCP_INC_STATS(sock_net(ssk), - MPTCP_MIB_DSSCORRUPTIONFALLBACK); -- mptcp_do_fallback(ssk); - } else { - MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DSSCORRUPTIONRESET); - mptcp_subflow_reset(ssk); -@@ -792,7 +807,7 @@ void mptcp_data_ready(struct sock *sk, s - static void mptcp_subflow_joined(struct mptcp_sock *msk, struct sock *ssk) - { - mptcp_subflow_ctx(ssk)->map_seq = READ_ONCE(msk->ack_seq); -- WRITE_ONCE(msk->allow_infinite_fallback, false); -+ msk->allow_infinite_fallback = false; - mptcp_event(MPTCP_EVENT_SUB_ESTABLISHED, msk, ssk, GFP_ATOMIC); - } - -@@ -803,6 +818,14 @@ static bool __mptcp_finish_join(struct m - if (sk->sk_state != TCP_ESTABLISHED) - return false; - -+ spin_lock_bh(&msk->fallback_lock); -+ if (!msk->allow_subflows) { -+ spin_unlock_bh(&msk->fallback_lock); -+ return false; -+ } -+ mptcp_subflow_joined(msk, ssk); -+ spin_unlock_bh(&msk->fallback_lock); -+ - /* attach to msk socket only after we are sure we will deal with it - * at close time - */ -@@ -811,7 +834,6 @@ static bool __mptcp_finish_join(struct m - - mptcp_subflow_ctx(ssk)->subflow_id = msk->subflow_id++; - mptcp_sockopt_sync_locked(msk, ssk); -- mptcp_subflow_joined(msk, ssk); - mptcp_stop_tout_timer(sk); - __mptcp_propagate_sndbuf(sk, ssk); - return true; -@@ -1136,10 +1158,14 @@ static void mptcp_update_infinite_map(st - mpext->infinite_map = 1; - mpext->data_len = 0; - -+ if (!mptcp_try_fallback(ssk)) { -+ mptcp_subflow_reset(ssk); -+ return; -+ } -+ - MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_INFINITEMAPTX); - mptcp_subflow_ctx(ssk)->send_infinite_map = 0; - pr_fallback(msk); -- mptcp_do_fallback(ssk); - } - - #define MPTCP_MAX_GSO_SIZE (GSO_LEGACY_MAX_SIZE - (MAX_TCP_HEADER + 1)) -@@ -2543,9 +2569,9 @@ static void mptcp_check_fastclose(struct - - static void __mptcp_retrans(struct sock *sk) - { -+ struct mptcp_sendmsg_info info = { .data_lock_held = true, }; - struct mptcp_sock *msk = mptcp_sk(sk); - struct mptcp_subflow_context *subflow; -- struct mptcp_sendmsg_info info = {}; - struct mptcp_data_frag *dfrag; - struct sock *ssk; - int ret, err; -@@ -2590,6 +2616,18 @@ static void __mptcp_retrans(struct sock - info.sent = 0; - info.limit = READ_ONCE(msk->csum_enabled) ? dfrag->data_len : - dfrag->already_sent; -+ -+ /* -+ * make the whole retrans decision, xmit, disallow -+ * fallback atomic -+ */ -+ spin_lock_bh(&msk->fallback_lock); -+ if (__mptcp_check_fallback(msk)) { -+ spin_unlock_bh(&msk->fallback_lock); -+ release_sock(ssk); -+ return; -+ } -+ - while (info.sent < info.limit) { - ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info); - if (ret <= 0) -@@ -2603,8 +2641,9 @@ static void __mptcp_retrans(struct sock - len = max(copied, len); - tcp_push(ssk, 0, info.mss_now, tcp_sk(ssk)->nonagle, - info.size_goal); -- WRITE_ONCE(msk->allow_infinite_fallback, false); -+ msk->allow_infinite_fallback = false; - } -+ spin_unlock_bh(&msk->fallback_lock); - - release_sock(ssk); - } -@@ -2730,7 +2769,8 @@ static void __mptcp_init_sock(struct soc - WRITE_ONCE(msk->first, NULL); - inet_csk(sk)->icsk_sync_mss = mptcp_sync_mss; - WRITE_ONCE(msk->csum_enabled, mptcp_is_checksum_enabled(sock_net(sk))); -- WRITE_ONCE(msk->allow_infinite_fallback, true); -+ msk->allow_infinite_fallback = true; -+ msk->allow_subflows = true; - msk->recovery = false; - msk->subflow_id = 1; - msk->last_data_sent = tcp_jiffies32; -@@ -2738,6 +2778,7 @@ static void __mptcp_init_sock(struct soc - msk->last_ack_recv = tcp_jiffies32; - - mptcp_pm_data_init(msk); -+ spin_lock_init(&msk->fallback_lock); - - /* re-use the csk retrans timer for MPTCP-level retrans */ - timer_setup(&msk->sk.icsk_retransmit_timer, mptcp_retransmit_timer, 0); -@@ -3117,7 +3158,16 @@ static int mptcp_disconnect(struct sock - * subflow - */ - mptcp_destroy_common(msk, MPTCP_CF_FASTCLOSE); -+ -+ /* The first subflow is already in TCP_CLOSE status, the following -+ * can't overlap with a fallback anymore -+ */ -+ spin_lock_bh(&msk->fallback_lock); -+ msk->allow_subflows = true; -+ msk->allow_infinite_fallback = true; - WRITE_ONCE(msk->flags, 0); -+ spin_unlock_bh(&msk->fallback_lock); -+ - msk->cb_flags = 0; - msk->recovery = false; - WRITE_ONCE(msk->can_ack, false); -@@ -3503,7 +3553,6 @@ void mptcp_sock_graft(struct sock *sk, s - write_lock_bh(&sk->sk_callback_lock); - rcu_assign_pointer(sk->sk_wq, &parent->wq); - sk_set_socket(sk, parent); -- sk->sk_uid = SOCK_INODE(parent)->i_uid; - write_unlock_bh(&sk->sk_callback_lock); - } - -@@ -3524,7 +3573,13 @@ bool mptcp_finish_join(struct sock *ssk) - - /* active subflow, already present inside the conn_list */ - if (!list_empty(&subflow->node)) { -+ spin_lock_bh(&msk->fallback_lock); -+ if (!msk->allow_subflows) { -+ spin_unlock_bh(&msk->fallback_lock); -+ return false; -+ } - mptcp_subflow_joined(msk, ssk); -+ spin_unlock_bh(&msk->fallback_lock); - mptcp_propagate_sndbuf(parent, ssk); - return true; - } -diff -purNx .git BPI-Router-Linux-kernel/net/mptcp/protocol.h BPI-Router-Linux-kernel-6.16.12/net/mptcp/protocol.h ---- BPI-Router-Linux-kernel/net/mptcp/protocol.h 2025-10-22 13:53:23.647327057 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mptcp/protocol.h 2025-10-22 13:53:56.827167637 -0400 -@@ -346,10 +346,16 @@ struct mptcp_sock { - u64 rtt_us; /* last maximum rtt of subflows */ - } rcvq_space; - u8 scaling_ratio; -+ bool allow_subflows; - - u32 subflow_id; - u32 setsockopt_seq; - char ca_name[TCP_CA_NAME_MAX]; -+ -+ spinlock_t fallback_lock; /* protects fallback, -+ * allow_infinite_fallback and -+ * allow_join -+ */ - }; - - #define mptcp_data_lock(sk) spin_lock_bh(&(sk)->sk_lock.slock) -@@ -1216,15 +1222,22 @@ static inline bool mptcp_check_fallback( - return __mptcp_check_fallback(msk); - } - --static inline void __mptcp_do_fallback(struct mptcp_sock *msk) -+static inline bool __mptcp_try_fallback(struct mptcp_sock *msk) - { - if (__mptcp_check_fallback(msk)) { - pr_debug("TCP fallback already done (msk=%p)\n", msk); -- return; -+ return true; - } -- if (WARN_ON_ONCE(!READ_ONCE(msk->allow_infinite_fallback))) -- return; -+ spin_lock_bh(&msk->fallback_lock); -+ if (!msk->allow_infinite_fallback) { -+ spin_unlock_bh(&msk->fallback_lock); -+ return false; -+ } -+ -+ msk->allow_subflows = false; - set_bit(MPTCP_FALLBACK_DONE, &msk->flags); -+ spin_unlock_bh(&msk->fallback_lock); -+ return true; - } - - static inline bool __mptcp_has_initial_subflow(const struct mptcp_sock *msk) -@@ -1236,14 +1249,15 @@ static inline bool __mptcp_has_initial_s - TCPF_SYN_RECV | TCPF_LISTEN)); - } - --static inline void mptcp_do_fallback(struct sock *ssk) -+static inline bool mptcp_try_fallback(struct sock *ssk) - { - struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); - struct sock *sk = subflow->conn; - struct mptcp_sock *msk; - - msk = mptcp_sk(sk); -- __mptcp_do_fallback(msk); -+ if (!__mptcp_try_fallback(msk)) -+ return false; - if (READ_ONCE(msk->snd_data_fin_enable) && !(ssk->sk_shutdown & SEND_SHUTDOWN)) { - gfp_t saved_allocation = ssk->sk_allocation; - -@@ -1255,6 +1269,7 @@ static inline void mptcp_do_fallback(str - tcp_shutdown(ssk, SEND_SHUTDOWN); - ssk->sk_allocation = saved_allocation; - } -+ return true; - } - - #define pr_fallback(a) pr_debug("%s:fallback to TCP (msk=%p)\n", __func__, a) -@@ -1264,7 +1279,7 @@ static inline void mptcp_subflow_early_f - { - pr_fallback(msk); - subflow->request_mptcp = 0; -- __mptcp_do_fallback(msk); -+ WARN_ON_ONCE(!__mptcp_try_fallback(msk)); - } - - static inline bool mptcp_check_infinite_map(struct sk_buff *skb) -diff -purNx .git BPI-Router-Linux-kernel/net/mptcp/sockopt.c BPI-Router-Linux-kernel-6.16.12/net/mptcp/sockopt.c ---- BPI-Router-Linux-kernel/net/mptcp/sockopt.c 2025-10-22 13:53:23.647327057 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mptcp/sockopt.c 2025-10-22 13:53:56.827167637 -0400 -@@ -1508,13 +1508,12 @@ static void sync_socket_options(struct m - { - static const unsigned int tx_rx_locks = SOCK_RCVBUF_LOCK | SOCK_SNDBUF_LOCK; - struct sock *sk = (struct sock *)msk; -+ bool keep_open; - -- if (ssk->sk_prot->keepalive) { -- if (sock_flag(sk, SOCK_KEEPOPEN)) -- ssk->sk_prot->keepalive(ssk, 1); -- else -- ssk->sk_prot->keepalive(ssk, 0); -- } -+ keep_open = sock_flag(sk, SOCK_KEEPOPEN); -+ if (ssk->sk_prot->keepalive) -+ ssk->sk_prot->keepalive(ssk, keep_open); -+ sock_valbool_flag(ssk, SOCK_KEEPOPEN, keep_open); - - ssk->sk_priority = sk->sk_priority; - ssk->sk_bound_dev_if = sk->sk_bound_dev_if; -diff -purNx .git BPI-Router-Linux-kernel/net/mptcp/subflow.c BPI-Router-Linux-kernel-6.16.12/net/mptcp/subflow.c ---- BPI-Router-Linux-kernel/net/mptcp/subflow.c 2025-10-22 13:53:23.647327057 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/mptcp/subflow.c 2025-10-22 13:53:56.827167637 -0400 -@@ -544,9 +544,11 @@ static void subflow_finish_connect(struc - mptcp_get_options(skb, &mp_opt); - if (subflow->request_mptcp) { - if (!(mp_opt.suboptions & OPTION_MPTCP_MPC_SYNACK)) { -+ if (!mptcp_try_fallback(sk)) -+ goto do_reset; -+ - MPTCP_INC_STATS(sock_net(sk), - MPTCP_MIB_MPCAPABLEACTIVEFALLBACK); -- mptcp_do_fallback(sk); - pr_fallback(msk); - goto fallback; - } -@@ -880,6 +882,10 @@ create_child: - - ctx->subflow_id = 1; - owner = mptcp_sk(ctx->conn); -+ -+ if (mp_opt.deny_join_id0) -+ WRITE_ONCE(owner->pm.remote_deny_join_id0, true); -+ - mptcp_pm_new_connection(owner, child, 1); - - /* with OoO packets we can reach here without ingress -@@ -1300,20 +1306,29 @@ static void subflow_sched_work_if_closed - mptcp_schedule_work(sk); - } - --static void mptcp_subflow_fail(struct mptcp_sock *msk, struct sock *ssk) -+static bool mptcp_subflow_fail(struct mptcp_sock *msk, struct sock *ssk) - { - struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); - unsigned long fail_tout; - -+ /* we are really failing, prevent any later subflow join */ -+ spin_lock_bh(&msk->fallback_lock); -+ if (!msk->allow_infinite_fallback) { -+ spin_unlock_bh(&msk->fallback_lock); -+ return false; -+ } -+ msk->allow_subflows = false; -+ spin_unlock_bh(&msk->fallback_lock); -+ - /* graceful failure can happen only on the MPC subflow */ - if (WARN_ON_ONCE(ssk != READ_ONCE(msk->first))) -- return; -+ return false; - - /* since the close timeout take precedence on the fail one, - * no need to start the latter when the first is already set - */ - if (sock_flag((struct sock *)msk, SOCK_DEAD)) -- return; -+ return true; - - /* we don't need extreme accuracy here, use a zero fail_tout as special - * value meaning no fail timeout at all; -@@ -1325,6 +1340,7 @@ static void mptcp_subflow_fail(struct mp - tcp_send_ack(ssk); - - mptcp_reset_tout_timer(msk, subflow->fail_tout); -+ return true; - } - - static bool subflow_check_data_avail(struct sock *ssk) -@@ -1385,17 +1401,16 @@ fallback: - (subflow->mp_join || subflow->valid_csum_seen)) { - subflow->send_mp_fail = 1; - -- if (!READ_ONCE(msk->allow_infinite_fallback)) { -+ if (!mptcp_subflow_fail(msk, ssk)) { - subflow->reset_transient = 0; - subflow->reset_reason = MPTCP_RST_EMIDDLEBOX; - goto reset; - } -- mptcp_subflow_fail(msk, ssk); - WRITE_ONCE(subflow->data_avail, true); - return true; - } - -- if (!READ_ONCE(msk->allow_infinite_fallback)) { -+ if (!mptcp_try_fallback(ssk)) { - /* fatal protocol error, close the socket. - * subflow_error_report() will introduce the appropriate barriers - */ -@@ -1413,8 +1428,6 @@ reset: - WRITE_ONCE(subflow->data_avail, false); - return false; - } -- -- mptcp_do_fallback(ssk); - } - - skb = skb_peek(&ssk->sk_receive_queue); -@@ -1679,7 +1692,6 @@ int __mptcp_subflow_connect(struct sock - /* discard the subflow socket */ - mptcp_sock_graft(ssk, sk->sk_socket); - iput(SOCK_INODE(sf)); -- WRITE_ONCE(msk->allow_infinite_fallback, false); - mptcp_stop_tout_timer(sk); - return 0; - -@@ -1851,7 +1863,7 @@ static void subflow_state_change(struct - - msk = mptcp_sk(parent); - if (subflow_simultaneous_connect(sk)) { -- mptcp_do_fallback(sk); -+ WARN_ON_ONCE(!mptcp_try_fallback(sk)); - pr_fallback(msk); - subflow->conn_finished = 1; - mptcp_propagate_state(parent, sk, subflow, NULL); -diff -purNx .git BPI-Router-Linux-kernel/net/ncsi/internal.h BPI-Router-Linux-kernel-6.16.12/net/ncsi/internal.h ---- BPI-Router-Linux-kernel/net/ncsi/internal.h 2025-10-22 13:53:23.647327057 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ncsi/internal.h 2025-10-22 13:53:56.827167637 -0400 -@@ -110,7 +110,7 @@ struct ncsi_channel_version { - u8 update; /* NCSI version update */ - char alpha1; /* NCSI version alpha1 */ - char alpha2; /* NCSI version alpha2 */ -- u8 fw_name[12]; /* Firmware name string */ -+ u8 fw_name[12 + 1]; /* Firmware name string */ - u32 fw_version; /* Firmware version */ - u16 pci_ids[4]; /* PCI identification */ - u32 mf_id; /* Manufacture ID */ -diff -purNx .git BPI-Router-Linux-kernel/net/ncsi/ncsi-rsp.c BPI-Router-Linux-kernel-6.16.12/net/ncsi/ncsi-rsp.c ---- BPI-Router-Linux-kernel/net/ncsi/ncsi-rsp.c 2025-10-22 13:53:23.647327057 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/ncsi/ncsi-rsp.c 2025-10-22 13:53:56.827167637 -0400 -@@ -775,6 +775,7 @@ static int ncsi_rsp_handler_gvi(struct n - ncv->alpha1 = rsp->alpha1; - ncv->alpha2 = rsp->alpha2; - memcpy(ncv->fw_name, rsp->fw_name, 12); -+ ncv->fw_name[12] = '\0'; - ncv->fw_version = ntohl(rsp->fw_version); - for (i = 0; i < ARRAY_SIZE(ncv->pci_ids); i++) - ncv->pci_ids[i] = ntohs(rsp->pci_ids[i]); -diff -purNx .git BPI-Router-Linux-kernel/net/netfilter/ipvs/ip_vs_est.c BPI-Router-Linux-kernel-6.16.12/net/netfilter/ipvs/ip_vs_est.c ---- BPI-Router-Linux-kernel/net/netfilter/ipvs/ip_vs_est.c 2025-10-22 13:53:23.647327057 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/netfilter/ipvs/ip_vs_est.c 2025-10-22 13:53:56.827167637 -0400 -@@ -265,7 +265,8 @@ int ip_vs_est_kthread_start(struct netns - } - - set_user_nice(kd->task, sysctl_est_nice(ipvs)); -- set_cpus_allowed_ptr(kd->task, sysctl_est_cpulist(ipvs)); -+ if (sysctl_est_preferred_cpulist(ipvs)) -+ kthread_affine_preferred(kd->task, sysctl_est_preferred_cpulist(ipvs)); - - pr_info("starting estimator thread %d...\n", kd->id); - wake_up_process(kd->task); -diff -purNx .git BPI-Router-Linux-kernel/net/netfilter/nf_bpf_link.c BPI-Router-Linux-kernel-6.16.12/net/netfilter/nf_bpf_link.c ---- BPI-Router-Linux-kernel/net/netfilter/nf_bpf_link.c 2025-10-22 13:53:23.647327057 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/netfilter/nf_bpf_link.c 2025-10-22 13:53:56.827167637 -0400 -@@ -17,7 +17,7 @@ static unsigned int nf_hook_run_bpf(void - .skb = skb, - }; - -- return bpf_prog_run(prog, &ctx); -+ return bpf_prog_run_pin_on_cpu(prog, &ctx); - } - - struct bpf_nf_link { -@@ -295,6 +295,9 @@ static bool nf_is_valid_access(int off, - if (off < 0 || off >= sizeof(struct bpf_nf_ctx)) - return false; - -+ if (off % size != 0) -+ return false; -+ - if (type == BPF_WRITE) - return false; - -diff -purNx .git BPI-Router-Linux-kernel/net/netfilter/nf_conntrack_core.c BPI-Router-Linux-kernel-6.16.12/net/netfilter/nf_conntrack_core.c ---- BPI-Router-Linux-kernel/net/netfilter/nf_conntrack_core.c 2025-10-22 13:53:23.647327057 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/netfilter/nf_conntrack_core.c 2025-10-22 13:53:56.827167637 -0400 -@@ -1124,6 +1124,12 @@ static int nf_ct_resolve_clash_harder(st - - hlist_nulls_add_head_rcu(&loser_ct->tuplehash[IP_CT_DIR_REPLY].hnnode, - &nf_conntrack_hash[repl_idx]); -+ /* confirmed bit must be set after hlist add, not before: -+ * loser_ct can still be visible to other cpu due to -+ * SLAB_TYPESAFE_BY_RCU. -+ */ -+ smp_mb__before_atomic(); -+ set_bit(IPS_CONFIRMED_BIT, &loser_ct->status); - - NF_CT_STAT_INC(net, clash_resolve); - return NF_ACCEPT; -@@ -1260,8 +1266,6 @@ __nf_conntrack_confirm(struct sk_buff *s - * user context, else we insert an already 'dead' hash, blocking - * further use of that particular connection -JM. - */ -- ct->status |= IPS_CONFIRMED; -- - if (unlikely(nf_ct_is_dying(ct))) { - NF_CT_STAT_INC(net, insert_failed); - goto dying; -@@ -1293,7 +1297,7 @@ chaintoolong: - } - } - -- /* Timer relative to confirmation time, not original -+ /* Timeout is relative to confirmation time, not original - setting time, otherwise we'd get timer wrap in - weird delay cases. */ - ct->timeout += nfct_time_stamp; -@@ -1301,11 +1305,21 @@ chaintoolong: - __nf_conntrack_insert_prepare(ct); - - /* Since the lookup is lockless, hash insertion must be done after -- * starting the timer and setting the CONFIRMED bit. The RCU barriers -- * guarantee that no other CPU can find the conntrack before the above -- * stores are visible. -+ * setting ct->timeout. The RCU barriers guarantee that no other CPU -+ * can find the conntrack before the above stores are visible. - */ - __nf_conntrack_hash_insert(ct, hash, reply_hash); -+ -+ /* IPS_CONFIRMED unset means 'ct not (yet) in hash', conntrack lookups -+ * skip entries that lack this bit. This happens when a CPU is looking -+ * at a stale entry that is being recycled due to SLAB_TYPESAFE_BY_RCU -+ * or when another CPU encounters this entry right after the insertion -+ * but before the set-confirm-bit below. This bit must not be set until -+ * after __nf_conntrack_hash_insert(). -+ */ -+ smp_mb__before_atomic(); -+ set_bit(IPS_CONFIRMED_BIT, &ct->status); -+ - nf_conntrack_double_unlock(hash, reply_hash); - local_bh_enable(); - -diff -purNx .git BPI-Router-Linux-kernel/net/netfilter/nf_conntrack_helper.c BPI-Router-Linux-kernel-6.16.12/net/netfilter/nf_conntrack_helper.c ---- BPI-Router-Linux-kernel/net/netfilter/nf_conntrack_helper.c 2025-10-22 13:53:23.647327057 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/netfilter/nf_conntrack_helper.c 2025-10-22 13:53:56.827167637 -0400 -@@ -368,7 +368,7 @@ int nf_conntrack_helper_register(struct - (cur->tuple.src.l3num == NFPROTO_UNSPEC || - cur->tuple.src.l3num == me->tuple.src.l3num) && - cur->tuple.dst.protonum == me->tuple.dst.protonum) { -- ret = -EEXIST; -+ ret = -EBUSY; - goto out; - } - } -@@ -379,7 +379,7 @@ int nf_conntrack_helper_register(struct - hlist_for_each_entry(cur, &nf_ct_helper_hash[h], hnode) { - if (nf_ct_tuple_src_mask_cmp(&cur->tuple, &me->tuple, - &mask)) { -- ret = -EEXIST; -+ ret = -EBUSY; - goto out; - } - } -diff -purNx .git BPI-Router-Linux-kernel/net/netfilter/nf_conntrack_netlink.c BPI-Router-Linux-kernel-6.16.12/net/netfilter/nf_conntrack_netlink.c ---- BPI-Router-Linux-kernel/net/netfilter/nf_conntrack_netlink.c 2025-10-22 13:53:23.647327057 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/netfilter/nf_conntrack_netlink.c 2025-10-22 13:53:56.827167637 -0400 -@@ -884,8 +884,6 @@ errout: - - static int ctnetlink_done(struct netlink_callback *cb) - { -- if (cb->args[1]) -- nf_ct_put((struct nf_conn *)cb->args[1]); - kfree(cb->data); - return 0; - } -@@ -1208,19 +1206,26 @@ ignore_entry: - return 0; - } - -+static unsigned long ctnetlink_get_id(const struct nf_conn *ct) -+{ -+ unsigned long id = nf_ct_get_id(ct); -+ -+ return id ? id : 1; -+} -+ - static int - ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) - { - unsigned int flags = cb->data ? NLM_F_DUMP_FILTERED : 0; - struct net *net = sock_net(skb->sk); -- struct nf_conn *ct, *last; -+ unsigned long last_id = cb->args[1]; - struct nf_conntrack_tuple_hash *h; - struct hlist_nulls_node *n; - struct nf_conn *nf_ct_evict[8]; -+ struct nf_conn *ct; - int res, i; - spinlock_t *lockp; - -- last = (struct nf_conn *)cb->args[1]; - i = 0; - - local_bh_disable(); -@@ -1257,7 +1262,7 @@ restart: - continue; - - if (cb->args[1]) { -- if (ct != last) -+ if (ctnetlink_get_id(ct) != last_id) - continue; - cb->args[1] = 0; - } -@@ -1270,8 +1275,7 @@ restart: - NFNL_MSG_TYPE(cb->nlh->nlmsg_type), - ct, true, flags); - if (res < 0) { -- nf_conntrack_get(&ct->ct_general); -- cb->args[1] = (unsigned long)ct; -+ cb->args[1] = ctnetlink_get_id(ct); - spin_unlock(lockp); - goto out; - } -@@ -1284,12 +1288,10 @@ restart: - } - out: - local_bh_enable(); -- if (last) { -+ if (last_id) { - /* nf ct hash resize happened, now clear the leftover. */ -- if ((struct nf_conn *)cb->args[1] == last) -+ if (cb->args[1] == last_id) - cb->args[1] = 0; -- -- nf_ct_put(last); - } - - while (i) { -@@ -3169,23 +3171,27 @@ errout: - return 0; - } - #endif --static int ctnetlink_exp_done(struct netlink_callback *cb) -+ -+static unsigned long ctnetlink_exp_id(const struct nf_conntrack_expect *exp) - { -- if (cb->args[1]) -- nf_ct_expect_put((struct nf_conntrack_expect *)cb->args[1]); -- return 0; -+ unsigned long id = (unsigned long)exp; -+ -+ id += nf_ct_get_id(exp->master); -+ id += exp->class; -+ -+ return id ? id : 1; - } - - static int - ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb) - { - struct net *net = sock_net(skb->sk); -- struct nf_conntrack_expect *exp, *last; - struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); - u_int8_t l3proto = nfmsg->nfgen_family; -+ unsigned long last_id = cb->args[1]; -+ struct nf_conntrack_expect *exp; - - rcu_read_lock(); -- last = (struct nf_conntrack_expect *)cb->args[1]; - for (; cb->args[0] < nf_ct_expect_hsize; cb->args[0]++) { - restart: - hlist_for_each_entry_rcu(exp, &nf_ct_expect_hash[cb->args[0]], -@@ -3197,7 +3203,7 @@ restart: - continue; - - if (cb->args[1]) { -- if (exp != last) -+ if (ctnetlink_exp_id(exp) != last_id) - continue; - cb->args[1] = 0; - } -@@ -3206,9 +3212,7 @@ restart: - cb->nlh->nlmsg_seq, - IPCTNL_MSG_EXP_NEW, - exp) < 0) { -- if (!refcount_inc_not_zero(&exp->use)) -- continue; -- cb->args[1] = (unsigned long)exp; -+ cb->args[1] = ctnetlink_exp_id(exp); - goto out; - } - } -@@ -3219,32 +3223,30 @@ restart: - } - out: - rcu_read_unlock(); -- if (last) -- nf_ct_expect_put(last); -- - return skb->len; - } - - static int - ctnetlink_exp_ct_dump_table(struct sk_buff *skb, struct netlink_callback *cb) - { -- struct nf_conntrack_expect *exp, *last; - struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); - struct nf_conn *ct = cb->data; - struct nf_conn_help *help = nfct_help(ct); - u_int8_t l3proto = nfmsg->nfgen_family; -+ unsigned long last_id = cb->args[1]; -+ struct nf_conntrack_expect *exp; - - if (cb->args[0]) - return 0; - - rcu_read_lock(); -- last = (struct nf_conntrack_expect *)cb->args[1]; -+ - restart: - hlist_for_each_entry_rcu(exp, &help->expectations, lnode) { - if (l3proto && exp->tuple.src.l3num != l3proto) - continue; - if (cb->args[1]) { -- if (exp != last) -+ if (ctnetlink_exp_id(exp) != last_id) - continue; - cb->args[1] = 0; - } -@@ -3252,9 +3254,7 @@ restart: - cb->nlh->nlmsg_seq, - IPCTNL_MSG_EXP_NEW, - exp) < 0) { -- if (!refcount_inc_not_zero(&exp->use)) -- continue; -- cb->args[1] = (unsigned long)exp; -+ cb->args[1] = ctnetlink_exp_id(exp); - goto out; - } - } -@@ -3265,9 +3265,6 @@ restart: - cb->args[0] = 1; - out: - rcu_read_unlock(); -- if (last) -- nf_ct_expect_put(last); -- - return skb->len; - } - -@@ -3286,7 +3283,6 @@ static int ctnetlink_dump_exp_ct(struct - struct nf_conntrack_zone zone; - struct netlink_dump_control c = { - .dump = ctnetlink_exp_ct_dump_table, -- .done = ctnetlink_exp_done, - }; - - err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER, -@@ -3336,7 +3332,6 @@ static int ctnetlink_get_expect(struct s - else { - struct netlink_dump_control c = { - .dump = ctnetlink_exp_dump_table, -- .done = ctnetlink_exp_done, - }; - return netlink_dump_start(info->sk, skb, info->nlh, &c); - } -diff -purNx .git BPI-Router-Linux-kernel/net/netfilter/nfnetlink.c BPI-Router-Linux-kernel-6.16.12/net/netfilter/nfnetlink.c ---- BPI-Router-Linux-kernel/net/netfilter/nfnetlink.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/netfilter/nfnetlink.c 2025-10-22 13:53:56.827167637 -0400 -@@ -86,7 +86,6 @@ static const int nfnl_group2type[NFNLGRP - [NFNLGRP_NFTABLES] = NFNL_SUBSYS_NFTABLES, - [NFNLGRP_ACCT_QUOTA] = NFNL_SUBSYS_ACCT, - [NFNLGRP_NFTRACE] = NFNL_SUBSYS_NFTABLES, -- [NFNLGRP_NFT_DEV] = NFNL_SUBSYS_NFTABLES, - }; - - static struct nfnl_net *nfnl_pernet(struct net *net) -diff -purNx .git BPI-Router-Linux-kernel/net/netfilter/nf_tables_api.c BPI-Router-Linux-kernel-6.16.12/net/netfilter/nf_tables_api.c ---- BPI-Router-Linux-kernel/net/netfilter/nf_tables_api.c 2025-10-22 13:53:23.647327057 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/netfilter/nf_tables_api.c 2025-10-22 13:53:56.827167637 -0400 -@@ -1131,11 +1131,14 @@ nf_tables_chain_type_lookup(struct net * - return ERR_PTR(-ENOENT); - } - --static __be16 nft_base_seq(const struct net *net) -+static unsigned int nft_base_seq(const struct net *net) - { -- struct nftables_pernet *nft_net = nft_pernet(net); -+ return READ_ONCE(net->nft.base_seq); -+} - -- return htons(nft_net->base_seq & 0xffff); -+static __be16 nft_base_seq_be16(const struct net *net) -+{ -+ return htons(nft_base_seq(net) & 0xffff); - } - - static const struct nla_policy nft_table_policy[NFTA_TABLE_MAX + 1] = { -@@ -1153,9 +1156,9 @@ static int nf_tables_fill_table_info(str - { - struct nlmsghdr *nlh; - -- event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event); -- nlh = nfnl_msg_put(skb, portid, seq, event, flags, family, -- NFNETLINK_V0, nft_base_seq(net)); -+ nlh = nfnl_msg_put(skb, portid, seq, -+ nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event), -+ flags, family, NFNETLINK_V0, nft_base_seq_be16(net)); - if (!nlh) - goto nla_put_failure; - -@@ -1165,7 +1168,8 @@ static int nf_tables_fill_table_info(str - NFTA_TABLE_PAD)) - goto nla_put_failure; - -- if (event == NFT_MSG_DELTABLE) { -+ if (event == NFT_MSG_DELTABLE || -+ event == NFT_MSG_DESTROYTABLE) { - nlmsg_end(skb, nlh); - return 0; - } -@@ -1247,7 +1251,7 @@ static int nf_tables_dump_tables(struct - - rcu_read_lock(); - nft_net = nft_pernet(net); -- cb->seq = READ_ONCE(nft_net->base_seq); -+ cb->seq = nft_base_seq(net); - - list_for_each_entry_rcu(table, &nft_net->tables, list) { - if (family != NFPROTO_UNSPEC && family != table->family) -@@ -1958,6 +1962,18 @@ nla_put_failure: - return -ENOSPC; - } - -+static bool hook_is_prefix(struct nft_hook *hook) -+{ -+ return strlen(hook->ifname) >= hook->ifnamelen; -+} -+ -+static int nft_nla_put_hook_dev(struct sk_buff *skb, struct nft_hook *hook) -+{ -+ int attr = hook_is_prefix(hook) ? NFTA_DEVICE_PREFIX : NFTA_DEVICE_NAME; -+ -+ return nla_put_string(skb, attr, hook->ifname); -+} -+ - static int nft_dump_basechain_hook(struct sk_buff *skb, - const struct net *net, int family, - const struct nft_base_chain *basechain, -@@ -1989,16 +2005,15 @@ static int nft_dump_basechain_hook(struc - if (!first) - first = hook; - -- if (nla_put(skb, NFTA_DEVICE_NAME, -- hook->ifnamelen, hook->ifname)) -+ if (nft_nla_put_hook_dev(skb, hook)) - goto nla_put_failure; - n++; - } - nla_nest_end(skb, nest_devs); - - if (n == 1 && -- nla_put(skb, NFTA_HOOK_DEV, -- first->ifnamelen, first->ifname)) -+ !hook_is_prefix(first) && -+ nla_put_string(skb, NFTA_HOOK_DEV, first->ifname)) - goto nla_put_failure; - } - nla_nest_end(skb, nest); -@@ -2016,9 +2031,9 @@ static int nf_tables_fill_chain_info(str - { - struct nlmsghdr *nlh; - -- event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event); -- nlh = nfnl_msg_put(skb, portid, seq, event, flags, family, -- NFNETLINK_V0, nft_base_seq(net)); -+ nlh = nfnl_msg_put(skb, portid, seq, -+ nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event), -+ flags, family, NFNETLINK_V0, nft_base_seq_be16(net)); - if (!nlh) - goto nla_put_failure; - -@@ -2028,7 +2043,9 @@ static int nf_tables_fill_chain_info(str - NFTA_CHAIN_PAD)) - goto nla_put_failure; - -- if (event == NFT_MSG_DELCHAIN && !hook_list) { -+ if (!hook_list && -+ (event == NFT_MSG_DELCHAIN || -+ event == NFT_MSG_DESTROYCHAIN)) { - nlmsg_end(skb, nlh); - return 0; - } -@@ -2119,7 +2136,7 @@ static int nf_tables_dump_chains(struct - - rcu_read_lock(); - nft_net = nft_pernet(net); -- cb->seq = READ_ONCE(nft_net->base_seq); -+ cb->seq = nft_base_seq(net); - - list_for_each_entry_rcu(table, &nft_net->tables, list) { - if (family != NFPROTO_UNSPEC && family != table->family) -@@ -2307,7 +2324,8 @@ void nf_tables_chain_destroy(struct nft_ - } - - static struct nft_hook *nft_netdev_hook_alloc(struct net *net, -- const struct nlattr *attr) -+ const struct nlattr *attr, -+ bool prefix) - { - struct nf_hook_ops *ops; - struct net_device *dev; -@@ -2324,7 +2342,8 @@ static struct nft_hook *nft_netdev_hook_ - if (err < 0) - goto err_hook_free; - -- hook->ifnamelen = nla_len(attr); -+ /* include the terminating NUL-char when comparing non-prefixes */ -+ hook->ifnamelen = strlen(hook->ifname) + !prefix; - - /* nf_tables_netdev_event() is called under rtnl_mutex, this is - * indirectly serializing all the other holders of the commit_mutex with -@@ -2371,14 +2390,22 @@ static int nf_tables_parse_netdev_hooks( - struct nft_hook *hook, *next; - const struct nlattr *tmp; - int rem, n = 0, err; -+ bool prefix; - - nla_for_each_nested(tmp, attr, rem) { -- if (nla_type(tmp) != NFTA_DEVICE_NAME) { -+ switch (nla_type(tmp)) { -+ case NFTA_DEVICE_NAME: -+ prefix = false; -+ break; -+ case NFTA_DEVICE_PREFIX: -+ prefix = true; -+ break; -+ default: - err = -EINVAL; - goto err_hook; - } - -- hook = nft_netdev_hook_alloc(net, tmp); -+ hook = nft_netdev_hook_alloc(net, tmp, prefix); - if (IS_ERR(hook)) { - NL_SET_BAD_ATTR(extack, tmp); - err = PTR_ERR(hook); -@@ -2424,7 +2451,7 @@ static int nft_chain_parse_netdev(struct - int err; - - if (tb[NFTA_HOOK_DEV]) { -- hook = nft_netdev_hook_alloc(net, tb[NFTA_HOOK_DEV]); -+ hook = nft_netdev_hook_alloc(net, tb[NFTA_HOOK_DEV], false); - if (IS_ERR(hook)) { - NL_SET_BAD_ATTR(extack, tb[NFTA_HOOK_DEV]); - return PTR_ERR(hook); -@@ -2800,6 +2827,7 @@ static int nf_tables_updchain(struct nft - struct nft_chain *chain = ctx->chain; - struct nft_chain_hook hook = {}; - struct nft_stats __percpu *stats = NULL; -+ struct nftables_pernet *nft_net; - struct nft_hook *h, *next; - struct nf_hook_ops *ops; - struct nft_trans *trans; -@@ -2842,6 +2870,20 @@ static int nf_tables_updchain(struct nft - if (nft_hook_list_find(&basechain->hook_list, h)) { - list_del(&h->list); - nft_netdev_hook_free(h); -+ continue; -+ } -+ -+ nft_net = nft_pernet(ctx->net); -+ list_for_each_entry(trans, &nft_net->commit_list, list) { -+ if (trans->msg_type != NFT_MSG_NEWCHAIN || -+ trans->table != ctx->table || -+ !nft_trans_chain_update(trans)) -+ continue; -+ -+ if (nft_hook_list_find(&nft_trans_chain_hooks(trans), h)) { -+ nft_chain_release_hook(&hook); -+ return -EEXIST; -+ } - } - } - } else { -@@ -3632,7 +3674,7 @@ static int nf_tables_fill_rule_info(stru - u16 type = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event); - - nlh = nfnl_msg_put(skb, portid, seq, type, flags, family, NFNETLINK_V0, -- nft_base_seq(net)); -+ nft_base_seq_be16(net)); - if (!nlh) - goto nla_put_failure; - -@@ -3800,7 +3842,7 @@ static int nf_tables_dump_rules(struct s - - rcu_read_lock(); - nft_net = nft_pernet(net); -- cb->seq = READ_ONCE(nft_net->base_seq); -+ cb->seq = nft_base_seq(net); - - list_for_each_entry_rcu(table, &nft_net->tables, list) { - if (family != NFPROTO_UNSPEC && family != table->family) -@@ -4011,7 +4053,7 @@ static int nf_tables_getrule_reset(struc - buf = kasprintf(GFP_ATOMIC, "%.*s:%u", - nla_len(nla[NFTA_RULE_TABLE]), - (char *)nla_data(nla[NFTA_RULE_TABLE]), -- nft_net->base_seq); -+ nft_base_seq(net)); - audit_log_nfcfg(buf, info->nfmsg->nfgen_family, 1, - AUDIT_NFT_OP_RULE_RESET, GFP_ATOMIC); - kfree(buf); -@@ -4039,7 +4081,7 @@ void nf_tables_rule_destroy(const struct - /* can only be used if rule is no longer visible to dumps */ - static void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule) - { -- lockdep_commit_lock_is_held(ctx->net); -+ WARN_ON_ONCE(!lockdep_commit_lock_is_held(ctx->net)); - - nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_RELEASE); - nf_tables_rule_destroy(ctx, rule); -@@ -4845,9 +4887,10 @@ static int nf_tables_fill_set(struct sk_ - u32 seq = ctx->seq; - int i; - -- event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event); -- nlh = nfnl_msg_put(skb, portid, seq, event, flags, ctx->family, -- NFNETLINK_V0, nft_base_seq(ctx->net)); -+ nlh = nfnl_msg_put(skb, portid, seq, -+ nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event), -+ flags, ctx->family, NFNETLINK_V0, -+ nft_base_seq_be16(ctx->net)); - if (!nlh) - goto nla_put_failure; - -@@ -4859,7 +4902,8 @@ static int nf_tables_fill_set(struct sk_ - NFTA_SET_PAD)) - goto nla_put_failure; - -- if (event == NFT_MSG_DELSET) { -+ if (event == NFT_MSG_DELSET || -+ event == NFT_MSG_DESTROYSET) { - nlmsg_end(skb, nlh); - return 0; - } -@@ -4991,7 +5035,7 @@ static int nf_tables_dump_sets(struct sk - - rcu_read_lock(); - nft_net = nft_pernet(net); -- cb->seq = READ_ONCE(nft_net->base_seq); -+ cb->seq = nft_base_seq(net); - - list_for_each_entry_rcu(table, &nft_net->tables, list) { - if (ctx->family != NFPROTO_UNSPEC && -@@ -5859,7 +5903,7 @@ void nf_tables_deactivate_set(const stru - struct nft_set_binding *binding, - enum nft_trans_phase phase) - { -- lockdep_commit_lock_is_held(ctx->net); -+ WARN_ON_ONCE(!lockdep_commit_lock_is_held(ctx->net)); - - switch (phase) { - case NFT_TRANS_PREPARE_ERROR: -@@ -6168,7 +6212,7 @@ static int nf_tables_dump_set(struct sk_ - - rcu_read_lock(); - nft_net = nft_pernet(net); -- cb->seq = READ_ONCE(nft_net->base_seq); -+ cb->seq = nft_base_seq(net); - - list_for_each_entry_rcu(table, &nft_net->tables, list) { - if (dump_ctx->ctx.family != NFPROTO_UNSPEC && -@@ -6197,7 +6241,7 @@ static int nf_tables_dump_set(struct sk_ - seq = cb->nlh->nlmsg_seq; - - nlh = nfnl_msg_put(skb, portid, seq, event, NLM_F_MULTI, -- table->family, NFNETLINK_V0, nft_base_seq(net)); -+ table->family, NFNETLINK_V0, nft_base_seq_be16(net)); - if (!nlh) - goto nla_put_failure; - -@@ -6290,7 +6334,7 @@ static int nf_tables_fill_setelem_info(s - - event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event); - nlh = nfnl_msg_put(skb, portid, seq, event, flags, ctx->family, -- NFNETLINK_V0, nft_base_seq(ctx->net)); -+ NFNETLINK_V0, nft_base_seq_be16(ctx->net)); - if (!nlh) - goto nla_put_failure; - -@@ -6589,7 +6633,7 @@ static int nf_tables_getsetelem_reset(st - } - nelems++; - } -- audit_log_nft_set_reset(dump_ctx.ctx.table, nft_net->base_seq, nelems); -+ audit_log_nft_set_reset(dump_ctx.ctx.table, nft_base_seq(info->net), nelems); - - out_unlock: - rcu_read_unlock(); -@@ -8338,25 +8382,26 @@ static int nf_tables_fill_obj_info(struc - { - struct nlmsghdr *nlh; - -- event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event); -- nlh = nfnl_msg_put(skb, portid, seq, event, flags, family, -- NFNETLINK_V0, nft_base_seq(net)); -+ nlh = nfnl_msg_put(skb, portid, seq, -+ nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event), -+ flags, family, NFNETLINK_V0, nft_base_seq_be16(net)); - if (!nlh) - goto nla_put_failure; - - if (nla_put_string(skb, NFTA_OBJ_TABLE, table->name) || - nla_put_string(skb, NFTA_OBJ_NAME, obj->key.name) || -+ nla_put_be32(skb, NFTA_OBJ_TYPE, htonl(obj->ops->type->type)) || - nla_put_be64(skb, NFTA_OBJ_HANDLE, cpu_to_be64(obj->handle), - NFTA_OBJ_PAD)) - goto nla_put_failure; - -- if (event == NFT_MSG_DELOBJ) { -+ if (event == NFT_MSG_DELOBJ || -+ event == NFT_MSG_DESTROYOBJ) { - nlmsg_end(skb, nlh); - return 0; - } - -- if (nla_put_be32(skb, NFTA_OBJ_TYPE, htonl(obj->ops->type->type)) || -- nla_put_be32(skb, NFTA_OBJ_USE, htonl(obj->use)) || -+ if (nla_put_be32(skb, NFTA_OBJ_USE, htonl(obj->use)) || - nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset)) - goto nla_put_failure; - -@@ -8404,7 +8449,7 @@ static int nf_tables_dump_obj(struct sk_ - - rcu_read_lock(); - nft_net = nft_pernet(net); -- cb->seq = READ_ONCE(nft_net->base_seq); -+ cb->seq = nft_base_seq(net); - - list_for_each_entry_rcu(table, &nft_net->tables, list) { - if (family != NFPROTO_UNSPEC && family != table->family) -@@ -8438,7 +8483,7 @@ cont: - idx++; - } - if (ctx->reset && entries) -- audit_log_obj_reset(table, nft_net->base_seq, entries); -+ audit_log_obj_reset(table, nft_base_seq(net), entries); - if (rc < 0) - break; - } -@@ -8607,7 +8652,7 @@ static int nf_tables_getobj_reset(struct - buf = kasprintf(GFP_ATOMIC, "%.*s:%u", - nla_len(nla[NFTA_OBJ_TABLE]), - (char *)nla_data(nla[NFTA_OBJ_TABLE]), -- nft_net->base_seq); -+ nft_base_seq(net)); - audit_log_nfcfg(buf, info->nfmsg->nfgen_family, 1, - AUDIT_NFT_OP_OBJ_RESET, GFP_ATOMIC); - kfree(buf); -@@ -8712,9 +8757,8 @@ void nft_obj_notify(struct net *net, con - struct nft_object *obj, u32 portid, u32 seq, int event, - u16 flags, int family, int report, gfp_t gfp) - { -- struct nftables_pernet *nft_net = nft_pernet(net); - char *buf = kasprintf(gfp, "%s:%u", -- table->name, nft_net->base_seq); -+ table->name, nft_base_seq(net)); - - audit_log_nfcfg(buf, - family, -@@ -9053,6 +9097,7 @@ static int nft_flowtable_update(struct n - { - const struct nlattr * const *nla = ctx->nla; - struct nft_flowtable_hook flowtable_hook; -+ struct nftables_pernet *nft_net; - struct nft_hook *hook, *next; - struct nf_hook_ops *ops; - struct nft_trans *trans; -@@ -9069,6 +9114,20 @@ static int nft_flowtable_update(struct n - if (nft_hook_list_find(&flowtable->hook_list, hook)) { - list_del(&hook->list); - nft_netdev_hook_free(hook); -+ continue; -+ } -+ -+ nft_net = nft_pernet(ctx->net); -+ list_for_each_entry(trans, &nft_net->commit_list, list) { -+ if (trans->msg_type != NFT_MSG_NEWFLOWTABLE || -+ trans->table != ctx->table || -+ !nft_trans_flowtable_update(trans)) -+ continue; -+ -+ if (nft_hook_list_find(&nft_trans_flowtable_hooks(trans), hook)) { -+ err = -EEXIST; -+ goto err_flowtable_update_hook; -+ } - } - } - -@@ -9382,9 +9441,9 @@ static int nf_tables_fill_flowtable_info - struct nft_hook *hook; - struct nlmsghdr *nlh; - -- event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event); -- nlh = nfnl_msg_put(skb, portid, seq, event, flags, family, -- NFNETLINK_V0, nft_base_seq(net)); -+ nlh = nfnl_msg_put(skb, portid, seq, -+ nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event), -+ flags, family, NFNETLINK_V0, nft_base_seq_be16(net)); - if (!nlh) - goto nla_put_failure; - -@@ -9394,7 +9453,9 @@ static int nf_tables_fill_flowtable_info - NFTA_FLOWTABLE_PAD)) - goto nla_put_failure; - -- if (event == NFT_MSG_DELFLOWTABLE && !hook_list) { -+ if (!hook_list && -+ (event == NFT_MSG_DELFLOWTABLE || -+ event == NFT_MSG_DESTROYFLOWTABLE)) { - nlmsg_end(skb, nlh); - return 0; - } -@@ -9419,8 +9480,7 @@ static int nf_tables_fill_flowtable_info - - list_for_each_entry_rcu(hook, hook_list, list, - lockdep_commit_lock_is_held(net)) { -- if (nla_put(skb, NFTA_DEVICE_NAME, -- hook->ifnamelen, hook->ifname)) -+ if (nft_nla_put_hook_dev(skb, hook)) - goto nla_put_failure; - } - nla_nest_end(skb, nest_devs); -@@ -9452,7 +9512,7 @@ static int nf_tables_dump_flowtable(stru - - rcu_read_lock(); - nft_net = nft_pernet(net); -- cb->seq = READ_ONCE(nft_net->base_seq); -+ cb->seq = nft_base_seq(net); - - list_for_each_entry_rcu(table, &nft_net->tables, list) { - if (family != NFPROTO_UNSPEC && family != table->family) -@@ -9637,17 +9697,16 @@ static void nf_tables_flowtable_destroy( - static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net, - u32 portid, u32 seq) - { -- struct nftables_pernet *nft_net = nft_pernet(net); - struct nlmsghdr *nlh; - char buf[TASK_COMM_LEN]; - int event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, NFT_MSG_NEWGEN); - - nlh = nfnl_msg_put(skb, portid, seq, event, 0, AF_UNSPEC, -- NFNETLINK_V0, nft_base_seq(net)); -+ NFNETLINK_V0, nft_base_seq_be16(net)); - if (!nlh) - goto nla_put_failure; - -- if (nla_put_be32(skb, NFTA_GEN_ID, htonl(nft_net->base_seq)) || -+ if (nla_put_be32(skb, NFTA_GEN_ID, htonl(nft_base_seq(net))) || - nla_put_be32(skb, NFTA_GEN_PROC_PID, htonl(task_pid_nr(current))) || - nla_put_string(skb, NFTA_GEN_PROC_NAME, get_task_comm(buf, current))) - goto nla_put_failure; -@@ -9686,64 +9745,6 @@ struct nf_hook_ops *nft_hook_find_ops_rc - } - EXPORT_SYMBOL_GPL(nft_hook_find_ops_rcu); - --static void --nf_tables_device_notify(const struct nft_table *table, int attr, -- const char *name, const struct nft_hook *hook, -- const struct net_device *dev, int event) --{ -- struct net *net = dev_net(dev); -- struct nlmsghdr *nlh; -- struct sk_buff *skb; -- u16 flags = 0; -- -- if (!nfnetlink_has_listeners(net, NFNLGRP_NFT_DEV)) -- return; -- -- skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); -- if (!skb) -- goto err; -- -- event = event == NETDEV_REGISTER ? NFT_MSG_NEWDEV : NFT_MSG_DELDEV; -- event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event); -- nlh = nfnl_msg_put(skb, 0, 0, event, flags, table->family, -- NFNETLINK_V0, nft_base_seq(net)); -- if (!nlh) -- goto err; -- -- if (nla_put_string(skb, NFTA_DEVICE_TABLE, table->name) || -- nla_put_string(skb, attr, name) || -- nla_put(skb, NFTA_DEVICE_SPEC, hook->ifnamelen, hook->ifname) || -- nla_put_string(skb, NFTA_DEVICE_NAME, dev->name)) -- goto err; -- -- nlmsg_end(skb, nlh); -- nfnetlink_send(skb, net, 0, NFNLGRP_NFT_DEV, -- nlmsg_report(nlh), GFP_KERNEL); -- return; --err: -- if (skb) -- kfree_skb(skb); -- nfnetlink_set_err(net, 0, NFNLGRP_NFT_DEV, -ENOBUFS); --} -- --void --nf_tables_chain_device_notify(const struct nft_chain *chain, -- const struct nft_hook *hook, -- const struct net_device *dev, int event) --{ -- nf_tables_device_notify(chain->table, NFTA_DEVICE_CHAIN, -- chain->name, hook, dev, event); --} -- --static void --nf_tables_flowtable_device_notify(const struct nft_flowtable *ft, -- const struct nft_hook *hook, -- const struct net_device *dev, int event) --{ -- nf_tables_device_notify(ft->table, NFTA_DEVICE_FLOWTABLE, -- ft->name, hook, dev, event); --} -- - static int nft_flowtable_event(unsigned long event, struct net_device *dev, - struct nft_flowtable *flowtable, bool changename) - { -@@ -9791,7 +9792,6 @@ static int nft_flowtable_event(unsigned - list_add_tail_rcu(&ops->list, &hook->ops_list); - break; - } -- nf_tables_flowtable_device_notify(flowtable, hook, dev, event); - break; - } - return 0; -@@ -10967,11 +10967,12 @@ static int nf_tables_commit(struct net * - * Bump generation counter, invalidate any dump in progress. - * Cannot fail after this point. - */ -- base_seq = READ_ONCE(nft_net->base_seq); -+ base_seq = nft_base_seq(net); - while (++base_seq == 0) - ; - -- WRITE_ONCE(nft_net->base_seq, base_seq); -+ /* pairs with smp_load_acquire in nft_lookup_eval */ -+ smp_store_release(&net->nft.base_seq, base_seq); - - gc_seq = nft_gc_seq_begin(nft_net); - -@@ -11180,7 +11181,7 @@ static int nf_tables_commit(struct net * - - nft_commit_notify(net, NETLINK_CB(skb).portid); - nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN); -- nf_tables_commit_audit_log(&adl, nft_net->base_seq); -+ nf_tables_commit_audit_log(&adl, nft_base_seq(net)); - - nft_gc_seq_end(nft_net, gc_seq); - nft_net->validate_state = NFT_VALIDATE_SKIP; -@@ -11505,7 +11506,7 @@ static bool nf_tables_valid_genid(struct - mutex_lock(&nft_net->commit_mutex); - nft_net->tstamp = get_jiffies_64(); - -- genid_ok = genid == 0 || nft_net->base_seq == genid; -+ genid_ok = genid == 0 || nft_base_seq(net) == genid; - if (!genid_ok) - mutex_unlock(&nft_net->commit_mutex); - -@@ -12142,7 +12143,7 @@ static int __net_init nf_tables_init_net - INIT_LIST_HEAD(&nft_net->module_list); - INIT_LIST_HEAD(&nft_net->notify_list); - mutex_init(&nft_net->commit_mutex); -- nft_net->base_seq = 1; -+ net->nft.base_seq = 1; - nft_net->gc_seq = 0; - nft_net->validate_state = NFT_VALIDATE_SKIP; - INIT_WORK(&nft_net->destroy_work, nf_tables_trans_destroy_work); -diff -purNx .git BPI-Router-Linux-kernel/net/netfilter/nf_tables_trace.c BPI-Router-Linux-kernel-6.16.12/net/netfilter/nf_tables_trace.c ---- BPI-Router-Linux-kernel/net/netfilter/nf_tables_trace.c 2025-10-22 13:53:23.647327057 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/netfilter/nf_tables_trace.c 2025-10-22 13:53:56.827167637 -0400 -@@ -127,6 +127,9 @@ static int nf_trace_fill_ct_info(struct - if (nla_put_be32(nlskb, NFTA_TRACE_CT_ID, (__force __be32)id)) - return -1; - -+ /* Kernel implementation detail, withhold this from userspace for now */ -+ status &= ~IPS_NAT_CLASH; -+ - if (status && nla_put_be32(nlskb, NFTA_TRACE_CT_STATUS, htonl(status))) - return -1; - } -diff -purNx .git BPI-Router-Linux-kernel/net/netfilter/nft_chain_filter.c BPI-Router-Linux-kernel-6.16.12/net/netfilter/nft_chain_filter.c ---- BPI-Router-Linux-kernel/net/netfilter/nft_chain_filter.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/netfilter/nft_chain_filter.c 2025-10-22 13:53:56.827167637 -0400 -@@ -363,8 +363,6 @@ static int nft_netdev_event(unsigned lon - list_add_tail_rcu(&ops->list, &hook->ops_list); - break; - } -- nf_tables_chain_device_notify(&basechain->chain, -- hook, dev, event); - break; - } - return 0; -diff -purNx .git BPI-Router-Linux-kernel/net/netfilter/nft_dynset.c BPI-Router-Linux-kernel-6.16.12/net/netfilter/nft_dynset.c ---- BPI-Router-Linux-kernel/net/netfilter/nft_dynset.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/netfilter/nft_dynset.c 2025-10-22 13:53:56.827167637 -0400 -@@ -91,8 +91,9 @@ void nft_dynset_eval(const struct nft_ex - return; - } - -- if (set->ops->update(set, ®s->data[priv->sreg_key], nft_dynset_new, -- expr, regs, &ext)) { -+ ext = set->ops->update(set, ®s->data[priv->sreg_key], nft_dynset_new, -+ expr, regs); -+ if (ext) { - if (priv->op == NFT_DYNSET_OP_UPDATE && - nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT) && - READ_ONCE(nft_set_ext_timeout(ext)->timeout) != 0) { -diff -purNx .git BPI-Router-Linux-kernel/net/netfilter/nft_lookup.c BPI-Router-Linux-kernel-6.16.12/net/netfilter/nft_lookup.c ---- BPI-Router-Linux-kernel/net/netfilter/nft_lookup.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/netfilter/nft_lookup.c 2025-10-22 13:53:56.827167637 -0400 -@@ -24,36 +24,73 @@ struct nft_lookup { - struct nft_set_binding binding; - }; - --#ifdef CONFIG_MITIGATION_RETPOLINE --bool nft_set_do_lookup(const struct net *net, const struct nft_set *set, -- const u32 *key, const struct nft_set_ext **ext) -+static const struct nft_set_ext * -+__nft_set_do_lookup(const struct net *net, const struct nft_set *set, -+ const u32 *key) - { -+#ifdef CONFIG_MITIGATION_RETPOLINE - if (set->ops == &nft_set_hash_fast_type.ops) -- return nft_hash_lookup_fast(net, set, key, ext); -+ return nft_hash_lookup_fast(net, set, key); - if (set->ops == &nft_set_hash_type.ops) -- return nft_hash_lookup(net, set, key, ext); -+ return nft_hash_lookup(net, set, key); - - if (set->ops == &nft_set_rhash_type.ops) -- return nft_rhash_lookup(net, set, key, ext); -+ return nft_rhash_lookup(net, set, key); - - if (set->ops == &nft_set_bitmap_type.ops) -- return nft_bitmap_lookup(net, set, key, ext); -+ return nft_bitmap_lookup(net, set, key); - - if (set->ops == &nft_set_pipapo_type.ops) -- return nft_pipapo_lookup(net, set, key, ext); -+ return nft_pipapo_lookup(net, set, key); - #if defined(CONFIG_X86_64) && !defined(CONFIG_UML) - if (set->ops == &nft_set_pipapo_avx2_type.ops) -- return nft_pipapo_avx2_lookup(net, set, key, ext); -+ return nft_pipapo_avx2_lookup(net, set, key); - #endif - - if (set->ops == &nft_set_rbtree_type.ops) -- return nft_rbtree_lookup(net, set, key, ext); -+ return nft_rbtree_lookup(net, set, key); - - WARN_ON_ONCE(1); -- return set->ops->lookup(net, set, key, ext); -+#endif -+ return set->ops->lookup(net, set, key); -+} -+ -+static unsigned int nft_base_seq(const struct net *net) -+{ -+ /* pairs with smp_store_release() in nf_tables_commit() */ -+ return smp_load_acquire(&net->nft.base_seq); -+} -+ -+static bool nft_lookup_should_retry(const struct net *net, unsigned int seq) -+{ -+ return unlikely(seq != nft_base_seq(net)); -+} -+ -+const struct nft_set_ext * -+nft_set_do_lookup(const struct net *net, const struct nft_set *set, -+ const u32 *key) -+{ -+ const struct nft_set_ext *ext; -+ unsigned int base_seq; -+ -+ do { -+ base_seq = nft_base_seq(net); -+ -+ ext = __nft_set_do_lookup(net, set, key); -+ if (ext) -+ break; -+ /* No match? There is a small chance that lookup was -+ * performed in the old generation, but nf_tables_commit() -+ * already unlinked a (matching) element. -+ * -+ * We need to repeat the lookup to make sure that we didn't -+ * miss a matching element in the new generation. -+ */ -+ } while (nft_lookup_should_retry(net, base_seq)); -+ -+ return ext; - } - EXPORT_SYMBOL_GPL(nft_set_do_lookup); --#endif - - void nft_lookup_eval(const struct nft_expr *expr, - struct nft_regs *regs, -@@ -61,12 +98,12 @@ void nft_lookup_eval(const struct nft_ex - { - const struct nft_lookup *priv = nft_expr_priv(expr); - const struct nft_set *set = priv->set; -- const struct nft_set_ext *ext = NULL; - const struct net *net = nft_net(pkt); -+ const struct nft_set_ext *ext; - bool found; - -- found = nft_set_do_lookup(net, set, ®s->data[priv->sreg], &ext) ^ -- priv->invert; -+ ext = nft_set_do_lookup(net, set, ®s->data[priv->sreg]); -+ found = !!ext ^ priv->invert; - if (!found) { - ext = nft_set_catchall_lookup(net, set); - if (!ext) { -diff -purNx .git BPI-Router-Linux-kernel/net/netfilter/nft_objref.c BPI-Router-Linux-kernel-6.16.12/net/netfilter/nft_objref.c ---- BPI-Router-Linux-kernel/net/netfilter/nft_objref.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/netfilter/nft_objref.c 2025-10-22 13:53:56.827167637 -0400 -@@ -111,10 +111,9 @@ void nft_objref_map_eval(const struct nf - struct net *net = nft_net(pkt); - const struct nft_set_ext *ext; - struct nft_object *obj; -- bool found; - -- found = nft_set_do_lookup(net, set, ®s->data[priv->sreg], &ext); -- if (!found) { -+ ext = nft_set_do_lookup(net, set, ®s->data[priv->sreg]); -+ if (!ext) { - ext = nft_set_catchall_lookup(net, set); - if (!ext) { - regs->verdict.code = NFT_BREAK; -diff -purNx .git BPI-Router-Linux-kernel/net/netfilter/nft_set_bitmap.c BPI-Router-Linux-kernel-6.16.12/net/netfilter/nft_set_bitmap.c ---- BPI-Router-Linux-kernel/net/netfilter/nft_set_bitmap.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/netfilter/nft_set_bitmap.c 2025-10-22 13:53:56.827167637 -0400 -@@ -75,16 +75,21 @@ nft_bitmap_active(const u8 *bitmap, u32 - } - - INDIRECT_CALLABLE_SCOPE --bool nft_bitmap_lookup(const struct net *net, const struct nft_set *set, -- const u32 *key, const struct nft_set_ext **ext) -+const struct nft_set_ext * -+nft_bitmap_lookup(const struct net *net, const struct nft_set *set, -+ const u32 *key) - { - const struct nft_bitmap *priv = nft_set_priv(set); -+ static const struct nft_set_ext found; - u8 genmask = nft_genmask_cur(net); - u32 idx, off; - - nft_bitmap_location(set, key, &idx, &off); - -- return nft_bitmap_active(priv->bitmap, idx, off, genmask); -+ if (nft_bitmap_active(priv->bitmap, idx, off, genmask)) -+ return &found; -+ -+ return NULL; - } - - static struct nft_bitmap_elem * -@@ -221,7 +226,8 @@ static void nft_bitmap_walk(const struct - const struct nft_bitmap *priv = nft_set_priv(set); - struct nft_bitmap_elem *be; - -- list_for_each_entry_rcu(be, &priv->list, head) { -+ list_for_each_entry_rcu(be, &priv->list, head, -+ lockdep_is_held(&nft_pernet(ctx->net)->commit_mutex)) { - if (iter->count < iter->skip) - goto cont; - -diff -purNx .git BPI-Router-Linux-kernel/net/netfilter/nft_set_hash.c BPI-Router-Linux-kernel-6.16.12/net/netfilter/nft_set_hash.c ---- BPI-Router-Linux-kernel/net/netfilter/nft_set_hash.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/netfilter/nft_set_hash.c 2025-10-22 13:53:56.827167637 -0400 -@@ -81,8 +81,9 @@ static const struct rhashtable_params nf - }; - - INDIRECT_CALLABLE_SCOPE --bool nft_rhash_lookup(const struct net *net, const struct nft_set *set, -- const u32 *key, const struct nft_set_ext **ext) -+const struct nft_set_ext * -+nft_rhash_lookup(const struct net *net, const struct nft_set *set, -+ const u32 *key) - { - struct nft_rhash *priv = nft_set_priv(set); - const struct nft_rhash_elem *he; -@@ -95,9 +96,9 @@ bool nft_rhash_lookup(const struct net * - - he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params); - if (he != NULL) -- *ext = &he->ext; -+ return &he->ext; - -- return !!he; -+ return NULL; - } - - static struct nft_elem_priv * -@@ -120,14 +121,11 @@ nft_rhash_get(const struct net *net, con - return ERR_PTR(-ENOENT); - } - --static bool nft_rhash_update(struct nft_set *set, const u32 *key, -- struct nft_elem_priv * -- (*new)(struct nft_set *, -- const struct nft_expr *, -- struct nft_regs *regs), -- const struct nft_expr *expr, -- struct nft_regs *regs, -- const struct nft_set_ext **ext) -+static const struct nft_set_ext * -+nft_rhash_update(struct nft_set *set, const u32 *key, -+ struct nft_elem_priv *(*new)(struct nft_set *, const struct nft_expr *, -+ struct nft_regs *regs), -+ const struct nft_expr *expr, struct nft_regs *regs) - { - struct nft_rhash *priv = nft_set_priv(set); - struct nft_rhash_elem *he, *prev; -@@ -161,14 +159,13 @@ static bool nft_rhash_update(struct nft_ - } - - out: -- *ext = &he->ext; -- return true; -+ return &he->ext; - - err2: - nft_set_elem_destroy(set, &he->priv, true); - atomic_dec(&set->nelems); - err1: -- return false; -+ return NULL; - } - - static int nft_rhash_insert(const struct net *net, const struct nft_set *set, -@@ -507,8 +504,9 @@ struct nft_hash_elem { - }; - - INDIRECT_CALLABLE_SCOPE --bool nft_hash_lookup(const struct net *net, const struct nft_set *set, -- const u32 *key, const struct nft_set_ext **ext) -+const struct nft_set_ext * -+nft_hash_lookup(const struct net *net, const struct nft_set *set, -+ const u32 *key) - { - struct nft_hash *priv = nft_set_priv(set); - u8 genmask = nft_genmask_cur(net); -@@ -519,12 +517,10 @@ bool nft_hash_lookup(const struct net *n - hash = reciprocal_scale(hash, priv->buckets); - hlist_for_each_entry_rcu(he, &priv->table[hash], node) { - if (!memcmp(nft_set_ext_key(&he->ext), key, set->klen) && -- nft_set_elem_active(&he->ext, genmask)) { -- *ext = &he->ext; -- return true; -- } -+ nft_set_elem_active(&he->ext, genmask)) -+ return &he->ext; - } -- return false; -+ return NULL; - } - - static struct nft_elem_priv * -@@ -547,9 +543,9 @@ nft_hash_get(const struct net *net, cons - } - - INDIRECT_CALLABLE_SCOPE --bool nft_hash_lookup_fast(const struct net *net, -- const struct nft_set *set, -- const u32 *key, const struct nft_set_ext **ext) -+const struct nft_set_ext * -+nft_hash_lookup_fast(const struct net *net, const struct nft_set *set, -+ const u32 *key) - { - struct nft_hash *priv = nft_set_priv(set); - u8 genmask = nft_genmask_cur(net); -@@ -562,12 +558,10 @@ bool nft_hash_lookup_fast(const struct n - hlist_for_each_entry_rcu(he, &priv->table[hash], node) { - k2 = *(u32 *)nft_set_ext_key(&he->ext)->data; - if (k1 == k2 && -- nft_set_elem_active(&he->ext, genmask)) { -- *ext = &he->ext; -- return true; -- } -+ nft_set_elem_active(&he->ext, genmask)) -+ return &he->ext; - } -- return false; -+ return NULL; - } - - static u32 nft_jhash(const struct nft_set *set, const struct nft_hash *priv, -diff -purNx .git BPI-Router-Linux-kernel/net/netfilter/nft_set_pipapo_avx2.c BPI-Router-Linux-kernel-6.16.12/net/netfilter/nft_set_pipapo_avx2.c ---- BPI-Router-Linux-kernel/net/netfilter/nft_set_pipapo_avx2.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/netfilter/nft_set_pipapo_avx2.c 2025-10-22 13:53:56.827167637 -0400 -@@ -1146,26 +1146,27 @@ static inline void pipapo_resmap_init_av - * - * Return: true on match, false otherwise. - */ --bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set, -- const u32 *key, const struct nft_set_ext **ext) -+const struct nft_set_ext * -+nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set, -+ const u32 *key) - { - struct nft_pipapo *priv = nft_set_priv(set); -+ const struct nft_set_ext *ext = NULL; - struct nft_pipapo_scratch *scratch; -- u8 genmask = nft_genmask_cur(net); - const struct nft_pipapo_match *m; - const struct nft_pipapo_field *f; - const u8 *rp = (const u8 *)key; - unsigned long *res, *fill; - bool map_index; -- int i, ret = 0; -+ int i; - - local_bh_disable(); - - if (unlikely(!irq_fpu_usable())) { -- bool fallback_res = nft_pipapo_lookup(net, set, key, ext); -+ ext = nft_pipapo_lookup(net, set, key); - - local_bh_enable(); -- return fallback_res; -+ return ext; - } - - m = rcu_dereference(priv->match); -@@ -1182,7 +1183,7 @@ bool nft_pipapo_avx2_lookup(const struct - if (unlikely(!scratch)) { - kernel_fpu_end(); - local_bh_enable(); -- return false; -+ return NULL; - } - - map_index = scratch->map_index; -@@ -1197,6 +1198,7 @@ bool nft_pipapo_avx2_lookup(const struct - next_match: - nft_pipapo_for_each_field(f, i, m) { - bool last = i == m->field_count - 1, first = !i; -+ int ret = 0; - - #define NFT_SET_PIPAPO_AVX2_LOOKUP(b, n) \ - (ret = nft_pipapo_avx2_lookup_##b##b_##n(res, fill, f, \ -@@ -1244,13 +1246,12 @@ next_match: - goto out; - - if (last) { -- *ext = &f->mt[ret].e->ext; -- if (unlikely(nft_set_elem_expired(*ext) || -- !nft_set_elem_active(*ext, genmask))) { -- ret = 0; -+ const struct nft_set_ext *e = &f->mt[ret].e->ext; -+ -+ if (unlikely(nft_set_elem_expired(e))) - goto next_match; -- } - -+ ext = e; - goto out; - } - -@@ -1264,5 +1265,5 @@ out: - kernel_fpu_end(); - local_bh_enable(); - -- return ret >= 0; -+ return ext; - } -diff -purNx .git BPI-Router-Linux-kernel/net/netfilter/nft_set_pipapo.c BPI-Router-Linux-kernel-6.16.12/net/netfilter/nft_set_pipapo.c ---- BPI-Router-Linux-kernel/net/netfilter/nft_set_pipapo.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/netfilter/nft_set_pipapo.c 2025-10-22 13:53:56.827167637 -0400 -@@ -397,37 +397,38 @@ int pipapo_refill(unsigned long *map, un - } - - /** -- * nft_pipapo_lookup() - Lookup function -- * @net: Network namespace -- * @set: nftables API set representation -- * @key: nftables API element representation containing key data -- * @ext: nftables API extension pointer, filled with matching reference -+ * pipapo_get() - Get matching element reference given key data -+ * @m: storage containing the set elements -+ * @data: Key data to be matched against existing elements -+ * @genmask: If set, check that element is active in given genmask -+ * @tstamp: timestamp to check for expired elements - * - * For more details, see DOC: Theory of Operation. - * -- * Return: true on match, false otherwise. -+ * This is the main lookup function. It matches key data against either -+ * the working match set or the uncommitted copy, depending on what the -+ * caller passed to us. -+ * nft_pipapo_get (lookup from userspace/control plane) and nft_pipapo_lookup -+ * (datapath lookup) pass the active copy. -+ * The insertion path will pass the uncommitted working copy. -+ * -+ * Return: pointer to &struct nft_pipapo_elem on match, NULL otherwise. - */ --bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set, -- const u32 *key, const struct nft_set_ext **ext) -+static struct nft_pipapo_elem *pipapo_get(const struct nft_pipapo_match *m, -+ const u8 *data, u8 genmask, -+ u64 tstamp) - { -- struct nft_pipapo *priv = nft_set_priv(set); - struct nft_pipapo_scratch *scratch; - unsigned long *res_map, *fill_map; -- u8 genmask = nft_genmask_cur(net); -- const struct nft_pipapo_match *m; - const struct nft_pipapo_field *f; -- const u8 *rp = (const u8 *)key; - bool map_index; - int i; - - local_bh_disable(); - -- m = rcu_dereference(priv->match); -- -- if (unlikely(!m || !*raw_cpu_ptr(m->scratch))) -- goto out; -- - scratch = *raw_cpu_ptr(m->scratch); -+ if (unlikely(!scratch)) -+ goto out; - - map_index = scratch->map_index; - -@@ -444,12 +445,12 @@ bool nft_pipapo_lookup(const struct net - * packet bytes value, then AND bucket value - */ - if (likely(f->bb == 8)) -- pipapo_and_field_buckets_8bit(f, res_map, rp); -+ pipapo_and_field_buckets_8bit(f, res_map, data); - else -- pipapo_and_field_buckets_4bit(f, res_map, rp); -+ pipapo_and_field_buckets_4bit(f, res_map, data); - NFT_PIPAPO_GROUP_BITS_ARE_8_OR_4; - -- rp += f->groups / NFT_PIPAPO_GROUPS_PER_BYTE(f); -+ data += f->groups / NFT_PIPAPO_GROUPS_PER_BYTE(f); - - /* Now populate the bitmap for the next field, unless this is - * the last field, in which case return the matched 'ext' -@@ -465,13 +466,15 @@ next_match: - scratch->map_index = map_index; - local_bh_enable(); - -- return false; -+ return NULL; - } - - if (last) { -- *ext = &f->mt[b].e->ext; -- if (unlikely(nft_set_elem_expired(*ext) || -- !nft_set_elem_active(*ext, genmask))) -+ struct nft_pipapo_elem *e; -+ -+ e = f->mt[b].e; -+ if (unlikely(__nft_set_elem_expired(&e->ext, tstamp) || -+ !nft_set_elem_active(&e->ext, genmask))) - goto next_match; - - /* Last field: we're just returning the key without -@@ -481,8 +484,7 @@ next_match: - */ - scratch->map_index = map_index; - local_bh_enable(); -- -- return true; -+ return e; - } - - /* Swap bitmap indices: res_map is the initial bitmap for the -@@ -492,112 +494,54 @@ next_match: - map_index = !map_index; - swap(res_map, fill_map); - -- rp += NFT_PIPAPO_GROUPS_PADDING(f); -+ data += NFT_PIPAPO_GROUPS_PADDING(f); - } - - out: - local_bh_enable(); -- return false; -+ return NULL; - } - - /** -- * pipapo_get() - Get matching element reference given key data -+ * nft_pipapo_lookup() - Dataplane fronted for main lookup function - * @net: Network namespace - * @set: nftables API set representation -- * @m: storage containing active/existing elements -- * @data: Key data to be matched against existing elements -- * @genmask: If set, check that element is active in given genmask -- * @tstamp: timestamp to check for expired elements -- * @gfp: the type of memory to allocate (see kmalloc). -- * -- * This is essentially the same as the lookup function, except that it matches -- * key data against the uncommitted copy and doesn't use preallocated maps for -- * bitmap results. -+ * @key: pointer to nft registers containing key data - * -- * Return: pointer to &struct nft_pipapo_elem on match, error pointer otherwise. -- */ --static struct nft_pipapo_elem *pipapo_get(const struct net *net, -- const struct nft_set *set, -- const struct nft_pipapo_match *m, -- const u8 *data, u8 genmask, -- u64 tstamp, gfp_t gfp) -+ * This function is called from the data path. It will search for -+ * an element matching the given key in the current active copy. -+ * Unlike other set types, this uses NFT_GENMASK_ANY instead of -+ * nft_genmask_cur(). -+ * -+ * This is because new (future) elements are not reachable from -+ * priv->match, they get added to priv->clone instead. -+ * When the commit phase flips the generation bitmask, the -+ * 'now old' entries are skipped but without the 'now current' -+ * elements becoming visible. Using nft_genmask_cur() thus creates -+ * inconsistent state: matching old entries get skipped but thew -+ * newly matching entries are unreachable. -+ * -+ * GENMASK will still find the 'now old' entries which ensures consistent -+ * priv->match view. -+ * -+ * nft_pipapo_commit swaps ->clone and ->match shortly after the -+ * genbit flip. As ->clone doesn't contain the old entries in the first -+ * place, lookup will only find the now-current ones. -+ * -+ * Return: ntables API extension pointer or NULL if no match. -+ */ -+const struct nft_set_ext * -+nft_pipapo_lookup(const struct net *net, const struct nft_set *set, -+ const u32 *key) - { -- struct nft_pipapo_elem *ret = ERR_PTR(-ENOENT); -- unsigned long *res_map, *fill_map = NULL; -- const struct nft_pipapo_field *f; -- int i; -- -- if (m->bsize_max == 0) -- return ret; -- -- res_map = kmalloc_array(m->bsize_max, sizeof(*res_map), gfp); -- if (!res_map) { -- ret = ERR_PTR(-ENOMEM); -- goto out; -- } -- -- fill_map = kcalloc(m->bsize_max, sizeof(*res_map), gfp); -- if (!fill_map) { -- ret = ERR_PTR(-ENOMEM); -- goto out; -- } -- -- pipapo_resmap_init(m, res_map); -- -- nft_pipapo_for_each_field(f, i, m) { -- bool last = i == m->field_count - 1; -- int b; -- -- /* For each bit group: select lookup table bucket depending on -- * packet bytes value, then AND bucket value -- */ -- if (f->bb == 8) -- pipapo_and_field_buckets_8bit(f, res_map, data); -- else if (f->bb == 4) -- pipapo_and_field_buckets_4bit(f, res_map, data); -- else -- BUG(); -- -- data += f->groups / NFT_PIPAPO_GROUPS_PER_BYTE(f); -- -- /* Now populate the bitmap for the next field, unless this is -- * the last field, in which case return the matched 'ext' -- * pointer if any. -- * -- * Now res_map contains the matching bitmap, and fill_map is the -- * bitmap for the next field. -- */ --next_match: -- b = pipapo_refill(res_map, f->bsize, f->rules, fill_map, f->mt, -- last); -- if (b < 0) -- goto out; -- -- if (last) { -- if (__nft_set_elem_expired(&f->mt[b].e->ext, tstamp)) -- goto next_match; -- if ((genmask && -- !nft_set_elem_active(&f->mt[b].e->ext, genmask))) -- goto next_match; -- -- ret = f->mt[b].e; -- goto out; -- } -- -- data += NFT_PIPAPO_GROUPS_PADDING(f); -+ struct nft_pipapo *priv = nft_set_priv(set); -+ const struct nft_pipapo_match *m; -+ const struct nft_pipapo_elem *e; - -- /* Swap bitmap indices: fill_map will be the initial bitmap for -- * the next field (i.e. the new res_map), and res_map is -- * guaranteed to be all-zeroes at this point, ready to be filled -- * according to the next mapping table. -- */ -- swap(res_map, fill_map); -- } -+ m = rcu_dereference(priv->match); -+ e = pipapo_get(m, (const u8 *)key, NFT_GENMASK_ANY, get_jiffies_64()); - --out: -- kfree(fill_map); -- kfree(res_map); -- return ret; -+ return e ? &e->ext : NULL; - } - - /** -@@ -606,6 +550,11 @@ out: - * @set: nftables API set representation - * @elem: nftables API element representation containing key data - * @flags: Unused -+ * -+ * This function is called from the control plane path under -+ * RCU read lock. -+ * -+ * Return: set element private pointer or ERR_PTR(-ENOENT). - */ - static struct nft_elem_priv * - nft_pipapo_get(const struct net *net, const struct nft_set *set, -@@ -615,11 +564,10 @@ nft_pipapo_get(const struct net *net, co - struct nft_pipapo_match *m = rcu_dereference(priv->match); - struct nft_pipapo_elem *e; - -- e = pipapo_get(net, set, m, (const u8 *)elem->key.val.data, -- nft_genmask_cur(net), get_jiffies_64(), -- GFP_ATOMIC); -- if (IS_ERR(e)) -- return ERR_CAST(e); -+ e = pipapo_get(m, (const u8 *)elem->key.val.data, -+ nft_genmask_cur(net), get_jiffies_64()); -+ if (!e) -+ return ERR_PTR(-ENOENT); - - return &e->priv; - } -@@ -1219,7 +1167,7 @@ static void pipapo_free_scratch(const st - - mem = s; - mem -= s->align_off; -- kfree(mem); -+ kvfree(mem); - } - - /** -@@ -1240,10 +1188,9 @@ static int pipapo_realloc_scratch(struct - void *scratch_aligned; - u32 align_off; - #endif -- scratch = kzalloc_node(struct_size(scratch, map, -- bsize_max * 2) + -- NFT_PIPAPO_ALIGN_HEADROOM, -- GFP_KERNEL_ACCOUNT, cpu_to_node(i)); -+ scratch = kvzalloc_node(struct_size(scratch, map, bsize_max * 2) + -+ NFT_PIPAPO_ALIGN_HEADROOM, -+ GFP_KERNEL_ACCOUNT, cpu_to_node(i)); - if (!scratch) { - /* On failure, there's no need to undo previous - * allocations: this means that some scratch maps have -@@ -1345,8 +1292,8 @@ static int nft_pipapo_insert(const struc - else - end = start; - -- dup = pipapo_get(net, set, m, start, genmask, tstamp, GFP_KERNEL); -- if (!IS_ERR(dup)) { -+ dup = pipapo_get(m, start, genmask, tstamp); -+ if (dup) { - /* Check if we already have the same exact entry */ - const struct nft_data *dup_key, *dup_end; - -@@ -1365,15 +1312,9 @@ static int nft_pipapo_insert(const struc - return -ENOTEMPTY; - } - -- if (PTR_ERR(dup) == -ENOENT) { -- /* Look for partially overlapping entries */ -- dup = pipapo_get(net, set, m, end, nft_genmask_next(net), tstamp, -- GFP_KERNEL); -- } -- -- if (PTR_ERR(dup) != -ENOENT) { -- if (IS_ERR(dup)) -- return PTR_ERR(dup); -+ /* Look for partially overlapping entries */ -+ dup = pipapo_get(m, end, nft_genmask_next(net), tstamp); -+ if (dup) { - *elem_priv = &dup->priv; - return -ENOTEMPTY; - } -@@ -1914,9 +1855,9 @@ nft_pipapo_deactivate(const struct net * - if (!m) - return NULL; - -- e = pipapo_get(net, set, m, (const u8 *)elem->key.val.data, -- nft_genmask_next(net), nft_net_tstamp(net), GFP_KERNEL); -- if (IS_ERR(e)) -+ e = pipapo_get(m, (const u8 *)elem->key.val.data, -+ nft_genmask_next(net), nft_net_tstamp(net)); -+ if (!e) - return NULL; - - nft_set_elem_change_active(net, set, &e->ext); -diff -purNx .git BPI-Router-Linux-kernel/net/netfilter/nft_set_rbtree.c BPI-Router-Linux-kernel-6.16.12/net/netfilter/nft_set_rbtree.c ---- BPI-Router-Linux-kernel/net/netfilter/nft_set_rbtree.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/netfilter/nft_set_rbtree.c 2025-10-22 13:53:56.827167637 -0400 -@@ -52,9 +52,9 @@ static bool nft_rbtree_elem_expired(cons - return nft_set_elem_expired(&rbe->ext); - } - --static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set, -- const u32 *key, const struct nft_set_ext **ext, -- unsigned int seq) -+static const struct nft_set_ext * -+__nft_rbtree_lookup(const struct net *net, const struct nft_set *set, -+ const u32 *key, unsigned int seq) - { - struct nft_rbtree *priv = nft_set_priv(set); - const struct nft_rbtree_elem *rbe, *interval = NULL; -@@ -65,7 +65,7 @@ static bool __nft_rbtree_lookup(const st - parent = rcu_dereference_raw(priv->root.rb_node); - while (parent != NULL) { - if (read_seqcount_retry(&priv->count, seq)) -- return false; -+ return NULL; - - rbe = rb_entry(parent, struct nft_rbtree_elem, node); - -@@ -77,7 +77,9 @@ static bool __nft_rbtree_lookup(const st - nft_rbtree_interval_end(rbe) && - nft_rbtree_interval_start(interval)) - continue; -- interval = rbe; -+ if (nft_set_elem_active(&rbe->ext, genmask) && -+ !nft_rbtree_elem_expired(rbe)) -+ interval = rbe; - } else if (d > 0) - parent = rcu_dereference_raw(parent->rb_right); - else { -@@ -87,50 +89,46 @@ static bool __nft_rbtree_lookup(const st - } - - if (nft_rbtree_elem_expired(rbe)) -- return false; -+ return NULL; - - if (nft_rbtree_interval_end(rbe)) { - if (nft_set_is_anonymous(set)) -- return false; -+ return NULL; - parent = rcu_dereference_raw(parent->rb_left); - interval = NULL; - continue; - } - -- *ext = &rbe->ext; -- return true; -+ return &rbe->ext; - } - } - - if (set->flags & NFT_SET_INTERVAL && interval != NULL && -- nft_set_elem_active(&interval->ext, genmask) && -- !nft_rbtree_elem_expired(interval) && -- nft_rbtree_interval_start(interval)) { -- *ext = &interval->ext; -- return true; -- } -+ nft_rbtree_interval_start(interval)) -+ return &interval->ext; - -- return false; -+ return NULL; - } - - INDIRECT_CALLABLE_SCOPE --bool nft_rbtree_lookup(const struct net *net, const struct nft_set *set, -- const u32 *key, const struct nft_set_ext **ext) -+const struct nft_set_ext * -+nft_rbtree_lookup(const struct net *net, const struct nft_set *set, -+ const u32 *key) - { - struct nft_rbtree *priv = nft_set_priv(set); - unsigned int seq = read_seqcount_begin(&priv->count); -- bool ret; -+ const struct nft_set_ext *ext; - -- ret = __nft_rbtree_lookup(net, set, key, ext, seq); -- if (ret || !read_seqcount_retry(&priv->count, seq)) -- return ret; -+ ext = __nft_rbtree_lookup(net, set, key, seq); -+ if (ext || !read_seqcount_retry(&priv->count, seq)) -+ return ext; - - read_lock_bh(&priv->lock); - seq = read_seqcount_begin(&priv->count); -- ret = __nft_rbtree_lookup(net, set, key, ext, seq); -+ ext = __nft_rbtree_lookup(net, set, key, seq); - read_unlock_bh(&priv->lock); - -- return ret; -+ return ext; - } - - static bool __nft_rbtree_get(const struct net *net, const struct nft_set *set, -diff -purNx .git BPI-Router-Linux-kernel/net/netfilter/xt_nfacct.c BPI-Router-Linux-kernel-6.16.12/net/netfilter/xt_nfacct.c ---- BPI-Router-Linux-kernel/net/netfilter/xt_nfacct.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/netfilter/xt_nfacct.c 2025-10-22 13:53:56.827167637 -0400 -@@ -38,8 +38,8 @@ nfacct_mt_checkentry(const struct xt_mtc - - nfacct = nfnl_acct_find_get(par->net, info->name); - if (nfacct == NULL) { -- pr_info_ratelimited("accounting object `%s' does not exists\n", -- info->name); -+ pr_info_ratelimited("accounting object `%.*s' does not exist\n", -+ NFACCT_NAME_MAX, info->name); - return -ENOENT; - } - info->nfacct = nfacct; -diff -purNx .git BPI-Router-Linux-kernel/net/netlink/af_netlink.c BPI-Router-Linux-kernel-6.16.12/net/netlink/af_netlink.c ---- BPI-Router-Linux-kernel/net/netlink/af_netlink.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/netlink/af_netlink.c 2025-10-22 13:53:56.827167637 -0400 -@@ -387,7 +387,6 @@ static void netlink_skb_set_owner_r(stru - WARN_ON(skb->sk != NULL); - skb->sk = sk; - skb->destructor = netlink_skb_destructor; -- atomic_add(skb->truesize, &sk->sk_rmem_alloc); - sk_mem_charge(sk, skb->truesize); - } - -@@ -1212,41 +1211,48 @@ struct sk_buff *netlink_alloc_large_skb( - int netlink_attachskb(struct sock *sk, struct sk_buff *skb, - long *timeo, struct sock *ssk) - { -+ DECLARE_WAITQUEUE(wait, current); - struct netlink_sock *nlk; -+ unsigned int rmem; - - nlk = nlk_sk(sk); -+ rmem = atomic_add_return(skb->truesize, &sk->sk_rmem_alloc); - -- if ((atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf || -- test_bit(NETLINK_S_CONGESTED, &nlk->state))) { -- DECLARE_WAITQUEUE(wait, current); -- if (!*timeo) { -- if (!ssk || netlink_is_kernel(ssk)) -- netlink_overrun(sk); -- sock_put(sk); -- kfree_skb(skb); -- return -EAGAIN; -- } -- -- __set_current_state(TASK_INTERRUPTIBLE); -- add_wait_queue(&nlk->wait, &wait); -+ if ((rmem == skb->truesize || rmem <= READ_ONCE(sk->sk_rcvbuf)) && -+ !test_bit(NETLINK_S_CONGESTED, &nlk->state)) { -+ netlink_skb_set_owner_r(skb, sk); -+ return 0; -+ } - -- if ((atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf || -- test_bit(NETLINK_S_CONGESTED, &nlk->state)) && -- !sock_flag(sk, SOCK_DEAD)) -- *timeo = schedule_timeout(*timeo); -+ atomic_sub(skb->truesize, &sk->sk_rmem_alloc); - -- __set_current_state(TASK_RUNNING); -- remove_wait_queue(&nlk->wait, &wait); -+ if (!*timeo) { -+ if (!ssk || netlink_is_kernel(ssk)) -+ netlink_overrun(sk); - sock_put(sk); -+ kfree_skb(skb); -+ return -EAGAIN; -+ } - -- if (signal_pending(current)) { -- kfree_skb(skb); -- return sock_intr_errno(*timeo); -- } -- return 1; -+ __set_current_state(TASK_INTERRUPTIBLE); -+ add_wait_queue(&nlk->wait, &wait); -+ rmem = atomic_read(&sk->sk_rmem_alloc); -+ -+ if (((rmem && rmem + skb->truesize > READ_ONCE(sk->sk_rcvbuf)) || -+ test_bit(NETLINK_S_CONGESTED, &nlk->state)) && -+ !sock_flag(sk, SOCK_DEAD)) -+ *timeo = schedule_timeout(*timeo); -+ -+ __set_current_state(TASK_RUNNING); -+ remove_wait_queue(&nlk->wait, &wait); -+ sock_put(sk); -+ -+ if (signal_pending(current)) { -+ kfree_skb(skb); -+ return sock_intr_errno(*timeo); - } -- netlink_skb_set_owner_r(skb, sk); -- return 0; -+ -+ return 1; - } - - static int __netlink_sendskb(struct sock *sk, struct sk_buff *skb) -@@ -1307,6 +1313,7 @@ static int netlink_unicast_kernel(struct - ret = -ECONNREFUSED; - if (nlk->netlink_rcv != NULL) { - ret = skb->len; -+ atomic_add(skb->truesize, &sk->sk_rmem_alloc); - netlink_skb_set_owner_r(skb, sk); - NETLINK_CB(skb).sk = ssk; - netlink_deliver_tap_kernel(sk, ssk, skb); -@@ -1383,13 +1390,19 @@ EXPORT_SYMBOL_GPL(netlink_strict_get_che - static int netlink_broadcast_deliver(struct sock *sk, struct sk_buff *skb) - { - struct netlink_sock *nlk = nlk_sk(sk); -+ unsigned int rmem, rcvbuf; -+ -+ rmem = atomic_add_return(skb->truesize, &sk->sk_rmem_alloc); -+ rcvbuf = READ_ONCE(sk->sk_rcvbuf); - -- if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf && -+ if ((rmem == skb->truesize || rmem <= rcvbuf) && - !test_bit(NETLINK_S_CONGESTED, &nlk->state)) { - netlink_skb_set_owner_r(skb, sk); - __netlink_sendskb(sk, skb); -- return atomic_read(&sk->sk_rmem_alloc) > (sk->sk_rcvbuf >> 1); -+ return rmem > (rcvbuf >> 1); - } -+ -+ atomic_sub(skb->truesize, &sk->sk_rmem_alloc); - return -1; - } - -@@ -2245,6 +2258,7 @@ static int netlink_dump(struct sock *sk, - struct netlink_ext_ack extack = {}; - struct netlink_callback *cb; - struct sk_buff *skb = NULL; -+ unsigned int rmem, rcvbuf; - size_t max_recvmsg_len; - struct module *module; - int err = -ENOBUFS; -@@ -2258,9 +2272,6 @@ static int netlink_dump(struct sock *sk, - goto errout_skb; - } - -- if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf) -- goto errout_skb; -- - /* NLMSG_GOODSIZE is small to avoid high order allocations being - * required, but it makes sense to _attempt_ a 32KiB allocation - * to reduce number of system calls on dump operations, if user -@@ -2283,6 +2294,13 @@ static int netlink_dump(struct sock *sk, - if (!skb) - goto errout_skb; - -+ rcvbuf = READ_ONCE(sk->sk_rcvbuf); -+ rmem = atomic_add_return(skb->truesize, &sk->sk_rmem_alloc); -+ if (rmem != skb->truesize && rmem >= rcvbuf) { -+ atomic_sub(skb->truesize, &sk->sk_rmem_alloc); -+ goto errout_skb; -+ } -+ - /* Trim skb to allocated size. User is expected to provide buffer as - * large as max(min_dump_alloc, 32KiB (max_recvmsg_len capped at - * netlink_recvmsg())). dump will pack as many smaller messages as -diff -purNx .git BPI-Router-Linux-kernel/net/netlink/diag.c BPI-Router-Linux-kernel-6.16.12/net/netlink/diag.c ---- BPI-Router-Linux-kernel/net/netlink/diag.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/netlink/diag.c 2025-10-22 13:53:56.827167637 -0400 -@@ -168,7 +168,7 @@ mc_list: - NETLINK_CB(cb->skb).portid, - cb->nlh->nlmsg_seq, - NLM_F_MULTI, -- __sock_i_ino(sk)) < 0) { -+ sock_i_ino(sk)) < 0) { - ret = 1; - break; - } -diff -purNx .git BPI-Router-Linux-kernel/net/netlink/genetlink.c BPI-Router-Linux-kernel-6.16.12/net/netlink/genetlink.c ---- BPI-Router-Linux-kernel/net/netlink/genetlink.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/netlink/genetlink.c 2025-10-22 13:53:56.827167637 -0400 -@@ -1836,6 +1836,9 @@ static int genl_bind(struct net *net, in - !ns_capable(net->user_ns, CAP_SYS_ADMIN)) - ret = -EPERM; - -+ if (ret) -+ break; -+ - if (family->bind) - family->bind(i); - -diff -purNx .git BPI-Router-Linux-kernel/net/nfc/nci/uart.c BPI-Router-Linux-kernel-6.16.12/net/nfc/nci/uart.c ---- BPI-Router-Linux-kernel/net/nfc/nci/uart.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/nfc/nci/uart.c 2025-10-22 13:53:56.827167637 -0400 -@@ -119,22 +119,22 @@ static int nci_uart_set_driver(struct tt - - memcpy(nu, nci_uart_drivers[driver], sizeof(struct nci_uart)); - nu->tty = tty; -- tty->disc_data = nu; - skb_queue_head_init(&nu->tx_q); - INIT_WORK(&nu->write_work, nci_uart_write_work); - spin_lock_init(&nu->rx_lock); - - ret = nu->ops.open(nu); - if (ret) { -- tty->disc_data = NULL; - kfree(nu); -+ return ret; - } else if (!try_module_get(nu->owner)) { - nu->ops.close(nu); -- tty->disc_data = NULL; - kfree(nu); - return -ENOENT; - } -- return ret; -+ tty->disc_data = nu; -+ -+ return 0; - } - - /* ------ LDISC part ------ */ -diff -purNx .git BPI-Router-Linux-kernel/net/openvswitch/actions.c BPI-Router-Linux-kernel-6.16.12/net/openvswitch/actions.c ---- BPI-Router-Linux-kernel/net/openvswitch/actions.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/openvswitch/actions.c 2025-10-22 13:53:56.827167637 -0400 -@@ -39,16 +39,14 @@ - #include "flow_netlink.h" - #include "openvswitch_trace.h" - --DEFINE_PER_CPU(struct ovs_pcpu_storage, ovs_pcpu_storage) = { -- .bh_lock = INIT_LOCAL_LOCK(bh_lock), --}; -+struct ovs_pcpu_storage __percpu *ovs_pcpu_storage; - - /* Make a clone of the 'key', using the pre-allocated percpu 'flow_keys' - * space. Return NULL if out of key spaces. - */ - static struct sw_flow_key *clone_key(const struct sw_flow_key *key_) - { -- struct ovs_pcpu_storage *ovs_pcpu = this_cpu_ptr(&ovs_pcpu_storage); -+ struct ovs_pcpu_storage *ovs_pcpu = this_cpu_ptr(ovs_pcpu_storage); - struct action_flow_keys *keys = &ovs_pcpu->flow_keys; - int level = ovs_pcpu->exec_level; - struct sw_flow_key *key = NULL; -@@ -94,7 +92,7 @@ static struct deferred_action *add_defer - const struct nlattr *actions, - const int actions_len) - { -- struct action_fifo *fifo = this_cpu_ptr(&ovs_pcpu_storage.action_fifos); -+ struct action_fifo *fifo = this_cpu_ptr(&ovs_pcpu_storage->action_fifos); - struct deferred_action *da; - - da = action_fifo_put(fifo); -@@ -755,7 +753,7 @@ static int set_sctp(struct sk_buff *skb, - static int ovs_vport_output(struct net *net, struct sock *sk, - struct sk_buff *skb) - { -- struct ovs_frag_data *data = this_cpu_ptr(&ovs_pcpu_storage.frag_data); -+ struct ovs_frag_data *data = this_cpu_ptr(&ovs_pcpu_storage->frag_data); - struct vport *vport = data->vport; - - if (skb_cow_head(skb, data->l2_len) < 0) { -@@ -807,7 +805,7 @@ static void prepare_frag(struct vport *v - unsigned int hlen = skb_network_offset(skb); - struct ovs_frag_data *data; - -- data = this_cpu_ptr(&ovs_pcpu_storage.frag_data); -+ data = this_cpu_ptr(&ovs_pcpu_storage->frag_data); - data->dst = skb->_skb_refdst; - data->vport = vport; - data->cb = *OVS_CB(skb); -@@ -1566,16 +1564,15 @@ static int clone_execute(struct datapath - clone = clone_flow_key ? clone_key(key) : key; - if (clone) { - int err = 0; -- - if (actions) { /* Sample action */ - if (clone_flow_key) -- __this_cpu_inc(ovs_pcpu_storage.exec_level); -+ __this_cpu_inc(ovs_pcpu_storage->exec_level); - - err = do_execute_actions(dp, skb, clone, - actions, len); - - if (clone_flow_key) -- __this_cpu_dec(ovs_pcpu_storage.exec_level); -+ __this_cpu_dec(ovs_pcpu_storage->exec_level); - } else { /* Recirc action */ - clone->recirc_id = recirc_id; - ovs_dp_process_packet(skb, clone); -@@ -1611,7 +1608,7 @@ static int clone_execute(struct datapath - - static void process_deferred_actions(struct datapath *dp) - { -- struct action_fifo *fifo = this_cpu_ptr(&ovs_pcpu_storage.action_fifos); -+ struct action_fifo *fifo = this_cpu_ptr(&ovs_pcpu_storage->action_fifos); - - /* Do not touch the FIFO in case there is no deferred actions. */ - if (action_fifo_is_empty(fifo)) -@@ -1642,7 +1639,7 @@ int ovs_execute_actions(struct datapath - { - int err, level; - -- level = __this_cpu_inc_return(ovs_pcpu_storage.exec_level); -+ level = __this_cpu_inc_return(ovs_pcpu_storage->exec_level); - if (unlikely(level > OVS_RECURSION_LIMIT)) { - net_crit_ratelimited("ovs: recursion limit reached on datapath %s, probable configuration error\n", - ovs_dp_name(dp)); -@@ -1659,6 +1656,6 @@ int ovs_execute_actions(struct datapath - process_deferred_actions(dp); - - out: -- __this_cpu_dec(ovs_pcpu_storage.exec_level); -+ __this_cpu_dec(ovs_pcpu_storage->exec_level); - return err; - } -diff -purNx .git BPI-Router-Linux-kernel/net/openvswitch/datapath.c BPI-Router-Linux-kernel-6.16.12/net/openvswitch/datapath.c ---- BPI-Router-Linux-kernel/net/openvswitch/datapath.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/openvswitch/datapath.c 2025-10-22 13:53:56.827167637 -0400 -@@ -244,7 +244,7 @@ void ovs_dp_detach_port(struct vport *p) - /* Must be called with rcu_read_lock. */ - void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key) - { -- struct ovs_pcpu_storage *ovs_pcpu = this_cpu_ptr(&ovs_pcpu_storage); -+ struct ovs_pcpu_storage *ovs_pcpu = this_cpu_ptr(ovs_pcpu_storage); - const struct vport *p = OVS_CB(skb)->input_vport; - struct datapath *dp = p->dp; - struct sw_flow *flow; -@@ -299,7 +299,7 @@ void ovs_dp_process_packet(struct sk_buf - * avoided. - */ - if (IS_ENABLED(CONFIG_PREEMPT_RT) && ovs_pcpu->owner != current) { -- local_lock_nested_bh(&ovs_pcpu_storage.bh_lock); -+ local_lock_nested_bh(&ovs_pcpu_storage->bh_lock); - ovs_pcpu->owner = current; - ovs_pcpu_locked = true; - } -@@ -310,7 +310,7 @@ void ovs_dp_process_packet(struct sk_buf - ovs_dp_name(dp), error); - if (ovs_pcpu_locked) { - ovs_pcpu->owner = NULL; -- local_unlock_nested_bh(&ovs_pcpu_storage.bh_lock); -+ local_unlock_nested_bh(&ovs_pcpu_storage->bh_lock); - } - - stats_counter = &stats->n_hit; -@@ -689,13 +689,13 @@ static int ovs_packet_cmd_execute(struct - sf_acts = rcu_dereference(flow->sf_acts); - - local_bh_disable(); -- local_lock_nested_bh(&ovs_pcpu_storage.bh_lock); -+ local_lock_nested_bh(&ovs_pcpu_storage->bh_lock); - if (IS_ENABLED(CONFIG_PREEMPT_RT)) -- this_cpu_write(ovs_pcpu_storage.owner, current); -+ this_cpu_write(ovs_pcpu_storage->owner, current); - err = ovs_execute_actions(dp, packet, sf_acts, &flow->key); - if (IS_ENABLED(CONFIG_PREEMPT_RT)) -- this_cpu_write(ovs_pcpu_storage.owner, NULL); -- local_unlock_nested_bh(&ovs_pcpu_storage.bh_lock); -+ this_cpu_write(ovs_pcpu_storage->owner, NULL); -+ local_unlock_nested_bh(&ovs_pcpu_storage->bh_lock); - local_bh_enable(); - rcu_read_unlock(); - -@@ -2744,6 +2744,28 @@ static struct drop_reason_list drop_reas - .n_reasons = ARRAY_SIZE(ovs_drop_reasons), - }; - -+static int __init ovs_alloc_percpu_storage(void) -+{ -+ unsigned int cpu; -+ -+ ovs_pcpu_storage = alloc_percpu(*ovs_pcpu_storage); -+ if (!ovs_pcpu_storage) -+ return -ENOMEM; -+ -+ for_each_possible_cpu(cpu) { -+ struct ovs_pcpu_storage *ovs_pcpu; -+ -+ ovs_pcpu = per_cpu_ptr(ovs_pcpu_storage, cpu); -+ local_lock_init(&ovs_pcpu->bh_lock); -+ } -+ return 0; -+} -+ -+static void ovs_free_percpu_storage(void) -+{ -+ free_percpu(ovs_pcpu_storage); -+} -+ - static int __init dp_init(void) - { - int err; -@@ -2753,6 +2775,10 @@ static int __init dp_init(void) - - pr_info("Open vSwitch switching datapath\n"); - -+ err = ovs_alloc_percpu_storage(); -+ if (err) -+ goto error; -+ - err = ovs_internal_dev_rtnl_link_register(); - if (err) - goto error; -@@ -2799,6 +2825,7 @@ error_flow_exit: - error_unreg_rtnl_link: - ovs_internal_dev_rtnl_link_unregister(); - error: -+ ovs_free_percpu_storage(); - return err; - } - -@@ -2813,6 +2840,7 @@ static void dp_cleanup(void) - ovs_vport_exit(); - ovs_flow_exit(); - ovs_internal_dev_rtnl_link_unregister(); -+ ovs_free_percpu_storage(); - } - - module_init(dp_init); -diff -purNx .git BPI-Router-Linux-kernel/net/openvswitch/datapath.h BPI-Router-Linux-kernel-6.16.12/net/openvswitch/datapath.h ---- BPI-Router-Linux-kernel/net/openvswitch/datapath.h 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/openvswitch/datapath.h 2025-10-22 13:53:56.827167637 -0400 -@@ -220,7 +220,8 @@ struct ovs_pcpu_storage { - struct task_struct *owner; - local_lock_t bh_lock; - }; --DECLARE_PER_CPU(struct ovs_pcpu_storage, ovs_pcpu_storage); -+ -+extern struct ovs_pcpu_storage __percpu *ovs_pcpu_storage; - - /** - * enum ovs_pkt_hash_types - hash info to include with a packet -diff -purNx .git BPI-Router-Linux-kernel/net/packet/af_packet.c BPI-Router-Linux-kernel-6.16.12/net/packet/af_packet.c ---- BPI-Router-Linux-kernel/net/packet/af_packet.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/packet/af_packet.c 2025-10-22 13:53:56.831167617 -0400 -@@ -2785,7 +2785,7 @@ static int tpacket_snd(struct packet_soc - int len_sum = 0; - int status = TP_STATUS_AVAILABLE; - int hlen, tlen, copylen = 0; -- long timeo = 0; -+ long timeo; - - mutex_lock(&po->pg_vec_lock); - -@@ -2839,22 +2839,28 @@ static int tpacket_snd(struct packet_soc - if ((size_max > dev->mtu + reserve + VLAN_HLEN) && !vnet_hdr_sz) - size_max = dev->mtu + reserve + VLAN_HLEN; - -+ timeo = sock_sndtimeo(&po->sk, msg->msg_flags & MSG_DONTWAIT); - reinit_completion(&po->skb_completion); - - do { - ph = packet_current_frame(po, &po->tx_ring, - TP_STATUS_SEND_REQUEST); - if (unlikely(ph == NULL)) { -- if (need_wait && skb) { -- timeo = sock_sndtimeo(&po->sk, msg->msg_flags & MSG_DONTWAIT); -+ /* Note: packet_read_pending() might be slow if we -+ * have to call it as it's per_cpu variable, but in -+ * fast-path we don't have to call it, only when ph -+ * is NULL, we need to check the pending_refcnt. -+ */ -+ if (need_wait && packet_read_pending(&po->tx_ring)) { - timeo = wait_for_completion_interruptible_timeout(&po->skb_completion, timeo); - if (timeo <= 0) { - err = !timeo ? -ETIMEDOUT : -ERESTARTSYS; - goto out_put; - } -- } -- /* check for additional frames */ -- continue; -+ /* check for additional frames */ -+ continue; -+ } else -+ break; - } - - skb = NULL; -@@ -2943,14 +2949,7 @@ tpacket_error: - } - packet_increment_head(&po->tx_ring); - len_sum += tp_len; -- } while (likely((ph != NULL) || -- /* Note: packet_read_pending() might be slow if we have -- * to call it as it's per_cpu variable, but in fast-path -- * we already short-circuit the loop with the first -- * condition, and luckily don't have to go that path -- * anyway. -- */ -- (need_wait && packet_read_pending(&po->tx_ring)))); -+ } while (1); - - err = len_sum; - goto out_put; -@@ -4574,10 +4573,10 @@ static int packet_set_ring(struct sock * - spin_lock(&po->bind_lock); - was_running = packet_sock_flag(po, PACKET_SOCK_RUNNING); - num = po->num; -- if (was_running) { -- WRITE_ONCE(po->num, 0); -+ WRITE_ONCE(po->num, 0); -+ if (was_running) - __unregister_prot_hook(sk, false); -- } -+ - spin_unlock(&po->bind_lock); - - synchronize_net(); -@@ -4609,10 +4608,10 @@ static int packet_set_ring(struct sock * - mutex_unlock(&po->pg_vec_lock); - - spin_lock(&po->bind_lock); -- if (was_running) { -- WRITE_ONCE(po->num, num); -+ WRITE_ONCE(po->num, num); -+ if (was_running) - register_prot_hook(sk); -- } -+ - spin_unlock(&po->bind_lock); - if (pg_vec && (po->tp_version > TPACKET_V2)) { - /* Because we don't support block-based V3 on tx-ring */ -@@ -4783,7 +4782,7 @@ static int packet_seq_show(struct seq_fi - READ_ONCE(po->ifindex), - packet_sock_flag(po, PACKET_SOCK_RUNNING), - atomic_read(&s->sk_rmem_alloc), -- from_kuid_munged(seq_user_ns(seq), sock_i_uid(s)), -+ from_kuid_munged(seq_user_ns(seq), sk_uid(s)), - sock_i_ino(s)); - } - -diff -purNx .git BPI-Router-Linux-kernel/net/packet/diag.c BPI-Router-Linux-kernel-6.16.12/net/packet/diag.c ---- BPI-Router-Linux-kernel/net/packet/diag.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/packet/diag.c 2025-10-22 13:53:56.831167617 -0400 -@@ -153,7 +153,7 @@ static int sk_diag_fill(struct sock *sk, - - if ((req->pdiag_show & PACKET_SHOW_INFO) && - nla_put_u32(skb, PACKET_DIAG_UID, -- from_kuid_munged(user_ns, sock_i_uid(sk)))) -+ from_kuid_munged(user_ns, sk_uid(sk)))) - goto out_nlmsg_trim; - - if ((req->pdiag_show & PACKET_SHOW_MCLIST) && -diff -purNx .git BPI-Router-Linux-kernel/net/phonet/pep.c BPI-Router-Linux-kernel-6.16.12/net/phonet/pep.c ---- BPI-Router-Linux-kernel/net/phonet/pep.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/phonet/pep.c 2025-10-22 13:53:56.831167617 -0400 -@@ -826,6 +826,7 @@ static struct sock *pep_sock_accept(stru - } - - /* Check for duplicate pipe handle */ -+ pn_skb_get_dst_sockaddr(skb, &dst); - newsk = pep_find_pipe(&pn->hlist, &dst, pipe_handle); - if (unlikely(newsk)) { - __sock_put(newsk); -@@ -850,7 +851,6 @@ static struct sock *pep_sock_accept(stru - newsk->sk_destruct = pipe_destruct; - - newpn = pep_sk(newsk); -- pn_skb_get_dst_sockaddr(skb, &dst); - pn_skb_get_src_sockaddr(skb, &src); - newpn->pn_sk.sobject = pn_sockaddr_get_object(&dst); - newpn->pn_sk.dobject = pn_sockaddr_get_object(&src); -diff -purNx .git BPI-Router-Linux-kernel/net/phonet/socket.c BPI-Router-Linux-kernel-6.16.12/net/phonet/socket.c ---- BPI-Router-Linux-kernel/net/phonet/socket.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/phonet/socket.c 2025-10-22 13:53:56.831167617 -0400 -@@ -584,7 +584,7 @@ static int pn_sock_seq_show(struct seq_f - sk->sk_protocol, pn->sobject, pn->dobject, - pn->resource, sk->sk_state, - sk_wmem_alloc_get(sk), sk_rmem_alloc_get(sk), -- from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), -+ from_kuid_munged(seq_user_ns(seq), sk_uid(sk)), - sock_i_ino(sk), - refcount_read(&sk->sk_refcnt), sk, - atomic_read(&sk->sk_drops)); -@@ -755,7 +755,7 @@ static int pn_res_seq_show(struct seq_fi - - seq_printf(seq, "%02X %5u %lu", - (int) (psk - pnres.sk), -- from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), -+ from_kuid_munged(seq_user_ns(seq), sk_uid(sk)), - sock_i_ino(sk)); - } - seq_pad(seq, '\n'); -diff -purNx .git BPI-Router-Linux-kernel/net/rds/ib_frmr.c BPI-Router-Linux-kernel-6.16.12/net/rds/ib_frmr.c ---- BPI-Router-Linux-kernel/net/rds/ib_frmr.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/rds/ib_frmr.c 2025-10-22 13:53:56.831167617 -0400 -@@ -133,12 +133,15 @@ static int rds_ib_post_reg_frmr(struct r - - ret = ib_map_mr_sg_zbva(frmr->mr, ibmr->sg, ibmr->sg_dma_len, - &off, PAGE_SIZE); -- if (unlikely(ret != ibmr->sg_dma_len)) -- return ret < 0 ? ret : -EINVAL; -+ if (unlikely(ret != ibmr->sg_dma_len)) { -+ ret = ret < 0 ? ret : -EINVAL; -+ goto out_inc; -+ } - -- if (cmpxchg(&frmr->fr_state, -- FRMR_IS_FREE, FRMR_IS_INUSE) != FRMR_IS_FREE) -- return -EBUSY; -+ if (cmpxchg(&frmr->fr_state, FRMR_IS_FREE, FRMR_IS_INUSE) != FRMR_IS_FREE) { -+ ret = -EBUSY; -+ goto out_inc; -+ } - - atomic_inc(&ibmr->ic->i_fastreg_inuse_count); - -@@ -166,11 +169,10 @@ static int rds_ib_post_reg_frmr(struct r - /* Failure here can be because of -ENOMEM as well */ - rds_transition_frwr_state(ibmr, FRMR_IS_INUSE, FRMR_IS_STALE); - -- atomic_inc(&ibmr->ic->i_fastreg_wrs); - if (printk_ratelimit()) - pr_warn("RDS/IB: %s returned error(%d)\n", - __func__, ret); -- goto out; -+ goto out_inc; - } - - /* Wait for the registration to complete in order to prevent an invalid -@@ -179,8 +181,10 @@ static int rds_ib_post_reg_frmr(struct r - */ - wait_event(frmr->fr_reg_done, !frmr->fr_reg); - --out: -+ return ret; - -+out_inc: -+ atomic_inc(&ibmr->ic->i_fastreg_wrs); - return ret; - } - -diff -purNx .git BPI-Router-Linux-kernel/net/rfkill/rfkill-gpio.c BPI-Router-Linux-kernel-6.16.12/net/rfkill/rfkill-gpio.c ---- BPI-Router-Linux-kernel/net/rfkill/rfkill-gpio.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/rfkill/rfkill-gpio.c 2025-10-22 13:53:56.831167617 -0400 -@@ -94,10 +94,10 @@ static const struct dmi_system_id rfkill - static int rfkill_gpio_probe(struct platform_device *pdev) - { - struct rfkill_gpio_data *rfkill; -- struct gpio_desc *gpio; -+ const char *type_name = NULL; - const char *name_property; - const char *type_property; -- const char *type_name; -+ struct gpio_desc *gpio; - int ret; - - if (dmi_check_system(rfkill_gpio_deny_table)) -diff -purNx .git BPI-Router-Linux-kernel/net/rose/af_rose.c BPI-Router-Linux-kernel-6.16.12/net/rose/af_rose.c ---- BPI-Router-Linux-kernel/net/rose/af_rose.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/rose/af_rose.c 2025-10-22 13:53:56.831167617 -0400 -@@ -170,7 +170,7 @@ void rose_kill_by_neigh(struct rose_neig - - if (rose->neighbour == neigh) { - rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0); -- rose->neighbour->use--; -+ rose_neigh_put(rose->neighbour); - rose->neighbour = NULL; - } - } -@@ -212,7 +212,7 @@ start: - if (rose->device == dev) { - rose_disconnect(sk, ENETUNREACH, ROSE_OUT_OF_ORDER, 0); - if (rose->neighbour) -- rose->neighbour->use--; -+ rose_neigh_put(rose->neighbour); - netdev_put(rose->device, &rose->dev_tracker); - rose->device = NULL; - } -@@ -655,7 +655,7 @@ static int rose_release(struct socket *s - break; - - case ROSE_STATE_2: -- rose->neighbour->use--; -+ rose_neigh_put(rose->neighbour); - release_sock(sk); - rose_disconnect(sk, 0, -1, -1); - lock_sock(sk); -@@ -823,6 +823,7 @@ static int rose_connect(struct socket *s - rose->lci = rose_new_lci(rose->neighbour); - if (!rose->lci) { - err = -ENETUNREACH; -+ rose_neigh_put(rose->neighbour); - goto out_release; - } - -@@ -834,12 +835,14 @@ static int rose_connect(struct socket *s - dev = rose_dev_first(); - if (!dev) { - err = -ENETUNREACH; -+ rose_neigh_put(rose->neighbour); - goto out_release; - } - - user = ax25_findbyuid(current_euid()); - if (!user) { - err = -EINVAL; -+ rose_neigh_put(rose->neighbour); - dev_put(dev); - goto out_release; - } -@@ -874,8 +877,6 @@ static int rose_connect(struct socket *s - - rose->state = ROSE_STATE_1; - -- rose->neighbour->use++; -- - rose_write_internal(sk, ROSE_CALL_REQUEST); - rose_start_heartbeat(sk); - rose_start_t1timer(sk); -@@ -1077,7 +1078,7 @@ int rose_rx_call_request(struct sk_buff - GFP_ATOMIC); - make_rose->facilities = facilities; - -- make_rose->neighbour->use++; -+ rose_neigh_hold(make_rose->neighbour); - - if (rose_sk(sk)->defer) { - make_rose->state = ROSE_STATE_5; -diff -purNx .git BPI-Router-Linux-kernel/net/rose/rose_in.c BPI-Router-Linux-kernel-6.16.12/net/rose/rose_in.c ---- BPI-Router-Linux-kernel/net/rose/rose_in.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/rose/rose_in.c 2025-10-22 13:53:56.831167617 -0400 -@@ -56,7 +56,7 @@ static int rose_state1_machine(struct so - case ROSE_CLEAR_REQUEST: - rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); - rose_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]); -- rose->neighbour->use--; -+ rose_neigh_put(rose->neighbour); - break; - - default: -@@ -79,12 +79,12 @@ static int rose_state2_machine(struct so - case ROSE_CLEAR_REQUEST: - rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); - rose_disconnect(sk, 0, skb->data[3], skb->data[4]); -- rose->neighbour->use--; -+ rose_neigh_put(rose->neighbour); - break; - - case ROSE_CLEAR_CONFIRMATION: - rose_disconnect(sk, 0, -1, -1); -- rose->neighbour->use--; -+ rose_neigh_put(rose->neighbour); - break; - - default: -@@ -120,7 +120,7 @@ static int rose_state3_machine(struct so - case ROSE_CLEAR_REQUEST: - rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); - rose_disconnect(sk, 0, skb->data[3], skb->data[4]); -- rose->neighbour->use--; -+ rose_neigh_put(rose->neighbour); - break; - - case ROSE_RR: -@@ -233,7 +233,7 @@ static int rose_state4_machine(struct so - case ROSE_CLEAR_REQUEST: - rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); - rose_disconnect(sk, 0, skb->data[3], skb->data[4]); -- rose->neighbour->use--; -+ rose_neigh_put(rose->neighbour); - break; - - default: -@@ -253,7 +253,7 @@ static int rose_state5_machine(struct so - if (frametype == ROSE_CLEAR_REQUEST) { - rose_write_internal(sk, ROSE_CLEAR_CONFIRMATION); - rose_disconnect(sk, 0, skb->data[3], skb->data[4]); -- rose_sk(sk)->neighbour->use--; -+ rose_neigh_put(rose_sk(sk)->neighbour); - } - - return 0; -diff -purNx .git BPI-Router-Linux-kernel/net/rose/rose_route.c BPI-Router-Linux-kernel-6.16.12/net/rose/rose_route.c ---- BPI-Router-Linux-kernel/net/rose/rose_route.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/rose/rose_route.c 2025-10-22 13:53:56.831167617 -0400 -@@ -93,11 +93,11 @@ static int __must_check rose_add_node(st - rose_neigh->ax25 = NULL; - rose_neigh->dev = dev; - rose_neigh->count = 0; -- rose_neigh->use = 0; - rose_neigh->dce_mode = 0; - rose_neigh->loopback = 0; - rose_neigh->number = rose_neigh_no++; - rose_neigh->restarted = 0; -+ refcount_set(&rose_neigh->use, 1); - - skb_queue_head_init(&rose_neigh->queue); - -@@ -178,6 +178,7 @@ static int __must_check rose_add_node(st - } - } - rose_neigh->count++; -+ rose_neigh_hold(rose_neigh); - - goto out; - } -@@ -187,6 +188,7 @@ static int __must_check rose_add_node(st - rose_node->neighbour[rose_node->count] = rose_neigh; - rose_node->count++; - rose_neigh->count++; -+ rose_neigh_hold(rose_neigh); - } - - out: -@@ -234,20 +236,12 @@ static void rose_remove_neigh(struct ros - - if ((s = rose_neigh_list) == rose_neigh) { - rose_neigh_list = rose_neigh->next; -- if (rose_neigh->ax25) -- ax25_cb_put(rose_neigh->ax25); -- kfree(rose_neigh->digipeat); -- kfree(rose_neigh); - return; - } - - while (s != NULL && s->next != NULL) { - if (s->next == rose_neigh) { - s->next = rose_neigh->next; -- if (rose_neigh->ax25) -- ax25_cb_put(rose_neigh->ax25); -- kfree(rose_neigh->digipeat); -- kfree(rose_neigh); - return; - } - -@@ -263,10 +257,10 @@ static void rose_remove_route(struct ros - struct rose_route *s; - - if (rose_route->neigh1 != NULL) -- rose_route->neigh1->use--; -+ rose_neigh_put(rose_route->neigh1); - - if (rose_route->neigh2 != NULL) -- rose_route->neigh2->use--; -+ rose_neigh_put(rose_route->neigh2); - - if ((s = rose_route_list) == rose_route) { - rose_route_list = rose_route->next; -@@ -330,9 +324,12 @@ static int rose_del_node(struct rose_rou - for (i = 0; i < rose_node->count; i++) { - if (rose_node->neighbour[i] == rose_neigh) { - rose_neigh->count--; -+ rose_neigh_put(rose_neigh); - -- if (rose_neigh->count == 0 && rose_neigh->use == 0) -+ if (rose_neigh->count == 0) { - rose_remove_neigh(rose_neigh); -+ rose_neigh_put(rose_neigh); -+ } - - rose_node->count--; - -@@ -381,11 +378,11 @@ void rose_add_loopback_neigh(void) - sn->ax25 = NULL; - sn->dev = NULL; - sn->count = 0; -- sn->use = 0; - sn->dce_mode = 1; - sn->loopback = 1; - sn->number = rose_neigh_no++; - sn->restarted = 1; -+ refcount_set(&sn->use, 1); - - skb_queue_head_init(&sn->queue); - -@@ -436,6 +433,7 @@ int rose_add_loopback_node(const rose_ad - rose_node_list = rose_node; - - rose_loopback_neigh->count++; -+ rose_neigh_hold(rose_loopback_neigh); - - out: - spin_unlock_bh(&rose_node_list_lock); -@@ -467,6 +465,7 @@ void rose_del_loopback_node(const rose_a - rose_remove_node(rose_node); - - rose_loopback_neigh->count--; -+ rose_neigh_put(rose_loopback_neigh); - - out: - spin_unlock_bh(&rose_node_list_lock); -@@ -497,22 +496,16 @@ void rose_rt_device_down(struct net_devi - t = rose_node; - rose_node = rose_node->next; - -- for (i = 0; i < t->count; i++) { -+ for (i = t->count - 1; i >= 0; i--) { - if (t->neighbour[i] != s) - continue; - - t->count--; - -- switch (i) { -- case 0: -- t->neighbour[0] = t->neighbour[1]; -- fallthrough; -- case 1: -- t->neighbour[1] = t->neighbour[2]; -- break; -- case 2: -- break; -- } -+ memmove(&t->neighbour[i], &t->neighbour[i + 1], -+ sizeof(t->neighbour[0]) * -+ (t->count - i)); -+ rose_neigh_put(s); - } - - if (t->count <= 0) -@@ -520,6 +513,7 @@ void rose_rt_device_down(struct net_devi - } - - rose_remove_neigh(s); -+ rose_neigh_put(s); - } - spin_unlock_bh(&rose_neigh_list_lock); - spin_unlock_bh(&rose_node_list_lock); -@@ -555,6 +549,7 @@ static int rose_clear_routes(void) - { - struct rose_neigh *s, *rose_neigh; - struct rose_node *t, *rose_node; -+ int i; - - spin_lock_bh(&rose_node_list_lock); - spin_lock_bh(&rose_neigh_list_lock); -@@ -565,17 +560,21 @@ static int rose_clear_routes(void) - while (rose_node != NULL) { - t = rose_node; - rose_node = rose_node->next; -- if (!t->loopback) -+ -+ if (!t->loopback) { -+ for (i = 0; i < t->count; i++) -+ rose_neigh_put(t->neighbour[i]); - rose_remove_node(t); -+ } - } - - while (rose_neigh != NULL) { - s = rose_neigh; - rose_neigh = rose_neigh->next; - -- if (s->use == 0 && !s->loopback) { -- s->count = 0; -+ if (!s->loopback) { - rose_remove_neigh(s); -+ rose_neigh_put(s); - } - } - -@@ -691,6 +690,7 @@ struct rose_neigh *rose_get_neigh(rose_a - for (i = 0; i < node->count; i++) { - if (node->neighbour[i]->restarted) { - res = node->neighbour[i]; -+ rose_neigh_hold(node->neighbour[i]); - goto out; - } - } -@@ -702,6 +702,7 @@ struct rose_neigh *rose_get_neigh(rose_a - for (i = 0; i < node->count; i++) { - if (!rose_ftimer_running(node->neighbour[i])) { - res = node->neighbour[i]; -+ rose_neigh_hold(node->neighbour[i]); - goto out; - } - failed = 1; -@@ -791,13 +792,13 @@ static void rose_del_route_by_neigh(stru - } - - if (rose_route->neigh1 == rose_neigh) { -- rose_route->neigh1->use--; -+ rose_neigh_put(rose_route->neigh1); - rose_route->neigh1 = NULL; - rose_transmit_clear_request(rose_route->neigh2, rose_route->lci2, ROSE_OUT_OF_ORDER, 0); - } - - if (rose_route->neigh2 == rose_neigh) { -- rose_route->neigh2->use--; -+ rose_neigh_put(rose_route->neigh2); - rose_route->neigh2 = NULL; - rose_transmit_clear_request(rose_route->neigh1, rose_route->lci1, ROSE_OUT_OF_ORDER, 0); - } -@@ -926,7 +927,7 @@ int rose_route_frame(struct sk_buff *skb - rose_clear_queues(sk); - rose->cause = ROSE_NETWORK_CONGESTION; - rose->diagnostic = 0; -- rose->neighbour->use--; -+ rose_neigh_put(rose->neighbour); - rose->neighbour = NULL; - rose->lci = 0; - rose->state = ROSE_STATE_0; -@@ -1051,12 +1052,12 @@ int rose_route_frame(struct sk_buff *skb - - if ((new_lci = rose_new_lci(new_neigh)) == 0) { - rose_transmit_clear_request(rose_neigh, lci, ROSE_NETWORK_CONGESTION, 71); -- goto out; -+ goto put_neigh; - } - - if ((rose_route = kmalloc(sizeof(*rose_route), GFP_ATOMIC)) == NULL) { - rose_transmit_clear_request(rose_neigh, lci, ROSE_NETWORK_CONGESTION, 120); -- goto out; -+ goto put_neigh; - } - - rose_route->lci1 = lci; -@@ -1069,8 +1070,8 @@ int rose_route_frame(struct sk_buff *skb - rose_route->lci2 = new_lci; - rose_route->neigh2 = new_neigh; - -- rose_route->neigh1->use++; -- rose_route->neigh2->use++; -+ rose_neigh_hold(rose_route->neigh1); -+ rose_neigh_hold(rose_route->neigh2); - - rose_route->next = rose_route_list; - rose_route_list = rose_route; -@@ -1082,6 +1083,8 @@ int rose_route_frame(struct sk_buff *skb - rose_transmit_link(skb, rose_route->neigh2); - res = 1; - -+put_neigh: -+ rose_neigh_put(new_neigh); - out: - spin_unlock_bh(&rose_route_list_lock); - spin_unlock_bh(&rose_neigh_list_lock); -@@ -1197,7 +1200,7 @@ static int rose_neigh_show(struct seq_fi - (rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(buf, &rose_neigh->callsign), - rose_neigh->dev ? rose_neigh->dev->name : "???", - rose_neigh->count, -- rose_neigh->use, -+ refcount_read(&rose_neigh->use) - rose_neigh->count - 1, - (rose_neigh->dce_mode) ? "DCE" : "DTE", - (rose_neigh->restarted) ? "yes" : "no", - ax25_display_timer(&rose_neigh->t0timer) / HZ, -@@ -1302,18 +1305,22 @@ void __exit rose_rt_free(void) - struct rose_neigh *s, *rose_neigh = rose_neigh_list; - struct rose_node *t, *rose_node = rose_node_list; - struct rose_route *u, *rose_route = rose_route_list; -+ int i; - - while (rose_neigh != NULL) { - s = rose_neigh; - rose_neigh = rose_neigh->next; - - rose_remove_neigh(s); -+ rose_neigh_put(s); - } - - while (rose_node != NULL) { - t = rose_node; - rose_node = rose_node->next; - -+ for (i = 0; i < t->count; i++) -+ rose_neigh_put(t->neighbour[i]); - rose_remove_node(t); - } - -diff -purNx .git BPI-Router-Linux-kernel/net/rose/rose_timer.c BPI-Router-Linux-kernel-6.16.12/net/rose/rose_timer.c ---- BPI-Router-Linux-kernel/net/rose/rose_timer.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/rose/rose_timer.c 2025-10-22 13:53:56.831167617 -0400 -@@ -180,7 +180,7 @@ static void rose_timer_expiry(struct tim - break; - - case ROSE_STATE_2: /* T3 */ -- rose->neighbour->use--; -+ rose_neigh_put(rose->neighbour); - rose_disconnect(sk, ETIMEDOUT, -1, -1); - break; - -diff -purNx .git BPI-Router-Linux-kernel/net/rxrpc/ar-internal.h BPI-Router-Linux-kernel-6.16.12/net/rxrpc/ar-internal.h ---- BPI-Router-Linux-kernel/net/rxrpc/ar-internal.h 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/rxrpc/ar-internal.h 2025-10-22 13:53:56.831167617 -0400 -@@ -44,6 +44,7 @@ enum rxrpc_skb_mark { - RXRPC_SKB_MARK_SERVICE_CONN_SECURED, /* Service connection response has been verified */ - RXRPC_SKB_MARK_REJECT_BUSY, /* Reject with BUSY */ - RXRPC_SKB_MARK_REJECT_ABORT, /* Reject with ABORT (code in skb->priority) */ -+ RXRPC_SKB_MARK_REJECT_CONN_ABORT, /* Reject with connection ABORT (code in skb->priority) */ - }; - - /* -@@ -361,12 +362,15 @@ struct rxrpc_local { - struct list_head new_client_calls; /* Newly created client calls need connection */ - spinlock_t client_call_lock; /* Lock for ->new_client_calls */ - struct sockaddr_rxrpc srx; /* local address */ -- /* Provide a kvec table sufficiently large to manage either a DATA -- * packet with a maximum set of jumbo subpackets or a PING ACK padded -- * out to 64K with zeropages for PMTUD. -- */ -- struct kvec kvec[1 + RXRPC_MAX_NR_JUMBO > 3 + 16 ? -- 1 + RXRPC_MAX_NR_JUMBO : 3 + 16]; -+ union { -+ /* Provide a kvec table sufficiently large to manage either a -+ * DATA packet with a maximum set of jumbo subpackets or a PING -+ * ACK padded out to 64K with zeropages for PMTUD. -+ */ -+ struct kvec kvec[1 + RXRPC_MAX_NR_JUMBO > 3 + 16 ? -+ 1 + RXRPC_MAX_NR_JUMBO : 3 + 16]; -+ struct bio_vec bvec[3 + 16]; -+ }; - }; - - /* -@@ -1250,6 +1254,8 @@ int rxrpc_encap_rcv(struct sock *, struc - void rxrpc_error_report(struct sock *); - bool rxrpc_direct_abort(struct sk_buff *skb, enum rxrpc_abort_reason why, - s32 abort_code, int err); -+bool rxrpc_direct_conn_abort(struct sk_buff *skb, enum rxrpc_abort_reason why, -+ s32 abort_code, int err); - int rxrpc_io_thread(void *data); - void rxrpc_post_response(struct rxrpc_connection *conn, struct sk_buff *skb); - static inline void rxrpc_wake_up_io_thread(struct rxrpc_local *local) -@@ -1380,6 +1386,7 @@ struct rxrpc_peer *rxrpc_lookup_peer_rcu - const struct sockaddr_rxrpc *); - struct rxrpc_peer *rxrpc_lookup_peer(struct rxrpc_local *local, - struct sockaddr_rxrpc *srx, gfp_t gfp); -+void rxrpc_assess_MTU_size(struct rxrpc_local *local, struct rxrpc_peer *peer); - struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *, gfp_t, - enum rxrpc_peer_trace); - void rxrpc_new_incoming_peer(struct rxrpc_local *local, struct rxrpc_peer *peer); -diff -purNx .git BPI-Router-Linux-kernel/net/rxrpc/call_accept.c BPI-Router-Linux-kernel-6.16.12/net/rxrpc/call_accept.c ---- BPI-Router-Linux-kernel/net/rxrpc/call_accept.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/rxrpc/call_accept.c 2025-10-22 13:53:56.831167617 -0400 -@@ -149,6 +149,7 @@ static int rxrpc_service_prealloc_one(st - - id_in_use: - write_unlock(&rx->call_lock); -+ rxrpc_prefail_call(call, RXRPC_CALL_LOCAL_ERROR, -EBADSLT); - rxrpc_cleanup_call(call); - _leave(" = -EBADSLT"); - return -EBADSLT; -@@ -218,6 +219,7 @@ void rxrpc_discard_prealloc(struct rxrpc - tail = b->call_backlog_tail; - while (CIRC_CNT(head, tail, size) > 0) { - struct rxrpc_call *call = b->call_backlog[tail]; -+ rxrpc_see_call(call, rxrpc_call_see_discard); - rcu_assign_pointer(call->socket, rx); - if (rx->app_ops && - rx->app_ops->discard_new_call) { -@@ -254,6 +256,9 @@ static struct rxrpc_call *rxrpc_alloc_in - unsigned short call_tail, conn_tail, peer_tail; - unsigned short call_count, conn_count; - -+ if (!b) -+ return NULL; -+ - /* #calls >= #conns >= #peers must hold true. */ - call_head = smp_load_acquire(&b->call_backlog_head); - call_tail = b->call_backlog_tail; -@@ -369,8 +374,8 @@ bool rxrpc_new_incoming_call(struct rxrp - spin_lock(&rx->incoming_lock); - if (rx->sk.sk_state == RXRPC_SERVER_LISTEN_DISABLED || - rx->sk.sk_state == RXRPC_CLOSE) { -- rxrpc_direct_abort(skb, rxrpc_abort_shut_down, -- RX_INVALID_OPERATION, -ESHUTDOWN); -+ rxrpc_direct_conn_abort(skb, rxrpc_abort_shut_down, -+ RX_INVALID_OPERATION, -ESHUTDOWN); - goto no_call; - } - -@@ -402,6 +407,7 @@ bool rxrpc_new_incoming_call(struct rxrp - - spin_unlock(&rx->incoming_lock); - read_unlock_irq(&local->services_lock); -+ rxrpc_assess_MTU_size(local, call->peer); - - if (hlist_unhashed(&call->error_link)) { - spin_lock_irq(&call->peer->lock); -@@ -416,12 +422,12 @@ bool rxrpc_new_incoming_call(struct rxrp - - unsupported_service: - read_unlock_irq(&local->services_lock); -- return rxrpc_direct_abort(skb, rxrpc_abort_service_not_offered, -- RX_INVALID_OPERATION, -EOPNOTSUPP); -+ return rxrpc_direct_conn_abort(skb, rxrpc_abort_service_not_offered, -+ RX_INVALID_OPERATION, -EOPNOTSUPP); - unsupported_security: - read_unlock_irq(&local->services_lock); -- return rxrpc_direct_abort(skb, rxrpc_abort_service_not_offered, -- RX_INVALID_OPERATION, -EKEYREJECTED); -+ return rxrpc_direct_conn_abort(skb, rxrpc_abort_service_not_offered, -+ RX_INVALID_OPERATION, -EKEYREJECTED); - no_call: - spin_unlock(&rx->incoming_lock); - read_unlock_irq(&local->services_lock); -diff -purNx .git BPI-Router-Linux-kernel/net/rxrpc/call_object.c BPI-Router-Linux-kernel-6.16.12/net/rxrpc/call_object.c ---- BPI-Router-Linux-kernel/net/rxrpc/call_object.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/rxrpc/call_object.c 2025-10-22 13:53:56.831167617 -0400 -@@ -561,7 +561,7 @@ static void rxrpc_cleanup_rx_buffers(str - void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call) - { - struct rxrpc_connection *conn = call->conn; -- bool put = false, putu = false; -+ bool putu = false; - - _enter("{%d,%d}", call->debug_id, refcount_read(&call->ref)); - -@@ -573,23 +573,13 @@ void rxrpc_release_call(struct rxrpc_soc - - rxrpc_put_call_slot(call); - -- /* Make sure we don't get any more notifications */ -+ /* Note that at this point, the call may still be on or may have been -+ * added back on to the socket receive queue. recvmsg() must discard -+ * released calls. The CALL_RELEASED flag should prevent further -+ * notifications. -+ */ - spin_lock_irq(&rx->recvmsg_lock); -- -- if (!list_empty(&call->recvmsg_link)) { -- _debug("unlinking once-pending call %p { e=%lx f=%lx }", -- call, call->events, call->flags); -- list_del(&call->recvmsg_link); -- put = true; -- } -- -- /* list_empty() must return false in rxrpc_notify_socket() */ -- call->recvmsg_link.next = NULL; -- call->recvmsg_link.prev = NULL; -- - spin_unlock_irq(&rx->recvmsg_lock); -- if (put) -- rxrpc_put_call(call, rxrpc_call_put_unnotify); - - write_lock(&rx->call_lock); - -@@ -638,6 +628,12 @@ void rxrpc_release_calls_on_socket(struc - rxrpc_put_call(call, rxrpc_call_put_release_sock); - } - -+ while ((call = list_first_entry_or_null(&rx->recvmsg_q, -+ struct rxrpc_call, recvmsg_link))) { -+ list_del_init(&call->recvmsg_link); -+ rxrpc_put_call(call, rxrpc_call_put_release_recvmsg_q); -+ } -+ - _leave(""); - } - -diff -purNx .git BPI-Router-Linux-kernel/net/rxrpc/io_thread.c BPI-Router-Linux-kernel-6.16.12/net/rxrpc/io_thread.c ---- BPI-Router-Linux-kernel/net/rxrpc/io_thread.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/rxrpc/io_thread.c 2025-10-22 13:53:56.831167617 -0400 -@@ -97,6 +97,20 @@ bool rxrpc_direct_abort(struct sk_buff * - return false; - } - -+/* -+ * Directly produce a connection abort from a packet. -+ */ -+bool rxrpc_direct_conn_abort(struct sk_buff *skb, enum rxrpc_abort_reason why, -+ s32 abort_code, int err) -+{ -+ struct rxrpc_skb_priv *sp = rxrpc_skb(skb); -+ -+ trace_rxrpc_abort(0, why, sp->hdr.cid, 0, sp->hdr.seq, abort_code, err); -+ skb->mark = RXRPC_SKB_MARK_REJECT_CONN_ABORT; -+ skb->priority = abort_code; -+ return false; -+} -+ - static bool rxrpc_bad_message(struct sk_buff *skb, enum rxrpc_abort_reason why) - { - return rxrpc_direct_abort(skb, why, RX_PROTOCOL_ERROR, -EBADMSG); -diff -purNx .git BPI-Router-Linux-kernel/net/rxrpc/output.c BPI-Router-Linux-kernel-6.16.12/net/rxrpc/output.c ---- BPI-Router-Linux-kernel/net/rxrpc/output.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/rxrpc/output.c 2025-10-22 13:53:56.831167617 -0400 -@@ -814,6 +814,9 @@ void rxrpc_reject_packet(struct rxrpc_lo - __be32 code; - int ret, ioc; - -+ if (sp->hdr.type == RXRPC_PACKET_TYPE_ABORT) -+ return; /* Never abort an abort. */ -+ - rxrpc_see_skb(skb, rxrpc_skb_see_reject); - - iov[0].iov_base = &whdr; -@@ -826,7 +829,13 @@ void rxrpc_reject_packet(struct rxrpc_lo - msg.msg_controllen = 0; - msg.msg_flags = 0; - -- memset(&whdr, 0, sizeof(whdr)); -+ whdr = (struct rxrpc_wire_header) { -+ .epoch = htonl(sp->hdr.epoch), -+ .cid = htonl(sp->hdr.cid), -+ .callNumber = htonl(sp->hdr.callNumber), -+ .serviceId = htons(sp->hdr.serviceId), -+ .flags = ~sp->hdr.flags & RXRPC_CLIENT_INITIATED, -+ }; - - switch (skb->mark) { - case RXRPC_SKB_MARK_REJECT_BUSY: -@@ -834,6 +843,9 @@ void rxrpc_reject_packet(struct rxrpc_lo - size = sizeof(whdr); - ioc = 1; - break; -+ case RXRPC_SKB_MARK_REJECT_CONN_ABORT: -+ whdr.callNumber = 0; -+ fallthrough; - case RXRPC_SKB_MARK_REJECT_ABORT: - whdr.type = RXRPC_PACKET_TYPE_ABORT; - code = htonl(skb->priority); -@@ -847,14 +859,6 @@ void rxrpc_reject_packet(struct rxrpc_lo - if (rxrpc_extract_addr_from_skb(&srx, skb) == 0) { - msg.msg_namelen = srx.transport_len; - -- whdr.epoch = htonl(sp->hdr.epoch); -- whdr.cid = htonl(sp->hdr.cid); -- whdr.callNumber = htonl(sp->hdr.callNumber); -- whdr.serviceId = htons(sp->hdr.serviceId); -- whdr.flags = sp->hdr.flags; -- whdr.flags ^= RXRPC_CLIENT_INITIATED; -- whdr.flags &= RXRPC_CLIENT_INITIATED; -- - iov_iter_kvec(&msg.msg_iter, WRITE, iov, ioc, size); - ret = do_udp_sendmsg(local->socket, &msg, size); - if (ret < 0) -@@ -924,7 +928,7 @@ void rxrpc_send_response(struct rxrpc_co - { - struct rxrpc_skb_priv *sp = rxrpc_skb(response); - struct scatterlist sg[16]; -- struct bio_vec bvec[16]; -+ struct bio_vec *bvec = conn->local->bvec; - struct msghdr msg; - size_t len = sp->resp.len; - __be32 wserial; -@@ -938,6 +942,9 @@ void rxrpc_send_response(struct rxrpc_co - if (ret < 0) - goto fail; - nr_sg = ret; -+ ret = -EIO; -+ if (WARN_ON_ONCE(nr_sg > ARRAY_SIZE(conn->local->bvec))) -+ goto fail; - - for (int i = 0; i < nr_sg; i++) - bvec_set_page(&bvec[i], sg_page(&sg[i]), sg[i].length, sg[i].offset); -diff -purNx .git BPI-Router-Linux-kernel/net/rxrpc/peer_object.c BPI-Router-Linux-kernel-6.16.12/net/rxrpc/peer_object.c ---- BPI-Router-Linux-kernel/net/rxrpc/peer_object.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/rxrpc/peer_object.c 2025-10-22 13:53:56.831167617 -0400 -@@ -149,8 +149,7 @@ struct rxrpc_peer *rxrpc_lookup_peer_rcu - * assess the MTU size for the network interface through which this peer is - * reached - */ --static void rxrpc_assess_MTU_size(struct rxrpc_local *local, -- struct rxrpc_peer *peer) -+void rxrpc_assess_MTU_size(struct rxrpc_local *local, struct rxrpc_peer *peer) - { - struct net *net = local->net; - struct dst_entry *dst; -@@ -277,8 +276,6 @@ static void rxrpc_init_peer(struct rxrpc - - peer->hdrsize += sizeof(struct rxrpc_wire_header); - peer->max_data = peer->if_mtu - peer->hdrsize; -- -- rxrpc_assess_MTU_size(local, peer); - } - - /* -@@ -297,6 +294,7 @@ static struct rxrpc_peer *rxrpc_create_p - if (peer) { - memcpy(&peer->srx, srx, sizeof(*srx)); - rxrpc_init_peer(local, peer, hash_key); -+ rxrpc_assess_MTU_size(local, peer); - } - - _leave(" = %p", peer); -diff -purNx .git BPI-Router-Linux-kernel/net/rxrpc/recvmsg.c BPI-Router-Linux-kernel-6.16.12/net/rxrpc/recvmsg.c ---- BPI-Router-Linux-kernel/net/rxrpc/recvmsg.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/rxrpc/recvmsg.c 2025-10-22 13:53:56.831167617 -0400 -@@ -29,6 +29,10 @@ void rxrpc_notify_socket(struct rxrpc_ca - - if (!list_empty(&call->recvmsg_link)) - return; -+ if (test_bit(RXRPC_CALL_RELEASED, &call->flags)) { -+ rxrpc_see_call(call, rxrpc_call_see_notify_released); -+ return; -+ } - - rcu_read_lock(); - -@@ -447,6 +451,16 @@ try_again: - goto try_again; - } - -+ rxrpc_see_call(call, rxrpc_call_see_recvmsg); -+ if (test_bit(RXRPC_CALL_RELEASED, &call->flags)) { -+ rxrpc_see_call(call, rxrpc_call_see_already_released); -+ list_del_init(&call->recvmsg_link); -+ spin_unlock_irq(&rx->recvmsg_lock); -+ release_sock(&rx->sk); -+ trace_rxrpc_recvmsg(call->debug_id, rxrpc_recvmsg_unqueue, 0); -+ rxrpc_put_call(call, rxrpc_call_put_recvmsg); -+ goto try_again; -+ } - if (!(flags & MSG_PEEK)) - list_del_init(&call->recvmsg_link); - else -@@ -470,8 +484,13 @@ try_again: - - release_sock(&rx->sk); - -- if (test_bit(RXRPC_CALL_RELEASED, &call->flags)) -- BUG(); -+ if (test_bit(RXRPC_CALL_RELEASED, &call->flags)) { -+ rxrpc_see_call(call, rxrpc_call_see_already_released); -+ mutex_unlock(&call->user_mutex); -+ if (!(flags & MSG_PEEK)) -+ rxrpc_put_call(call, rxrpc_call_put_recvmsg); -+ goto try_again; -+ } - - ret = rxrpc_recvmsg_user_id(call, msg, flags); - if (ret < 0) -diff -purNx .git BPI-Router-Linux-kernel/net/rxrpc/rxgk_app.c BPI-Router-Linux-kernel-6.16.12/net/rxrpc/rxgk_app.c ---- BPI-Router-Linux-kernel/net/rxrpc/rxgk_app.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/rxrpc/rxgk_app.c 2025-10-22 13:53:56.831167617 -0400 -@@ -54,6 +54,10 @@ int rxgk_yfs_decode_ticket(struct rxrpc_ - - _enter(""); - -+ if (ticket_len < 10 * sizeof(__be32)) -+ return rxrpc_abort_conn(conn, skb, RXGK_INCONSISTENCY, -EPROTO, -+ rxgk_abort_resp_short_yfs_tkt); -+ - /* Get the session key length */ - ret = skb_copy_bits(skb, ticket_offset, tmp, sizeof(tmp)); - if (ret < 0) -@@ -187,7 +191,7 @@ int rxgk_extract_token(struct rxrpc_conn - struct key *server_key; - unsigned int ticket_offset, ticket_len; - u32 kvno, enctype; -- int ret, ec; -+ int ret, ec = 0; - - struct { - __be32 kvno; -@@ -195,22 +199,23 @@ int rxgk_extract_token(struct rxrpc_conn - __be32 token_len; - } container; - -+ if (token_len < sizeof(container)) -+ goto short_packet; -+ - /* Decode the RXGK_TokenContainer object. This tells us which server - * key we should be using. We can then fetch the key, get the secret - * and set up the crypto to extract the token. - */ - if (skb_copy_bits(skb, token_offset, &container, sizeof(container)) < 0) -- return rxrpc_abort_conn(conn, skb, RXGK_PACKETSHORT, -EPROTO, -- rxgk_abort_resp_tok_short); -+ goto short_packet; - - kvno = ntohl(container.kvno); - enctype = ntohl(container.enctype); - ticket_len = ntohl(container.token_len); - ticket_offset = token_offset + sizeof(container); - -- if (xdr_round_up(ticket_len) > token_len - 3 * 4) -- return rxrpc_abort_conn(conn, skb, RXGK_PACKETSHORT, -EPROTO, -- rxgk_abort_resp_tok_short); -+ if (xdr_round_up(ticket_len) > token_len - sizeof(container)) -+ goto short_packet; - - _debug("KVNO %u", kvno); - _debug("ENC %u", enctype); -@@ -236,9 +241,11 @@ int rxgk_extract_token(struct rxrpc_conn - &ticket_offset, &ticket_len, &ec); - crypto_free_aead(token_enc); - token_enc = NULL; -- if (ret < 0) -- return rxrpc_abort_conn(conn, skb, ec, ret, -- rxgk_abort_resp_tok_dec); -+ if (ret < 0) { -+ if (ret != -ENOMEM) -+ return rxrpc_abort_conn(conn, skb, ec, ret, -+ rxgk_abort_resp_tok_dec); -+ } - - ret = conn->security->default_decode_ticket(conn, skb, ticket_offset, - ticket_len, _key); -@@ -283,4 +290,8 @@ temporary_error: - * also come out this way if the ticket decryption fails. - */ - return ret; -+ -+short_packet: -+ return rxrpc_abort_conn(conn, skb, RXGK_PACKETSHORT, -EPROTO, -+ rxgk_abort_resp_tok_short); - } -diff -purNx .git BPI-Router-Linux-kernel/net/rxrpc/rxgk.c BPI-Router-Linux-kernel-6.16.12/net/rxrpc/rxgk.c ---- BPI-Router-Linux-kernel/net/rxrpc/rxgk.c 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/rxrpc/rxgk.c 2025-10-22 13:53:56.831167617 -0400 -@@ -475,7 +475,7 @@ static int rxgk_verify_packet_integrity( - struct krb5_buffer metadata; - unsigned int offset = sp->offset, len = sp->len; - size_t data_offset = 0, data_len = len; -- u32 ac; -+ u32 ac = 0; - int ret = -ENOMEM; - - _enter(""); -@@ -499,9 +499,10 @@ static int rxgk_verify_packet_integrity( - ret = rxgk_verify_mic_skb(gk->krb5, gk->rx_Kc, &metadata, - skb, &offset, &len, &ac); - kfree(hdr); -- if (ret == -EPROTO) { -- rxrpc_abort_eproto(call, skb, ac, -- rxgk_abort_1_verify_mic_eproto); -+ if (ret < 0) { -+ if (ret != -ENOMEM) -+ rxrpc_abort_eproto(call, skb, ac, -+ rxgk_abort_1_verify_mic_eproto); - } else { - sp->offset = offset; - sp->len = len; -@@ -524,15 +525,16 @@ static int rxgk_verify_packet_encrypted( - struct rxgk_header hdr; - unsigned int offset = sp->offset, len = sp->len; - int ret; -- u32 ac; -+ u32 ac = 0; - - _enter(""); - - ret = rxgk_decrypt_skb(gk->krb5, gk->rx_enc, skb, &offset, &len, &ac); -- if (ret == -EPROTO) -- rxrpc_abort_eproto(call, skb, ac, rxgk_abort_2_decrypt_eproto); -- if (ret < 0) -+ if (ret < 0) { -+ if (ret != -ENOMEM) -+ rxrpc_abort_eproto(call, skb, ac, rxgk_abort_2_decrypt_eproto); - goto error; -+ } - - if (len < sizeof(hdr)) { - ret = rxrpc_abort_eproto(call, skb, RXGK_PACKETSHORT, -diff -purNx .git BPI-Router-Linux-kernel/net/rxrpc/rxgk_common.h BPI-Router-Linux-kernel-6.16.12/net/rxrpc/rxgk_common.h ---- BPI-Router-Linux-kernel/net/rxrpc/rxgk_common.h 2025-10-22 13:53:23.651327038 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/rxrpc/rxgk_common.h 2025-10-22 13:53:56.831167617 -0400 -@@ -88,11 +88,16 @@ int rxgk_decrypt_skb(const struct krb5_e - *_offset += offset; - *_len = len; - break; -+ case -EBADMSG: /* Checksum mismatch. */ - case -EPROTO: -- case -EBADMSG: - *_error_code = RXGK_SEALEDINCON; - break; -+ case -EMSGSIZE: -+ *_error_code = RXGK_PACKETSHORT; -+ break; -+ case -ENOPKG: /* Would prefer RXGK_BADETYPE, but not available for YFS. */ - default: -+ *_error_code = RXGK_INCONSISTENCY; - break; - } - -@@ -127,11 +132,16 @@ int rxgk_verify_mic_skb(const struct krb - *_offset += offset; - *_len = len; - break; -+ case -EBADMSG: /* Checksum mismatch */ - case -EPROTO: -- case -EBADMSG: - *_error_code = RXGK_SEALEDINCON; - break; -+ case -EMSGSIZE: -+ *_error_code = RXGK_PACKETSHORT; -+ break; -+ case -ENOPKG: /* Would prefer RXGK_BADETYPE, but not available for YFS. */ - default: -+ *_error_code = RXGK_INCONSISTENCY; - break; - } - -diff -purNx .git BPI-Router-Linux-kernel/net/rxrpc/security.c BPI-Router-Linux-kernel-6.16.12/net/rxrpc/security.c ---- BPI-Router-Linux-kernel/net/rxrpc/security.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/rxrpc/security.c 2025-10-22 13:53:56.831167617 -0400 -@@ -140,15 +140,15 @@ const struct rxrpc_security *rxrpc_get_i - - sec = rxrpc_security_lookup(sp->hdr.securityIndex); - if (!sec) { -- rxrpc_direct_abort(skb, rxrpc_abort_unsupported_security, -- RX_INVALID_OPERATION, -EKEYREJECTED); -+ rxrpc_direct_conn_abort(skb, rxrpc_abort_unsupported_security, -+ RX_INVALID_OPERATION, -EKEYREJECTED); - return NULL; - } - - if (sp->hdr.securityIndex != RXRPC_SECURITY_NONE && - !rx->securities) { -- rxrpc_direct_abort(skb, rxrpc_abort_no_service_key, -- sec->no_key_abort, -EKEYREJECTED); -+ rxrpc_direct_conn_abort(skb, rxrpc_abort_no_service_key, -+ sec->no_key_abort, -EKEYREJECTED); - return NULL; - } - -diff -purNx .git BPI-Router-Linux-kernel/net/sched/act_ctinfo.c BPI-Router-Linux-kernel-6.16.12/net/sched/act_ctinfo.c ---- BPI-Router-Linux-kernel/net/sched/act_ctinfo.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sched/act_ctinfo.c 2025-10-22 13:53:56.831167617 -0400 -@@ -44,9 +44,9 @@ static void tcf_ctinfo_dscp_set(struct n - ipv4_change_dsfield(ip_hdr(skb), - INET_ECN_MASK, - newdscp); -- ca->stats_dscp_set++; -+ atomic64_inc(&ca->stats_dscp_set); - } else { -- ca->stats_dscp_error++; -+ atomic64_inc(&ca->stats_dscp_error); - } - } - break; -@@ -57,9 +57,9 @@ static void tcf_ctinfo_dscp_set(struct n - ipv6_change_dsfield(ipv6_hdr(skb), - INET_ECN_MASK, - newdscp); -- ca->stats_dscp_set++; -+ atomic64_inc(&ca->stats_dscp_set); - } else { -- ca->stats_dscp_error++; -+ atomic64_inc(&ca->stats_dscp_error); - } - } - break; -@@ -72,7 +72,7 @@ static void tcf_ctinfo_cpmark_set(struct - struct tcf_ctinfo_params *cp, - struct sk_buff *skb) - { -- ca->stats_cpmark_set++; -+ atomic64_inc(&ca->stats_cpmark_set); - skb->mark = READ_ONCE(ct->mark) & cp->cpmarkmask; - } - -@@ -323,15 +323,18 @@ static int tcf_ctinfo_dump(struct sk_buf - } - - if (nla_put_u64_64bit(skb, TCA_CTINFO_STATS_DSCP_SET, -- ci->stats_dscp_set, TCA_CTINFO_PAD)) -+ atomic64_read(&ci->stats_dscp_set), -+ TCA_CTINFO_PAD)) - goto nla_put_failure; - - if (nla_put_u64_64bit(skb, TCA_CTINFO_STATS_DSCP_ERROR, -- ci->stats_dscp_error, TCA_CTINFO_PAD)) -+ atomic64_read(&ci->stats_dscp_error), -+ TCA_CTINFO_PAD)) - goto nla_put_failure; - - if (nla_put_u64_64bit(skb, TCA_CTINFO_STATS_CPMARK_SET, -- ci->stats_cpmark_set, TCA_CTINFO_PAD)) -+ atomic64_read(&ci->stats_cpmark_set), -+ TCA_CTINFO_PAD)) - goto nla_put_failure; - - spin_unlock_bh(&ci->tcf_lock); -diff -purNx .git BPI-Router-Linux-kernel/net/sched/sch_api.c BPI-Router-Linux-kernel-6.16.12/net/sched/sch_api.c ---- BPI-Router-Linux-kernel/net/sched/sch_api.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sched/sch_api.c 2025-10-22 13:53:56.831167617 -0400 -@@ -336,17 +336,22 @@ out: - return q; - } - --static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid) -+static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid, -+ struct netlink_ext_ack *extack) - { - unsigned long cl; - const struct Qdisc_class_ops *cops = p->ops->cl_ops; - -- if (cops == NULL) -- return NULL; -+ if (cops == NULL) { -+ NL_SET_ERR_MSG(extack, "Parent qdisc is not classful"); -+ return ERR_PTR(-EOPNOTSUPP); -+ } - cl = cops->find(p, classid); - -- if (cl == 0) -- return NULL; -+ if (cl == 0) { -+ NL_SET_ERR_MSG(extack, "Specified class not found"); -+ return ERR_PTR(-ENOENT); -+ } - return cops->leaf(p, cl); - } - -@@ -596,16 +601,6 @@ out: - qdisc_skb_cb(skb)->pkt_len = pkt_len; - } - --void qdisc_warn_nonwc(const char *txt, struct Qdisc *qdisc) --{ -- if (!(qdisc->flags & TCQ_F_WARN_NONWC)) { -- pr_warn("%s: %s qdisc %X: is non-work-conserving?\n", -- txt, qdisc->ops->id, qdisc->handle >> 16); -- qdisc->flags |= TCQ_F_WARN_NONWC; -- } --} --EXPORT_SYMBOL(qdisc_warn_nonwc); -- - static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer) - { - struct qdisc_watchdog *wd = container_of(timer, struct qdisc_watchdog, -@@ -780,15 +775,12 @@ static u32 qdisc_alloc_handle(struct net - - void qdisc_tree_reduce_backlog(struct Qdisc *sch, int n, int len) - { -- bool qdisc_is_offloaded = sch->flags & TCQ_F_OFFLOADED; - const struct Qdisc_class_ops *cops; - unsigned long cl; - u32 parentid; - bool notify; - int drops; - -- if (n == 0 && len == 0) -- return; - drops = max_t(int, n, 0); - rcu_read_lock(); - while ((parentid = sch->parent)) { -@@ -797,17 +789,8 @@ void qdisc_tree_reduce_backlog(struct Qd - - if (sch->flags & TCQ_F_NOPARENT) - break; -- /* Notify parent qdisc only if child qdisc becomes empty. -- * -- * If child was empty even before update then backlog -- * counter is screwed and we skip notification because -- * parent class is already passive. -- * -- * If the original child was offloaded then it is allowed -- * to be seem as empty, so the parent is notified anyway. -- */ -- notify = !sch->q.qlen && !WARN_ON_ONCE(!n && -- !qdisc_is_offloaded); -+ /* Notify parent qdisc only if child qdisc becomes empty. */ -+ notify = !sch->q.qlen; - /* TODO: perform the search on a per txq basis */ - sch = qdisc_lookup_rcu(qdisc_dev(sch), TC_H_MAJ(parentid)); - if (sch == NULL) { -@@ -816,6 +799,9 @@ void qdisc_tree_reduce_backlog(struct Qd - } - cops = sch->ops->cl_ops; - if (notify && cops->qlen_notify) { -+ /* Note that qlen_notify must be idempotent as it may get called -+ * multiple times. -+ */ - cl = cops->find(sch, parentid); - cops->qlen_notify(sch, cl); - } -@@ -1499,7 +1485,7 @@ static int __tc_get_qdisc(struct sk_buff - NL_SET_ERR_MSG(extack, "Failed to find qdisc with specified classid"); - return -ENOENT; - } -- q = qdisc_leaf(p, clid); -+ q = qdisc_leaf(p, clid, extack); - } else if (dev_ingress_queue(dev)) { - q = rtnl_dereference(dev_ingress_queue(dev)->qdisc_sleeping); - } -@@ -1510,6 +1496,8 @@ static int __tc_get_qdisc(struct sk_buff - NL_SET_ERR_MSG(extack, "Cannot find specified qdisc on specified device"); - return -ENOENT; - } -+ if (IS_ERR(q)) -+ return PTR_ERR(q); - - if (tcm->tcm_handle && q->handle != tcm->tcm_handle) { - NL_SET_ERR_MSG(extack, "Invalid handle"); -@@ -1611,7 +1599,9 @@ static int __tc_modify_qdisc(struct sk_b - NL_SET_ERR_MSG(extack, "Failed to find specified qdisc"); - return -ENOENT; - } -- q = qdisc_leaf(p, clid); -+ q = qdisc_leaf(p, clid, extack); -+ if (IS_ERR(q)) -+ return PTR_ERR(q); - } else if (dev_ingress_queue_create(dev)) { - q = rtnl_dereference(dev_ingress_queue(dev)->qdisc_sleeping); - } -diff -purNx .git BPI-Router-Linux-kernel/net/sched/sch_cake.c BPI-Router-Linux-kernel-6.16.12/net/sched/sch_cake.c ---- BPI-Router-Linux-kernel/net/sched/sch_cake.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sched/sch_cake.c 2025-10-22 13:53:56.831167617 -0400 -@@ -1747,7 +1747,7 @@ static s32 cake_enqueue(struct sk_buff * - ktime_t now = ktime_get(); - struct cake_tin_data *b; - struct cake_flow *flow; -- u32 idx; -+ u32 idx, tin; - - /* choose flow to insert into */ - idx = cake_classify(sch, &b, skb, q->flow_mode, &ret); -@@ -1757,6 +1757,7 @@ static s32 cake_enqueue(struct sk_buff * - __qdisc_drop(skb, to_free); - return ret; - } -+ tin = (u32)(b - q->tins); - idx--; - flow = &b->flows[idx]; - -@@ -1924,13 +1925,22 @@ static s32 cake_enqueue(struct sk_buff * - q->buffer_max_used = q->buffer_used; - - if (q->buffer_used > q->buffer_limit) { -+ bool same_flow = false; - u32 dropped = 0; -+ u32 drop_id; - - while (q->buffer_used > q->buffer_limit) { - dropped++; -- cake_drop(sch, to_free); -+ drop_id = cake_drop(sch, to_free); -+ -+ if ((drop_id >> 16) == tin && -+ (drop_id & 0xFFFF) == idx) -+ same_flow = true; - } - b->drop_overlimit += dropped; -+ -+ if (same_flow) -+ return NET_XMIT_CN; - } - return NET_XMIT_SUCCESS; - } -diff -purNx .git BPI-Router-Linux-kernel/net/sched/sch_codel.c BPI-Router-Linux-kernel-6.16.12/net/sched/sch_codel.c ---- BPI-Router-Linux-kernel/net/sched/sch_codel.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sched/sch_codel.c 2025-10-22 13:53:56.831167617 -0400 -@@ -101,9 +101,9 @@ static const struct nla_policy codel_pol - static int codel_change(struct Qdisc *sch, struct nlattr *opt, - struct netlink_ext_ack *extack) - { -+ unsigned int dropped_pkts = 0, dropped_bytes = 0; - struct codel_sched_data *q = qdisc_priv(sch); - struct nlattr *tb[TCA_CODEL_MAX + 1]; -- unsigned int qlen, dropped = 0; - int err; - - err = nla_parse_nested_deprecated(tb, TCA_CODEL_MAX, opt, -@@ -142,15 +142,17 @@ static int codel_change(struct Qdisc *sc - WRITE_ONCE(q->params.ecn, - !!nla_get_u32(tb[TCA_CODEL_ECN])); - -- qlen = sch->q.qlen; - while (sch->q.qlen > sch->limit) { - struct sk_buff *skb = qdisc_dequeue_internal(sch, true); - -- dropped += qdisc_pkt_len(skb); -- qdisc_qstats_backlog_dec(sch, skb); -+ if (!skb) -+ break; -+ -+ dropped_pkts++; -+ dropped_bytes += qdisc_pkt_len(skb); - rtnl_qdisc_drop(skb, sch); - } -- qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen, dropped); -+ qdisc_tree_reduce_backlog(sch, dropped_pkts, dropped_bytes); - - sch_tree_unlock(sch); - return 0; -diff -purNx .git BPI-Router-Linux-kernel/net/sched/sch_ets.c BPI-Router-Linux-kernel-6.16.12/net/sched/sch_ets.c ---- BPI-Router-Linux-kernel/net/sched/sch_ets.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sched/sch_ets.c 2025-10-22 13:53:56.831167617 -0400 -@@ -651,6 +651,12 @@ static int ets_qdisc_change(struct Qdisc - - sch_tree_lock(sch); - -+ for (i = nbands; i < oldbands; i++) { -+ if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) -+ list_del_init(&q->classes[i].alist); -+ qdisc_purge_queue(q->classes[i].qdisc); -+ } -+ - WRITE_ONCE(q->nbands, nbands); - for (i = nstrict; i < q->nstrict; i++) { - if (q->classes[i].qdisc->q.qlen) { -@@ -658,11 +664,6 @@ static int ets_qdisc_change(struct Qdisc - q->classes[i].deficit = quanta[i]; - } - } -- for (i = q->nbands; i < oldbands; i++) { -- if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) -- list_del_init(&q->classes[i].alist); -- qdisc_tree_flush_backlog(q->classes[i].qdisc); -- } - WRITE_ONCE(q->nstrict, nstrict); - memcpy(q->prio2band, priomap, sizeof(priomap)); - -diff -purNx .git BPI-Router-Linux-kernel/net/sched/sch_fq.c BPI-Router-Linux-kernel-6.16.12/net/sched/sch_fq.c ---- BPI-Router-Linux-kernel/net/sched/sch_fq.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sched/sch_fq.c 2025-10-22 13:53:56.831167617 -0400 -@@ -1013,11 +1013,11 @@ static int fq_load_priomap(struct fq_sch - static int fq_change(struct Qdisc *sch, struct nlattr *opt, - struct netlink_ext_ack *extack) - { -+ unsigned int dropped_pkts = 0, dropped_bytes = 0; - struct fq_sched_data *q = qdisc_priv(sch); - struct nlattr *tb[TCA_FQ_MAX + 1]; -- int err, drop_count = 0; -- unsigned drop_len = 0; - u32 fq_log; -+ int err; - - err = nla_parse_nested_deprecated(tb, TCA_FQ_MAX, opt, fq_policy, - NULL); -@@ -1135,16 +1135,18 @@ static int fq_change(struct Qdisc *sch, - err = fq_resize(sch, fq_log); - sch_tree_lock(sch); - } -+ - while (sch->q.qlen > sch->limit) { - struct sk_buff *skb = qdisc_dequeue_internal(sch, false); - - if (!skb) - break; -- drop_len += qdisc_pkt_len(skb); -+ -+ dropped_pkts++; -+ dropped_bytes += qdisc_pkt_len(skb); - rtnl_kfree_skbs(skb, skb); -- drop_count++; - } -- qdisc_tree_reduce_backlog(sch, drop_count, drop_len); -+ qdisc_tree_reduce_backlog(sch, dropped_pkts, dropped_bytes); - - sch_tree_unlock(sch); - return err; -diff -purNx .git BPI-Router-Linux-kernel/net/sched/sch_fq_codel.c BPI-Router-Linux-kernel-6.16.12/net/sched/sch_fq_codel.c ---- BPI-Router-Linux-kernel/net/sched/sch_fq_codel.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sched/sch_fq_codel.c 2025-10-22 13:53:56.831167617 -0400 -@@ -366,6 +366,7 @@ static const struct nla_policy fq_codel_ - static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt, - struct netlink_ext_ack *extack) - { -+ unsigned int dropped_pkts = 0, dropped_bytes = 0; - struct fq_codel_sched_data *q = qdisc_priv(sch); - struct nlattr *tb[TCA_FQ_CODEL_MAX + 1]; - u32 quantum = 0; -@@ -443,13 +444,14 @@ static int fq_codel_change(struct Qdisc - q->memory_usage > q->memory_limit) { - struct sk_buff *skb = qdisc_dequeue_internal(sch, false); - -- q->cstats.drop_len += qdisc_pkt_len(skb); -+ if (!skb) -+ break; -+ -+ dropped_pkts++; -+ dropped_bytes += qdisc_pkt_len(skb); - rtnl_kfree_skbs(skb, skb); -- q->cstats.drop_count++; - } -- qdisc_tree_reduce_backlog(sch, q->cstats.drop_count, q->cstats.drop_len); -- q->cstats.drop_count = 0; -- q->cstats.drop_len = 0; -+ qdisc_tree_reduce_backlog(sch, dropped_pkts, dropped_bytes); - - sch_tree_unlock(sch); - return 0; -diff -purNx .git BPI-Router-Linux-kernel/net/sched/sch_fq_pie.c BPI-Router-Linux-kernel-6.16.12/net/sched/sch_fq_pie.c ---- BPI-Router-Linux-kernel/net/sched/sch_fq_pie.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sched/sch_fq_pie.c 2025-10-22 13:53:56.831167617 -0400 -@@ -287,10 +287,9 @@ begin: - static int fq_pie_change(struct Qdisc *sch, struct nlattr *opt, - struct netlink_ext_ack *extack) - { -+ unsigned int dropped_pkts = 0, dropped_bytes = 0; - struct fq_pie_sched_data *q = qdisc_priv(sch); - struct nlattr *tb[TCA_FQ_PIE_MAX + 1]; -- unsigned int len_dropped = 0; -- unsigned int num_dropped = 0; - int err; - - err = nla_parse_nested(tb, TCA_FQ_PIE_MAX, opt, fq_pie_policy, extack); -@@ -368,11 +367,14 @@ static int fq_pie_change(struct Qdisc *s - while (sch->q.qlen > sch->limit) { - struct sk_buff *skb = qdisc_dequeue_internal(sch, false); - -- len_dropped += qdisc_pkt_len(skb); -- num_dropped += 1; -+ if (!skb) -+ break; -+ -+ dropped_pkts++; -+ dropped_bytes += qdisc_pkt_len(skb); - rtnl_kfree_skbs(skb, skb); - } -- qdisc_tree_reduce_backlog(sch, num_dropped, len_dropped); -+ qdisc_tree_reduce_backlog(sch, dropped_pkts, dropped_bytes); - - sch_tree_unlock(sch); - return 0; -diff -purNx .git BPI-Router-Linux-kernel/net/sched/sch_hfsc.c BPI-Router-Linux-kernel-6.16.12/net/sched/sch_hfsc.c ---- BPI-Router-Linux-kernel/net/sched/sch_hfsc.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sched/sch_hfsc.c 2025-10-22 13:53:56.831167617 -0400 -@@ -835,22 +835,6 @@ update_vf(struct hfsc_class *cl, unsigne - } - } - --static unsigned int --qdisc_peek_len(struct Qdisc *sch) --{ -- struct sk_buff *skb; -- unsigned int len; -- -- skb = sch->ops->peek(sch); -- if (unlikely(skb == NULL)) { -- qdisc_warn_nonwc("qdisc_peek_len", sch); -- return 0; -- } -- len = qdisc_pkt_len(skb); -- -- return len; --} -- - static void - hfsc_adjust_levels(struct hfsc_class *cl) - { -diff -purNx .git BPI-Router-Linux-kernel/net/sched/sch_hhf.c BPI-Router-Linux-kernel-6.16.12/net/sched/sch_hhf.c ---- BPI-Router-Linux-kernel/net/sched/sch_hhf.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sched/sch_hhf.c 2025-10-22 13:53:56.831167617 -0400 -@@ -508,9 +508,9 @@ static const struct nla_policy hhf_polic - static int hhf_change(struct Qdisc *sch, struct nlattr *opt, - struct netlink_ext_ack *extack) - { -+ unsigned int dropped_pkts = 0, dropped_bytes = 0; - struct hhf_sched_data *q = qdisc_priv(sch); - struct nlattr *tb[TCA_HHF_MAX + 1]; -- unsigned int qlen, prev_backlog; - int err; - u64 non_hh_quantum; - u32 new_quantum = q->quantum; -@@ -561,15 +561,17 @@ static int hhf_change(struct Qdisc *sch, - usecs_to_jiffies(us)); - } - -- qlen = sch->q.qlen; -- prev_backlog = sch->qstats.backlog; - while (sch->q.qlen > sch->limit) { - struct sk_buff *skb = qdisc_dequeue_internal(sch, false); - -+ if (!skb) -+ break; -+ -+ dropped_pkts++; -+ dropped_bytes += qdisc_pkt_len(skb); - rtnl_kfree_skbs(skb, skb); - } -- qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen, -- prev_backlog - sch->qstats.backlog); -+ qdisc_tree_reduce_backlog(sch, dropped_pkts, dropped_bytes); - - sch_tree_unlock(sch); - return 0; -diff -purNx .git BPI-Router-Linux-kernel/net/sched/sch_htb.c BPI-Router-Linux-kernel-6.16.12/net/sched/sch_htb.c ---- BPI-Router-Linux-kernel/net/sched/sch_htb.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sched/sch_htb.c 2025-10-22 13:53:56.831167617 -0400 -@@ -592,7 +592,7 @@ htb_change_class_mode(struct htb_sched * - */ - static inline void htb_activate(struct htb_sched *q, struct htb_class *cl) - { -- WARN_ON(cl->level || !cl->leaf.q || !cl->leaf.q->q.qlen); -+ WARN_ON(cl->level || !cl->leaf.q); - - if (!cl->prio_activity) { - cl->prio_activity = 1 << cl->prio; -@@ -821,7 +821,9 @@ static struct htb_class *htb_lookup_leaf - u32 *pid; - } stk[TC_HTB_MAXDEPTH], *sp = stk; - -- BUG_ON(!hprio->row.rb_node); -+ if (unlikely(!hprio->row.rb_node)) -+ return NULL; -+ - sp->root = hprio->row.rb_node; - sp->pptr = &hprio->ptr; - sp->pid = &hprio->last_ptr_id; -diff -purNx .git BPI-Router-Linux-kernel/net/sched/sch_mqprio.c BPI-Router-Linux-kernel-6.16.12/net/sched/sch_mqprio.c ---- BPI-Router-Linux-kernel/net/sched/sch_mqprio.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sched/sch_mqprio.c 2025-10-22 13:53:56.831167617 -0400 -@@ -152,7 +152,7 @@ static int mqprio_parse_opt(struct net_d - static const struct - nla_policy mqprio_tc_entry_policy[TCA_MQPRIO_TC_ENTRY_MAX + 1] = { - [TCA_MQPRIO_TC_ENTRY_INDEX] = NLA_POLICY_MAX(NLA_U32, -- TC_QOPT_MAX_QUEUE), -+ TC_QOPT_MAX_QUEUE - 1), - [TCA_MQPRIO_TC_ENTRY_FP] = NLA_POLICY_RANGE(NLA_U32, - TC_FP_EXPRESS, - TC_FP_PREEMPTIBLE), -diff -purNx .git BPI-Router-Linux-kernel/net/sched/sch_netem.c BPI-Router-Linux-kernel-6.16.12/net/sched/sch_netem.c ---- BPI-Router-Linux-kernel/net/sched/sch_netem.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sched/sch_netem.c 2025-10-22 13:53:56.831167617 -0400 -@@ -973,6 +973,41 @@ static int parse_attr(struct nlattr *tb[ - return 0; - } - -+static const struct Qdisc_class_ops netem_class_ops; -+ -+static int check_netem_in_tree(struct Qdisc *sch, bool duplicates, -+ struct netlink_ext_ack *extack) -+{ -+ struct Qdisc *root, *q; -+ unsigned int i; -+ -+ root = qdisc_root_sleeping(sch); -+ -+ if (sch != root && root->ops->cl_ops == &netem_class_ops) { -+ if (duplicates || -+ ((struct netem_sched_data *)qdisc_priv(root))->duplicate) -+ goto err; -+ } -+ -+ if (!qdisc_dev(root)) -+ return 0; -+ -+ hash_for_each(qdisc_dev(root)->qdisc_hash, i, q, hash) { -+ if (sch != q && q->ops->cl_ops == &netem_class_ops) { -+ if (duplicates || -+ ((struct netem_sched_data *)qdisc_priv(q))->duplicate) -+ goto err; -+ } -+ } -+ -+ return 0; -+ -+err: -+ NL_SET_ERR_MSG(extack, -+ "netem: cannot mix duplicating netems with other netems in tree"); -+ return -EINVAL; -+} -+ - /* Parse netlink message to set options */ - static int netem_change(struct Qdisc *sch, struct nlattr *opt, - struct netlink_ext_ack *extack) -@@ -1031,6 +1066,11 @@ static int netem_change(struct Qdisc *sc - q->gap = qopt->gap; - q->counter = 0; - q->loss = qopt->loss; -+ -+ ret = check_netem_in_tree(sch, qopt->duplicate, extack); -+ if (ret) -+ goto unlock; -+ - q->duplicate = qopt->duplicate; - - /* for compatibility with earlier versions. -diff -purNx .git BPI-Router-Linux-kernel/net/sched/sch_pie.c BPI-Router-Linux-kernel-6.16.12/net/sched/sch_pie.c ---- BPI-Router-Linux-kernel/net/sched/sch_pie.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sched/sch_pie.c 2025-10-22 13:53:56.831167617 -0400 -@@ -141,9 +141,9 @@ static const struct nla_policy pie_polic - static int pie_change(struct Qdisc *sch, struct nlattr *opt, - struct netlink_ext_ack *extack) - { -+ unsigned int dropped_pkts = 0, dropped_bytes = 0; - struct pie_sched_data *q = qdisc_priv(sch); - struct nlattr *tb[TCA_PIE_MAX + 1]; -- unsigned int qlen, dropped = 0; - int err; - - err = nla_parse_nested_deprecated(tb, TCA_PIE_MAX, opt, pie_policy, -@@ -193,15 +193,17 @@ static int pie_change(struct Qdisc *sch, - nla_get_u32(tb[TCA_PIE_DQ_RATE_ESTIMATOR])); - - /* Drop excess packets if new limit is lower */ -- qlen = sch->q.qlen; - while (sch->q.qlen > sch->limit) { - struct sk_buff *skb = qdisc_dequeue_internal(sch, true); - -- dropped += qdisc_pkt_len(skb); -- qdisc_qstats_backlog_dec(sch, skb); -+ if (!skb) -+ break; -+ -+ dropped_pkts++; -+ dropped_bytes += qdisc_pkt_len(skb); - rtnl_qdisc_drop(skb, sch); - } -- qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen, dropped); -+ qdisc_tree_reduce_backlog(sch, dropped_pkts, dropped_bytes); - - sch_tree_unlock(sch); - return 0; -diff -purNx .git BPI-Router-Linux-kernel/net/sched/sch_prio.c BPI-Router-Linux-kernel-6.16.12/net/sched/sch_prio.c ---- BPI-Router-Linux-kernel/net/sched/sch_prio.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sched/sch_prio.c 2025-10-22 13:53:56.831167617 -0400 -@@ -211,7 +211,7 @@ static int prio_tune(struct Qdisc *sch, - memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1); - - for (i = q->bands; i < oldbands; i++) -- qdisc_tree_flush_backlog(q->queues[i]); -+ qdisc_purge_queue(q->queues[i]); - - for (i = oldbands; i < q->bands; i++) { - q->queues[i] = queues[i]; -diff -purNx .git BPI-Router-Linux-kernel/net/sched/sch_qfq.c BPI-Router-Linux-kernel-6.16.12/net/sched/sch_qfq.c ---- BPI-Router-Linux-kernel/net/sched/sch_qfq.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sched/sch_qfq.c 2025-10-22 13:53:56.831167617 -0400 -@@ -412,7 +412,7 @@ static int qfq_change_class(struct Qdisc - bool existing = false; - struct nlattr *tb[TCA_QFQ_MAX + 1]; - struct qfq_aggregate *new_agg = NULL; -- u32 weight, lmax, inv_w; -+ u32 weight, lmax, inv_w, old_weight, old_lmax; - int err; - int delta_w; - -@@ -443,12 +443,16 @@ static int qfq_change_class(struct Qdisc - inv_w = ONE_FP / weight; - weight = ONE_FP / inv_w; - -- if (cl != NULL && -- lmax == cl->agg->lmax && -- weight == cl->agg->class_weight) -- return 0; /* nothing to change */ -+ if (cl != NULL) { -+ sch_tree_lock(sch); -+ old_weight = cl->agg->class_weight; -+ old_lmax = cl->agg->lmax; -+ sch_tree_unlock(sch); -+ if (lmax == old_lmax && weight == old_weight) -+ return 0; /* nothing to change */ -+ } - -- delta_w = weight - (cl ? cl->agg->class_weight : 0); -+ delta_w = weight - (cl ? old_weight : 0); - - if (q->wsum + delta_w > QFQ_MAX_WSUM) { - NL_SET_ERR_MSG_FMT_MOD(extack, -@@ -532,9 +536,6 @@ destroy_class: - - static void qfq_destroy_class(struct Qdisc *sch, struct qfq_class *cl) - { -- struct qfq_sched *q = qdisc_priv(sch); -- -- qfq_rm_from_agg(q, cl); - gen_kill_estimator(&cl->rate_est); - qdisc_put(cl->qdisc); - kfree(cl); -@@ -555,6 +556,7 @@ static int qfq_delete_class(struct Qdisc - - qdisc_purge_queue(cl->qdisc); - qdisc_class_hash_remove(&q->clhash, &cl->common); -+ qfq_rm_from_agg(q, cl); - - sch_tree_unlock(sch); - -@@ -625,6 +627,7 @@ static int qfq_dump_class(struct Qdisc * - { - struct qfq_class *cl = (struct qfq_class *)arg; - struct nlattr *nest; -+ u32 class_weight, lmax; - - tcm->tcm_parent = TC_H_ROOT; - tcm->tcm_handle = cl->common.classid; -@@ -633,8 +636,13 @@ static int qfq_dump_class(struct Qdisc * - nest = nla_nest_start_noflag(skb, TCA_OPTIONS); - if (nest == NULL) - goto nla_put_failure; -- if (nla_put_u32(skb, TCA_QFQ_WEIGHT, cl->agg->class_weight) || -- nla_put_u32(skb, TCA_QFQ_LMAX, cl->agg->lmax)) -+ -+ sch_tree_lock(sch); -+ class_weight = cl->agg->class_weight; -+ lmax = cl->agg->lmax; -+ sch_tree_unlock(sch); -+ if (nla_put_u32(skb, TCA_QFQ_WEIGHT, class_weight) || -+ nla_put_u32(skb, TCA_QFQ_LMAX, lmax)) - goto nla_put_failure; - return nla_nest_end(skb, nest); - -@@ -651,8 +659,10 @@ static int qfq_dump_class_stats(struct Q - - memset(&xstats, 0, sizeof(xstats)); - -+ sch_tree_lock(sch); - xstats.weight = cl->agg->class_weight; - xstats.lmax = cl->agg->lmax; -+ sch_tree_unlock(sch); - - if (gnet_stats_copy_basic(d, NULL, &cl->bstats, true) < 0 || - gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 || -@@ -989,7 +999,7 @@ static struct sk_buff *agg_dequeue(struc - - if (cl->qdisc->q.qlen == 0) /* no more packets, remove from list */ - list_del_init(&cl->alist); -- else if (cl->deficit < qdisc_pkt_len(cl->qdisc->ops->peek(cl->qdisc))) { -+ else if (cl->deficit < qdisc_peek_len(cl->qdisc)) { - cl->deficit += agg->lmax; - list_move_tail(&cl->alist, &agg->active); - } -@@ -1491,6 +1501,7 @@ static void qfq_destroy_qdisc(struct Qdi - for (i = 0; i < q->clhash.hashsize; i++) { - hlist_for_each_entry_safe(cl, next, &q->clhash.hash[i], - common.hnode) { -+ qfq_rm_from_agg(q, cl); - qfq_destroy_class(sch, cl); - } - } -diff -purNx .git BPI-Router-Linux-kernel/net/sched/sch_red.c BPI-Router-Linux-kernel-6.16.12/net/sched/sch_red.c ---- BPI-Router-Linux-kernel/net/sched/sch_red.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sched/sch_red.c 2025-10-22 13:53:56.831167617 -0400 -@@ -285,7 +285,7 @@ static int __red_change(struct Qdisc *sc - q->userbits = userbits; - q->limit = ctl->limit; - if (child) { -- qdisc_tree_flush_backlog(q->qdisc); -+ qdisc_purge_queue(q->qdisc); - old_child = q->qdisc; - q->qdisc = child; - } -diff -purNx .git BPI-Router-Linux-kernel/net/sched/sch_sfq.c BPI-Router-Linux-kernel-6.16.12/net/sched/sch_sfq.c ---- BPI-Router-Linux-kernel/net/sched/sch_sfq.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sched/sch_sfq.c 2025-10-22 13:53:56.831167617 -0400 -@@ -310,7 +310,10 @@ drop: - /* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */ - x = q->tail->next; - slot = &q->slots[x]; -- q->tail->next = slot->next; -+ if (slot->next == x) -+ q->tail = NULL; /* no more active slots */ -+ else -+ q->tail->next = slot->next; - q->ht[slot->hash] = SFQ_EMPTY_SLOT; - goto drop; - } -@@ -653,6 +656,14 @@ static int sfq_change(struct Qdisc *sch, - NL_SET_ERR_MSG_MOD(extack, "invalid quantum"); - return -EINVAL; - } -+ -+ if (ctl->perturb_period < 0 || -+ ctl->perturb_period > INT_MAX / HZ) { -+ NL_SET_ERR_MSG_MOD(extack, "invalid perturb period"); -+ return -EINVAL; -+ } -+ perturb_period = ctl->perturb_period * HZ; -+ - if (ctl_v1 && !red_check_params(ctl_v1->qth_min, ctl_v1->qth_max, - ctl_v1->Wlog, ctl_v1->Scell_log, NULL)) - return -EINVAL; -@@ -669,14 +680,12 @@ static int sfq_change(struct Qdisc *sch, - headdrop = q->headdrop; - maxdepth = q->maxdepth; - maxflows = q->maxflows; -- perturb_period = q->perturb_period; - quantum = q->quantum; - flags = q->flags; - - /* update and validate configuration */ - if (ctl->quantum) - quantum = ctl->quantum; -- perturb_period = ctl->perturb_period * HZ; - if (ctl->flows) - maxflows = min_t(u32, ctl->flows, SFQ_MAX_FLOWS); - if (ctl->divisor) { -diff -purNx .git BPI-Router-Linux-kernel/net/sched/sch_taprio.c BPI-Router-Linux-kernel-6.16.12/net/sched/sch_taprio.c ---- BPI-Router-Linux-kernel/net/sched/sch_taprio.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sched/sch_taprio.c 2025-10-22 13:53:56.831167617 -0400 -@@ -43,6 +43,11 @@ static struct static_key_false taprio_ha - #define TAPRIO_SUPPORTED_FLAGS \ - (TCA_TAPRIO_ATTR_FLAG_TXTIME_ASSIST | TCA_TAPRIO_ATTR_FLAG_FULL_OFFLOAD) - #define TAPRIO_FLAGS_INVALID U32_MAX -+/* Minimum value for picos_per_byte to ensure non-zero duration -+ * for minimum-sized Ethernet frames (ETH_ZLEN = 60). -+ * 60 * 17 > PSEC_PER_NSEC (1000) -+ */ -+#define TAPRIO_PICOS_PER_BYTE_MIN 17 - - struct sched_entry { - /* Durations between this GCL entry and the GCL entry where the -@@ -1284,7 +1289,8 @@ static void taprio_start_sched(struct Qd - } - - static void taprio_set_picos_per_byte(struct net_device *dev, -- struct taprio_sched *q) -+ struct taprio_sched *q, -+ struct netlink_ext_ack *extack) - { - struct ethtool_link_ksettings ecmd; - int speed = SPEED_10; -@@ -1300,6 +1306,15 @@ static void taprio_set_picos_per_byte(st - - skip: - picos_per_byte = (USEC_PER_SEC * 8) / speed; -+ if (picos_per_byte < TAPRIO_PICOS_PER_BYTE_MIN) { -+ if (!extack) -+ pr_warn("Link speed %d is too high. Schedule may be inaccurate.\n", -+ speed); -+ NL_SET_ERR_MSG_FMT_MOD(extack, -+ "Link speed %d is too high. Schedule may be inaccurate.", -+ speed); -+ picos_per_byte = TAPRIO_PICOS_PER_BYTE_MIN; -+ } - - atomic64_set(&q->picos_per_byte, picos_per_byte); - netdev_dbg(dev, "taprio: set %s's picos_per_byte to: %lld, linkspeed: %d\n", -@@ -1324,17 +1339,19 @@ static int taprio_dev_notifier(struct no - if (dev != qdisc_dev(q->root)) - continue; - -- taprio_set_picos_per_byte(dev, q); -+ taprio_set_picos_per_byte(dev, q, NULL); - - stab = rtnl_dereference(q->root->stab); - -- oper = rtnl_dereference(q->oper_sched); -+ rcu_read_lock(); -+ oper = rcu_dereference(q->oper_sched); - if (oper) - taprio_update_queue_max_sdu(q, oper, stab); - -- admin = rtnl_dereference(q->admin_sched); -+ admin = rcu_dereference(q->admin_sched); - if (admin) - taprio_update_queue_max_sdu(q, admin, stab); -+ rcu_read_unlock(); - - break; - } -@@ -1846,7 +1863,7 @@ static int taprio_change(struct Qdisc *s - q->flags = taprio_flags; - - /* Needed for length_to_duration() during netlink attribute parsing */ -- taprio_set_picos_per_byte(dev, q); -+ taprio_set_picos_per_byte(dev, q, extack); - - err = taprio_parse_mqprio_opt(dev, mqprio, extack, q->flags); - if (err < 0) -diff -purNx .git BPI-Router-Linux-kernel/net/sched/sch_tbf.c BPI-Router-Linux-kernel-6.16.12/net/sched/sch_tbf.c ---- BPI-Router-Linux-kernel/net/sched/sch_tbf.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sched/sch_tbf.c 2025-10-22 13:53:56.831167617 -0400 -@@ -452,7 +452,7 @@ static int tbf_change(struct Qdisc *sch, - - sch_tree_lock(sch); - if (child) { -- qdisc_tree_flush_backlog(q->qdisc); -+ qdisc_purge_queue(q->qdisc); - old = q->qdisc; - q->qdisc = child; - } -diff -purNx .git BPI-Router-Linux-kernel/net/sctp/input.c BPI-Router-Linux-kernel-6.16.12/net/sctp/input.c ---- BPI-Router-Linux-kernel/net/sctp/input.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sctp/input.c 2025-10-22 13:53:56.831167617 -0400 -@@ -117,7 +117,7 @@ int sctp_rcv(struct sk_buff *skb) - * it's better to just linearize it otherwise crc computing - * takes longer. - */ -- if ((!is_gso && skb_linearize(skb)) || -+ if (((!is_gso || skb_cloned(skb)) && skb_linearize(skb)) || - !pskb_may_pull(skb, sizeof(struct sctphdr))) - goto discard_it; - -@@ -756,7 +756,7 @@ static int __sctp_hash_endpoint(struct s - struct sock *sk2 = ep2->base.sk; - - if (!net_eq(sock_net(sk2), net) || sk2 == sk || -- !uid_eq(sock_i_uid(sk2), sock_i_uid(sk)) || -+ !uid_eq(sk_uid(sk2), sk_uid(sk)) || - !sk2->sk_reuseport) - continue; - -diff -purNx .git BPI-Router-Linux-kernel/net/sctp/ipv6.c BPI-Router-Linux-kernel-6.16.12/net/sctp/ipv6.c ---- BPI-Router-Linux-kernel/net/sctp/ipv6.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sctp/ipv6.c 2025-10-22 13:53:56.835167598 -0400 -@@ -546,7 +546,9 @@ static void sctp_v6_from_sk(union sctp_a - { - addr->v6.sin6_family = AF_INET6; - addr->v6.sin6_port = 0; -+ addr->v6.sin6_flowinfo = 0; - addr->v6.sin6_addr = sk->sk_v6_rcv_saddr; -+ addr->v6.sin6_scope_id = 0; - } - - /* Initialize sk->sk_rcv_saddr from sctp_addr. */ -diff -purNx .git BPI-Router-Linux-kernel/net/sctp/proc.c BPI-Router-Linux-kernel-6.16.12/net/sctp/proc.c ---- BPI-Router-Linux-kernel/net/sctp/proc.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sctp/proc.c 2025-10-22 13:53:56.835167598 -0400 -@@ -177,7 +177,7 @@ static int sctp_eps_seq_show(struct seq_ - seq_printf(seq, "%8pK %8pK %-3d %-3d %-4d %-5d %5u %5lu ", ep, sk, - sctp_sk(sk)->type, sk->sk_state, hash, - ep->base.bind_addr.port, -- from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), -+ from_kuid_munged(seq_user_ns(seq), sk_uid(sk)), - sock_i_ino(sk)); - - sctp_seq_dump_local_addrs(seq, &ep->base); -@@ -267,7 +267,7 @@ static int sctp_assocs_seq_show(struct s - assoc->assoc_id, - assoc->sndbuf_used, - atomic_read(&assoc->rmem_alloc), -- from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), -+ from_kuid_munged(seq_user_ns(seq), sk_uid(sk)), - sock_i_ino(sk), - epb->bind_addr.port, - assoc->peer.port); -diff -purNx .git BPI-Router-Linux-kernel/net/sctp/socket.c BPI-Router-Linux-kernel-6.16.12/net/sctp/socket.c ---- BPI-Router-Linux-kernel/net/sctp/socket.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sctp/socket.c 2025-10-22 13:53:56.835167598 -0400 -@@ -8345,8 +8345,8 @@ static int sctp_get_port_local(struct so - bool reuse = (sk->sk_reuse || sp->reuse); - struct sctp_bind_hashbucket *head; /* hash list */ - struct net *net = sock_net(sk); -- kuid_t uid = sock_i_uid(sk); - struct sctp_bind_bucket *pp; -+ kuid_t uid = sk_uid(sk); - unsigned short snum; - int ret; - -@@ -8444,7 +8444,7 @@ pp_found: - (reuse && (sk2->sk_reuse || sp2->reuse) && - sk2->sk_state != SCTP_SS_LISTENING) || - (sk->sk_reuseport && sk2->sk_reuseport && -- uid_eq(uid, sock_i_uid(sk2)))) -+ uid_eq(uid, sk_uid(sk2)))) - continue; - - if ((!sk->sk_bound_dev_if || !bound_dev_if2 || -diff -purNx .git BPI-Router-Linux-kernel/net/smc/af_smc.c BPI-Router-Linux-kernel-6.16.12/net/smc/af_smc.c ---- BPI-Router-Linux-kernel/net/smc/af_smc.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/smc/af_smc.c 2025-10-22 13:53:56.835167598 -0400 -@@ -30,6 +30,10 @@ - #include - - #include -+#include -+#if IS_ENABLED(CONFIG_IPV6) -+#include -+#endif - #include - #include - #include -@@ -360,6 +364,16 @@ static void smc_destruct(struct sock *sk - return; - if (!sock_flag(sk, SOCK_DEAD)) - return; -+ switch (sk->sk_family) { -+ case AF_INET: -+ inet_sock_destruct(sk); -+ break; -+#if IS_ENABLED(CONFIG_IPV6) -+ case AF_INET6: -+ inet6_sock_destruct(sk); -+ break; -+#endif -+ } - } - - static struct lock_class_key smc_key; -@@ -2554,8 +2568,9 @@ static void smc_listen_work(struct work_ - goto out_decl; - } - -- smc_listen_out_connected(new_smc); - SMC_STAT_SERV_SUCC_INC(sock_net(newclcsock->sk), ini); -+ /* smc_listen_out() will release smcsk */ -+ smc_listen_out_connected(new_smc); - goto out_free; - - out_unlock: -diff -purNx .git BPI-Router-Linux-kernel/net/smc/smc_clc.c BPI-Router-Linux-kernel-6.16.12/net/smc/smc_clc.c ---- BPI-Router-Linux-kernel/net/smc/smc_clc.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/smc/smc_clc.c 2025-10-22 13:53:56.835167598 -0400 -@@ -426,8 +426,6 @@ smc_clc_msg_decl_valid(struct smc_clc_ms - { - struct smc_clc_msg_hdr *hdr = &dclc->hdr; - -- if (hdr->typev1 != SMC_TYPE_R && hdr->typev1 != SMC_TYPE_D) -- return false; - if (hdr->version == SMC_V1) { - if (ntohs(hdr->length) != sizeof(struct smc_clc_msg_decline)) - return false; -diff -purNx .git BPI-Router-Linux-kernel/net/smc/smc_diag.c BPI-Router-Linux-kernel-6.16.12/net/smc/smc_diag.c ---- BPI-Router-Linux-kernel/net/smc/smc_diag.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/smc/smc_diag.c 2025-10-22 13:53:56.835167598 -0400 -@@ -64,7 +64,7 @@ static int smc_diag_msg_attrs_fill(struc - if (nla_put_u8(skb, SMC_DIAG_SHUTDOWN, sk->sk_shutdown)) - return 1; - -- r->diag_uid = from_kuid_munged(user_ns, sock_i_uid(sk)); -+ r->diag_uid = from_kuid_munged(user_ns, sk_uid(sk)); - r->diag_inode = sock_i_ino(sk); - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/net/smc/smc.h BPI-Router-Linux-kernel-6.16.12/net/smc/smc.h ---- BPI-Router-Linux-kernel/net/smc/smc.h 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/smc/smc.h 2025-10-22 13:53:56.835167598 -0400 -@@ -283,10 +283,10 @@ struct smc_connection { - }; - - struct smc_sock { /* smc sock container */ -- struct sock sk; --#if IS_ENABLED(CONFIG_IPV6) -- struct ipv6_pinfo *pinet6; --#endif -+ union { -+ struct sock sk; -+ struct inet_sock icsk_inet; -+ }; - struct socket *clcsock; /* internal tcp socket */ - void (*clcsk_state_change)(struct sock *sk); - /* original stat_change fct. */ -diff -purNx .git BPI-Router-Linux-kernel/net/smc/smc_ib.c BPI-Router-Linux-kernel-6.16.12/net/smc/smc_ib.c ---- BPI-Router-Linux-kernel/net/smc/smc_ib.c 2025-10-22 13:53:23.655327019 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/smc/smc_ib.c 2025-10-22 13:53:56.835167598 -0400 -@@ -742,6 +742,9 @@ bool smc_ib_is_sg_need_sync(struct smc_l - unsigned int i; - bool ret = false; - -+ if (!lnk->smcibdev->ibdev->dma_device) -+ return ret; -+ - /* for now there is just one DMA address */ - for_each_sg(buf_slot->sgt[lnk->link_idx].sgl, sg, - buf_slot->sgt[lnk->link_idx].nents, i) { -diff -purNx .git BPI-Router-Linux-kernel/net/smc/smc_loopback.c BPI-Router-Linux-kernel-6.16.12/net/smc/smc_loopback.c ---- BPI-Router-Linux-kernel/net/smc/smc_loopback.c 2025-10-22 13:53:23.659327000 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/smc/smc_loopback.c 2025-10-22 13:53:56.835167598 -0400 -@@ -56,6 +56,7 @@ static int smc_lo_register_dmb(struct sm - { - struct smc_lo_dmb_node *dmb_node, *tmp_node; - struct smc_lo_dev *ldev = smcd->priv; -+ struct folio *folio; - int sba_idx, rc; - - /* check space for new dmb */ -@@ -74,13 +75,16 @@ static int smc_lo_register_dmb(struct sm - - dmb_node->sba_idx = sba_idx; - dmb_node->len = dmb->dmb_len; -- dmb_node->cpu_addr = kzalloc(dmb_node->len, GFP_KERNEL | -- __GFP_NOWARN | __GFP_NORETRY | -- __GFP_NOMEMALLOC); -- if (!dmb_node->cpu_addr) { -+ -+ /* not critical; fail under memory pressure and fallback to TCP */ -+ folio = folio_alloc(GFP_KERNEL | __GFP_NOWARN | __GFP_NOMEMALLOC | -+ __GFP_NORETRY | __GFP_ZERO, -+ get_order(dmb_node->len)); -+ if (!folio) { - rc = -ENOMEM; - goto err_node; - } -+ dmb_node->cpu_addr = folio_address(folio); - dmb_node->dma_addr = SMC_DMA_ADDR_INVALID; - refcount_set(&dmb_node->refcnt, 1); - -@@ -122,7 +126,7 @@ static void __smc_lo_unregister_dmb(stru - write_unlock_bh(&ldev->dmb_ht_lock); - - clear_bit(dmb_node->sba_idx, ldev->sba_idx_mask); -- kvfree(dmb_node->cpu_addr); -+ folio_put(virt_to_folio(dmb_node->cpu_addr)); - kfree(dmb_node); - - if (atomic_dec_and_test(&ldev->dmb_cnt)) -diff -purNx .git BPI-Router-Linux-kernel/net/socket.c BPI-Router-Linux-kernel-6.16.12/net/socket.c ---- BPI-Router-Linux-kernel/net/socket.c 2025-10-22 13:53:23.659327000 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/socket.c 2025-10-22 13:53:56.835167598 -0400 -@@ -592,10 +592,12 @@ static int sockfs_setattr(struct mnt_idm - if (!err && (iattr->ia_valid & ATTR_UID)) { - struct socket *sock = SOCKET_I(d_inode(dentry)); - -- if (sock->sk) -- sock->sk->sk_uid = iattr->ia_uid; -- else -+ if (sock->sk) { -+ /* Paired with READ_ONCE() in sk_uid() */ -+ WRITE_ONCE(sock->sk->sk_uid, iattr->ia_uid); -+ } else { - err = -ENOENT; -+ } - } - - return err; -diff -purNx .git BPI-Router-Linux-kernel/net/sunrpc/auth_gss/auth_gss.c BPI-Router-Linux-kernel-6.16.12/net/sunrpc/auth_gss/auth_gss.c ---- BPI-Router-Linux-kernel/net/sunrpc/auth_gss/auth_gss.c 2025-10-22 13:53:23.659327000 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sunrpc/auth_gss/auth_gss.c 2025-10-22 13:53:56.835167598 -0400 -@@ -1724,7 +1724,7 @@ gss_validate(struct rpc_task *task, stru - maj_stat = gss_validate_seqno_mic(ctx, task->tk_rqstp->rq_seqnos[0], seq, p, len); - /* RFC 2203 5.3.3.1 - compute the checksum of each sequence number in the cache */ - while (unlikely(maj_stat == GSS_S_BAD_SIG && i < task->tk_rqstp->rq_seqno_count)) -- maj_stat = gss_validate_seqno_mic(ctx, task->tk_rqstp->rq_seqnos[i], seq, p, len); -+ maj_stat = gss_validate_seqno_mic(ctx, task->tk_rqstp->rq_seqnos[i++], seq, p, len); - if (maj_stat == GSS_S_CONTEXT_EXPIRED) - clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); - if (maj_stat) -diff -purNx .git BPI-Router-Linux-kernel/net/sunrpc/sched.c BPI-Router-Linux-kernel-6.16.12/net/sunrpc/sched.c ---- BPI-Router-Linux-kernel/net/sunrpc/sched.c 2025-10-22 13:53:23.659327000 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sunrpc/sched.c 2025-10-22 13:53:56.835167598 -0400 -@@ -276,8 +276,6 @@ EXPORT_SYMBOL_GPL(rpc_destroy_wait_queue - - static int rpc_wait_bit_killable(struct wait_bit_key *key, int mode) - { -- if (unlikely(current->flags & PF_EXITING)) -- return -EINTR; - schedule(); - if (signal_pending_state(mode, current)) - return -ERESTARTSYS; -diff -purNx .git BPI-Router-Linux-kernel/net/sunrpc/svc.c BPI-Router-Linux-kernel-6.16.12/net/sunrpc/svc.c ---- BPI-Router-Linux-kernel/net/sunrpc/svc.c 2025-10-22 13:53:23.659327000 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sunrpc/svc.c 2025-10-22 13:53:56.835167598 -0400 -@@ -638,8 +638,6 @@ EXPORT_SYMBOL_GPL(svc_destroy); - static bool - svc_init_buffer(struct svc_rqst *rqstp, const struct svc_serv *serv, int node) - { -- unsigned long ret; -- - rqstp->rq_maxpages = svc_serv_maxpages(serv); - - /* rq_pages' last entry is NULL for historical reasons. */ -@@ -649,9 +647,7 @@ svc_init_buffer(struct svc_rqst *rqstp, - if (!rqstp->rq_pages) - return false; - -- ret = alloc_pages_bulk_node(GFP_KERNEL, node, rqstp->rq_maxpages, -- rqstp->rq_pages); -- return ret == rqstp->rq_maxpages; -+ return true; - } - - /* -@@ -1375,7 +1371,8 @@ svc_process_common(struct svc_rqst *rqst - case SVC_OK: - break; - case SVC_GARBAGE: -- goto err_garbage_args; -+ rqstp->rq_auth_stat = rpc_autherr_badcred; -+ goto err_bad_auth; - case SVC_SYSERR: - goto err_system_err; - case SVC_DENIED: -@@ -1516,14 +1513,6 @@ err_bad_proc: - *rqstp->rq_accept_statp = rpc_proc_unavail; - goto sendit; - --err_garbage_args: -- svc_printk(rqstp, "failed to decode RPC header\n"); -- -- if (serv->sv_stats) -- serv->sv_stats->rpcbadfmt++; -- *rqstp->rq_accept_statp = rpc_garbage_args; -- goto sendit; -- - err_system_err: - if (serv->sv_stats) - serv->sv_stats->rpcbadfmt++; -diff -purNx .git BPI-Router-Linux-kernel/net/sunrpc/svcsock.c BPI-Router-Linux-kernel-6.16.12/net/sunrpc/svcsock.c ---- BPI-Router-Linux-kernel/net/sunrpc/svcsock.c 2025-10-22 13:53:23.659327000 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sunrpc/svcsock.c 2025-10-22 13:53:56.835167598 -0400 -@@ -257,20 +257,47 @@ svc_tcp_sock_process_cmsg(struct socket - } - - static int --svc_tcp_sock_recv_cmsg(struct svc_sock *svsk, struct msghdr *msg) -+svc_tcp_sock_recv_cmsg(struct socket *sock, unsigned int *msg_flags) - { - union { - struct cmsghdr cmsg; - u8 buf[CMSG_SPACE(sizeof(u8))]; - } u; -- struct socket *sock = svsk->sk_sock; -+ u8 alert[2]; -+ struct kvec alert_kvec = { -+ .iov_base = alert, -+ .iov_len = sizeof(alert), -+ }; -+ struct msghdr msg = { -+ .msg_flags = *msg_flags, -+ .msg_control = &u, -+ .msg_controllen = sizeof(u), -+ }; -+ int ret; -+ -+ iov_iter_kvec(&msg.msg_iter, ITER_DEST, &alert_kvec, 1, -+ alert_kvec.iov_len); -+ ret = sock_recvmsg(sock, &msg, MSG_DONTWAIT); -+ if (ret > 0 && -+ tls_get_record_type(sock->sk, &u.cmsg) == TLS_RECORD_TYPE_ALERT) { -+ iov_iter_revert(&msg.msg_iter, ret); -+ ret = svc_tcp_sock_process_cmsg(sock, &msg, &u.cmsg, -EAGAIN); -+ } -+ return ret; -+} -+ -+static int -+svc_tcp_sock_recvmsg(struct svc_sock *svsk, struct msghdr *msg) -+{ - int ret; -+ struct socket *sock = svsk->sk_sock; - -- msg->msg_control = &u; -- msg->msg_controllen = sizeof(u); - ret = sock_recvmsg(sock, msg, MSG_DONTWAIT); -- if (unlikely(msg->msg_controllen != sizeof(u))) -- ret = svc_tcp_sock_process_cmsg(sock, msg, &u.cmsg, ret); -+ if (msg->msg_flags & MSG_CTRUNC) { -+ msg->msg_flags &= ~(MSG_CTRUNC | MSG_EOR); -+ if (ret == 0 || ret == -EIO) -+ ret = svc_tcp_sock_recv_cmsg(sock, &msg->msg_flags); -+ } - return ret; - } - -@@ -321,7 +348,7 @@ static ssize_t svc_tcp_read_msg(struct s - iov_iter_advance(&msg.msg_iter, seek); - buflen -= seek; - } -- len = svc_tcp_sock_recv_cmsg(svsk, &msg); -+ len = svc_tcp_sock_recvmsg(svsk, &msg); - if (len > 0) - svc_flush_bvec(bvec, len, seek); - -@@ -1018,7 +1045,7 @@ static ssize_t svc_tcp_read_marker(struc - iov.iov_base = ((char *)&svsk->sk_marker) + svsk->sk_tcplen; - iov.iov_len = want; - iov_iter_kvec(&msg.msg_iter, ITER_DEST, &iov, 1, want); -- len = svc_tcp_sock_recv_cmsg(svsk, &msg); -+ len = svc_tcp_sock_recvmsg(svsk, &msg); - if (len < 0) - return len; - svsk->sk_tcplen += len; -diff -purNx .git BPI-Router-Linux-kernel/net/sunrpc/xprtsock.c BPI-Router-Linux-kernel-6.16.12/net/sunrpc/xprtsock.c ---- BPI-Router-Linux-kernel/net/sunrpc/xprtsock.c 2025-10-22 13:53:23.659327000 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/sunrpc/xprtsock.c 2025-10-22 13:53:56.835167598 -0400 -@@ -358,7 +358,7 @@ xs_alloc_sparse_pages(struct xdr_buf *bu - - static int - xs_sock_process_cmsg(struct socket *sock, struct msghdr *msg, -- struct cmsghdr *cmsg, int ret) -+ unsigned int *msg_flags, struct cmsghdr *cmsg, int ret) - { - u8 content_type = tls_get_record_type(sock->sk, cmsg); - u8 level, description; -@@ -371,7 +371,7 @@ xs_sock_process_cmsg(struct socket *sock - * record, even though there might be more frames - * waiting to be decrypted. - */ -- msg->msg_flags &= ~MSG_EOR; -+ *msg_flags &= ~MSG_EOR; - break; - case TLS_RECORD_TYPE_ALERT: - tls_alert_recv(sock->sk, msg, &level, &description); -@@ -386,19 +386,33 @@ xs_sock_process_cmsg(struct socket *sock - } - - static int --xs_sock_recv_cmsg(struct socket *sock, struct msghdr *msg, int flags) -+xs_sock_recv_cmsg(struct socket *sock, unsigned int *msg_flags, int flags) - { - union { - struct cmsghdr cmsg; - u8 buf[CMSG_SPACE(sizeof(u8))]; - } u; -+ u8 alert[2]; -+ struct kvec alert_kvec = { -+ .iov_base = alert, -+ .iov_len = sizeof(alert), -+ }; -+ struct msghdr msg = { -+ .msg_flags = *msg_flags, -+ .msg_control = &u, -+ .msg_controllen = sizeof(u), -+ }; - int ret; - -- msg->msg_control = &u; -- msg->msg_controllen = sizeof(u); -- ret = sock_recvmsg(sock, msg, flags); -- if (msg->msg_controllen != sizeof(u)) -- ret = xs_sock_process_cmsg(sock, msg, &u.cmsg, ret); -+ iov_iter_kvec(&msg.msg_iter, ITER_DEST, &alert_kvec, 1, -+ alert_kvec.iov_len); -+ ret = sock_recvmsg(sock, &msg, flags); -+ if (ret > 0) { -+ if (tls_get_record_type(sock->sk, &u.cmsg) == TLS_RECORD_TYPE_ALERT) -+ iov_iter_revert(&msg.msg_iter, ret); -+ ret = xs_sock_process_cmsg(sock, &msg, msg_flags, &u.cmsg, -+ -EAGAIN); -+ } - return ret; - } - -@@ -408,7 +422,13 @@ xs_sock_recvmsg(struct socket *sock, str - ssize_t ret; - if (seek != 0) - iov_iter_advance(&msg->msg_iter, seek); -- ret = xs_sock_recv_cmsg(sock, msg, flags); -+ ret = sock_recvmsg(sock, msg, flags); -+ /* Handle TLS inband control message lazily */ -+ if (msg->msg_flags & MSG_CTRUNC) { -+ msg->msg_flags &= ~(MSG_CTRUNC | MSG_EOR); -+ if (ret == 0 || ret == -EIO) -+ ret = xs_sock_recv_cmsg(sock, &msg->msg_flags, flags); -+ } - return ret > 0 ? ret + seek : ret; - } - -@@ -434,7 +454,7 @@ xs_read_discard(struct socket *sock, str - size_t count) - { - iov_iter_discard(&msg->msg_iter, ITER_DEST, count); -- return xs_sock_recv_cmsg(sock, msg, flags); -+ return xs_sock_recvmsg(sock, msg, flags, 0); - } - - #if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE -diff -purNx .git BPI-Router-Linux-kernel/net/tipc/socket.c BPI-Router-Linux-kernel-6.16.12/net/tipc/socket.c ---- BPI-Router-Linux-kernel/net/tipc/socket.c 2025-10-22 13:53:23.659327000 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/tipc/socket.c 2025-10-22 13:53:56.835167598 -0400 -@@ -3642,7 +3642,7 @@ int tipc_sk_fill_sock_diag(struct sk_buf - nla_put_u32(skb, TIPC_NLA_SOCK_INO, sock_i_ino(sk)) || - nla_put_u32(skb, TIPC_NLA_SOCK_UID, - from_kuid_munged(sk_user_ns(NETLINK_CB(cb->skb).sk), -- sock_i_uid(sk))) || -+ sk_uid(sk))) || - nla_put_u64_64bit(skb, TIPC_NLA_SOCK_COOKIE, - tipc_diag_gen_cookie(sk), - TIPC_NLA_SOCK_PAD)) -diff -purNx .git BPI-Router-Linux-kernel/net/tipc/topsrv.c BPI-Router-Linux-kernel-6.16.12/net/tipc/topsrv.c ---- BPI-Router-Linux-kernel/net/tipc/topsrv.c 2025-10-22 13:53:23.659327000 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/tipc/topsrv.c 2025-10-22 13:53:56.835167598 -0400 -@@ -704,8 +704,10 @@ static void tipc_topsrv_stop(struct net - for (id = 0; srv->idr_in_use; id++) { - con = idr_find(&srv->conn_idr, id); - if (con) { -+ conn_get(con); - spin_unlock_bh(&srv->idr_lock); - tipc_conn_close(con); -+ conn_put(con); - spin_lock_bh(&srv->idr_lock); - } - } -diff -purNx .git BPI-Router-Linux-kernel/net/tipc/udp_media.c BPI-Router-Linux-kernel-6.16.12/net/tipc/udp_media.c ---- BPI-Router-Linux-kernel/net/tipc/udp_media.c 2025-10-22 13:53:23.659327000 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/tipc/udp_media.c 2025-10-22 13:53:56.835167598 -0400 -@@ -489,7 +489,7 @@ int tipc_udp_nl_dump_remoteip(struct sk_ - - rtnl_lock(); - b = tipc_bearer_find(net, bname); -- if (!b) { -+ if (!b || b->bcast_addr.media_id != TIPC_MEDIA_TYPE_UDP) { - rtnl_unlock(); - return -EINVAL; - } -@@ -500,7 +500,7 @@ int tipc_udp_nl_dump_remoteip(struct sk_ - - rtnl_lock(); - b = rtnl_dereference(tn->bearer_list[bid]); -- if (!b) { -+ if (!b || b->bcast_addr.media_id != TIPC_MEDIA_TYPE_UDP) { - rtnl_unlock(); - return -EINVAL; - } -diff -purNx .git BPI-Router-Linux-kernel/net/tls/tls.h BPI-Router-Linux-kernel-6.16.12/net/tls/tls.h ---- BPI-Router-Linux-kernel/net/tls/tls.h 2025-10-22 13:53:23.659327000 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/tls/tls.h 2025-10-22 13:53:56.835167598 -0400 -@@ -141,6 +141,7 @@ void update_sk_prot(struct sock *sk, str - - int wait_on_pending_writer(struct sock *sk, long *timeo); - void tls_err_abort(struct sock *sk, int err); -+void tls_strp_abort_strp(struct tls_strparser *strp, int err); - - int init_prot_info(struct tls_prot_info *prot, - const struct tls_crypto_info *crypto_info, -@@ -196,7 +197,7 @@ void tls_strp_msg_done(struct tls_strpar - int tls_rx_msg_size(struct tls_strparser *strp, struct sk_buff *skb); - void tls_rx_msg_ready(struct tls_strparser *strp); - --void tls_strp_msg_load(struct tls_strparser *strp, bool force_refresh); -+bool tls_strp_msg_load(struct tls_strparser *strp, bool force_refresh); - int tls_strp_msg_cow(struct tls_sw_context_rx *ctx); - struct sk_buff *tls_strp_msg_detach(struct tls_sw_context_rx *ctx); - int tls_strp_msg_hold(struct tls_strparser *strp, struct sk_buff_head *dst); -diff -purNx .git BPI-Router-Linux-kernel/net/tls/tls_strp.c BPI-Router-Linux-kernel-6.16.12/net/tls/tls_strp.c ---- BPI-Router-Linux-kernel/net/tls/tls_strp.c 2025-10-22 13:53:23.659327000 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/tls/tls_strp.c 2025-10-22 13:53:56.835167598 -0400 -@@ -13,7 +13,7 @@ - - static struct workqueue_struct *tls_strp_wq; - --static void tls_strp_abort_strp(struct tls_strparser *strp, int err) -+void tls_strp_abort_strp(struct tls_strparser *strp, int err) - { - if (strp->stopped) - return; -@@ -211,11 +211,17 @@ static int tls_strp_copyin_frag(struct t - struct sk_buff *in_skb, unsigned int offset, - size_t in_len) - { -+ unsigned int nfrag = skb->len / PAGE_SIZE; - size_t len, chunk; - skb_frag_t *frag; - int sz; - -- frag = &skb_shinfo(skb)->frags[skb->len / PAGE_SIZE]; -+ if (unlikely(nfrag >= skb_shinfo(skb)->nr_frags)) { -+ DEBUG_NET_WARN_ON_ONCE(1); -+ return -EMSGSIZE; -+ } -+ -+ frag = &skb_shinfo(skb)->frags[nfrag]; - - len = in_len; - /* First make sure we got the header */ -@@ -475,7 +481,7 @@ static void tls_strp_load_anchor_with_qu - strp->stm.offset = offset; - } - --void tls_strp_msg_load(struct tls_strparser *strp, bool force_refresh) -+bool tls_strp_msg_load(struct tls_strparser *strp, bool force_refresh) - { - struct strp_msg *rxm; - struct tls_msg *tlm; -@@ -484,8 +490,11 @@ void tls_strp_msg_load(struct tls_strpar - DEBUG_NET_WARN_ON_ONCE(!strp->stm.full_len); - - if (!strp->copy_mode && force_refresh) { -- if (WARN_ON(tcp_inq(strp->sk) < strp->stm.full_len)) -- return; -+ if (unlikely(tcp_inq(strp->sk) < strp->stm.full_len)) { -+ WRITE_ONCE(strp->msg_ready, 0); -+ memset(&strp->stm, 0, sizeof(strp->stm)); -+ return false; -+ } - - tls_strp_load_anchor_with_queue(strp, strp->stm.full_len); - } -@@ -495,6 +504,8 @@ void tls_strp_msg_load(struct tls_strpar - rxm->offset = strp->stm.offset; - tlm = tls_msg(strp->anchor); - tlm->control = strp->mark; -+ -+ return true; - } - - /* Called with lock held on lower socket */ -@@ -512,14 +523,11 @@ static int tls_strp_read_sock(struct tls - if (inq < strp->stm.full_len) - return tls_strp_read_copy(strp, true); - -+ tls_strp_load_anchor_with_queue(strp, inq); - if (!strp->stm.full_len) { -- tls_strp_load_anchor_with_queue(strp, inq); -- - sz = tls_rx_msg_size(strp, strp->anchor); -- if (sz < 0) { -- tls_strp_abort_strp(strp, sz); -+ if (sz < 0) - return sz; -- } - - strp->stm.full_len = sz; - -diff -purNx .git BPI-Router-Linux-kernel/net/tls/tls_sw.c BPI-Router-Linux-kernel-6.16.12/net/tls/tls_sw.c ---- BPI-Router-Linux-kernel/net/tls/tls_sw.c 2025-10-22 13:53:23.659327000 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/tls/tls_sw.c 2025-10-22 13:53:56.835167598 -0400 -@@ -872,6 +872,19 @@ more_data: - delta = msg->sg.size; - psock->eval = sk_psock_msg_verdict(sk, psock, msg); - delta -= msg->sg.size; -+ -+ if ((s32)delta > 0) { -+ /* It indicates that we executed bpf_msg_pop_data(), -+ * causing the plaintext data size to decrease. -+ * Therefore the encrypted data size also needs to -+ * correspondingly decrease. We only need to subtract -+ * delta to calculate the new ciphertext length since -+ * ktls does not support block encryption. -+ */ -+ struct sk_msg *enc = &ctx->open_rec->msg_encrypted; -+ -+ sk_msg_trim(sk, enc, enc->sg.size - delta); -+ } - } - if (msg->cork_bytes && msg->cork_bytes > msg->sg.size && - !enospc && !full_record) { -@@ -1371,7 +1384,8 @@ tls_rx_rec_wait(struct sock *sk, struct - return sock_intr_errno(timeo); - } - -- tls_strp_msg_load(&ctx->strp, released); -+ if (unlikely(!tls_strp_msg_load(&ctx->strp, released))) -+ return tls_rx_rec_wait(sk, psock, nonblock, false); - - return 1; - } -@@ -1794,6 +1808,9 @@ int decrypt_skb(struct sock *sk, struct - return tls_decrypt_sg(sk, NULL, sgout, &darg); - } - -+/* All records returned from a recvmsg() call must have the same type. -+ * 0 is not a valid content type. Use it as "no type reported, yet". -+ */ - static int tls_record_content_type(struct msghdr *msg, struct tls_msg *tlm, - u8 *control) - { -@@ -2037,8 +2054,10 @@ int tls_sw_recvmsg(struct sock *sk, - if (err < 0) - goto end; - -+ /* process_rx_list() will set @control if it processed any records */ - copied = err; -- if (len <= copied || (copied && control != TLS_RECORD_TYPE_DATA) || rx_more) -+ if (len <= copied || rx_more || -+ (control && control != TLS_RECORD_TYPE_DATA)) - goto end; - - target = sock_rcvlowat(sk, flags & MSG_WAITALL, len); -@@ -2455,8 +2474,7 @@ int tls_rx_msg_size(struct tls_strparser - return data_len + TLS_HEADER_SIZE; - - read_failure: -- tls_err_abort(strp->sk, ret); -- -+ tls_strp_abort_strp(strp, ret); - return ret; - } - -diff -purNx .git BPI-Router-Linux-kernel/net/unix/af_unix.c BPI-Router-Linux-kernel-6.16.12/net/unix/af_unix.c ---- BPI-Router-Linux-kernel/net/unix/af_unix.c 2025-10-22 13:53:23.659327000 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/unix/af_unix.c 2025-10-22 13:53:56.835167598 -0400 -@@ -660,6 +660,11 @@ static void unix_sock_destructor(struct - #endif - } - -+static unsigned int unix_skb_len(const struct sk_buff *skb) -+{ -+ return skb->len - UNIXCB(skb).consumed; -+} -+ - static void unix_release_sock(struct sock *sk, int embrion) - { - struct unix_sock *u = unix_sk(sk); -@@ -694,10 +699,16 @@ static void unix_release_sock(struct soc - - if (skpair != NULL) { - if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) { -+ struct sk_buff *skb = skb_peek(&sk->sk_receive_queue); -+ -+#if IS_ENABLED(CONFIG_AF_UNIX_OOB) -+ if (skb && !unix_skb_len(skb)) -+ skb = skb_peek_next(skb, &sk->sk_receive_queue); -+#endif - unix_state_lock(skpair); - /* No more writes */ - WRITE_ONCE(skpair->sk_shutdown, SHUTDOWN_MASK); -- if (!skb_queue_empty_lockless(&sk->sk_receive_queue) || embrion) -+ if (skb || embrion) - WRITE_ONCE(skpair->sk_err, ECONNRESET); - unix_state_unlock(skpair); - skpair->sk_state_change(skpair); -@@ -1971,7 +1982,8 @@ static void unix_maybe_add_creds(struct - if (UNIXCB(skb).pid) - return; - -- if (unix_may_passcred(sk) || unix_may_passcred(other)) { -+ if (unix_may_passcred(sk) || unix_may_passcred(other) || -+ !other->sk_socket) { - UNIXCB(skb).pid = get_pid(task_tgid(current)); - current_uid_gid(&UNIXCB(skb).uid, &UNIXCB(skb).gid); - } -@@ -2660,11 +2672,6 @@ static long unix_stream_data_wait(struct - return timeo; - } - --static unsigned int unix_skb_len(const struct sk_buff *skb) --{ -- return skb->len - UNIXCB(skb).consumed; --} -- - struct unix_stream_read_state { - int (*recv_actor)(struct sk_buff *, int, int, - struct unix_stream_read_state *); -@@ -2679,11 +2686,11 @@ struct unix_stream_read_state { - #if IS_ENABLED(CONFIG_AF_UNIX_OOB) - static int unix_stream_recv_urg(struct unix_stream_read_state *state) - { -+ struct sk_buff *oob_skb, *read_skb = NULL; - struct socket *sock = state->socket; - struct sock *sk = sock->sk; - struct unix_sock *u = unix_sk(sk); - int chunk = 1; -- struct sk_buff *oob_skb; - - mutex_lock(&u->iolock); - unix_state_lock(sk); -@@ -2698,9 +2705,16 @@ static int unix_stream_recv_urg(struct u - - oob_skb = u->oob_skb; - -- if (!(state->flags & MSG_PEEK)) -+ if (!(state->flags & MSG_PEEK)) { - WRITE_ONCE(u->oob_skb, NULL); - -+ if (oob_skb->prev != (struct sk_buff *)&sk->sk_receive_queue && -+ !unix_skb_len(oob_skb->prev)) { -+ read_skb = oob_skb->prev; -+ __skb_unlink(read_skb, &sk->sk_receive_queue); -+ } -+ } -+ - spin_unlock(&sk->sk_receive_queue.lock); - unix_state_unlock(sk); - -@@ -2711,6 +2725,8 @@ static int unix_stream_recv_urg(struct u - - mutex_unlock(&u->iolock); - -+ consume_skb(read_skb); -+ - if (chunk < 0) - return -EFAULT; - -@@ -3681,7 +3697,7 @@ static int bpf_iter_unix_seq_show(struct - goto unlock; - } - -- uid = from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)); -+ uid = from_kuid_munged(seq_user_ns(seq), sk_uid(sk)); - meta.seq = seq; - prog = bpf_iter_get_info(&meta, false); - ret = unix_prog_seq_show(prog, &meta, v, uid); -diff -purNx .git BPI-Router-Linux-kernel/net/unix/diag.c BPI-Router-Linux-kernel-6.16.12/net/unix/diag.c ---- BPI-Router-Linux-kernel/net/unix/diag.c 2025-10-22 13:53:23.659327000 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/unix/diag.c 2025-10-22 13:53:56.835167598 -0400 -@@ -106,7 +106,7 @@ static int sk_diag_show_rqlen(struct soc - static int sk_diag_dump_uid(struct sock *sk, struct sk_buff *nlskb, - struct user_namespace *user_ns) - { -- uid_t uid = from_kuid_munged(user_ns, sock_i_uid(sk)); -+ uid_t uid = from_kuid_munged(user_ns, sk_uid(sk)); - return nla_put(nlskb, UNIX_DIAG_UID, sizeof(uid_t), &uid); - } - -diff -purNx .git BPI-Router-Linux-kernel/net/vmw_vsock/af_vsock.c BPI-Router-Linux-kernel-6.16.12/net/vmw_vsock/af_vsock.c ---- BPI-Router-Linux-kernel/net/vmw_vsock/af_vsock.c 2025-10-22 13:53:23.659327000 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/vmw_vsock/af_vsock.c 2025-10-22 13:53:56.835167598 -0400 -@@ -407,6 +407,8 @@ EXPORT_SYMBOL_GPL(vsock_enqueue_accept); - - static bool vsock_use_local_transport(unsigned int remote_cid) - { -+ lockdep_assert_held(&vsock_register_mutex); -+ - if (!transport_local) - return false; - -@@ -464,6 +466,8 @@ int vsock_assign_transport(struct vsock_ - - remote_flags = vsk->remote_addr.svm_flags; - -+ mutex_lock(&vsock_register_mutex); -+ - switch (sk->sk_type) { - case SOCK_DGRAM: - new_transport = transport_dgram; -@@ -479,12 +483,15 @@ int vsock_assign_transport(struct vsock_ - new_transport = transport_h2g; - break; - default: -- return -ESOCKTNOSUPPORT; -+ ret = -ESOCKTNOSUPPORT; -+ goto err; - } - - if (vsk->transport) { -- if (vsk->transport == new_transport) -- return 0; -+ if (vsk->transport == new_transport) { -+ ret = 0; -+ goto err; -+ } - - /* transport->release() must be called with sock lock acquired. - * This path can only be taken during vsock_connect(), where we -@@ -508,8 +515,16 @@ int vsock_assign_transport(struct vsock_ - /* We increase the module refcnt to prevent the transport unloading - * while there are open sockets assigned to it. - */ -- if (!new_transport || !try_module_get(new_transport->module)) -- return -ENODEV; -+ if (!new_transport || !try_module_get(new_transport->module)) { -+ ret = -ENODEV; -+ goto err; -+ } -+ -+ /* It's safe to release the mutex after a successful try_module_get(). -+ * Whichever transport `new_transport` points at, it won't go away until -+ * the last module_put() below or in vsock_deassign_transport(). -+ */ -+ mutex_unlock(&vsock_register_mutex); - - if (sk->sk_type == SOCK_SEQPACKET) { - if (!new_transport->seqpacket_allow || -@@ -528,12 +543,31 @@ int vsock_assign_transport(struct vsock_ - vsk->transport = new_transport; - - return 0; -+err: -+ mutex_unlock(&vsock_register_mutex); -+ return ret; - } - EXPORT_SYMBOL_GPL(vsock_assign_transport); - -+/* -+ * Provide safe access to static transport_{h2g,g2h,dgram,local} callbacks. -+ * Otherwise we may race with module removal. Do not use on `vsk->transport`. -+ */ -+static u32 vsock_registered_transport_cid(const struct vsock_transport **transport) -+{ -+ u32 cid = VMADDR_CID_ANY; -+ -+ mutex_lock(&vsock_register_mutex); -+ if (*transport) -+ cid = (*transport)->get_local_cid(); -+ mutex_unlock(&vsock_register_mutex); -+ -+ return cid; -+} -+ - bool vsock_find_cid(unsigned int cid) - { -- if (transport_g2h && cid == transport_g2h->get_local_cid()) -+ if (cid == vsock_registered_transport_cid(&transport_g2h)) - return true; - - if (transport_h2g && cid == VMADDR_CID_HOST) -@@ -655,7 +689,8 @@ static int __vsock_bind_connectible(stru - unsigned int i; - - for (i = 0; i < MAX_PORT_RETRIES; i++) { -- if (port <= LAST_RESERVED_PORT) -+ if (port == VMADDR_PORT_ANY || -+ port <= LAST_RESERVED_PORT) - port = LAST_RESERVED_PORT + 1; - - new_addr.svm_port = port++; -@@ -2536,18 +2571,19 @@ static long vsock_dev_do_ioctl(struct fi - unsigned int cmd, void __user *ptr) - { - u32 __user *p = ptr; -- u32 cid = VMADDR_CID_ANY; - int retval = 0; -+ u32 cid; - - switch (cmd) { - case IOCTL_VM_SOCKETS_GET_LOCAL_CID: - /* To be compatible with the VMCI behavior, we prioritize the - * guest CID instead of well-know host CID (VMADDR_CID_HOST). - */ -- if (transport_g2h) -- cid = transport_g2h->get_local_cid(); -- else if (transport_h2g) -- cid = transport_h2g->get_local_cid(); -+ cid = vsock_registered_transport_cid(&transport_g2h); -+ if (cid == VMADDR_CID_ANY) -+ cid = vsock_registered_transport_cid(&transport_h2g); -+ if (cid == VMADDR_CID_ANY) -+ cid = vsock_registered_transport_cid(&transport_local); - - if (put_user(cid, p) != 0) - retval = -EFAULT; -diff -purNx .git BPI-Router-Linux-kernel/net/vmw_vsock/virtio_transport.c BPI-Router-Linux-kernel-6.16.12/net/vmw_vsock/virtio_transport.c ---- BPI-Router-Linux-kernel/net/vmw_vsock/virtio_transport.c 2025-10-22 13:53:23.659327000 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/vmw_vsock/virtio_transport.c 2025-10-22 13:53:56.835167598 -0400 -@@ -307,7 +307,7 @@ out_rcu: - - static void virtio_vsock_rx_fill(struct virtio_vsock *vsock) - { -- int total_len = VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE + VIRTIO_VSOCK_SKB_HEADROOM; -+ int total_len = VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE; - struct scatterlist pkt, *p; - struct virtqueue *vq; - struct sk_buff *skb; -@@ -624,8 +624,9 @@ static void virtio_transport_rx_work(str - do { - virtqueue_disable_cb(vq); - for (;;) { -+ unsigned int len, payload_len; -+ struct virtio_vsock_hdr *hdr; - struct sk_buff *skb; -- unsigned int len; - - if (!virtio_transport_more_replies(vsock)) { - /* Stop rx until the device processes already -@@ -642,11 +643,18 @@ static void virtio_transport_rx_work(str - vsock->rx_buf_nr--; - - /* Drop short/long packets */ -- if (unlikely(len < sizeof(struct virtio_vsock_hdr) || -+ if (unlikely(len < sizeof(*hdr) || - len > virtio_vsock_skb_len(skb))) { - kfree_skb(skb); - continue; - } -+ -+ hdr = virtio_vsock_hdr(skb); -+ payload_len = le32_to_cpu(hdr->len); -+ if (unlikely(payload_len > len - sizeof(*hdr))) { -+ kfree_skb(skb); -+ continue; -+ } - - virtio_vsock_skb_rx_put(skb); - virtio_transport_deliver_tap_pkt(skb); -diff -purNx .git BPI-Router-Linux-kernel/net/vmw_vsock/vmci_transport.c BPI-Router-Linux-kernel-6.16.12/net/vmw_vsock/vmci_transport.c ---- BPI-Router-Linux-kernel/net/vmw_vsock/vmci_transport.c 2025-10-22 13:53:23.659327000 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/vmw_vsock/vmci_transport.c 2025-10-22 13:53:56.835167598 -0400 -@@ -119,6 +119,8 @@ vmci_transport_packet_init(struct vmci_t - u16 proto, - struct vmci_handle handle) - { -+ memset(pkt, 0, sizeof(*pkt)); -+ - /* We register the stream control handler as an any cid handle so we - * must always send from a source address of VMADDR_CID_ANY - */ -@@ -131,8 +133,6 @@ vmci_transport_packet_init(struct vmci_t - pkt->type = type; - pkt->src_port = src->svm_port; - pkt->dst_port = dst->svm_port; -- memset(&pkt->proto, 0, sizeof(pkt->proto)); -- memset(&pkt->_reserved2, 0, sizeof(pkt->_reserved2)); - - switch (pkt->type) { - case VMCI_TRANSPORT_PACKET_TYPE_INVALID: -diff -purNx .git BPI-Router-Linux-kernel/net/wireless/mlme.c BPI-Router-Linux-kernel-6.16.12/net/wireless/mlme.c ---- BPI-Router-Linux-kernel/net/wireless/mlme.c 2025-10-22 13:53:23.659327000 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/wireless/mlme.c 2025-10-22 13:53:56.839167579 -0400 -@@ -850,7 +850,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg8021 - - mgmt = (const struct ieee80211_mgmt *)params->buf; - -- if (!ieee80211_is_mgmt(mgmt->frame_control)) -+ if (!ieee80211_is_mgmt(mgmt->frame_control) || -+ ieee80211_has_order(mgmt->frame_control)) - return -EINVAL; - - stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; -diff -purNx .git BPI-Router-Linux-kernel/net/wireless/nl80211.c BPI-Router-Linux-kernel-6.16.12/net/wireless/nl80211.c ---- BPI-Router-Linux-kernel/net/wireless/nl80211.c 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/wireless/nl80211.c 2025-10-22 13:53:56.839167579 -0400 -@@ -229,6 +229,7 @@ static int validate_beacon_head(const st - unsigned int len = nla_len(attr); - const struct element *elem; - const struct ieee80211_mgmt *mgmt = (void *)data; -+ const struct ieee80211_ext *ext; - unsigned int fixedlen, hdrlen; - bool s1g_bcn; - -@@ -237,8 +238,10 @@ static int validate_beacon_head(const st - - s1g_bcn = ieee80211_is_s1g_beacon(mgmt->frame_control); - if (s1g_bcn) { -- fixedlen = offsetof(struct ieee80211_ext, -- u.s1g_beacon.variable); -+ ext = (struct ieee80211_ext *)mgmt; -+ fixedlen = -+ offsetof(struct ieee80211_ext, u.s1g_beacon.variable) + -+ ieee80211_s1g_optional_len(ext->frame_control); - hdrlen = offsetof(struct ieee80211_ext, u.s1g_beacon); - } else { - fixedlen = offsetof(struct ieee80211_mgmt, -@@ -1583,7 +1586,7 @@ nl80211_parse_connkeys(struct cfg80211_r - - return result; - error: -- kfree(result); -+ kfree_sensitive(result); - return ERR_PTR(err); - } - -@@ -16929,6 +16932,7 @@ static int nl80211_set_sar_specs(struct - if (!sar_spec) - return -ENOMEM; - -+ sar_spec->num_sub_specs = specs; - sar_spec->type = type; - specs = 0; - nla_for_each_nested(spec_list, tb[NL80211_SAR_ATTR_SPECS], rem) { -diff -purNx .git BPI-Router-Linux-kernel/net/wireless/reg.c BPI-Router-Linux-kernel-6.16.12/net/wireless/reg.c ---- BPI-Router-Linux-kernel/net/wireless/reg.c 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/wireless/reg.c 2025-10-22 13:53:56.839167579 -0400 -@@ -4229,6 +4229,8 @@ static void cfg80211_check_and_end_cac(s - struct wireless_dev *wdev; - unsigned int link_id; - -+ guard(wiphy)(&rdev->wiphy); -+ - /* If we finished CAC or received radar, we should end any - * CAC running on the same channels. - * the check !cfg80211_chandef_dfs_usable contain 2 options: -diff -purNx .git BPI-Router-Linux-kernel/net/wireless/scan.c BPI-Router-Linux-kernel-6.16.12/net/wireless/scan.c ---- BPI-Router-Linux-kernel/net/wireless/scan.c 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/wireless/scan.c 2025-10-22 13:53:56.839167579 -0400 -@@ -1905,7 +1905,8 @@ cfg80211_update_known_bss(struct cfg8021 - */ - - f = rcu_access_pointer(new->pub.beacon_ies); -- kfree_rcu((struct cfg80211_bss_ies *)f, rcu_head); -+ if (!new->pub.hidden_beacon_bss) -+ kfree_rcu((struct cfg80211_bss_ies *)f, rcu_head); - return false; - } - -diff -purNx .git BPI-Router-Linux-kernel/net/wireless/sme.c BPI-Router-Linux-kernel-6.16.12/net/wireless/sme.c ---- BPI-Router-Linux-kernel/net/wireless/sme.c 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/wireless/sme.c 2025-10-22 13:53:56.839167579 -0400 -@@ -901,13 +901,16 @@ void __cfg80211_connect_result(struct ne - if (!wdev->u.client.ssid_len) { - rcu_read_lock(); - for_each_valid_link(cr, link) { -+ u32 ssid_len; -+ - ssid = ieee80211_bss_get_elem(cr->links[link].bss, - WLAN_EID_SSID); - - if (!ssid || !ssid->datalen) - continue; - -- memcpy(wdev->u.client.ssid, ssid->data, ssid->datalen); -+ ssid_len = min(ssid->datalen, IEEE80211_MAX_SSID_LEN); -+ memcpy(wdev->u.client.ssid, ssid->data, ssid_len); - wdev->u.client.ssid_len = ssid->datalen; - break; - } -diff -purNx .git BPI-Router-Linux-kernel/net/wireless/util.c BPI-Router-Linux-kernel-6.16.12/net/wireless/util.c ---- BPI-Router-Linux-kernel/net/wireless/util.c 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/wireless/util.c 2025-10-22 13:53:56.839167579 -0400 -@@ -820,6 +820,52 @@ bool ieee80211_is_valid_amsdu(struct sk_ - } - EXPORT_SYMBOL(ieee80211_is_valid_amsdu); - -+ -+/* -+ * Detects if an MSDU frame was maliciously converted into an A-MSDU -+ * frame by an adversary. This is done by parsing the received frame -+ * as if it were a regular MSDU, even though the A-MSDU flag is set. -+ * -+ * For non-mesh interfaces, detection involves checking whether the -+ * payload, when interpreted as an MSDU, begins with a valid RFC1042 -+ * header. This is done by comparing the A-MSDU subheader's destination -+ * address to the start of the RFC1042 header. -+ * -+ * For mesh interfaces, the MSDU includes a 6-byte Mesh Control field -+ * and an optional variable-length Mesh Address Extension field before -+ * the RFC1042 header. The position of the RFC1042 header must therefore -+ * be calculated based on the mesh header length. -+ * -+ * Since this function intentionally parses an A-MSDU frame as an MSDU, -+ * it only assumes that the A-MSDU subframe header is present, and -+ * beyond this it performs its own bounds checks under the assumption -+ * that the frame is instead parsed as a non-aggregated MSDU. -+ */ -+static bool -+is_amsdu_aggregation_attack(struct ethhdr *eth, struct sk_buff *skb, -+ enum nl80211_iftype iftype) -+{ -+ int offset; -+ -+ /* Non-mesh case can be directly compared */ -+ if (iftype != NL80211_IFTYPE_MESH_POINT) -+ return ether_addr_equal(eth->h_dest, rfc1042_header); -+ -+ offset = __ieee80211_get_mesh_hdrlen(eth->h_dest[0]); -+ if (offset == 6) { -+ /* Mesh case with empty address extension field */ -+ return ether_addr_equal(eth->h_source, rfc1042_header); -+ } else if (offset + ETH_ALEN <= skb->len) { -+ /* Mesh case with non-empty address extension field */ -+ u8 temp[ETH_ALEN]; -+ -+ skb_copy_bits(skb, offset, temp, ETH_ALEN); -+ return ether_addr_equal(temp, rfc1042_header); -+ } -+ -+ return false; -+} -+ - void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, - const u8 *addr, enum nl80211_iftype iftype, - const unsigned int extra_headroom, -@@ -861,8 +907,10 @@ void ieee80211_amsdu_to_8023s(struct sk_ - /* the last MSDU has no padding */ - if (subframe_len > remaining) - goto purge; -- /* mitigate A-MSDU aggregation injection attacks */ -- if (ether_addr_equal(hdr.eth.h_dest, rfc1042_header)) -+ /* mitigate A-MSDU aggregation injection attacks, to be -+ * checked when processing first subframe (offset == 0). -+ */ -+ if (offset == 0 && is_amsdu_aggregation_attack(&hdr.eth, skb, iftype)) - goto purge; - - offset += sizeof(struct ethhdr); -diff -purNx .git BPI-Router-Linux-kernel/net/xdp/xsk.c BPI-Router-Linux-kernel-6.16.12/net/xdp/xsk.c ---- BPI-Router-Linux-kernel/net/xdp/xsk.c 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/xdp/xsk.c 2025-10-22 13:53:56.839167579 -0400 -@@ -36,6 +36,20 @@ - #define TX_BATCH_SIZE 32 - #define MAX_PER_SOCKET_BUDGET (TX_BATCH_SIZE) - -+struct xsk_addr_node { -+ u64 addr; -+ struct list_head addr_node; -+}; -+ -+struct xsk_addr_head { -+ u32 num_descs; -+ struct list_head addrs_list; -+}; -+ -+static struct kmem_cache *xsk_tx_generic_cache; -+ -+#define XSKCB(skb) ((struct xsk_addr_head *)((skb)->cb)) -+ - void xsk_set_rx_need_wakeup(struct xsk_buff_pool *pool) - { - if (pool->cached_need_wakeup & XDP_WAKEUP_RX) -@@ -528,24 +542,43 @@ static int xsk_wakeup(struct xdp_sock *x - return dev->netdev_ops->ndo_xsk_wakeup(dev, xs->queue_id, flags); - } - --static int xsk_cq_reserve_addr_locked(struct xsk_buff_pool *pool, u64 addr) -+static int xsk_cq_reserve_locked(struct xsk_buff_pool *pool) - { - unsigned long flags; - int ret; - - spin_lock_irqsave(&pool->cq_lock, flags); -- ret = xskq_prod_reserve_addr(pool->cq, addr); -+ ret = xskq_prod_reserve(pool->cq); - spin_unlock_irqrestore(&pool->cq_lock, flags); - - return ret; - } - --static void xsk_cq_submit_locked(struct xsk_buff_pool *pool, u32 n) -+static void xsk_cq_submit_addr_locked(struct xsk_buff_pool *pool, -+ struct sk_buff *skb) - { -+ struct xsk_addr_node *pos, *tmp; -+ u32 descs_processed = 0; - unsigned long flags; -+ u32 idx; - - spin_lock_irqsave(&pool->cq_lock, flags); -- xskq_prod_submit_n(pool->cq, n); -+ idx = xskq_get_prod(pool->cq); -+ -+ xskq_prod_write_addr(pool->cq, idx, -+ (u64)(uintptr_t)skb_shinfo(skb)->destructor_arg); -+ descs_processed++; -+ -+ if (unlikely(XSKCB(skb)->num_descs > 1)) { -+ list_for_each_entry_safe(pos, tmp, &XSKCB(skb)->addrs_list, addr_node) { -+ xskq_prod_write_addr(pool->cq, idx + descs_processed, -+ pos->addr); -+ descs_processed++; -+ list_del(&pos->addr_node); -+ kmem_cache_free(xsk_tx_generic_cache, pos); -+ } -+ } -+ xskq_prod_submit_n(pool->cq, descs_processed); - spin_unlock_irqrestore(&pool->cq_lock, flags); - } - -@@ -558,9 +591,14 @@ static void xsk_cq_cancel_locked(struct - spin_unlock_irqrestore(&pool->cq_lock, flags); - } - -+static void xsk_inc_num_desc(struct sk_buff *skb) -+{ -+ XSKCB(skb)->num_descs++; -+} -+ - static u32 xsk_get_num_desc(struct sk_buff *skb) - { -- return skb ? (long)skb_shinfo(skb)->destructor_arg : 0; -+ return XSKCB(skb)->num_descs; - } - - static void xsk_destruct_skb(struct sk_buff *skb) -@@ -572,23 +610,33 @@ static void xsk_destruct_skb(struct sk_b - *compl->tx_timestamp = ktime_get_tai_fast_ns(); - } - -- xsk_cq_submit_locked(xdp_sk(skb->sk)->pool, xsk_get_num_desc(skb)); -+ xsk_cq_submit_addr_locked(xdp_sk(skb->sk)->pool, skb); - sock_wfree(skb); - } - --static void xsk_set_destructor_arg(struct sk_buff *skb) -+static void xsk_set_destructor_arg(struct sk_buff *skb, u64 addr) - { -- long num = xsk_get_num_desc(xdp_sk(skb->sk)->skb) + 1; -- -- skb_shinfo(skb)->destructor_arg = (void *)num; -+ BUILD_BUG_ON(sizeof(struct xsk_addr_head) > sizeof(skb->cb)); -+ INIT_LIST_HEAD(&XSKCB(skb)->addrs_list); -+ XSKCB(skb)->num_descs = 0; -+ skb_shinfo(skb)->destructor_arg = (void *)(uintptr_t)addr; - } - - static void xsk_consume_skb(struct sk_buff *skb) - { - struct xdp_sock *xs = xdp_sk(skb->sk); -+ u32 num_descs = xsk_get_num_desc(skb); -+ struct xsk_addr_node *pos, *tmp; -+ -+ if (unlikely(num_descs > 1)) { -+ list_for_each_entry_safe(pos, tmp, &XSKCB(skb)->addrs_list, addr_node) { -+ list_del(&pos->addr_node); -+ kmem_cache_free(xsk_tx_generic_cache, pos); -+ } -+ } - - skb->destructor = sock_wfree; -- xsk_cq_cancel_locked(xs->pool, xsk_get_num_desc(skb)); -+ xsk_cq_cancel_locked(xs->pool, num_descs); - /* Free skb without triggering the perf drop trace */ - consume_skb(skb); - xs->skb = NULL; -@@ -605,6 +653,7 @@ static struct sk_buff *xsk_build_skb_zer - { - struct xsk_buff_pool *pool = xs->pool; - u32 hr, len, ts, offset, copy, copied; -+ struct xsk_addr_node *xsk_addr; - struct sk_buff *skb = xs->skb; - struct page *page; - void *buffer; -@@ -619,6 +668,19 @@ static struct sk_buff *xsk_build_skb_zer - return ERR_PTR(err); - - skb_reserve(skb, hr); -+ -+ xsk_set_destructor_arg(skb, desc->addr); -+ } else { -+ xsk_addr = kmem_cache_zalloc(xsk_tx_generic_cache, GFP_KERNEL); -+ if (!xsk_addr) -+ return ERR_PTR(-ENOMEM); -+ -+ /* in case of -EOVERFLOW that could happen below, -+ * xsk_consume_skb() will release this node as whole skb -+ * would be dropped, which implies freeing all list elements -+ */ -+ xsk_addr->addr = desc->addr; -+ list_add_tail(&xsk_addr->addr_node, &XSKCB(skb)->addrs_list); - } - - addr = desc->addr; -@@ -690,8 +752,11 @@ static struct sk_buff *xsk_build_skb(str - err = skb_store_bits(skb, 0, buffer, len); - if (unlikely(err)) - goto free_err; -+ -+ xsk_set_destructor_arg(skb, desc->addr); - } else { - int nr_frags = skb_shinfo(skb)->nr_frags; -+ struct xsk_addr_node *xsk_addr; - struct page *page; - u8 *vaddr; - -@@ -706,12 +771,22 @@ static struct sk_buff *xsk_build_skb(str - goto free_err; - } - -+ xsk_addr = kmem_cache_zalloc(xsk_tx_generic_cache, GFP_KERNEL); -+ if (!xsk_addr) { -+ __free_page(page); -+ err = -ENOMEM; -+ goto free_err; -+ } -+ - vaddr = kmap_local_page(page); - memcpy(vaddr, buffer, len); - kunmap_local(vaddr); - - skb_add_rx_frag(skb, nr_frags, page, 0, len, PAGE_SIZE); - refcount_add(PAGE_SIZE, &xs->sk.sk_wmem_alloc); -+ -+ xsk_addr->addr = desc->addr; -+ list_add_tail(&xsk_addr->addr_node, &XSKCB(skb)->addrs_list); - } - - if (first_frag && desc->options & XDP_TX_METADATA) { -@@ -755,7 +830,7 @@ static struct sk_buff *xsk_build_skb(str - skb->mark = READ_ONCE(xs->sk.sk_mark); - skb->destructor = xsk_destruct_skb; - xsk_tx_metadata_to_compl(meta, &skb_shinfo(skb)->xsk_meta); -- xsk_set_destructor_arg(skb); -+ xsk_inc_num_desc(skb); - - return skb; - -@@ -765,7 +840,7 @@ free_err: - - if (err == -EOVERFLOW) { - /* Drop the packet */ -- xsk_set_destructor_arg(xs->skb); -+ xsk_inc_num_desc(xs->skb); - xsk_drop_skb(xs->skb); - xskq_cons_release(xs->tx); - } else { -@@ -807,7 +882,7 @@ static int __xsk_generic_xmit(struct soc - * if there is space in it. This avoids having to implement - * any buffering in the Tx path. - */ -- err = xsk_cq_reserve_addr_locked(xs->pool, desc.addr); -+ err = xsk_cq_reserve_locked(xs->pool); - if (err) { - err = -EAGAIN; - goto out; -@@ -1795,8 +1870,18 @@ static int __init xsk_init(void) - if (err) - goto out_pernet; - -+ xsk_tx_generic_cache = kmem_cache_create("xsk_generic_xmit_cache", -+ sizeof(struct xsk_addr_node), -+ 0, SLAB_HWCACHE_ALIGN, NULL); -+ if (!xsk_tx_generic_cache) { -+ err = -ENOMEM; -+ goto out_unreg_notif; -+ } -+ - return 0; - -+out_unreg_notif: -+ unregister_netdevice_notifier(&xsk_netdev_notifier); - out_pernet: - unregister_pernet_subsys(&xsk_net_ops); - out_sk: -diff -purNx .git BPI-Router-Linux-kernel/net/xdp/xsk_diag.c BPI-Router-Linux-kernel-6.16.12/net/xdp/xsk_diag.c ---- BPI-Router-Linux-kernel/net/xdp/xsk_diag.c 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/xdp/xsk_diag.c 2025-10-22 13:53:56.839167579 -0400 -@@ -119,7 +119,7 @@ static int xsk_diag_fill(struct sock *sk - - if ((req->xdiag_show & XDP_SHOW_INFO) && - nla_put_u32(nlskb, XDP_DIAG_UID, -- from_kuid_munged(user_ns, sock_i_uid(sk)))) -+ from_kuid_munged(user_ns, sk_uid(sk)))) - goto out_nlmsg_trim; - - if ((req->xdiag_show & XDP_SHOW_RING_CFG) && -diff -purNx .git BPI-Router-Linux-kernel/net/xdp/xsk_queue.h BPI-Router-Linux-kernel-6.16.12/net/xdp/xsk_queue.h ---- BPI-Router-Linux-kernel/net/xdp/xsk_queue.h 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/xdp/xsk_queue.h 2025-10-22 13:53:56.839167579 -0400 -@@ -344,6 +344,11 @@ static inline u32 xskq_cons_present_entr - - /* Functions for producers */ - -+static inline u32 xskq_get_prod(struct xsk_queue *q) -+{ -+ return READ_ONCE(q->ring->producer); -+} -+ - static inline u32 xskq_prod_nb_free(struct xsk_queue *q, u32 max) - { - u32 free_entries = q->nentries - (q->cached_prod - q->cached_cons); -@@ -390,6 +395,13 @@ static inline int xskq_prod_reserve_addr - return 0; - } - -+static inline void xskq_prod_write_addr(struct xsk_queue *q, u32 idx, u64 addr) -+{ -+ struct xdp_umem_ring *ring = (struct xdp_umem_ring *)q->ring; -+ -+ ring->desc[idx & q->ring_mask] = addr; -+} -+ - static inline void xskq_prod_write_addr_batch(struct xsk_queue *q, struct xdp_desc *descs, - u32 nb_entries) - { -diff -purNx .git BPI-Router-Linux-kernel/net/xfrm/xfrm_device.c BPI-Router-Linux-kernel-6.16.12/net/xfrm/xfrm_device.c ---- BPI-Router-Linux-kernel/net/xfrm/xfrm_device.c 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/xfrm/xfrm_device.c 2025-10-22 13:53:56.839167579 -0400 -@@ -155,7 +155,8 @@ struct sk_buff *validate_xmit_xfrm(struc - return skb; - } - -- if (skb_is_gso(skb) && unlikely(xmit_xfrm_check_overflow(skb))) { -+ if (skb_is_gso(skb) && (unlikely(x->xso.dev != dev) || -+ unlikely(xmit_xfrm_check_overflow(skb)))) { - struct sk_buff *segs; - - /* Packet got rerouted, fixup features and segment it. */ -@@ -305,7 +306,6 @@ int xfrm_dev_state_add(struct net *net, - return -EINVAL; - } - -- xfrm_set_type_offload(x); - if (!x->type_offload) { - NL_SET_ERR_MSG(extack, "Type doesn't support offload"); - dev_put(dev); -@@ -416,10 +416,12 @@ bool xfrm_dev_offload_ok(struct sk_buff - struct net_device *dev = x->xso.dev; - bool check_tunnel_size; - -- if (x->xso.type == XFRM_DEV_OFFLOAD_UNSPECIFIED) -+ if (!x->type_offload || -+ (x->xso.type == XFRM_DEV_OFFLOAD_UNSPECIFIED && x->encap)) - return false; - -- if ((dev == xfrm_dst_path(dst)->dev) && !xdst->child->xfrm) { -+ if ((!dev || dev == xfrm_dst_path(dst)->dev) && -+ !xdst->child->xfrm) { - mtu = xfrm_state_mtu(x, xdst->child_mtu_cached); - if (skb->len <= mtu) - goto ok; -@@ -431,9 +433,12 @@ bool xfrm_dev_offload_ok(struct sk_buff - return false; - - ok: -+ if (!dev) -+ return true; -+ - check_tunnel_size = x->xso.type == XFRM_DEV_OFFLOAD_PACKET && - x->props.mode == XFRM_MODE_TUNNEL; -- switch (x->props.family) { -+ switch (x->inner_mode.family) { - case AF_INET: - /* Check for IPv4 options */ - if (ip_hdr(skb)->ihl != 5) -diff -purNx .git BPI-Router-Linux-kernel/net/xfrm/xfrm_interface_core.c BPI-Router-Linux-kernel-6.16.12/net/xfrm/xfrm_interface_core.c ---- BPI-Router-Linux-kernel/net/xfrm/xfrm_interface_core.c 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/xfrm/xfrm_interface_core.c 2025-10-22 13:53:56.839167579 -0400 -@@ -875,7 +875,7 @@ static int xfrmi_changelink(struct net_d - return -EINVAL; - } - -- if (p.collect_md) { -+ if (p.collect_md || xi->p.collect_md) { - NL_SET_ERR_MSG(extack, "collect_md can't be changed"); - return -EINVAL; - } -@@ -886,11 +886,6 @@ static int xfrmi_changelink(struct net_d - } else { - if (xi->dev != dev) - return -EEXIST; -- if (xi->p.collect_md) { -- NL_SET_ERR_MSG(extack, -- "device can't be changed to collect_md"); -- return -EINVAL; -- } - } - - return xfrmi_update(xi, &p); -diff -purNx .git BPI-Router-Linux-kernel/net/xfrm/xfrm_ipcomp.c BPI-Router-Linux-kernel-6.16.12/net/xfrm/xfrm_ipcomp.c ---- BPI-Router-Linux-kernel/net/xfrm/xfrm_ipcomp.c 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/xfrm/xfrm_ipcomp.c 2025-10-22 13:53:56.839167579 -0400 -@@ -97,7 +97,7 @@ static int ipcomp_input_done2(struct sk_ - struct ip_comp_hdr *ipch = ip_comp_hdr(skb); - const int plen = skb->len; - -- skb_reset_transport_header(skb); -+ skb->transport_header = skb->network_header + sizeof(*ipch); - - return ipcomp_post_acomp(skb, err, 0) ?: - skb->len < (plen + sizeof(ip_comp_hdr)) ? -EINVAL : -@@ -313,7 +313,6 @@ void ipcomp_destroy(struct xfrm_state *x - struct ipcomp_data *ipcd = x->data; - if (!ipcd) - return; -- xfrm_state_delete_tunnel(x); - ipcomp_free_data(ipcd); - kfree(ipcd); - } -diff -purNx .git BPI-Router-Linux-kernel/net/xfrm/xfrm_state.c BPI-Router-Linux-kernel-6.16.12/net/xfrm/xfrm_state.c ---- BPI-Router-Linux-kernel/net/xfrm/xfrm_state.c 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/xfrm/xfrm_state.c 2025-10-22 13:53:56.839167579 -0400 -@@ -424,11 +424,10 @@ void xfrm_unregister_type_offload(const - } - EXPORT_SYMBOL(xfrm_unregister_type_offload); - --void xfrm_set_type_offload(struct xfrm_state *x) -+void xfrm_set_type_offload(struct xfrm_state *x, bool try_load) - { - const struct xfrm_type_offload *type = NULL; - struct xfrm_state_afinfo *afinfo; -- bool try_load = true; - - retry: - afinfo = xfrm_state_get_afinfo(x->props.family); -@@ -593,7 +592,7 @@ void xfrm_state_free(struct xfrm_state * - } - EXPORT_SYMBOL(xfrm_state_free); - --static void ___xfrm_state_destroy(struct xfrm_state *x) -+static void xfrm_state_gc_destroy(struct xfrm_state *x) - { - if (x->mode_cbs && x->mode_cbs->destroy_state) - x->mode_cbs->destroy_state(x); -@@ -607,6 +606,7 @@ static void ___xfrm_state_destroy(struct - kfree(x->coaddr); - kfree(x->replay_esn); - kfree(x->preplay_esn); -+ xfrm_unset_type_offload(x); - if (x->type) { - x->type->destructor(x); - xfrm_put_type(x->type); -@@ -631,7 +631,7 @@ static void xfrm_state_gc_task(struct wo - synchronize_rcu(); - - hlist_for_each_entry_safe(x, tmp, &gc_list, gclist) -- ___xfrm_state_destroy(x); -+ xfrm_state_gc_destroy(x); - } - - static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me) -@@ -780,8 +780,6 @@ void xfrm_dev_state_free(struct xfrm_sta - struct xfrm_dev_offload *xso = &x->xso; - struct net_device *dev = READ_ONCE(xso->dev); - -- xfrm_unset_type_offload(x); -- - if (dev && dev->xfrmdev_ops) { - spin_lock_bh(&xfrm_state_dev_gc_lock); - if (!hlist_unhashed(&x->dev_gclist)) -@@ -797,22 +795,18 @@ void xfrm_dev_state_free(struct xfrm_sta - } - #endif - --void __xfrm_state_destroy(struct xfrm_state *x, bool sync) -+void __xfrm_state_destroy(struct xfrm_state *x) - { - WARN_ON(x->km.state != XFRM_STATE_DEAD); - -- if (sync) { -- synchronize_rcu(); -- ___xfrm_state_destroy(x); -- } else { -- spin_lock_bh(&xfrm_state_gc_lock); -- hlist_add_head(&x->gclist, &xfrm_state_gc_list); -- spin_unlock_bh(&xfrm_state_gc_lock); -- schedule_work(&xfrm_state_gc_work); -- } -+ spin_lock_bh(&xfrm_state_gc_lock); -+ hlist_add_head(&x->gclist, &xfrm_state_gc_list); -+ spin_unlock_bh(&xfrm_state_gc_lock); -+ schedule_work(&xfrm_state_gc_work); - } - EXPORT_SYMBOL(__xfrm_state_destroy); - -+static void xfrm_state_delete_tunnel(struct xfrm_state *x); - int __xfrm_state_delete(struct xfrm_state *x) - { - struct net *net = xs_net(x); -@@ -840,6 +834,8 @@ int __xfrm_state_delete(struct xfrm_stat - - xfrm_dev_state_delete(x); - -+ xfrm_state_delete_tunnel(x); -+ - /* All xfrm_state objects are created by xfrm_state_alloc. - * The xfrm_state_alloc call gives a reference, and that - * is what we are dropping here. -@@ -921,7 +917,7 @@ xfrm_dev_state_flush_secctx_check(struct - } - #endif - --int xfrm_state_flush(struct net *net, u8 proto, bool task_valid, bool sync) -+int xfrm_state_flush(struct net *net, u8 proto, bool task_valid) - { - int i, err = 0, cnt = 0; - -@@ -943,10 +939,7 @@ restart: - err = xfrm_state_delete(x); - xfrm_audit_state_delete(x, err ? 0 : 1, - task_valid); -- if (sync) -- xfrm_state_put_sync(x); -- else -- xfrm_state_put(x); -+ xfrm_state_put(x); - if (!err) - cnt++; - -@@ -1307,14 +1300,8 @@ static void xfrm_hash_grow_check(struct - static void xfrm_state_look_at(struct xfrm_policy *pol, struct xfrm_state *x, - const struct flowi *fl, unsigned short family, - struct xfrm_state **best, int *acq_in_progress, -- int *error) -+ int *error, unsigned int pcpu_id) - { -- /* We need the cpu id just as a lookup key, -- * we don't require it to be stable. -- */ -- unsigned int pcpu_id = get_cpu(); -- put_cpu(); -- - /* Resolution logic: - * 1. There is a valid state with matching selector. Done. - * 2. Valid state with inappropriate selector. Skip. -@@ -1381,14 +1368,15 @@ xfrm_state_find(const xfrm_address_t *da - /* We need the cpu id just as a lookup key, - * we don't require it to be stable. - */ -- pcpu_id = get_cpu(); -- put_cpu(); -+ pcpu_id = raw_smp_processor_id(); - - to_put = NULL; - - sequence = read_seqcount_begin(&net->xfrm.xfrm_state_hash_generation); - - rcu_read_lock(); -+ xfrm_hash_ptrs_get(net, &state_ptrs); -+ - hlist_for_each_entry_rcu(x, &pol->state_cache_list, state_cache) { - if (x->props.family == encap_family && - x->props.reqid == tmpl->reqid && -@@ -1400,7 +1388,7 @@ xfrm_state_find(const xfrm_address_t *da - tmpl->id.proto == x->id.proto && - (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) - xfrm_state_look_at(pol, x, fl, encap_family, -- &best, &acquire_in_progress, &error); -+ &best, &acquire_in_progress, &error, pcpu_id); - } - - if (best) -@@ -1417,7 +1405,7 @@ xfrm_state_find(const xfrm_address_t *da - tmpl->id.proto == x->id.proto && - (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) - xfrm_state_look_at(pol, x, fl, family, -- &best, &acquire_in_progress, &error); -+ &best, &acquire_in_progress, &error, pcpu_id); - } - - cached: -@@ -1429,8 +1417,6 @@ cached: - else if (acquire_in_progress) /* XXX: acquire_in_progress should not happen */ - WARN_ON(1); - -- xfrm_hash_ptrs_get(net, &state_ptrs); -- - h = __xfrm_dst_hash(daddr, saddr, tmpl->reqid, encap_family, state_ptrs.hmask); - hlist_for_each_entry_rcu(x, state_ptrs.bydst + h, bydst) { - #ifdef CONFIG_XFRM_OFFLOAD -@@ -1460,7 +1446,7 @@ cached: - tmpl->id.proto == x->id.proto && - (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) - xfrm_state_look_at(pol, x, fl, family, -- &best, &acquire_in_progress, &error); -+ &best, &acquire_in_progress, &error, pcpu_id); - } - if (best || acquire_in_progress) - goto found; -@@ -1495,7 +1481,7 @@ cached: - tmpl->id.proto == x->id.proto && - (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) - xfrm_state_look_at(pol, x, fl, family, -- &best, &acquire_in_progress, &error); -+ &best, &acquire_in_progress, &error, pcpu_id); - } - - found: -@@ -1711,6 +1697,26 @@ struct xfrm_state *xfrm_state_lookup_bys - } - EXPORT_SYMBOL(xfrm_state_lookup_byspi); - -+static struct xfrm_state *xfrm_state_lookup_spi_proto(struct net *net, __be32 spi, u8 proto) -+{ -+ struct xfrm_state *x; -+ unsigned int i; -+ -+ rcu_read_lock(); -+ for (i = 0; i <= net->xfrm.state_hmask; i++) { -+ hlist_for_each_entry_rcu(x, &net->xfrm.state_byspi[i], byspi) { -+ if (x->id.spi == spi && x->id.proto == proto) { -+ if (!xfrm_state_hold_rcu(x)) -+ continue; -+ rcu_read_unlock(); -+ return x; -+ } -+ } -+ } -+ rcu_read_unlock(); -+ return NULL; -+} -+ - static void __xfrm_state_insert(struct xfrm_state *x) - { - struct net *net = xs_net(x); -@@ -2555,10 +2561,8 @@ int xfrm_alloc_spi(struct xfrm_state *x, - unsigned int h; - struct xfrm_state *x0; - int err = -ENOENT; -- __be32 minspi = htonl(low); -- __be32 maxspi = htonl(high); -+ u32 range = high - low + 1; - __be32 newspi = 0; -- u32 mark = x->mark.v & x->mark.m; - - spin_lock_bh(&x->lock); - if (x->km.state == XFRM_STATE_DEAD) { -@@ -2572,38 +2576,37 @@ int xfrm_alloc_spi(struct xfrm_state *x, - - err = -ENOENT; - -- if (minspi == maxspi) { -- x0 = xfrm_state_lookup(net, mark, &x->id.daddr, minspi, x->id.proto, x->props.family); -- if (x0) { -- NL_SET_ERR_MSG(extack, "Requested SPI is already in use"); -- xfrm_state_put(x0); -+ for (h = 0; h < range; h++) { -+ u32 spi = (low == high) ? low : get_random_u32_inclusive(low, high); -+ if (spi == 0) -+ goto next; -+ newspi = htonl(spi); -+ -+ spin_lock_bh(&net->xfrm.xfrm_state_lock); -+ x0 = xfrm_state_lookup_spi_proto(net, newspi, x->id.proto); -+ if (!x0) { -+ x->id.spi = newspi; -+ h = xfrm_spi_hash(net, &x->id.daddr, newspi, x->id.proto, x->props.family); -+ XFRM_STATE_INSERT(byspi, &x->byspi, net->xfrm.state_byspi + h, x->xso.type); -+ spin_unlock_bh(&net->xfrm.xfrm_state_lock); -+ err = 0; - goto unlock; - } -- newspi = minspi; -- } else { -- u32 spi = 0; -- for (h = 0; h < high-low+1; h++) { -- spi = get_random_u32_inclusive(low, high); -- x0 = xfrm_state_lookup(net, mark, &x->id.daddr, htonl(spi), x->id.proto, x->props.family); -- if (x0 == NULL) { -- newspi = htonl(spi); -- break; -- } -- xfrm_state_put(x0); -+ xfrm_state_put(x0); -+ spin_unlock_bh(&net->xfrm.xfrm_state_lock); -+ -+next: -+ if (signal_pending(current)) { -+ err = -ERESTARTSYS; -+ goto unlock; - } -+ -+ if (low == high) -+ break; - } -- if (newspi) { -- spin_lock_bh(&net->xfrm.xfrm_state_lock); -- x->id.spi = newspi; -- h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, x->props.family); -- XFRM_STATE_INSERT(byspi, &x->byspi, net->xfrm.state_byspi + h, -- x->xso.type); -- spin_unlock_bh(&net->xfrm.xfrm_state_lock); - -- err = 0; -- } else { -+ if (err) - NL_SET_ERR_MSG(extack, "No SPI available in the requested range"); -- } - - unlock: - spin_unlock_bh(&x->lock); -@@ -3077,20 +3080,17 @@ void xfrm_flush_gc(void) - } - EXPORT_SYMBOL(xfrm_flush_gc); - --/* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */ --void xfrm_state_delete_tunnel(struct xfrm_state *x) -+static void xfrm_state_delete_tunnel(struct xfrm_state *x) - { - if (x->tunnel) { - struct xfrm_state *t = x->tunnel; - -- if (atomic_read(&t->tunnel_users) == 2) -+ if (atomic_dec_return(&t->tunnel_users) == 1) - xfrm_state_delete(t); -- atomic_dec(&t->tunnel_users); -- xfrm_state_put_sync(t); -+ xfrm_state_put(t); - x->tunnel = NULL; - } - } --EXPORT_SYMBOL(xfrm_state_delete_tunnel); - - u32 xfrm_state_mtu(struct xfrm_state *x, int mtu) - { -@@ -3295,8 +3295,8 @@ void xfrm_state_fini(struct net *net) - unsigned int sz; - - flush_work(&net->xfrm.state_hash_work); -+ xfrm_state_flush(net, 0, false); - flush_work(&xfrm_state_gc_work); -- xfrm_state_flush(net, 0, false, true); - - WARN_ON(!list_empty(&net->xfrm.state_all)); - -diff -purNx .git BPI-Router-Linux-kernel/net/xfrm/xfrm_user.c BPI-Router-Linux-kernel-6.16.12/net/xfrm/xfrm_user.c ---- BPI-Router-Linux-kernel/net/xfrm/xfrm_user.c 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/net/xfrm/xfrm_user.c 2025-10-22 13:53:56.839167579 -0400 -@@ -977,6 +977,7 @@ static struct xfrm_state *xfrm_state_con - /* override default values from above */ - xfrm_update_ae_params(x, attrs, 0); - -+ xfrm_set_type_offload(x, attrs[XFRMA_OFFLOAD_DEV]); - /* configure the hardware if offload is requested */ - if (attrs[XFRMA_OFFLOAD_DEV]) { - err = xfrm_dev_state_add(net, x, -@@ -2634,7 +2635,7 @@ static int xfrm_flush_sa(struct sk_buff - struct xfrm_usersa_flush *p = nlmsg_data(nlh); - int err; - -- err = xfrm_state_flush(net, p->proto, true, false); -+ err = xfrm_state_flush(net, p->proto, true); - if (err) { - if (err == -ESRCH) /* empty table */ - return 0; -diff -purNx .git BPI-Router-Linux-kernel/rust/bindings/bindings_helper.h BPI-Router-Linux-kernel-6.16.12/rust/bindings/bindings_helper.h ---- BPI-Router-Linux-kernel/rust/bindings/bindings_helper.h 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/bindings/bindings_helper.h 2025-10-22 13:53:56.839167579 -0400 -@@ -39,6 +39,7 @@ - #include - #include - #include -+#include - #include - #include - #include -diff -purNx .git BPI-Router-Linux-kernel/rust/helpers/completion.c BPI-Router-Linux-kernel-6.16.12/rust/helpers/completion.c ---- BPI-Router-Linux-kernel/rust/helpers/completion.c 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/rust/helpers/completion.c 2025-10-22 13:53:56.839167579 -0400 -@@ -0,0 +1,8 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+#include -+ -+void rust_helper_init_completion(struct completion *x) -+{ -+ init_completion(x); -+} -diff -purNx .git BPI-Router-Linux-kernel/rust/helpers/cpu.c BPI-Router-Linux-kernel-6.16.12/rust/helpers/cpu.c ---- BPI-Router-Linux-kernel/rust/helpers/cpu.c 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/rust/helpers/cpu.c 2025-10-22 13:53:56.839167579 -0400 -@@ -0,0 +1,8 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+#include -+ -+unsigned int rust_helper_raw_smp_processor_id(void) -+{ -+ return raw_smp_processor_id(); -+} -diff -purNx .git BPI-Router-Linux-kernel/rust/helpers/helpers.c BPI-Router-Linux-kernel-6.16.12/rust/helpers/helpers.c ---- BPI-Router-Linux-kernel/rust/helpers/helpers.c 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/helpers/helpers.c 2025-10-22 13:53:56.839167579 -0400 -@@ -13,6 +13,8 @@ - #include "build_assert.c" - #include "build_bug.c" - #include "clk.c" -+#include "completion.c" -+#include "cpu.c" - #include "cpufreq.c" - #include "cpumask.c" - #include "cred.c" -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/alloc/allocator.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/alloc/allocator.rs ---- BPI-Router-Linux-kernel/rust/kernel/alloc/allocator.rs 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/alloc/allocator.rs 2025-10-22 13:53:56.839167579 -0400 -@@ -43,17 +43,6 @@ pub struct Vmalloc; - /// For more details see [self]. - pub struct KVmalloc; - --/// Returns a proper size to alloc a new object aligned to `new_layout`'s alignment. --fn aligned_size(new_layout: Layout) -> usize { -- // Customized layouts from `Layout::from_size_align()` can have size < align, so pad first. -- let layout = new_layout.pad_to_align(); -- -- // Note that `layout.size()` (after padding) is guaranteed to be a multiple of `layout.align()` -- // which together with the slab guarantees means the `krealloc` will return a properly aligned -- // object (see comments in `kmalloc()` for more information). -- layout.size() --} -- - /// # Invariants - /// - /// One of the following: `krealloc`, `vrealloc`, `kvrealloc`. -@@ -88,7 +77,7 @@ impl ReallocFunc { - old_layout: Layout, - flags: Flags, - ) -> Result, AllocError> { -- let size = aligned_size(layout); -+ let size = layout.size(); - let ptr = match ptr { - Some(ptr) => { - if old_layout.size() == 0 { -@@ -123,6 +112,17 @@ impl ReallocFunc { - } - } - -+impl Kmalloc { -+ /// Returns a [`Layout`] that makes [`Kmalloc`] fulfill the requested size and alignment of -+ /// `layout`. -+ pub fn aligned_layout(layout: Layout) -> Layout { -+ // Note that `layout.size()` (after padding) is guaranteed to be a multiple of -+ // `layout.align()` which together with the slab guarantees means that `Kmalloc` will return -+ // a properly aligned object (see comments in `kmalloc()` for more information). -+ layout.pad_to_align() -+ } -+} -+ - // SAFETY: `realloc` delegates to `ReallocFunc::call`, which guarantees that - // - memory remains valid until it is explicitly freed, - // - passing a pointer to a valid memory allocation is OK, -@@ -135,6 +135,8 @@ unsafe impl Allocator for Kmalloc { - old_layout: Layout, - flags: Flags, - ) -> Result, AllocError> { -+ let layout = Kmalloc::aligned_layout(layout); -+ - // SAFETY: `ReallocFunc::call` has the same safety requirements as `Allocator::realloc`. - unsafe { ReallocFunc::KREALLOC.call(ptr, layout, old_layout, flags) } - } -@@ -176,6 +178,10 @@ unsafe impl Allocator for KVmalloc { - old_layout: Layout, - flags: Flags, - ) -> Result, AllocError> { -+ // `KVmalloc` may use the `Kmalloc` backend, hence we have to enforce a `Kmalloc` -+ // compatible layout. -+ let layout = Kmalloc::aligned_layout(layout); -+ - // TODO: Support alignments larger than PAGE_SIZE. - if layout.align() > bindings::PAGE_SIZE { - pr_warn!("KVmalloc does not support alignments larger than PAGE_SIZE yet.\n"); -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/alloc/allocator_test.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/alloc/allocator_test.rs ---- BPI-Router-Linux-kernel/rust/kernel/alloc/allocator_test.rs 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/alloc/allocator_test.rs 2025-10-22 13:53:56.839167579 -0400 -@@ -22,6 +22,17 @@ pub type Kmalloc = Cmalloc; - pub type Vmalloc = Kmalloc; - pub type KVmalloc = Kmalloc; - -+impl Cmalloc { -+ /// Returns a [`Layout`] that makes [`Kmalloc`] fulfill the requested size and alignment of -+ /// `layout`. -+ pub fn aligned_layout(layout: Layout) -> Layout { -+ // Note that `layout.size()` (after padding) is guaranteed to be a multiple of -+ // `layout.align()` which together with the slab guarantees means that `Kmalloc` will return -+ // a properly aligned object (see comments in `kmalloc()` for more information). -+ layout.pad_to_align() -+ } -+} -+ - extern "C" { - #[link_name = "aligned_alloc"] - fn libc_aligned_alloc(align: usize, size: usize) -> *mut crate::ffi::c_void; -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/block/mq/gen_disk.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/block/mq/gen_disk.rs ---- BPI-Router-Linux-kernel/rust/kernel/block/mq/gen_disk.rs 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/block/mq/gen_disk.rs 2025-10-22 13:53:56.839167579 -0400 -@@ -3,7 +3,7 @@ - //! Generic disk abstraction. - //! - //! C header: [`include/linux/blkdev.h`](srctree/include/linux/blkdev.h) --//! C header: [`include/linux/blk_mq.h`](srctree/include/linux/blk_mq.h) -+//! C header: [`include/linux/blk-mq.h`](srctree/include/linux/blk-mq.h) - - use crate::block::mq::{raw_writer::RawWriter, Operations, TagSet}; - use crate::{bindings, error::from_err_ptr, error::Result, sync::Arc}; -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/cpufreq.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/cpufreq.rs ---- BPI-Router-Linux-kernel/rust/kernel/cpufreq.rs 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/cpufreq.rs 2025-10-22 13:53:56.839167579 -0400 -@@ -10,6 +10,7 @@ - - use crate::{ - clk::Hertz, -+ cpu::CpuId, - cpumask, - device::{Bound, Device}, - devres::Devres, -@@ -465,8 +466,9 @@ impl Policy { - - /// Returns the primary CPU for the [`Policy`]. - #[inline] -- pub fn cpu(&self) -> u32 { -- self.as_ref().cpu -+ pub fn cpu(&self) -> CpuId { -+ // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number. -+ unsafe { CpuId::from_u32_unchecked(self.as_ref().cpu) } - } - - /// Returns the minimum frequency for the [`Policy`]. -@@ -525,7 +527,7 @@ impl Policy { - #[inline] - pub fn generic_get(&self) -> Result { - // SAFETY: By the type invariant, the pointer stored in `self` is valid. -- Ok(unsafe { bindings::cpufreq_generic_get(self.cpu()) }) -+ Ok(unsafe { bindings::cpufreq_generic_get(u32::from(self.cpu())) }) - } - - /// Provides a wrapper to the register with energy model using the OPP core. -@@ -678,9 +680,9 @@ impl Policy { - struct PolicyCpu<'a>(&'a mut Policy); - - impl<'a> PolicyCpu<'a> { -- fn from_cpu(cpu: u32) -> Result { -+ fn from_cpu(cpu: CpuId) -> Result { - // SAFETY: It is safe to call `cpufreq_cpu_get` for any valid CPU. -- let ptr = from_err_ptr(unsafe { bindings::cpufreq_cpu_get(cpu) })?; -+ let ptr = from_err_ptr(unsafe { bindings::cpufreq_cpu_get(u32::from(cpu)) })?; - - Ok(Self( - // SAFETY: The `ptr` is guaranteed to be valid and remains valid for the lifetime of -@@ -1055,8 +1057,11 @@ impl Registration { - impl Registration { - /// Driver's `init` callback. - /// -- /// SAFETY: Called from C. Inputs must be valid pointers. -- extern "C" fn init_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { -+ /// # Safety -+ /// -+ /// - This function may only be called from the cpufreq C infrastructure. -+ /// - The pointer arguments must be valid pointers. -+ unsafe extern "C" fn init_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { - from_result(|| { - // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the - // lifetime of `policy`. -@@ -1070,8 +1075,11 @@ impl Registration { - - /// Driver's `exit` callback. - /// -- /// SAFETY: Called from C. Inputs must be valid pointers. -- extern "C" fn exit_callback(ptr: *mut bindings::cpufreq_policy) { -+ /// # Safety -+ /// -+ /// - This function may only be called from the cpufreq C infrastructure. -+ /// - The pointer arguments must be valid pointers. -+ unsafe extern "C" fn exit_callback(ptr: *mut bindings::cpufreq_policy) { - // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the - // lifetime of `policy`. - let policy = unsafe { Policy::from_raw_mut(ptr) }; -@@ -1082,8 +1090,11 @@ impl Registration { - - /// Driver's `online` callback. - /// -- /// SAFETY: Called from C. Inputs must be valid pointers. -- extern "C" fn online_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { -+ /// # Safety -+ /// -+ /// - This function may only be called from the cpufreq C infrastructure. -+ /// - The pointer arguments must be valid pointers. -+ unsafe extern "C" fn online_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { - from_result(|| { - // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the - // lifetime of `policy`. -@@ -1094,8 +1105,13 @@ impl Registration { - - /// Driver's `offline` callback. - /// -- /// SAFETY: Called from C. Inputs must be valid pointers. -- extern "C" fn offline_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { -+ /// # Safety -+ /// -+ /// - This function may only be called from the cpufreq C infrastructure. -+ /// - The pointer arguments must be valid pointers. -+ unsafe extern "C" fn offline_callback( -+ ptr: *mut bindings::cpufreq_policy, -+ ) -> kernel::ffi::c_int { - from_result(|| { - // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the - // lifetime of `policy`. -@@ -1106,8 +1122,13 @@ impl Registration { - - /// Driver's `suspend` callback. - /// -- /// SAFETY: Called from C. Inputs must be valid pointers. -- extern "C" fn suspend_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { -+ /// # Safety -+ /// -+ /// - This function may only be called from the cpufreq C infrastructure. -+ /// - The pointer arguments must be valid pointers. -+ unsafe extern "C" fn suspend_callback( -+ ptr: *mut bindings::cpufreq_policy, -+ ) -> kernel::ffi::c_int { - from_result(|| { - // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the - // lifetime of `policy`. -@@ -1118,8 +1139,11 @@ impl Registration { - - /// Driver's `resume` callback. - /// -- /// SAFETY: Called from C. Inputs must be valid pointers. -- extern "C" fn resume_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { -+ /// # Safety -+ /// -+ /// - This function may only be called from the cpufreq C infrastructure. -+ /// - The pointer arguments must be valid pointers. -+ unsafe extern "C" fn resume_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { - from_result(|| { - // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the - // lifetime of `policy`. -@@ -1130,8 +1154,11 @@ impl Registration { - - /// Driver's `ready` callback. - /// -- /// SAFETY: Called from C. Inputs must be valid pointers. -- extern "C" fn ready_callback(ptr: *mut bindings::cpufreq_policy) { -+ /// # Safety -+ /// -+ /// - This function may only be called from the cpufreq C infrastructure. -+ /// - The pointer arguments must be valid pointers. -+ unsafe extern "C" fn ready_callback(ptr: *mut bindings::cpufreq_policy) { - // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the - // lifetime of `policy`. - let policy = unsafe { Policy::from_raw_mut(ptr) }; -@@ -1140,8 +1167,13 @@ impl Registration { - - /// Driver's `verify` callback. - /// -- /// SAFETY: Called from C. Inputs must be valid pointers. -- extern "C" fn verify_callback(ptr: *mut bindings::cpufreq_policy_data) -> kernel::ffi::c_int { -+ /// # Safety -+ /// -+ /// - This function may only be called from the cpufreq C infrastructure. -+ /// - The pointer arguments must be valid pointers. -+ unsafe extern "C" fn verify_callback( -+ ptr: *mut bindings::cpufreq_policy_data, -+ ) -> kernel::ffi::c_int { - from_result(|| { - // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the - // lifetime of `policy`. -@@ -1152,8 +1184,13 @@ impl Registration { - - /// Driver's `setpolicy` callback. - /// -- /// SAFETY: Called from C. Inputs must be valid pointers. -- extern "C" fn setpolicy_callback(ptr: *mut bindings::cpufreq_policy) -> kernel::ffi::c_int { -+ /// # Safety -+ /// -+ /// - This function may only be called from the cpufreq C infrastructure. -+ /// - The pointer arguments must be valid pointers. -+ unsafe extern "C" fn setpolicy_callback( -+ ptr: *mut bindings::cpufreq_policy, -+ ) -> kernel::ffi::c_int { - from_result(|| { - // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the - // lifetime of `policy`. -@@ -1164,8 +1201,11 @@ impl Registration { - - /// Driver's `target` callback. - /// -- /// SAFETY: Called from C. Inputs must be valid pointers. -- extern "C" fn target_callback( -+ /// # Safety -+ /// -+ /// - This function may only be called from the cpufreq C infrastructure. -+ /// - The pointer arguments must be valid pointers. -+ unsafe extern "C" fn target_callback( - ptr: *mut bindings::cpufreq_policy, - target_freq: u32, - relation: u32, -@@ -1180,8 +1220,11 @@ impl Registration { - - /// Driver's `target_index` callback. - /// -- /// SAFETY: Called from C. Inputs must be valid pointers. -- extern "C" fn target_index_callback( -+ /// # Safety -+ /// -+ /// - This function may only be called from the cpufreq C infrastructure. -+ /// - The pointer arguments must be valid pointers. -+ unsafe extern "C" fn target_index_callback( - ptr: *mut bindings::cpufreq_policy, - index: u32, - ) -> kernel::ffi::c_int { -@@ -1200,8 +1243,11 @@ impl Registration { - - /// Driver's `fast_switch` callback. - /// -- /// SAFETY: Called from C. Inputs must be valid pointers. -- extern "C" fn fast_switch_callback( -+ /// # Safety -+ /// -+ /// - This function may only be called from the cpufreq C infrastructure. -+ /// - The pointer arguments must be valid pointers. -+ unsafe extern "C" fn fast_switch_callback( - ptr: *mut bindings::cpufreq_policy, - target_freq: u32, - ) -> kernel::ffi::c_uint { -@@ -1212,21 +1258,31 @@ impl Registration { - } - - /// Driver's `adjust_perf` callback. -- extern "C" fn adjust_perf_callback( -+ /// -+ /// # Safety -+ /// -+ /// - This function may only be called from the cpufreq C infrastructure. -+ unsafe extern "C" fn adjust_perf_callback( - cpu: u32, - min_perf: usize, - target_perf: usize, - capacity: usize, - ) { -- if let Ok(mut policy) = PolicyCpu::from_cpu(cpu) { -+ // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number. -+ let cpu_id = unsafe { CpuId::from_u32_unchecked(cpu) }; -+ -+ if let Ok(mut policy) = PolicyCpu::from_cpu(cpu_id) { - T::adjust_perf(&mut policy, min_perf, target_perf, capacity); - } - } - - /// Driver's `get_intermediate` callback. - /// -- /// SAFETY: Called from C. Inputs must be valid pointers. -- extern "C" fn get_intermediate_callback( -+ /// # Safety -+ /// -+ /// - This function may only be called from the cpufreq C infrastructure. -+ /// - The pointer arguments must be valid pointers. -+ unsafe extern "C" fn get_intermediate_callback( - ptr: *mut bindings::cpufreq_policy, - index: u32, - ) -> kernel::ffi::c_uint { -@@ -1243,8 +1299,11 @@ impl Registration { - - /// Driver's `target_intermediate` callback. - /// -- /// SAFETY: Called from C. Inputs must be valid pointers. -- extern "C" fn target_intermediate_callback( -+ /// # Safety -+ /// -+ /// - This function may only be called from the cpufreq C infrastructure. -+ /// - The pointer arguments must be valid pointers. -+ unsafe extern "C" fn target_intermediate_callback( - ptr: *mut bindings::cpufreq_policy, - index: u32, - ) -> kernel::ffi::c_int { -@@ -1262,12 +1321,24 @@ impl Registration { - } - - /// Driver's `get` callback. -- extern "C" fn get_callback(cpu: u32) -> kernel::ffi::c_uint { -- PolicyCpu::from_cpu(cpu).map_or(0, |mut policy| T::get(&mut policy).map_or(0, |f| f)) -+ /// -+ /// # Safety -+ /// -+ /// - This function may only be called from the cpufreq C infrastructure. -+ unsafe extern "C" fn get_callback(cpu: u32) -> kernel::ffi::c_uint { -+ // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number. -+ let cpu_id = unsafe { CpuId::from_u32_unchecked(cpu) }; -+ -+ PolicyCpu::from_cpu(cpu_id).map_or(0, |mut policy| T::get(&mut policy).map_or(0, |f| f)) - } - - /// Driver's `update_limit` callback. -- extern "C" fn update_limits_callback(ptr: *mut bindings::cpufreq_policy) { -+ /// -+ /// # Safety -+ /// -+ /// - This function may only be called from the cpufreq C infrastructure. -+ /// - The pointer arguments must be valid pointers. -+ unsafe extern "C" fn update_limits_callback(ptr: *mut bindings::cpufreq_policy) { - // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the - // lifetime of `policy`. - let policy = unsafe { Policy::from_raw_mut(ptr) }; -@@ -1276,10 +1347,16 @@ impl Registration { - - /// Driver's `bios_limit` callback. - /// -- /// SAFETY: Called from C. Inputs must be valid pointers. -- extern "C" fn bios_limit_callback(cpu: i32, limit: *mut u32) -> kernel::ffi::c_int { -+ /// # Safety -+ /// -+ /// - This function may only be called from the cpufreq C infrastructure. -+ /// - The pointer arguments must be valid pointers. -+ unsafe extern "C" fn bios_limit_callback(cpu: i32, limit: *mut u32) -> kernel::ffi::c_int { -+ // SAFETY: The C API guarantees that `cpu` refers to a valid CPU number. -+ let cpu_id = unsafe { CpuId::from_i32_unchecked(cpu) }; -+ - from_result(|| { -- let mut policy = PolicyCpu::from_cpu(cpu as u32)?; -+ let mut policy = PolicyCpu::from_cpu(cpu_id)?; - - // SAFETY: `limit` is guaranteed by the C code to be valid. - T::bios_limit(&mut policy, &mut (unsafe { *limit })).map(|()| 0) -@@ -1288,8 +1365,11 @@ impl Registration { - - /// Driver's `set_boost` callback. - /// -- /// SAFETY: Called from C. Inputs must be valid pointers. -- extern "C" fn set_boost_callback( -+ /// # Safety -+ /// -+ /// - This function may only be called from the cpufreq C infrastructure. -+ /// - The pointer arguments must be valid pointers. -+ unsafe extern "C" fn set_boost_callback( - ptr: *mut bindings::cpufreq_policy, - state: i32, - ) -> kernel::ffi::c_int { -@@ -1303,8 +1383,11 @@ impl Registration { - - /// Driver's `register_em` callback. - /// -- /// SAFETY: Called from C. Inputs must be valid pointers. -- extern "C" fn register_em_callback(ptr: *mut bindings::cpufreq_policy) { -+ /// # Safety -+ /// -+ /// - This function may only be called from the cpufreq C infrastructure. -+ /// - The pointer arguments must be valid pointers. -+ unsafe extern "C" fn register_em_callback(ptr: *mut bindings::cpufreq_policy) { - // SAFETY: The `ptr` is guaranteed to be valid by the contract with the C code for the - // lifetime of `policy`. - let policy = unsafe { Policy::from_raw_mut(ptr) }; -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/cpumask.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/cpumask.rs ---- BPI-Router-Linux-kernel/rust/kernel/cpumask.rs 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/cpumask.rs 2025-10-22 13:53:56.839167579 -0400 -@@ -6,6 +6,7 @@ - - use crate::{ - alloc::{AllocError, Flags}, -+ cpu::CpuId, - prelude::*, - types::Opaque, - }; -@@ -35,9 +36,10 @@ use core::ops::{Deref, DerefMut}; - /// - /// ``` - /// use kernel::bindings; -+/// use kernel::cpu::CpuId; - /// use kernel::cpumask::Cpumask; - /// --/// fn set_clear_cpu(ptr: *mut bindings::cpumask, set_cpu: u32, clear_cpu: i32) { -+/// fn set_clear_cpu(ptr: *mut bindings::cpumask, set_cpu: CpuId, clear_cpu: CpuId) { - /// // SAFETY: The `ptr` is valid for writing and remains valid for the lifetime of the - /// // returned reference. - /// let mask = unsafe { Cpumask::as_mut_ref(ptr) }; -@@ -90,9 +92,9 @@ impl Cpumask { - /// This mismatches kernel naming convention and corresponds to the C - /// function `__cpumask_set_cpu()`. - #[inline] -- pub fn set(&mut self, cpu: u32) { -+ pub fn set(&mut self, cpu: CpuId) { - // SAFETY: By the type invariant, `self.as_raw` is a valid argument to `__cpumask_set_cpu`. -- unsafe { bindings::__cpumask_set_cpu(cpu, self.as_raw()) }; -+ unsafe { bindings::__cpumask_set_cpu(u32::from(cpu), self.as_raw()) }; - } - - /// Clear `cpu` in the cpumask. -@@ -101,19 +103,19 @@ impl Cpumask { - /// This mismatches kernel naming convention and corresponds to the C - /// function `__cpumask_clear_cpu()`. - #[inline] -- pub fn clear(&mut self, cpu: i32) { -+ pub fn clear(&mut self, cpu: CpuId) { - // SAFETY: By the type invariant, `self.as_raw` is a valid argument to - // `__cpumask_clear_cpu`. -- unsafe { bindings::__cpumask_clear_cpu(cpu, self.as_raw()) }; -+ unsafe { bindings::__cpumask_clear_cpu(i32::from(cpu), self.as_raw()) }; - } - - /// Test `cpu` in the cpumask. - /// - /// Equivalent to the kernel's `cpumask_test_cpu` API. - #[inline] -- pub fn test(&self, cpu: i32) -> bool { -+ pub fn test(&self, cpu: CpuId) -> bool { - // SAFETY: By the type invariant, `self.as_raw` is a valid argument to `cpumask_test_cpu`. -- unsafe { bindings::cpumask_test_cpu(cpu, self.as_raw()) } -+ unsafe { bindings::cpumask_test_cpu(i32::from(cpu), self.as_raw()) } - } - - /// Set all CPUs in the cpumask. -@@ -178,21 +180,40 @@ impl Cpumask { - /// The following example demonstrates how to create and update a [`CpumaskVar`]. - /// - /// ``` -+/// use kernel::cpu::CpuId; - /// use kernel::cpumask::CpumaskVar; - /// - /// let mut mask = CpumaskVar::new_zero(GFP_KERNEL).unwrap(); - /// - /// assert!(mask.empty()); --/// mask.set(2); --/// assert!(mask.test(2)); --/// mask.set(3); --/// assert!(mask.test(3)); --/// assert_eq!(mask.weight(), 2); -+/// let mut count = 0; -+/// -+/// let cpu2 = CpuId::from_u32(2); -+/// if let Some(cpu) = cpu2 { -+/// mask.set(cpu); -+/// assert!(mask.test(cpu)); -+/// count += 1; -+/// } -+/// -+/// let cpu3 = CpuId::from_u32(3); -+/// if let Some(cpu) = cpu3 { -+/// mask.set(cpu); -+/// assert!(mask.test(cpu)); -+/// count += 1; -+/// } -+/// -+/// assert_eq!(mask.weight(), count); - /// - /// let mask2 = CpumaskVar::try_clone(&mask).unwrap(); --/// assert!(mask2.test(2)); --/// assert!(mask2.test(3)); --/// assert_eq!(mask2.weight(), 2); -+/// -+/// if let Some(cpu) = cpu2 { -+/// assert!(mask2.test(cpu)); -+/// } -+/// -+/// if let Some(cpu) = cpu3 { -+/// assert!(mask2.test(cpu)); -+/// } -+/// assert_eq!(mask2.weight(), count); - /// ``` - pub struct CpumaskVar { - #[cfg(CONFIG_CPUMASK_OFFSTACK)] -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/cpu.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/cpu.rs ---- BPI-Router-Linux-kernel/rust/kernel/cpu.rs 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/cpu.rs 2025-10-22 13:53:56.839167579 -0400 -@@ -6,6 +6,127 @@ - - use crate::{bindings, device::Device, error::Result, prelude::ENODEV}; - -+/// Returns the maximum number of possible CPUs in the current system configuration. -+#[inline] -+pub fn nr_cpu_ids() -> u32 { -+ #[cfg(any(NR_CPUS_1, CONFIG_FORCE_NR_CPUS))] -+ { -+ bindings::NR_CPUS -+ } -+ -+ #[cfg(not(any(NR_CPUS_1, CONFIG_FORCE_NR_CPUS)))] -+ // SAFETY: `nr_cpu_ids` is a valid global provided by the kernel. -+ unsafe { -+ bindings::nr_cpu_ids -+ } -+} -+ -+/// The CPU ID. -+/// -+/// Represents a CPU identifier as a wrapper around an [`u32`]. -+/// -+/// # Invariants -+/// -+/// The CPU ID lies within the range `[0, nr_cpu_ids())`. -+/// -+/// # Examples -+/// -+/// ``` -+/// use kernel::cpu::CpuId; -+/// -+/// let cpu = 0; -+/// -+/// // SAFETY: 0 is always a valid CPU number. -+/// let id = unsafe { CpuId::from_u32_unchecked(cpu) }; -+/// -+/// assert_eq!(id.as_u32(), cpu); -+/// assert!(CpuId::from_i32(0).is_some()); -+/// assert!(CpuId::from_i32(-1).is_none()); -+/// ``` -+#[derive(Copy, Clone, PartialEq, Eq, Debug)] -+pub struct CpuId(u32); -+ -+impl CpuId { -+ /// Creates a new [`CpuId`] from the given `id` without checking bounds. -+ /// -+ /// # Safety -+ /// -+ /// The caller must ensure that `id` is a valid CPU ID (i.e., `0 <= id < nr_cpu_ids()`). -+ #[inline] -+ pub unsafe fn from_i32_unchecked(id: i32) -> Self { -+ debug_assert!(id >= 0); -+ debug_assert!((id as u32) < nr_cpu_ids()); -+ -+ // INVARIANT: The function safety guarantees `id` is a valid CPU id. -+ Self(id as u32) -+ } -+ -+ /// Creates a new [`CpuId`] from the given `id`, checking that it is valid. -+ pub fn from_i32(id: i32) -> Option { -+ if id < 0 || id as u32 >= nr_cpu_ids() { -+ None -+ } else { -+ // INVARIANT: `id` has just been checked as a valid CPU ID. -+ Some(Self(id as u32)) -+ } -+ } -+ -+ /// Creates a new [`CpuId`] from the given `id` without checking bounds. -+ /// -+ /// # Safety -+ /// -+ /// The caller must ensure that `id` is a valid CPU ID (i.e., `0 <= id < nr_cpu_ids()`). -+ #[inline] -+ pub unsafe fn from_u32_unchecked(id: u32) -> Self { -+ debug_assert!(id < nr_cpu_ids()); -+ -+ // Ensure the `id` fits in an [`i32`] as it's also representable that way. -+ debug_assert!(id <= i32::MAX as u32); -+ -+ // INVARIANT: The function safety guarantees `id` is a valid CPU id. -+ Self(id) -+ } -+ -+ /// Creates a new [`CpuId`] from the given `id`, checking that it is valid. -+ pub fn from_u32(id: u32) -> Option { -+ if id >= nr_cpu_ids() { -+ None -+ } else { -+ // INVARIANT: `id` has just been checked as a valid CPU ID. -+ Some(Self(id)) -+ } -+ } -+ -+ /// Returns CPU number. -+ #[inline] -+ pub fn as_u32(&self) -> u32 { -+ self.0 -+ } -+ -+ /// Returns the ID of the CPU the code is currently running on. -+ /// -+ /// The returned value is considered unstable because it may change -+ /// unexpectedly due to preemption or CPU migration. It should only be -+ /// used when the context ensures that the task remains on the same CPU -+ /// or the users could use a stale (yet valid) CPU ID. -+ pub fn current() -> Self { -+ // SAFETY: raw_smp_processor_id() always returns a valid CPU ID. -+ unsafe { Self::from_u32_unchecked(bindings::raw_smp_processor_id()) } -+ } -+} -+ -+impl From for u32 { -+ fn from(id: CpuId) -> Self { -+ id.as_u32() -+ } -+} -+ -+impl From for i32 { -+ fn from(id: CpuId) -> Self { -+ id.as_u32() as i32 -+ } -+} -+ - /// Creates a new instance of CPU's device. - /// - /// # Safety -@@ -17,9 +138,9 @@ use crate::{bindings, device::Device, er - /// Callers must ensure that the CPU device is not used after it has been unregistered. - /// This can be achieved, for example, by registering a CPU hotplug notifier and removing - /// any references to the CPU device within the notifier's callback. --pub unsafe fn from_cpu(cpu: u32) -> Result<&'static Device> { -+pub unsafe fn from_cpu(cpu: CpuId) -> Result<&'static Device> { - // SAFETY: It is safe to call `get_cpu_device()` for any CPU. -- let ptr = unsafe { bindings::get_cpu_device(cpu) }; -+ let ptr = unsafe { bindings::get_cpu_device(u32::from(cpu)) }; - if ptr.is_null() { - return Err(ENODEV); - } -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/devres.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/devres.rs ---- BPI-Router-Linux-kernel/rust/kernel/devres.rs 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/devres.rs 2025-10-22 13:53:56.839167579 -0400 -@@ -12,26 +12,28 @@ use crate::{ - error::{Error, Result}, - ffi::c_void, - prelude::*, -- revocable::Revocable, -- sync::Arc, -+ revocable::{Revocable, RevocableGuard}, -+ sync::{rcu, Arc, Completion}, - types::ARef, - }; - --use core::ops::Deref; -- - #[pin_data] --struct DevresInner { -+struct DevresInner { - dev: ARef, - callback: unsafe extern "C" fn(*mut c_void), - #[pin] - data: Revocable, -+ #[pin] -+ revoke: Completion, - } - - /// This abstraction is meant to be used by subsystems to containerize [`Device`] bound resources to - /// manage their lifetime. - /// - /// [`Device`] bound resources should be freed when either the resource goes out of scope or the --/// [`Device`] is unbound respectively, depending on what happens first. -+/// [`Device`] is unbound respectively, depending on what happens first. In any case, it is always -+/// guaranteed that revoking the device resource is completed before the corresponding [`Device`] -+/// is unbound. - /// - /// To achieve that [`Devres`] registers a devres callback on creation, which is called once the - /// [`Device`] is unbound, revoking access to the encapsulated resource (see also [`Revocable`]). -@@ -93,15 +95,16 @@ struct DevresInner { - /// # Ok(()) - /// # } - /// ``` --pub struct Devres(Arc>); -+pub struct Devres(Arc>); - --impl DevresInner { -+impl DevresInner { - fn new(dev: &Device, data: T, flags: Flags) -> Result>> { - let inner = Arc::pin_init( - pin_init!( DevresInner { - dev: dev.into(), - callback: Self::devres_callback, - data <- Revocable::new(data), -+ revoke <- Completion::new(), - }), - flags, - )?; -@@ -130,26 +133,28 @@ impl DevresInner { - self as _ - } - -- fn remove_action(this: &Arc) { -+ fn remove_action(this: &Arc) -> bool { - // SAFETY: - // - `self.inner.dev` is a valid `Device`, - // - the `action` and `data` pointers are the exact same ones as given to devm_add_action() - // previously, - // - `self` is always valid, even if the action has been released already. -- let ret = unsafe { -+ let success = unsafe { - bindings::devm_remove_action_nowarn( - this.dev.as_raw(), - Some(this.callback), - this.as_ptr() as _, - ) -- }; -+ } == 0; - -- if ret == 0 { -+ if success { - // SAFETY: We leaked an `Arc` reference to devm_add_action() in `DevresInner::new`; if - // devm_remove_action_nowarn() was successful we can (and have to) claim back ownership - // of this reference. - let _ = unsafe { Arc::from_raw(this.as_ptr()) }; - } -+ -+ success - } - - #[allow(clippy::missing_safety_doc)] -@@ -161,11 +166,16 @@ impl DevresInner { - // `DevresInner::new`. - let inner = unsafe { Arc::from_raw(ptr) }; - -- inner.data.revoke(); -+ if !inner.data.revoke() { -+ // If `revoke()` returns false, it means that `Devres::drop` already started revoking -+ // `inner.data` for us. Hence we have to wait until `Devres::drop()` signals that it -+ // completed revoking `inner.data`. -+ inner.revoke.wait_for_completion(); -+ } - } - } - --impl Devres { -+impl Devres { - /// Creates a new [`Devres`] instance of the given `data`. The `data` encapsulated within the - /// returned `Devres` instance' `data` will be revoked once the device is detached. - pub fn new(dev: &Device, data: T, flags: Flags) -> Result { -@@ -218,20 +228,36 @@ impl Devres { - // SAFETY: `dev` being the same device as the device this `Devres` has been created for - // proves that `self.0.data` hasn't been revoked and is guaranteed to not be revoked as - // long as `dev` lives; `dev` lives at least as long as `self`. -- Ok(unsafe { self.deref().access() }) -+ Ok(unsafe { self.0.data.access() }) - } --} - --impl Deref for Devres { -- type Target = Revocable; -+ /// [`Devres`] accessor for [`Revocable::try_access`]. -+ pub fn try_access(&self) -> Option> { -+ self.0.data.try_access() -+ } -+ -+ /// [`Devres`] accessor for [`Revocable::try_access_with`]. -+ pub fn try_access_with R>(&self, f: F) -> Option { -+ self.0.data.try_access_with(f) -+ } - -- fn deref(&self) -> &Self::Target { -- &self.0.data -+ /// [`Devres`] accessor for [`Revocable::try_access_with_guard`]. -+ pub fn try_access_with_guard<'a>(&'a self, guard: &'a rcu::Guard) -> Option<&'a T> { -+ self.0.data.try_access_with_guard(guard) - } - } - --impl Drop for Devres { -+impl Drop for Devres { - fn drop(&mut self) { -- DevresInner::remove_action(&self.0); -+ // SAFETY: When `drop` runs, it is guaranteed that nobody is accessing the revocable data -+ // anymore, hence it is safe not to wait for the grace period to finish. -+ if unsafe { self.0.data.revoke_nosync() } { -+ // We revoked `self.0.data` before the devres action did, hence try to remove it. -+ if !DevresInner::remove_action(&self.0) { -+ // We could not remove the devres action, which means that it now runs concurrently, -+ // hence signal that `self.0.data` has been revoked successfully. -+ self.0.revoke.complete_all(); -+ } -+ } - } - } -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/drm/device.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/drm/device.rs ---- BPI-Router-Linux-kernel/rust/kernel/drm/device.rs 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/drm/device.rs 2025-10-22 13:53:56.839167579 -0400 -@@ -2,9 +2,10 @@ - - //! DRM device. - //! --//! C header: [`include/linux/drm/drm_device.h`](srctree/include/linux/drm/drm_device.h) -+//! C header: [`include/drm/drm_device.h`](srctree/include/drm/drm_device.h) - - use crate::{ -+ alloc::allocator::Kmalloc, - bindings, device, drm, - drm::driver::AllocImpl, - error::from_err_ptr, -@@ -12,7 +13,7 @@ use crate::{ - prelude::*, - types::{ARef, AlwaysRefCounted, Opaque}, - }; --use core::{mem, ops::Deref, ptr, ptr::NonNull}; -+use core::{alloc::Layout, mem, ops::Deref, ptr, ptr::NonNull}; - - #[cfg(CONFIG_DRM_LEGACY)] - macro_rules! drm_legacy_fields { -@@ -53,10 +54,8 @@ macro_rules! drm_legacy_fields { - /// - /// `self.dev` is a valid instance of a `struct device`. - #[repr(C)] --#[pin_data] - pub struct Device { - dev: Opaque, -- #[pin] - data: T::Data, - } - -@@ -66,7 +65,7 @@ impl Device { - open: Some(drm::File::::open_callback), - postclose: Some(drm::File::::postclose_callback), - unload: None, -- release: None, -+ release: Some(Self::release), - master_set: None, - master_drop: None, - debugfs_init: None, -@@ -96,6 +95,10 @@ impl Device { - - /// Create a new `drm::Device` for a `drm::Driver`. - pub fn new(dev: &device::Device, data: impl PinInit) -> Result> { -+ // `__drm_dev_alloc` uses `kmalloc()` to allocate memory, hence ensure a `kmalloc()` -+ // compatible `Layout`. -+ let layout = Kmalloc::aligned_layout(Layout::new::()); -+ - // SAFETY: - // - `VTABLE`, as a `const` is pinned to the read-only section of the compilation, - // - `dev` is valid by its type invarants, -@@ -103,7 +106,7 @@ impl Device { - bindings::__drm_dev_alloc( - dev.as_raw(), - &Self::VTABLE, -- mem::size_of::(), -+ layout.size(), - mem::offset_of!(Self, dev), - ) - } -@@ -117,9 +120,13 @@ impl Device { - // - `raw_data` is a valid pointer to uninitialized memory. - // - `raw_data` will not move until it is dropped. - unsafe { data.__pinned_init(raw_data) }.inspect_err(|_| { -- // SAFETY: `__drm_dev_alloc()` was successful, hence `raw_drm` must be valid and the -+ // SAFETY: `raw_drm` is a valid pointer to `Self`, given that `__drm_dev_alloc` was -+ // successful. -+ let drm_dev = unsafe { Self::into_drm_device(raw_drm) }; -+ -+ // SAFETY: `__drm_dev_alloc()` was successful, hence `drm_dev` must be valid and the - // refcount must be non-zero. -- unsafe { bindings::drm_dev_put(ptr::addr_of_mut!((*raw_drm.as_ptr()).dev).cast()) }; -+ unsafe { bindings::drm_dev_put(drm_dev) }; - })?; - - // SAFETY: The reference count is one, and now we take ownership of that reference as a -@@ -142,6 +149,14 @@ impl Device { - unsafe { crate::container_of!(ptr, Self, dev) }.cast_mut() - } - -+ /// # Safety -+ /// -+ /// `ptr` must be a valid pointer to `Self`. -+ unsafe fn into_drm_device(ptr: NonNull) -> *mut bindings::drm_device { -+ // SAFETY: By the safety requirements of this function, `ptr` is a valid pointer to `Self`. -+ unsafe { &raw mut (*ptr.as_ptr()).dev }.cast() -+ } -+ - /// Not intended to be called externally, except via declare_drm_ioctls!() - /// - /// # Safety -@@ -162,6 +177,16 @@ impl Device { - // SAFETY: `ptr` is valid by the safety requirements of this function. - unsafe { &*ptr.cast() } - } -+ -+ extern "C" fn release(ptr: *mut bindings::drm_device) { -+ // SAFETY: `ptr` is a valid pointer to a `struct drm_device` and embedded in `Self`. -+ let this = unsafe { Self::from_drm_device(ptr) }; -+ -+ // SAFETY: -+ // - When `release` runs it is guaranteed that there is no further access to `this`. -+ // - `this` is valid for dropping. -+ unsafe { core::ptr::drop_in_place(this) }; -+ } - } - - impl Deref for Device { -@@ -181,8 +206,11 @@ unsafe impl AlwaysRefCou - } - - unsafe fn dec_ref(obj: NonNull) { -+ // SAFETY: `obj` is a valid pointer to `Self`. -+ let drm_dev = unsafe { Self::into_drm_device(obj) }; -+ - // SAFETY: The safety requirements guarantee that the refcount is non-zero. -- unsafe { bindings::drm_dev_put(obj.cast().as_ptr()) }; -+ unsafe { bindings::drm_dev_put(drm_dev) }; - } - } - -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/drm/driver.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/drm/driver.rs ---- BPI-Router-Linux-kernel/rust/kernel/drm/driver.rs 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/drm/driver.rs 2025-10-22 13:53:56.839167579 -0400 -@@ -2,7 +2,7 @@ - - //! DRM driver core. - //! --//! C header: [`include/linux/drm/drm_drv.h`](srctree/include/linux/drm/drm_drv.h) -+//! C header: [`include/drm/drm_drv.h`](srctree/include/drm/drm_drv.h) - - use crate::{ - bindings, device, -@@ -10,7 +10,6 @@ use crate::{ - drm, - error::{to_result, Result}, - prelude::*, -- str::CStr, - types::ARef, - }; - use macros::vtable; -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/drm/file.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/drm/file.rs ---- BPI-Router-Linux-kernel/rust/kernel/drm/file.rs 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/drm/file.rs 2025-10-22 13:53:56.839167579 -0400 -@@ -2,7 +2,7 @@ - - //! DRM File objects. - //! --//! C header: [`include/linux/drm/drm_file.h`](srctree/include/linux/drm/drm_file.h) -+//! C header: [`include/drm/drm_file.h`](srctree/include/drm/drm_file.h) - - use crate::{bindings, drm, error::Result, prelude::*, types::Opaque}; - use core::marker::PhantomData; -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/drm/gem/mod.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/drm/gem/mod.rs ---- BPI-Router-Linux-kernel/rust/kernel/drm/gem/mod.rs 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/drm/gem/mod.rs 2025-10-22 13:53:56.843167560 -0400 -@@ -2,7 +2,7 @@ - - //! DRM GEM API - //! --//! C header: [`include/linux/drm/drm_gem.h`](srctree/include/linux/drm/drm_gem.h) -+//! C header: [`include/drm/drm_gem.h`](srctree/include/drm/drm_gem.h) - - use crate::{ - alloc::flags::*, -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/drm/ioctl.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/drm/ioctl.rs ---- BPI-Router-Linux-kernel/rust/kernel/drm/ioctl.rs 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/drm/ioctl.rs 2025-10-22 13:53:56.843167560 -0400 -@@ -2,7 +2,7 @@ - - //! DRM IOCTL definitions. - //! --//! C header: [`include/linux/drm/drm_ioctl.h`](srctree/include/linux/drm/drm_ioctl.h) -+//! C header: [`include/drm/drm_ioctl.h`](srctree/include/drm/drm_ioctl.h) - - use crate::ioctl; - -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/faux.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/faux.rs ---- BPI-Router-Linux-kernel/rust/kernel/faux.rs 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/faux.rs 2025-10-22 13:53:56.843167560 -0400 -@@ -4,7 +4,7 @@ - //! - //! This module provides bindings for working with faux devices in kernel modules. - //! --//! C header: [`include/linux/device/faux.h`] -+//! C header: [`include/linux/device/faux.h`](srctree/include/linux/device/faux.h) - - use crate::{bindings, device, error::code::*, prelude::*}; - use core::ptr::{addr_of_mut, null, null_mut, NonNull}; -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/firmware.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/firmware.rs ---- BPI-Router-Linux-kernel/rust/kernel/firmware.rs 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/firmware.rs 2025-10-22 13:53:56.843167560 -0400 -@@ -202,7 +202,7 @@ macro_rules! module_firmware { - }; - - #[link_section = ".modinfo"] -- #[used] -+ #[used(compiler)] - static __MODULE_FIRMWARE: [u8; $($builder)*::create(__MODULE_FIRMWARE_PREFIX) - .build_length()] = $($builder)*::create(__MODULE_FIRMWARE_PREFIX).build(); - }; -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/init.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/init.rs ---- BPI-Router-Linux-kernel/rust/kernel/init.rs 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/init.rs 2025-10-22 13:53:56.843167560 -0400 -@@ -231,14 +231,14 @@ macro_rules! try_init { - ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? { - $($fields:tt)* - }) => { -- ::pin_init::try_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? { -+ ::pin_init::try_init!($(&$this in)? $t $(::<$($generics),*>)? { - $($fields)* - }? $crate::error::Error) - }; - ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? { - $($fields:tt)* - }? $err:ty) => { -- ::pin_init::try_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? { -+ ::pin_init::try_init!($(&$this in)? $t $(::<$($generics),*>)? { - $($fields)* - }? $err) - }; -@@ -291,14 +291,14 @@ macro_rules! try_pin_init { - ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? { - $($fields:tt)* - }) => { -- ::pin_init::try_pin_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? { -+ ::pin_init::try_pin_init!($(&$this in)? $t $(::<$($generics),*>)? { - $($fields)* - }? $crate::error::Error) - }; - ($(&$this:ident in)? $t:ident $(::<$($generics:ty),* $(,)?>)? { - $($fields:tt)* - }? $err:ty) => { -- ::pin_init::try_pin_init!($(&$this in)? $t $(::<$($generics),* $(,)?>)? { -+ ::pin_init::try_pin_init!($(&$this in)? $t $(::<$($generics),*>)? { - $($fields)* - }? $err) - }; -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/kunit.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/kunit.rs ---- BPI-Router-Linux-kernel/rust/kernel/kunit.rs 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/kunit.rs 2025-10-22 13:53:56.843167560 -0400 -@@ -302,7 +302,7 @@ macro_rules! kunit_unsafe_test_suite { - is_init: false, - }; - -- #[used] -+ #[used(compiler)] - #[allow(unused_unsafe)] - #[cfg_attr(not(target_os = "macos"), link_section = ".kunit_test_suites")] - static mut KUNIT_TEST_SUITE_ENTRY: *const ::kernel::bindings::kunit_suite = -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/lib.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/lib.rs ---- BPI-Router-Linux-kernel/rust/kernel/lib.rs 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/lib.rs 2025-10-22 13:53:56.843167560 -0400 -@@ -34,6 +34,9 @@ - // Expected to become stable. - #![feature(arbitrary_self_types)] - // -+// To be determined. -+#![feature(used_with_arg)] -+// - // `feature(derive_coerce_pointee)` is expected to become stable. Before Rust - // 1.84.0, it did not exist, so enable the predecessor features. - #![cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, feature(derive_coerce_pointee))] -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/miscdevice.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/miscdevice.rs ---- BPI-Router-Linux-kernel/rust/kernel/miscdevice.rs 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/miscdevice.rs 2025-10-22 13:53:56.843167560 -0400 -@@ -45,7 +45,13 @@ impl MiscDeviceOptions { - /// - /// # Invariants - /// --/// `inner` is a registered misc device. -+/// - `inner` contains a `struct miscdevice` that is registered using -+/// `misc_register()`. -+/// - This registration remains valid for the entire lifetime of the -+/// [`MiscDeviceRegistration`] instance. -+/// - Deregistration occurs exactly once in [`Drop`] via `misc_deregister()`. -+/// - `inner` wraps a valid, pinned `miscdevice` created using -+/// [`MiscDeviceOptions::into_raw`]. - #[repr(transparent)] - #[pin_data(PinnedDrop)] - pub struct MiscDeviceRegistration { -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/mm/virt.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/mm/virt.rs ---- BPI-Router-Linux-kernel/rust/kernel/mm/virt.rs 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/mm/virt.rs 2025-10-22 13:53:56.843167560 -0400 -@@ -209,6 +209,7 @@ impl VmaMixedMap { - /// - /// For the duration of 'a, the referenced vma must be undergoing initialization in an - /// `f_ops->mmap()` hook. -+#[repr(transparent)] - pub struct VmaNew { - vma: VmaRef, - } -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/pci.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/pci.rs ---- BPI-Router-Linux-kernel/rust/kernel/pci.rs 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/pci.rs 2025-10-22 13:53:56.843167560 -0400 -@@ -238,8 +238,8 @@ pub trait Driver: Send { - - /// PCI driver probe. - /// -- /// Called when a new platform device is added or discovered. -- /// Implementers should attempt to initialize the device here. -+ /// Called when a new pci device is added or discovered. Implementers should -+ /// attempt to initialize the device here. - fn probe(dev: &Device, id_info: &Self::IdInfo) -> Result>>; - } - -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/revocable.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/revocable.rs ---- BPI-Router-Linux-kernel/rust/kernel/revocable.rs 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/revocable.rs 2025-10-22 13:53:56.843167560 -0400 -@@ -154,8 +154,10 @@ impl Revocable { - /// # Safety - /// - /// Callers must ensure that there are no more concurrent users of the revocable object. -- unsafe fn revoke_internal(&self) { -- if self.is_available.swap(false, Ordering::Relaxed) { -+ unsafe fn revoke_internal(&self) -> bool { -+ let revoke = self.is_available.swap(false, Ordering::Relaxed); -+ -+ if revoke { - if SYNC { - // SAFETY: Just an FFI call, there are no further requirements. - unsafe { bindings::synchronize_rcu() }; -@@ -165,6 +167,8 @@ impl Revocable { - // `compare_exchange` above that takes `is_available` from `true` to `false`. - unsafe { drop_in_place(self.data.get()) }; - } -+ -+ revoke - } - - /// Revokes access to and drops the wrapped object. -@@ -172,10 +176,13 @@ impl Revocable { - /// Access to the object is revoked immediately to new callers of [`Revocable::try_access`], - /// expecting that there are no concurrent users of the object. - /// -+ /// Returns `true` if `&self` has been revoked with this call, `false` if it was revoked -+ /// already. -+ /// - /// # Safety - /// - /// Callers must ensure that there are no more concurrent users of the revocable object. -- pub unsafe fn revoke_nosync(&self) { -+ pub unsafe fn revoke_nosync(&self) -> bool { - // SAFETY: By the safety requirement of this function, the caller ensures that nobody is - // accessing the data anymore and hence we don't have to wait for the grace period to - // finish. -@@ -189,7 +196,10 @@ impl Revocable { - /// If there are concurrent users of the object (i.e., ones that called - /// [`Revocable::try_access`] beforehand and still haven't dropped the returned guard), this - /// function waits for the concurrent access to complete before dropping the wrapped object. -- pub fn revoke(&self) { -+ /// -+ /// Returns `true` if `&self` has been revoked with this call, `false` if it was revoked -+ /// already. -+ pub fn revoke(&self) -> bool { - // SAFETY: By passing `true` we ask `revoke_internal` to wait for the grace period to - // finish. - unsafe { self.revoke_internal::() } -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/sync/completion.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/sync/completion.rs ---- BPI-Router-Linux-kernel/rust/kernel/sync/completion.rs 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/sync/completion.rs 2025-10-22 13:53:56.843167560 -0400 -@@ -0,0 +1,112 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+//! Completion support. -+//! -+//! Reference: -+//! -+//! C header: [`include/linux/completion.h`](srctree/include/linux/completion.h) -+ -+use crate::{bindings, prelude::*, types::Opaque}; -+ -+/// Synchronization primitive to signal when a certain task has been completed. -+/// -+/// The [`Completion`] synchronization primitive signals when a certain task has been completed by -+/// waking up other tasks that have been queued up to wait for the [`Completion`] to be completed. -+/// -+/// # Examples -+/// -+/// ``` -+/// use kernel::sync::{Arc, Completion}; -+/// use kernel::workqueue::{self, impl_has_work, new_work, Work, WorkItem}; -+/// -+/// #[pin_data] -+/// struct MyTask { -+/// #[pin] -+/// work: Work, -+/// #[pin] -+/// done: Completion, -+/// } -+/// -+/// impl_has_work! { -+/// impl HasWork for MyTask { self.work } -+/// } -+/// -+/// impl MyTask { -+/// fn new() -> Result> { -+/// let this = Arc::pin_init(pin_init!(MyTask { -+/// work <- new_work!("MyTask::work"), -+/// done <- Completion::new(), -+/// }), GFP_KERNEL)?; -+/// -+/// let _ = workqueue::system().enqueue(this.clone()); -+/// -+/// Ok(this) -+/// } -+/// -+/// fn wait_for_completion(&self) { -+/// self.done.wait_for_completion(); -+/// -+/// pr_info!("Completion: task complete\n"); -+/// } -+/// } -+/// -+/// impl WorkItem for MyTask { -+/// type Pointer = Arc; -+/// -+/// fn run(this: Arc) { -+/// // process this task -+/// this.done.complete_all(); -+/// } -+/// } -+/// -+/// let task = MyTask::new()?; -+/// task.wait_for_completion(); -+/// # Ok::<(), Error>(()) -+/// ``` -+#[pin_data] -+pub struct Completion { -+ #[pin] -+ inner: Opaque, -+} -+ -+// SAFETY: `Completion` is safe to be send to any task. -+unsafe impl Send for Completion {} -+ -+// SAFETY: `Completion` is safe to be accessed concurrently. -+unsafe impl Sync for Completion {} -+ -+impl Completion { -+ /// Create an initializer for a new [`Completion`]. -+ pub fn new() -> impl PinInit { -+ pin_init!(Self { -+ inner <- Opaque::ffi_init(|slot: *mut bindings::completion| { -+ // SAFETY: `slot` is a valid pointer to an uninitialized `struct completion`. -+ unsafe { bindings::init_completion(slot) }; -+ }), -+ }) -+ } -+ -+ fn as_raw(&self) -> *mut bindings::completion { -+ self.inner.get() -+ } -+ -+ /// Signal all tasks waiting on this completion. -+ /// -+ /// This method wakes up all tasks waiting on this completion; after this operation the -+ /// completion is permanently done, i.e. signals all current and future waiters. -+ pub fn complete_all(&self) { -+ // SAFETY: `self.as_raw()` is a pointer to a valid `struct completion`. -+ unsafe { bindings::complete_all(self.as_raw()) }; -+ } -+ -+ /// Wait for completion of a task. -+ /// -+ /// This method waits for the completion of a task; it is not interruptible and there is no -+ /// timeout. -+ /// -+ /// See also [`Completion::complete_all`]. -+ pub fn wait_for_completion(&self) { -+ // SAFETY: `self.as_raw()` is a pointer to a valid `struct completion`. -+ unsafe { bindings::wait_for_completion(self.as_raw()) }; -+ } -+} -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/sync.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/sync.rs ---- BPI-Router-Linux-kernel/rust/kernel/sync.rs 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/sync.rs 2025-10-22 13:53:56.843167560 -0400 -@@ -10,6 +10,7 @@ use crate::types::Opaque; - use pin_init; - - mod arc; -+pub mod completion; - mod condvar; - pub mod lock; - mod locked_by; -@@ -17,6 +18,7 @@ pub mod poll; - pub mod rcu; - - pub use arc::{Arc, ArcBorrow, UniqueArc}; -+pub use completion::Completion; - pub use condvar::{new_condvar, CondVar, CondVarTimeoutResult}; - pub use lock::global::{global_lock, GlobalGuard, GlobalLock, GlobalLockBackend, GlobalLockedBy}; - pub use lock::mutex::{new_mutex, Mutex, MutexGuard}; -diff -purNx .git BPI-Router-Linux-kernel/rust/kernel/time/hrtimer.rs BPI-Router-Linux-kernel-6.16.12/rust/kernel/time/hrtimer.rs ---- BPI-Router-Linux-kernel/rust/kernel/time/hrtimer.rs 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/kernel/time/hrtimer.rs 2025-10-22 13:53:56.843167560 -0400 -@@ -517,7 +517,7 @@ macro_rules! impl_has_hr_timer { - ) -> *mut Self { - // SAFETY: As per the safety requirement of this function, `ptr` - // is pointing inside a `$timer_type`. -- unsafe { ::kernel::container_of!(ptr, $timer_type, $field).cast_mut() } -+ unsafe { ::kernel::container_of!(ptr, $timer_type, $field) } - } - } - } -diff -purNx .git BPI-Router-Linux-kernel/rust/macros/module.rs BPI-Router-Linux-kernel-6.16.12/rust/macros/module.rs ---- BPI-Router-Linux-kernel/rust/macros/module.rs 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/macros/module.rs 2025-10-22 13:53:56.843167560 -0400 -@@ -57,7 +57,7 @@ impl<'a> ModInfoBuilder<'a> { - {cfg} - #[doc(hidden)] - #[cfg_attr(not(target_os = \"macos\"), link_section = \".modinfo\")] -- #[used] -+ #[used(compiler)] - pub static __{module}_{counter}: [u8; {length}] = *{string}; - ", - cfg = if builtin { -@@ -249,7 +249,7 @@ pub(crate) fn module(ts: TokenStream) -> - // key or a new section. For the moment, keep it simple. - #[cfg(MODULE)] - #[doc(hidden)] -- #[used] -+ #[used(compiler)] - static __IS_RUST_MODULE: () = (); - - static mut __MOD: ::core::mem::MaybeUninit<{type_}> = -@@ -273,7 +273,7 @@ pub(crate) fn module(ts: TokenStream) -> - - #[cfg(MODULE)] - #[doc(hidden)] -- #[used] -+ #[used(compiler)] - #[link_section = \".init.data\"] - static __UNIQUE_ID___addressable_init_module: unsafe extern \"C\" fn() -> i32 = init_module; - -@@ -293,7 +293,7 @@ pub(crate) fn module(ts: TokenStream) -> - - #[cfg(MODULE)] - #[doc(hidden)] -- #[used] -+ #[used(compiler)] - #[link_section = \".exit.data\"] - static __UNIQUE_ID___addressable_cleanup_module: extern \"C\" fn() = cleanup_module; - -@@ -303,7 +303,7 @@ pub(crate) fn module(ts: TokenStream) -> - #[cfg(not(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS))] - #[doc(hidden)] - #[link_section = \"{initcall_section}\"] -- #[used] -+ #[used(compiler)] - pub static __{ident}_initcall: extern \"C\" fn() -> - ::kernel::ffi::c_int = __{ident}_init; - -diff -purNx .git BPI-Router-Linux-kernel/rust/Makefile BPI-Router-Linux-kernel-6.16.12/rust/Makefile ---- BPI-Router-Linux-kernel/rust/Makefile 2025-10-22 13:53:23.663326980 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/rust/Makefile 2025-10-22 13:53:56.839167579 -0400 -@@ -62,6 +62,10 @@ core-cfgs = \ - - core-edition := $(if $(call rustc-min-version,108700),2024,2021) - -+# `rustdoc` did not save the target modifiers, thus workaround for -+# the time being (https://github.com/rust-lang/rust/issues/144521). -+rustdoc_modifiers_workaround := $(if $(call rustc-min-version,108800),-Cunsafe-allow-abi-mismatch=fixed-x18) -+ - # `rustc` recognizes `--remap-path-prefix` since 1.26.0, but `rustdoc` only - # since Rust 1.81.0. Moreover, `rustdoc` ICEs on out-of-tree builds since Rust - # 1.82.0 (https://github.com/rust-lang/rust/issues/138520). Thus workaround both -@@ -74,6 +78,7 @@ quiet_cmd_rustdoc = RUSTDOC $(if $(rustd - -Zunstable-options --generate-link-to-definition \ - --output $(rustdoc_output) \ - --crate-name $(subst rustdoc-,,$@) \ -+ $(rustdoc_modifiers_workaround) \ - $(if $(rustdoc_host),,--sysroot=/dev/null) \ - @$(objtree)/include/generated/rustc_cfg $< - -@@ -103,14 +108,14 @@ rustdoc: rustdoc-core rustdoc-macros rus - rustdoc-macros: private rustdoc_host = yes - rustdoc-macros: private rustc_target_flags = --crate-type proc-macro \ - --extern proc_macro --rustdoc-macros: $(src)/macros/lib.rs FORCE -+rustdoc-macros: $(src)/macros/lib.rs rustdoc-clean FORCE - +$(call if_changed,rustdoc) - - # Starting with Rust 1.82.0, skipping `-Wrustdoc::unescaped_backticks` should - # not be needed -- see https://github.com/rust-lang/rust/pull/128307. - rustdoc-core: private skip_flags = --edition=2021 -Wrustdoc::unescaped_backticks - rustdoc-core: private rustc_target_flags = --edition=$(core-edition) $(core-cfgs) --rustdoc-core: $(RUST_LIB_SRC)/core/src/lib.rs FORCE -+rustdoc-core: $(RUST_LIB_SRC)/core/src/lib.rs rustdoc-clean FORCE - +$(call if_changed,rustdoc) - - rustdoc-compiler_builtins: $(src)/compiler_builtins.rs rustdoc-core FORCE -@@ -122,7 +127,8 @@ rustdoc-ffi: $(src)/ffi.rs rustdoc-core - rustdoc-pin_init_internal: private rustdoc_host = yes - rustdoc-pin_init_internal: private rustc_target_flags = --cfg kernel \ - --extern proc_macro --crate-type proc-macro --rustdoc-pin_init_internal: $(src)/pin-init/internal/src/lib.rs FORCE -+rustdoc-pin_init_internal: $(src)/pin-init/internal/src/lib.rs \ -+ rustdoc-clean FORCE - +$(call if_changed,rustdoc) - - rustdoc-pin_init: private rustdoc_host = yes -@@ -140,6 +146,9 @@ rustdoc-kernel: $(src)/kernel/lib.rs rus - $(obj)/bindings.o FORCE - +$(call if_changed,rustdoc) - -+rustdoc-clean: FORCE -+ $(Q)rm -rf $(rustdoc_output) -+ - quiet_cmd_rustc_test_library = $(RUSTC_OR_CLIPPY_QUIET) TL $< - cmd_rustc_test_library = \ - OBJTREE=$(abspath $(objtree)) \ -@@ -194,6 +203,7 @@ quiet_cmd_rustdoc_test = RUSTDOC T $< - RUST_MODFILE=test.rs \ - OBJTREE=$(abspath $(objtree)) \ - $(RUSTDOC) --test $(rust_common_flags) \ -+ -Zcrate-attr='feature(used_with_arg)' \ - @$(objtree)/include/generated/rustc_cfg \ - $(rustc_target_flags) $(rustdoc_test_target_flags) \ - $(rustdoc_test_quiet) \ -@@ -211,6 +221,7 @@ quiet_cmd_rustdoc_test_kernel = RUSTDOC - --extern bindings --extern uapi \ - --no-run --crate-name kernel -Zunstable-options \ - --sysroot=/dev/null \ -+ $(rustdoc_modifiers_workaround) \ - --test-builder $(objtree)/scripts/rustdoc_test_builder \ - $< $(rustdoc_test_kernel_quiet); \ - $(objtree)/scripts/rustdoc_test_gen -diff -purNx .git BPI-Router-Linux-kernel/samples/damon/mtier.c BPI-Router-Linux-kernel-6.16.12/samples/damon/mtier.c ---- BPI-Router-Linux-kernel/samples/damon/mtier.c 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/samples/damon/mtier.c 2025-10-22 13:53:56.843167560 -0400 -@@ -27,14 +27,14 @@ module_param(node1_end_addr, ulong, 0600 - static int damon_sample_mtier_enable_store( - const char *val, const struct kernel_param *kp); - --static const struct kernel_param_ops enable_param_ops = { -+static const struct kernel_param_ops enabled_param_ops = { - .set = damon_sample_mtier_enable_store, - .get = param_get_bool, - }; - --static bool enable __read_mostly; --module_param_cb(enable, &enable_param_ops, &enable, 0600); --MODULE_PARM_DESC(enable, "Enable of disable DAMON_SAMPLE_MTIER"); -+static bool enabled __read_mostly; -+module_param_cb(enabled, &enabled_param_ops, &enabled, 0600); -+MODULE_PARM_DESC(enabled, "Enable or disable DAMON_SAMPLE_MTIER"); - - static struct damon_ctx *ctxs[2]; - -@@ -151,27 +151,44 @@ static void damon_sample_mtier_stop(void - damon_destroy_ctx(ctxs[1]); - } - -+static bool init_called; -+ - static int damon_sample_mtier_enable_store( - const char *val, const struct kernel_param *kp) - { -- bool enabled = enable; -+ bool is_enabled = enabled; - int err; - -- err = kstrtobool(val, &enable); -+ err = kstrtobool(val, &enabled); - if (err) - return err; - -- if (enable == enabled) -+ if (enabled == is_enabled) -+ return 0; -+ -+ if (!init_called) - return 0; - -- if (enable) -- return damon_sample_mtier_start(); -+ if (enabled) { -+ err = damon_sample_mtier_start(); -+ if (err) -+ enabled = false; -+ return err; -+ } - damon_sample_mtier_stop(); - return 0; - } - - static int __init damon_sample_mtier_init(void) - { -+ int err = 0; -+ -+ init_called = true; -+ if (enabled) { -+ err = damon_sample_mtier_start(); -+ if (err) -+ enabled = false; -+ } - return 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/samples/damon/prcl.c BPI-Router-Linux-kernel-6.16.12/samples/damon/prcl.c ---- BPI-Router-Linux-kernel/samples/damon/prcl.c 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/samples/damon/prcl.c 2025-10-22 13:53:56.843167560 -0400 -@@ -17,14 +17,14 @@ module_param(target_pid, int, 0600); - static int damon_sample_prcl_enable_store( - const char *val, const struct kernel_param *kp); - --static const struct kernel_param_ops enable_param_ops = { -+static const struct kernel_param_ops enabled_param_ops = { - .set = damon_sample_prcl_enable_store, - .get = param_get_bool, - }; - --static bool enable __read_mostly; --module_param_cb(enable, &enable_param_ops, &enable, 0600); --MODULE_PARM_DESC(enable, "Enable of disable DAMON_SAMPLE_WSSE"); -+static bool enabled __read_mostly; -+module_param_cb(enabled, &enabled_param_ops, &enabled, 0600); -+MODULE_PARM_DESC(enabled, "Enable or disable DAMON_SAMPLE_PRCL"); - - static struct damon_ctx *ctx; - static struct pid *target_pidp; -@@ -109,27 +109,44 @@ static void damon_sample_prcl_stop(void) - put_pid(target_pidp); - } - -+static bool init_called; -+ - static int damon_sample_prcl_enable_store( - const char *val, const struct kernel_param *kp) - { -- bool enabled = enable; -+ bool is_enabled = enabled; - int err; - -- err = kstrtobool(val, &enable); -+ err = kstrtobool(val, &enabled); - if (err) - return err; - -- if (enable == enabled) -+ if (enabled == is_enabled) -+ return 0; -+ -+ if (!init_called) - return 0; - -- if (enable) -- return damon_sample_prcl_start(); -+ if (enabled) { -+ err = damon_sample_prcl_start(); -+ if (err) -+ enabled = false; -+ return err; -+ } - damon_sample_prcl_stop(); - return 0; - } - - static int __init damon_sample_prcl_init(void) - { -+ int err = 0; -+ -+ init_called = true; -+ if (enabled) { -+ err = damon_sample_prcl_start(); -+ if (err) -+ enabled = false; -+ } - return 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/samples/damon/wsse.c BPI-Router-Linux-kernel-6.16.12/samples/damon/wsse.c ---- BPI-Router-Linux-kernel/samples/damon/wsse.c 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/samples/damon/wsse.c 2025-10-22 13:53:56.843167560 -0400 -@@ -18,14 +18,14 @@ module_param(target_pid, int, 0600); - static int damon_sample_wsse_enable_store( - const char *val, const struct kernel_param *kp); - --static const struct kernel_param_ops enable_param_ops = { -+static const struct kernel_param_ops enabled_param_ops = { - .set = damon_sample_wsse_enable_store, - .get = param_get_bool, - }; - --static bool enable __read_mostly; --module_param_cb(enable, &enable_param_ops, &enable, 0600); --MODULE_PARM_DESC(enable, "Enable or disable DAMON_SAMPLE_WSSE"); -+static bool enabled __read_mostly; -+module_param_cb(enabled, &enabled_param_ops, &enabled, 0600); -+MODULE_PARM_DESC(enabled, "Enable or disable DAMON_SAMPLE_WSSE"); - - static struct damon_ctx *ctx; - static struct pid *target_pidp; -@@ -89,28 +89,42 @@ static void damon_sample_wsse_stop(void) - put_pid(target_pidp); - } - -+static bool init_called; -+ - static int damon_sample_wsse_enable_store( - const char *val, const struct kernel_param *kp) - { -- bool enabled = enable; -+ bool is_enabled = enabled; - int err; - -- err = kstrtobool(val, &enable); -+ err = kstrtobool(val, &enabled); - if (err) - return err; - -- if (enable == enabled) -+ if (enabled == is_enabled) - return 0; - -- if (enable) -- return damon_sample_wsse_start(); -+ if (enabled) { -+ err = damon_sample_wsse_start(); -+ if (err) -+ enabled = false; -+ return err; -+ } - damon_sample_wsse_stop(); - return 0; - } - - static int __init damon_sample_wsse_init(void) - { -- return 0; -+ int err = 0; -+ -+ init_called = true; -+ if (enabled) { -+ err = damon_sample_wsse_start(); -+ if (err) -+ enabled = false; -+ } -+ return err; - } - - module_init(damon_sample_wsse_init); -diff -purNx .git BPI-Router-Linux-kernel/samples/ftrace/ftrace-direct-modify.c BPI-Router-Linux-kernel-6.16.12/samples/ftrace/ftrace-direct-modify.c ---- BPI-Router-Linux-kernel/samples/ftrace/ftrace-direct-modify.c 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/samples/ftrace/ftrace-direct-modify.c 2025-10-22 13:53:56.843167560 -0400 -@@ -75,8 +75,8 @@ asm ( - CALL_DEPTH_ACCOUNT - " call my_direct_func1\n" - " leave\n" --" .size my_tramp1, .-my_tramp1\n" - ASM_RET -+" .size my_tramp1, .-my_tramp1\n" - - " .type my_tramp2, @function\n" - " .globl my_tramp2\n" -diff -purNx .git BPI-Router-Linux-kernel/samples/mei/mei-amt-version.c BPI-Router-Linux-kernel-6.16.12/samples/mei/mei-amt-version.c ---- BPI-Router-Linux-kernel/samples/mei/mei-amt-version.c 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/samples/mei/mei-amt-version.c 2025-10-22 13:53:56.843167560 -0400 -@@ -69,11 +69,11 @@ - #include - #include - #include -+#include - #include - #include - #include - #include --#include - #include - - /***************************************************************************** -diff -purNx .git BPI-Router-Linux-kernel/scripts/gcc-plugins/gcc-common.h BPI-Router-Linux-kernel-6.16.12/scripts/gcc-plugins/gcc-common.h ---- BPI-Router-Linux-kernel/scripts/gcc-plugins/gcc-common.h 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/scripts/gcc-plugins/gcc-common.h 2025-10-22 13:53:56.843167560 -0400 -@@ -173,10 +173,17 @@ static inline opt_pass *get_pass_for_id( - return g->get_passes()->get_pass_for_id(id); - } - -+#if BUILDING_GCC_VERSION < 16000 - #define TODO_verify_ssa TODO_verify_il - #define TODO_verify_flow TODO_verify_il - #define TODO_verify_stmts TODO_verify_il - #define TODO_verify_rtl_sharing TODO_verify_il -+#else -+#define TODO_verify_ssa 0 -+#define TODO_verify_flow 0 -+#define TODO_verify_stmts 0 -+#define TODO_verify_rtl_sharing 0 -+#endif - - #define INSN_DELETED_P(insn) (insn)->deleted() - -diff -purNx .git BPI-Router-Linux-kernel/scripts/gdb/linux/constants.py.in BPI-Router-Linux-kernel-6.16.12/scripts/gdb/linux/constants.py.in ---- BPI-Router-Linux-kernel/scripts/gdb/linux/constants.py.in 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/scripts/gdb/linux/constants.py.in 2025-10-22 13:53:56.843167560 -0400 -@@ -20,6 +20,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -73,12 +74,12 @@ if IS_BUILTIN(CONFIG_MODULES): - LX_GDBPARSED(MOD_RO_AFTER_INIT) - - /* linux/mount.h */ --LX_VALUE(MNT_NOSUID) --LX_VALUE(MNT_NODEV) --LX_VALUE(MNT_NOEXEC) --LX_VALUE(MNT_NOATIME) --LX_VALUE(MNT_NODIRATIME) --LX_VALUE(MNT_RELATIME) -+LX_GDBPARSED(MNT_NOSUID) -+LX_GDBPARSED(MNT_NODEV) -+LX_GDBPARSED(MNT_NOEXEC) -+LX_GDBPARSED(MNT_NOATIME) -+LX_GDBPARSED(MNT_NODIRATIME) -+LX_GDBPARSED(MNT_RELATIME) - - /* linux/threads.h */ - LX_VALUE(NR_CPUS) -@@ -93,6 +94,12 @@ LX_GDBPARSED(RADIX_TREE_MAP_SIZE) - LX_GDBPARSED(RADIX_TREE_MAP_SHIFT) - LX_GDBPARSED(RADIX_TREE_MAP_MASK) - -+/* linux/maple_tree.h */ -+LX_VALUE(MAPLE_NODE_SLOTS) -+LX_VALUE(MAPLE_RANGE64_SLOTS) -+LX_VALUE(MAPLE_ARANGE64_SLOTS) -+LX_GDBPARSED(MAPLE_NODE_MASK) -+ - /* linux/vmalloc.h */ - LX_VALUE(VM_IOREMAP) - LX_VALUE(VM_ALLOC) -diff -purNx .git BPI-Router-Linux-kernel/scripts/gdb/linux/interrupts.py BPI-Router-Linux-kernel-6.16.12/scripts/gdb/linux/interrupts.py ---- BPI-Router-Linux-kernel/scripts/gdb/linux/interrupts.py 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/scripts/gdb/linux/interrupts.py 2025-10-22 13:53:56.843167560 -0400 -@@ -7,7 +7,7 @@ import gdb - from linux import constants - from linux import cpus - from linux import utils --from linux import radixtree -+from linux import mapletree - - irq_desc_type = utils.CachedType("struct irq_desc") - -@@ -23,12 +23,12 @@ def irqd_is_level(desc): - def show_irq_desc(prec, irq): - text = "" - -- desc = radixtree.lookup(gdb.parse_and_eval("&irq_desc_tree"), irq) -+ desc = mapletree.mtree_load(gdb.parse_and_eval("&sparse_irqs"), irq) - if desc is None: - return text - -- desc = desc.cast(irq_desc_type.get_type()) -- if desc is None: -+ desc = desc.cast(irq_desc_type.get_type().pointer()) -+ if desc == 0: - return text - - if irq_settings_is_hidden(desc): -@@ -110,7 +110,7 @@ def x86_show_mce(prec, var, pfx, desc): - pvar = gdb.parse_and_eval(var) - text = "%*s: " % (prec, pfx) - for cpu in cpus.each_online_cpu(): -- text += "%10u " % (cpus.per_cpu(pvar, cpu)) -+ text += "%10u " % (cpus.per_cpu(pvar, cpu).dereference()) - text += " %s\n" % (desc) - return text - -@@ -142,7 +142,7 @@ def x86_show_interupts(prec): - - if constants.LX_CONFIG_X86_MCE: - text += x86_show_mce(prec, "&mce_exception_count", "MCE", "Machine check exceptions") -- text == x86_show_mce(prec, "&mce_poll_count", "MCP", "Machine check polls") -+ text += x86_show_mce(prec, "&mce_poll_count", "MCP", "Machine check polls") - - text += show_irq_err_count(prec) - -@@ -221,8 +221,8 @@ class LxInterruptList(gdb.Command): - gdb.write("CPU%-8d" % cpu) - gdb.write("\n") - -- if utils.gdb_eval_or_none("&irq_desc_tree") is None: -- return -+ if utils.gdb_eval_or_none("&sparse_irqs") is None: -+ raise gdb.GdbError("Unable to find the sparse IRQ tree, is CONFIG_SPARSE_IRQ enabled?") - - for irq in range(nr_irqs): - gdb.write(show_irq_desc(prec, irq)) -diff -purNx .git BPI-Router-Linux-kernel/scripts/gdb/linux/mapletree.py BPI-Router-Linux-kernel-6.16.12/scripts/gdb/linux/mapletree.py ---- BPI-Router-Linux-kernel/scripts/gdb/linux/mapletree.py 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/scripts/gdb/linux/mapletree.py 2025-10-22 13:53:56.843167560 -0400 -@@ -0,0 +1,252 @@ -+# SPDX-License-Identifier: GPL-2.0 -+# -+# Maple tree helpers -+# -+# Copyright (c) 2025 Broadcom -+# -+# Authors: -+# Florian Fainelli -+ -+import gdb -+ -+from linux import utils -+from linux import constants -+from linux import xarray -+ -+maple_tree_root_type = utils.CachedType("struct maple_tree") -+maple_node_type = utils.CachedType("struct maple_node") -+maple_enode_type = utils.CachedType("void") -+ -+maple_dense = 0 -+maple_leaf_64 = 1 -+maple_range_64 = 2 -+maple_arange_64 = 3 -+ -+class Mas(object): -+ ma_active = 0 -+ ma_start = 1 -+ ma_root = 2 -+ ma_none = 3 -+ ma_pause = 4 -+ ma_overflow = 5 -+ ma_underflow = 6 -+ ma_error = 7 -+ -+ def __init__(self, mt, first, end): -+ if mt.type == maple_tree_root_type.get_type().pointer(): -+ self.tree = mt.dereference() -+ elif mt.type != maple_tree_root_type.get_type(): -+ raise gdb.GdbError("must be {} not {}" -+ .format(maple_tree_root_type.get_type().pointer(), mt.type)) -+ self.tree = mt -+ self.index = first -+ self.last = end -+ self.node = None -+ self.status = self.ma_start -+ self.min = 0 -+ self.max = -1 -+ -+ def is_start(self): -+ # mas_is_start() -+ return self.status == self.ma_start -+ -+ def is_ptr(self): -+ # mas_is_ptr() -+ return self.status == self.ma_root -+ -+ def is_none(self): -+ # mas_is_none() -+ return self.status == self.ma_none -+ -+ def root(self): -+ # mas_root() -+ return self.tree['ma_root'].cast(maple_enode_type.get_type().pointer()) -+ -+ def start(self): -+ # mas_start() -+ if self.is_start() is False: -+ return None -+ -+ self.min = 0 -+ self.max = ~0 -+ -+ while True: -+ self.depth = 0 -+ root = self.root() -+ if xarray.xa_is_node(root): -+ self.depth = 0 -+ self.status = self.ma_active -+ self.node = mte_safe_root(root) -+ self.offset = 0 -+ if mte_dead_node(self.node) is True: -+ continue -+ -+ return None -+ -+ self.node = None -+ # Empty tree -+ if root is None: -+ self.status = self.ma_none -+ self.offset = constants.LX_MAPLE_NODE_SLOTS -+ return None -+ -+ # Single entry tree -+ self.status = self.ma_root -+ self.offset = constants.LX_MAPLE_NODE_SLOTS -+ -+ if self.index != 0: -+ return None -+ -+ return root -+ -+ return None -+ -+ def reset(self): -+ # mas_reset() -+ self.status = self.ma_start -+ self.node = None -+ -+def mte_safe_root(node): -+ if node.type != maple_enode_type.get_type().pointer(): -+ raise gdb.GdbError("{} must be {} not {}" -+ .format(mte_safe_root.__name__, maple_enode_type.get_type().pointer(), node.type)) -+ ulong_type = utils.get_ulong_type() -+ indirect_ptr = node.cast(ulong_type) & ~0x2 -+ val = indirect_ptr.cast(maple_enode_type.get_type().pointer()) -+ return val -+ -+def mte_node_type(entry): -+ ulong_type = utils.get_ulong_type() -+ val = None -+ if entry.type == maple_enode_type.get_type().pointer(): -+ val = entry.cast(ulong_type) -+ elif entry.type == ulong_type: -+ val = entry -+ else: -+ raise gdb.GdbError("{} must be {} not {}" -+ .format(mte_node_type.__name__, maple_enode_type.get_type().pointer(), entry.type)) -+ return (val >> 0x3) & 0xf -+ -+def ma_dead_node(node): -+ if node.type != maple_node_type.get_type().pointer(): -+ raise gdb.GdbError("{} must be {} not {}" -+ .format(ma_dead_node.__name__, maple_node_type.get_type().pointer(), node.type)) -+ ulong_type = utils.get_ulong_type() -+ parent = node['parent'] -+ indirect_ptr = node['parent'].cast(ulong_type) & ~constants.LX_MAPLE_NODE_MASK -+ return indirect_ptr == node -+ -+def mte_to_node(enode): -+ ulong_type = utils.get_ulong_type() -+ if enode.type == maple_enode_type.get_type().pointer(): -+ indirect_ptr = enode.cast(ulong_type) -+ elif enode.type == ulong_type: -+ indirect_ptr = enode -+ else: -+ raise gdb.GdbError("{} must be {} not {}" -+ .format(mte_to_node.__name__, maple_enode_type.get_type().pointer(), enode.type)) -+ indirect_ptr = indirect_ptr & ~constants.LX_MAPLE_NODE_MASK -+ return indirect_ptr.cast(maple_node_type.get_type().pointer()) -+ -+def mte_dead_node(enode): -+ if enode.type != maple_enode_type.get_type().pointer(): -+ raise gdb.GdbError("{} must be {} not {}" -+ .format(mte_dead_node.__name__, maple_enode_type.get_type().pointer(), enode.type)) -+ node = mte_to_node(enode) -+ return ma_dead_node(node) -+ -+def ma_is_leaf(tp): -+ result = tp < maple_range_64 -+ return tp < maple_range_64 -+ -+def mt_pivots(t): -+ if t == maple_dense: -+ return 0 -+ elif t == maple_leaf_64 or t == maple_range_64: -+ return constants.LX_MAPLE_RANGE64_SLOTS - 1 -+ elif t == maple_arange_64: -+ return constants.LX_MAPLE_ARANGE64_SLOTS - 1 -+ -+def ma_pivots(node, t): -+ if node.type != maple_node_type.get_type().pointer(): -+ raise gdb.GdbError("{}: must be {} not {}" -+ .format(ma_pivots.__name__, maple_node_type.get_type().pointer(), node.type)) -+ if t == maple_arange_64: -+ return node['ma64']['pivot'] -+ elif t == maple_leaf_64 or t == maple_range_64: -+ return node['mr64']['pivot'] -+ else: -+ return None -+ -+def ma_slots(node, tp): -+ if node.type != maple_node_type.get_type().pointer(): -+ raise gdb.GdbError("{}: must be {} not {}" -+ .format(ma_slots.__name__, maple_node_type.get_type().pointer(), node.type)) -+ if tp == maple_arange_64: -+ return node['ma64']['slot'] -+ elif tp == maple_range_64 or tp == maple_leaf_64: -+ return node['mr64']['slot'] -+ elif tp == maple_dense: -+ return node['slot'] -+ else: -+ return None -+ -+def mt_slot(mt, slots, offset): -+ ulong_type = utils.get_ulong_type() -+ return slots[offset].cast(ulong_type) -+ -+def mtree_lookup_walk(mas): -+ ulong_type = utils.get_ulong_type() -+ n = mas.node -+ -+ while True: -+ node = mte_to_node(n) -+ tp = mte_node_type(n) -+ pivots = ma_pivots(node, tp) -+ end = mt_pivots(tp) -+ offset = 0 -+ while True: -+ if pivots[offset] >= mas.index: -+ break -+ if offset >= end: -+ break -+ offset += 1 -+ -+ slots = ma_slots(node, tp) -+ n = mt_slot(mas.tree, slots, offset) -+ if ma_dead_node(node) is True: -+ mas.reset() -+ return None -+ break -+ -+ if ma_is_leaf(tp) is True: -+ break -+ -+ return n -+ -+def mtree_load(mt, index): -+ ulong_type = utils.get_ulong_type() -+ # MT_STATE(...) -+ mas = Mas(mt, index, index) -+ entry = None -+ -+ while True: -+ entry = mas.start() -+ if mas.is_none(): -+ return None -+ -+ if mas.is_ptr(): -+ if index != 0: -+ entry = None -+ return entry -+ -+ entry = mtree_lookup_walk(mas) -+ if entry is None and mas.is_start(): -+ continue -+ else: -+ break -+ -+ if xarray.xa_is_zero(entry): -+ return None -+ -+ return entry -diff -purNx .git BPI-Router-Linux-kernel/scripts/gdb/linux/vfs.py BPI-Router-Linux-kernel-6.16.12/scripts/gdb/linux/vfs.py ---- BPI-Router-Linux-kernel/scripts/gdb/linux/vfs.py 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/scripts/gdb/linux/vfs.py 2025-10-22 13:53:56.843167560 -0400 -@@ -22,7 +22,7 @@ def dentry_name(d): - if parent == d or parent == 0: - return "" - p = dentry_name(d['d_parent']) + "/" -- return p + d['d_iname'].string() -+ return p + d['d_name']['name'].string() - - class DentryName(gdb.Function): - """Return string of the full path of a dentry. -diff -purNx .git BPI-Router-Linux-kernel/scripts/gdb/linux/xarray.py BPI-Router-Linux-kernel-6.16.12/scripts/gdb/linux/xarray.py ---- BPI-Router-Linux-kernel/scripts/gdb/linux/xarray.py 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/scripts/gdb/linux/xarray.py 2025-10-22 13:53:56.843167560 -0400 -@@ -0,0 +1,28 @@ -+# SPDX-License-Identifier: GPL-2.0 -+# -+# Xarray helpers -+# -+# Copyright (c) 2025 Broadcom -+# -+# Authors: -+# Florian Fainelli -+ -+import gdb -+ -+from linux import utils -+from linux import constants -+ -+def xa_is_internal(entry): -+ ulong_type = utils.get_ulong_type() -+ return ((entry.cast(ulong_type) & 3) == 2) -+ -+def xa_mk_internal(v): -+ return ((v << 2) | 2) -+ -+def xa_is_zero(entry): -+ ulong_type = utils.get_ulong_type() -+ return entry.cast(ulong_type) == xa_mk_internal(257) -+ -+def xa_is_node(entry): -+ ulong_type = utils.get_ulong_type() -+ return xa_is_internal(entry) and (entry.cast(ulong_type) > 4096) -diff -purNx .git BPI-Router-Linux-kernel/scripts/gendwarfksyms/gendwarfksyms.h BPI-Router-Linux-kernel-6.16.12/scripts/gendwarfksyms/gendwarfksyms.h ---- BPI-Router-Linux-kernel/scripts/gendwarfksyms/gendwarfksyms.h 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/scripts/gendwarfksyms/gendwarfksyms.h 2025-10-22 13:53:56.843167560 -0400 -@@ -216,24 +216,14 @@ int cache_get(struct cache *cache, unsig - void cache_init(struct cache *cache); - void cache_free(struct cache *cache); - --static inline void __cache_mark_expanded(struct cache *cache, uintptr_t addr) --{ -- cache_set(cache, addr, 1); --} -- --static inline bool __cache_was_expanded(struct cache *cache, uintptr_t addr) --{ -- return cache_get(cache, addr) == 1; --} -- - static inline void cache_mark_expanded(struct cache *cache, void *addr) - { -- __cache_mark_expanded(cache, (uintptr_t)addr); -+ cache_set(cache, (unsigned long)addr, 1); - } - - static inline bool cache_was_expanded(struct cache *cache, void *addr) - { -- return __cache_was_expanded(cache, (uintptr_t)addr); -+ return cache_get(cache, (unsigned long)addr) == 1; - } - - /* -diff -purNx .git BPI-Router-Linux-kernel/scripts/gendwarfksyms/types.c BPI-Router-Linux-kernel-6.16.12/scripts/gendwarfksyms/types.c ---- BPI-Router-Linux-kernel/scripts/gendwarfksyms/types.c 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/scripts/gendwarfksyms/types.c 2025-10-22 13:53:56.843167560 -0400 -@@ -333,37 +333,11 @@ static void calculate_version(struct ver - cache_free(&expansion_cache); - } - --static void __type_expand(struct die *cache, struct type_expansion *type, -- bool recursive); -- --static void type_expand_child(struct die *cache, struct type_expansion *type, -- bool recursive) --{ -- struct type_expansion child; -- char *name; -- -- name = get_type_name(cache); -- if (!name) { -- __type_expand(cache, type, recursive); -- return; -- } -- -- if (recursive && !__cache_was_expanded(&expansion_cache, cache->addr)) { -- __cache_mark_expanded(&expansion_cache, cache->addr); -- type_expansion_init(&child); -- __type_expand(cache, &child, true); -- type_map_add(name, &child); -- type_expansion_free(&child); -- } -- -- type_expansion_append(type, name, name); --} -- --static void __type_expand(struct die *cache, struct type_expansion *type, -- bool recursive) -+static void __type_expand(struct die *cache, struct type_expansion *type) - { - struct die_fragment *df; - struct die *child; -+ char *name; - - list_for_each_entry(df, &cache->fragments, list) { - switch (df->type) { -@@ -379,7 +353,12 @@ static void __type_expand(struct die *ca - error("unknown child: %" PRIxPTR, - df->data.addr); - -- type_expand_child(child, type, recursive); -+ name = get_type_name(child); -+ if (name) -+ type_expansion_append(type, name, name); -+ else -+ __type_expand(child, type); -+ - break; - case FRAGMENT_LINEBREAK: - /* -@@ -397,12 +376,17 @@ static void __type_expand(struct die *ca - } - } - --static void type_expand(struct die *cache, struct type_expansion *type, -- bool recursive) -+static void type_expand(const char *name, struct die *cache, -+ struct type_expansion *type) - { -+ const char *override; -+ - type_expansion_init(type); -- __type_expand(cache, type, recursive); -- cache_free(&expansion_cache); -+ -+ if (stable && kabi_get_type_string(name, &override)) -+ type_parse(name, override, type); -+ else -+ __type_expand(cache, type); - } - - static void type_parse(const char *name, const char *str, -@@ -416,8 +400,6 @@ static void type_parse(const char *name, - if (!*str) - error("empty type string override for '%s'", name); - -- type_expansion_init(type); -- - for (pos = 0; str[pos]; ++pos) { - bool empty; - char marker = ' '; -@@ -478,7 +460,6 @@ static void type_parse(const char *name, - static void expand_type(struct die *cache, void *arg) - { - struct type_expansion type; -- const char *override; - char *name; - - if (cache->mapped) -@@ -504,11 +485,7 @@ static void expand_type(struct die *cach - - debug("%s", name); - -- if (stable && kabi_get_type_string(name, &override)) -- type_parse(name, override, &type); -- else -- type_expand(cache, &type, true); -- -+ type_expand(name, cache, &type); - type_map_add(name, &type); - type_expansion_free(&type); - free(name); -@@ -518,7 +495,6 @@ static void expand_symbol(struct symbol - { - struct type_expansion type; - struct version version; -- const char *override; - struct die *cache; - - /* -@@ -532,10 +508,7 @@ static void expand_symbol(struct symbol - if (__die_map_get(sym->die_addr, DIE_SYMBOL, &cache)) - return; /* We'll warn about missing CRCs later. */ - -- if (stable && kabi_get_type_string(sym->name, &override)) -- type_parse(sym->name, override, &type); -- else -- type_expand(cache, &type, false); -+ type_expand(sym->name, cache, &type); - - /* If the symbol already has a version, don't calculate it again. */ - if (sym->state != SYMBOL_PROCESSED) { -diff -purNx .git BPI-Router-Linux-kernel/scripts/generate_rust_target.rs BPI-Router-Linux-kernel-6.16.12/scripts/generate_rust_target.rs ---- BPI-Router-Linux-kernel/scripts/generate_rust_target.rs 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/scripts/generate_rust_target.rs 2025-10-22 13:53:56.843167560 -0400 -@@ -225,7 +225,11 @@ fn main() { - ts.push("features", features); - ts.push("llvm-target", "x86_64-linux-gnu"); - ts.push("supported-sanitizers", ["kcfi", "kernel-address"]); -- ts.push("target-pointer-width", "64"); -+ if cfg.rustc_version_atleast(1, 91, 0) { -+ ts.push("target-pointer-width", 64); -+ } else { -+ ts.push("target-pointer-width", "64"); -+ } - } else if cfg.has("X86_32") { - // This only works on UML, as i386 otherwise needs regparm support in rustc - if !cfg.has("UML") { -@@ -245,7 +249,11 @@ fn main() { - } - ts.push("features", features); - ts.push("llvm-target", "i386-unknown-linux-gnu"); -- ts.push("target-pointer-width", "32"); -+ if cfg.rustc_version_atleast(1, 91, 0) { -+ ts.push("target-pointer-width", 32); -+ } else { -+ ts.push("target-pointer-width", "32"); -+ } - } else if cfg.has("LOONGARCH") { - panic!("loongarch uses the builtin rustc loongarch64-unknown-none-softfloat target"); - } else { -diff -purNx .git BPI-Router-Linux-kernel/scripts/kconfig/gconf.c BPI-Router-Linux-kernel-6.16.12/scripts/kconfig/gconf.c ---- BPI-Router-Linux-kernel/scripts/kconfig/gconf.c 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/scripts/kconfig/gconf.c 2025-10-22 13:53:56.843167560 -0400 -@@ -748,7 +748,7 @@ static void renderer_edited(GtkCellRende - struct symbol *sym; - - if (!gtk_tree_model_get_iter(model2, &iter, path)) -- return; -+ goto free; - - gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); - sym = menu->sym; -@@ -760,6 +760,7 @@ static void renderer_edited(GtkCellRende - - update_tree(&rootmenu, NULL); - -+free: - gtk_tree_path_free(path); - } - -@@ -942,13 +943,14 @@ on_treeview2_key_press_event(GtkWidget * - void - on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data) - { -+ GtkTreeModel *model = gtk_tree_view_get_model(treeview); - GtkTreeSelection *selection; - GtkTreeIter iter; - struct menu *menu; - - selection = gtk_tree_view_get_selection(treeview); -- if (gtk_tree_selection_get_selected(selection, &model2, &iter)) { -- gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); -+ if (gtk_tree_selection_get_selected(selection, &model, &iter)) { -+ gtk_tree_model_get(model, &iter, COL_MENU, &menu, -1); - text_insert_help(menu); - } - } -diff -purNx .git BPI-Router-Linux-kernel/scripts/kconfig/lxdialog/inputbox.c BPI-Router-Linux-kernel-6.16.12/scripts/kconfig/lxdialog/inputbox.c ---- BPI-Router-Linux-kernel/scripts/kconfig/lxdialog/inputbox.c 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/scripts/kconfig/lxdialog/inputbox.c 2025-10-22 13:53:56.843167560 -0400 -@@ -39,8 +39,10 @@ int dialog_inputbox(const char *title, c - - if (!init) - instr[0] = '\0'; -- else -- strcpy(instr, init); -+ else { -+ strncpy(instr, init, sizeof(dialog_input_result) - 1); -+ instr[sizeof(dialog_input_result) - 1] = '\0'; -+ } - - do_resize: - if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGHT_MIN)) -diff -purNx .git BPI-Router-Linux-kernel/scripts/kconfig/lxdialog/menubox.c BPI-Router-Linux-kernel-6.16.12/scripts/kconfig/lxdialog/menubox.c ---- BPI-Router-Linux-kernel/scripts/kconfig/lxdialog/menubox.c 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/scripts/kconfig/lxdialog/menubox.c 2025-10-22 13:53:56.843167560 -0400 -@@ -264,7 +264,7 @@ do_resize: - if (key < 256 && isalpha(key)) - key = tolower(key); - -- if (strchr("ynmh", key)) -+ if (strchr("ynmh ", key)) - i = max_choice; - else { - for (i = choice + 1; i < max_choice; i++) { -diff -purNx .git BPI-Router-Linux-kernel/scripts/kconfig/nconf.c BPI-Router-Linux-kernel-6.16.12/scripts/kconfig/nconf.c ---- BPI-Router-Linux-kernel/scripts/kconfig/nconf.c 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/scripts/kconfig/nconf.c 2025-10-22 13:53:56.843167560 -0400 -@@ -593,6 +593,8 @@ static void item_add_str(const char *fmt - tmp_str, - sizeof(k_menu_items[index].str)); - -+ k_menu_items[index].str[sizeof(k_menu_items[index].str) - 1] = '\0'; -+ - free_item(curses_menu_items[index]); - curses_menu_items[index] = new_item( - k_menu_items[index].str, -diff -purNx .git BPI-Router-Linux-kernel/scripts/kconfig/nconf.gui.c BPI-Router-Linux-kernel-6.16.12/scripts/kconfig/nconf.gui.c ---- BPI-Router-Linux-kernel/scripts/kconfig/nconf.gui.c 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/scripts/kconfig/nconf.gui.c 2025-10-22 13:53:56.843167560 -0400 -@@ -359,6 +359,7 @@ int dialog_inputbox(WINDOW *main_window, - x = (columns-win_cols)/2; - - strncpy(result, init, *result_len); -+ result[*result_len - 1] = '\0'; - - /* create the windows */ - win = newwin(win_lines, win_cols, y, x); -diff -purNx .git BPI-Router-Linux-kernel/scripts/kconfig/qconf.cc BPI-Router-Linux-kernel-6.16.12/scripts/kconfig/qconf.cc ---- BPI-Router-Linux-kernel/scripts/kconfig/qconf.cc 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/scripts/kconfig/qconf.cc 2025-10-22 13:53:56.843167560 -0400 -@@ -478,7 +478,7 @@ void ConfigList::updateListAllForAll() - while (it.hasNext()) { - ConfigList *list = it.next(); - -- list->updateList(); -+ list->updateListAll(); - } - } - -diff -purNx .git BPI-Router-Linux-kernel/scripts/Makefile.build BPI-Router-Linux-kernel-6.16.12/scripts/Makefile.build ---- BPI-Router-Linux-kernel/scripts/Makefile.build 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/scripts/Makefile.build 2025-10-22 13:53:56.843167560 -0400 -@@ -312,10 +312,11 @@ $(obj)/%.lst: $(obj)/%.c FORCE - # - Stable since Rust 1.82.0: `feature(asm_const)`, `feature(raw_ref_op)`. - # - Stable since Rust 1.87.0: `feature(asm_goto)`. - # - Expected to become stable: `feature(arbitrary_self_types)`. -+# - To be determined: `feature(used_with_arg)`. - # - # Please see https://github.com/Rust-for-Linux/linux/issues/2 for details on - # the unstable features in use. --rust_allowed_features := asm_const,asm_goto,arbitrary_self_types,lint_reasons,raw_ref_op -+rust_allowed_features := asm_const,asm_goto,arbitrary_self_types,lint_reasons,raw_ref_op,used_with_arg - - # `--out-dir` is required to avoid temporaries being created by `rustc` in the - # current working directory, which may be not accessible in the out-of-tree -diff -purNx .git BPI-Router-Linux-kernel/scripts/Makefile.kasan BPI-Router-Linux-kernel-6.16.12/scripts/Makefile.kasan ---- BPI-Router-Linux-kernel/scripts/Makefile.kasan 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/scripts/Makefile.kasan 2025-10-22 13:53:56.843167560 -0400 -@@ -86,10 +86,14 @@ kasan_params += hwasan-instrument-stack= - hwasan-use-short-granules=0 \ - hwasan-inline-all-checks=0 - --# Instrument memcpy/memset/memmove calls by using instrumented __hwasan_mem*(). --ifeq ($(call clang-min-version, 150000)$(call gcc-min-version, 130000),y) -- kasan_params += hwasan-kernel-mem-intrinsic-prefix=1 --endif -+# Instrument memcpy/memset/memmove calls by using instrumented __(hw)asan_mem*(). -+ifdef CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX -+ ifdef CONFIG_CC_IS_GCC -+ kasan_params += asan-kernel-mem-intrinsic-prefix=1 -+ else -+ kasan_params += hwasan-kernel-mem-intrinsic-prefix=1 -+ endif -+endif # CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX - - endif # CONFIG_KASAN_SW_TAGS - -diff -purNx .git BPI-Router-Linux-kernel/scripts/misc-check BPI-Router-Linux-kernel-6.16.12/scripts/misc-check ---- BPI-Router-Linux-kernel/scripts/misc-check 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/scripts/misc-check 2025-10-22 13:53:56.843167560 -0400 -@@ -62,6 +62,15 @@ check_unnecessary_include_linux_export_h - xargs -r printf "%s: warning: EXPORT_SYMBOL() is not used, but #include is present\n" >&2 - } - --check_tracked_ignored_files --check_missing_include_linux_export_h --check_unnecessary_include_linux_export_h -+case "${KBUILD_EXTRA_WARN}" in -+*1*) -+ check_tracked_ignored_files -+ ;; -+esac -+ -+case "${KBUILD_EXTRA_WARN}" in -+*2*) -+ check_missing_include_linux_export_h -+ check_unnecessary_include_linux_export_h -+ ;; -+esac -diff -purNx .git BPI-Router-Linux-kernel/security/apparmor/domain.c BPI-Router-Linux-kernel-6.16.12/security/apparmor/domain.c ---- BPI-Router-Linux-kernel/security/apparmor/domain.c 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/security/apparmor/domain.c 2025-10-22 13:53:56.843167560 -0400 -@@ -508,6 +508,7 @@ static const char *next_name(int xtype, - * @name: returns: name tested to find label (NOT NULL) - * - * Returns: refcounted label, or NULL on failure (MAYBE NULL) -+ * @name will always be set with the last name tried - */ - struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex, - const char **name) -@@ -517,6 +518,7 @@ struct aa_label *x_table_lookup(struct a - struct aa_label *label = NULL; - u32 xtype = xindex & AA_X_TYPE_MASK; - int index = xindex & AA_X_INDEX_MASK; -+ const char *next; - - AA_BUG(!name); - -@@ -524,25 +526,27 @@ struct aa_label *x_table_lookup(struct a - /* TODO: move lookup parsing to unpack time so this is a straight - * index into the resultant label - */ -- for (*name = rules->file->trans.table[index]; !label && *name; -- *name = next_name(xtype, *name)) { -+ for (next = rules->file->trans.table[index]; next; -+ next = next_name(xtype, next)) { -+ const char *lookup = (*next == '&') ? next + 1 : next; -+ *name = next; - if (xindex & AA_X_CHILD) { -- struct aa_profile *new_profile; -- /* release by caller */ -- new_profile = aa_find_child(profile, *name); -- if (new_profile) -- label = &new_profile->label; -+ /* TODO: switich to parse to get stack of child */ -+ struct aa_profile *new = aa_find_child(profile, lookup); -+ -+ if (new) -+ /* release by caller */ -+ return &new->label; - continue; - } -- label = aa_label_parse(&profile->label, *name, GFP_KERNEL, -+ label = aa_label_parse(&profile->label, lookup, GFP_KERNEL, - true, false); -- if (IS_ERR(label)) -- label = NULL; -+ if (!IS_ERR_OR_NULL(label)) -+ /* release by caller */ -+ return label; - } - -- /* released by caller */ -- -- return label; -+ return NULL; - } - - /** -@@ -567,9 +571,9 @@ static struct aa_label *x_to_label(struc - struct aa_ruleset *rules = list_first_entry(&profile->rules, - typeof(*rules), list); - struct aa_label *new = NULL; -+ struct aa_label *stack = NULL; - struct aa_ns *ns = profile->ns; - u32 xtype = xindex & AA_X_TYPE_MASK; -- const char *stack = NULL; - - switch (xtype) { - case AA_X_NONE: -@@ -578,13 +582,14 @@ static struct aa_label *x_to_label(struc - break; - case AA_X_TABLE: - /* TODO: fix when perm mapping done at unload */ -- stack = rules->file->trans.table[xindex & AA_X_INDEX_MASK]; -- if (*stack != '&') { -- /* released by caller */ -- new = x_table_lookup(profile, xindex, lookupname); -- stack = NULL; -+ /* released by caller -+ * if null for both stack and direct want to try fallback -+ */ -+ new = x_table_lookup(profile, xindex, lookupname); -+ if (!new || **lookupname != '&') - break; -- } -+ stack = new; -+ new = NULL; - fallthrough; /* to X_NAME */ - case AA_X_NAME: - if (xindex & AA_X_CHILD) -@@ -599,6 +604,7 @@ static struct aa_label *x_to_label(struc - break; - } - -+ /* fallback transition check */ - if (!new) { - if (xindex & AA_X_INHERIT) { - /* (p|c|n)ix - don't change profile but do -@@ -617,12 +623,12 @@ static struct aa_label *x_to_label(struc - /* base the stack on post domain transition */ - struct aa_label *base = new; - -- new = aa_label_parse(base, stack, GFP_KERNEL, true, false); -- if (IS_ERR(new)) -- new = NULL; -+ new = aa_label_merge(base, stack, GFP_KERNEL); -+ /* null on error */ - aa_put_label(base); - } - -+ aa_put_label(stack); - /* released by caller */ - return new; - } -diff -purNx .git BPI-Router-Linux-kernel/security/apparmor/file.c BPI-Router-Linux-kernel-6.16.12/security/apparmor/file.c ---- BPI-Router-Linux-kernel/security/apparmor/file.c 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/security/apparmor/file.c 2025-10-22 13:53:56.843167560 -0400 -@@ -423,9 +423,11 @@ int aa_path_link(const struct cred *subj - { - struct path link = { .mnt = new_dir->mnt, .dentry = new_dentry }; - struct path target = { .mnt = new_dir->mnt, .dentry = old_dentry }; -+ struct inode *inode = d_backing_inode(old_dentry); -+ vfsuid_t vfsuid = i_uid_into_vfsuid(mnt_idmap(target.mnt), inode); - struct path_cond cond = { -- d_backing_inode(old_dentry)->i_uid, -- d_backing_inode(old_dentry)->i_mode -+ .uid = vfsuid_into_kuid(vfsuid), -+ .mode = inode->i_mode, - }; - char *buffer = NULL, *buffer2 = NULL; - struct aa_profile *profile; -diff -purNx .git BPI-Router-Linux-kernel/security/apparmor/include/lib.h BPI-Router-Linux-kernel-6.16.12/security/apparmor/include/lib.h ---- BPI-Router-Linux-kernel/security/apparmor/include/lib.h 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/security/apparmor/include/lib.h 2025-10-22 13:53:56.843167560 -0400 -@@ -48,7 +48,11 @@ extern struct aa_dfa *stacksplitdfa; - #define AA_BUG_FMT(X, fmt, args...) \ - WARN((X), "AppArmor WARN %s: (" #X "): " fmt, __func__, ##args) - #else --#define AA_BUG_FMT(X, fmt, args...) no_printk(fmt, ##args) -+#define AA_BUG_FMT(X, fmt, args...) \ -+ do { \ -+ BUILD_BUG_ON_INVALID(X); \ -+ no_printk(fmt, ##args); \ -+ } while (0) - #endif - - #define AA_ERROR(fmt, args...) \ -diff -purNx .git BPI-Router-Linux-kernel/security/apparmor/include/match.h BPI-Router-Linux-kernel-6.16.12/security/apparmor/include/match.h ---- BPI-Router-Linux-kernel/security/apparmor/include/match.h 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/security/apparmor/include/match.h 2025-10-22 13:53:56.843167560 -0400 -@@ -137,17 +137,15 @@ aa_state_t aa_dfa_matchn_until(struct aa - - void aa_dfa_free_kref(struct kref *kref); - --#define WB_HISTORY_SIZE 24 -+/* This needs to be a power of 2 */ -+#define WB_HISTORY_SIZE 32 - struct match_workbuf { -- unsigned int count; - unsigned int pos; - unsigned int len; -- unsigned int size; /* power of 2, same as history size */ -- unsigned int history[WB_HISTORY_SIZE]; -+ aa_state_t history[WB_HISTORY_SIZE]; - }; - #define DEFINE_MATCH_WB(N) \ - struct match_workbuf N = { \ -- .count = 0, \ - .pos = 0, \ - .len = 0, \ - } -diff -purNx .git BPI-Router-Linux-kernel/security/apparmor/lsm.c BPI-Router-Linux-kernel-6.16.12/security/apparmor/lsm.c ---- BPI-Router-Linux-kernel/security/apparmor/lsm.c 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/security/apparmor/lsm.c 2025-10-22 13:53:56.843167560 -0400 -@@ -2149,12 +2149,12 @@ static int __init apparmor_nf_ip_init(vo - __initcall(apparmor_nf_ip_init); - #endif - --static char nulldfa_src[] = { -+static char nulldfa_src[] __aligned(8) = { - #include "nulldfa.in" - }; - static struct aa_dfa *nulldfa; - --static char stacksplitdfa_src[] = { -+static char stacksplitdfa_src[] __aligned(8) = { - #include "stacksplitdfa.in" - }; - struct aa_dfa *stacksplitdfa; -diff -purNx .git BPI-Router-Linux-kernel/security/apparmor/match.c BPI-Router-Linux-kernel-6.16.12/security/apparmor/match.c ---- BPI-Router-Linux-kernel/security/apparmor/match.c 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/security/apparmor/match.c 2025-10-22 13:53:56.843167560 -0400 -@@ -679,34 +679,35 @@ aa_state_t aa_dfa_matchn_until(struct aa - return state; - } - --#define inc_wb_pos(wb) \ --do { \ -+#define inc_wb_pos(wb) \ -+do { \ -+ BUILD_BUG_ON_NOT_POWER_OF_2(WB_HISTORY_SIZE); \ - wb->pos = (wb->pos + 1) & (WB_HISTORY_SIZE - 1); \ -- wb->len = (wb->len + 1) & (WB_HISTORY_SIZE - 1); \ -+ wb->len = (wb->len + 1) > WB_HISTORY_SIZE ? WB_HISTORY_SIZE : \ -+ wb->len + 1; \ - } while (0) - - /* For DFAs that don't support extended tagging of states */ -+/* adjust is only set if is_loop returns true */ - static bool is_loop(struct match_workbuf *wb, aa_state_t state, - unsigned int *adjust) - { -- aa_state_t pos = wb->pos; -- aa_state_t i; -+ int pos = wb->pos; -+ int i; - - if (wb->history[pos] < state) - return false; - -- for (i = 0; i <= wb->len; i++) { -+ for (i = 0; i < wb->len; i++) { - if (wb->history[pos] == state) { - *adjust = i; - return true; - } -- if (pos == 0) -- pos = WB_HISTORY_SIZE; -- pos--; -+ /* -1 wraps to WB_HISTORY_SIZE - 1 */ -+ pos = (pos - 1) & (WB_HISTORY_SIZE - 1); - } - -- *adjust = i; -- return true; -+ return false; - } - - static aa_state_t leftmatch_fb(struct aa_dfa *dfa, aa_state_t start, -diff -purNx .git BPI-Router-Linux-kernel/security/apparmor/policy_unpack_test.c BPI-Router-Linux-kernel-6.16.12/security/apparmor/policy_unpack_test.c ---- BPI-Router-Linux-kernel/security/apparmor/policy_unpack_test.c 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/security/apparmor/policy_unpack_test.c 2025-10-22 13:53:56.843167560 -0400 -@@ -9,6 +9,8 @@ - #include "include/policy.h" - #include "include/policy_unpack.h" - -+#include -+ - #define TEST_STRING_NAME "TEST_STRING" - #define TEST_STRING_DATA "testing" - #define TEST_STRING_BUF_OFFSET \ -@@ -80,7 +82,7 @@ static struct aa_ext *build_aa_ext_struc - *(buf + 1) = strlen(TEST_U32_NAME) + 1; - strscpy(buf + 3, TEST_U32_NAME, e->end - (void *)(buf + 3)); - *(buf + 3 + strlen(TEST_U32_NAME) + 1) = AA_U32; -- *((__le32 *)(buf + 3 + strlen(TEST_U32_NAME) + 2)) = cpu_to_le32(TEST_U32_DATA); -+ put_unaligned_le32(TEST_U32_DATA, buf + 3 + strlen(TEST_U32_NAME) + 2); - - buf = e->start + TEST_NAMED_U64_BUF_OFFSET; - *buf = AA_NAME; -@@ -103,7 +105,7 @@ static struct aa_ext *build_aa_ext_struc - *(buf + 1) = strlen(TEST_ARRAY_NAME) + 1; - strscpy(buf + 3, TEST_ARRAY_NAME, e->end - (void *)(buf + 3)); - *(buf + 3 + strlen(TEST_ARRAY_NAME) + 1) = AA_ARRAY; -- *((__le16 *)(buf + 3 + strlen(TEST_ARRAY_NAME) + 2)) = cpu_to_le16(TEST_ARRAY_SIZE); -+ put_unaligned_le16(TEST_ARRAY_SIZE, buf + 3 + strlen(TEST_ARRAY_NAME) + 2); - - return e; - } -diff -purNx .git BPI-Router-Linux-kernel/security/inode.c BPI-Router-Linux-kernel-6.16.12/security/inode.c ---- BPI-Router-Linux-kernel/security/inode.c 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/security/inode.c 2025-10-22 13:53:56.843167560 -0400 -@@ -159,7 +159,6 @@ static struct dentry *securityfs_create_ - inode->i_fop = fops; - } - d_instantiate(dentry, inode); -- dget(dentry); - inode_unlock(dir); - return dentry; - -@@ -306,7 +305,6 @@ void securityfs_remove(struct dentry *de - simple_rmdir(dir, dentry); - else - simple_unlink(dir, dentry); -- dput(dentry); - } - inode_unlock(dir); - simple_release_fs(&mount, &mount_count); -diff -purNx .git BPI-Router-Linux-kernel/security/keys/gc.c BPI-Router-Linux-kernel-6.16.12/security/keys/gc.c ---- BPI-Router-Linux-kernel/security/keys/gc.c 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/security/keys/gc.c 2025-10-22 13:53:56.843167560 -0400 -@@ -218,8 +218,8 @@ continue_scanning: - key = rb_entry(cursor, struct key, serial_node); - cursor = rb_next(cursor); - -- if (test_bit(KEY_FLAG_FINAL_PUT, &key->flags)) { -- smp_mb(); /* Clobber key->user after FINAL_PUT seen. */ -+ if (!test_bit_acquire(KEY_FLAG_USER_ALIVE, &key->flags)) { -+ /* Clobber key->user after final put seen. */ - goto found_unreferenced_key; - } - -diff -purNx .git BPI-Router-Linux-kernel/security/keys/key.c BPI-Router-Linux-kernel-6.16.12/security/keys/key.c ---- BPI-Router-Linux-kernel/security/keys/key.c 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/security/keys/key.c 2025-10-22 13:53:56.843167560 -0400 -@@ -298,6 +298,7 @@ struct key *key_alloc(struct key_type *t - key->restrict_link = restrict_link; - key->last_used_at = ktime_get_real_seconds(); - -+ key->flags |= 1 << KEY_FLAG_USER_ALIVE; - if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) - key->flags |= 1 << KEY_FLAG_IN_QUOTA; - if (flags & KEY_ALLOC_BUILT_IN) -@@ -658,8 +659,8 @@ void key_put(struct key *key) - key->user->qnbytes -= key->quotalen; - spin_unlock_irqrestore(&key->user->lock, flags); - } -- smp_mb(); /* key->user before FINAL_PUT set. */ -- set_bit(KEY_FLAG_FINAL_PUT, &key->flags); -+ /* Mark key as safe for GC after key->user done. */ -+ clear_bit_unlock(KEY_FLAG_USER_ALIVE, &key->flags); - schedule_work(&key_gc_work); - } - } -diff -purNx .git BPI-Router-Linux-kernel/security/landlock/id.c BPI-Router-Linux-kernel-6.16.12/security/landlock/id.c ---- BPI-Router-Linux-kernel/security/landlock/id.c 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/security/landlock/id.c 2025-10-22 13:53:56.843167560 -0400 -@@ -119,6 +119,12 @@ static u64 get_id_range(size_t number_of - - #ifdef CONFIG_SECURITY_LANDLOCK_KUNIT_TEST - -+static u8 get_random_u8_positive(void) -+{ -+ /* max() evaluates its arguments once. */ -+ return max(1, get_random_u8()); -+} -+ - static void test_range1_rand0(struct kunit *const test) - { - atomic64_t counter; -@@ -127,9 +133,10 @@ static void test_range1_rand0(struct kun - init = get_random_u32(); - atomic64_set(&counter, init); - KUNIT_EXPECT_EQ(test, get_id_range(1, &counter, 0), init); -- KUNIT_EXPECT_EQ( -- test, get_id_range(get_random_u8(), &counter, get_random_u8()), -- init + 1); -+ KUNIT_EXPECT_EQ(test, -+ get_id_range(get_random_u8_positive(), &counter, -+ get_random_u8()), -+ init + 1); - } - - static void test_range1_rand1(struct kunit *const test) -@@ -140,9 +147,10 @@ static void test_range1_rand1(struct kun - init = get_random_u32(); - atomic64_set(&counter, init); - KUNIT_EXPECT_EQ(test, get_id_range(1, &counter, 1), init); -- KUNIT_EXPECT_EQ( -- test, get_id_range(get_random_u8(), &counter, get_random_u8()), -- init + 2); -+ KUNIT_EXPECT_EQ(test, -+ get_id_range(get_random_u8_positive(), &counter, -+ get_random_u8()), -+ init + 2); - } - - static void test_range1_rand15(struct kunit *const test) -@@ -153,9 +161,10 @@ static void test_range1_rand15(struct ku - init = get_random_u32(); - atomic64_set(&counter, init); - KUNIT_EXPECT_EQ(test, get_id_range(1, &counter, 15), init); -- KUNIT_EXPECT_EQ( -- test, get_id_range(get_random_u8(), &counter, get_random_u8()), -- init + 16); -+ KUNIT_EXPECT_EQ(test, -+ get_id_range(get_random_u8_positive(), &counter, -+ get_random_u8()), -+ init + 16); - } - - static void test_range1_rand16(struct kunit *const test) -@@ -166,9 +175,10 @@ static void test_range1_rand16(struct ku - init = get_random_u32(); - atomic64_set(&counter, init); - KUNIT_EXPECT_EQ(test, get_id_range(1, &counter, 16), init); -- KUNIT_EXPECT_EQ( -- test, get_id_range(get_random_u8(), &counter, get_random_u8()), -- init + 1); -+ KUNIT_EXPECT_EQ(test, -+ get_id_range(get_random_u8_positive(), &counter, -+ get_random_u8()), -+ init + 1); - } - - static void test_range2_rand0(struct kunit *const test) -@@ -179,9 +189,10 @@ static void test_range2_rand0(struct kun - init = get_random_u32(); - atomic64_set(&counter, init); - KUNIT_EXPECT_EQ(test, get_id_range(2, &counter, 0), init); -- KUNIT_EXPECT_EQ( -- test, get_id_range(get_random_u8(), &counter, get_random_u8()), -- init + 2); -+ KUNIT_EXPECT_EQ(test, -+ get_id_range(get_random_u8_positive(), &counter, -+ get_random_u8()), -+ init + 2); - } - - static void test_range2_rand1(struct kunit *const test) -@@ -192,9 +203,10 @@ static void test_range2_rand1(struct kun - init = get_random_u32(); - atomic64_set(&counter, init); - KUNIT_EXPECT_EQ(test, get_id_range(2, &counter, 1), init); -- KUNIT_EXPECT_EQ( -- test, get_id_range(get_random_u8(), &counter, get_random_u8()), -- init + 3); -+ KUNIT_EXPECT_EQ(test, -+ get_id_range(get_random_u8_positive(), &counter, -+ get_random_u8()), -+ init + 3); - } - - static void test_range2_rand2(struct kunit *const test) -@@ -205,9 +217,10 @@ static void test_range2_rand2(struct kun - init = get_random_u32(); - atomic64_set(&counter, init); - KUNIT_EXPECT_EQ(test, get_id_range(2, &counter, 2), init); -- KUNIT_EXPECT_EQ( -- test, get_id_range(get_random_u8(), &counter, get_random_u8()), -- init + 4); -+ KUNIT_EXPECT_EQ(test, -+ get_id_range(get_random_u8_positive(), &counter, -+ get_random_u8()), -+ init + 4); - } - - static void test_range2_rand15(struct kunit *const test) -@@ -218,9 +231,10 @@ static void test_range2_rand15(struct ku - init = get_random_u32(); - atomic64_set(&counter, init); - KUNIT_EXPECT_EQ(test, get_id_range(2, &counter, 15), init); -- KUNIT_EXPECT_EQ( -- test, get_id_range(get_random_u8(), &counter, get_random_u8()), -- init + 17); -+ KUNIT_EXPECT_EQ(test, -+ get_id_range(get_random_u8_positive(), &counter, -+ get_random_u8()), -+ init + 17); - } - - static void test_range2_rand16(struct kunit *const test) -@@ -231,9 +245,10 @@ static void test_range2_rand16(struct ku - init = get_random_u32(); - atomic64_set(&counter, init); - KUNIT_EXPECT_EQ(test, get_id_range(2, &counter, 16), init); -- KUNIT_EXPECT_EQ( -- test, get_id_range(get_random_u8(), &counter, get_random_u8()), -- init + 2); -+ KUNIT_EXPECT_EQ(test, -+ get_id_range(get_random_u8_positive(), &counter, -+ get_random_u8()), -+ init + 2); - } - - #endif /* CONFIG_SECURITY_LANDLOCK_KUNIT_TEST */ -diff -purNx .git BPI-Router-Linux-kernel/security/landlock/syscalls.c BPI-Router-Linux-kernel-6.16.12/security/landlock/syscalls.c ---- BPI-Router-Linux-kernel/security/landlock/syscalls.c 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/security/landlock/syscalls.c 2025-10-22 13:53:56.843167560 -0400 -@@ -303,7 +303,6 @@ static int get_path_from_fd(const s32 fd - if ((fd_file(f)->f_op == &ruleset_fops) || - (fd_file(f)->f_path.mnt->mnt_flags & MNT_INTERNAL) || - (fd_file(f)->f_path.dentry->d_sb->s_flags & SB_NOUSER) || -- d_is_negative(fd_file(f)->f_path.dentry) || - IS_PRIVATE(d_backing_inode(fd_file(f)->f_path.dentry))) - return -EBADFD; - -diff -purNx .git BPI-Router-Linux-kernel/security/selinux/ss/services.c BPI-Router-Linux-kernel-6.16.12/security/selinux/ss/services.c ---- BPI-Router-Linux-kernel/security/selinux/ss/services.c 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/security/selinux/ss/services.c 2025-10-22 13:53:56.843167560 -0400 -@@ -1909,11 +1909,17 @@ retry: - goto out_unlock; - } - /* Obtain the sid for the context. */ -- rc = sidtab_context_to_sid(sidtab, &newcontext, out_sid); -- if (rc == -ESTALE) { -- rcu_read_unlock(); -- context_destroy(&newcontext); -- goto retry; -+ if (context_equal(scontext, &newcontext)) -+ *out_sid = ssid; -+ else if (context_equal(tcontext, &newcontext)) -+ *out_sid = tsid; -+ else { -+ rc = sidtab_context_to_sid(sidtab, &newcontext, out_sid); -+ if (rc == -ESTALE) { -+ rcu_read_unlock(); -+ context_destroy(&newcontext); -+ goto retry; -+ } - } - out_unlock: - rcu_read_unlock(); -diff -purNx .git BPI-Router-Linux-kernel/security/selinux/xfrm.c BPI-Router-Linux-kernel-6.16.12/security/selinux/xfrm.c ---- BPI-Router-Linux-kernel/security/selinux/xfrm.c 2025-10-22 13:53:23.667326961 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/security/selinux/xfrm.c 2025-10-22 13:53:56.843167560 -0400 -@@ -94,7 +94,7 @@ static int selinux_xfrm_alloc_user(struc - - ctx->ctx_doi = XFRM_SC_DOI_LSM; - ctx->ctx_alg = XFRM_SC_ALG_SELINUX; -- ctx->ctx_len = str_len; -+ ctx->ctx_len = str_len + 1; - memcpy(ctx->ctx_str, &uctx[1], str_len); - ctx->ctx_str[str_len] = '\0'; - rc = security_context_to_sid(ctx->ctx_str, str_len, -diff -purNx .git BPI-Router-Linux-kernel/sound/core/compress_offload.c BPI-Router-Linux-kernel-6.16.12/sound/core/compress_offload.c ---- BPI-Router-Linux-kernel/sound/core/compress_offload.c 2025-10-22 13:53:23.671326942 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/core/compress_offload.c 2025-10-22 13:53:56.843167560 -0400 -@@ -1269,62 +1269,62 @@ static long snd_compr_ioctl(struct file - stream = &data->stream; - - guard(mutex)(&stream->device->lock); -- switch (_IOC_NR(cmd)) { -- case _IOC_NR(SNDRV_COMPRESS_IOCTL_VERSION): -+ switch (cmd) { -+ case SNDRV_COMPRESS_IOCTL_VERSION: - return put_user(SNDRV_COMPRESS_VERSION, - (int __user *)arg) ? -EFAULT : 0; -- case _IOC_NR(SNDRV_COMPRESS_GET_CAPS): -+ case SNDRV_COMPRESS_GET_CAPS: - return snd_compr_get_caps(stream, arg); - #ifndef COMPR_CODEC_CAPS_OVERFLOW -- case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS): -+ case SNDRV_COMPRESS_GET_CODEC_CAPS: - return snd_compr_get_codec_caps(stream, arg); - #endif -- case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS): -+ case SNDRV_COMPRESS_SET_PARAMS: - return snd_compr_set_params(stream, arg); -- case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS): -+ case SNDRV_COMPRESS_GET_PARAMS: - return snd_compr_get_params(stream, arg); -- case _IOC_NR(SNDRV_COMPRESS_SET_METADATA): -+ case SNDRV_COMPRESS_SET_METADATA: - return snd_compr_set_metadata(stream, arg); -- case _IOC_NR(SNDRV_COMPRESS_GET_METADATA): -+ case SNDRV_COMPRESS_GET_METADATA: - return snd_compr_get_metadata(stream, arg); - } - - if (stream->direction == SND_COMPRESS_ACCEL) { - #if IS_ENABLED(CONFIG_SND_COMPRESS_ACCEL) -- switch (_IOC_NR(cmd)) { -- case _IOC_NR(SNDRV_COMPRESS_TASK_CREATE): -+ switch (cmd) { -+ case SNDRV_COMPRESS_TASK_CREATE: - return snd_compr_task_create(stream, arg); -- case _IOC_NR(SNDRV_COMPRESS_TASK_FREE): -+ case SNDRV_COMPRESS_TASK_FREE: - return snd_compr_task_seq(stream, arg, snd_compr_task_free_one); -- case _IOC_NR(SNDRV_COMPRESS_TASK_START): -+ case SNDRV_COMPRESS_TASK_START: - return snd_compr_task_start_ioctl(stream, arg); -- case _IOC_NR(SNDRV_COMPRESS_TASK_STOP): -+ case SNDRV_COMPRESS_TASK_STOP: - return snd_compr_task_seq(stream, arg, snd_compr_task_stop_one); -- case _IOC_NR(SNDRV_COMPRESS_TASK_STATUS): -+ case SNDRV_COMPRESS_TASK_STATUS: - return snd_compr_task_status_ioctl(stream, arg); - } - #endif - return -ENOTTY; - } - -- switch (_IOC_NR(cmd)) { -- case _IOC_NR(SNDRV_COMPRESS_TSTAMP): -+ switch (cmd) { -+ case SNDRV_COMPRESS_TSTAMP: - return snd_compr_tstamp(stream, arg); -- case _IOC_NR(SNDRV_COMPRESS_AVAIL): -+ case SNDRV_COMPRESS_AVAIL: - return snd_compr_ioctl_avail(stream, arg); -- case _IOC_NR(SNDRV_COMPRESS_PAUSE): -+ case SNDRV_COMPRESS_PAUSE: - return snd_compr_pause(stream); -- case _IOC_NR(SNDRV_COMPRESS_RESUME): -+ case SNDRV_COMPRESS_RESUME: - return snd_compr_resume(stream); -- case _IOC_NR(SNDRV_COMPRESS_START): -+ case SNDRV_COMPRESS_START: - return snd_compr_start(stream); -- case _IOC_NR(SNDRV_COMPRESS_STOP): -+ case SNDRV_COMPRESS_STOP: - return snd_compr_stop(stream); -- case _IOC_NR(SNDRV_COMPRESS_DRAIN): -+ case SNDRV_COMPRESS_DRAIN: - return snd_compr_drain(stream); -- case _IOC_NR(SNDRV_COMPRESS_PARTIAL_DRAIN): -+ case SNDRV_COMPRESS_PARTIAL_DRAIN: - return snd_compr_partial_drain(stream); -- case _IOC_NR(SNDRV_COMPRESS_NEXT_TRACK): -+ case SNDRV_COMPRESS_NEXT_TRACK: - return snd_compr_next_track(stream); - } - -diff -purNx .git BPI-Router-Linux-kernel/sound/core/pcm_native.c BPI-Router-Linux-kernel-6.16.12/sound/core/pcm_native.c ---- BPI-Router-Linux-kernel/sound/core/pcm_native.c 2025-10-22 13:53:23.671326942 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/core/pcm_native.c 2025-10-22 13:53:56.847167540 -0400 -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - - #include "pcm_local.h" - -@@ -3130,13 +3131,23 @@ struct snd_pcm_sync_ptr32 { - static snd_pcm_uframes_t recalculate_boundary(struct snd_pcm_runtime *runtime) - { - snd_pcm_uframes_t boundary; -+ snd_pcm_uframes_t border; -+ int order; - - if (! runtime->buffer_size) - return 0; -- boundary = runtime->buffer_size; -- while (boundary * 2 <= 0x7fffffffUL - runtime->buffer_size) -- boundary *= 2; -- return boundary; -+ -+ border = 0x7fffffffUL - runtime->buffer_size; -+ if (runtime->buffer_size > border) -+ return runtime->buffer_size; -+ -+ order = __fls(border) - __fls(runtime->buffer_size); -+ boundary = runtime->buffer_size << order; -+ -+ if (boundary <= border) -+ return boundary; -+ else -+ return boundary / 2; - } - - static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream, -diff -purNx .git BPI-Router-Linux-kernel/sound/core/timer.c BPI-Router-Linux-kernel-6.16.12/sound/core/timer.c ---- BPI-Router-Linux-kernel/sound/core/timer.c 2025-10-22 13:53:23.671326942 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/core/timer.c 2025-10-22 13:53:56.847167540 -0400 -@@ -2139,14 +2139,14 @@ static int snd_utimer_create(struct snd_ - goto err_take_id; - } - -+ utimer->id = utimer_id; -+ - utimer->name = kasprintf(GFP_KERNEL, "snd-utimer%d", utimer_id); - if (!utimer->name) { - err = -ENOMEM; - goto err_get_name; - } - -- utimer->id = utimer_id; -- - tid.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION; - tid.dev_class = SNDRV_TIMER_CLASS_GLOBAL; - tid.card = -1; -diff -purNx .git BPI-Router-Linux-kernel/sound/firewire/motu/motu-hwdep.c BPI-Router-Linux-kernel-6.16.12/sound/firewire/motu/motu-hwdep.c ---- BPI-Router-Linux-kernel/sound/firewire/motu/motu-hwdep.c 2025-10-22 13:53:23.671326942 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/firewire/motu/motu-hwdep.c 2025-10-22 13:53:56.847167540 -0400 -@@ -111,7 +111,7 @@ static __poll_t hwdep_poll(struct snd_hw - events = 0; - spin_unlock_irq(&motu->lock); - -- return events | EPOLLOUT; -+ return events; - } - - static int hwdep_get_info(struct snd_motu *motu, void __user *arg) -diff -purNx .git BPI-Router-Linux-kernel/sound/isa/ad1816a/ad1816a.c BPI-Router-Linux-kernel-6.16.12/sound/isa/ad1816a/ad1816a.c ---- BPI-Router-Linux-kernel/sound/isa/ad1816a/ad1816a.c 2025-10-22 13:53:23.671326942 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/isa/ad1816a/ad1816a.c 2025-10-22 13:53:56.847167540 -0400 -@@ -98,7 +98,7 @@ static int snd_card_ad1816a_pnp(int dev, - pdev = pnp_request_card_device(card, id->devs[1].id, NULL); - if (pdev == NULL) { - mpu_port[dev] = -1; -- dev_warn(&pdev->dev, "MPU401 device busy, skipping.\n"); -+ pr_warn("MPU401 device busy, skipping.\n"); - return 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/sound/isa/sb/sb16_main.c BPI-Router-Linux-kernel-6.16.12/sound/isa/sb/sb16_main.c ---- BPI-Router-Linux-kernel/sound/isa/sb/sb16_main.c 2025-10-22 13:53:23.671326942 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/isa/sb/sb16_main.c 2025-10-22 13:53:56.847167540 -0400 -@@ -703,6 +703,9 @@ static int snd_sb16_dma_control_put(stru - unsigned char nval, oval; - int change; - -+ if (chip->mode & (SB_MODE_PLAYBACK | SB_MODE_CAPTURE)) -+ return -EBUSY; -+ - nval = ucontrol->value.enumerated.item[0]; - if (nval > 2) - return -EINVAL; -@@ -711,6 +714,10 @@ static int snd_sb16_dma_control_put(stru - change = nval != oval; - snd_sb16_set_dma_mode(chip, nval); - spin_unlock_irqrestore(&chip->reg_lock, flags); -+ if (change) { -+ snd_dma_disable(chip->dma8); -+ snd_dma_disable(chip->dma16); -+ } - return change; - } - -diff -purNx .git BPI-Router-Linux-kernel/sound/pci/ctxfi/xfi.c BPI-Router-Linux-kernel-6.16.12/sound/pci/ctxfi/xfi.c ---- BPI-Router-Linux-kernel/sound/pci/ctxfi/xfi.c 2025-10-22 13:53:23.671326942 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/pci/ctxfi/xfi.c 2025-10-22 13:53:56.847167540 -0400 -@@ -98,8 +98,8 @@ ct_card_probe(struct pci_dev *pci, const - if (err < 0) - goto error; - -- strcpy(card->driver, "SB-XFi"); -- strcpy(card->shortname, "Creative X-Fi"); -+ strscpy(card->driver, "SB-XFi"); -+ strscpy(card->shortname, "Creative X-Fi"); - snprintf(card->longname, sizeof(card->longname), "%s %s %s", - card->shortname, atc->chip_name, atc->model_name); - -diff -purNx .git BPI-Router-Linux-kernel/sound/pci/hda/cs35l41_hda.c BPI-Router-Linux-kernel-6.16.12/sound/pci/hda/cs35l41_hda.c ---- BPI-Router-Linux-kernel/sound/pci/hda/cs35l41_hda.c 2025-10-22 13:53:23.671326942 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/pci/hda/cs35l41_hda.c 2025-10-22 13:53:56.847167540 -0400 -@@ -2085,3 +2085,5 @@ MODULE_IMPORT_NS("SND_SOC_CS_AMP_LIB"); - MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, "); - MODULE_LICENSE("GPL"); - MODULE_IMPORT_NS("FW_CS_DSP"); -+MODULE_FIRMWARE("cirrus/cs35l41-*.wmfw"); -+MODULE_FIRMWARE("cirrus/cs35l41-*.bin"); -diff -purNx .git BPI-Router-Linux-kernel/sound/pci/hda/cs35l56_hda.c BPI-Router-Linux-kernel-6.16.12/sound/pci/hda/cs35l56_hda.c ---- BPI-Router-Linux-kernel/sound/pci/hda/cs35l56_hda.c 2025-10-22 13:53:23.671326942 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/pci/hda/cs35l56_hda.c 2025-10-22 13:53:56.847167540 -0400 -@@ -873,6 +873,52 @@ static int cs35l56_hda_system_resume(str - return 0; - } - -+static int cs35l56_hda_fixup_yoga9(struct cs35l56_hda *cs35l56, int *bus_addr) -+{ -+ /* The cirrus,dev-index property has the wrong values */ -+ switch (*bus_addr) { -+ case 0x30: -+ cs35l56->index = 1; -+ return 0; -+ case 0x31: -+ cs35l56->index = 0; -+ return 0; -+ default: -+ /* There is a pseudo-address for broadcast to both amps - ignore it */ -+ dev_dbg(cs35l56->base.dev, "Ignoring I2C address %#x\n", *bus_addr); -+ return 0; -+ } -+} -+ -+static const struct { -+ const char *sub; -+ int (*fixup_fn)(struct cs35l56_hda *cs35l56, int *bus_addr); -+} cs35l56_hda_fixups[] = { -+ { -+ .sub = "17AA390B", /* Lenovo Yoga Book 9i GenX */ -+ .fixup_fn = cs35l56_hda_fixup_yoga9, -+ }, -+}; -+ -+static int cs35l56_hda_apply_platform_fixups(struct cs35l56_hda *cs35l56, const char *sub, -+ int *bus_addr) -+{ -+ int i; -+ -+ if (IS_ERR(sub)) -+ return 0; -+ -+ for (i = 0; i < ARRAY_SIZE(cs35l56_hda_fixups); i++) { -+ if (strcasecmp(cs35l56_hda_fixups[i].sub, sub) == 0) { -+ dev_dbg(cs35l56->base.dev, "Applying fixup for %s\n", -+ cs35l56_hda_fixups[i].sub); -+ return (cs35l56_hda_fixups[i].fixup_fn)(cs35l56, bus_addr); -+ } -+ } -+ -+ return 0; -+} -+ - static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int hid, int id) - { - u32 values[HDA_MAX_COMPONENTS]; -@@ -897,39 +943,47 @@ static int cs35l56_hda_read_acpi(struct - ACPI_COMPANION_SET(cs35l56->base.dev, adev); - } - -- property = "cirrus,dev-index"; -- ret = device_property_count_u32(cs35l56->base.dev, property); -- if (ret <= 0) -- goto err; -- -- if (ret > ARRAY_SIZE(values)) { -- ret = -EINVAL; -- goto err; -- } -- nval = ret; -+ /* Initialize things that could be overwritten by a fixup */ -+ cs35l56->index = -1; - -- ret = device_property_read_u32_array(cs35l56->base.dev, property, values, nval); -+ sub = acpi_get_subsystem_id(ACPI_HANDLE(cs35l56->base.dev)); -+ ret = cs35l56_hda_apply_platform_fixups(cs35l56, sub, &id); - if (ret) -- goto err; -+ return ret; - -- cs35l56->index = -1; -- for (i = 0; i < nval; i++) { -- if (values[i] == id) { -- cs35l56->index = i; -- break; -- } -- } -- /* -- * It's not an error for the ID to be missing: for I2C there can be -- * an alias address that is not a real device. So reject silently. -- */ - if (cs35l56->index == -1) { -- dev_dbg(cs35l56->base.dev, "No index found in %s\n", property); -- ret = -ENODEV; -- goto err; -- } -+ property = "cirrus,dev-index"; -+ ret = device_property_count_u32(cs35l56->base.dev, property); -+ if (ret <= 0) -+ goto err; -+ -+ if (ret > ARRAY_SIZE(values)) { -+ ret = -EINVAL; -+ goto err; -+ } -+ nval = ret; - -- sub = acpi_get_subsystem_id(ACPI_HANDLE(cs35l56->base.dev)); -+ ret = device_property_read_u32_array(cs35l56->base.dev, property, values, nval); -+ if (ret) -+ goto err; -+ -+ for (i = 0; i < nval; i++) { -+ if (values[i] == id) { -+ cs35l56->index = i; -+ break; -+ } -+ } -+ -+ /* -+ * It's not an error for the ID to be missing: for I2C there can be -+ * an alias address that is not a real device. So reject silently. -+ */ -+ if (cs35l56->index == -1) { -+ dev_dbg(cs35l56->base.dev, "No index found in %s\n", property); -+ ret = -ENODEV; -+ goto err; -+ } -+ } - - if (IS_ERR(sub)) { - dev_info(cs35l56->base.dev, -@@ -1122,3 +1176,7 @@ MODULE_IMPORT_NS("SND_SOC_CS_AMP_LIB"); - MODULE_AUTHOR("Richard Fitzgerald "); - MODULE_AUTHOR("Simon Trimmer "); - MODULE_LICENSE("GPL"); -+MODULE_FIRMWARE("cirrus/cs35l54-*.wmfw"); -+MODULE_FIRMWARE("cirrus/cs35l54-*.bin"); -+MODULE_FIRMWARE("cirrus/cs35l56-*.wmfw"); -+MODULE_FIRMWARE("cirrus/cs35l56-*.bin"); -diff -purNx .git BPI-Router-Linux-kernel/sound/pci/hda/hda_codec.c BPI-Router-Linux-kernel-6.16.12/sound/pci/hda/hda_codec.c ---- BPI-Router-Linux-kernel/sound/pci/hda/hda_codec.c 2025-10-22 13:53:23.671326942 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/pci/hda/hda_codec.c 2025-10-22 13:53:56.847167540 -0400 -@@ -639,24 +639,16 @@ static void hda_jackpoll_work(struct wor - struct hda_codec *codec = - container_of(work, struct hda_codec, jackpoll_work.work); - -- /* for non-polling trigger: we need nothing if already powered on */ -- if (!codec->jackpoll_interval && snd_hdac_is_power_on(&codec->core)) -+ if (!codec->jackpoll_interval) - return; - - /* the power-up/down sequence triggers the runtime resume */ -- snd_hda_power_up_pm(codec); -+ snd_hda_power_up(codec); - /* update jacks manually if polling is required, too */ -- if (codec->jackpoll_interval) { -- snd_hda_jack_set_dirty_all(codec); -- snd_hda_jack_poll_all(codec); -- } -- snd_hda_power_down_pm(codec); -- -- if (!codec->jackpoll_interval) -- return; -- -- schedule_delayed_work(&codec->jackpoll_work, -- codec->jackpoll_interval); -+ snd_hda_jack_set_dirty_all(codec); -+ snd_hda_jack_poll_all(codec); -+ schedule_delayed_work(&codec->jackpoll_work, codec->jackpoll_interval); -+ snd_hda_power_down(codec); - } - - /* release all pincfg lists */ -@@ -2895,12 +2887,12 @@ static void hda_call_codec_resume(struct - snd_hda_regmap_sync(codec); - } - -- if (codec->jackpoll_interval) -- hda_jackpoll_work(&codec->jackpoll_work.work); -- else -- snd_hda_jack_report_sync(codec); -+ snd_hda_jack_report_sync(codec); - codec->core.dev.power.power_state = PMSG_ON; - snd_hdac_leave_pm(&codec->core); -+ if (codec->jackpoll_interval) -+ schedule_delayed_work(&codec->jackpoll_work, -+ codec->jackpoll_interval); - } - - static int hda_codec_runtime_suspend(struct device *dev) -@@ -2912,8 +2904,6 @@ static int hda_codec_runtime_suspend(str - if (!codec->card) - return 0; - -- cancel_delayed_work_sync(&codec->jackpoll_work); -- - state = hda_call_codec_suspend(codec); - if (codec->link_down_at_suspend || - (codec_has_clkstop(codec) && codec_has_epss(codec) && -@@ -2921,10 +2911,6 @@ static int hda_codec_runtime_suspend(str - snd_hdac_codec_link_down(&codec->core); - snd_hda_codec_display_power(codec, false); - -- if (codec->bus->jackpoll_in_suspend && -- (dev->power.power_state.event != PM_EVENT_SUSPEND)) -- schedule_delayed_work(&codec->jackpoll_work, -- codec->jackpoll_interval); - return 0; - } - -@@ -3020,6 +3006,7 @@ void snd_hda_codec_shutdown(struct hda_c - if (!codec->core.registered) - return; - -+ codec->jackpoll_interval = 0; /* don't poll any longer */ - cancel_delayed_work_sync(&codec->jackpoll_work); - list_for_each_entry(cpcm, &codec->pcm_list_head, list) - snd_pcm_suspend_all(cpcm->pcm); -@@ -3086,10 +3073,11 @@ int snd_hda_codec_build_controls(struct - if (err < 0) - return err; - -+ snd_hda_jack_report_sync(codec); /* call at the last init point */ - if (codec->jackpoll_interval) -- hda_jackpoll_work(&codec->jackpoll_work.work); -- else -- snd_hda_jack_report_sync(codec); /* call at the last init point */ -+ schedule_delayed_work(&codec->jackpoll_work, -+ codec->jackpoll_interval); -+ - sync_power_up_states(codec); - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/sound/pci/hda/hda_intel.c BPI-Router-Linux-kernel-6.16.12/sound/pci/hda/hda_intel.c ---- BPI-Router-Linux-kernel/sound/pci/hda/hda_intel.c 2025-10-22 13:53:23.671326942 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/pci/hda/hda_intel.c 2025-10-22 13:53:56.847167540 -0400 -@@ -2283,6 +2283,8 @@ static const struct snd_pci_quirk power_ - SND_PCI_QUIRK(0x1734, 0x1232, "KONTRON SinglePC", 0), - /* Dell ALC3271 */ - SND_PCI_QUIRK(0x1028, 0x0962, "Dell ALC3271", 0), -+ /* https://bugzilla.kernel.org/show_bug.cgi?id=220210 */ -+ SND_PCI_QUIRK(0x17aa, 0x5079, "Lenovo Thinkpad E15", 0), - {} - }; - -diff -purNx .git BPI-Router-Linux-kernel/sound/pci/hda/patch_ca0132.c BPI-Router-Linux-kernel-6.16.12/sound/pci/hda/patch_ca0132.c ---- BPI-Router-Linux-kernel/sound/pci/hda/patch_ca0132.c 2025-10-22 13:53:23.671326942 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/pci/hda/patch_ca0132.c 2025-10-22 13:53:56.847167540 -0400 -@@ -4410,7 +4410,7 @@ static int add_tuning_control(struct hda - } - knew.private_value = - HDA_COMPOSE_AMP_VAL(nid, 1, 0, type); -- sprintf(namestr, "%s %s Volume", name, dirstr[dir]); -+ snprintf(namestr, sizeof(namestr), "%s %s Volume", name, dirstr[dir]); - return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); - } - -@@ -4802,7 +4802,8 @@ static int ca0132_alt_select_out(struct - if (err < 0) - goto exit; - -- if (ca0132_alt_select_out_quirk_set(codec) < 0) -+ err = ca0132_alt_select_out_quirk_set(codec); -+ if (err < 0) - goto exit; - - switch (spec->cur_out_type) { -@@ -4892,6 +4893,8 @@ static int ca0132_alt_select_out(struct - spec->bass_redirection_val); - else - err = ca0132_alt_surround_set_bass_redirection(codec, 0); -+ if (err < 0) -+ goto exit; - - /* Unmute DSP now that we're done with output selection. */ - err = dspio_set_uint_param(codec, 0x96, -diff -purNx .git BPI-Router-Linux-kernel/sound/pci/hda/patch_hdmi.c BPI-Router-Linux-kernel-6.16.12/sound/pci/hda/patch_hdmi.c ---- BPI-Router-Linux-kernel/sound/pci/hda/patch_hdmi.c 2025-10-22 13:53:23.671326942 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/pci/hda/patch_hdmi.c 2025-10-22 13:53:56.847167540 -0400 -@@ -1991,6 +1991,7 @@ static int hdmi_add_cvt(struct hda_codec - static const struct snd_pci_quirk force_connect_list[] = { - SND_PCI_QUIRK(0x103c, 0x83e2, "HP EliteDesk 800 G4", 1), - SND_PCI_QUIRK(0x103c, 0x83ef, "HP MP9 G4 Retail System AMS", 1), -+ SND_PCI_QUIRK(0x103c, 0x845a, "HP EliteDesk 800 G4 DM 65W", 1), - SND_PCI_QUIRK(0x103c, 0x870f, "HP", 1), - SND_PCI_QUIRK(0x103c, 0x871a, "HP", 1), - SND_PCI_QUIRK(0x103c, 0x8711, "HP", 1), -@@ -4551,7 +4552,9 @@ HDA_CODEC_ENTRY(0x10de002e, "Tegra186 HD - HDA_CODEC_ENTRY(0x10de002f, "Tegra194 HDMI/DP2", patch_tegra_hdmi), - HDA_CODEC_ENTRY(0x10de0030, "Tegra194 HDMI/DP3", patch_tegra_hdmi), - HDA_CODEC_ENTRY(0x10de0031, "Tegra234 HDMI/DP", patch_tegra234_hdmi), -+HDA_CODEC_ENTRY(0x10de0033, "SoC 33 HDMI/DP", patch_tegra234_hdmi), - HDA_CODEC_ENTRY(0x10de0034, "Tegra264 HDMI/DP", patch_tegra234_hdmi), -+HDA_CODEC_ENTRY(0x10de0035, "SoC 35 HDMI/DP", patch_tegra234_hdmi), - HDA_CODEC_ENTRY(0x10de0040, "GPU 40 HDMI/DP", patch_nvhdmi), - HDA_CODEC_ENTRY(0x10de0041, "GPU 41 HDMI/DP", patch_nvhdmi), - HDA_CODEC_ENTRY(0x10de0042, "GPU 42 HDMI/DP", patch_nvhdmi), -@@ -4590,15 +4593,32 @@ HDA_CODEC_ENTRY(0x10de0097, "GPU 97 HDMI - HDA_CODEC_ENTRY(0x10de0098, "GPU 98 HDMI/DP", patch_nvhdmi), - HDA_CODEC_ENTRY(0x10de0099, "GPU 99 HDMI/DP", patch_nvhdmi), - HDA_CODEC_ENTRY(0x10de009a, "GPU 9a HDMI/DP", patch_nvhdmi), -+HDA_CODEC_ENTRY(0x10de009b, "GPU 9b HDMI/DP", patch_nvhdmi), -+HDA_CODEC_ENTRY(0x10de009c, "GPU 9c HDMI/DP", patch_nvhdmi), - HDA_CODEC_ENTRY(0x10de009d, "GPU 9d HDMI/DP", patch_nvhdmi), - HDA_CODEC_ENTRY(0x10de009e, "GPU 9e HDMI/DP", patch_nvhdmi), - HDA_CODEC_ENTRY(0x10de009f, "GPU 9f HDMI/DP", patch_nvhdmi), - HDA_CODEC_ENTRY(0x10de00a0, "GPU a0 HDMI/DP", patch_nvhdmi), -+HDA_CODEC_ENTRY(0x10de00a1, "GPU a1 HDMI/DP", patch_nvhdmi), - HDA_CODEC_ENTRY(0x10de00a3, "GPU a3 HDMI/DP", patch_nvhdmi), - HDA_CODEC_ENTRY(0x10de00a4, "GPU a4 HDMI/DP", patch_nvhdmi), - HDA_CODEC_ENTRY(0x10de00a5, "GPU a5 HDMI/DP", patch_nvhdmi), - HDA_CODEC_ENTRY(0x10de00a6, "GPU a6 HDMI/DP", patch_nvhdmi), - HDA_CODEC_ENTRY(0x10de00a7, "GPU a7 HDMI/DP", patch_nvhdmi), -+HDA_CODEC_ENTRY(0x10de00a8, "GPU a8 HDMI/DP", patch_nvhdmi), -+HDA_CODEC_ENTRY(0x10de00a9, "GPU a9 HDMI/DP", patch_nvhdmi), -+HDA_CODEC_ENTRY(0x10de00aa, "GPU aa HDMI/DP", patch_nvhdmi), -+HDA_CODEC_ENTRY(0x10de00ab, "GPU ab HDMI/DP", patch_nvhdmi), -+HDA_CODEC_ENTRY(0x10de00ad, "GPU ad HDMI/DP", patch_nvhdmi), -+HDA_CODEC_ENTRY(0x10de00ae, "GPU ae HDMI/DP", patch_nvhdmi), -+HDA_CODEC_ENTRY(0x10de00af, "GPU af HDMI/DP", patch_nvhdmi), -+HDA_CODEC_ENTRY(0x10de00b0, "GPU b0 HDMI/DP", patch_nvhdmi), -+HDA_CODEC_ENTRY(0x10de00b1, "GPU b1 HDMI/DP", patch_nvhdmi), -+HDA_CODEC_ENTRY(0x10de00c0, "GPU c0 HDMI/DP", patch_nvhdmi), -+HDA_CODEC_ENTRY(0x10de00c1, "GPU c1 HDMI/DP", patch_nvhdmi), -+HDA_CODEC_ENTRY(0x10de00c3, "GPU c3 HDMI/DP", patch_nvhdmi), -+HDA_CODEC_ENTRY(0x10de00c4, "GPU c4 HDMI/DP", patch_nvhdmi), -+HDA_CODEC_ENTRY(0x10de00c5, "GPU c5 HDMI/DP", patch_nvhdmi), - HDA_CODEC_ENTRY(0x10de8001, "MCP73 HDMI", patch_nvhdmi_2ch), - HDA_CODEC_ENTRY(0x10de8067, "MCP67/68 HDMI", patch_nvhdmi_2ch), - HDA_CODEC_ENTRY(0x67663d82, "Arise 82 HDMI/DP", patch_gf_hdmi), -diff -purNx .git BPI-Router-Linux-kernel/sound/pci/hda/patch_realtek.c BPI-Router-Linux-kernel-6.16.12/sound/pci/hda/patch_realtek.c ---- BPI-Router-Linux-kernel/sound/pci/hda/patch_realtek.c 2025-10-22 13:53:23.675326923 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/pci/hda/patch_realtek.c 2025-10-22 13:53:56.847167540 -0400 -@@ -2656,6 +2656,7 @@ static const struct hda_quirk alc882_fix - SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX), - SND_PCI_QUIRK(0x1558, 0x3702, "Clevo X370SN[VW]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), - SND_PCI_QUIRK(0x1558, 0x50d3, "Clevo PC50[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), -+ SND_PCI_QUIRK(0x1558, 0x5802, "Clevo X58[05]WN[RST]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), - SND_PCI_QUIRK(0x1558, 0x65d1, "Clevo PB51[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), - SND_PCI_QUIRK(0x1558, 0x65d2, "Clevo PB51R[CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), - SND_PCI_QUIRK(0x1558, 0x65e1, "Clevo PB51[ED][DF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), -@@ -4752,7 +4753,7 @@ static void alc245_fixup_hp_mute_led_v1_ - if (action == HDA_FIXUP_ACT_PRE_PROBE) { - spec->mute_led_polarity = 0; - spec->mute_led_coef.idx = 0x0b; -- spec->mute_led_coef.mask = 1 << 3; -+ spec->mute_led_coef.mask = 3 << 2; - spec->mute_led_coef.on = 1 << 3; - spec->mute_led_coef.off = 0; - snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set); -@@ -6609,6 +6610,7 @@ static void alc294_fixup_bass_speaker_15 - if (action == HDA_FIXUP_ACT_PRE_PROBE) { - static const hda_nid_t conn[] = { 0x02, 0x03 }; - snd_hda_override_conn_list(codec, 0x15, ARRAY_SIZE(conn), conn); -+ snd_hda_gen_add_micmute_led_cdev(codec, NULL); - } - } - -@@ -7296,6 +7298,11 @@ static void cs35l41_fixup_spi_two(struct - comp_generic_fixup(codec, action, "spi", "CSC3551", "-%s:00-cs35l41-hda.%d", 2); - } - -+static void cs35l41_fixup_spi_one(struct hda_codec *codec, const struct hda_fixup *fix, int action) -+{ -+ comp_generic_fixup(codec, action, "spi", "CSC3551", "-%s:00-cs35l41-hda.%d", 1); -+} -+ - static void cs35l41_fixup_spi_four(struct hda_codec *codec, const struct hda_fixup *fix, int action) - { - comp_generic_fixup(codec, action, "spi", "CSC3551", "-%s:00-cs35l41-hda.%d", 4); -@@ -7495,6 +7502,9 @@ static void alc287_fixup_yoga9_14iap7_ba - }; - struct alc_spec *spec = codec->spec; - -+ /* Support Audio mute LED and Mic mute LED on keyboard */ -+ hda_fixup_ideapad_acpi(codec, fix, action); -+ - switch (action) { - case HDA_FIXUP_ACT_PRE_PROBE: - snd_hda_apply_pincfgs(codec, pincfgs); -@@ -7986,6 +7996,7 @@ enum { - ALC287_FIXUP_CS35L41_I2C_2, - ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED, - ALC287_FIXUP_CS35L41_I2C_4, -+ ALC245_FIXUP_CS35L41_SPI_1, - ALC245_FIXUP_CS35L41_SPI_2, - ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED, - ALC245_FIXUP_CS35L41_SPI_4, -@@ -8030,6 +8041,9 @@ enum { - ALC294_FIXUP_ASUS_CS35L41_SPI_2, - ALC274_FIXUP_HP_AIO_BIND_DACS, - ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2, -+ ALC285_FIXUP_ASUS_GA605K_HEADSET_MIC, -+ ALC285_FIXUP_ASUS_GA605K_I2C_SPEAKER2_TO_DAC1, -+ ALC269_FIXUP_POSITIVO_P15X_HEADSET_MIC, - }; - - /* A special fixup for Lenovo C940 and Yoga Duet 7; -@@ -10112,6 +10126,10 @@ static const struct hda_fixup alc269_fix - .type = HDA_FIXUP_FUNC, - .v.func = cs35l41_fixup_spi_two, - }, -+ [ALC245_FIXUP_CS35L41_SPI_1] = { -+ .type = HDA_FIXUP_FUNC, -+ .v.func = cs35l41_fixup_spi_one, -+ }, - [ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED] = { - .type = HDA_FIXUP_FUNC, - .v.func = cs35l41_fixup_spi_two, -@@ -10414,6 +10432,26 @@ static const struct hda_fixup alc269_fix - .type = HDA_FIXUP_FUNC, - .v.func = alc274_fixup_hp_aio_bind_dacs, - }, -+ [ALC285_FIXUP_ASUS_GA605K_HEADSET_MIC] = { -+ .type = HDA_FIXUP_PINS, -+ .v.pins = (const struct hda_pintbl[]) { -+ { 0x19, 0x03a11050 }, -+ { 0x1b, 0x03a11c30 }, -+ { } -+ }, -+ .chained = true, -+ .chain_id = ALC285_FIXUP_ASUS_GA605K_I2C_SPEAKER2_TO_DAC1 -+ }, -+ [ALC285_FIXUP_ASUS_GA605K_I2C_SPEAKER2_TO_DAC1] = { -+ .type = HDA_FIXUP_FUNC, -+ .v.func = alc285_fixup_speaker2_to_dac1, -+ }, -+ [ALC269_FIXUP_POSITIVO_P15X_HEADSET_MIC] = { -+ .type = HDA_FIXUP_FUNC, -+ .v.func = alc269_fixup_limit_int_mic_boost, -+ .chained = true, -+ .chain_id = ALC269VC_FIXUP_ACER_MIC_NO_PRESENCE, -+ }, - }; - - static const struct hda_quirk alc269_fixup_tbl[] = { -@@ -10509,6 +10547,7 @@ static const struct hda_quirk alc269_fix - SND_PCI_QUIRK(0x1028, 0x0871, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC), - SND_PCI_QUIRK(0x1028, 0x0872, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC), - SND_PCI_QUIRK(0x1028, 0x0873, "Dell Precision 3930", ALC255_FIXUP_DUMMY_LINEOUT_VERB), -+ SND_PCI_QUIRK(0x1028, 0x0879, "Dell Latitude 5420 Rugged", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1028, 0x08ad, "Dell WYSE AIO", ALC225_FIXUP_DELL_WYSE_AIO_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1028, 0x08ae, "Dell WYSE NB", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1028, 0x0935, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB), -@@ -10633,6 +10672,8 @@ static const struct hda_quirk alc269_fix - SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3), - SND_PCI_QUIRK(0x103c, 0x8519, "HP Spectre x360 15-df0xxx", ALC285_FIXUP_HP_SPECTRE_X360), - SND_PCI_QUIRK(0x103c, 0x8537, "HP ProBook 440 G6", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), -+ SND_PCI_QUIRK(0x103c, 0x8548, "HP EliteBook x360 830 G6", ALC285_FIXUP_HP_GPIO_LED), -+ SND_PCI_QUIRK(0x103c, 0x854a, "HP EliteBook 830 G6", ALC285_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x85c6, "HP Pavilion x360 Convertible 14-dy1xxx", ALC295_FIXUP_HP_MUTE_LED_COEFBIT11), - SND_PCI_QUIRK(0x103c, 0x85de, "HP Envy x360 13-ar0xxx", ALC285_FIXUP_HP_ENVY_X360), - SND_PCI_QUIRK(0x103c, 0x860f, "HP ZBook 15 G6", ALC285_FIXUP_HP_GPIO_AMP_INIT), -@@ -10665,6 +10706,7 @@ static const struct hda_quirk alc269_fix - SND_PCI_QUIRK(0x103c, 0x8788, "HP OMEN 15", ALC285_FIXUP_HP_MUTE_LED), - SND_PCI_QUIRK(0x103c, 0x87b7, "HP Laptop 14-fq0xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), - SND_PCI_QUIRK(0x103c, 0x87c8, "HP", ALC287_FIXUP_HP_GPIO_LED), -+ SND_PCI_QUIRK(0x103c, 0x87cc, "HP Pavilion 15-eg0xxx", ALC287_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x87d3, "HP Laptop 15-gw0xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), - SND_PCI_QUIRK(0x103c, 0x87df, "HP ProBook 430 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x87e5, "HP ProBook 440 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED), -@@ -10713,12 +10755,14 @@ static const struct hda_quirk alc269_fix - SND_PCI_QUIRK(0x103c, 0x8975, "HP EliteBook x360 840 Aero G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x897d, "HP mt440 Mobile Thin Client U74", ALC236_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8981, "HP Elite Dragonfly G3", ALC245_FIXUP_CS35L41_SPI_4), -+ SND_PCI_QUIRK(0x103c, 0x898a, "HP Pavilion 15-eg100", ALC287_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x898e, "HP EliteBook 835 G9", ALC287_FIXUP_CS35L41_I2C_2), - SND_PCI_QUIRK(0x103c, 0x898f, "HP EliteBook 835 G9", ALC287_FIXUP_CS35L41_I2C_2), - SND_PCI_QUIRK(0x103c, 0x8991, "HP EliteBook 845 G9", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8992, "HP EliteBook 845 G9", ALC287_FIXUP_CS35L41_I2C_2), - SND_PCI_QUIRK(0x103c, 0x8994, "HP EliteBook 855 G9", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8995, "HP EliteBook 855 G9", ALC287_FIXUP_CS35L41_I2C_2), -+ SND_PCI_QUIRK(0x103c, 0x89a0, "HP Laptop 15-dw4xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), - SND_PCI_QUIRK(0x103c, 0x89a4, "HP ProBook 440 G9", ALC236_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x89a6, "HP ProBook 450 G9", ALC236_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x89aa, "HP EliteBook 630 G9", ALC236_FIXUP_HP_GPIO_LED), -@@ -10733,6 +10777,7 @@ static const struct hda_quirk alc269_fix - SND_PCI_QUIRK(0x103c, 0x8a0f, "HP Pavilion 14-ec1xxx", ALC287_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8a20, "HP Laptop 15s-fq5xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), - SND_PCI_QUIRK(0x103c, 0x8a25, "HP Victus 16-d1xxx (MB 8A25)", ALC245_FIXUP_HP_MUTE_LED_COEFBIT), -+ SND_PCI_QUIRK(0x103c, 0x8a26, "HP Victus 16-d1xxx (MB 8A26)", ALC245_FIXUP_HP_MUTE_LED_COEFBIT), - SND_PCI_QUIRK(0x103c, 0x8a28, "HP Envy 13", ALC287_FIXUP_CS35L41_I2C_2), - SND_PCI_QUIRK(0x103c, 0x8a29, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2), - SND_PCI_QUIRK(0x103c, 0x8a2a, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2), -@@ -10742,6 +10787,7 @@ static const struct hda_quirk alc269_fix - SND_PCI_QUIRK(0x103c, 0x8a2e, "HP Envy 16", ALC287_FIXUP_CS35L41_I2C_2), - SND_PCI_QUIRK(0x103c, 0x8a30, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2), - SND_PCI_QUIRK(0x103c, 0x8a31, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2), -+ SND_PCI_QUIRK(0x103c, 0x8a4f, "HP Victus 15-fa0xxx (MB 8A4F)", ALC245_FIXUP_HP_MUTE_LED_COEFBIT), - SND_PCI_QUIRK(0x103c, 0x8a6e, "HP EDNA 360", ALC287_FIXUP_CS35L41_I2C_4), - SND_PCI_QUIRK(0x103c, 0x8a74, "HP ProBook 440 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8a78, "HP Dev One", ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST), -@@ -10787,7 +10833,10 @@ static const struct hda_quirk alc269_fix - SND_PCI_QUIRK(0x103c, 0x8b97, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), - SND_PCI_QUIRK(0x103c, 0x8bb3, "HP Slim OMEN", ALC287_FIXUP_CS35L41_I2C_2), - SND_PCI_QUIRK(0x103c, 0x8bb4, "HP Slim OMEN", ALC287_FIXUP_CS35L41_I2C_2), -+ SND_PCI_QUIRK(0x103c, 0x8bbe, "HP Victus 16-r0xxx (MB 8BBE)", ALC245_FIXUP_HP_MUTE_LED_COEFBIT), -+ SND_PCI_QUIRK(0x103c, 0x8bc8, "HP Victus 15-fa1xxx", ALC245_FIXUP_HP_MUTE_LED_COEFBIT), - SND_PCI_QUIRK(0x103c, 0x8bcd, "HP Omen 16-xd0xxx", ALC245_FIXUP_HP_MUTE_LED_V1_COEFBIT), -+ SND_PCI_QUIRK(0x103c, 0x8bd4, "HP Victus 16-s0xxx (MB 8BD4)", ALC245_FIXUP_HP_MUTE_LED_COEFBIT), - SND_PCI_QUIRK(0x103c, 0x8bdd, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2), - SND_PCI_QUIRK(0x103c, 0x8bde, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2), - SND_PCI_QUIRK(0x103c, 0x8bdf, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2), -@@ -10840,6 +10889,8 @@ static const struct hda_quirk alc269_fix - SND_PCI_QUIRK(0x103c, 0x8c91, "HP EliteBook 660", ALC236_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8c96, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), - SND_PCI_QUIRK(0x103c, 0x8c97, "HP ZBook", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), -+ SND_PCI_QUIRK(0x103c, 0x8c99, "HP Victus 16-r1xxx (MB 8C99)", ALC245_FIXUP_HP_MUTE_LED_COEFBIT), -+ SND_PCI_QUIRK(0x103c, 0x8c9c, "HP Victus 16-s1xxx (MB 8C9C)", ALC245_FIXUP_HP_MUTE_LED_COEFBIT), - SND_PCI_QUIRK(0x103c, 0x8ca1, "HP ZBook Power", ALC236_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8ca2, "HP ZBook Power", ALC236_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8ca4, "HP ZBook Fury", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), -@@ -10852,6 +10903,7 @@ static const struct hda_quirk alc269_fix - SND_PCI_QUIRK(0x103c, 0x8ce0, "HP SnowWhite", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8cf5, "HP ZBook Studio 16", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8d01, "HP ZBook Power 14 G12", ALC285_FIXUP_HP_GPIO_LED), -+ SND_PCI_QUIRK(0x103c, 0x8d07, "HP Victus 15-fb2xxx (MB 8D07)", ALC245_FIXUP_HP_MUTE_LED_COEFBIT), - SND_PCI_QUIRK(0x103c, 0x8d18, "HP EliteStudio 8 AIO", ALC274_FIXUP_HP_AIO_BIND_DACS), - SND_PCI_QUIRK(0x103c, 0x8d84, "HP EliteBook X G1i", ALC285_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8d85, "HP EliteBook 14 G12", ALC285_FIXUP_HP_GPIO_LED), -@@ -10881,7 +10933,9 @@ static const struct hda_quirk alc269_fix - SND_PCI_QUIRK(0x103c, 0x8def, "HP EliteBook 660 G12", ALC236_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8df0, "HP EliteBook 630 G12", ALC236_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8df1, "HP EliteBook 630 G12", ALC236_FIXUP_HP_GPIO_LED), -+ SND_PCI_QUIRK(0x103c, 0x8dfb, "HP EliteBook 6 G1a 14", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), - SND_PCI_QUIRK(0x103c, 0x8dfc, "HP EliteBook 645 G12", ALC236_FIXUP_HP_GPIO_LED), -+ SND_PCI_QUIRK(0x103c, 0x8dfd, "HP EliteBook 6 G1a 16", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), - SND_PCI_QUIRK(0x103c, 0x8dfe, "HP EliteBook 665 G12", ALC236_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8e11, "HP Trekker", ALC287_FIXUP_CS35L41_I2C_2), - SND_PCI_QUIRK(0x103c, 0x8e12, "HP Trekker", ALC287_FIXUP_CS35L41_I2C_2), -@@ -10904,6 +10958,8 @@ static const struct hda_quirk alc269_fix - SND_PCI_QUIRK(0x103c, 0x8e60, "HP Trekker ", ALC287_FIXUP_CS35L41_I2C_2), - SND_PCI_QUIRK(0x103c, 0x8e61, "HP Trekker ", ALC287_FIXUP_CS35L41_I2C_2), - SND_PCI_QUIRK(0x103c, 0x8e62, "HP Trekker ", ALC287_FIXUP_CS35L41_I2C_2), -+ SND_PCI_QUIRK(0x1043, 0x1032, "ASUS VivoBook X513EA", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE), -+ SND_PCI_QUIRK(0x1043, 0x1034, "ASUS GU605C", ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1), - SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), - SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), - SND_PCI_QUIRK(0x1043, 0x1054, "ASUS G614FH/FM/FP", ALC287_FIXUP_CS35L41_I2C_2), -@@ -10932,6 +10988,7 @@ static const struct hda_quirk alc269_fix - SND_PCI_QUIRK(0x1043, 0x12e0, "ASUS X541SA", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1043, 0x12f0, "ASUS X541UV", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1043, 0x1313, "Asus K42JZ", ALC269VB_FIXUP_ASUS_MIC_NO_PRESENCE), -+ SND_PCI_QUIRK(0x1043, 0x1314, "ASUS GA605K", ALC285_FIXUP_ASUS_GA605K_HEADSET_MIC), - SND_PCI_QUIRK(0x1043, 0x13b0, "ASUS Z550SA", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK), - SND_PCI_QUIRK(0x1043, 0x1433, "ASUS GX650PY/PZ/PV/PU/PYV/PZV/PIV/PVV", ALC285_FIXUP_ASUS_I2C_HEADSET_MIC), -@@ -10971,6 +11028,7 @@ static const struct hda_quirk alc269_fix - SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), - SND_PCI_QUIRK(0x1043, 0x1a63, "ASUS UX3405MA", ALC245_FIXUP_CS35L41_SPI_2), - SND_PCI_QUIRK(0x1043, 0x1a83, "ASUS UM5302LA", ALC294_FIXUP_CS35L41_I2C_2), -+ SND_PCI_QUIRK(0x1043, 0x1a8e, "ASUS G712LWS", ALC294_FIXUP_LENOVO_MIC_LOCATION), - SND_PCI_QUIRK(0x1043, 0x1a8f, "ASUS UX582ZS", ALC245_FIXUP_CS35L41_SPI_2), - SND_PCI_QUIRK(0x1043, 0x1b11, "ASUS UX431DA", ALC294_FIXUP_ASUS_COEF_1B), - SND_PCI_QUIRK(0x1043, 0x1b13, "ASUS U41SV/GA403U", ALC285_FIXUP_ASUS_GA403U_HEADSET_MIC), -@@ -10997,6 +11055,7 @@ static const struct hda_quirk alc269_fix - SND_PCI_QUIRK(0x1043, 0x1df3, "ASUS UM5606WA", ALC294_FIXUP_BASS_SPEAKER_15), - SND_PCI_QUIRK(0x1043, 0x1264, "ASUS UM5606KA", ALC294_FIXUP_BASS_SPEAKER_15), - SND_PCI_QUIRK(0x1043, 0x1e02, "ASUS UX3402ZA", ALC245_FIXUP_CS35L41_SPI_2), -+ SND_PCI_QUIRK(0x1043, 0x1e10, "ASUS VivoBook X507UAR", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502), - SND_PCI_QUIRK(0x1043, 0x1e12, "ASUS UM3402", ALC287_FIXUP_CS35L41_I2C_2), - SND_PCI_QUIRK(0x1043, 0x1e1f, "ASUS Vivobook 15 X1504VAP", ALC2XX_FIXUP_HEADSET_MIC), -@@ -11005,6 +11064,7 @@ static const struct hda_quirk alc269_fix - SND_PCI_QUIRK(0x1043, 0x1e63, "ASUS H7606W", ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1), - SND_PCI_QUIRK(0x1043, 0x1e83, "ASUS GA605W", ALC285_FIXUP_ASUS_GU605_SPI_SPEAKER2_TO_DAC1), - SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401), -+ SND_PCI_QUIRK(0x1043, 0x1e93, "ASUS ExpertBook B9403CVAR", ALC294_FIXUP_ASUS_HPE), - SND_PCI_QUIRK(0x1043, 0x1eb3, "ASUS Ally RCLA72", ALC287_FIXUP_TAS2781_I2C), - SND_PCI_QUIRK(0x1043, 0x1ed3, "ASUS HN7306W", ALC287_FIXUP_CS35L41_I2C_2), - SND_PCI_QUIRK(0x1043, 0x1ee2, "ASUS UM6702RA/RC", ALC287_FIXUP_CS35L41_I2C_2), -@@ -11049,6 +11109,7 @@ static const struct hda_quirk alc269_fix - SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC), - SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC), - SND_PCI_QUIRK(0x1043, 0x8516, "ASUS X101CH", ALC269_FIXUP_ASUS_X101), -+ SND_PCI_QUIRK(0x1043, 0x88f4, "ASUS NUC14LNS", ALC245_FIXUP_CS35L41_SPI_1), - SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2), - SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), - SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), -@@ -11106,6 +11167,8 @@ static const struct hda_quirk alc269_fix - SND_PCI_QUIRK(0x1558, 0x14a1, "Clevo L141MU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x2624, "Clevo L240TU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x28c1, "Clevo V370VND", ALC2XX_FIXUP_HEADSET_MIC), -+ SND_PCI_QUIRK(0x1558, 0x35a1, "Clevo V3[56]0EN[CDE]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), -+ SND_PCI_QUIRK(0x1558, 0x35b1, "Clevo V3[57]0WN[MNP]Q", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x4018, "Clevo NV40M[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x4019, "Clevo NV40MZ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x4020, "Clevo NV40MB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), -@@ -11133,6 +11196,7 @@ static const struct hda_quirk alc269_fix - SND_PCI_QUIRK(0x1558, 0x51b1, "Clevo NS50AU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x51b3, "Clevo NS70AU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x5630, "Clevo NP50RNJS", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), -+ SND_PCI_QUIRK(0x1558, 0x5700, "Clevo X560WN[RST]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x70a1, "Clevo NB70T[HJK]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x70b3, "Clevo NK70SB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0x70f2, "Clevo NH79EPY", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), -@@ -11172,6 +11236,7 @@ static const struct hda_quirk alc269_fix - SND_PCI_QUIRK(0x1558, 0xa650, "Clevo NP[567]0SN[CD]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0xa671, "Clevo NP70SN[CDE]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0xa741, "Clevo V54x_6x_TNE", ALC245_FIXUP_CLEVO_NOISY_MIC), -+ SND_PCI_QUIRK(0x1558, 0xa743, "Clevo V54x_6x_TU", ALC245_FIXUP_CLEVO_NOISY_MIC), - SND_PCI_QUIRK(0x1558, 0xa763, "Clevo V54x_6x_TU", ALC245_FIXUP_CLEVO_NOISY_MIC), - SND_PCI_QUIRK(0x1558, 0xb018, "Clevo NP50D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1558, 0xb019, "Clevo NH77D[BE]Q", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), -@@ -11350,6 +11415,7 @@ static const struct hda_quirk alc269_fix - SND_PCI_QUIRK(0x1854, 0x0440, "LG CQ6", ALC256_FIXUP_HEADPHONE_AMP_VOL), - SND_PCI_QUIRK(0x1854, 0x0441, "LG CQ6 AIO", ALC256_FIXUP_HEADPHONE_AMP_VOL), - SND_PCI_QUIRK(0x1854, 0x0488, "LG gram 16 (16Z90R)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS), -+ SND_PCI_QUIRK(0x1854, 0x0489, "LG gram 16 (16Z90R-A)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS), - SND_PCI_QUIRK(0x1854, 0x048a, "LG gram 17 (17ZD90R)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS), - SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MACH-WX9", ALC256_FIXUP_HUAWEI_MACH_WX9_PINS), - SND_PCI_QUIRK(0x19e5, 0x320f, "Huawei WRT-WX9 ", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE), -@@ -11373,17 +11439,22 @@ static const struct hda_quirk alc269_fix - SND_PCI_QUIRK(0x1d05, 0x121b, "TongFang GMxAGxx", ALC269_FIXUP_NO_SHUTUP), - SND_PCI_QUIRK(0x1d05, 0x1387, "TongFang GMxIXxx", ALC2XX_FIXUP_HEADSET_MIC), - SND_PCI_QUIRK(0x1d05, 0x1409, "TongFang GMxIXxx", ALC2XX_FIXUP_HEADSET_MIC), -+ SND_PCI_QUIRK(0x1d05, 0x300f, "TongFang X6AR5xxY", ALC2XX_FIXUP_HEADSET_MIC), -+ SND_PCI_QUIRK(0x1d05, 0x3019, "TongFang X6FR5xxY", ALC2XX_FIXUP_HEADSET_MIC), - SND_PCI_QUIRK(0x1d17, 0x3288, "Haier Boyue G42", ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS), - SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC), - SND_PCI_QUIRK(0x1d72, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC), - SND_PCI_QUIRK(0x1d72, 0x1945, "Redmi G", ALC256_FIXUP_ASUS_HEADSET_MIC), - SND_PCI_QUIRK(0x1d72, 0x1947, "RedmiBook Air", ALC255_FIXUP_XIAOMI_HEADSET_MIC), -+ SND_PCI_QUIRK(0x1ee7, 0x2078, "HONOR BRB-X M1010", ALC2XX_FIXUP_HEADSET_MIC), - SND_PCI_QUIRK(0x1f66, 0x0105, "Ayaneo Portable Game Player", ALC287_FIXUP_CS35L41_I2C_2), - SND_PCI_QUIRK(0x2014, 0x800a, "Positivo ARN50", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), - SND_PCI_QUIRK(0x2782, 0x0214, "VAIO VJFE-CL", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), - SND_PCI_QUIRK(0x2782, 0x0228, "Infinix ZERO BOOK 13", ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13), - SND_PCI_QUIRK(0x2782, 0x0232, "CHUWI CoreBook XPro", ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO), -+ SND_PCI_QUIRK(0x2782, 0x1407, "Positivo P15X", ALC269_FIXUP_POSITIVO_P15X_HEADSET_MIC), -+ SND_PCI_QUIRK(0x2782, 0x1409, "Positivo K116J", ALC269_FIXUP_POSITIVO_P15X_HEADSET_MIC), - SND_PCI_QUIRK(0x2782, 0x1701, "Infinix Y4 Max", ALC269VC_FIXUP_INFINIX_Y4_MAX), - SND_PCI_QUIRK(0x2782, 0x1705, "MEDION E15433", ALC269VC_FIXUP_INFINIX_Y4_MAX), - SND_PCI_QUIRK(0x2782, 0x1707, "Vaio VJFE-ADL", ALC298_FIXUP_SPK_VOLUME), -@@ -11395,6 +11466,7 @@ static const struct hda_quirk alc269_fix - SND_PCI_QUIRK(0xf111, 0x0001, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0xf111, 0x0006, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0xf111, 0x0009, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE), -+ SND_PCI_QUIRK(0xf111, 0x000b, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0xf111, 0x000c, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE), - - #if 0 -diff -purNx .git BPI-Router-Linux-kernel/sound/pci/hda/tas2781_hda.c BPI-Router-Linux-kernel-6.16.12/sound/pci/hda/tas2781_hda.c ---- BPI-Router-Linux-kernel/sound/pci/hda/tas2781_hda.c 2025-10-22 13:53:23.675326923 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/pci/hda/tas2781_hda.c 2025-10-22 13:53:56.851167521 -0400 -@@ -31,6 +31,23 @@ const efi_guid_t tasdev_fct_efi_guid[] = - }; - EXPORT_SYMBOL_NS_GPL(tasdev_fct_efi_guid, "SND_HDA_SCODEC_TAS2781"); - -+/* -+ * The order of calibrated-data writing function is a bit different from the -+ * order in UEFI. Here is the conversion to match the order of calibrated-data -+ * writing function. -+ */ -+static void cali_cnv(unsigned char *data, unsigned int base, int offset) -+{ -+ struct cali_reg reg_data; -+ -+ memcpy(®_data, &data[base], sizeof(reg_data)); -+ /* the data order has to be swapped between r0_low_reg and inv0_reg */ -+ swap(reg_data.r0_low_reg, reg_data.invr0_reg); -+ -+ cpu_to_be32_array((__force __be32 *)(data + offset + 1), -+ (u32 *)®_data, TASDEV_CALIB_N); -+} -+ - static void tas2781_apply_calib(struct tasdevice_priv *p) - { - struct calidata *cali_data = &p->cali_data; -@@ -44,7 +61,7 @@ static void tas2781_apply_calib(struct t - TASDEVICE_REG(0, 0x13, 0x70), - TASDEVICE_REG(0, 0x18, 0x7c), - }; -- unsigned int crc, oft; -+ unsigned int crc, oft, node_num; - unsigned char *buf; - int i, j, k, l; - -@@ -80,8 +97,9 @@ static void tas2781_apply_calib(struct t - dev_err(p->dev, "%s: CRC error\n", __func__); - return; - } -+ node_num = tmp_val[1]; - -- for (j = 0, k = 0; j < tmp_val[1]; j++) { -+ for (j = 0, k = 0; j < node_num; j++) { - oft = j * 6 + 3; - if (tmp_val[oft] == TASDEV_UEFI_CALI_REG_ADDR_FLG) { - for (i = 0; i < TASDEV_CALIB_N; i++) { -@@ -99,8 +117,8 @@ static void tas2781_apply_calib(struct t - } - - data[l] = k; -- for (i = 0; i < TASDEV_CALIB_N * 4; i++) -- data[l + i] = data[4 * oft + i]; -+ oft++; -+ cali_cnv(data, 4 * oft, l); - k++; - } - } -@@ -126,9 +144,8 @@ static void tas2781_apply_calib(struct t - - for (j = p->ndev - 1; j >= 0; j--) { - l = j * (cali_data->cali_dat_sz_per_dev + 1); -- for (i = TASDEV_CALIB_N * 4; i > 0 ; i--) -- data[l + i] = data[p->index * 5 + i]; -- data[l+i] = j; -+ cali_cnv(data, cali_data->cali_dat_sz_per_dev * j, l); -+ data[l] = j; - } - } - -diff -purNx .git BPI-Router-Linux-kernel/sound/pci/hda/tas2781_hda_i2c.c BPI-Router-Linux-kernel-6.16.12/sound/pci/hda/tas2781_hda_i2c.c ---- BPI-Router-Linux-kernel/sound/pci/hda/tas2781_hda_i2c.c 2025-10-22 13:53:23.675326923 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/pci/hda/tas2781_hda_i2c.c 2025-10-22 13:53:56.851167521 -0400 -@@ -282,16 +282,17 @@ static int tas2563_save_calibration(stru - { - efi_guid_t efi_guid = tasdev_fct_efi_guid[LENOVO]; - char *vars[TASDEV_CALIB_N] = { -- "R0_%d", "InvR0_%d", "R0_Low_%d", "Power_%d", "TLim_%d" -+ "R0_%d", "R0_Low_%d", "InvR0_%d", "Power_%d", "TLim_%d" - }; - efi_char16_t efi_name[TAS2563_CAL_VAR_NAME_MAX]; - unsigned long max_size = TAS2563_CAL_DATA_SIZE; - unsigned char var8[TAS2563_CAL_VAR_NAME_MAX]; -- struct tasdevice_priv *p = h->hda_priv; -+ struct tasdevice_priv *p = h->priv; - struct calidata *cd = &p->cali_data; - struct cali_reg *r = &cd->cali_reg_array; - unsigned int offset = 0; - unsigned char *data; -+ __be32 bedata; - efi_status_t status; - unsigned int attr; - int ret, i, j, k; -@@ -333,6 +334,8 @@ static int tas2563_save_calibration(stru - i, j, status); - return -EINVAL; - } -+ bedata = cpu_to_be32(*(uint32_t *)&data[offset]); -+ memcpy(&data[offset], &bedata, sizeof(bedata)); - offset += TAS2563_CAL_DATA_SIZE; - } - } -diff -purNx .git BPI-Router-Linux-kernel/sound/pci/intel8x0.c BPI-Router-Linux-kernel-6.16.12/sound/pci/intel8x0.c ---- BPI-Router-Linux-kernel/sound/pci/intel8x0.c 2025-10-22 13:53:23.675326923 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/pci/intel8x0.c 2025-10-22 13:53:56.851167521 -0400 -@@ -2249,7 +2249,7 @@ static int snd_intel8x0_mixer(struct int - tmp |= chip->ac97_sdin[0] << ICH_DI1L_SHIFT; - for (i = 1; i < 4; i++) { - if (pcm->r[0].codec[i]) { -- tmp |= chip->ac97_sdin[pcm->r[0].codec[1]->num] << ICH_DI2L_SHIFT; -+ tmp |= chip->ac97_sdin[pcm->r[0].codec[i]->num] << ICH_DI2L_SHIFT; - break; - } - } -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/amd/acp/acp-i2s.c BPI-Router-Linux-kernel-6.16.12/sound/soc/amd/acp/acp-i2s.c ---- BPI-Router-Linux-kernel/sound/soc/amd/acp/acp-i2s.c 2025-10-22 13:53:23.675326923 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/amd/acp/acp-i2s.c 2025-10-22 13:53:56.851167521 -0400 -@@ -72,7 +72,7 @@ static int acp_i2s_set_fmt(struct snd_so - unsigned int fmt) - { - struct device *dev = cpu_dai->component->dev; -- struct acp_chip_info *chip = dev_get_platdata(dev); -+ struct acp_chip_info *chip = dev_get_drvdata(dev->parent); - int mode; - - mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK; -@@ -196,7 +196,7 @@ static int acp_i2s_hwparams(struct snd_p - u32 reg_val, fmt_reg, tdm_fmt; - u32 lrclk_div_val, bclk_div_val; - -- chip = dev_get_platdata(dev); -+ chip = dev_get_drvdata(dev->parent); - rsrc = chip->rsrc; - - /* These values are as per Hardware Spec */ -@@ -383,7 +383,7 @@ static int acp_i2s_trigger(struct snd_pc - { - struct acp_stream *stream = substream->runtime->private_data; - struct device *dev = dai->component->dev; -- struct acp_chip_info *chip = dev_get_platdata(dev); -+ struct acp_chip_info *chip = dev_get_drvdata(dev->parent); - struct acp_resource *rsrc = chip->rsrc; - u32 val, period_bytes, reg_val, ier_val, water_val, buf_size, buf_reg; - -@@ -513,14 +513,13 @@ static int acp_i2s_trigger(struct snd_pc - static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) - { - struct device *dev = dai->component->dev; -- struct acp_chip_info *chip = dev_get_platdata(dev); -+ struct acp_chip_info *chip = dev_get_drvdata(dev->parent); - struct acp_resource *rsrc = chip->rsrc; - struct acp_stream *stream = substream->runtime->private_data; - u32 reg_dma_size = 0, reg_fifo_size = 0, reg_fifo_addr = 0; - u32 phy_addr = 0, acp_fifo_addr = 0, ext_int_ctrl; - unsigned int dir = substream->stream; - -- chip = dev_get_platdata(dev); - switch (dai->driver->id) { - case I2S_SP_INSTANCE: - if (dir == SNDRV_PCM_STREAM_PLAYBACK) { -@@ -629,7 +628,7 @@ static int acp_i2s_startup(struct snd_pc - { - struct acp_stream *stream = substream->runtime->private_data; - struct device *dev = dai->component->dev; -- struct acp_chip_info *chip = dev_get_platdata(dev); -+ struct acp_chip_info *chip = dev_get_drvdata(dev->parent); - struct acp_resource *rsrc = chip->rsrc; - unsigned int dir = substream->stream; - unsigned int irq_bit = 0; -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/amd/acp/acp-pci.c BPI-Router-Linux-kernel-6.16.12/sound/soc/amd/acp/acp-pci.c ---- BPI-Router-Linux-kernel/sound/soc/amd/acp/acp-pci.c 2025-10-22 13:53:23.675326923 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/amd/acp/acp-pci.c 2025-10-22 13:53:56.851167521 -0400 -@@ -137,26 +137,26 @@ static int acp_pci_probe(struct pci_dev - chip->name = "acp_asoc_renoir"; - chip->rsrc = &rn_rsrc; - chip->acp_hw_ops_init = acp31_hw_ops_init; -- chip->machines = &snd_soc_acpi_amd_acp_machines; -+ chip->machines = snd_soc_acpi_amd_acp_machines; - break; - case 0x6f: - chip->name = "acp_asoc_rembrandt"; - chip->rsrc = &rmb_rsrc; - chip->acp_hw_ops_init = acp6x_hw_ops_init; -- chip->machines = &snd_soc_acpi_amd_rmb_acp_machines; -+ chip->machines = snd_soc_acpi_amd_rmb_acp_machines; - break; - case 0x63: - chip->name = "acp_asoc_acp63"; - chip->rsrc = &acp63_rsrc; - chip->acp_hw_ops_init = acp63_hw_ops_init; -- chip->machines = &snd_soc_acpi_amd_acp63_acp_machines; -+ chip->machines = snd_soc_acpi_amd_acp63_acp_machines; - break; - case 0x70: - case 0x71: - chip->name = "acp_asoc_acp70"; - chip->rsrc = &acp70_rsrc; - chip->acp_hw_ops_init = acp70_hw_ops_init; -- chip->machines = &snd_soc_acpi_amd_acp70_acp_machines; -+ chip->machines = snd_soc_acpi_amd_acp70_acp_machines; - break; - default: - dev_err(dev, "Unsupported device revision:0x%x\n", pci->revision); -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/amd/acp/amd-acpi-mach.c BPI-Router-Linux-kernel-6.16.12/sound/soc/amd/acp/amd-acpi-mach.c ---- BPI-Router-Linux-kernel/sound/soc/amd/acp/amd-acpi-mach.c 2025-10-22 13:53:23.675326923 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/amd/acp/amd-acpi-mach.c 2025-10-22 13:53:56.851167521 -0400 -@@ -8,12 +8,12 @@ - - #include - --struct snd_soc_acpi_codecs amp_rt1019 = { -+static struct snd_soc_acpi_codecs amp_rt1019 = { - .num_codecs = 1, - .codecs = {"10EC1019"} - }; - --struct snd_soc_acpi_codecs amp_max = { -+static struct snd_soc_acpi_codecs amp_max = { - .num_codecs = 1, - .codecs = {"MX98360A"} - }; -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/amd/acp/amd.h BPI-Router-Linux-kernel-6.16.12/sound/soc/amd/acp/amd.h ---- BPI-Router-Linux-kernel/sound/soc/amd/acp/amd.h 2025-10-22 13:53:23.675326923 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/amd/acp/amd.h 2025-10-22 13:53:56.851167521 -0400 -@@ -130,7 +130,7 @@ - #define PDM_DMA_INTR_MASK 0x10000 - #define PDM_DEC_64 0x2 - #define PDM_CLK_FREQ_MASK 0x07 --#define PDM_MISC_CTRL_MASK 0x10 -+#define PDM_MISC_CTRL_MASK 0x18 - #define PDM_ENABLE 0x01 - #define PDM_DISABLE 0x00 - #define DMA_EN_MASK 0x02 -@@ -243,10 +243,10 @@ extern struct acp_resource rmb_rsrc; - extern struct acp_resource acp63_rsrc; - extern struct acp_resource acp70_rsrc; - --extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp_machines; --extern struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_acp_machines; --extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_acp_machines; --extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_acp_machines; -+extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp_machines[]; -+extern struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_acp_machines[]; -+extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_acp_machines[]; -+extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_acp_machines[]; - - extern const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops; - extern const struct snd_soc_dai_ops acp_dmic_dai_ops; -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/amd/ps/acp63.h BPI-Router-Linux-kernel-6.16.12/sound/soc/amd/ps/acp63.h ---- BPI-Router-Linux-kernel/sound/soc/amd/ps/acp63.h 2025-10-22 13:53:23.675326923 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/amd/ps/acp63.h 2025-10-22 13:53:56.851167521 -0400 -@@ -334,6 +334,8 @@ struct acp_hw_ops { - * @addr: pci ioremap address - * @reg_range: ACP reigister range - * @acp_rev: ACP PCI revision id -+ * @acp_sw_pad_keeper_en: store acp SoundWire pad keeper enable register value -+ * @acp_pad_pulldown_ctrl: store acp pad pulldown control register value - * @acp63_sdw0-dma_intr_stat: DMA interrupt status array for ACP6.3 platform SoundWire - * manager-SW0 instance - * @acp63_sdw_dma_intr_stat: DMA interrupt status array for ACP6.3 platform SoundWire -@@ -367,6 +369,8 @@ struct acp63_dev_data { - u32 addr; - u32 reg_range; - u32 acp_rev; -+ u32 acp_sw_pad_keeper_en; -+ u32 acp_pad_pulldown_ctrl; - u16 acp63_sdw0_dma_intr_stat[ACP63_SDW0_DMA_MAX_STREAMS]; - u16 acp63_sdw1_dma_intr_stat[ACP63_SDW1_DMA_MAX_STREAMS]; - u16 acp70_sdw0_dma_intr_stat[ACP70_SDW0_DMA_MAX_STREAMS]; -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/amd/ps/ps-common.c BPI-Router-Linux-kernel-6.16.12/sound/soc/amd/ps/ps-common.c ---- BPI-Router-Linux-kernel/sound/soc/amd/ps/ps-common.c 2025-10-22 13:53:23.675326923 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/amd/ps/ps-common.c 2025-10-22 13:53:56.851167521 -0400 -@@ -160,6 +160,8 @@ static int __maybe_unused snd_acp63_susp - - adata = dev_get_drvdata(dev); - if (adata->is_sdw_dev) { -+ adata->acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW0_PAD_KEEPER_EN); -+ adata->acp_pad_pulldown_ctrl = readl(adata->acp63_base + ACP_PAD_PULLDOWN_CTRL); - adata->sdw_en_stat = check_acp_sdw_enable_status(adata); - if (adata->sdw_en_stat) { - writel(1, adata->acp63_base + ACP_ZSC_DSP_CTRL); -@@ -197,6 +199,7 @@ static int __maybe_unused snd_acp63_runt - static int __maybe_unused snd_acp63_resume(struct device *dev) - { - struct acp63_dev_data *adata; -+ u32 acp_sw_pad_keeper_en; - int ret; - - adata = dev_get_drvdata(dev); -@@ -209,6 +212,12 @@ static int __maybe_unused snd_acp63_resu - if (ret) - dev_err(dev, "ACP init failed\n"); - -+ acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW0_PAD_KEEPER_EN); -+ dev_dbg(dev, "ACP_SW0_PAD_KEEPER_EN:0x%x\n", acp_sw_pad_keeper_en); -+ if (!acp_sw_pad_keeper_en) { -+ writel(adata->acp_sw_pad_keeper_en, adata->acp63_base + ACP_SW0_PAD_KEEPER_EN); -+ writel(adata->acp_pad_pulldown_ctrl, adata->acp63_base + ACP_PAD_PULLDOWN_CTRL); -+ } - return ret; - } - -@@ -408,6 +417,8 @@ static int __maybe_unused snd_acp70_susp - - adata = dev_get_drvdata(dev); - if (adata->is_sdw_dev) { -+ adata->acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW0_PAD_KEEPER_EN); -+ adata->acp_pad_pulldown_ctrl = readl(adata->acp63_base + ACP_PAD_PULLDOWN_CTRL); - adata->sdw_en_stat = check_acp_sdw_enable_status(adata); - if (adata->sdw_en_stat) { - writel(1, adata->acp63_base + ACP_ZSC_DSP_CTRL); -@@ -445,6 +456,7 @@ static int __maybe_unused snd_acp70_runt - static int __maybe_unused snd_acp70_resume(struct device *dev) - { - struct acp63_dev_data *adata; -+ u32 acp_sw_pad_keeper_en; - int ret; - - adata = dev_get_drvdata(dev); -@@ -459,6 +471,12 @@ static int __maybe_unused snd_acp70_resu - if (ret) - dev_err(dev, "ACP init failed\n"); - -+ acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW0_PAD_KEEPER_EN); -+ dev_dbg(dev, "ACP_SW0_PAD_KEEPER_EN:0x%x\n", acp_sw_pad_keeper_en); -+ if (!acp_sw_pad_keeper_en) { -+ writel(adata->acp_sw_pad_keeper_en, adata->acp63_base + ACP_SW0_PAD_KEEPER_EN); -+ writel(adata->acp_pad_pulldown_ctrl, adata->acp63_base + ACP_PAD_PULLDOWN_CTRL); -+ } - return ret; - } - -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/amd/yc/acp6x-mach.c BPI-Router-Linux-kernel-6.16.12/sound/soc/amd/yc/acp6x-mach.c ---- BPI-Router-Linux-kernel/sound/soc/amd/yc/acp6x-mach.c 2025-10-22 13:53:23.675326923 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/amd/yc/acp6x-mach.c 2025-10-22 13:53:56.851167521 -0400 -@@ -356,6 +356,13 @@ static const struct dmi_system_id yc_acp - { - .driver_data = &acp6x_card, - .matches = { -+ DMI_MATCH(DMI_BOARD_VENDOR, "RB"), -+ DMI_MATCH(DMI_PRODUCT_NAME, "Nitro ANV15-41"), -+ } -+ }, -+ { -+ .driver_data = &acp6x_card, -+ .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_NAME, "83J2"), - } -@@ -363,6 +370,13 @@ static const struct dmi_system_id yc_acp - { - .driver_data = &acp6x_card, - .matches = { -+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), -+ DMI_MATCH(DMI_PRODUCT_NAME, "83J3"), -+ } -+ }, -+ { -+ .driver_data = &acp6x_card, -+ .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "UM5302TA"), - } -@@ -406,6 +420,13 @@ static const struct dmi_system_id yc_acp - .driver_data = &acp6x_card, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), -+ DMI_MATCH(DMI_PRODUCT_NAME, "M6501RM"), -+ } -+ }, -+ { -+ .driver_data = &acp6x_card, -+ .matches = { -+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "E1404FA"), - } - }, -@@ -454,6 +475,13 @@ static const struct dmi_system_id yc_acp - { - .driver_data = &acp6x_card, - .matches = { -+ DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."), -+ DMI_MATCH(DMI_PRODUCT_NAME, "Bravo 17 D7VF"), -+ } -+ }, -+ { -+ .driver_data = &acp6x_card, -+ .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Alienware"), - DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m17 R5 AMD"), - } -@@ -518,6 +546,20 @@ static const struct dmi_system_id yc_acp - .driver_data = &acp6x_card, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "HP"), -+ DMI_MATCH(DMI_PRODUCT_NAME, "Victus by HP Gaming Laptop 15-fb1xxx"), -+ } -+ }, -+ { -+ .driver_data = &acp6x_card, -+ .matches = { -+ DMI_MATCH(DMI_BOARD_VENDOR, "HP"), -+ DMI_MATCH(DMI_PRODUCT_NAME, "Victus by HP Gaming Laptop 15-fb2xxx"), -+ } -+ }, -+ { -+ .driver_data = &acp6x_card, -+ .matches = { -+ DMI_MATCH(DMI_BOARD_VENDOR, "HP"), - DMI_MATCH(DMI_BOARD_NAME, "8A42"), - } - }, -@@ -557,6 +599,13 @@ static const struct dmi_system_id yc_acp - } - }, - { -+ .driver_data = &acp6x_card, -+ .matches = { -+ DMI_MATCH(DMI_BOARD_VENDOR, "HP"), -+ DMI_MATCH(DMI_BOARD_NAME, "8A81"), -+ } -+ }, -+ { - .driver_data = &acp6x_card, - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "HP"), -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/apple/Kconfig BPI-Router-Linux-kernel-6.16.12/sound/soc/apple/Kconfig ---- BPI-Router-Linux-kernel/sound/soc/apple/Kconfig 2025-10-22 13:53:23.675326923 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/apple/Kconfig 2025-10-22 13:53:56.851167521 -0400 -@@ -2,7 +2,6 @@ config SND_SOC_APPLE_MCA - tristate "Apple Silicon MCA driver" - depends on ARCH_APPLE || COMPILE_TEST - select SND_DMAENGINE_PCM -- default ARCH_APPLE - help - This option enables an ASoC platform driver for MCA peripherals found - on Apple Silicon SoCs. -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/codecs/cs35l56.c BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/cs35l56.c ---- BPI-Router-Linux-kernel/sound/soc/codecs/cs35l56.c 2025-10-22 13:53:23.675326923 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/cs35l56.c 2025-10-22 13:53:56.851167521 -0400 -@@ -695,7 +695,7 @@ static int cs35l56_write_cal(struct cs35 - return ret; - - ret = cs_amp_write_cal_coeffs(&cs35l56->dsp.cs_dsp, -- &cs35l56_calibration_controls, -+ cs35l56->base.calibration_controls, - &cs35l56->base.cal_data); - - wm_adsp_stop(&cs35l56->dsp); -@@ -706,17 +706,41 @@ static int cs35l56_write_cal(struct cs35 - return ret; - } - --static void cs35l56_reinit_patch(struct cs35l56_private *cs35l56) -+static int cs35l56_dsp_download_and_power_up(struct cs35l56_private *cs35l56, -+ bool load_firmware) - { - int ret; - -- /* Use wm_adsp to load and apply the firmware patch and coefficient files */ -- ret = wm_adsp_power_up(&cs35l56->dsp, true); -+ /* -+ * Abort the first load if it didn't find the suffixed bins and -+ * we have an alternate fallback suffix. -+ */ -+ cs35l56->dsp.bin_mandatory = (load_firmware && cs35l56->fallback_fw_suffix); -+ -+ ret = wm_adsp_power_up(&cs35l56->dsp, load_firmware); -+ if ((ret == -ENOENT) && cs35l56->dsp.bin_mandatory) { -+ cs35l56->dsp.fwf_suffix = cs35l56->fallback_fw_suffix; -+ cs35l56->fallback_fw_suffix = NULL; -+ cs35l56->dsp.bin_mandatory = false; -+ ret = wm_adsp_power_up(&cs35l56->dsp, load_firmware); -+ } -+ - if (ret) { -- dev_dbg(cs35l56->base.dev, "%s: wm_adsp_power_up ret %d\n", __func__, ret); -- return; -+ dev_dbg(cs35l56->base.dev, "wm_adsp_power_up ret %d\n", ret); -+ return ret; - } - -+ return 0; -+} -+ -+static void cs35l56_reinit_patch(struct cs35l56_private *cs35l56) -+{ -+ int ret; -+ -+ ret = cs35l56_dsp_download_and_power_up(cs35l56, true); -+ if (ret) -+ return; -+ - cs35l56_write_cal(cs35l56); - - /* Always REINIT after applying patch or coefficients */ -@@ -750,11 +774,9 @@ static void cs35l56_patch(struct cs35l56 - * but only if firmware is missing. If firmware is already patched just - * power-up wm_adsp without downloading firmware. - */ -- ret = wm_adsp_power_up(&cs35l56->dsp, !!firmware_missing); -- if (ret) { -- dev_dbg(cs35l56->base.dev, "%s: wm_adsp_power_up ret %d\n", __func__, ret); -+ ret = cs35l56_dsp_download_and_power_up(cs35l56, firmware_missing); -+ if (ret) - goto err; -- } - - mutex_lock(&cs35l56->base.irq_lock); - -@@ -853,6 +875,34 @@ err: - pm_runtime_put_autosuspend(cs35l56->base.dev); - } - -+static int cs35l56_set_fw_suffix(struct cs35l56_private *cs35l56) -+{ -+ if (cs35l56->dsp.fwf_suffix) -+ return 0; -+ -+ if (!cs35l56->sdw_peripheral) -+ return 0; -+ -+ cs35l56->dsp.fwf_suffix = devm_kasprintf(cs35l56->base.dev, GFP_KERNEL, -+ "l%uu%u", -+ cs35l56->sdw_link_num, -+ cs35l56->sdw_unique_id); -+ if (!cs35l56->dsp.fwf_suffix) -+ return -ENOMEM; -+ -+ /* -+ * There are published firmware files for L56 B0 silicon using -+ * the ALSA prefix as the filename suffix. Default to trying these -+ * first, with the new name as an alternate. -+ */ -+ if ((cs35l56->base.type == 0x56) && (cs35l56->base.rev == 0xb0)) { -+ cs35l56->fallback_fw_suffix = cs35l56->dsp.fwf_suffix; -+ cs35l56->dsp.fwf_suffix = cs35l56->component->name_prefix; -+ } -+ -+ return 0; -+} -+ - static int cs35l56_component_probe(struct snd_soc_component *component) - { - struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); -@@ -892,6 +942,10 @@ static int cs35l56_component_probe(struc - return -ENOMEM; - - cs35l56->component = component; -+ ret = cs35l56_set_fw_suffix(cs35l56); -+ if (ret) -+ return ret; -+ - wm_adsp2_component_probe(&cs35l56->dsp, component); - - debugfs_create_bool("init_done", 0444, debugfs_root, &cs35l56->base.init_done); -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/codecs/cs35l56.h BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/cs35l56.h ---- BPI-Router-Linux-kernel/sound/soc/codecs/cs35l56.h 2025-10-22 13:53:23.675326923 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/cs35l56.h 2025-10-22 13:53:56.851167521 -0400 -@@ -20,8 +20,6 @@ - #define CS35L56_SDW_GEN_INT_MASK_1 0xc1 - #define CS35L56_SDW_INT_MASK_CODEC_IRQ BIT(0) - --#define CS35L56_SDW_INVALID_BUS_SCALE 0xf -- - #define CS35L56_RX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) - #define CS35L56_TX_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE \ - | SNDRV_PCM_FMTBIT_S32_LE) -@@ -38,6 +36,7 @@ struct cs35l56_private { - struct snd_soc_component *component; - struct regulator_bulk_data supplies[CS35L56_NUM_BULK_SUPPLIES]; - struct sdw_slave *sdw_peripheral; -+ const char *fallback_fw_suffix; - struct work_struct sdw_irq_work; - bool sdw_irq_no_unmask; - bool soft_resetting; -@@ -51,7 +50,8 @@ struct cs35l56_private { - u8 asp_slot_count; - bool tdm_mode; - bool sysclk_set; -- u8 old_sdw_clock_scale; -+ u8 sdw_link_num; -+ u8 sdw_unique_id; - }; - - extern const struct dev_pm_ops cs35l56_pm_ops_i2c_spi; -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/codecs/cs35l56-sdw.c BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/cs35l56-sdw.c ---- BPI-Router-Linux-kernel/sound/soc/codecs/cs35l56-sdw.c 2025-10-22 13:53:23.675326923 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/cs35l56-sdw.c 2025-10-22 13:53:56.851167521 -0400 -@@ -238,16 +238,15 @@ static const struct regmap_bus cs35l56_r - .val_format_endian_default = REGMAP_ENDIAN_BIG, - }; - --static int cs35l56_sdw_set_cal_index(struct cs35l56_private *cs35l56) -+static int cs35l56_sdw_get_unique_id(struct cs35l56_private *cs35l56) - { - int ret; - -- /* SoundWire UniqueId is used to index the calibration array */ - ret = sdw_read_no_pm(cs35l56->sdw_peripheral, SDW_SCP_DEVID_0); - if (ret < 0) - return ret; - -- cs35l56->base.cal_index = ret & 0xf; -+ cs35l56->sdw_unique_id = ret & 0xf; - - return 0; - } -@@ -259,11 +258,13 @@ static void cs35l56_sdw_init(struct sdw_ - - pm_runtime_get_noresume(cs35l56->base.dev); - -- if (cs35l56->base.cal_index < 0) { -- ret = cs35l56_sdw_set_cal_index(cs35l56); -- if (ret < 0) -- goto out; -- } -+ ret = cs35l56_sdw_get_unique_id(cs35l56); -+ if (ret) -+ goto out; -+ -+ /* SoundWire UniqueId is used to index the calibration array */ -+ if (cs35l56->base.cal_index < 0) -+ cs35l56->base.cal_index = cs35l56->sdw_unique_id; - - ret = cs35l56_init(cs35l56); - if (ret < 0) { -@@ -393,74 +394,6 @@ static int cs35l56_sdw_update_status(str - return 0; - } - --static int cs35l63_sdw_kick_divider(struct cs35l56_private *cs35l56, -- struct sdw_slave *peripheral) --{ -- unsigned int curr_scale_reg, next_scale_reg; -- int curr_scale, next_scale, ret; -- -- if (!cs35l56->base.init_done) -- return 0; -- -- if (peripheral->bus->params.curr_bank) { -- curr_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B1; -- next_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B0; -- } else { -- curr_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B0; -- next_scale_reg = SDW_SCP_BUSCLOCK_SCALE_B1; -- } -- -- /* -- * Current clock scale value must be different to new value. -- * Modify current to guarantee this. If next still has the dummy -- * value we wrote when it was current, the core code has not set -- * a new scale so restore its original good value -- */ -- curr_scale = sdw_read_no_pm(peripheral, curr_scale_reg); -- if (curr_scale < 0) { -- dev_err(cs35l56->base.dev, "Failed to read current clock scale: %d\n", curr_scale); -- return curr_scale; -- } -- -- next_scale = sdw_read_no_pm(peripheral, next_scale_reg); -- if (next_scale < 0) { -- dev_err(cs35l56->base.dev, "Failed to read next clock scale: %d\n", next_scale); -- return next_scale; -- } -- -- if (next_scale == CS35L56_SDW_INVALID_BUS_SCALE) { -- next_scale = cs35l56->old_sdw_clock_scale; -- ret = sdw_write_no_pm(peripheral, next_scale_reg, next_scale); -- if (ret < 0) { -- dev_err(cs35l56->base.dev, "Failed to modify current clock scale: %d\n", -- ret); -- return ret; -- } -- } -- -- cs35l56->old_sdw_clock_scale = curr_scale; -- ret = sdw_write_no_pm(peripheral, curr_scale_reg, CS35L56_SDW_INVALID_BUS_SCALE); -- if (ret < 0) { -- dev_err(cs35l56->base.dev, "Failed to modify current clock scale: %d\n", ret); -- return ret; -- } -- -- dev_dbg(cs35l56->base.dev, "Next bus scale: %#x\n", next_scale); -- -- return 0; --} -- --static int cs35l56_sdw_bus_config(struct sdw_slave *peripheral, -- struct sdw_bus_params *params) --{ -- struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev); -- -- if ((cs35l56->base.type == 0x63) && (cs35l56->base.rev < 0xa1)) -- return cs35l63_sdw_kick_divider(cs35l56, peripheral); -- -- return 0; --} -- - static int __maybe_unused cs35l56_sdw_clk_stop(struct sdw_slave *peripheral, - enum sdw_clk_stop_mode mode, - enum sdw_clk_stop_type type) -@@ -476,7 +409,6 @@ static const struct sdw_slave_ops cs35l5 - .read_prop = cs35l56_sdw_read_prop, - .interrupt_callback = cs35l56_sdw_interrupt, - .update_status = cs35l56_sdw_update_status, -- .bus_config = cs35l56_sdw_bus_config, - #ifdef DEBUG - .clk_stop = cs35l56_sdw_clk_stop, - #endif -@@ -587,6 +519,7 @@ static int cs35l56_sdw_probe(struct sdw_ - - cs35l56->base.dev = dev; - cs35l56->sdw_peripheral = peripheral; -+ cs35l56->sdw_link_num = peripheral->bus->link_id; - INIT_WORK(&cs35l56->sdw_irq_work, cs35l56_sdw_irq_work); - - dev_set_drvdata(dev, cs35l56); -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/codecs/cs35l56-shared.c BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/cs35l56-shared.c ---- BPI-Router-Linux-kernel/sound/soc/codecs/cs35l56-shared.c 2025-10-22 13:53:23.675326923 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/cs35l56-shared.c 2025-10-22 13:53:56.851167521 -0400 -@@ -838,6 +838,15 @@ const struct cirrus_amp_cal_controls cs3 - }; - EXPORT_SYMBOL_NS_GPL(cs35l56_calibration_controls, "SND_SOC_CS35L56_SHARED"); - -+static const struct cirrus_amp_cal_controls cs35l63_calibration_controls = { -+ .alg_id = 0xbf210, -+ .mem_region = WMFW_ADSP2_YM, -+ .ambient = "CAL_AMBIENT", -+ .calr = "CAL_R", -+ .status = "CAL_STATUS", -+ .checksum = "CAL_CHECKSUM", -+}; -+ - int cs35l56_get_calibration(struct cs35l56_base *cs35l56_base) - { - u64 silicon_uid = 0; -@@ -912,19 +921,31 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_read_prot_s - void cs35l56_log_tuning(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_dsp) - { - __be32 pid, sid, tid; -+ unsigned int alg_id; - int ret; - -+ switch (cs35l56_base->type) { -+ case 0x54: -+ case 0x56: -+ case 0x57: -+ alg_id = 0x9f212; -+ break; -+ default: -+ alg_id = 0xbf212; -+ break; -+ } -+ - scoped_guard(mutex, &cs_dsp->pwr_lock) { - ret = cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(cs_dsp, "AS_PRJCT_ID", -- WMFW_ADSP2_XM, 0x9f212), -+ WMFW_ADSP2_XM, alg_id), - 0, &pid, sizeof(pid)); - if (!ret) - ret = cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(cs_dsp, "AS_CHNNL_ID", -- WMFW_ADSP2_XM, 0x9f212), -+ WMFW_ADSP2_XM, alg_id), - 0, &sid, sizeof(sid)); - if (!ret) - ret = cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(cs_dsp, "AS_SNPSHT_ID", -- WMFW_ADSP2_XM, 0x9f212), -+ WMFW_ADSP2_XM, alg_id), - 0, &tid, sizeof(tid)); - } - -@@ -974,13 +995,15 @@ int cs35l56_hw_init(struct cs35l56_base - case 0x35A54: - case 0x35A56: - case 0x35A57: -+ cs35l56_base->calibration_controls = &cs35l56_calibration_controls; - break; - case 0x35A630: -+ cs35l56_base->calibration_controls = &cs35l63_calibration_controls; - devid = devid >> 4; - break; - default: - dev_err(cs35l56_base->dev, "Unknown device %x\n", devid); -- return ret; -+ return -ENODEV; - } - - cs35l56_base->type = devid & 0xFF; -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/codecs/cs48l32.c BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/cs48l32.c ---- BPI-Router-Linux-kernel/sound/soc/codecs/cs48l32.c 2025-10-22 13:53:23.675326923 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/cs48l32.c 2025-10-22 13:53:56.851167521 -0400 -@@ -2162,6 +2162,10 @@ static int cs48l32_hw_params(struct snd_ - n_slots_multiple = 1; - - sclk_target = snd_soc_tdm_params_to_bclk(params, slotw, n_slots, n_slots_multiple); -+ if (sclk_target < 0) { -+ cs48l32_asp_err(dai, "Invalid parameters\n"); -+ return sclk_target; -+ } - - for (i = 0; i < ARRAY_SIZE(cs48l32_sclk_rates); i++) { - if ((cs48l32_sclk_rates[i].freq >= sclk_target) && -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/codecs/es8326.c BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/es8326.c ---- BPI-Router-Linux-kernel/sound/soc/codecs/es8326.c 2025-10-22 13:53:23.675326923 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/es8326.c 2025-10-22 13:53:56.851167521 -0400 -@@ -1079,8 +1079,7 @@ static void es8326_init(struct snd_soc_c - regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x00); - regmap_write(es8326->regmap, ES8326_INTOUT_IO, - es8326->interrupt_clk); -- regmap_write(es8326->regmap, ES8326_SDINOUT1_IO, -- (ES8326_IO_DMIC_CLK << ES8326_SDINOUT1_SHIFT)); -+ regmap_write(es8326->regmap, ES8326_SDINOUT1_IO, ES8326_IO_INPUT); - regmap_write(es8326->regmap, ES8326_SDINOUT23_IO, ES8326_IO_INPUT); - - regmap_write(es8326->regmap, ES8326_ANA_PDN, 0x00); -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/codecs/hdac_hdmi.c BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/hdac_hdmi.c ---- BPI-Router-Linux-kernel/sound/soc/codecs/hdac_hdmi.c 2025-10-22 13:53:23.675326923 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/hdac_hdmi.c 2025-10-22 13:53:56.851167521 -0400 -@@ -1232,7 +1232,8 @@ static int hdac_hdmi_parse_eld(struct hd - >> DRM_ELD_VER_SHIFT; - - if (ver != ELD_VER_CEA_861D && ver != ELD_VER_PARTIAL) { -- dev_err(&hdev->dev, "HDMI: Unknown ELD version %d\n", ver); -+ dev_err_ratelimited(&hdev->dev, -+ "HDMI: Unknown ELD version %d\n", ver); - return -EINVAL; - } - -@@ -1240,7 +1241,8 @@ static int hdac_hdmi_parse_eld(struct hd - DRM_ELD_MNL_MASK) >> DRM_ELD_MNL_SHIFT; - - if (mnl > ELD_MAX_MNL) { -- dev_err(&hdev->dev, "HDMI: MNL Invalid %d\n", mnl); -+ dev_err_ratelimited(&hdev->dev, -+ "HDMI: MNL Invalid %d\n", mnl); - return -EINVAL; - } - -@@ -1299,8 +1301,8 @@ static void hdac_hdmi_present_sense(stru - - if (!port->eld.monitor_present || !port->eld.eld_valid) { - -- dev_err(&hdev->dev, "%s: disconnect for pin:port %d:%d\n", -- __func__, pin->nid, port->id); -+ dev_dbg(&hdev->dev, "%s: disconnect for pin:port %d:%d\n", -+ __func__, pin->nid, port->id); - - /* - * PCMs are not registered during device probe, so don't -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/codecs/lpass-tx-macro.c BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/lpass-tx-macro.c ---- BPI-Router-Linux-kernel/sound/soc/codecs/lpass-tx-macro.c 2025-10-22 13:53:23.675326923 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/lpass-tx-macro.c 2025-10-22 13:53:56.851167521 -0400 -@@ -2230,7 +2230,7 @@ static int tx_macro_register_mclk_output - } - - static const struct snd_soc_component_driver tx_macro_component_drv = { -- .name = "RX-MACRO", -+ .name = "TX-MACRO", - .probe = tx_macro_component_probe, - .controls = tx_macro_snd_controls, - .num_controls = ARRAY_SIZE(tx_macro_snd_controls), -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/codecs/rt1320-sdw.c BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/rt1320-sdw.c ---- BPI-Router-Linux-kernel/sound/soc/codecs/rt1320-sdw.c 2025-10-22 13:53:23.675326923 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/rt1320-sdw.c 2025-10-22 13:53:56.851167521 -0400 -@@ -109,6 +109,7 @@ static const struct reg_sequence rt1320_ - { 0x0000d540, 0x01 }, - { 0xd172, 0x2a }, - { 0xc5d6, 0x01 }, -+ { 0xd478, 0xff }, - }; - - static const struct reg_sequence rt1320_vc_blind_write[] = { -@@ -159,7 +160,7 @@ static const struct reg_sequence rt1320_ - { 0xd471, 0x3a }, - { 0xd474, 0x11 }, - { 0xd475, 0x32 }, -- { 0xd478, 0x64 }, -+ { 0xd478, 0xff }, - { 0xd479, 0x20 }, - { 0xd47a, 0x10 }, - { 0xd47c, 0xff }, -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/codecs/rt5640.c BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/rt5640.c ---- BPI-Router-Linux-kernel/sound/soc/codecs/rt5640.c 2025-10-22 13:53:23.675326923 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/rt5640.c 2025-10-22 13:53:56.851167521 -0400 -@@ -3014,6 +3014,11 @@ static int rt5640_i2c_probe(struct i2c_c - - regmap_read(rt5640->regmap, RT5640_VENDOR_ID2, &val); - if (val != RT5640_DEVICE_ID) { -+ usleep_range(60000, 100000); -+ regmap_read(rt5640->regmap, RT5640_VENDOR_ID2, &val); -+ } -+ -+ if (val != RT5640_DEVICE_ID) { - dev_err(&i2c->dev, - "Device with ID register %#x is not rt5640/39\n", val); - return -ENODEV; -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/codecs/rt5645.c BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/rt5645.c ---- BPI-Router-Linux-kernel/sound/soc/codecs/rt5645.c 2025-10-22 13:53:23.675326923 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/rt5645.c 2025-10-22 13:53:56.851167521 -0400 -@@ -82,6 +82,7 @@ static const struct reg_sequence rt5650_ - {0xf6, 0x0100}, - {RT5645_PWR_ANLG1, 0x02}, - {RT5645_IL_CMD3, 0x6728}, -+ {RT5645_PR_BASE + 0x3a, 0x0000}, - }; - - static const struct reg_default rt5645_reg[] = { -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/codecs/rt5660.c BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/rt5660.c ---- BPI-Router-Linux-kernel/sound/soc/codecs/rt5660.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/rt5660.c 2025-10-22 13:53:56.851167521 -0400 -@@ -1315,14 +1315,17 @@ static int rt5660_i2c_probe(struct i2c_c - regmap_update_bits(rt5660->regmap, RT5660_GPIO_CTRL1, - RT5660_GP1_PIN_MASK, RT5660_GP1_PIN_DMIC1_SCL); - -- if (rt5660->pdata.dmic1_data_pin == RT5660_DMIC1_DATA_GPIO2) -+ if (rt5660->pdata.dmic1_data_pin == RT5660_DMIC1_DATA_GPIO2) { - regmap_update_bits(rt5660->regmap, RT5660_DMIC_CTRL1, - RT5660_SEL_DMIC_DATA_MASK, - RT5660_SEL_DMIC_DATA_GPIO2); -- else if (rt5660->pdata.dmic1_data_pin == RT5660_DMIC1_DATA_IN1P) -+ regmap_update_bits(rt5660->regmap, RT5660_GPIO_CTRL1, -+ RT5660_GP2_PIN_MASK, RT5660_GP2_PIN_DMIC1_SDA); -+ } else if (rt5660->pdata.dmic1_data_pin == RT5660_DMIC1_DATA_IN1P) { - regmap_update_bits(rt5660->regmap, RT5660_DMIC_CTRL1, - RT5660_SEL_DMIC_DATA_MASK, - RT5660_SEL_DMIC_DATA_IN1P); -+ } - } - - return devm_snd_soc_register_component(&i2c->dev, -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/codecs/rt5682s.c BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/rt5682s.c ---- BPI-Router-Linux-kernel/sound/soc/codecs/rt5682s.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/rt5682s.c 2025-10-22 13:53:56.851167521 -0400 -@@ -653,14 +653,15 @@ static void rt5682s_sar_power_mode(struc - switch (mode) { - case SAR_PWR_SAVING: - snd_soc_component_update_bits(component, RT5682S_CBJ_CTRL_3, -- RT5682S_CBJ_IN_BUF_MASK, RT5682S_CBJ_IN_BUF_DIS); -+ RT5682S_CBJ_IN_BUF_MASK, RT5682S_CBJ_IN_BUF_EN); - snd_soc_component_update_bits(component, RT5682S_CBJ_CTRL_1, -- RT5682S_MB1_PATH_MASK | RT5682S_MB2_PATH_MASK, -- RT5682S_CTRL_MB1_REG | RT5682S_CTRL_MB2_REG); -+ RT5682S_MB1_PATH_MASK | RT5682S_MB2_PATH_MASK | -+ RT5682S_VREF_POW_MASK, RT5682S_CTRL_MB1_FSM | -+ RT5682S_CTRL_MB2_FSM | RT5682S_VREF_POW_FSM); - snd_soc_component_update_bits(component, RT5682S_SAR_IL_CMD_1, - RT5682S_SAR_BUTDET_MASK | RT5682S_SAR_BUTDET_POW_MASK | - RT5682S_SAR_SEL_MB1_2_CTL_MASK, RT5682S_SAR_BUTDET_DIS | -- RT5682S_SAR_BUTDET_POW_SAV | RT5682S_SAR_SEL_MB1_2_MANU); -+ RT5682S_SAR_BUTDET_POW_NORM | RT5682S_SAR_SEL_MB1_2_MANU); - usleep_range(5000, 5500); - snd_soc_component_update_bits(component, RT5682S_SAR_IL_CMD_1, - RT5682S_SAR_BUTDET_MASK, RT5682S_SAR_BUTDET_EN); -@@ -688,7 +689,7 @@ static void rt5682s_sar_power_mode(struc - snd_soc_component_update_bits(component, RT5682S_SAR_IL_CMD_1, - RT5682S_SAR_BUTDET_MASK | RT5682S_SAR_BUTDET_POW_MASK | - RT5682S_SAR_SEL_MB1_2_CTL_MASK, RT5682S_SAR_BUTDET_DIS | -- RT5682S_SAR_BUTDET_POW_SAV | RT5682S_SAR_SEL_MB1_2_MANU); -+ RT5682S_SAR_BUTDET_POW_NORM | RT5682S_SAR_SEL_MB1_2_MANU); - break; - default: - dev_err(component->dev, "Invalid SAR Power mode: %d\n", mode); -@@ -725,7 +726,7 @@ static void rt5682s_disable_push_button_ - snd_soc_component_update_bits(component, RT5682S_SAR_IL_CMD_1, - RT5682S_SAR_BUTDET_MASK | RT5682S_SAR_BUTDET_POW_MASK | - RT5682S_SAR_SEL_MB1_2_CTL_MASK, RT5682S_SAR_BUTDET_DIS | -- RT5682S_SAR_BUTDET_POW_SAV | RT5682S_SAR_SEL_MB1_2_MANU); -+ RT5682S_SAR_BUTDET_POW_NORM | RT5682S_SAR_SEL_MB1_2_MANU); - } - - /** -@@ -786,7 +787,7 @@ static int rt5682s_headset_detect(struct - jack_type = SND_JACK_HEADSET; - snd_soc_component_write(component, RT5682S_SAR_IL_CMD_3, 0x024c); - snd_soc_component_update_bits(component, RT5682S_CBJ_CTRL_1, -- RT5682S_FAST_OFF_MASK, RT5682S_FAST_OFF_EN); -+ RT5682S_FAST_OFF_MASK, RT5682S_FAST_OFF_DIS); - snd_soc_component_update_bits(component, RT5682S_SAR_IL_CMD_1, - RT5682S_SAR_SEL_MB1_2_MASK, val << RT5682S_SAR_SEL_MB1_2_SFT); - rt5682s_enable_push_button_irq(component); -@@ -966,7 +967,7 @@ static int rt5682s_set_jack_detect(struc - RT5682S_EMB_JD_MASK | RT5682S_DET_TYPE | - RT5682S_POL_FAST_OFF_MASK | RT5682S_MIC_CAP_MASK, - RT5682S_EMB_JD_EN | RT5682S_DET_TYPE | -- RT5682S_POL_FAST_OFF_HIGH | RT5682S_MIC_CAP_HS); -+ RT5682S_POL_FAST_OFF_LOW | RT5682S_MIC_CAP_HS); - regmap_update_bits(rt5682s->regmap, RT5682S_SAR_IL_CMD_1, - RT5682S_SAR_POW_MASK, RT5682S_SAR_POW_EN); - regmap_update_bits(rt5682s->regmap, RT5682S_GPIO_CTRL_1, -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/codecs/rt712-sdca.c BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/rt712-sdca.c ---- BPI-Router-Linux-kernel/sound/soc/codecs/rt712-sdca.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/rt712-sdca.c 2025-10-22 13:53:56.851167521 -0400 -@@ -1891,11 +1891,9 @@ int rt712_sdca_io_init(struct device *de - - rt712_sdca_va_io_init(rt712); - } else { -- if (!rt712->dmic_function_found) { -- dev_err(&slave->dev, "%s RT712 VB detected but no SMART_MIC function exposed in ACPI\n", -+ if (!rt712->dmic_function_found) -+ dev_warn(&slave->dev, "%s RT712 VB detected but no SMART_MIC function exposed in ACPI\n", - __func__); -- goto suspend; -- } - - /* multilanes and DMIC are supported by rt712vb */ - prop->lane_control_support = true; -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/codecs/rt721-sdca.c BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/rt721-sdca.c ---- BPI-Router-Linux-kernel/sound/soc/codecs/rt721-sdca.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/rt721-sdca.c 2025-10-22 13:53:56.851167521 -0400 -@@ -278,6 +278,8 @@ static void rt721_sdca_jack_preset(struc - RT721_ENT_FLOAT_CTL1, 0x4040); - rt_sdca_index_write(rt721->mbq_regmap, RT721_HDA_SDCA_FLOAT, - RT721_ENT_FLOAT_CTL4, 0x1201); -+ rt_sdca_index_write(rt721->mbq_regmap, RT721_BOOST_CTRL, -+ RT721_BST_4CH_TOP_GATING_CTRL1, 0x002a); - regmap_write(rt721->regmap, 0x2f58, 0x07); - } - -@@ -430,6 +432,7 @@ static int rt721_sdca_set_gain_get(struc - unsigned int read_l, read_r, ctl_l = 0, ctl_r = 0; - unsigned int adc_vol_flag = 0; - const unsigned int interval_offset = 0xc0; -+ const unsigned int tendA = 0x200; - const unsigned int tendB = 0xa00; - - if (strstr(ucontrol->id.name, "FU1E Capture Volume") || -@@ -439,9 +442,16 @@ static int rt721_sdca_set_gain_get(struc - regmap_read(rt721->mbq_regmap, mc->reg, &read_l); - regmap_read(rt721->mbq_regmap, mc->rreg, &read_r); - -- if (mc->shift == 8) /* boost gain */ -+ if (mc->shift == 8) { -+ /* boost gain */ - ctl_l = read_l / tendB; -- else { -+ } else if (mc->shift == 1) { -+ /* FU33 boost gain */ -+ if (read_l == 0x8000 || read_l == 0xfe00) -+ ctl_l = 0; -+ else -+ ctl_l = read_l / tendA + 1; -+ } else { - if (adc_vol_flag) - ctl_l = mc->max - (((0x1e00 - read_l) & 0xffff) / interval_offset); - else -@@ -449,9 +459,16 @@ static int rt721_sdca_set_gain_get(struc - } - - if (read_l != read_r) { -- if (mc->shift == 8) /* boost gain */ -+ if (mc->shift == 8) { -+ /* boost gain */ - ctl_r = read_r / tendB; -- else { /* ADC/DAC gain */ -+ } else if (mc->shift == 1) { -+ /* FU33 boost gain */ -+ if (read_r == 0x8000 || read_r == 0xfe00) -+ ctl_r = 0; -+ else -+ ctl_r = read_r / tendA + 1; -+ } else { /* ADC/DAC gain */ - if (adc_vol_flag) - ctl_r = mc->max - (((0x1e00 - read_r) & 0xffff) / interval_offset); - else -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/codecs/rt721-sdca.h BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/rt721-sdca.h ---- BPI-Router-Linux-kernel/sound/soc/codecs/rt721-sdca.h 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/rt721-sdca.h 2025-10-22 13:53:56.851167521 -0400 -@@ -56,6 +56,7 @@ struct rt721_sdca_dmic_kctrl_priv { - #define RT721_CBJ_CTRL 0x0a - #define RT721_CAP_PORT_CTRL 0x0c - #define RT721_CLASD_AMP_CTRL 0x0d -+#define RT721_BOOST_CTRL 0x0f - #define RT721_VENDOR_REG 0x20 - #define RT721_RC_CALIB_CTRL 0x40 - #define RT721_VENDOR_EQ_L 0x53 -@@ -93,6 +94,9 @@ struct rt721_sdca_dmic_kctrl_priv { - /* Index (NID:0dh) */ - #define RT721_CLASD_AMP_2CH_CAL 0x14 - -+/* Index (NID:0fh) */ -+#define RT721_BST_4CH_TOP_GATING_CTRL1 0x05 -+ - /* Index (NID:20h) */ - #define RT721_JD_PRODUCT_NUM 0x00 - #define RT721_ANALOG_BIAS_CTL3 0x04 -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/codecs/sma1307.c BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/sma1307.c ---- BPI-Router-Linux-kernel/sound/soc/codecs/sma1307.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/sma1307.c 2025-10-22 13:53:56.851167521 -0400 -@@ -1737,9 +1737,10 @@ static void sma1307_setting_loaded(struc - sma1307->set.checksum = data[sma1307->set.header_size - 2]; - sma1307->set.num_mode = data[sma1307->set.header_size - 1]; - num_mode = sma1307->set.num_mode; -- sma1307->set.header = devm_kzalloc(sma1307->dev, -- sma1307->set.header_size, -- GFP_KERNEL); -+ sma1307->set.header = devm_kmalloc_array(sma1307->dev, -+ sma1307->set.header_size, -+ sizeof(int), -+ GFP_KERNEL); - if (!sma1307->set.header) { - sma1307->set.status = false; - return; -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/codecs/wm8940.c BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/wm8940.c ---- BPI-Router-Linux-kernel/sound/soc/codecs/wm8940.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/wm8940.c 2025-10-22 13:53:56.851167521 -0400 -@@ -220,7 +220,7 @@ static const struct snd_kcontrol_new wm8 - SOC_SINGLE_TLV("Digital Capture Volume", WM8940_ADCVOL, - 0, 255, 0, wm8940_adc_tlv), - SOC_ENUM("Mic Bias Level", wm8940_mic_bias_level_enum), -- SOC_SINGLE_TLV("Capture Boost Volue", WM8940_ADCBOOST, -+ SOC_SINGLE_TLV("Capture Boost Volume", WM8940_ADCBOOST, - 8, 1, 0, wm8940_capture_boost_vol_tlv), - SOC_SINGLE_TLV("Speaker Playback Volume", WM8940_SPKVOL, - 0, 63, 0, wm8940_spk_vol_tlv), -@@ -693,7 +693,12 @@ static int wm8940_update_clocks(struct s - f = wm8940_get_mclkdiv(priv->mclk, fs256, &mclkdiv); - if (f != priv->mclk) { - /* The PLL performs best around 90MHz */ -- fpll = wm8940_get_mclkdiv(22500000, fs256, &mclkdiv); -+ if (fs256 % 8000) -+ f = 22579200; -+ else -+ f = 24576000; -+ -+ fpll = wm8940_get_mclkdiv(f, fs256, &mclkdiv); - } - - wm8940_set_dai_pll(dai, 0, 0, priv->mclk, fpll); -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/codecs/wm8974.c BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/wm8974.c ---- BPI-Router-Linux-kernel/sound/soc/codecs/wm8974.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/wm8974.c 2025-10-22 13:53:56.851167521 -0400 -@@ -419,10 +419,14 @@ static int wm8974_update_clocks(struct s - fs256 = 256 * priv->fs; - - f = wm8974_get_mclkdiv(priv->mclk, fs256, &mclkdiv); -- - if (f != priv->mclk) { - /* The PLL performs best around 90MHz */ -- fpll = wm8974_get_mclkdiv(22500000, fs256, &mclkdiv); -+ if (fs256 % 8000) -+ f = 22579200; -+ else -+ f = 24576000; -+ -+ fpll = wm8974_get_mclkdiv(f, fs256, &mclkdiv); - } - - wm8974_set_dai_pll(dai, 0, 0, priv->mclk, fpll); -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/codecs/wm_adsp.c BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/wm_adsp.c ---- BPI-Router-Linux-kernel/sound/soc/codecs/wm_adsp.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/wm_adsp.c 2025-10-22 13:53:56.851167521 -0400 -@@ -783,16 +783,19 @@ static int wm_adsp_request_firmware_file - char **coeff_filename) - { - const char *system_name = dsp->system_name; -- const char *asoc_component_prefix = dsp->component->name_prefix; -+ const char *suffix = dsp->component->name_prefix; - int ret = 0; - -- if (system_name && asoc_component_prefix) { -+ if (dsp->fwf_suffix) -+ suffix = dsp->fwf_suffix; -+ -+ if (system_name && suffix) { - if (!wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, - cirrus_dir, system_name, -- asoc_component_prefix, "wmfw")) { -+ suffix, "wmfw")) { - wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, - cirrus_dir, system_name, -- asoc_component_prefix, "bin"); -+ suffix, "bin"); - return 0; - } - } -@@ -801,10 +804,10 @@ static int wm_adsp_request_firmware_file - if (!wm_adsp_request_firmware_file(dsp, wmfw_firmware, wmfw_filename, - cirrus_dir, system_name, - NULL, "wmfw")) { -- if (asoc_component_prefix) -+ if (suffix) - wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, - cirrus_dir, system_name, -- asoc_component_prefix, "bin"); -+ suffix, "bin"); - - if (!*coeff_firmware) - wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, -@@ -816,10 +819,10 @@ static int wm_adsp_request_firmware_file - - /* Check system-specific bin without wmfw before falling back to generic */ - if (dsp->wmfw_optional && system_name) { -- if (asoc_component_prefix) -+ if (suffix) - wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, - cirrus_dir, system_name, -- asoc_component_prefix, "bin"); -+ suffix, "bin"); - - if (!*coeff_firmware) - wm_adsp_request_firmware_file(dsp, coeff_firmware, coeff_filename, -@@ -850,7 +853,7 @@ static int wm_adsp_request_firmware_file - adsp_err(dsp, "Failed to request firmware <%s>%s-%s-%s<-%s<%s>>.wmfw\n", - cirrus_dir, dsp->part, - dsp->fwf_name ? dsp->fwf_name : dsp->cs_dsp.name, -- wm_adsp_fw[dsp->fw].file, system_name, asoc_component_prefix); -+ wm_adsp_fw[dsp->fw].file, system_name, suffix); - - return -ENOENT; - } -@@ -997,11 +1000,17 @@ int wm_adsp_power_up(struct wm_adsp *dsp - return ret; - } - -+ if (dsp->bin_mandatory && !coeff_firmware) { -+ ret = -ENOENT; -+ goto err; -+ } -+ - ret = cs_dsp_power_up(&dsp->cs_dsp, - wmfw_firmware, wmfw_filename, - coeff_firmware, coeff_filename, - wm_adsp_fw_text[dsp->fw]); - -+err: - wm_adsp_release_firmware_files(dsp, - wmfw_firmware, wmfw_filename, - coeff_firmware, coeff_filename); -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/codecs/wm_adsp.h BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/wm_adsp.h ---- BPI-Router-Linux-kernel/sound/soc/codecs/wm_adsp.h 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/codecs/wm_adsp.h 2025-10-22 13:53:56.851167521 -0400 -@@ -29,12 +29,14 @@ struct wm_adsp { - const char *part; - const char *fwf_name; - const char *system_name; -+ const char *fwf_suffix; - struct snd_soc_component *component; - - unsigned int sys_config_size; - - int fw; - bool wmfw_optional; -+ bool bin_mandatory; - - struct work_struct boot_work; - int (*control_add)(struct wm_adsp *dsp, struct cs_dsp_coeff_ctl *cs_ctl); -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/fsl/fsl_asrc.c BPI-Router-Linux-kernel-6.16.12/sound/soc/fsl/fsl_asrc.c ---- BPI-Router-Linux-kernel/sound/soc/fsl/fsl_asrc.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/fsl/fsl_asrc.c 2025-10-22 13:53:56.851167521 -0400 -@@ -517,7 +517,8 @@ static int fsl_asrc_config_pair(struct f - regmap_update_bits(asrc->regmap, REG_ASRCTR, - ASRCTR_ATSi_MASK(index), ASRCTR_ATS(index)); - regmap_update_bits(asrc->regmap, REG_ASRCTR, -- ASRCTR_USRi_MASK(index), 0); -+ ASRCTR_IDRi_MASK(index) | ASRCTR_USRi_MASK(index), -+ ASRCTR_USR(index)); - - /* Set the input and output clock sources */ - regmap_update_bits(asrc->regmap, REG_ASRCSR, -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/fsl/fsl_sai.c BPI-Router-Linux-kernel-6.16.12/sound/soc/fsl/fsl_sai.c ---- BPI-Router-Linux-kernel/sound/soc/fsl/fsl_sai.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/fsl/fsl_sai.c 2025-10-22 13:53:56.851167521 -0400 -@@ -803,13 +803,15 @@ static void fsl_sai_config_disable(struc - * anymore. Add software reset to fix this issue. - * This is a hardware bug, and will be fix in the - * next sai version. -+ * -+ * In consumer mode, this can happen even after a -+ * single open/close, especially if both tx and rx -+ * are running concurrently. - */ -- if (!sai->is_consumer_mode[tx]) { -- /* Software Reset */ -- regmap_write(sai->regmap, FSL_SAI_xCSR(tx, ofs), FSL_SAI_CSR_SR); -- /* Clear SR bit to finish the reset */ -- regmap_write(sai->regmap, FSL_SAI_xCSR(tx, ofs), 0); -- } -+ /* Software Reset */ -+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), FSL_SAI_CSR_SR, FSL_SAI_CSR_SR); -+ /* Clear SR bit to finish the reset */ -+ regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), FSL_SAI_CSR_SR, 0); - } - - static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, -@@ -928,11 +930,11 @@ static int fsl_sai_dai_probe(struct snd_ - unsigned int ofs = sai->soc_data->reg_offset; - - /* Software Reset for both Tx and Rx */ -- regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR); -- regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR); -+ regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR, FSL_SAI_CSR_SR); -+ regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR, FSL_SAI_CSR_SR); - /* Clear SR bit to finish the reset */ -- regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0); -- regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0); -+ regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR, 0); -+ regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR, 0); - - regmap_update_bits(sai->regmap, FSL_SAI_TCR1(ofs), - FSL_SAI_CR1_RFW_MASK(sai->soc_data->fifo_depth), -@@ -1822,11 +1824,11 @@ static int fsl_sai_runtime_resume(struct - - regcache_cache_only(sai->regmap, false); - regcache_mark_dirty(sai->regmap); -- regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR); -- regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR); -+ regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR, FSL_SAI_CSR_SR); -+ regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR, FSL_SAI_CSR_SR); - usleep_range(1000, 2000); -- regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0); -- regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0); -+ regmap_update_bits(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR, 0); -+ regmap_update_bits(sai->regmap, FSL_SAI_RCSR(ofs), FSL_SAI_CSR_SR, 0); - - ret = regcache_sync(sai->regmap); - if (ret) -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/fsl/fsl_xcvr.c BPI-Router-Linux-kernel-6.16.12/sound/soc/fsl/fsl_xcvr.c ---- BPI-Router-Linux-kernel/sound/soc/fsl/fsl_xcvr.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/fsl/fsl_xcvr.c 2025-10-22 13:53:56.855167502 -0400 -@@ -1395,7 +1395,7 @@ static irqreturn_t irq0_isr(int irq, voi - if (isr & FSL_XCVR_IRQ_NEW_CS) { - dev_dbg(dev, "Received new CS block\n"); - isr_clr |= FSL_XCVR_IRQ_NEW_CS; -- if (!xcvr->soc_data->spdif_only) { -+ if (xcvr->soc_data->fw_name) { - /* Data RAM is 4KiB, last two pages: 8 and 9. Select page 8. */ - regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL, - FSL_XCVR_EXT_CTRL_PAGE_MASK, -@@ -1423,6 +1423,26 @@ static irqreturn_t irq0_isr(int irq, voi - /* clear CS control register */ - memset_io(reg_ctrl, 0, sizeof(val)); - } -+ } else { -+ regmap_read(xcvr->regmap, FSL_XCVR_RX_CS_DATA_0, -+ (u32 *)&xcvr->rx_iec958.status[0]); -+ regmap_read(xcvr->regmap, FSL_XCVR_RX_CS_DATA_1, -+ (u32 *)&xcvr->rx_iec958.status[4]); -+ regmap_read(xcvr->regmap, FSL_XCVR_RX_CS_DATA_2, -+ (u32 *)&xcvr->rx_iec958.status[8]); -+ regmap_read(xcvr->regmap, FSL_XCVR_RX_CS_DATA_3, -+ (u32 *)&xcvr->rx_iec958.status[12]); -+ regmap_read(xcvr->regmap, FSL_XCVR_RX_CS_DATA_4, -+ (u32 *)&xcvr->rx_iec958.status[16]); -+ regmap_read(xcvr->regmap, FSL_XCVR_RX_CS_DATA_5, -+ (u32 *)&xcvr->rx_iec958.status[20]); -+ for (i = 0; i < 6; i++) { -+ val = *(u32 *)(xcvr->rx_iec958.status + i * 4); -+ *(u32 *)(xcvr->rx_iec958.status + i * 4) = -+ bitrev32(val); -+ } -+ regmap_set_bits(xcvr->regmap, FSL_XCVR_RX_DPTH_CTRL, -+ FSL_XCVR_RX_DPTH_CTRL_CSA); - } - } - if (isr & FSL_XCVR_IRQ_NEW_UD) { -@@ -1497,6 +1517,7 @@ static const struct fsl_xcvr_soc_data fs - }; - - static const struct fsl_xcvr_soc_data fsl_xcvr_imx95_data = { -+ .fw_name = "imx/xcvr/xcvr-imx95.bin", - .spdif_only = true, - .use_phy = true, - .use_edma = true, -@@ -1786,7 +1807,7 @@ static int fsl_xcvr_runtime_resume(struc - } - } - -- if (xcvr->mode == FSL_XCVR_MODE_EARC) { -+ if (xcvr->soc_data->fw_name) { - ret = fsl_xcvr_load_firmware(xcvr); - if (ret) { - dev_err(dev, "failed to load firmware.\n"); -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/intel/avs/core.c BPI-Router-Linux-kernel-6.16.12/sound/soc/intel/avs/core.c ---- BPI-Router-Linux-kernel/sound/soc/intel/avs/core.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/intel/avs/core.c 2025-10-22 13:53:56.855167502 -0400 -@@ -446,6 +446,8 @@ static int avs_pci_probe(struct pci_dev - adev = devm_kzalloc(dev, sizeof(*adev), GFP_KERNEL); - if (!adev) - return -ENOMEM; -+ bus = &adev->base.core; -+ - ret = avs_bus_init(adev, pci, id); - if (ret < 0) { - dev_err(dev, "failed to init avs bus: %d\n", ret); -@@ -456,7 +458,6 @@ static int avs_pci_probe(struct pci_dev - if (ret < 0) - return ret; - -- bus = &adev->base.core; - bus->addr = pci_resource_start(pci, 0); - bus->remap_addr = pci_ioremap_bar(pci, 0); - if (!bus->remap_addr) { -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/intel/avs/pcm.c BPI-Router-Linux-kernel-6.16.12/sound/soc/intel/avs/pcm.c ---- BPI-Router-Linux-kernel/sound/soc/intel/avs/pcm.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/intel/avs/pcm.c 2025-10-22 13:53:56.855167502 -0400 -@@ -1570,11 +1570,13 @@ static void avs_component_hda_unregister - { - struct snd_soc_acpi_mach *mach; - struct snd_soc_dai *dai, *save; -+ struct avs_mach_pdata *pdata; - struct hda_codec *codec; - char name[32]; - - mach = dev_get_platdata(component->card->dev); -- codec = mach->pdata; -+ pdata = mach->pdata; -+ codec = pdata->codec; - snprintf(name, sizeof(name), "%s-cpu", dev_name(&codec->core.dev)); - - for_each_component_dais_safe(component, dai, save) { -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/intel/boards/Kconfig BPI-Router-Linux-kernel-6.16.12/sound/soc/intel/boards/Kconfig ---- BPI-Router-Linux-kernel/sound/soc/intel/boards/Kconfig 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/intel/boards/Kconfig 2025-10-22 13:53:56.855167502 -0400 -@@ -11,7 +11,7 @@ menuconfig SND_SOC_INTEL_MACH - kernel: saying N will just cause the configurator to skip all - the questions about Intel ASoC machine drivers. - --if SND_SOC_INTEL_MACH -+if SND_SOC_INTEL_MACH && (SND_SOC_SOF_INTEL_COMMON || !SND_SOC_SOF_INTEL_COMMON) - - config SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES - bool "Use more user friendly long card names" -@@ -42,6 +42,7 @@ config SND_SOC_INTEL_SOF_NUVOTON_COMMON - tristate - - config SND_SOC_INTEL_SOF_BOARD_HELPERS -+ select SND_SOC_ACPI_INTEL_MATCH - tristate - - if SND_SOC_INTEL_CATPT -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/intel/boards/sof_es8336.c BPI-Router-Linux-kernel-6.16.12/sound/soc/intel/boards/sof_es8336.c ---- BPI-Router-Linux-kernel/sound/soc/intel/boards/sof_es8336.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/intel/boards/sof_es8336.c 2025-10-22 13:53:56.855167502 -0400 -@@ -826,6 +826,16 @@ static const struct platform_device_id b - SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK | - SOF_ES8336_JD_INVERTED), - }, -+ { -+ .name = "ptl_es83x6_c1_h02", -+ .driver_data = (kernel_ulong_t)(SOF_ES8336_SSP_CODEC(1) | -+ SOF_NO_OF_HDMI_CAPTURE_SSP(2) | -+ SOF_HDMI_CAPTURE_1_SSP(0) | -+ SOF_HDMI_CAPTURE_2_SSP(2) | -+ SOF_SSP_HDMI_CAPTURE_PRESENT | -+ SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK | -+ SOF_ES8336_JD_INVERTED), -+ }, - { } - }; - MODULE_DEVICE_TABLE(platform, board_ids); -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/intel/boards/sof_rt5682.c BPI-Router-Linux-kernel-6.16.12/sound/soc/intel/boards/sof_rt5682.c ---- BPI-Router-Linux-kernel/sound/soc/intel/boards/sof_rt5682.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/intel/boards/sof_rt5682.c 2025-10-22 13:53:56.855167502 -0400 -@@ -892,6 +892,13 @@ static const struct platform_device_id b - SOF_SSP_PORT_BT_OFFLOAD(2) | - SOF_BT_OFFLOAD_PRESENT), - }, -+ { -+ .name = "ptl_rt5682_c1_h02", -+ .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | -+ SOF_SSP_PORT_CODEC(1) | -+ /* SSP 0 and SSP 2 are used for HDMI IN */ -+ SOF_SSP_MASK_HDMI_CAPTURE(0x5)), -+ }, - { } - }; - MODULE_DEVICE_TABLE(platform, board_ids); -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/intel/boards/sof_sdw.c BPI-Router-Linux-kernel-6.16.12/sound/soc/intel/boards/sof_sdw.c ---- BPI-Router-Linux-kernel/sound/soc/intel/boards/sof_sdw.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/intel/boards/sof_sdw.c 2025-10-22 13:53:56.855167502 -0400 -@@ -741,6 +741,14 @@ static const struct dmi_system_id sof_sd - }, - .driver_data = (void *)(SOC_SDW_CODEC_SPKR), - }, -+ { -+ .callback = sof_sdw_quirk_cb, -+ .matches = { -+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), -+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0CCC") -+ }, -+ .driver_data = (void *)(SOC_SDW_CODEC_SPKR), -+ }, - /* Pantherlake devices*/ - { - .callback = sof_sdw_quirk_cb, -@@ -783,6 +791,9 @@ static const struct dmi_system_id sof_sd - static const struct snd_pci_quirk sof_sdw_ssid_quirk_table[] = { - SND_PCI_QUIRK(0x1043, 0x1e13, "ASUS Zenbook S14", SOC_SDW_CODEC_MIC), - SND_PCI_QUIRK(0x1043, 0x1f43, "ASUS Zenbook S16", SOC_SDW_CODEC_MIC), -+ SND_PCI_QUIRK(0x17aa, 0x2347, "Lenovo P16", SOC_SDW_CODEC_MIC), -+ SND_PCI_QUIRK(0x17aa, 0x2348, "Lenovo P16", SOC_SDW_CODEC_MIC), -+ SND_PCI_QUIRK(0x17aa, 0x2349, "Lenovo P1", SOC_SDW_CODEC_MIC), - {} - }; - -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/intel/catpt/pcm.c BPI-Router-Linux-kernel-6.16.12/sound/soc/intel/catpt/pcm.c ---- BPI-Router-Linux-kernel/sound/soc/intel/catpt/pcm.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/intel/catpt/pcm.c 2025-10-22 13:53:56.855167502 -0400 -@@ -568,8 +568,9 @@ static const struct snd_pcm_hardware cat - SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, - .formats = SNDRV_PCM_FMTBIT_S16_LE | -- SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE, -+ .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_24 | -+ SNDRV_PCM_SUBFMTBIT_MSBITS_MAX, - .period_bytes_min = PAGE_SIZE, - .period_bytes_max = CATPT_BUFFER_MAX_SIZE / CATPT_PCM_PERIODS_MIN, - .periods_min = CATPT_PCM_PERIODS_MIN, -@@ -699,14 +700,18 @@ static struct snd_soc_dai_driver dai_dri - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_48000, -- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, -+ .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_24 | -+ SNDRV_PCM_SUBFMTBIT_MSBITS_MAX, - }, - .capture = { - .stream_name = "Analog Capture", - .channels_min = 2, - .channels_max = 4, - .rates = SNDRV_PCM_RATE_48000, -- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, -+ .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_24 | -+ SNDRV_PCM_SUBFMTBIT_MSBITS_MAX, - }, - }, - { -@@ -718,7 +723,9 @@ static struct snd_soc_dai_driver dai_dri - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, -- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, -+ .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_24 | -+ SNDRV_PCM_SUBFMTBIT_MSBITS_MAX, - }, - }, - { -@@ -730,7 +737,9 @@ static struct snd_soc_dai_driver dai_dri - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_192000, -- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, -+ .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_24 | -+ SNDRV_PCM_SUBFMTBIT_MSBITS_MAX, - }, - }, - { -@@ -742,7 +751,9 @@ static struct snd_soc_dai_driver dai_dri - .channels_min = 2, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_48000, -- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, -+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, -+ .subformats = SNDRV_PCM_SUBFMTBIT_MSBITS_24 | -+ SNDRV_PCM_SUBFMTBIT_MSBITS_MAX, - }, - }, - { -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/intel/common/soc-acpi-intel-arl-match.c BPI-Router-Linux-kernel-6.16.12/sound/soc/intel/common/soc-acpi-intel-arl-match.c ---- BPI-Router-Linux-kernel/sound/soc/intel/common/soc-acpi-intel-arl-match.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/intel/common/soc-acpi-intel-arl-match.c 2025-10-22 13:53:56.855167502 -0400 -@@ -238,6 +238,15 @@ static const struct snd_soc_acpi_adr_dev - } - }; - -+static const struct snd_soc_acpi_adr_device rt1316_3_single_adr[] = { -+ { -+ .adr = 0x000330025D131601ull, -+ .num_endpoints = 1, -+ .endpoints = &single_endpoint, -+ .name_prefix = "rt1316-1" -+ } -+}; -+ - static const struct snd_soc_acpi_adr_device rt1320_2_single_adr[] = { - { - .adr = 0x000230025D132001ull, -@@ -368,6 +377,20 @@ static const struct snd_soc_acpi_link_ad - {} - }; - -+static const struct snd_soc_acpi_link_adr arl_rt711_l0_rt1316_l3[] = { -+ { -+ .mask = BIT(0), -+ .num_adr = ARRAY_SIZE(rt711_sdca_0_adr), -+ .adr_d = rt711_sdca_0_adr, -+ }, -+ { -+ .mask = BIT(3), -+ .num_adr = ARRAY_SIZE(rt1316_3_single_adr), -+ .adr_d = rt1316_3_single_adr, -+ }, -+ {} -+}; -+ - static const struct snd_soc_acpi_link_adr arl_rt722_l0_rt1320_l2[] = { - { - .mask = BIT(0), -@@ -468,6 +491,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_in - .get_function_tplg_files = sof_sdw_get_tplg_files, - }, - { -+ .link_mask = BIT(2) | BIT(3), -+ .links = arl_cs42l43_l2_cs35l56_l3, -+ .drv_name = "sof_sdw", -+ .sof_tplg_filename = "sof-arl-cs42l43-l2-cs35l56-l3.tplg", -+ .get_function_tplg_files = sof_sdw_get_tplg_files, -+ }, -+ { - .link_mask = BIT(2), - .links = arl_cs42l43_l2, - .drv_name = "sof_sdw", -@@ -475,11 +505,10 @@ struct snd_soc_acpi_mach snd_soc_acpi_in - .get_function_tplg_files = sof_sdw_get_tplg_files, - }, - { -- .link_mask = BIT(2) | BIT(3), -- .links = arl_cs42l43_l2_cs35l56_l3, -+ .link_mask = BIT(0) | BIT(3), -+ .links = arl_rt711_l0_rt1316_l3, - .drv_name = "sof_sdw", -- .sof_tplg_filename = "sof-arl-cs42l43-l2-cs35l56-l3.tplg", -- .get_function_tplg_files = sof_sdw_get_tplg_files, -+ .sof_tplg_filename = "sof-arl-rt711-l0-rt1316-l3.tplg", - }, - { - .link_mask = 0x1, /* link0 required */ -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/intel/common/soc-acpi-intel-ptl-match.c BPI-Router-Linux-kernel-6.16.12/sound/soc/intel/common/soc-acpi-intel-ptl-match.c ---- BPI-Router-Linux-kernel/sound/soc/intel/common/soc-acpi-intel-ptl-match.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/intel/common/soc-acpi-intel-ptl-match.c 2025-10-22 13:53:56.855167502 -0400 -@@ -21,14 +21,46 @@ static const struct snd_soc_acpi_codecs - .codecs = {RT5682_ACPI_HID, RT5682S_ACPI_HID}, - }; - -+static const struct snd_soc_acpi_codecs ptl_essx_83x6 = { -+ .num_codecs = 3, -+ .codecs = { "ESSX8316", "ESSX8326", "ESSX8336"}, -+}; -+ -+static const struct snd_soc_acpi_codecs ptl_lt6911_hdmi = { -+ .num_codecs = 1, -+ .codecs = {"INTC10B0"} -+}; -+ - struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_machines[] = { - { - .comp_ids = &ptl_rt5682_rt5682s_hp, -+ .drv_name = "ptl_rt5682_c1_h02", -+ .machine_quirk = snd_soc_acpi_codec_list, -+ .quirk_data = &ptl_lt6911_hdmi, -+ .sof_tplg_filename = "sof-ptl-rt5682-ssp1-hdmi-ssp02.tplg", -+ }, -+ { -+ .comp_ids = &ptl_rt5682_rt5682s_hp, - .drv_name = "ptl_rt5682_def", - .sof_tplg_filename = "sof-ptl", /* the tplg suffix is added at run time */ - .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | - SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, - }, -+ { -+ .comp_ids = &ptl_essx_83x6, -+ .drv_name = "ptl_es83x6_c1_h02", -+ .machine_quirk = snd_soc_acpi_codec_list, -+ .quirk_data = &ptl_lt6911_hdmi, -+ .sof_tplg_filename = "sof-ptl-es83x6-ssp1-hdmi-ssp02.tplg", -+ }, -+ { -+ .comp_ids = &ptl_essx_83x6, -+ .drv_name = "sof-essx8336", -+ .sof_tplg_filename = "sof-ptl-es8336", /* the tplg suffix is added at run time */ -+ .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER | -+ SND_SOC_ACPI_TPLG_INTEL_SSP_MSB | -+ SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER, -+ }, - {}, - }; - EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_ptl_machines); -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/intel/common/sof-function-topology-lib.c BPI-Router-Linux-kernel-6.16.12/sound/soc/intel/common/sof-function-topology-lib.c ---- BPI-Router-Linux-kernel/sound/soc/intel/common/sof-function-topology-lib.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/intel/common/sof-function-topology-lib.c 2025-10-22 13:53:56.855167502 -0400 -@@ -73,7 +73,8 @@ int sof_sdw_get_tplg_files(struct snd_so - break; - default: - dev_warn(card->dev, -- "only -2ch and -4ch are supported for dmic\n"); -+ "unsupported number of dmics: %d\n", -+ mach_params.dmic_num); - continue; - } - tplg_dev = TPLG_DEVICE_INTEL_PCH_DMIC; -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/loongson/loongson_i2s.c BPI-Router-Linux-kernel-6.16.12/sound/soc/loongson/loongson_i2s.c ---- BPI-Router-Linux-kernel/sound/soc/loongson/loongson_i2s.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/loongson/loongson_i2s.c 2025-10-22 13:53:56.855167502 -0400 -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include - #include - #include -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/mediatek/common/mtk-afe-platform-driver.c BPI-Router-Linux-kernel-6.16.12/sound/soc/mediatek/common/mtk-afe-platform-driver.c ---- BPI-Router-Linux-kernel/sound/soc/mediatek/common/mtk-afe-platform-driver.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/mediatek/common/mtk-afe-platform-driver.c 2025-10-22 13:53:56.855167502 -0400 -@@ -120,7 +120,9 @@ int mtk_afe_pcm_new(struct snd_soc_compo - struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); - - size = afe->mtk_afe_hardware->buffer_bytes_max; -- snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, afe->dev, 0, size); -+ snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, afe->dev, -+ afe->preallocate_buffers ? size : 0, -+ size); - - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/mediatek/common/mtk-base-afe.h BPI-Router-Linux-kernel-6.16.12/sound/soc/mediatek/common/mtk-base-afe.h ---- BPI-Router-Linux-kernel/sound/soc/mediatek/common/mtk-base-afe.h 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/mediatek/common/mtk-base-afe.h 2025-10-22 13:53:56.855167502 -0400 -@@ -117,6 +117,7 @@ struct mtk_base_afe { - struct mtk_base_afe_irq *irqs; - int irqs_size; - int memif_32bit_supported; -+ bool preallocate_buffers; - - struct list_head sub_dais; - struct snd_soc_dai_driver *dai_drivers; -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/mediatek/common/mtk-soundcard-driver.c BPI-Router-Linux-kernel-6.16.12/sound/soc/mediatek/common/mtk-soundcard-driver.c ---- BPI-Router-Linux-kernel/sound/soc/mediatek/common/mtk-soundcard-driver.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/mediatek/common/mtk-soundcard-driver.c 2025-10-22 13:53:56.855167502 -0400 -@@ -262,9 +262,13 @@ int mtk_soundcard_common_probe(struct pl - soc_card_data->accdet = accdet_comp; - else - dev_err(&pdev->dev, "No sound component found from mediatek,accdet property\n"); -+ -+ put_device(&accdet_pdev->dev); - } else { - dev_err(&pdev->dev, "No device found from mediatek,accdet property\n"); - } -+ -+ of_node_put(accdet_node); - } - - platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0); -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c BPI-Router-Linux-kernel-6.16.12/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c ---- BPI-Router-Linux-kernel/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c 2025-10-22 13:53:56.855167502 -0400 -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -1070,6 +1071,12 @@ static int mt8173_afe_pcm_dev_probe(stru - - afe->dev = &pdev->dev; - -+ ret = of_reserved_mem_device_init(&pdev->dev); -+ if (ret) { -+ dev_info(&pdev->dev, "no reserved memory found, pre-allocating buffers instead\n"); -+ afe->preallocate_buffers = true; -+ } -+ - irq_id = platform_get_irq(pdev, 0); - if (irq_id <= 0) - return irq_id < 0 ? irq_id : -ENXIO; -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c BPI-Router-Linux-kernel-6.16.12/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c ---- BPI-Router-Linux-kernel/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c 2025-10-22 13:53:56.855167502 -0400 -@@ -6,10 +6,12 @@ - // Author: KaiChieh Chuang - - #include -+#include - #include - #include - #include - #include -+#include - #include - #include - -@@ -431,6 +433,9 @@ static const struct snd_soc_component_dr - .reg_ofs_base = AFE_##_id##_BASE, \ - .reg_ofs_cur = AFE_##_id##_CUR, \ - .reg_ofs_end = AFE_##_id##_END, \ -+ .reg_ofs_base_msb = AFE_##_id##_BASE_MSB, \ -+ .reg_ofs_cur_msb = AFE_##_id##_CUR_MSB, \ -+ .reg_ofs_end_msb = AFE_##_id##_END_MSB, \ - .fs_reg = (_fs_reg), \ - .fs_shift = _id##_MODE_SFT, \ - .fs_maskbit = _id##_MODE_MASK, \ -@@ -462,11 +467,17 @@ static const struct snd_soc_component_dr - #define AFE_VUL12_BASE AFE_VUL_D2_BASE - #define AFE_VUL12_CUR AFE_VUL_D2_CUR - #define AFE_VUL12_END AFE_VUL_D2_END -+#define AFE_VUL12_BASE_MSB AFE_VUL_D2_BASE_MSB -+#define AFE_VUL12_CUR_MSB AFE_VUL_D2_CUR_MSB -+#define AFE_VUL12_END_MSB AFE_VUL_D2_END_MSB - #define AWB2_HD_ALIGN_SFT AWB2_ALIGN_SFT - #define VUL12_DATA_SFT VUL12_MONO_SFT - #define AFE_HDMI_BASE AFE_HDMI_OUT_BASE - #define AFE_HDMI_CUR AFE_HDMI_OUT_CUR - #define AFE_HDMI_END AFE_HDMI_OUT_END -+#define AFE_HDMI_BASE_MSB AFE_HDMI_OUT_BASE_MSB -+#define AFE_HDMI_CUR_MSB AFE_HDMI_OUT_CUR_MSB -+#define AFE_HDMI_END_MSB AFE_HDMI_OUT_END_MSB - - static const struct mtk_base_memif_data memif_data[MT8183_MEMIF_NUM] = { - MT8183_MEMIF(DL1, AFE_DAC_CON1, AFE_DAC_CON1), -@@ -763,6 +774,10 @@ static int mt8183_afe_pcm_dev_probe(stru - struct reset_control *rstc; - int i, irq_id, ret; - -+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(34)); -+ if (ret) -+ return ret; -+ - afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL); - if (!afe) - return -ENOMEM; -@@ -777,6 +792,12 @@ static int mt8183_afe_pcm_dev_probe(stru - afe->dev = &pdev->dev; - dev = afe->dev; - -+ ret = of_reserved_mem_device_init(dev); -+ if (ret) { -+ dev_info(dev, "no reserved memory found, pre-allocating buffers instead\n"); -+ afe->preallocate_buffers = true; -+ } -+ - /* initial audio related clock */ - ret = mt8183_init_clock(afe); - if (ret) { -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c BPI-Router-Linux-kernel-6.16.12/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c ---- BPI-Router-Linux-kernel/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c 2025-10-22 13:53:56.855167502 -0400 -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -2835,6 +2836,12 @@ static int mt8186_afe_pcm_dev_probe(stru - afe_priv = afe->platform_priv; - afe->dev = &pdev->dev; - -+ ret = of_reserved_mem_device_init(dev); -+ if (ret) { -+ dev_info(dev, "no reserved memory found, pre-allocating buffers instead\n"); -+ afe->preallocate_buffers = true; -+ } -+ - afe->base_addr = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(afe->base_addr)) - return PTR_ERR(afe->base_addr); -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c BPI-Router-Linux-kernel-6.16.12/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c ---- BPI-Router-Linux-kernel/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c 2025-10-22 13:53:56.855167502 -0400 -@@ -12,6 +12,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -2179,6 +2180,12 @@ static int mt8192_afe_pcm_dev_probe(stru - - afe->dev = dev; - -+ ret = of_reserved_mem_device_init(dev); -+ if (ret) { -+ dev_info(dev, "no reserved memory found, pre-allocating buffers instead\n"); -+ afe->preallocate_buffers = true; -+ } -+ - /* init audio related clock */ - ret = mt8192_init_clock(afe); - if (ret) { -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c BPI-Router-Linux-kernel-6.16.12/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c ---- BPI-Router-Linux-kernel/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c 2025-10-22 13:53:23.679326904 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c 2025-10-22 13:53:56.855167502 -0400 -@@ -812,11 +812,10 @@ static const struct snd_soc_dapm_route m - static int mt8365_dai_i2s_set_priv(struct mtk_base_afe *afe) - { - int i, ret; -- struct mt8365_afe_private *afe_priv = afe->platform_priv; - - for (i = 0; i < DAI_I2S_NUM; i++) { - ret = mt8365_dai_set_priv(afe, mt8365_i2s_priv[i].id, -- sizeof(*afe_priv), -+ sizeof(mt8365_i2s_priv[i]), - &mt8365_i2s_priv[i]); - if (ret) - return ret; -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/qcom/Kconfig BPI-Router-Linux-kernel-6.16.12/sound/soc/qcom/Kconfig ---- BPI-Router-Linux-kernel/sound/soc/qcom/Kconfig 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/qcom/Kconfig 2025-10-22 13:53:56.855167502 -0400 -@@ -186,6 +186,7 @@ config SND_SOC_SM8250 - tristate "SoC Machine driver for SM8250 boards" - depends on QCOM_APR && SOUNDWIRE - depends on COMMON_CLK -+ depends on SND_SOC_QCOM_OFFLOAD_UTILS || !SND_SOC_QCOM_OFFLOAD_UTILS - select SND_SOC_QDSP6 - select SND_SOC_QCOM_COMMON - select SND_SOC_QCOM_SDW -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/qcom/lpass-platform.c BPI-Router-Linux-kernel-6.16.12/sound/soc/qcom/lpass-platform.c ---- BPI-Router-Linux-kernel/sound/soc/qcom/lpass-platform.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/qcom/lpass-platform.c 2025-10-22 13:53:56.855167502 -0400 -@@ -202,7 +202,6 @@ static int lpass_platform_pcmops_open(st - struct regmap *map; - unsigned int dai_id = cpu_dai->driver->id; - -- component->id = dai_id; - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; -@@ -1190,13 +1189,14 @@ static int lpass_platform_pcmops_suspend - { - struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); - struct regmap *map; -- unsigned int dai_id = component->id; - -- if (dai_id == LPASS_DP_RX) -+ if (drvdata->hdmi_port_enable) { - map = drvdata->hdmiif_map; -- else -- map = drvdata->lpaif_map; -+ regcache_cache_only(map, true); -+ regcache_mark_dirty(map); -+ } - -+ map = drvdata->lpaif_map; - regcache_cache_only(map, true); - regcache_mark_dirty(map); - -@@ -1207,14 +1207,19 @@ static int lpass_platform_pcmops_resume( - { - struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); - struct regmap *map; -- unsigned int dai_id = component->id; -+ int ret; - -- if (dai_id == LPASS_DP_RX) -+ if (drvdata->hdmi_port_enable) { - map = drvdata->hdmiif_map; -- else -- map = drvdata->lpaif_map; -+ regcache_cache_only(map, false); -+ ret = regcache_sync(map); -+ if (ret) -+ return ret; -+ } - -+ map = drvdata->lpaif_map; - regcache_cache_only(map, false); -+ - return regcache_sync(map); - } - -@@ -1224,7 +1229,9 @@ static int lpass_platform_copy(struct sn - unsigned long bytes) - { - struct snd_pcm_runtime *rt = substream->runtime; -- unsigned int dai_id = component->id; -+ struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(substream); -+ struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_runtime, 0); -+ unsigned int dai_id = cpu_dai->driver->id; - int ret = 0; - - void __iomem *dma_buf = (void __iomem *) (rt->dma_area + pos + -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/qcom/qdsp6/audioreach.c BPI-Router-Linux-kernel-6.16.12/sound/soc/qcom/qdsp6/audioreach.c ---- BPI-Router-Linux-kernel/sound/soc/qcom/qdsp6/audioreach.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/qcom/qdsp6/audioreach.c 2025-10-22 13:53:56.855167502 -0400 -@@ -971,6 +971,7 @@ static int audioreach_i2s_set_media_form - param_data->param_id = PARAM_ID_I2S_INTF_CFG; - param_data->param_size = ic_sz - APM_MODULE_PARAM_DATA_SIZE; - -+ intf_cfg->cfg.lpaif_type = module->hw_interface_type; - intf_cfg->cfg.intf_idx = module->hw_interface_idx; - intf_cfg->cfg.sd_line_idx = module->sd_line_idx; - -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c BPI-Router-Linux-kernel-6.16.12/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c ---- BPI-Router-Linux-kernel/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/qcom/qdsp6/q6apm-lpass-dais.c 2025-10-22 13:53:56.855167502 -0400 -@@ -213,8 +213,10 @@ static int q6apm_lpass_dai_prepare(struc - - return 0; - err: -- q6apm_graph_close(dai_data->graph[dai->id]); -- dai_data->graph[dai->id] = NULL; -+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { -+ q6apm_graph_close(dai_data->graph[dai->id]); -+ dai_data->graph[dai->id] = NULL; -+ } - return rc; - } - -@@ -260,6 +262,7 @@ static const struct snd_soc_dai_ops q6i2 - .shutdown = q6apm_lpass_dai_shutdown, - .set_channel_map = q6dma_set_channel_map, - .hw_params = q6dma_hw_params, -+ .set_fmt = q6i2s_set_fmt, - }; - - static const struct snd_soc_dai_ops q6hdmi_ops = { -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/qcom/qdsp6/topology.c BPI-Router-Linux-kernel-6.16.12/sound/soc/qcom/qdsp6/topology.c ---- BPI-Router-Linux-kernel/sound/soc/qcom/qdsp6/topology.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/qcom/qdsp6/topology.c 2025-10-22 13:53:56.855167502 -0400 -@@ -587,8 +587,8 @@ static int audioreach_widget_load_module - return PTR_ERR(cont); - - mod = audioreach_parse_common_tokens(apm, cont, &tplg_w->priv, w); -- if (IS_ERR(mod)) -- return PTR_ERR(mod); -+ if (IS_ERR_OR_NULL(mod)) -+ return mod ? PTR_ERR(mod) : -ENODEV; - - dobj = &w->dobj; - dobj->private = mod; -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/renesas/rcar/core.c BPI-Router-Linux-kernel-6.16.12/sound/soc/renesas/rcar/core.c ---- BPI-Router-Linux-kernel/sound/soc/renesas/rcar/core.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/renesas/rcar/core.c 2025-10-22 13:53:56.855167502 -0400 -@@ -597,7 +597,7 @@ int rsnd_dai_connect(struct rsnd_mod *mo - - dev_dbg(dev, "%s is connected to io (%s)\n", - rsnd_mod_name(mod), -- snd_pcm_direction_name(io->substream->stream)); -+ rsnd_io_is_play(io) ? "Playback" : "Capture"); - - return 0; - } -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/rockchip/rockchip_sai.c BPI-Router-Linux-kernel-6.16.12/sound/soc/rockchip/rockchip_sai.c ---- BPI-Router-Linux-kernel/sound/soc/rockchip/rockchip_sai.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/rockchip/rockchip_sai.c 2025-10-22 13:53:56.855167502 -0400 -@@ -378,19 +378,9 @@ static void rockchip_sai_xfer_start(stru - static void rockchip_sai_xfer_stop(struct rk_sai_dev *sai, int stream) - { - unsigned int msk = 0, val = 0, clr = 0; -- bool playback; -- bool capture; -- -- if (stream < 0) { -- playback = true; -- capture = true; -- } else if (stream == SNDRV_PCM_STREAM_PLAYBACK) { -- playback = true; -- capture = false; -- } else { -- playback = true; -- capture = false; -- } -+ bool capture = stream == SNDRV_PCM_STREAM_CAPTURE || stream < 0; -+ bool playback = stream == SNDRV_PCM_STREAM_PLAYBACK || stream < 0; -+ /* could be <= 0 but we don't want to depend on enum values */ - - if (playback) { - msk |= SAI_XFER_TXS_MASK; -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/sdca/sdca_asoc.c BPI-Router-Linux-kernel-6.16.12/sound/soc/sdca/sdca_asoc.c ---- BPI-Router-Linux-kernel/sound/soc/sdca/sdca_asoc.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/sdca/sdca_asoc.c 2025-10-22 13:53:56.855167502 -0400 -@@ -229,11 +229,11 @@ static int entity_early_parse_ge(struct - if (!control_name) - return -ENOMEM; - -- kctl = devm_kmalloc(dev, sizeof(*kctl), GFP_KERNEL); -+ kctl = devm_kzalloc(dev, sizeof(*kctl), GFP_KERNEL); - if (!kctl) - return -ENOMEM; - -- soc_enum = devm_kmalloc(dev, sizeof(*soc_enum), GFP_KERNEL); -+ soc_enum = devm_kzalloc(dev, sizeof(*soc_enum), GFP_KERNEL); - if (!soc_enum) - return -ENOMEM; - -@@ -397,6 +397,8 @@ static int entity_pde_event(struct snd_s - from = widget->off_val; - to = widget->on_val; - break; -+ default: -+ return 0; - } - - for (i = 0; i < entity->pde.num_max_delay; i++) { -@@ -558,11 +560,11 @@ static int entity_parse_su_class(struct - const char **texts; - int i; - -- kctl = devm_kmalloc(dev, sizeof(*kctl), GFP_KERNEL); -+ kctl = devm_kzalloc(dev, sizeof(*kctl), GFP_KERNEL); - if (!kctl) - return -ENOMEM; - -- soc_enum = devm_kmalloc(dev, sizeof(*soc_enum), GFP_KERNEL); -+ soc_enum = devm_kzalloc(dev, sizeof(*soc_enum), GFP_KERNEL); - if (!soc_enum) - return -ENOMEM; - -@@ -669,7 +671,7 @@ static int entity_parse_mu(struct device - if (!control_name) - return -ENOMEM; - -- mc = devm_kmalloc(dev, sizeof(*mc), GFP_KERNEL); -+ mc = devm_kzalloc(dev, sizeof(*mc), GFP_KERNEL); - if (!mc) - return -ENOMEM; - -@@ -923,7 +925,7 @@ static int populate_control(struct devic - if (!control_name) - return -ENOMEM; - -- mc = devm_kmalloc(dev, sizeof(*mc), GFP_KERNEL); -+ mc = devm_kzalloc(dev, sizeof(*mc), GFP_KERNEL); - if (!mc) - return -ENOMEM; - -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/sdca/sdca_device.c BPI-Router-Linux-kernel-6.16.12/sound/soc/sdca/sdca_device.c ---- BPI-Router-Linux-kernel/sound/soc/sdca/sdca_device.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/sdca/sdca_device.c 2025-10-22 13:53:56.855167502 -0400 -@@ -7,6 +7,7 @@ - */ - - #include -+#include - #include - #include - #include -@@ -55,11 +56,30 @@ static bool sdca_device_quirk_rt712_vb(s - return false; - } - -+static bool sdca_device_quirk_skip_func_type_patching(struct sdw_slave *slave) -+{ -+ const char *vendor, *sku; -+ -+ vendor = dmi_get_system_info(DMI_SYS_VENDOR); -+ sku = dmi_get_system_info(DMI_PRODUCT_SKU); -+ -+ if (vendor && sku && -+ !strcmp(vendor, "Dell Inc.") && -+ (!strcmp(sku, "0C62") || !strcmp(sku, "0C63") || !strcmp(sku, "0C6B")) && -+ slave->sdca_data.interface_revision == 0x061c && -+ slave->id.mfg_id == 0x01fa && slave->id.part_id == 0x4243) -+ return true; -+ -+ return false; -+} -+ - bool sdca_device_quirk_match(struct sdw_slave *slave, enum sdca_quirk quirk) - { - switch (quirk) { - case SDCA_QUIRKS_RT712_VB: - return sdca_device_quirk_rt712_vb(slave); -+ case SDCA_QUIRKS_SKIP_FUNC_TYPE_PATCHING: -+ return sdca_device_quirk_skip_func_type_patching(slave); - default: - break; - } -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/sdca/sdca_functions.c BPI-Router-Linux-kernel-6.16.12/sound/soc/sdca/sdca_functions.c ---- BPI-Router-Linux-kernel/sound/soc/sdca/sdca_functions.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/sdca/sdca_functions.c 2025-10-22 13:53:56.855167502 -0400 -@@ -89,6 +89,7 @@ static int find_sdca_function(struct acp - { - struct fwnode_handle *function_node = acpi_fwnode_handle(adev); - struct sdca_device_data *sdca_data = data; -+ struct sdw_slave *slave = container_of(sdca_data, struct sdw_slave, sdca_data); - struct device *dev = &adev->dev; - struct fwnode_handle *control5; /* used to identify function type */ - const char *function_name; -@@ -136,11 +137,13 @@ static int find_sdca_function(struct acp - return ret; - } - -- ret = patch_sdca_function_type(sdca_data->interface_revision, &function_type); -- if (ret < 0) { -- dev_err(dev, "SDCA version %#x invalid function type %d\n", -- sdca_data->interface_revision, function_type); -- return ret; -+ if (!sdca_device_quirk_match(slave, SDCA_QUIRKS_SKIP_FUNC_TYPE_PATCHING)) { -+ ret = patch_sdca_function_type(sdca_data->interface_revision, &function_type); -+ if (ret < 0) { -+ dev_err(dev, "SDCA version %#x invalid function type %d\n", -+ sdca_data->interface_revision, function_type); -+ return ret; -+ } - } - - function_name = get_sdca_function_name(function_type); -@@ -211,7 +214,7 @@ static int find_sdca_init_table(struct d - } else if (num_init_writes % sizeof(*raw) != 0) { - dev_err(dev, "%pfwP: init table size invalid\n", function_node); - return -EINVAL; -- } else if (num_init_writes > SDCA_MAX_INIT_COUNT) { -+ } else if ((num_init_writes / sizeof(*raw)) > SDCA_MAX_INIT_COUNT) { - dev_err(dev, "%pfwP: maximum init table size exceeded\n", function_node); - return -EINVAL; - } -@@ -880,7 +883,8 @@ static int find_sdca_entity_control(stru - control->value = tmp; - control->has_fixed = true; - } -- -+ fallthrough; -+ case SDCA_ACCESS_MODE_RO: - control->deferrable = fwnode_property_read_bool(control_node, - "mipi-sdca-control-deferrable"); - break; -@@ -911,6 +915,8 @@ static int find_sdca_entity_control(stru - &tmp); - if (!ret) - control->interrupt_position = tmp; -+ else -+ control->interrupt_position = SDCA_NO_INTERRUPT; - - control->label = find_sdca_control_label(dev, entity, control); - if (!control->label) -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/sdca/sdca_regmap.c BPI-Router-Linux-kernel-6.16.12/sound/soc/sdca/sdca_regmap.c ---- BPI-Router-Linux-kernel/sound/soc/sdca/sdca_regmap.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/sdca/sdca_regmap.c 2025-10-22 13:53:56.855167502 -0400 -@@ -72,12 +72,18 @@ bool sdca_regmap_readable(struct sdca_fu - if (!control) - return false; - -+ if (!(BIT(SDW_SDCA_CTL_CNUM(reg)) & control->cn_list)) -+ return false; -+ - switch (control->mode) { - case SDCA_ACCESS_MODE_RW: - case SDCA_ACCESS_MODE_RO: -- case SDCA_ACCESS_MODE_DUAL: - case SDCA_ACCESS_MODE_RW1S: - case SDCA_ACCESS_MODE_RW1C: -+ if (SDW_SDCA_NEXT_CTL(0) & reg) -+ return false; -+ fallthrough; -+ case SDCA_ACCESS_MODE_DUAL: - /* No access to registers marked solely for device use */ - return control->layers & ~SDCA_ACCESS_LAYER_DEVICE; - default: -@@ -104,11 +110,17 @@ bool sdca_regmap_writeable(struct sdca_f - if (!control) - return false; - -+ if (!(BIT(SDW_SDCA_CTL_CNUM(reg)) & control->cn_list)) -+ return false; -+ - switch (control->mode) { - case SDCA_ACCESS_MODE_RW: -- case SDCA_ACCESS_MODE_DUAL: - case SDCA_ACCESS_MODE_RW1S: - case SDCA_ACCESS_MODE_RW1C: -+ if (SDW_SDCA_NEXT_CTL(0) & reg) -+ return false; -+ fallthrough; -+ case SDCA_ACCESS_MODE_DUAL: - /* No access to registers marked solely for device use */ - return control->layers & ~SDCA_ACCESS_LAYER_DEVICE; - default: -@@ -184,7 +196,7 @@ int sdca_regmap_mbq_size(struct sdca_fun - - control = function_find_control(function, reg); - if (!control) -- return false; -+ return -EINVAL; - - return clamp_val(control->nbits / BITS_PER_BYTE, sizeof(u8), sizeof(u32)); - } -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/sdw_utils/soc_sdw_utils.c BPI-Router-Linux-kernel-6.16.12/sound/soc/sdw_utils/soc_sdw_utils.c ---- BPI-Router-Linux-kernel/sound/soc/sdw_utils/soc_sdw_utils.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/sdw_utils/soc_sdw_utils.c 2025-10-22 13:53:56.855167502 -0400 -@@ -1205,6 +1205,8 @@ static int is_sdca_endpoint_present(stru - int i; - - dlc = kzalloc(sizeof(*dlc), GFP_KERNEL); -+ if (!dlc) -+ return -ENOMEM; - - adr_end = &adr_dev->endpoints[end_index]; - dai_info = &codec_info->dais[adr_end->num]; -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/soc-core.c BPI-Router-Linux-kernel-6.16.12/sound/soc/soc-core.c ---- BPI-Router-Linux-kernel/sound/soc/soc-core.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/soc-core.c 2025-10-22 13:53:56.855167502 -0400 -@@ -375,8 +375,9 @@ struct snd_soc_component - for_each_component(component) { - if ((dev == component->dev) && - (!driver_name || -- (driver_name == component->driver->name) || -- (strcmp(component->driver->name, driver_name) == 0))) { -+ (component->driver->name && -+ ((component->driver->name == driver_name) || -+ (strcmp(component->driver->name, driver_name) == 0))))) { - found_component = component; - break; - } -@@ -1139,6 +1140,9 @@ sanity_check: - void snd_soc_remove_pcm_runtime(struct snd_soc_card *card, - struct snd_soc_pcm_runtime *rtd) - { -+ if (!rtd) -+ return; -+ - lockdep_assert_held(&client_mutex); - - /* -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/soc-dai.c BPI-Router-Linux-kernel-6.16.12/sound/soc/soc-dai.c ---- BPI-Router-Linux-kernel/sound/soc/soc-dai.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/soc-dai.c 2025-10-22 13:53:56.855167502 -0400 -@@ -259,13 +259,15 @@ int snd_soc_dai_set_tdm_slot(struct snd_ - &rx_mask, - }; - -- if (dai->driver->ops && -- dai->driver->ops->xlate_tdm_slot_mask) -- ret = dai->driver->ops->xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); -- else -- ret = snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); -- if (ret) -- goto err; -+ if (slots) { -+ if (dai->driver->ops && -+ dai->driver->ops->xlate_tdm_slot_mask) -+ ret = dai->driver->ops->xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); -+ else -+ ret = snd_soc_xlate_tdm_slot_mask(slots, &tx_mask, &rx_mask); -+ if (ret) -+ goto err; -+ } - - for_each_pcm_streams(stream) - snd_soc_dai_tdm_mask_set(dai, stream, *tdm_mask[stream]); -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/soc-dapm.c BPI-Router-Linux-kernel-6.16.12/sound/soc/soc-dapm.c ---- BPI-Router-Linux-kernel/sound/soc/soc-dapm.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/soc-dapm.c 2025-10-22 13:53:56.855167502 -0400 -@@ -739,6 +739,10 @@ static int snd_soc_dapm_set_bias_level(s - out: - trace_snd_soc_bias_level_done(dapm, level); - -+ /* success */ -+ if (ret == 0) -+ snd_soc_dapm_init_bias_level(dapm, level); -+ - return ret; - } - -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/soc-ops.c BPI-Router-Linux-kernel-6.16.12/sound/soc/soc-ops.c ---- BPI-Router-Linux-kernel/sound/soc/soc-ops.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/soc-ops.c 2025-10-22 13:53:56.855167502 -0400 -@@ -399,28 +399,32 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx); - static int snd_soc_clip_to_platform_max(struct snd_kcontrol *kctl) - { - struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; -- struct snd_ctl_elem_value uctl; -+ struct snd_ctl_elem_value *uctl; - int ret; - - if (!mc->platform_max) - return 0; - -- ret = kctl->get(kctl, &uctl); -+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); -+ if (!uctl) -+ return -ENOMEM; -+ -+ ret = kctl->get(kctl, uctl); - if (ret < 0) -- return ret; -+ goto out; - -- if (uctl.value.integer.value[0] > mc->platform_max) -- uctl.value.integer.value[0] = mc->platform_max; -+ if (uctl->value.integer.value[0] > mc->platform_max) -+ uctl->value.integer.value[0] = mc->platform_max; - - if (snd_soc_volsw_is_stereo(mc) && -- uctl.value.integer.value[1] > mc->platform_max) -- uctl.value.integer.value[1] = mc->platform_max; -+ uctl->value.integer.value[1] > mc->platform_max) -+ uctl->value.integer.value[1] = mc->platform_max; - -- ret = kctl->put(kctl, &uctl); -- if (ret < 0) -- return ret; -+ ret = kctl->put(kctl, uctl); - -- return 0; -+out: -+ kfree(uctl); -+ return ret; - } - - /** -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/sof/amd/acp-loader.c BPI-Router-Linux-kernel-6.16.12/sound/soc/sof/amd/acp-loader.c ---- BPI-Router-Linux-kernel/sound/soc/sof/amd/acp-loader.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/sof/amd/acp-loader.c 2025-10-22 13:53:56.855167502 -0400 -@@ -65,7 +65,7 @@ int acp_dsp_block_write(struct snd_sof_d - dma_size = page_count * ACP_PAGE_SIZE; - adata->bin_buf = dma_alloc_coherent(&pci->dev, dma_size, - &adata->sha_dma_addr, -- GFP_ATOMIC); -+ GFP_KERNEL); - if (!adata->bin_buf) - return -ENOMEM; - } -@@ -77,7 +77,7 @@ int acp_dsp_block_write(struct snd_sof_d - adata->data_buf = dma_alloc_coherent(&pci->dev, - ACP_DEFAULT_DRAM_LENGTH, - &adata->dma_addr, -- GFP_ATOMIC); -+ GFP_KERNEL); - if (!adata->data_buf) - return -ENOMEM; - } -@@ -90,7 +90,7 @@ int acp_dsp_block_write(struct snd_sof_d - adata->sram_data_buf = dma_alloc_coherent(&pci->dev, - ACP_DEFAULT_SRAM_LENGTH, - &adata->sram_dma_addr, -- GFP_ATOMIC); -+ GFP_KERNEL); - if (!adata->sram_data_buf) - return -ENOMEM; - } -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/sof/imx/imx8.c BPI-Router-Linux-kernel-6.16.12/sound/soc/sof/imx/imx8.c ---- BPI-Router-Linux-kernel/sound/soc/sof/imx/imx8.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/sof/imx/imx8.c 2025-10-22 13:53:56.855167502 -0400 -@@ -40,6 +40,19 @@ struct imx8m_chip_data { - struct reset_control *run_stall; - }; - -+static int imx8_shutdown(struct snd_sof_dev *sdev) -+{ -+ /* -+ * Force the DSP to stall. After the firmware image is loaded, -+ * the stall will be removed during run() by a matching -+ * imx_sc_pm_cpu_start() call. -+ */ -+ imx_sc_pm_cpu_start(get_chip_pdata(sdev), IMX_SC_R_DSP, false, -+ RESET_VECTOR_VADDR); -+ -+ return 0; -+} -+ - /* - * DSP control. - */ -@@ -281,11 +294,13 @@ static int imx8_ops_init(struct snd_sof_ - static const struct imx_chip_ops imx8_chip_ops = { - .probe = imx8_probe, - .core_kick = imx8_run, -+ .core_shutdown = imx8_shutdown, - }; - - static const struct imx_chip_ops imx8x_chip_ops = { - .probe = imx8_probe, - .core_kick = imx8x_run, -+ .core_shutdown = imx8_shutdown, - }; - - static const struct imx_chip_ops imx8m_chip_ops = { -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/sof/intel/hda.c BPI-Router-Linux-kernel-6.16.12/sound/soc/sof/intel/hda.c ---- BPI-Router-Linux-kernel/sound/soc/sof/intel/hda.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/sof/intel/hda.c 2025-10-22 13:53:56.859167483 -0400 -@@ -1257,11 +1257,11 @@ static int check_tplg_quirk_mask(struct - return 0; - } - --static char *remove_file_ext(const char *tplg_filename) -+static char *remove_file_ext(struct device *dev, const char *tplg_filename) - { - char *filename, *tmp; - -- filename = kstrdup(tplg_filename, GFP_KERNEL); -+ filename = devm_kstrdup(dev, tplg_filename, GFP_KERNEL); - if (!filename) - return NULL; - -@@ -1345,7 +1345,7 @@ struct snd_soc_acpi_mach *hda_machine_se - */ - if (!sof_pdata->tplg_filename) { - /* remove file extension if it exists */ -- tplg_filename = remove_file_ext(mach->sof_tplg_filename); -+ tplg_filename = remove_file_ext(sdev->dev, mach->sof_tplg_filename); - if (!tplg_filename) - return NULL; - -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/sof/intel/hda-stream.c BPI-Router-Linux-kernel-6.16.12/sound/soc/sof/intel/hda-stream.c ---- BPI-Router-Linux-kernel/sound/soc/sof/intel/hda-stream.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/sof/intel/hda-stream.c 2025-10-22 13:53:56.859167483 -0400 -@@ -890,7 +890,7 @@ int hda_dsp_stream_init(struct snd_sof_d - - if (num_capture >= SOF_HDA_CAPTURE_STREAMS) { - dev_err(sdev->dev, "error: too many capture streams %d\n", -- num_playback); -+ num_capture); - return -EINVAL; - } - -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/sof/intel/Kconfig BPI-Router-Linux-kernel-6.16.12/sound/soc/sof/intel/Kconfig ---- BPI-Router-Linux-kernel/sound/soc/sof/intel/Kconfig 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/sof/intel/Kconfig 2025-10-22 13:53:56.855167502 -0400 -@@ -266,9 +266,10 @@ config SND_SOC_SOF_METEORLAKE - - config SND_SOC_SOF_INTEL_LNL - tristate -+ select SOUNDWIRE_INTEL if SND_SOC_SOF_INTEL_SOUNDWIRE != n - select SND_SOC_SOF_HDA_GENERIC - select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE -- select SND_SOF_SOF_HDA_SDW_BPT if SND_SOC_SOF_INTEL_SOUNDWIRE -+ select SND_SOF_SOF_HDA_SDW_BPT if SND_SOC_SOF_INTEL_SOUNDWIRE != n - select SND_SOC_SOF_IPC4 - select SND_SOC_SOF_INTEL_MTL - -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/sof/intel/ptl.c BPI-Router-Linux-kernel-6.16.12/sound/soc/sof/intel/ptl.c ---- BPI-Router-Linux-kernel/sound/soc/sof/intel/ptl.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/sof/intel/ptl.c 2025-10-22 13:53:56.859167483 -0400 -@@ -117,6 +117,7 @@ const struct sof_intel_dsp_desc ptl_chip - .read_sdw_lcount = hda_sdw_check_lcount_ext, - .check_sdw_irq = lnl_dsp_check_sdw_irq, - .check_sdw_wakeen_irq = lnl_sdw_check_wakeen_irq, -+ .sdw_process_wakeen = hda_sdw_process_wakeen_common, - .check_ipc_irq = mtl_dsp_check_ipc_irq, - .check_mic_privacy_irq = sof_ptl_check_mic_privacy_irq, - .process_mic_privacy = sof_ptl_process_mic_privacy, -@@ -142,6 +143,7 @@ const struct sof_intel_dsp_desc wcl_chip - .read_sdw_lcount = hda_sdw_check_lcount_ext, - .check_sdw_irq = lnl_dsp_check_sdw_irq, - .check_sdw_wakeen_irq = lnl_sdw_check_wakeen_irq, -+ .sdw_process_wakeen = hda_sdw_process_wakeen_common, - .check_ipc_irq = mtl_dsp_check_ipc_irq, - .cl_init = mtl_dsp_cl_init, - .power_down_dsp = mtl_power_down_dsp, -diff -purNx .git BPI-Router-Linux-kernel/sound/soc/sof/topology.c BPI-Router-Linux-kernel-6.16.12/sound/soc/sof/topology.c ---- BPI-Router-Linux-kernel/sound/soc/sof/topology.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/soc/sof/topology.c 2025-10-22 13:53:56.859167483 -0400 -@@ -2378,14 +2378,25 @@ static int sof_dspless_widget_ready(stru - struct snd_soc_dapm_widget *w, - struct snd_soc_tplg_dapm_widget *tw) - { -+ struct snd_soc_tplg_private *priv = &tw->priv; -+ int ret; -+ -+ /* for snd_soc_dapm_widget.no_wname_in_kcontrol_name */ -+ ret = sof_parse_tokens(scomp, w, dapm_widget_tokens, -+ ARRAY_SIZE(dapm_widget_tokens), -+ priv->array, le32_to_cpu(priv->size)); -+ if (ret < 0) { -+ dev_err(scomp->dev, "failed to parse dapm widget tokens for %s\n", -+ w->name); -+ return ret; -+ } -+ - if (WIDGET_IS_DAI(w->id)) { - static const struct sof_topology_token dai_tokens[] = { - {SOF_TKN_DAI_TYPE, SND_SOC_TPLG_TUPLE_TYPE_STRING, get_token_dai_type, 0}}; - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); -- struct snd_soc_tplg_private *priv = &tw->priv; - struct snd_sof_widget *swidget; - struct snd_sof_dai *sdai; -- int ret; - - swidget = kzalloc(sizeof(*swidget), GFP_KERNEL); - if (!swidget) -diff -purNx .git BPI-Router-Linux-kernel/sound/usb/format.c BPI-Router-Linux-kernel-6.16.12/sound/usb/format.c ---- BPI-Router-Linux-kernel/sound/usb/format.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/usb/format.c 2025-10-22 13:53:56.859167483 -0400 -@@ -310,16 +310,14 @@ static bool focusrite_valid_sample_rate( - struct audioformat *fp, - unsigned int rate) - { -- struct usb_interface *iface; - struct usb_host_interface *alts; - unsigned char *fmt; - unsigned int max_rate; - -- iface = usb_ifnum_to_if(chip->dev, fp->iface); -- if (!iface) -+ alts = snd_usb_get_host_interface(chip, fp->iface, fp->altsetting); -+ if (!alts) - return true; - -- alts = &iface->altsetting[fp->altset_idx]; - fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, - NULL, UAC_FORMAT_TYPE); - if (!fmt) -@@ -328,20 +326,24 @@ static bool focusrite_valid_sample_rate( - if (fmt[0] == 10) { /* bLength */ - max_rate = combine_quad(&fmt[6]); - -- /* Validate max rate */ -- if (max_rate != 48000 && -- max_rate != 96000 && -- max_rate != 192000 && -- max_rate != 384000) { -- -+ switch (max_rate) { -+ case 192000: -+ if (rate == 176400 || rate == 192000) -+ return true; -+ fallthrough; -+ case 96000: -+ if (rate == 88200 || rate == 96000) -+ return true; -+ fallthrough; -+ case 48000: -+ return (rate == 44100 || rate == 48000); -+ default: - usb_audio_info(chip, - "%u:%d : unexpected max rate: %u\n", - fp->iface, fp->altsetting, max_rate); - - return true; - } -- -- return rate <= max_rate; - } - - return true; -diff -purNx .git BPI-Router-Linux-kernel/sound/usb/midi.c BPI-Router-Linux-kernel-6.16.12/sound/usb/midi.c ---- BPI-Router-Linux-kernel/sound/usb/midi.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/usb/midi.c 2025-10-22 13:53:56.859167483 -0400 -@@ -1522,15 +1522,14 @@ static void snd_usbmidi_free(struct snd_ - { - int i; - -+ if (!umidi->disconnected) -+ snd_usbmidi_disconnect(&umidi->list); -+ - for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { - struct snd_usb_midi_endpoint *ep = &umidi->endpoints[i]; -- if (ep->out) -- snd_usbmidi_out_endpoint_delete(ep->out); -- if (ep->in) -- snd_usbmidi_in_endpoint_delete(ep->in); -+ kfree(ep->out); - } - mutex_destroy(&umidi->mutex); -- timer_shutdown_sync(&umidi->error_timer); - kfree(umidi); - } - -diff -purNx .git BPI-Router-Linux-kernel/sound/usb/mixer_maps.c BPI-Router-Linux-kernel-6.16.12/sound/usb/mixer_maps.c ---- BPI-Router-Linux-kernel/sound/usb/mixer_maps.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/usb/mixer_maps.c 2025-10-22 13:53:56.859167483 -0400 -@@ -383,6 +383,13 @@ static const struct usbmix_name_map ms_u - { 0 } /* terminator */ - }; - -+/* KTMicro USB */ -+static struct usbmix_name_map s31b2_0022_map[] = { -+ { 23, "Speaker Playback" }, -+ { 18, "Headphone Playback" }, -+ { 0 } -+}; -+ - /* ASUS ROG Zenith II with Realtek ALC1220-VB */ - static const struct usbmix_name_map asus_zenith_ii_map[] = { - { 19, NULL, 12 }, /* FU, Input Gain Pad - broken response, disabled */ -@@ -692,6 +699,11 @@ static const struct usbmix_ctl_map usbmi - .id = USB_ID(0x045e, 0x083c), - .map = ms_usb_link_map, - }, -+ { -+ /* KTMicro USB */ -+ .id = USB_ID(0X31b2, 0x0022), -+ .map = s31b2_0022_map, -+ }, - { 0 } /* terminator */ - }; - -diff -purNx .git BPI-Router-Linux-kernel/sound/usb/mixer_quirks.c BPI-Router-Linux-kernel-6.16.12/sound/usb/mixer_quirks.c ---- BPI-Router-Linux-kernel/sound/usb/mixer_quirks.c 2025-10-22 13:53:23.683326885 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/usb/mixer_quirks.c 2025-10-22 13:53:56.859167483 -0400 -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -55,13 +56,13 @@ struct std_mono_table { - * version, we keep it mono for simplicity. - */ - static int snd_create_std_mono_ctl_offset(struct usb_mixer_interface *mixer, -- unsigned int unitid, -- unsigned int control, -- unsigned int cmask, -- int val_type, -- unsigned int idx_off, -- const char *name, -- snd_kcontrol_tlv_rw_t *tlv_callback) -+ unsigned int unitid, -+ unsigned int control, -+ unsigned int cmask, -+ int val_type, -+ unsigned int idx_off, -+ const char *name, -+ snd_kcontrol_tlv_rw_t *tlv_callback) - { - struct usb_mixer_elem_info *cval; - struct snd_kcontrol *kctl; -@@ -78,7 +79,8 @@ static int snd_create_std_mono_ctl_offse - cval->idx_off = idx_off; - - /* get_min_max() is called only for integer volumes later, -- * so provide a short-cut for booleans */ -+ * so provide a short-cut for booleans -+ */ - cval->min = 0; - cval->max = 1; - cval->res = 0; -@@ -108,15 +110,16 @@ static int snd_create_std_mono_ctl_offse - } - - static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer, -- unsigned int unitid, -- unsigned int control, -- unsigned int cmask, -- int val_type, -- const char *name, -- snd_kcontrol_tlv_rw_t *tlv_callback) -+ unsigned int unitid, -+ unsigned int control, -+ unsigned int cmask, -+ int val_type, -+ const char *name, -+ snd_kcontrol_tlv_rw_t *tlv_callback) - { - return snd_create_std_mono_ctl_offset(mixer, unitid, control, cmask, -- val_type, 0 /* Offset */, name, tlv_callback); -+ val_type, 0 /* Offset */, -+ name, tlv_callback); - } - - /* -@@ -127,9 +130,10 @@ static int snd_create_std_mono_table(str - { - int err; - -- while (t->name != NULL) { -+ while (t->name) { - err = snd_create_std_mono_ctl(mixer, t->unitid, t->control, -- t->cmask, t->val_type, t->name, t->tlv_callback); -+ t->cmask, t->val_type, t->name, -+ t->tlv_callback); - if (err < 0) - return err; - t++; -@@ -209,12 +213,11 @@ static void snd_usb_soundblaster_remote_ - if (code == rc->mute_code) - snd_usb_mixer_notify_id(mixer, rc->mute_mixer_id); - mixer->rc_code = code; -- wmb(); - wake_up(&mixer->rc_waitq); - } - - static long snd_usb_sbrc_hwdep_read(struct snd_hwdep *hw, char __user *buf, -- long count, loff_t *offset) -+ long count, loff_t *offset) - { - struct usb_mixer_interface *mixer = hw->private_data; - int err; -@@ -234,7 +237,7 @@ static long snd_usb_sbrc_hwdep_read(stru - } - - static __poll_t snd_usb_sbrc_hwdep_poll(struct snd_hwdep *hw, struct file *file, -- poll_table *wait) -+ poll_table *wait) - { - struct usb_mixer_interface *mixer = hw->private_data; - -@@ -285,7 +288,7 @@ static int snd_usb_soundblaster_remote_i - mixer->rc_setup_packet->wLength = cpu_to_le16(len); - usb_fill_control_urb(mixer->rc_urb, mixer->chip->dev, - usb_rcvctrlpipe(mixer->chip->dev, 0), -- (u8*)mixer->rc_setup_packet, mixer->rc_buffer, len, -+ (u8 *)mixer->rc_setup_packet, mixer->rc_buffer, len, - snd_usb_soundblaster_remote_complete, mixer); - return 0; - } -@@ -310,20 +313,20 @@ static int snd_audigy2nx_led_update(stru - - if (chip->usb_id == USB_ID(0x041e, 0x3042)) - err = snd_usb_ctl_msg(chip->dev, -- usb_sndctrlpipe(chip->dev, 0), 0x24, -- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, -- !value, 0, NULL, 0); -+ usb_sndctrlpipe(chip->dev, 0), 0x24, -+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, -+ !value, 0, NULL, 0); - /* USB X-Fi S51 Pro */ - if (chip->usb_id == USB_ID(0x041e, 0x30df)) - err = snd_usb_ctl_msg(chip->dev, -- usb_sndctrlpipe(chip->dev, 0), 0x24, -- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, -- !value, 0, NULL, 0); -+ usb_sndctrlpipe(chip->dev, 0), 0x24, -+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, -+ !value, 0, NULL, 0); - else - err = snd_usb_ctl_msg(chip->dev, -- usb_sndctrlpipe(chip->dev, 0), 0x24, -- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, -- value, index + 2, NULL, 0); -+ usb_sndctrlpipe(chip->dev, 0), 0x24, -+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, -+ value, index + 2, NULL, 0); - snd_usb_unlock_shutdown(chip); - return err; - } -@@ -377,17 +380,17 @@ static int snd_audigy2nx_controls_create - struct snd_kcontrol_new knew; - - /* USB X-Fi S51 doesn't have a CMSS LED */ -- if ((mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) && i == 0) -+ if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042) && i == 0) - continue; - /* USB X-Fi S51 Pro doesn't have one either */ -- if ((mixer->chip->usb_id == USB_ID(0x041e, 0x30df)) && i == 0) -+ if (mixer->chip->usb_id == USB_ID(0x041e, 0x30df) && i == 0) - continue; - if (i > 1 && /* Live24ext has 2 LEDs only */ - (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || - mixer->chip->usb_id == USB_ID(0x041e, 0x3042) || - mixer->chip->usb_id == USB_ID(0x041e, 0x30df) || - mixer->chip->usb_id == USB_ID(0x041e, 0x3048))) -- break; -+ break; - - knew = snd_audigy2nx_control; - knew.name = snd_audigy2nx_led_names[i]; -@@ -481,9 +484,9 @@ static int snd_emu0204_ch_switch_update( - buf[0] = 0x01; - buf[1] = value ? 0x02 : 0x01; - err = snd_usb_ctl_msg(chip->dev, -- usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR, -- USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, -- 0x0400, 0x0e00, buf, 2); -+ usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR, -+ USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, -+ 0x0400, 0x0e00, buf, 2); - snd_usb_unlock_shutdown(chip); - return err; - } -@@ -529,6 +532,265 @@ static int snd_emu0204_controls_create(s - &snd_emu0204_control, NULL); - } - -+#if IS_REACHABLE(CONFIG_INPUT) -+/* -+ * Sony DualSense controller (PS5) jack detection -+ * -+ * Since this is an UAC 1 device, it doesn't support jack detection. -+ * However, the controller hid-playstation driver reports HP & MIC -+ * insert events through a dedicated input device. -+ */ -+ -+#define SND_DUALSENSE_JACK_OUT_TERM_ID 3 -+#define SND_DUALSENSE_JACK_IN_TERM_ID 4 -+ -+struct dualsense_mixer_elem_info { -+ struct usb_mixer_elem_info info; -+ struct input_handler ih; -+ struct input_device_id id_table[2]; -+ bool connected; -+}; -+ -+static void snd_dualsense_ih_event(struct input_handle *handle, -+ unsigned int type, unsigned int code, -+ int value) -+{ -+ struct dualsense_mixer_elem_info *mei; -+ struct usb_mixer_elem_list *me; -+ -+ if (type != EV_SW) -+ return; -+ -+ mei = container_of(handle->handler, struct dualsense_mixer_elem_info, ih); -+ me = &mei->info.head; -+ -+ if ((me->id == SND_DUALSENSE_JACK_OUT_TERM_ID && code == SW_HEADPHONE_INSERT) || -+ (me->id == SND_DUALSENSE_JACK_IN_TERM_ID && code == SW_MICROPHONE_INSERT)) { -+ mei->connected = !!value; -+ snd_ctl_notify(me->mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, -+ &me->kctl->id); -+ } -+} -+ -+static bool snd_dualsense_ih_match(struct input_handler *handler, -+ struct input_dev *dev) -+{ -+ struct dualsense_mixer_elem_info *mei; -+ struct usb_device *snd_dev; -+ char *input_dev_path, *usb_dev_path; -+ size_t usb_dev_path_len; -+ bool match = false; -+ -+ mei = container_of(handler, struct dualsense_mixer_elem_info, ih); -+ snd_dev = mei->info.head.mixer->chip->dev; -+ -+ input_dev_path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); -+ if (!input_dev_path) { -+ dev_warn(&snd_dev->dev, "Failed to get input dev path\n"); -+ return false; -+ } -+ -+ usb_dev_path = kobject_get_path(&snd_dev->dev.kobj, GFP_KERNEL); -+ if (!usb_dev_path) { -+ dev_warn(&snd_dev->dev, "Failed to get USB dev path\n"); -+ goto free_paths; -+ } -+ -+ /* -+ * Ensure the VID:PID matched input device supposedly owned by the -+ * hid-playstation driver belongs to the actual hardware handled by -+ * the current USB audio device, which implies input_dev_path being -+ * a subpath of usb_dev_path. -+ * -+ * This verification is necessary when there is more than one identical -+ * controller attached to the host system. -+ */ -+ usb_dev_path_len = strlen(usb_dev_path); -+ if (usb_dev_path_len >= strlen(input_dev_path)) -+ goto free_paths; -+ -+ usb_dev_path[usb_dev_path_len] = '/'; -+ match = !memcmp(input_dev_path, usb_dev_path, usb_dev_path_len + 1); -+ -+free_paths: -+ kfree(input_dev_path); -+ kfree(usb_dev_path); -+ -+ return match; -+} -+ -+static int snd_dualsense_ih_connect(struct input_handler *handler, -+ struct input_dev *dev, -+ const struct input_device_id *id) -+{ -+ struct input_handle *handle; -+ int err; -+ -+ handle = kzalloc(sizeof(*handle), GFP_KERNEL); -+ if (!handle) -+ return -ENOMEM; -+ -+ handle->dev = dev; -+ handle->handler = handler; -+ handle->name = handler->name; -+ -+ err = input_register_handle(handle); -+ if (err) -+ goto err_free; -+ -+ err = input_open_device(handle); -+ if (err) -+ goto err_unregister; -+ -+ return 0; -+ -+err_unregister: -+ input_unregister_handle(handle); -+err_free: -+ kfree(handle); -+ return err; -+} -+ -+static void snd_dualsense_ih_disconnect(struct input_handle *handle) -+{ -+ input_close_device(handle); -+ input_unregister_handle(handle); -+ kfree(handle); -+} -+ -+static void snd_dualsense_ih_start(struct input_handle *handle) -+{ -+ struct dualsense_mixer_elem_info *mei; -+ struct usb_mixer_elem_list *me; -+ int status = -1; -+ -+ mei = container_of(handle->handler, struct dualsense_mixer_elem_info, ih); -+ me = &mei->info.head; -+ -+ if (me->id == SND_DUALSENSE_JACK_OUT_TERM_ID && -+ test_bit(SW_HEADPHONE_INSERT, handle->dev->swbit)) -+ status = test_bit(SW_HEADPHONE_INSERT, handle->dev->sw); -+ else if (me->id == SND_DUALSENSE_JACK_IN_TERM_ID && -+ test_bit(SW_MICROPHONE_INSERT, handle->dev->swbit)) -+ status = test_bit(SW_MICROPHONE_INSERT, handle->dev->sw); -+ -+ if (status >= 0) { -+ mei->connected = !!status; -+ snd_ctl_notify(me->mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, -+ &me->kctl->id); -+ } -+} -+ -+static int snd_dualsense_jack_get(struct snd_kcontrol *kctl, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct dualsense_mixer_elem_info *mei = snd_kcontrol_chip(kctl); -+ -+ ucontrol->value.integer.value[0] = mei->connected; -+ -+ return 0; -+} -+ -+static const struct snd_kcontrol_new snd_dualsense_jack_control = { -+ .iface = SNDRV_CTL_ELEM_IFACE_CARD, -+ .access = SNDRV_CTL_ELEM_ACCESS_READ, -+ .info = snd_ctl_boolean_mono_info, -+ .get = snd_dualsense_jack_get, -+}; -+ -+static int snd_dualsense_resume_jack(struct usb_mixer_elem_list *list) -+{ -+ snd_ctl_notify(list->mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, -+ &list->kctl->id); -+ return 0; -+} -+ -+static void snd_dualsense_mixer_elem_free(struct snd_kcontrol *kctl) -+{ -+ struct dualsense_mixer_elem_info *mei = snd_kcontrol_chip(kctl); -+ -+ if (mei->ih.event) -+ input_unregister_handler(&mei->ih); -+ -+ snd_usb_mixer_elem_free(kctl); -+} -+ -+static int snd_dualsense_jack_create(struct usb_mixer_interface *mixer, -+ const char *name, bool is_output) -+{ -+ struct dualsense_mixer_elem_info *mei; -+ struct input_device_id *idev_id; -+ struct snd_kcontrol *kctl; -+ int err; -+ -+ mei = kzalloc(sizeof(*mei), GFP_KERNEL); -+ if (!mei) -+ return -ENOMEM; -+ -+ snd_usb_mixer_elem_init_std(&mei->info.head, mixer, -+ is_output ? SND_DUALSENSE_JACK_OUT_TERM_ID : -+ SND_DUALSENSE_JACK_IN_TERM_ID); -+ -+ mei->info.head.resume = snd_dualsense_resume_jack; -+ mei->info.val_type = USB_MIXER_BOOLEAN; -+ mei->info.channels = 1; -+ mei->info.min = 0; -+ mei->info.max = 1; -+ -+ kctl = snd_ctl_new1(&snd_dualsense_jack_control, mei); -+ if (!kctl) { -+ kfree(mei); -+ return -ENOMEM; -+ } -+ -+ strscpy(kctl->id.name, name, sizeof(kctl->id.name)); -+ kctl->private_free = snd_dualsense_mixer_elem_free; -+ -+ err = snd_usb_mixer_add_control(&mei->info.head, kctl); -+ if (err) -+ return err; -+ -+ idev_id = &mei->id_table[0]; -+ idev_id->flags = INPUT_DEVICE_ID_MATCH_VENDOR | INPUT_DEVICE_ID_MATCH_PRODUCT | -+ INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_SWBIT; -+ idev_id->vendor = USB_ID_VENDOR(mixer->chip->usb_id); -+ idev_id->product = USB_ID_PRODUCT(mixer->chip->usb_id); -+ idev_id->evbit[BIT_WORD(EV_SW)] = BIT_MASK(EV_SW); -+ if (is_output) -+ idev_id->swbit[BIT_WORD(SW_HEADPHONE_INSERT)] = BIT_MASK(SW_HEADPHONE_INSERT); -+ else -+ idev_id->swbit[BIT_WORD(SW_MICROPHONE_INSERT)] = BIT_MASK(SW_MICROPHONE_INSERT); -+ -+ mei->ih.event = snd_dualsense_ih_event; -+ mei->ih.match = snd_dualsense_ih_match; -+ mei->ih.connect = snd_dualsense_ih_connect; -+ mei->ih.disconnect = snd_dualsense_ih_disconnect; -+ mei->ih.start = snd_dualsense_ih_start; -+ mei->ih.name = name; -+ mei->ih.id_table = mei->id_table; -+ -+ err = input_register_handler(&mei->ih); -+ if (err) { -+ dev_warn(&mixer->chip->dev->dev, -+ "Could not register input handler: %d\n", err); -+ mei->ih.event = NULL; -+ } -+ -+ return 0; -+} -+ -+static int snd_dualsense_controls_create(struct usb_mixer_interface *mixer) -+{ -+ int err; -+ -+ err = snd_dualsense_jack_create(mixer, "Headphone Jack", true); -+ if (err < 0) -+ return err; -+ -+ return snd_dualsense_jack_create(mixer, "Headset Mic Jack", false); -+} -+#endif /* IS_REACHABLE(CONFIG_INPUT) */ -+ - /* ASUS Xonar U1 / U3 controls */ - - static int snd_xonar_u1_switch_get(struct snd_kcontrol *kcontrol, -@@ -856,6 +1118,7 @@ static const struct snd_kcontrol_new snd - static int snd_mbox1_controls_create(struct usb_mixer_interface *mixer) - { - int err; -+ - err = add_single_ctl_with_resume(mixer, 0, - snd_mbox1_clk_switch_resume, - &snd_mbox1_clk_switch, NULL); -@@ -869,7 +1132,7 @@ static int snd_mbox1_controls_create(str - - /* Native Instruments device quirks */ - --#define _MAKE_NI_CONTROL(bRequest,wIndex) ((bRequest) << 16 | (wIndex)) -+#define _MAKE_NI_CONTROL(bRequest, wIndex) ((bRequest) << 16 | (wIndex)) - - static int snd_ni_control_init_val(struct usb_mixer_interface *mixer, - struct snd_kcontrol *kctl) -@@ -1021,7 +1284,7 @@ static int snd_nativeinstruments_create_ - /* M-Audio FastTrack Ultra quirks */ - /* FTU Effect switch (also used by C400/C600) */ - static int snd_ftu_eff_switch_info(struct snd_kcontrol *kcontrol, -- struct snd_ctl_elem_info *uinfo) -+ struct snd_ctl_elem_info *uinfo) - { - static const char *const texts[8] = { - "Room 1", "Room 2", "Room 3", "Hall 1", -@@ -1055,7 +1318,7 @@ static int snd_ftu_eff_switch_init(struc - } - - static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl, -- struct snd_ctl_elem_value *ucontrol) -+ struct snd_ctl_elem_value *ucontrol) - { - ucontrol->value.enumerated.item[0] = kctl->private_value >> 24; - return 0; -@@ -1086,7 +1349,7 @@ static int snd_ftu_eff_switch_update(str - } - - static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, -- struct snd_ctl_elem_value *ucontrol) -+ struct snd_ctl_elem_value *ucontrol) - { - struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl); - unsigned int pval = list->kctl->private_value; -@@ -1104,7 +1367,7 @@ static int snd_ftu_eff_switch_put(struct - } - - static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer, -- int validx, int bUnitID) -+ int validx, int bUnitID) - { - static struct snd_kcontrol_new template = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -@@ -1143,22 +1406,22 @@ static int snd_ftu_create_volume_ctls(st - for (in = 0; in < 8; in++) { - cmask = BIT(in); - snprintf(name, sizeof(name), -- "AIn%d - Out%d Capture Volume", -- in + 1, out + 1); -+ "AIn%d - Out%d Capture Volume", -+ in + 1, out + 1); - err = snd_create_std_mono_ctl(mixer, id, control, -- cmask, val_type, name, -- &snd_usb_mixer_vol_tlv); -+ cmask, val_type, name, -+ &snd_usb_mixer_vol_tlv); - if (err < 0) - return err; - } - for (in = 8; in < 16; in++) { - cmask = BIT(in); - snprintf(name, sizeof(name), -- "DIn%d - Out%d Playback Volume", -- in - 7, out + 1); -+ "DIn%d - Out%d Playback Volume", -+ in - 7, out + 1); - err = snd_create_std_mono_ctl(mixer, id, control, -- cmask, val_type, name, -- &snd_usb_mixer_vol_tlv); -+ cmask, val_type, name, -+ &snd_usb_mixer_vol_tlv); - if (err < 0) - return err; - } -@@ -1219,10 +1482,10 @@ static int snd_ftu_create_effect_return_ - for (ch = 0; ch < 4; ++ch) { - cmask = BIT(ch); - snprintf(name, sizeof(name), -- "Effect Return %d Volume", ch + 1); -+ "Effect Return %d Volume", ch + 1); - err = snd_create_std_mono_ctl(mixer, id, control, -- cmask, val_type, name, -- snd_usb_mixer_vol_tlv); -+ cmask, val_type, name, -+ snd_usb_mixer_vol_tlv); - if (err < 0) - return err; - } -@@ -1243,20 +1506,20 @@ static int snd_ftu_create_effect_send_ct - for (ch = 0; ch < 8; ++ch) { - cmask = BIT(ch); - snprintf(name, sizeof(name), -- "Effect Send AIn%d Volume", ch + 1); -+ "Effect Send AIn%d Volume", ch + 1); - err = snd_create_std_mono_ctl(mixer, id, control, cmask, -- val_type, name, -- snd_usb_mixer_vol_tlv); -+ val_type, name, -+ snd_usb_mixer_vol_tlv); - if (err < 0) - return err; - } - for (ch = 8; ch < 16; ++ch) { - cmask = BIT(ch); - snprintf(name, sizeof(name), -- "Effect Send DIn%d Volume", ch - 7); -+ "Effect Send DIn%d Volume", ch - 7); - err = snd_create_std_mono_ctl(mixer, id, control, cmask, -- val_type, name, -- snd_usb_mixer_vol_tlv); -+ val_type, name, -+ snd_usb_mixer_vol_tlv); - if (err < 0) - return err; - } -@@ -1346,19 +1609,19 @@ static int snd_c400_create_vol_ctls(stru - for (out = 0; out < num_outs; out++) { - if (chan < num_outs) { - snprintf(name, sizeof(name), -- "PCM%d-Out%d Playback Volume", -- chan + 1, out + 1); -+ "PCM%d-Out%d Playback Volume", -+ chan + 1, out + 1); - } else { - snprintf(name, sizeof(name), -- "In%d-Out%d Playback Volume", -- chan - num_outs + 1, out + 1); -+ "In%d-Out%d Playback Volume", -+ chan - num_outs + 1, out + 1); - } - - cmask = (out == 0) ? 0 : BIT(out - 1); - offset = chan * num_outs; - err = snd_create_std_mono_ctl_offset(mixer, id, control, -- cmask, val_type, offset, name, -- &snd_usb_mixer_vol_tlv); -+ cmask, val_type, offset, name, -+ &snd_usb_mixer_vol_tlv); - if (err < 0) - return err; - } -@@ -1377,7 +1640,7 @@ static int snd_c400_create_effect_volume - const unsigned int cmask = 0; - - return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type, -- name, snd_usb_mixer_vol_tlv); -+ name, snd_usb_mixer_vol_tlv); - } - - /* This control needs a volume quirk, see mixer.c */ -@@ -1390,7 +1653,7 @@ static int snd_c400_create_effect_durati - const unsigned int cmask = 0; - - return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type, -- name, snd_usb_mixer_vol_tlv); -+ name, snd_usb_mixer_vol_tlv); - } - - /* This control needs a volume quirk, see mixer.c */ -@@ -1403,7 +1666,7 @@ static int snd_c400_create_effect_feedba - const unsigned int cmask = 0; - - return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type, -- name, NULL); -+ name, NULL); - } - - static int snd_c400_create_effect_vol_ctls(struct usb_mixer_interface *mixer) -@@ -1432,18 +1695,18 @@ static int snd_c400_create_effect_vol_ct - for (chan = 0; chan < num_outs + num_ins; chan++) { - if (chan < num_outs) { - snprintf(name, sizeof(name), -- "Effect Send DOut%d", -- chan + 1); -+ "Effect Send DOut%d", -+ chan + 1); - } else { - snprintf(name, sizeof(name), -- "Effect Send AIn%d", -- chan - num_outs + 1); -+ "Effect Send AIn%d", -+ chan - num_outs + 1); - } - - cmask = (chan == 0) ? 0 : BIT(chan - 1); - err = snd_create_std_mono_ctl(mixer, id, control, -- cmask, val_type, name, -- &snd_usb_mixer_vol_tlv); -+ cmask, val_type, name, -+ &snd_usb_mixer_vol_tlv); - if (err < 0) - return err; - } -@@ -1478,14 +1741,14 @@ static int snd_c400_create_effect_ret_vo - - for (chan = 0; chan < num_outs; chan++) { - snprintf(name, sizeof(name), -- "Effect Return %d", -- chan + 1); -+ "Effect Return %d", -+ chan + 1); - - cmask = (chan == 0) ? 0 : - BIT(chan + (chan % 2) * num_outs - 1); - err = snd_create_std_mono_ctl_offset(mixer, id, control, -- cmask, val_type, offset, name, -- &snd_usb_mixer_vol_tlv); -+ cmask, val_type, offset, name, -+ &snd_usb_mixer_vol_tlv); - if (err < 0) - return err; - } -@@ -1626,7 +1889,7 @@ static const struct std_mono_table ebox4 - * - */ - static int snd_microii_spdif_info(struct snd_kcontrol *kcontrol, -- struct snd_ctl_elem_info *uinfo) -+ struct snd_ctl_elem_info *uinfo) - { - uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; - uinfo->count = 1; -@@ -1634,7 +1897,7 @@ static int snd_microii_spdif_info(struct - } - - static int snd_microii_spdif_default_get(struct snd_kcontrol *kcontrol, -- struct snd_ctl_elem_value *ucontrol) -+ struct snd_ctl_elem_value *ucontrol) - { - struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); - struct snd_usb_audio *chip = list->mixer->chip; -@@ -1667,13 +1930,13 @@ static int snd_microii_spdif_default_get - ep = get_endpoint(alts, 0)->bEndpointAddress; - - err = snd_usb_ctl_msg(chip->dev, -- usb_rcvctrlpipe(chip->dev, 0), -- UAC_GET_CUR, -- USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN, -- UAC_EP_CS_ATTR_SAMPLE_RATE << 8, -- ep, -- data, -- sizeof(data)); -+ usb_rcvctrlpipe(chip->dev, 0), -+ UAC_GET_CUR, -+ USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN, -+ UAC_EP_CS_ATTR_SAMPLE_RATE << 8, -+ ep, -+ data, -+ sizeof(data)); - if (err < 0) - goto end; - -@@ -1700,26 +1963,26 @@ static int snd_microii_spdif_default_upd - - reg = ((pval >> 4) & 0xf0) | (pval & 0x0f); - err = snd_usb_ctl_msg(chip->dev, -- usb_sndctrlpipe(chip->dev, 0), -- UAC_SET_CUR, -- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, -- reg, -- 2, -- NULL, -- 0); -+ usb_sndctrlpipe(chip->dev, 0), -+ UAC_SET_CUR, -+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, -+ reg, -+ 2, -+ NULL, -+ 0); - if (err < 0) - goto end; - - reg = (pval & IEC958_AES0_NONAUDIO) ? 0xa0 : 0x20; - reg |= (pval >> 12) & 0x0f; - err = snd_usb_ctl_msg(chip->dev, -- usb_sndctrlpipe(chip->dev, 0), -- UAC_SET_CUR, -- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, -- reg, -- 3, -- NULL, -- 0); -+ usb_sndctrlpipe(chip->dev, 0), -+ UAC_SET_CUR, -+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, -+ reg, -+ 3, -+ NULL, -+ 0); - if (err < 0) - goto end; - -@@ -1729,13 +1992,14 @@ static int snd_microii_spdif_default_upd - } - - static int snd_microii_spdif_default_put(struct snd_kcontrol *kcontrol, -- struct snd_ctl_elem_value *ucontrol) -+ struct snd_ctl_elem_value *ucontrol) - { - struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); - unsigned int pval, pval_old; - int err; - -- pval = pval_old = kcontrol->private_value; -+ pval = kcontrol->private_value; -+ pval_old = pval; - pval &= 0xfffff0f0; - pval |= (ucontrol->value.iec958.status[1] & 0x0f) << 8; - pval |= (ucontrol->value.iec958.status[0] & 0x0f); -@@ -1756,7 +2020,7 @@ static int snd_microii_spdif_default_put - } - - static int snd_microii_spdif_mask_get(struct snd_kcontrol *kcontrol, -- struct snd_ctl_elem_value *ucontrol) -+ struct snd_ctl_elem_value *ucontrol) - { - ucontrol->value.iec958.status[0] = 0x0f; - ucontrol->value.iec958.status[1] = 0xff; -@@ -1767,7 +2031,7 @@ static int snd_microii_spdif_mask_get(st - } - - static int snd_microii_spdif_switch_get(struct snd_kcontrol *kcontrol, -- struct snd_ctl_elem_value *ucontrol) -+ struct snd_ctl_elem_value *ucontrol) - { - ucontrol->value.integer.value[0] = !(kcontrol->private_value & 0x02); - -@@ -1785,20 +2049,20 @@ static int snd_microii_spdif_switch_upda - return err; - - err = snd_usb_ctl_msg(chip->dev, -- usb_sndctrlpipe(chip->dev, 0), -- UAC_SET_CUR, -- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, -- reg, -- 9, -- NULL, -- 0); -+ usb_sndctrlpipe(chip->dev, 0), -+ UAC_SET_CUR, -+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, -+ reg, -+ 9, -+ NULL, -+ 0); - - snd_usb_unlock_shutdown(chip); - return err; - } - - static int snd_microii_spdif_switch_put(struct snd_kcontrol *kcontrol, -- struct snd_ctl_elem_value *ucontrol) -+ struct snd_ctl_elem_value *ucontrol) - { - struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol); - u8 reg; -@@ -1883,9 +2147,9 @@ static int snd_soundblaster_e1_switch_up - if (err < 0) - return err; - err = snd_usb_ctl_msg(chip->dev, -- usb_sndctrlpipe(chip->dev, 0), HID_REQ_SET_REPORT, -- USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, -- 0x0202, 3, buff, 2); -+ usb_sndctrlpipe(chip->dev, 0), HID_REQ_SET_REPORT, -+ USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, -+ 0x0202, 3, buff, 2); - snd_usb_unlock_shutdown(chip); - return err; - } -@@ -2153,15 +2417,15 @@ static int dell_dock_mixer_init(struct u - #define SND_RME_CLK_FREQMUL_SHIFT 18 - #define SND_RME_CLK_FREQMUL_MASK 0x7 - #define SND_RME_CLK_SYSTEM(x) \ -- ((x >> SND_RME_CLK_SYSTEM_SHIFT) & SND_RME_CLK_SYSTEM_MASK) -+ (((x) >> SND_RME_CLK_SYSTEM_SHIFT) & SND_RME_CLK_SYSTEM_MASK) - #define SND_RME_CLK_AES(x) \ -- ((x >> SND_RME_CLK_AES_SHIFT) & SND_RME_CLK_AES_SPDIF_MASK) -+ (((x) >> SND_RME_CLK_AES_SHIFT) & SND_RME_CLK_AES_SPDIF_MASK) - #define SND_RME_CLK_SPDIF(x) \ -- ((x >> SND_RME_CLK_SPDIF_SHIFT) & SND_RME_CLK_AES_SPDIF_MASK) -+ (((x) >> SND_RME_CLK_SPDIF_SHIFT) & SND_RME_CLK_AES_SPDIF_MASK) - #define SND_RME_CLK_SYNC(x) \ -- ((x >> SND_RME_CLK_SYNC_SHIFT) & SND_RME_CLK_SYNC_MASK) -+ (((x) >> SND_RME_CLK_SYNC_SHIFT) & SND_RME_CLK_SYNC_MASK) - #define SND_RME_CLK_FREQMUL(x) \ -- ((x >> SND_RME_CLK_FREQMUL_SHIFT) & SND_RME_CLK_FREQMUL_MASK) -+ (((x) >> SND_RME_CLK_FREQMUL_SHIFT) & SND_RME_CLK_FREQMUL_MASK) - #define SND_RME_CLK_AES_LOCK 0x1 - #define SND_RME_CLK_AES_SYNC 0x4 - #define SND_RME_CLK_SPDIF_LOCK 0x2 -@@ -2170,9 +2434,9 @@ static int dell_dock_mixer_init(struct u - #define SND_RME_SPDIF_FORMAT_SHIFT 5 - #define SND_RME_BINARY_MASK 0x1 - #define SND_RME_SPDIF_IF(x) \ -- ((x >> SND_RME_SPDIF_IF_SHIFT) & SND_RME_BINARY_MASK) -+ (((x) >> SND_RME_SPDIF_IF_SHIFT) & SND_RME_BINARY_MASK) - #define SND_RME_SPDIF_FORMAT(x) \ -- ((x >> SND_RME_SPDIF_FORMAT_SHIFT) & SND_RME_BINARY_MASK) -+ (((x) >> SND_RME_SPDIF_FORMAT_SHIFT) & SND_RME_BINARY_MASK) - - static const u32 snd_rme_rate_table[] = { - 32000, 44100, 48000, 50000, -@@ -2181,6 +2445,7 @@ static const u32 snd_rme_rate_table[] = - 256000, 352800, 384000, 400000, - 512000, 705600, 768000, 800000 - }; -+ - /* maximum number of items for AES and S/PDIF rates for above table */ - #define SND_RME_RATE_IDX_AES_SPDIF_NUM 12 - -@@ -3235,7 +3500,7 @@ static int snd_rme_digiface_enum_put(str - } - - static int snd_rme_digiface_current_sync_get(struct snd_kcontrol *kcontrol, -- struct snd_ctl_elem_value *ucontrol) -+ struct snd_ctl_elem_value *ucontrol) - { - int ret = snd_rme_digiface_enum_get(kcontrol, ucontrol); - -@@ -3269,7 +3534,6 @@ static int snd_rme_digiface_sync_state_g - return 0; - } - -- - static int snd_rme_digiface_format_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) - { -@@ -3281,7 +3545,6 @@ static int snd_rme_digiface_format_info( - ARRAY_SIZE(format), format); - } - -- - static int snd_rme_digiface_sync_source_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) - { -@@ -3564,7 +3827,6 @@ static int snd_rme_digiface_controls_cre - #define SND_DJM_A9_IDX 0x6 - #define SND_DJM_V10_IDX 0x7 - -- - #define SND_DJM_CTL(_name, suffix, _default_value, _windex) { \ - .name = _name, \ - .options = snd_djm_opts_##suffix, \ -@@ -3576,7 +3838,6 @@ static int snd_rme_digiface_controls_cre - .controls = snd_djm_ctls_##suffix, \ - .ncontrols = ARRAY_SIZE(snd_djm_ctls_##suffix) } - -- - struct snd_djm_device { - const char *name; - const struct snd_djm_ctl *controls; -@@ -3722,7 +3983,6 @@ static const struct snd_djm_ctl snd_djm_ - SND_DJM_CTL("Output 3 Playback Switch", 250mk2_pb3, 2, SND_DJM_WINDEX_PB) - }; - -- - // DJM-450 - static const u16 snd_djm_opts_450_cap1[] = { - 0x0103, 0x0100, 0x0106, 0x0107, 0x0108, 0x0109, 0x010d, 0x010a }; -@@ -3747,7 +4007,6 @@ static const struct snd_djm_ctl snd_djm_ - SND_DJM_CTL("Output 3 Playback Switch", 450_pb3, 2, SND_DJM_WINDEX_PB) - }; - -- - // DJM-750 - static const u16 snd_djm_opts_750_cap1[] = { - 0x0101, 0x0103, 0x0106, 0x0107, 0x0108, 0x0109, 0x010a, 0x010f }; -@@ -3766,7 +4025,6 @@ static const struct snd_djm_ctl snd_djm_ - SND_DJM_CTL("Input 4 Capture Switch", 750_cap4, 0, SND_DJM_WINDEX_CAP) - }; - -- - // DJM-850 - static const u16 snd_djm_opts_850_cap1[] = { - 0x0100, 0x0103, 0x0106, 0x0107, 0x0108, 0x0109, 0x010a, 0x010f }; -@@ -3785,7 +4043,6 @@ static const struct snd_djm_ctl snd_djm_ - SND_DJM_CTL("Input 4 Capture Switch", 850_cap4, 1, SND_DJM_WINDEX_CAP) - }; - -- - // DJM-900NXS2 - static const u16 snd_djm_opts_900nxs2_cap1[] = { - 0x0100, 0x0102, 0x0103, 0x0106, 0x0107, 0x0108, 0x0109, 0x010a }; -@@ -3823,7 +4080,6 @@ static const u16 snd_djm_opts_750mk2_pb1 - static const u16 snd_djm_opts_750mk2_pb2[] = { 0x0200, 0x0201, 0x0204 }; - static const u16 snd_djm_opts_750mk2_pb3[] = { 0x0300, 0x0301, 0x0304 }; - -- - static const struct snd_djm_ctl snd_djm_ctls_750mk2[] = { - SND_DJM_CTL("Master Input Level Capture Switch", cap_level, 0, SND_DJM_WINDEX_CAPLVL), - SND_DJM_CTL("Input 1 Capture Switch", 750mk2_cap1, 2, SND_DJM_WINDEX_CAP), -@@ -3836,7 +4092,6 @@ static const struct snd_djm_ctl snd_djm_ - SND_DJM_CTL("Output 3 Playback Switch", 750mk2_pb3, 2, SND_DJM_WINDEX_PB) - }; - -- - // DJM-A9 - static const u16 snd_djm_opts_a9_cap_level[] = { - 0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500 }; -@@ -3865,29 +4120,35 @@ static const struct snd_djm_ctl snd_djm_ - static const u16 snd_djm_opts_v10_cap_level[] = { - 0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500 - }; -+ - static const u16 snd_djm_opts_v10_cap1[] = { - 0x0103, - 0x0100, 0x0102, 0x0106, 0x0110, 0x0107, - 0x0108, 0x0109, 0x010a, 0x0121, 0x0122 - }; -+ - static const u16 snd_djm_opts_v10_cap2[] = { - 0x0200, 0x0202, 0x0206, 0x0210, 0x0207, - 0x0208, 0x0209, 0x020a, 0x0221, 0x0222 - }; -+ - static const u16 snd_djm_opts_v10_cap3[] = { - 0x0303, - 0x0300, 0x0302, 0x0306, 0x0310, 0x0307, - 0x0308, 0x0309, 0x030a, 0x0321, 0x0322 - }; -+ - static const u16 snd_djm_opts_v10_cap4[] = { - 0x0403, - 0x0400, 0x0402, 0x0406, 0x0410, 0x0407, - 0x0408, 0x0409, 0x040a, 0x0421, 0x0422 - }; -+ - static const u16 snd_djm_opts_v10_cap5[] = { - 0x0500, 0x0502, 0x0506, 0x0510, 0x0507, - 0x0508, 0x0509, 0x050a, 0x0521, 0x0522 - }; -+ - static const u16 snd_djm_opts_v10_cap6[] = { - 0x0603, - 0x0600, 0x0602, 0x0606, 0x0610, 0x0607, -@@ -3916,9 +4177,8 @@ static const struct snd_djm_device snd_d - [SND_DJM_V10_IDX] = SND_DJM_DEVICE(v10), - }; - -- - static int snd_djm_controls_info(struct snd_kcontrol *kctl, -- struct snd_ctl_elem_info *info) -+ struct snd_ctl_elem_info *info) - { - unsigned long private_value = kctl->private_value; - u8 device_idx = (private_value & SND_DJM_DEVICE_MASK) >> SND_DJM_DEVICE_SHIFT; -@@ -3937,8 +4197,8 @@ static int snd_djm_controls_info(struct - info->value.enumerated.item = noptions - 1; - - name = snd_djm_get_label(device_idx, -- ctl->options[info->value.enumerated.item], -- ctl->wIndex); -+ ctl->options[info->value.enumerated.item], -+ ctl->wIndex); - if (!name) - return -EINVAL; - -@@ -3950,25 +4210,25 @@ static int snd_djm_controls_info(struct - } - - static int snd_djm_controls_update(struct usb_mixer_interface *mixer, -- u8 device_idx, u8 group, u16 value) -+ u8 device_idx, u8 group, u16 value) - { - int err; - const struct snd_djm_device *device = &snd_djm_devices[device_idx]; - -- if ((group >= device->ncontrols) || value >= device->controls[group].noptions) -+ if (group >= device->ncontrols || value >= device->controls[group].noptions) - return -EINVAL; - - err = snd_usb_lock_shutdown(mixer->chip); - if (err) - return err; - -- err = snd_usb_ctl_msg( -- mixer->chip->dev, usb_sndctrlpipe(mixer->chip->dev, 0), -- USB_REQ_SET_FEATURE, -- USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, -- device->controls[group].options[value], -- device->controls[group].wIndex, -- NULL, 0); -+ err = snd_usb_ctl_msg(mixer->chip->dev, -+ usb_sndctrlpipe(mixer->chip->dev, 0), -+ USB_REQ_SET_FEATURE, -+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, -+ device->controls[group].options[value], -+ device->controls[group].wIndex, -+ NULL, 0); - - snd_usb_unlock_shutdown(mixer->chip); - return err; -@@ -4009,7 +4269,7 @@ static int snd_djm_controls_resume(struc - } - - static int snd_djm_controls_create(struct usb_mixer_interface *mixer, -- const u8 device_idx) -+ const u8 device_idx) - { - int err, i; - u16 value; -@@ -4028,10 +4288,10 @@ static int snd_djm_controls_create(struc - for (i = 0; i < device->ncontrols; i++) { - value = device->controls[i].default_value; - knew.name = device->controls[i].name; -- knew.private_value = ( -+ knew.private_value = - ((unsigned long)device_idx << SND_DJM_DEVICE_SHIFT) | - (i << SND_DJM_GROUP_SHIFT) | -- value); -+ value; - err = snd_djm_controls_update(mixer, device_idx, i, value); - if (err) - return err; -@@ -4073,6 +4333,13 @@ int snd_usb_mixer_apply_create_quirk(str - err = snd_emu0204_controls_create(mixer); - break; - -+#if IS_REACHABLE(CONFIG_INPUT) -+ case USB_ID(0x054c, 0x0ce6): /* Sony DualSense controller (PS5) */ -+ case USB_ID(0x054c, 0x0df2): /* Sony DualSense Edge controller (PS5) */ -+ err = snd_dualsense_controls_create(mixer); -+ break; -+#endif /* IS_REACHABLE(CONFIG_INPUT) */ -+ - case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */ - case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C400 */ - err = snd_c400_create_mixer(mixer); -@@ -4098,13 +4365,15 @@ int snd_usb_mixer_apply_create_quirk(str - break; - - case USB_ID(0x17cc, 0x1011): /* Traktor Audio 6 */ -- err = snd_nativeinstruments_create_mixer(mixer, -+ err = snd_nativeinstruments_create_mixer(/* checkpatch hack */ -+ mixer, - snd_nativeinstruments_ta6_mixers, - ARRAY_SIZE(snd_nativeinstruments_ta6_mixers)); - break; - - case USB_ID(0x17cc, 0x1021): /* Traktor Audio 10 */ -- err = snd_nativeinstruments_create_mixer(mixer, -+ err = snd_nativeinstruments_create_mixer(/* checkpatch hack */ -+ mixer, - snd_nativeinstruments_ta10_mixers, - ARRAY_SIZE(snd_nativeinstruments_ta10_mixers)); - break; -@@ -4254,7 +4523,8 @@ static void snd_dragonfly_quirk_db_scale - struct snd_kcontrol *kctl) - { - /* Approximation using 10 ranges based on output measurement on hw v1.2. -- * This seems close to the cubic mapping e.g. alsamixer uses. */ -+ * This seems close to the cubic mapping e.g. alsamixer uses. -+ */ - static const DECLARE_TLV_DB_RANGE(scale, - 0, 1, TLV_DB_MINMAX_ITEM(-5300, -4970), - 2, 5, TLV_DB_MINMAX_ITEM(-4710, -4160), -@@ -4338,18 +4608,15 @@ void snd_usb_mixer_fu_apply_quirk(struct - if (unitid == 7 && cval->control == UAC_FU_VOLUME) - snd_dragonfly_quirk_db_scale(mixer, cval, kctl); - break; -+ } -+ - /* lowest playback value is muted on some devices */ -- case USB_ID(0x0d8c, 0x000c): /* C-Media */ -- case USB_ID(0x0d8c, 0x0014): /* C-Media */ -- case USB_ID(0x19f7, 0x0003): /* RODE NT-USB */ -+ if (mixer->chip->quirk_flags & QUIRK_FLAG_MIXER_MIN_MUTE) - if (strstr(kctl->id.name, "Playback")) - cval->min_mute = 1; -- break; -- } - - /* ALSA-ify some Plantronics headset control names */ - if (USB_ID_VENDOR(mixer->chip->usb_id) == 0x047f && - (cval->control == UAC_FU_MUTE || cval->control == UAC_FU_VOLUME)) - snd_fix_plt_name(mixer->chip, &kctl->id); - } -- -diff -purNx .git BPI-Router-Linux-kernel/sound/usb/mixer_scarlett2.c BPI-Router-Linux-kernel-6.16.12/sound/usb/mixer_scarlett2.c ---- BPI-Router-Linux-kernel/sound/usb/mixer_scarlett2.c 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/usb/mixer_scarlett2.c 2025-10-22 13:53:56.859167483 -0400 -@@ -2351,6 +2351,8 @@ static int scarlett2_usb( - struct scarlett2_usb_packet *req, *resp = NULL; - size_t req_buf_size = struct_size(req, data, req_size); - size_t resp_buf_size = struct_size(resp, data, resp_size); -+ int retries = 0; -+ const int max_retries = 5; - int err; - - req = kmalloc(req_buf_size, GFP_KERNEL); -@@ -2374,10 +2376,15 @@ static int scarlett2_usb( - if (req_size) - memcpy(req->data, req_data, req_size); - -+retry: - err = scarlett2_usb_tx(dev, private->bInterfaceNumber, - req, req_buf_size); - - if (err != req_buf_size) { -+ if (err == -EPROTO && ++retries <= max_retries) { -+ msleep(5 * (1 << (retries - 1))); -+ goto retry; -+ } - usb_audio_err( - mixer->chip, - "%s USB request result cmd %x was %d\n", -@@ -3971,8 +3978,13 @@ static int scarlett2_input_select_ctl_in - goto unlock; - - /* Loop through each input */ -- for (i = 0; i < inputs; i++) -+ for (i = 0; i < inputs; i++) { - values[i] = kasprintf(GFP_KERNEL, "Input %d", i + 1); -+ if (!values[i]) { -+ err = -ENOMEM; -+ goto unlock; -+ } -+ } - - err = snd_ctl_enum_info(uinfo, 1, i, - (const char * const *)values); -diff -purNx .git BPI-Router-Linux-kernel/sound/usb/qcom/qc_audio_offload.c BPI-Router-Linux-kernel-6.16.12/sound/usb/qcom/qc_audio_offload.c ---- BPI-Router-Linux-kernel/sound/usb/qcom/qc_audio_offload.c 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/usb/qcom/qc_audio_offload.c 2025-10-22 13:53:56.859167483 -0400 -@@ -538,38 +538,33 @@ static void uaudio_iommu_unmap(enum mem_ - umap_size, iova, mapped_iova_size); - } - -+static int uaudio_iommu_map_prot(bool dma_coherent) -+{ -+ int prot = IOMMU_READ | IOMMU_WRITE; -+ -+ if (dma_coherent) -+ prot |= IOMMU_CACHE; -+ return prot; -+} -+ - /** -- * uaudio_iommu_map() - maps iommu memory for adsp -+ * uaudio_iommu_map_pa() - maps iommu memory for adsp - * @mtype: ring type - * @dma_coherent: dma coherent - * @pa: physical address for ring/buffer - * @size: size of memory region -- * @sgt: sg table for memory region - * - * Maps the XHCI related resources to a memory region that is assigned to be - * used by the adsp. This will be mapped to the domain, which is created by - * the ASoC USB backend driver. - * - */ --static unsigned long uaudio_iommu_map(enum mem_type mtype, bool dma_coherent, -- phys_addr_t pa, size_t size, -- struct sg_table *sgt) -+static unsigned long uaudio_iommu_map_pa(enum mem_type mtype, bool dma_coherent, -+ phys_addr_t pa, size_t size) - { -- struct scatterlist *sg; - unsigned long iova = 0; -- size_t total_len = 0; -- unsigned long iova_sg; -- phys_addr_t pa_sg; - bool map = true; -- size_t sg_len; -- int prot; -- int ret; -- int i; -- -- prot = IOMMU_READ | IOMMU_WRITE; -- -- if (dma_coherent) -- prot |= IOMMU_CACHE; -+ int prot = uaudio_iommu_map_prot(dma_coherent); - - switch (mtype) { - case MEM_EVENT_RING: -@@ -583,20 +578,41 @@ static unsigned long uaudio_iommu_map(en - &uaudio_qdev->xfer_ring_iova_size, - &uaudio_qdev->xfer_ring_list, size); - break; -- case MEM_XFER_BUF: -- iova = uaudio_get_iova(&uaudio_qdev->curr_xfer_buf_iova, -- &uaudio_qdev->xfer_buf_iova_size, -- &uaudio_qdev->xfer_buf_list, size); -- break; - default: - dev_err(uaudio_qdev->data->dev, "unknown mem type %d\n", mtype); - } - - if (!iova || !map) -- goto done; -+ return 0; -+ -+ iommu_map(uaudio_qdev->data->domain, iova, pa, size, prot, GFP_KERNEL); -+ -+ return iova; -+} -+ -+static unsigned long uaudio_iommu_map_xfer_buf(bool dma_coherent, size_t size, -+ struct sg_table *sgt) -+{ -+ struct scatterlist *sg; -+ unsigned long iova = 0; -+ size_t total_len = 0; -+ unsigned long iova_sg; -+ phys_addr_t pa_sg; -+ size_t sg_len; -+ int prot = uaudio_iommu_map_prot(dma_coherent); -+ int ret; -+ int i; - -- if (!sgt) -- goto skip_sgt_map; -+ prot = IOMMU_READ | IOMMU_WRITE; -+ -+ if (dma_coherent) -+ prot |= IOMMU_CACHE; -+ -+ iova = uaudio_get_iova(&uaudio_qdev->curr_xfer_buf_iova, -+ &uaudio_qdev->xfer_buf_iova_size, -+ &uaudio_qdev->xfer_buf_list, size); -+ if (!iova) -+ goto done; - - iova_sg = iova; - for_each_sg(sgt->sgl, sg, sgt->nents, i) { -@@ -618,11 +634,6 @@ static unsigned long uaudio_iommu_map(en - uaudio_iommu_unmap(MEM_XFER_BUF, iova, size, total_len); - iova = 0; - } -- return iova; -- --skip_sgt_map: -- iommu_map(uaudio_qdev->data->domain, iova, pa, size, prot, GFP_KERNEL); -- - done: - return iova; - } -@@ -759,7 +770,7 @@ static void qmi_stop_session(void) - subs = find_substream(pcm_card_num, info->pcm_dev_num, - info->direction); - if (!subs || !chip || atomic_read(&chip->shutdown)) { -- dev_err(&subs->dev->dev, -+ dev_err(&uadev[idx].udev->dev, - "no sub for c#%u dev#%u dir%u\n", - info->pcm_card_num, - info->pcm_dev_num, -@@ -825,8 +836,8 @@ static int uaudio_sideband_notifier(stru - } - } - -- mutex_unlock(&qdev_mutex); - mutex_unlock(&chip->mutex); -+ mutex_unlock(&qdev_mutex); - - return 0; - } -@@ -1020,7 +1031,6 @@ static int uaudio_transfer_buffer_setup( - struct sg_table xfer_buf_sgt; - dma_addr_t xfer_buf_dma; - void *xfer_buf; -- phys_addr_t xfer_buf_pa; - u32 len = xfer_buf_len; - bool dma_coherent; - dma_addr_t xfer_buf_dma_sysdev; -@@ -1051,18 +1061,12 @@ static int uaudio_transfer_buffer_setup( - if (!xfer_buf) - return -ENOMEM; - -- /* Remapping is not possible if xfer_buf is outside of linear map */ -- xfer_buf_pa = virt_to_phys(xfer_buf); -- if (WARN_ON(!page_is_ram(PFN_DOWN(xfer_buf_pa)))) { -- ret = -ENXIO; -- goto unmap_sync; -- } - dma_get_sgtable(subs->dev->bus->sysdev, &xfer_buf_sgt, xfer_buf, - xfer_buf_dma, len); - - /* map the physical buffer into sysdev as well */ -- xfer_buf_dma_sysdev = uaudio_iommu_map(MEM_XFER_BUF, dma_coherent, -- xfer_buf_pa, len, &xfer_buf_sgt); -+ xfer_buf_dma_sysdev = uaudio_iommu_map_xfer_buf(dma_coherent, -+ len, &xfer_buf_sgt); - if (!xfer_buf_dma_sysdev) { - ret = -ENOMEM; - goto unmap_sync; -@@ -1143,8 +1147,8 @@ uaudio_endpoint_setup(struct snd_usb_sub - sg_free_table(sgt); - - /* data transfer ring */ -- iova = uaudio_iommu_map(MEM_XFER_RING, dma_coherent, tr_pa, -- PAGE_SIZE, NULL); -+ iova = uaudio_iommu_map_pa(MEM_XFER_RING, dma_coherent, tr_pa, -+ PAGE_SIZE); - if (!iova) { - ret = -ENOMEM; - goto clear_pa; -@@ -1207,8 +1211,8 @@ static int uaudio_event_ring_setup(struc - mem_info->dma = sg_dma_address(sgt->sgl); - sg_free_table(sgt); - -- iova = uaudio_iommu_map(MEM_EVENT_RING, dma_coherent, er_pa, -- PAGE_SIZE, NULL); -+ iova = uaudio_iommu_map_pa(MEM_EVENT_RING, dma_coherent, er_pa, -+ PAGE_SIZE); - if (!iova) { - ret = -ENOMEM; - goto clear_pa; -@@ -1360,20 +1364,21 @@ static int prepare_qmi_response(struct s - - if (!uadev[card_num].ctrl_intf) { - dev_err(&subs->dev->dev, "audio ctrl intf info not cached\n"); -- ret = -ENODEV; -- goto err; -+ return -ENODEV; - } - - ret = uaudio_populate_uac_desc(subs, resp); - if (ret < 0) -- goto err; -+ return ret; - - resp->slot_id = subs->dev->slot_id; - resp->slot_id_valid = 1; - - data = snd_soc_usb_find_priv_data(uaudio_qdev->auxdev->dev.parent); -- if (!data) -- goto err; -+ if (!data) { -+ dev_err(&subs->dev->dev, "No private data found\n"); -+ return -ENODEV; -+ } - - uaudio_qdev->data = data; - -@@ -1382,7 +1387,7 @@ static int prepare_qmi_response(struct s - &resp->xhci_mem_info.tr_data, - &resp->std_as_data_ep_desc); - if (ret < 0) -- goto err; -+ return ret; - - resp->std_as_data_ep_desc_valid = 1; - -@@ -1500,7 +1505,6 @@ drop_data_ep: - xhci_sideband_remove_endpoint(uadev[card_num].sb, - usb_pipe_endpoint(subs->dev, subs->data_endpoint->pipe)); - --err: - return ret; - } - -@@ -1865,8 +1869,8 @@ static void qc_usb_audio_offload_disconn - - /* Device has already been cleaned up, or never populated */ - if (!dev->chip) { -- mutex_unlock(&qdev_mutex); - mutex_unlock(&chip->mutex); -+ mutex_unlock(&qdev_mutex); - return; - } - -@@ -1921,8 +1925,8 @@ static void qc_usb_audio_offload_suspend - - uaudio_send_disconnect_ind(chip); - -- mutex_unlock(&qdev_mutex); - mutex_unlock(&chip->mutex); -+ mutex_unlock(&qdev_mutex); - } - - static struct snd_usb_platform_ops offload_ops = { -diff -purNx .git BPI-Router-Linux-kernel/sound/usb/quirks.c BPI-Router-Linux-kernel-6.16.12/sound/usb/quirks.c ---- BPI-Router-Linux-kernel/sound/usb/quirks.c 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/usb/quirks.c 2025-10-22 13:53:56.859167483 -0400 -@@ -2199,6 +2199,10 @@ static const struct usb_audio_quirk_flag - QUIRK_FLAG_SET_IFACE_FIRST), - DEVICE_FLG(0x0556, 0x0014, /* Phoenix Audio TMX320VC */ - QUIRK_FLAG_GET_SAMPLE_RATE), -+ DEVICE_FLG(0x0572, 0x1b08, /* Conexant Systems (Rockwell), Inc. */ -+ QUIRK_FLAG_MIXER_MIN_MUTE), -+ DEVICE_FLG(0x0572, 0x1b09, /* Conexant Systems (Rockwell), Inc. */ -+ QUIRK_FLAG_MIXER_MIN_MUTE), - DEVICE_FLG(0x05a3, 0x9420, /* ELP HD USB Camera */ - QUIRK_FLAG_GET_SAMPLE_RATE), - DEVICE_FLG(0x05a7, 0x1020, /* Bose Companion 5 */ -@@ -2241,12 +2245,16 @@ static const struct usb_audio_quirk_flag - QUIRK_FLAG_CTL_MSG_DELAY_1M), - DEVICE_FLG(0x0b0e, 0x0349, /* Jabra 550a */ - QUIRK_FLAG_CTL_MSG_DELAY_1M), -+ DEVICE_FLG(0x0bda, 0x498a, /* Realtek Semiconductor Corp. */ -+ QUIRK_FLAG_MIXER_MIN_MUTE), - DEVICE_FLG(0x0c45, 0x6340, /* Sonix HD USB Camera */ - QUIRK_FLAG_GET_SAMPLE_RATE), - DEVICE_FLG(0x0c45, 0x636b, /* Microdia JP001 USB Camera */ - QUIRK_FLAG_GET_SAMPLE_RATE), -- DEVICE_FLG(0x0d8c, 0x0014, /* USB Audio Device */ -- QUIRK_FLAG_CTL_MSG_DELAY_1M), -+ DEVICE_FLG(0x0d8c, 0x000c, /* C-Media */ -+ QUIRK_FLAG_MIXER_MIN_MUTE), -+ DEVICE_FLG(0x0d8c, 0x0014, /* C-Media */ -+ QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIXER_MIN_MUTE), - DEVICE_FLG(0x0ecb, 0x205c, /* JBL Quantum610 Wireless */ - QUIRK_FLAG_FIXED_RATE), - DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */ -@@ -2255,6 +2263,8 @@ static const struct usb_audio_quirk_flag - QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER), - DEVICE_FLG(0x1101, 0x0003, /* Audioengine D1 */ - QUIRK_FLAG_GET_SAMPLE_RATE), -+ DEVICE_FLG(0x12d1, 0x3a07, /* Huawei Technologies Co., Ltd. */ -+ QUIRK_FLAG_MIXER_MIN_MUTE), - DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */ - QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16), - DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */ -@@ -2293,6 +2303,8 @@ static const struct usb_audio_quirk_flag - QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY), - DEVICE_FLG(0x1901, 0x0191, /* GE B850V3 CP2114 audio interface */ - QUIRK_FLAG_GET_SAMPLE_RATE), -+ DEVICE_FLG(0x19f7, 0x0003, /* RODE NT-USB */ -+ QUIRK_FLAG_MIXER_MIN_MUTE), - DEVICE_FLG(0x19f7, 0x0035, /* RODE NT-USB+ */ - QUIRK_FLAG_GET_SAMPLE_RATE), - DEVICE_FLG(0x1bcf, 0x2281, /* HD Webcam */ -@@ -2343,6 +2355,8 @@ static const struct usb_audio_quirk_flag - QUIRK_FLAG_IGNORE_CTL_ERROR), - DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */ - QUIRK_FLAG_GET_SAMPLE_RATE), -+ DEVICE_FLG(0x2a70, 0x1881, /* OnePlus Technology (Shenzhen) Co., Ltd. BE02T */ -+ QUIRK_FLAG_MIXER_MIN_MUTE), - DEVICE_FLG(0x2b53, 0x0023, /* Fiero SC-01 (firmware v1.0.0 @ 48 kHz) */ - QUIRK_FLAG_GENERIC_IMPLICIT_FB), - DEVICE_FLG(0x2b53, 0x0024, /* Fiero SC-01 (firmware v1.0.0 @ 96 kHz) */ -@@ -2353,10 +2367,14 @@ static const struct usb_audio_quirk_flag - QUIRK_FLAG_CTL_MSG_DELAY_1M), - DEVICE_FLG(0x2d95, 0x8021, /* VIVO USB-C-XE710 HEADSET */ - QUIRK_FLAG_CTL_MSG_DELAY_1M), -+ DEVICE_FLG(0x2d99, 0x0026, /* HECATE G2 GAMING HEADSET */ -+ QUIRK_FLAG_MIXER_MIN_MUTE), - DEVICE_FLG(0x2fc6, 0xf0b7, /* iBasso DC07 Pro */ - QUIRK_FLAG_CTL_MSG_DELAY_1M), - DEVICE_FLG(0x30be, 0x0101, /* Schiit Hel */ - QUIRK_FLAG_IGNORE_CTL_ERROR), -+ DEVICE_FLG(0x339b, 0x3a07, /* Synaptics HONOR USB-C HEADSET */ -+ QUIRK_FLAG_MIXER_MIN_MUTE), - DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */ - QUIRK_FLAG_GET_SAMPLE_RATE), - DEVICE_FLG(0x534d, 0x0021, /* MacroSilicon MS2100/MS2106 */ -@@ -2408,6 +2426,8 @@ static const struct usb_audio_quirk_flag - QUIRK_FLAG_DSD_RAW), - VENDOR_FLG(0x2d87, /* Cayin device */ - QUIRK_FLAG_DSD_RAW), -+ VENDOR_FLG(0x2fc6, /* Comture-inc devices */ -+ QUIRK_FLAG_DSD_RAW), - VENDOR_FLG(0x3336, /* HEM devices */ - QUIRK_FLAG_DSD_RAW), - VENDOR_FLG(0x3353, /* Khadas devices */ -diff -purNx .git BPI-Router-Linux-kernel/sound/usb/stream.c BPI-Router-Linux-kernel-6.16.12/sound/usb/stream.c ---- BPI-Router-Linux-kernel/sound/usb/stream.c 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/usb/stream.c 2025-10-22 13:53:56.859167483 -0400 -@@ -341,20 +341,28 @@ snd_pcm_chmap_elem *convert_chmap_v3(str - - len = le16_to_cpu(cluster->wLength); - c = 0; -- p += sizeof(struct uac3_cluster_header_descriptor); -+ p += sizeof(*cluster); -+ len -= sizeof(*cluster); - -- while (((p - (void *)cluster) < len) && (c < channels)) { -+ while (len > 0 && (c < channels)) { - struct uac3_cluster_segment_descriptor *cs_desc = p; - u16 cs_len; - u8 cs_type; - -+ if (len < sizeof(*cs_desc)) -+ break; - cs_len = le16_to_cpu(cs_desc->wLength); -+ if (len < cs_len) -+ break; - cs_type = cs_desc->bSegmentType; - - if (cs_type == UAC3_CHANNEL_INFORMATION) { - struct uac3_cluster_information_segment_descriptor *is = p; - unsigned char map; - -+ if (cs_len < sizeof(*is)) -+ break; -+ - /* - * TODO: this conversion is not complete, update it - * after adding UAC3 values to asound.h -@@ -456,6 +464,7 @@ snd_pcm_chmap_elem *convert_chmap_v3(str - chmap->map[c++] = map; - } - p += cs_len; -+ len -= cs_len; - } - - if (channels < c) -@@ -880,7 +889,7 @@ snd_usb_get_audioformat_uac3(struct snd_ - u64 badd_formats = 0; - unsigned int num_channels; - struct audioformat *fp; -- u16 cluster_id, wLength; -+ u16 cluster_id, wLength, cluster_wLength; - int clock = 0; - int err; - -@@ -987,6 +996,8 @@ snd_usb_get_audioformat_uac3(struct snd_ - * and request Cluster Descriptor - */ - wLength = le16_to_cpu(hc_header.wLength); -+ if (wLength < sizeof(cluster)) -+ return NULL; - cluster = kzalloc(wLength, GFP_KERNEL); - if (!cluster) - return ERR_PTR(-ENOMEM); -@@ -1006,6 +1017,16 @@ snd_usb_get_audioformat_uac3(struct snd_ - iface_no, altno); - kfree(cluster); - return ERR_PTR(-EIO); -+ } -+ -+ cluster_wLength = le16_to_cpu(cluster->wLength); -+ if (cluster_wLength < sizeof(*cluster) || -+ cluster_wLength > wLength) { -+ dev_err(&dev->dev, -+ "%u:%d : invalid Cluster Descriptor size\n", -+ iface_no, altno); -+ kfree(cluster); -+ return ERR_PTR(-EIO); - } - - num_channels = cluster->bNrChannels; -diff -purNx .git BPI-Router-Linux-kernel/sound/usb/usbaudio.h BPI-Router-Linux-kernel-6.16.12/sound/usb/usbaudio.h ---- BPI-Router-Linux-kernel/sound/usb/usbaudio.h 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/usb/usbaudio.h 2025-10-22 13:53:56.859167483 -0400 -@@ -196,6 +196,9 @@ extern bool snd_usb_skip_validation; - * for the given endpoint. - * QUIRK_FLAG_MIC_RES_16 and QUIRK_FLAG_MIC_RES_384 - * Set the fixed resolution for Mic Capture Volume (mostly for webcams) -+ * QUIRK_FLAG_MIXER_MIN_MUTE -+ * Set minimum volume control value as mute for devices where the lowest -+ * playback value represents muted state instead of minimum audible volume - */ - - #define QUIRK_FLAG_GET_SAMPLE_RATE (1U << 0) -@@ -222,5 +225,6 @@ extern bool snd_usb_skip_validation; - #define QUIRK_FLAG_FIXED_RATE (1U << 21) - #define QUIRK_FLAG_MIC_RES_16 (1U << 22) - #define QUIRK_FLAG_MIC_RES_384 (1U << 23) -+#define QUIRK_FLAG_MIXER_MIN_MUTE (1U << 24) - - #endif /* __USBAUDIO_H */ -diff -purNx .git BPI-Router-Linux-kernel/sound/usb/validate.c BPI-Router-Linux-kernel-6.16.12/sound/usb/validate.c ---- BPI-Router-Linux-kernel/sound/usb/validate.c 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/usb/validate.c 2025-10-22 13:53:56.859167483 -0400 -@@ -221,6 +221,17 @@ static bool validate_uac3_feature_unit(c - return d->bLength >= sizeof(*d) + 4 + 2; - } - -+static bool validate_uac3_power_domain_unit(const void *p, -+ const struct usb_desc_validator *v) -+{ -+ const struct uac3_power_domain_descriptor *d = p; -+ -+ if (d->bLength < sizeof(*d)) -+ return false; -+ /* baEntities[] + wPDomainDescrStr */ -+ return d->bLength >= sizeof(*d) + d->bNrEntities + 2; -+} -+ - static bool validate_midi_out_jack(const void *p, - const struct usb_desc_validator *v) - { -@@ -274,7 +285,7 @@ static const struct usb_desc_validator a - /* UAC_VERSION_3, UAC3_EXTENDED_TERMINAL: not implemented yet */ - FUNC(UAC_VERSION_3, UAC3_MIXER_UNIT, validate_mixer_unit), - FUNC(UAC_VERSION_3, UAC3_SELECTOR_UNIT, validate_selector_unit), -- FUNC(UAC_VERSION_3, UAC_FEATURE_UNIT, validate_uac3_feature_unit), -+ FUNC(UAC_VERSION_3, UAC3_FEATURE_UNIT, validate_uac3_feature_unit), - /* UAC_VERSION_3, UAC3_EFFECT_UNIT: not implemented yet */ - FUNC(UAC_VERSION_3, UAC3_PROCESSING_UNIT, validate_processing_unit), - FUNC(UAC_VERSION_3, UAC3_EXTENSION_UNIT, validate_processing_unit), -@@ -285,6 +296,7 @@ static const struct usb_desc_validator a - struct uac3_clock_multiplier_descriptor), - /* UAC_VERSION_3, UAC3_SAMPLE_RATE_CONVERTER: not implemented yet */ - /* UAC_VERSION_3, UAC3_CONNECTORS: not implemented yet */ -+ FUNC(UAC_VERSION_3, UAC3_POWER_DOMAIN, validate_uac3_power_domain_unit), - { } /* terminator */ - }; - -diff -purNx .git BPI-Router-Linux-kernel/sound/x86/intel_hdmi_audio.c BPI-Router-Linux-kernel-6.16.12/sound/x86/intel_hdmi_audio.c ---- BPI-Router-Linux-kernel/sound/x86/intel_hdmi_audio.c 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/sound/x86/intel_hdmi_audio.c 2025-10-22 13:53:56.859167483 -0400 -@@ -1768,7 +1768,7 @@ static int __hdmi_lpe_audio_probe(struct - /* setup private data which can be retrieved when required */ - pcm->private_data = ctx; - pcm->info_flags = 0; -- strscpy(pcm->name, card->shortname, strlen(card->shortname)); -+ strscpy(pcm->name, card->shortname, sizeof(pcm->name)); - /* setup the ops for playback */ - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &had_pcm_ops); - -diff -purNx .git BPI-Router-Linux-kernel/tools/arch/arm64/include/uapi/asm/kvm.h BPI-Router-Linux-kernel-6.16.12/tools/arch/arm64/include/uapi/asm/kvm.h ---- BPI-Router-Linux-kernel/tools/arch/arm64/include/uapi/asm/kvm.h 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/arch/arm64/include/uapi/asm/kvm.h 2025-10-22 13:53:56.859167483 -0400 -@@ -431,10 +431,11 @@ enum { - - /* Device Control API on vcpu fd */ - #define KVM_ARM_VCPU_PMU_V3_CTRL 0 --#define KVM_ARM_VCPU_PMU_V3_IRQ 0 --#define KVM_ARM_VCPU_PMU_V3_INIT 1 --#define KVM_ARM_VCPU_PMU_V3_FILTER 2 --#define KVM_ARM_VCPU_PMU_V3_SET_PMU 3 -+#define KVM_ARM_VCPU_PMU_V3_IRQ 0 -+#define KVM_ARM_VCPU_PMU_V3_INIT 1 -+#define KVM_ARM_VCPU_PMU_V3_FILTER 2 -+#define KVM_ARM_VCPU_PMU_V3_SET_PMU 3 -+#define KVM_ARM_VCPU_PMU_V3_SET_NR_COUNTERS 4 - #define KVM_ARM_VCPU_TIMER_CTRL 1 - #define KVM_ARM_VCPU_TIMER_IRQ_VTIMER 0 - #define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1 -diff -purNx .git BPI-Router-Linux-kernel/tools/arch/loongarch/include/asm/inst.h BPI-Router-Linux-kernel-6.16.12/tools/arch/loongarch/include/asm/inst.h ---- BPI-Router-Linux-kernel/tools/arch/loongarch/include/asm/inst.h 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/arch/loongarch/include/asm/inst.h 2025-10-22 13:53:56.859167483 -0400 -@@ -51,6 +51,10 @@ enum reg2i16_op { - bgeu_op = 0x1b, - }; - -+enum reg3_op { -+ amswapw_op = 0x70c0, -+}; -+ - struct reg0i15_format { - unsigned int immediate : 15; - unsigned int opcode : 17; -@@ -96,6 +100,13 @@ struct reg2i16_format { - unsigned int opcode : 6; - }; - -+struct reg3_format { -+ unsigned int rd : 5; -+ unsigned int rj : 5; -+ unsigned int rk : 5; -+ unsigned int opcode : 17; -+}; -+ - union loongarch_instruction { - unsigned int word; - struct reg0i15_format reg0i15_format; -@@ -105,6 +116,7 @@ union loongarch_instruction { - struct reg2i12_format reg2i12_format; - struct reg2i14_format reg2i14_format; - struct reg2i16_format reg2i16_format; -+ struct reg3_format reg3_format; - }; - - #define LOONGARCH_INSN_SIZE sizeof(union loongarch_instruction) -diff -purNx .git BPI-Router-Linux-kernel/tools/arch/loongarch/include/asm/orc_types.h BPI-Router-Linux-kernel-6.16.12/tools/arch/loongarch/include/asm/orc_types.h ---- BPI-Router-Linux-kernel/tools/arch/loongarch/include/asm/orc_types.h 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/arch/loongarch/include/asm/orc_types.h 2025-10-22 13:53:56.859167483 -0400 -@@ -34,7 +34,7 @@ - #define ORC_TYPE_REGS 3 - #define ORC_TYPE_REGS_PARTIAL 4 - --#ifndef __ASSEMBLY__ -+#ifndef __ASSEMBLER__ - /* - * This struct is more or less a vastly simplified version of the DWARF Call - * Frame Information standard. It contains only the necessary parts of DWARF -@@ -53,6 +53,6 @@ struct orc_entry { - unsigned int type:3; - unsigned int signal:1; - }; --#endif /* __ASSEMBLY__ */ -+#endif /* __ASSEMBLER__ */ - - #endif /* _ORC_TYPES_H */ -diff -purNx .git BPI-Router-Linux-kernel/tools/arch/x86/include/asm/amd/ibs.h BPI-Router-Linux-kernel-6.16.12/tools/arch/x86/include/asm/amd/ibs.h ---- BPI-Router-Linux-kernel/tools/arch/x86/include/asm/amd/ibs.h 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/arch/x86/include/asm/amd/ibs.h 2025-10-22 13:53:56.859167483 -0400 -@@ -1,4 +1,7 @@ - /* SPDX-License-Identifier: GPL-2.0 */ -+#ifndef _ASM_X86_AMD_IBS_H -+#define _ASM_X86_AMD_IBS_H -+ - /* - * From PPR Vol 1 for AMD Family 19h Model 01h B1 - * 55898 Rev 0.35 - Feb 5, 2021 -@@ -151,3 +154,5 @@ struct perf_ibs_data { - }; - u64 regs[MSR_AMD64_IBS_REG_COUNT_MAX]; - }; -+ -+#endif /* _ASM_X86_AMD_IBS_H */ -diff -purNx .git BPI-Router-Linux-kernel/tools/arch/x86/include/asm/cpufeatures.h BPI-Router-Linux-kernel-6.16.12/tools/arch/x86/include/asm/cpufeatures.h ---- BPI-Router-Linux-kernel/tools/arch/x86/include/asm/cpufeatures.h 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/arch/x86/include/asm/cpufeatures.h 2025-10-22 13:53:56.859167483 -0400 -@@ -336,7 +336,7 @@ - #define X86_FEATURE_AMD_IBRS (13*32+14) /* Indirect Branch Restricted Speculation */ - #define X86_FEATURE_AMD_STIBP (13*32+15) /* Single Thread Indirect Branch Predictors */ - #define X86_FEATURE_AMD_STIBP_ALWAYS_ON (13*32+17) /* Single Thread Indirect Branch Predictors always-on preferred */ --#define X86_FEATURE_AMD_IBRS_SAME_MODE (13*32+19) /* Indirect Branch Restricted Speculation same mode protection*/ -+#define X86_FEATURE_AMD_IBRS_SAME_MODE (13*32+19) /* Indirect Branch Restricted Speculation same mode protection*/ - #define X86_FEATURE_AMD_PPIN (13*32+23) /* "amd_ppin" Protected Processor Inventory Number */ - #define X86_FEATURE_AMD_SSBD (13*32+24) /* Speculative Store Bypass Disable */ - #define X86_FEATURE_VIRT_SSBD (13*32+25) /* "virt_ssbd" Virtualized Speculative Store Bypass Disable */ -@@ -379,6 +379,7 @@ - #define X86_FEATURE_V_SPEC_CTRL (15*32+20) /* "v_spec_ctrl" Virtual SPEC_CTRL */ - #define X86_FEATURE_VNMI (15*32+25) /* "vnmi" Virtual NMI */ - #define X86_FEATURE_SVME_ADDR_CHK (15*32+28) /* SVME addr check */ -+#define X86_FEATURE_BUS_LOCK_THRESHOLD (15*32+29) /* Bus lock threshold */ - #define X86_FEATURE_IDLE_HLT (15*32+30) /* IDLE HLT intercept */ - - /* Intel-defined CPU features, CPUID level 0x00000007:0 (ECX), word 16 */ -@@ -447,6 +448,7 @@ - #define X86_FEATURE_DEBUG_SWAP (19*32+14) /* "debug_swap" SEV-ES full debug state swap support */ - #define X86_FEATURE_RMPREAD (19*32+21) /* RMPREAD instruction */ - #define X86_FEATURE_SEGMENTED_RMP (19*32+23) /* Segmented RMP support */ -+#define X86_FEATURE_ALLOWED_SEV_FEATURES (19*32+27) /* Allowed SEV Features */ - #define X86_FEATURE_SVSM (19*32+28) /* "svsm" SVSM present */ - #define X86_FEATURE_HV_INUSE_WR_ALLOWED (19*32+30) /* Allow Write to in-use hypervisor-owned pages */ - -@@ -458,6 +460,7 @@ - #define X86_FEATURE_AUTOIBRS (20*32+ 8) /* Automatic IBRS */ - #define X86_FEATURE_NO_SMM_CTL_MSR (20*32+ 9) /* SMM_CTL MSR is not present */ - -+#define X86_FEATURE_PREFETCHI (20*32+20) /* Prefetch Data/Instruction to Cache Level */ - #define X86_FEATURE_SBPB (20*32+27) /* Selective Branch Prediction Barrier */ - #define X86_FEATURE_IBPB_BRTYPE (20*32+28) /* MSR_PRED_CMD[IBPB] flushes all branch type predictions */ - #define X86_FEATURE_SRSO_NO (20*32+29) /* CPU is not affected by SRSO */ -@@ -482,7 +485,8 @@ - #define X86_FEATURE_AMD_HTR_CORES (21*32+ 6) /* Heterogeneous Core Topology */ - #define X86_FEATURE_AMD_WORKLOAD_CLASS (21*32+ 7) /* Workload Classification */ - #define X86_FEATURE_PREFER_YMM (21*32+ 8) /* Avoid ZMM registers due to downclocking */ --#define X86_FEATURE_INDIRECT_THUNK_ITS (21*32+ 9) /* Use thunk for indirect branches in lower half of cacheline */ -+#define X86_FEATURE_APX (21*32+ 9) /* Advanced Performance Extensions */ -+#define X86_FEATURE_INDIRECT_THUNK_ITS (21*32+10) /* Use thunk for indirect branches in lower half of cacheline */ - - /* - * BUG word(s) -@@ -535,6 +539,8 @@ - #define X86_BUG_BHI X86_BUG( 1*32+ 3) /* "bhi" CPU is affected by Branch History Injection */ - #define X86_BUG_IBPB_NO_RET X86_BUG( 1*32+ 4) /* "ibpb_no_ret" IBPB omits return target predictions */ - #define X86_BUG_SPECTRE_V2_USER X86_BUG( 1*32+ 5) /* "spectre_v2_user" CPU is affected by Spectre variant 2 attack between user processes */ --#define X86_BUG_ITS X86_BUG( 1*32+ 6) /* "its" CPU is affected by Indirect Target Selection */ --#define X86_BUG_ITS_NATIVE_ONLY X86_BUG( 1*32+ 7) /* "its_native_only" CPU is affected by ITS, VMX is not affected */ -+#define X86_BUG_OLD_MICROCODE X86_BUG( 1*32+ 6) /* "old_microcode" CPU has old microcode, it is surely vulnerable to something */ -+#define X86_BUG_ITS X86_BUG( 1*32+ 7) /* "its" CPU is affected by Indirect Target Selection */ -+#define X86_BUG_ITS_NATIVE_ONLY X86_BUG( 1*32+ 8) /* "its_native_only" CPU is affected by ITS, VMX is not affected */ -+ - #endif /* _ASM_X86_CPUFEATURES_H */ -diff -purNx .git BPI-Router-Linux-kernel/tools/arch/x86/include/asm/msr-index.h BPI-Router-Linux-kernel-6.16.12/tools/arch/x86/include/asm/msr-index.h ---- BPI-Router-Linux-kernel/tools/arch/x86/include/asm/msr-index.h 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/arch/x86/include/asm/msr-index.h 2025-10-22 13:53:56.859167483 -0400 -@@ -533,7 +533,7 @@ - #define MSR_HWP_CAPABILITIES 0x00000771 - #define MSR_HWP_REQUEST_PKG 0x00000772 - #define MSR_HWP_INTERRUPT 0x00000773 --#define MSR_HWP_REQUEST 0x00000774 -+#define MSR_HWP_REQUEST 0x00000774 - #define MSR_HWP_STATUS 0x00000777 - - /* CPUID.6.EAX */ -@@ -550,16 +550,16 @@ - #define HWP_LOWEST_PERF(x) (((x) >> 24) & 0xff) - - /* IA32_HWP_REQUEST */ --#define HWP_MIN_PERF(x) (x & 0xff) --#define HWP_MAX_PERF(x) ((x & 0xff) << 8) -+#define HWP_MIN_PERF(x) (x & 0xff) -+#define HWP_MAX_PERF(x) ((x & 0xff) << 8) - #define HWP_DESIRED_PERF(x) ((x & 0xff) << 16) --#define HWP_ENERGY_PERF_PREFERENCE(x) (((unsigned long long) x & 0xff) << 24) -+#define HWP_ENERGY_PERF_PREFERENCE(x) (((u64)x & 0xff) << 24) - #define HWP_EPP_PERFORMANCE 0x00 - #define HWP_EPP_BALANCE_PERFORMANCE 0x80 - #define HWP_EPP_BALANCE_POWERSAVE 0xC0 - #define HWP_EPP_POWERSAVE 0xFF --#define HWP_ACTIVITY_WINDOW(x) ((unsigned long long)(x & 0xff3) << 32) --#define HWP_PACKAGE_CONTROL(x) ((unsigned long long)(x & 0x1) << 42) -+#define HWP_ACTIVITY_WINDOW(x) ((u64)(x & 0xff3) << 32) -+#define HWP_PACKAGE_CONTROL(x) ((u64)(x & 0x1) << 42) - - /* IA32_HWP_STATUS */ - #define HWP_GUARANTEED_CHANGE(x) (x & 0x1) -@@ -602,7 +602,11 @@ - /* V6 PMON MSR range */ - #define MSR_IA32_PMC_V6_GP0_CTR 0x1900 - #define MSR_IA32_PMC_V6_GP0_CFG_A 0x1901 -+#define MSR_IA32_PMC_V6_GP0_CFG_B 0x1902 -+#define MSR_IA32_PMC_V6_GP0_CFG_C 0x1903 - #define MSR_IA32_PMC_V6_FX0_CTR 0x1980 -+#define MSR_IA32_PMC_V6_FX0_CFG_B 0x1982 -+#define MSR_IA32_PMC_V6_FX0_CFG_C 0x1983 - #define MSR_IA32_PMC_V6_STEP 4 - - /* KeyID partitioning between MKTME and TDX */ -@@ -624,6 +628,7 @@ - #define MSR_AMD64_OSVW_STATUS 0xc0010141 - #define MSR_AMD_PPIN_CTL 0xc00102f0 - #define MSR_AMD_PPIN 0xc00102f1 -+#define MSR_AMD64_CPUID_FN_7 0xc0011002 - #define MSR_AMD64_CPUID_FN_1 0xc0011004 - #define MSR_AMD64_LS_CFG 0xc0011020 - #define MSR_AMD64_DC_CFG 0xc0011022 -diff -purNx .git BPI-Router-Linux-kernel/tools/arch/x86/include/uapi/asm/kvm.h BPI-Router-Linux-kernel-6.16.12/tools/arch/x86/include/uapi/asm/kvm.h ---- BPI-Router-Linux-kernel/tools/arch/x86/include/uapi/asm/kvm.h 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/arch/x86/include/uapi/asm/kvm.h 2025-10-22 13:53:56.859167483 -0400 -@@ -441,6 +441,7 @@ struct kvm_sync_regs { - #define KVM_X86_QUIRK_MWAIT_NEVER_UD_FAULTS (1 << 6) - #define KVM_X86_QUIRK_SLOT_ZAP_ALL (1 << 7) - #define KVM_X86_QUIRK_STUFF_FEATURE_MSRS (1 << 8) -+#define KVM_X86_QUIRK_IGNORE_GUEST_PAT (1 << 9) - - #define KVM_STATE_NESTED_FORMAT_VMX 0 - #define KVM_STATE_NESTED_FORMAT_SVM 1 -@@ -931,4 +932,74 @@ struct kvm_hyperv_eventfd { - #define KVM_X86_SNP_VM 4 - #define KVM_X86_TDX_VM 5 - -+/* Trust Domain eXtension sub-ioctl() commands. */ -+enum kvm_tdx_cmd_id { -+ KVM_TDX_CAPABILITIES = 0, -+ KVM_TDX_INIT_VM, -+ KVM_TDX_INIT_VCPU, -+ KVM_TDX_INIT_MEM_REGION, -+ KVM_TDX_FINALIZE_VM, -+ KVM_TDX_GET_CPUID, -+ -+ KVM_TDX_CMD_NR_MAX, -+}; -+ -+struct kvm_tdx_cmd { -+ /* enum kvm_tdx_cmd_id */ -+ __u32 id; -+ /* flags for sub-commend. If sub-command doesn't use this, set zero. */ -+ __u32 flags; -+ /* -+ * data for each sub-command. An immediate or a pointer to the actual -+ * data in process virtual address. If sub-command doesn't use it, -+ * set zero. -+ */ -+ __u64 data; -+ /* -+ * Auxiliary error code. The sub-command may return TDX SEAMCALL -+ * status code in addition to -Exxx. -+ */ -+ __u64 hw_error; -+}; -+ -+struct kvm_tdx_capabilities { -+ __u64 supported_attrs; -+ __u64 supported_xfam; -+ __u64 reserved[254]; -+ -+ /* Configurable CPUID bits for userspace */ -+ struct kvm_cpuid2 cpuid; -+}; -+ -+struct kvm_tdx_init_vm { -+ __u64 attributes; -+ __u64 xfam; -+ __u64 mrconfigid[6]; /* sha384 digest */ -+ __u64 mrowner[6]; /* sha384 digest */ -+ __u64 mrownerconfig[6]; /* sha384 digest */ -+ -+ /* The total space for TD_PARAMS before the CPUIDs is 256 bytes */ -+ __u64 reserved[12]; -+ -+ /* -+ * Call KVM_TDX_INIT_VM before vcpu creation, thus before -+ * KVM_SET_CPUID2. -+ * This configuration supersedes KVM_SET_CPUID2s for VCPUs because the -+ * TDX module directly virtualizes those CPUIDs without VMM. The user -+ * space VMM, e.g. qemu, should make KVM_SET_CPUID2 consistent with -+ * those values. If it doesn't, KVM may have wrong idea of vCPUIDs of -+ * the guest, and KVM may wrongly emulate CPUIDs or MSRs that the TDX -+ * module doesn't virtualize. -+ */ -+ struct kvm_cpuid2 cpuid; -+}; -+ -+#define KVM_TDX_MEASURE_MEMORY_REGION _BITULL(0) -+ -+struct kvm_tdx_init_mem_region { -+ __u64 source_addr; -+ __u64 gpa; -+ __u64 nr_pages; -+}; -+ - #endif /* _ASM_X86_KVM_H */ -diff -purNx .git BPI-Router-Linux-kernel/tools/arch/x86/include/uapi/asm/svm.h BPI-Router-Linux-kernel-6.16.12/tools/arch/x86/include/uapi/asm/svm.h ---- BPI-Router-Linux-kernel/tools/arch/x86/include/uapi/asm/svm.h 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/arch/x86/include/uapi/asm/svm.h 2025-10-22 13:53:56.859167483 -0400 -@@ -95,6 +95,7 @@ - #define SVM_EXIT_CR14_WRITE_TRAP 0x09e - #define SVM_EXIT_CR15_WRITE_TRAP 0x09f - #define SVM_EXIT_INVPCID 0x0a2 -+#define SVM_EXIT_BUS_LOCK 0x0a5 - #define SVM_EXIT_IDLE_HLT 0x0a6 - #define SVM_EXIT_NPF 0x400 - #define SVM_EXIT_AVIC_INCOMPLETE_IPI 0x401 -@@ -225,6 +226,7 @@ - { SVM_EXIT_CR4_WRITE_TRAP, "write_cr4_trap" }, \ - { SVM_EXIT_CR8_WRITE_TRAP, "write_cr8_trap" }, \ - { SVM_EXIT_INVPCID, "invpcid" }, \ -+ { SVM_EXIT_BUS_LOCK, "buslock" }, \ - { SVM_EXIT_IDLE_HLT, "idle-halt" }, \ - { SVM_EXIT_NPF, "npf" }, \ - { SVM_EXIT_AVIC_INCOMPLETE_IPI, "avic_incomplete_ipi" }, \ -diff -purNx .git BPI-Router-Linux-kernel/tools/arch/x86/include/uapi/asm/vmx.h BPI-Router-Linux-kernel-6.16.12/tools/arch/x86/include/uapi/asm/vmx.h ---- BPI-Router-Linux-kernel/tools/arch/x86/include/uapi/asm/vmx.h 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/arch/x86/include/uapi/asm/vmx.h 2025-10-22 13:53:56.859167483 -0400 -@@ -34,6 +34,7 @@ - #define EXIT_REASON_TRIPLE_FAULT 2 - #define EXIT_REASON_INIT_SIGNAL 3 - #define EXIT_REASON_SIPI_SIGNAL 4 -+#define EXIT_REASON_OTHER_SMI 6 - - #define EXIT_REASON_INTERRUPT_WINDOW 7 - #define EXIT_REASON_NMI_WINDOW 8 -@@ -92,6 +93,7 @@ - #define EXIT_REASON_TPAUSE 68 - #define EXIT_REASON_BUS_LOCK 74 - #define EXIT_REASON_NOTIFY 75 -+#define EXIT_REASON_TDCALL 77 - - #define VMX_EXIT_REASONS \ - { EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \ -@@ -155,7 +157,8 @@ - { EXIT_REASON_UMWAIT, "UMWAIT" }, \ - { EXIT_REASON_TPAUSE, "TPAUSE" }, \ - { EXIT_REASON_BUS_LOCK, "BUS_LOCK" }, \ -- { EXIT_REASON_NOTIFY, "NOTIFY" } -+ { EXIT_REASON_NOTIFY, "NOTIFY" }, \ -+ { EXIT_REASON_TDCALL, "TDCALL" } - - #define VMX_EXIT_REASON_FLAGS \ - { VMX_EXIT_REASONS_FAILED_VMENTRY, "FAILED_VMENTRY" } -diff -purNx .git BPI-Router-Linux-kernel/tools/arch/x86/lib/memcpy_64.S BPI-Router-Linux-kernel-6.16.12/tools/arch/x86/lib/memcpy_64.S ---- BPI-Router-Linux-kernel/tools/arch/x86/lib/memcpy_64.S 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/arch/x86/lib/memcpy_64.S 2025-10-22 13:53:56.859167483 -0400 -@@ -40,6 +40,7 @@ SYM_FUNC_END(__memcpy) - EXPORT_SYMBOL(__memcpy) - - SYM_FUNC_ALIAS_MEMFUNC(memcpy, __memcpy) -+SYM_PIC_ALIAS(memcpy) - EXPORT_SYMBOL(memcpy) - - SYM_FUNC_START_LOCAL(memcpy_orig) -diff -purNx .git BPI-Router-Linux-kernel/tools/arch/x86/lib/memset_64.S BPI-Router-Linux-kernel-6.16.12/tools/arch/x86/lib/memset_64.S ---- BPI-Router-Linux-kernel/tools/arch/x86/lib/memset_64.S 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/arch/x86/lib/memset_64.S 2025-10-22 13:53:56.859167483 -0400 -@@ -42,6 +42,7 @@ SYM_FUNC_END(__memset) - EXPORT_SYMBOL(__memset) - - SYM_FUNC_ALIAS_MEMFUNC(memset, __memset) -+SYM_PIC_ALIAS(memset) - EXPORT_SYMBOL(memset) - - SYM_FUNC_START_LOCAL(memset_orig) -diff -purNx .git BPI-Router-Linux-kernel/tools/bpf/bpftool/main.c BPI-Router-Linux-kernel-6.16.12/tools/bpf/bpftool/main.c ---- BPI-Router-Linux-kernel/tools/bpf/bpftool/main.c 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/bpf/bpftool/main.c 2025-10-22 13:53:56.859167483 -0400 -@@ -534,9 +534,9 @@ int main(int argc, char **argv) - usage(); - - if (version_requested) -- return do_version(argc, argv); -- -- ret = cmd_select(commands, argc, argv, do_help); -+ ret = do_version(argc, argv); -+ else -+ ret = cmd_select(commands, argc, argv, do_help); - - if (json_output) - jsonw_destroy(&json_wtr); -diff -purNx .git BPI-Router-Linux-kernel/tools/bpf/bpftool/net.c BPI-Router-Linux-kernel-6.16.12/tools/bpf/bpftool/net.c ---- BPI-Router-Linux-kernel/tools/bpf/bpftool/net.c 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/bpf/bpftool/net.c 2025-10-22 13:53:56.859167483 -0400 -@@ -366,17 +366,18 @@ static int dump_link_nlmsg(void *cookie, - { - struct bpf_netdev_t *netinfo = cookie; - struct ifinfomsg *ifinfo = msg; -+ struct ip_devname_ifindex *tmp; - - if (netinfo->filter_idx > 0 && netinfo->filter_idx != ifinfo->ifi_index) - return 0; - - if (netinfo->used_len == netinfo->array_len) { -- netinfo->devices = realloc(netinfo->devices, -- (netinfo->array_len + 16) * -- sizeof(struct ip_devname_ifindex)); -- if (!netinfo->devices) -+ tmp = realloc(netinfo->devices, -+ (netinfo->array_len + 16) * sizeof(struct ip_devname_ifindex)); -+ if (!tmp) - return -ENOMEM; - -+ netinfo->devices = tmp; - netinfo->array_len += 16; - } - netinfo->devices[netinfo->used_len].ifindex = ifinfo->ifi_index; -@@ -395,6 +396,7 @@ static int dump_class_qdisc_nlmsg(void * - { - struct bpf_tcinfo_t *tcinfo = cookie; - struct tcmsg *info = msg; -+ struct tc_kind_handle *tmp; - - if (tcinfo->is_qdisc) { - /* skip clsact qdisc */ -@@ -406,11 +408,12 @@ static int dump_class_qdisc_nlmsg(void * - } - - if (tcinfo->used_len == tcinfo->array_len) { -- tcinfo->handle_array = realloc(tcinfo->handle_array, -+ tmp = realloc(tcinfo->handle_array, - (tcinfo->array_len + 16) * sizeof(struct tc_kind_handle)); -- if (!tcinfo->handle_array) -+ if (!tmp) - return -ENOMEM; - -+ tcinfo->handle_array = tmp; - tcinfo->array_len += 16; - } - tcinfo->handle_array[tcinfo->used_len].handle = info->tcm_handle; -diff -purNx .git BPI-Router-Linux-kernel/tools/bpf/resolve_btfids/Makefile BPI-Router-Linux-kernel-6.16.12/tools/bpf/resolve_btfids/Makefile ---- BPI-Router-Linux-kernel/tools/bpf/resolve_btfids/Makefile 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/bpf/resolve_btfids/Makefile 2025-10-22 13:53:56.859167483 -0400 -@@ -17,7 +17,7 @@ endif - - # Overrides for the prepare step libraries. - HOST_OVERRIDES := AR="$(HOSTAR)" CC="$(HOSTCC)" LD="$(HOSTLD)" ARCH="$(HOSTARCH)" \ -- CROSS_COMPILE="" EXTRA_CFLAGS="$(HOSTCFLAGS)" -+ CROSS_COMPILE="" CLANG_CROSS_FLAGS="" EXTRA_CFLAGS="$(HOSTCFLAGS)" - - RM ?= rm - HOSTCC ?= gcc -diff -purNx .git BPI-Router-Linux-kernel/tools/cgroup/memcg_slabinfo.py BPI-Router-Linux-kernel-6.16.12/tools/cgroup/memcg_slabinfo.py ---- BPI-Router-Linux-kernel/tools/cgroup/memcg_slabinfo.py 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/cgroup/memcg_slabinfo.py 2025-10-22 13:53:56.859167483 -0400 -@@ -146,11 +146,11 @@ def detect_kernel_config(): - - - def for_each_slab(prog): -- PGSlab = ~prog.constant('PG_slab') -+ slabtype = prog.constant('PGTY_slab') - - for page in for_each_page(prog): - try: -- if page.page_type.value_() == PGSlab: -+ if (page.page_type.value_() >> 24) == slabtype: - yield cast('struct slab *', page) - except FaultError: - pass -diff -purNx .git BPI-Router-Linux-kernel/tools/gpio/Makefile BPI-Router-Linux-kernel-6.16.12/tools/gpio/Makefile ---- BPI-Router-Linux-kernel/tools/gpio/Makefile 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/gpio/Makefile 2025-10-22 13:53:56.859167483 -0400 -@@ -77,7 +77,7 @@ $(OUTPUT)gpio-watch: $(GPIO_WATCH_IN) - - clean: - rm -f $(ALL_PROGRAMS) -- rm -f $(OUTPUT)include/linux/gpio.h -+ rm -rf $(OUTPUT)include - find $(or $(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete -o -name '\.*.cmd' -delete - - install: $(ALL_PROGRAMS) -diff -purNx .git BPI-Router-Linux-kernel/tools/hv/hv_fcopy_uio_daemon.c BPI-Router-Linux-kernel-6.16.12/tools/hv/hv_fcopy_uio_daemon.c ---- BPI-Router-Linux-kernel/tools/hv/hv_fcopy_uio_daemon.c 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/hv/hv_fcopy_uio_daemon.c 2025-10-22 13:53:56.859167483 -0400 -@@ -35,7 +35,10 @@ - #define WIN8_SRV_MINOR 1 - #define WIN8_SRV_VERSION (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR) - --#define FCOPY_UIO "/sys/bus/vmbus/devices/eb765408-105f-49b6-b4aa-c123b64d17d4/uio" -+#define FCOPY_DEVICE_PATH(subdir) \ -+ "/sys/bus/vmbus/devices/eb765408-105f-49b6-b4aa-c123b64d17d4/" #subdir -+#define FCOPY_UIO_PATH FCOPY_DEVICE_PATH(uio) -+#define FCOPY_CHANNELS_PATH FCOPY_DEVICE_PATH(channels) - - #define FCOPY_VER_COUNT 1 - static const int fcopy_versions[] = { -@@ -47,9 +50,62 @@ static const int fw_versions[] = { - UTIL_FW_VERSION - }; - --#define HV_RING_SIZE 0x4000 /* 16KB ring buffer size */ -+static uint32_t get_ring_buffer_size(void) -+{ -+ char ring_path[PATH_MAX]; -+ DIR *dir; -+ struct dirent *entry; -+ struct stat st; -+ uint32_t ring_size = 0; -+ int retry_count = 0; -+ -+ /* Find the channel directory */ -+ dir = opendir(FCOPY_CHANNELS_PATH); -+ if (!dir) { -+ usleep(100 * 1000); /* Avoid race with kernel, wait 100ms and retry once */ -+ dir = opendir(FCOPY_CHANNELS_PATH); -+ if (!dir) { -+ syslog(LOG_ERR, "Failed to open channels directory: %s", strerror(errno)); -+ return 0; -+ } -+ } -+ -+retry_once: -+ while ((entry = readdir(dir)) != NULL) { -+ if (entry->d_type == DT_DIR && strcmp(entry->d_name, ".") != 0 && -+ strcmp(entry->d_name, "..") != 0) { -+ snprintf(ring_path, sizeof(ring_path), "%s/%s/ring", -+ FCOPY_CHANNELS_PATH, entry->d_name); -+ -+ if (stat(ring_path, &st) == 0) { -+ /* -+ * stat returns size of Tx, Rx rings combined, -+ * so take half of it for individual ring size. -+ */ -+ ring_size = (uint32_t)st.st_size / 2; -+ syslog(LOG_INFO, "Ring buffer size from %s: %u bytes", -+ ring_path, ring_size); -+ break; -+ } -+ } -+ } -+ -+ if (!ring_size && retry_count == 0) { -+ retry_count = 1; -+ rewinddir(dir); -+ usleep(100 * 1000); /* Wait 100ms and retry once */ -+ goto retry_once; -+ } -+ -+ closedir(dir); -+ -+ if (!ring_size) -+ syslog(LOG_ERR, "Could not determine ring size"); - --static unsigned char desc[HV_RING_SIZE]; -+ return ring_size; -+} -+ -+static unsigned char *desc; - - static int target_fd; - static char target_fname[PATH_MAX]; -@@ -62,8 +118,11 @@ static int hv_fcopy_create_file(char *fi - - filesize = 0; - p = path_name; -- snprintf(target_fname, sizeof(target_fname), "%s/%s", -- path_name, file_name); -+ if (snprintf(target_fname, sizeof(target_fname), "%s/%s", -+ path_name, file_name) >= sizeof(target_fname)) { -+ syslog(LOG_ERR, "target file name is too long: %s/%s", path_name, file_name); -+ goto done; -+ } - - /* - * Check to see if the path is already in place; if not, -@@ -270,7 +329,7 @@ static void wcstoutf8(char *dest, const - { - size_t len = 0; - -- while (len < dest_size) { -+ while (len < dest_size && *src) { - if (src[len] < 0x80) - dest[len++] = (char)(*src++); - else -@@ -282,27 +341,15 @@ static void wcstoutf8(char *dest, const - - static int hv_fcopy_start(struct hv_start_fcopy *smsg_in) - { -- setlocale(LC_ALL, "en_US.utf8"); -- size_t file_size, path_size; -- char *file_name, *path_name; -- char *in_file_name = (char *)smsg_in->file_name; -- char *in_path_name = (char *)smsg_in->path_name; -- -- file_size = wcstombs(NULL, (const wchar_t *restrict)in_file_name, 0) + 1; -- path_size = wcstombs(NULL, (const wchar_t *restrict)in_path_name, 0) + 1; -- -- file_name = (char *)malloc(file_size * sizeof(char)); -- path_name = (char *)malloc(path_size * sizeof(char)); -- -- if (!file_name || !path_name) { -- free(file_name); -- free(path_name); -- syslog(LOG_ERR, "Can't allocate memory for file name and/or path name"); -- return HV_E_FAIL; -- } -+ /* -+ * file_name and path_name should have same length with appropriate -+ * member of hv_start_fcopy. -+ */ -+ char file_name[W_MAX_PATH], path_name[W_MAX_PATH]; - -- wcstoutf8(file_name, (__u16 *)in_file_name, file_size); -- wcstoutf8(path_name, (__u16 *)in_path_name, path_size); -+ setlocale(LC_ALL, "en_US.utf8"); -+ wcstoutf8(file_name, smsg_in->file_name, W_MAX_PATH - 1); -+ wcstoutf8(path_name, smsg_in->path_name, W_MAX_PATH - 1); - - return hv_fcopy_create_file(file_name, path_name, smsg_in->copy_flags); - } -@@ -406,7 +453,7 @@ int main(int argc, char *argv[]) - int daemonize = 1, long_index = 0, opt, ret = -EINVAL; - struct vmbus_br txbr, rxbr; - void *ring; -- uint32_t len = HV_RING_SIZE; -+ uint32_t ring_size, len; - char uio_name[NAME_MAX] = {0}; - char uio_dev_path[PATH_MAX] = {0}; - -@@ -437,7 +484,20 @@ int main(int argc, char *argv[]) - openlog("HV_UIO_FCOPY", 0, LOG_USER); - syslog(LOG_INFO, "starting; pid is:%d", getpid()); - -- fcopy_get_first_folder(FCOPY_UIO, uio_name); -+ ring_size = get_ring_buffer_size(); -+ if (!ring_size) { -+ ret = -ENODEV; -+ goto exit; -+ } -+ -+ desc = malloc(ring_size * sizeof(unsigned char)); -+ if (!desc) { -+ syslog(LOG_ERR, "malloc failed for desc buffer"); -+ ret = -ENOMEM; -+ goto exit; -+ } -+ -+ fcopy_get_first_folder(FCOPY_UIO_PATH, uio_name); - snprintf(uio_dev_path, sizeof(uio_dev_path), "/dev/%s", uio_name); - fcopy_fd = open(uio_dev_path, O_RDWR); - -@@ -445,17 +505,17 @@ int main(int argc, char *argv[]) - syslog(LOG_ERR, "open %s failed; error: %d %s", - uio_dev_path, errno, strerror(errno)); - ret = fcopy_fd; -- goto exit; -+ goto free_desc; - } - -- ring = vmbus_uio_map(&fcopy_fd, HV_RING_SIZE); -+ ring = vmbus_uio_map(&fcopy_fd, ring_size); - if (!ring) { - ret = errno; - syslog(LOG_ERR, "mmap ringbuffer failed; error: %d %s", ret, strerror(ret)); - goto close; - } -- vmbus_br_setup(&txbr, ring, HV_RING_SIZE); -- vmbus_br_setup(&rxbr, (char *)ring + HV_RING_SIZE, HV_RING_SIZE); -+ vmbus_br_setup(&txbr, ring, ring_size); -+ vmbus_br_setup(&rxbr, (char *)ring + ring_size, ring_size); - - rxbr.vbr->imask = 0; - -@@ -472,7 +532,7 @@ int main(int argc, char *argv[]) - goto close; - } - -- len = HV_RING_SIZE; -+ len = ring_size; - ret = rte_vmbus_chan_recv_raw(&rxbr, desc, &len); - if (unlikely(ret <= 0)) { - /* This indicates a failure to communicate (or worse) */ -@@ -492,6 +552,8 @@ int main(int argc, char *argv[]) - } - close: - close(fcopy_fd); -+free_desc: -+ free(desc); - exit: - return ret; - } -diff -purNx .git BPI-Router-Linux-kernel/tools/include/linux/bits.h BPI-Router-Linux-kernel-6.16.12/tools/include/linux/bits.h ---- BPI-Router-Linux-kernel/tools/include/linux/bits.h 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/include/linux/bits.h 2025-10-22 13:53:56.859167483 -0400 -@@ -12,6 +12,7 @@ - #define BIT_ULL_MASK(nr) (ULL(1) << ((nr) % BITS_PER_LONG_LONG)) - #define BIT_ULL_WORD(nr) ((nr) / BITS_PER_LONG_LONG) - #define BITS_PER_BYTE 8 -+#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE) - - /* - * Create a contiguous bitmask starting at bit position @l and ending at -@@ -19,16 +20,68 @@ - * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000. - */ - #if !defined(__ASSEMBLY__) -+ -+/* -+ * Missing asm support -+ * -+ * GENMASK_U*() and BIT_U*() depend on BITS_PER_TYPE() which relies on sizeof(), -+ * something not available in asm. Nevertheless, fixed width integers is a C -+ * concept. Assembly code can rely on the long and long long versions instead. -+ */ -+ - #include - #include -+#include -+ - #define GENMASK_INPUT_CHECK(h, l) BUILD_BUG_ON_ZERO(const_true((l) > (h))) --#else -+ -+/* -+ * Generate a mask for the specified type @t. Additional checks are made to -+ * guarantee the value returned fits in that type, relying on -+ * -Wshift-count-overflow compiler check to detect incompatible arguments. -+ * For example, all these create build errors or warnings: -+ * -+ * - GENMASK(15, 20): wrong argument order -+ * - GENMASK(72, 15): doesn't fit unsigned long -+ * - GENMASK_U32(33, 15): doesn't fit in a u32 -+ */ -+#define GENMASK_TYPE(t, h, l) \ -+ ((t)(GENMASK_INPUT_CHECK(h, l) + \ -+ (type_max(t) << (l) & \ -+ type_max(t) >> (BITS_PER_TYPE(t) - 1 - (h))))) -+ -+#define GENMASK_U8(h, l) GENMASK_TYPE(u8, h, l) -+#define GENMASK_U16(h, l) GENMASK_TYPE(u16, h, l) -+#define GENMASK_U32(h, l) GENMASK_TYPE(u32, h, l) -+#define GENMASK_U64(h, l) GENMASK_TYPE(u64, h, l) -+ -+/* -+ * Fixed-type variants of BIT(), with additional checks like GENMASK_TYPE(). The -+ * following examples generate compiler warnings due to -Wshift-count-overflow: -+ * -+ * - BIT_U8(8) -+ * - BIT_U32(-1) -+ * - BIT_U32(40) -+ */ -+#define BIT_INPUT_CHECK(type, nr) \ -+ BUILD_BUG_ON_ZERO(const_true((nr) >= BITS_PER_TYPE(type))) -+ -+#define BIT_TYPE(type, nr) ((type)(BIT_INPUT_CHECK(type, nr) + BIT_ULL(nr))) -+ -+#define BIT_U8(nr) BIT_TYPE(u8, nr) -+#define BIT_U16(nr) BIT_TYPE(u16, nr) -+#define BIT_U32(nr) BIT_TYPE(u32, nr) -+#define BIT_U64(nr) BIT_TYPE(u64, nr) -+ -+#else /* defined(__ASSEMBLY__) */ -+ - /* - * BUILD_BUG_ON_ZERO is not available in h files included from asm files, - * disable the input check if that is the case. - */ - #define GENMASK_INPUT_CHECK(h, l) 0 --#endif -+ -+#endif /* !defined(__ASSEMBLY__) */ - - #define GENMASK(h, l) \ - (GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l)) -diff -purNx .git BPI-Router-Linux-kernel/tools/include/linux/build_bug.h BPI-Router-Linux-kernel-6.16.12/tools/include/linux/build_bug.h ---- BPI-Router-Linux-kernel/tools/include/linux/build_bug.h 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/include/linux/build_bug.h 2025-10-22 13:53:56.859167483 -0400 -@@ -4,17 +4,17 @@ - - #include - --#ifdef __CHECKER__ --#define BUILD_BUG_ON_ZERO(e) (0) --#else /* __CHECKER__ */ - /* - * Force a compilation error if condition is true, but also produce a - * result (of value 0 and type int), so the expression can be used - * e.g. in a structure initializer (or where-ever else comma expressions - * aren't permitted). -+ * -+ * Take an error message as an optional second argument. If omitted, -+ * default to the stringification of the tested expression. - */ --#define BUILD_BUG_ON_ZERO(e) ((int)(sizeof(struct { int:(-!!(e)); }))) --#endif /* __CHECKER__ */ -+#define BUILD_BUG_ON_ZERO(e, ...) \ -+ __BUILD_BUG_ON_ZERO_MSG(e, ##__VA_ARGS__, #e " is true") - - /* Force a compilation error if a constant expression is not a power of 2 */ - #define __BUILD_BUG_ON_NOT_POWER_OF_2(n) \ -diff -purNx .git BPI-Router-Linux-kernel/tools/include/linux/compiler.h BPI-Router-Linux-kernel-6.16.12/tools/include/linux/compiler.h ---- BPI-Router-Linux-kernel/tools/include/linux/compiler.h 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/include/linux/compiler.h 2025-10-22 13:53:56.859167483 -0400 -@@ -244,6 +244,14 @@ static __always_inline void __write_once - __asm__ ("" : "=r" (var) : "0" (var)) - #endif - -+#ifndef __BUILD_BUG_ON_ZERO_MSG -+#if defined(__clang__) -+#define __BUILD_BUG_ON_ZERO_MSG(e, msg, ...) ((int)(sizeof(struct { int:(-!!(e)); }))) -+#else -+#define __BUILD_BUG_ON_ZERO_MSG(e, msg, ...) ((int)sizeof(struct {_Static_assert(!(e), msg);})) -+#endif -+#endif -+ - #endif /* __ASSEMBLY__ */ - - #endif /* _TOOLS_LINUX_COMPILER_H */ -diff -purNx .git BPI-Router-Linux-kernel/tools/include/linux/kallsyms.h BPI-Router-Linux-kernel-6.16.12/tools/include/linux/kallsyms.h ---- BPI-Router-Linux-kernel/tools/include/linux/kallsyms.h 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/include/linux/kallsyms.h 2025-10-22 13:53:56.859167483 -0400 -@@ -18,6 +18,7 @@ static inline const char *kallsyms_looku - return NULL; - } - -+#ifdef HAVE_BACKTRACE_SUPPORT - #include - #include - static inline void print_ip_sym(const char *loglvl, unsigned long ip) -@@ -30,5 +31,8 @@ static inline void print_ip_sym(const ch - - free(name); - } -+#else -+static inline void print_ip_sym(const char *loglvl, unsigned long ip) {} -+#endif - - #endif -diff -purNx .git BPI-Router-Linux-kernel/tools/include/nolibc/std.h BPI-Router-Linux-kernel-6.16.12/tools/include/nolibc/std.h ---- BPI-Router-Linux-kernel/tools/include/nolibc/std.h 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/include/nolibc/std.h 2025-10-22 13:53:56.859167483 -0400 -@@ -16,6 +16,8 @@ - #include "stdint.h" - #include "stddef.h" - -+#include -+ - /* those are commonly provided by sys/types.h */ - typedef unsigned int dev_t; - typedef unsigned long ino_t; -@@ -27,6 +29,6 @@ typedef unsigned long nlink_t; - typedef signed long off_t; - typedef signed long blksize_t; - typedef signed long blkcnt_t; --typedef signed long time_t; -+typedef __kernel_old_time_t time_t; - - #endif /* _NOLIBC_STD_H */ -diff -purNx .git BPI-Router-Linux-kernel/tools/include/nolibc/stdio.h BPI-Router-Linux-kernel-6.16.12/tools/include/nolibc/stdio.h ---- BPI-Router-Linux-kernel/tools/include/nolibc/stdio.h 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/include/nolibc/stdio.h 2025-10-22 13:53:56.859167483 -0400 -@@ -358,11 +358,11 @@ int __nolibc_printf(__nolibc_printf_cb c - n -= w; - while (width-- > w) { - if (cb(state, " ", 1) != 0) -- break; -+ return -1; - written += 1; - } - if (cb(state, outstr, w) != 0) -- break; -+ return -1; - } - - written += len; -diff -purNx .git BPI-Router-Linux-kernel/tools/include/nolibc/sys/wait.h BPI-Router-Linux-kernel-6.16.12/tools/include/nolibc/sys/wait.h ---- BPI-Router-Linux-kernel/tools/include/nolibc/sys/wait.h 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/include/nolibc/sys/wait.h 2025-10-22 13:53:56.859167483 -0400 -@@ -78,7 +78,7 @@ pid_t waitpid(pid_t pid, int *status, in - - ret = waitid(idtype, id, &info, options); - if (ret) -- return ret; -+ return -1; - - switch (info.si_code) { - case 0: -diff -purNx .git BPI-Router-Linux-kernel/tools/include/nolibc/types.h BPI-Router-Linux-kernel-6.16.12/tools/include/nolibc/types.h ---- BPI-Router-Linux-kernel/tools/include/nolibc/types.h 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/include/nolibc/types.h 2025-10-22 13:53:56.859167483 -0400 -@@ -128,7 +128,7 @@ typedef struct { - int __fd = (fd); \ - if (__fd >= 0) \ - __set->fds[__fd / FD_SETIDXMASK] &= \ -- ~(1U << (__fd & FX_SETBITMASK)); \ -+ ~(1U << (__fd & FD_SETBITMASK)); \ - } while (0) - - #define FD_SET(fd, set) do { \ -@@ -145,7 +145,7 @@ typedef struct { - int __r = 0; \ - if (__fd >= 0) \ - __r = !!(__set->fds[__fd / FD_SETIDXMASK] & \ --1U << (__fd & FD_SET_BITMASK)); \ -+1U << (__fd & FD_SETBITMASK)); \ - __r; \ - }) - -diff -purNx .git BPI-Router-Linux-kernel/tools/include/uapi/drm/drm.h BPI-Router-Linux-kernel-6.16.12/tools/include/uapi/drm/drm.h ---- BPI-Router-Linux-kernel/tools/include/uapi/drm/drm.h 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/include/uapi/drm/drm.h 2025-10-22 13:53:56.859167483 -0400 -@@ -905,13 +905,17 @@ struct drm_syncobj_destroy { - }; - - #define DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE (1 << 0) -+#define DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_TIMELINE (1 << 1) - #define DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE (1 << 0) -+#define DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_TIMELINE (1 << 1) - struct drm_syncobj_handle { - __u32 handle; - __u32 flags; - - __s32 fd; - __u32 pad; -+ -+ __u64 point; - }; - - struct drm_syncobj_transfer { -diff -purNx .git BPI-Router-Linux-kernel/tools/include/uapi/linux/bits.h BPI-Router-Linux-kernel-6.16.12/tools/include/uapi/linux/bits.h ---- BPI-Router-Linux-kernel/tools/include/uapi/linux/bits.h 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/include/uapi/linux/bits.h 2025-10-22 13:53:56.863167463 -0400 -@@ -4,9 +4,9 @@ - #ifndef _UAPI_LINUX_BITS_H - #define _UAPI_LINUX_BITS_H - --#define __GENMASK(h, l) (((~_UL(0)) << (l)) & (~_UL(0) >> (BITS_PER_LONG - 1 - (h)))) -+#define __GENMASK(h, l) (((~_UL(0)) << (l)) & (~_UL(0) >> (__BITS_PER_LONG - 1 - (h)))) - --#define __GENMASK_ULL(h, l) (((~_ULL(0)) << (l)) & (~_ULL(0) >> (BITS_PER_LONG_LONG - 1 - (h)))) -+#define __GENMASK_ULL(h, l) (((~_ULL(0)) << (l)) & (~_ULL(0) >> (__BITS_PER_LONG_LONG - 1 - (h)))) - - #define __GENMASK_U128(h, l) \ - ((_BIT128((h)) << 1) - (_BIT128(l))) -diff -purNx .git BPI-Router-Linux-kernel/tools/include/uapi/linux/fscrypt.h BPI-Router-Linux-kernel-6.16.12/tools/include/uapi/linux/fscrypt.h ---- BPI-Router-Linux-kernel/tools/include/uapi/linux/fscrypt.h 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/include/uapi/linux/fscrypt.h 2025-10-22 13:53:56.863167463 -0400 -@@ -119,7 +119,7 @@ struct fscrypt_key_specifier { - */ - struct fscrypt_provisioning_key_payload { - __u32 type; -- __u32 __reserved; -+ __u32 flags; - __u8 raw[]; - }; - -@@ -128,7 +128,9 @@ struct fscrypt_add_key_arg { - struct fscrypt_key_specifier key_spec; - __u32 raw_size; - __u32 key_id; -- __u32 __reserved[8]; -+#define FSCRYPT_ADD_KEY_FLAG_HW_WRAPPED 0x00000001 -+ __u32 flags; -+ __u32 __reserved[7]; - __u8 raw[]; - }; - -diff -purNx .git BPI-Router-Linux-kernel/tools/include/uapi/linux/kvm.h BPI-Router-Linux-kernel-6.16.12/tools/include/uapi/linux/kvm.h ---- BPI-Router-Linux-kernel/tools/include/uapi/linux/kvm.h 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/include/uapi/linux/kvm.h 2025-10-22 13:53:56.863167463 -0400 -@@ -375,6 +375,7 @@ struct kvm_run { - #define KVM_SYSTEM_EVENT_WAKEUP 4 - #define KVM_SYSTEM_EVENT_SUSPEND 5 - #define KVM_SYSTEM_EVENT_SEV_TERM 6 -+#define KVM_SYSTEM_EVENT_TDX_FATAL 7 - __u32 type; - __u32 ndata; - union { -@@ -930,6 +931,9 @@ struct kvm_enable_cap { - #define KVM_CAP_X86_APIC_BUS_CYCLES_NS 237 - #define KVM_CAP_X86_GUEST_MODE 238 - #define KVM_CAP_ARM_WRITABLE_IMP_ID_REGS 239 -+#define KVM_CAP_ARM_EL2 240 -+#define KVM_CAP_ARM_EL2_E2H0 241 -+#define KVM_CAP_RISCV_MP_STATE_RESET 242 - - struct kvm_irq_routing_irqchip { - __u32 irqchip; -diff -purNx .git BPI-Router-Linux-kernel/tools/include/uapi/linux/stat.h BPI-Router-Linux-kernel-6.16.12/tools/include/uapi/linux/stat.h ---- BPI-Router-Linux-kernel/tools/include/uapi/linux/stat.h 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/include/uapi/linux/stat.h 2025-10-22 13:53:56.863167463 -0400 -@@ -182,8 +182,12 @@ struct statx { - /* File offset alignment for direct I/O reads */ - __u32 stx_dio_read_offset_align; - -- /* 0xb8 */ -- __u64 __spare3[9]; /* Spare space for future expansion */ -+ /* Optimised max atomic write unit in bytes */ -+ __u32 stx_atomic_write_unit_max_opt; -+ __u32 __spare2[1]; -+ -+ /* 0xc0 */ -+ __u64 __spare3[8]; /* Spare space for future expansion */ - - /* 0x100 */ - }; -diff -purNx .git BPI-Router-Linux-kernel/tools/lib/bpf/btf.c BPI-Router-Linux-kernel-6.16.12/tools/lib/bpf/btf.c ---- BPI-Router-Linux-kernel/tools/lib/bpf/btf.c 2025-10-22 13:53:23.687326866 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/lib/bpf/btf.c 2025-10-22 13:53:56.863167463 -0400 -@@ -1384,12 +1384,12 @@ static struct btf *btf_parse_raw_mmap(co - - fd = open(path, O_RDONLY); - if (fd < 0) -- return libbpf_err_ptr(-errno); -+ return ERR_PTR(-errno); - - if (fstat(fd, &st) < 0) { - err = -errno; - close(fd); -- return libbpf_err_ptr(err); -+ return ERR_PTR(err); - } - - data = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); -@@ -1397,7 +1397,7 @@ static struct btf *btf_parse_raw_mmap(co - close(fd); - - if (data == MAP_FAILED) -- return libbpf_err_ptr(err); -+ return ERR_PTR(err); - - btf = btf_new(data, st.st_size, base_btf, true); - if (IS_ERR(btf)) -diff -purNx .git BPI-Router-Linux-kernel/tools/lib/bpf/btf_dump.c BPI-Router-Linux-kernel-6.16.12/tools/lib/bpf/btf_dump.c ---- BPI-Router-Linux-kernel/tools/lib/bpf/btf_dump.c 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/lib/bpf/btf_dump.c 2025-10-22 13:53:56.863167463 -0400 -@@ -226,6 +226,9 @@ static void btf_dump_free_names(struct h - size_t bkt; - struct hashmap_entry *cur; - -+ if (!map) -+ return; -+ - hashmap__for_each_entry(map, cur, bkt) - free((void *)cur->pkey); - -diff -purNx .git BPI-Router-Linux-kernel/tools/lib/bpf/libbpf.c BPI-Router-Linux-kernel-6.16.12/tools/lib/bpf/libbpf.c ---- BPI-Router-Linux-kernel/tools/lib/bpf/libbpf.c 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/lib/bpf/libbpf.c 2025-10-22 13:53:56.863167463 -0400 -@@ -597,7 +597,7 @@ struct extern_desc { - int sym_idx; - int btf_id; - int sec_btf_id; -- const char *name; -+ char *name; - char *essent_name; - bool is_set; - bool is_weak; -@@ -735,7 +735,7 @@ struct bpf_object { - - struct usdt_manager *usdt_man; - -- struct bpf_map *arena_map; -+ int arena_map_idx; - void *arena_data; - size_t arena_data_sz; - -@@ -1517,6 +1517,7 @@ static struct bpf_object *bpf_object__ne - obj->efile.obj_buf_sz = obj_buf_sz; - obj->efile.btf_maps_shndx = -1; - obj->kconfig_map_idx = -1; -+ obj->arena_map_idx = -1; - - obj->kern_version = get_kernel_version(); - obj->state = OBJ_OPEN; -@@ -2964,7 +2965,7 @@ static int init_arena_map_data(struct bp - const long page_sz = sysconf(_SC_PAGE_SIZE); - size_t mmap_sz; - -- mmap_sz = bpf_map_mmap_sz(obj->arena_map); -+ mmap_sz = bpf_map_mmap_sz(map); - if (roundup(data_sz, page_sz) > mmap_sz) { - pr_warn("elf: sec '%s': declared ARENA map size (%zu) is too small to hold global __arena variables of size %zu\n", - sec_name, mmap_sz, data_sz); -@@ -3038,12 +3039,12 @@ static int bpf_object__init_user_btf_map - if (map->def.type != BPF_MAP_TYPE_ARENA) - continue; - -- if (obj->arena_map) { -+ if (obj->arena_map_idx >= 0) { - pr_warn("map '%s': only single ARENA map is supported (map '%s' is also ARENA)\n", -- map->name, obj->arena_map->name); -+ map->name, obj->maps[obj->arena_map_idx].name); - return -EINVAL; - } -- obj->arena_map = map; -+ obj->arena_map_idx = i; - - if (obj->efile.arena_data) { - err = init_arena_map_data(obj, map, ARENA_SEC, obj->efile.arena_data_shndx, -@@ -3053,7 +3054,7 @@ static int bpf_object__init_user_btf_map - return err; - } - } -- if (obj->efile.arena_data && !obj->arena_map) { -+ if (obj->efile.arena_data && obj->arena_map_idx < 0) { - pr_warn("elf: sec '%s': to use global __arena variables the ARENA map should be explicitly declared in SEC(\".maps\")\n", - ARENA_SEC); - return -ENOENT; -@@ -4259,7 +4260,9 @@ static int bpf_object__collect_externs(s - return ext->btf_id; - } - t = btf__type_by_id(obj->btf, ext->btf_id); -- ext->name = btf__name_by_offset(obj->btf, t->name_off); -+ ext->name = strdup(btf__name_by_offset(obj->btf, t->name_off)); -+ if (!ext->name) -+ return -ENOMEM; - ext->sym_idx = i; - ext->is_weak = ELF64_ST_BIND(sym->st_info) == STB_WEAK; - -@@ -4579,10 +4582,20 @@ static int bpf_program__record_reloc(str - - /* arena data relocation */ - if (shdr_idx == obj->efile.arena_data_shndx) { -+ if (obj->arena_map_idx < 0) { -+ pr_warn("prog '%s': bad arena data relocation at insn %u, no arena maps defined\n", -+ prog->name, insn_idx); -+ return -LIBBPF_ERRNO__RELOC; -+ } - reloc_desc->type = RELO_DATA; - reloc_desc->insn_idx = insn_idx; -- reloc_desc->map_idx = obj->arena_map - obj->maps; -+ reloc_desc->map_idx = obj->arena_map_idx; - reloc_desc->sym_off = sym->st_value; -+ -+ map = &obj->maps[obj->arena_map_idx]; -+ pr_debug("prog '%s': found arena map %d (%s, sec %d, off %zu) for insn %u\n", -+ prog->name, obj->arena_map_idx, map->name, map->sec_idx, -+ map->sec_offset, insn_idx); - return 0; - } - -@@ -9138,8 +9151,10 @@ void bpf_object__close(struct bpf_object - zfree(&obj->btf_custom_path); - zfree(&obj->kconfig); - -- for (i = 0; i < obj->nr_extern; i++) -+ for (i = 0; i < obj->nr_extern; i++) { -+ zfree(&obj->externs[i].name); - zfree(&obj->externs[i].essent_name); -+ } - - zfree(&obj->externs); - obj->nr_extern = 0; -@@ -9206,7 +9221,7 @@ int bpf_object__gen_loader(struct bpf_ob - return libbpf_err(-EFAULT); - if (!OPTS_VALID(opts, gen_loader_opts)) - return libbpf_err(-EINVAL); -- gen = calloc(sizeof(*gen), 1); -+ gen = calloc(1, sizeof(*gen)); - if (!gen) - return libbpf_err(-ENOMEM); - gen->opts = opts; -diff -purNx .git BPI-Router-Linux-kernel/tools/lib/subcmd/help.c BPI-Router-Linux-kernel-6.16.12/tools/lib/subcmd/help.c ---- BPI-Router-Linux-kernel/tools/lib/subcmd/help.c 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/lib/subcmd/help.c 2025-10-22 13:53:56.863167463 -0400 -@@ -9,6 +9,7 @@ - #include - #include - #include -+#include - #include "subcmd-util.h" - #include "help.h" - #include "exec-cmd.h" -@@ -74,6 +75,9 @@ void exclude_cmds(struct cmdnames *cmds, - size_t ci, cj, ei; - int cmp; - -+ if (!excludes->cnt) -+ return; -+ - ci = cj = ei = 0; - while (ci < cmds->cnt && ei < excludes->cnt) { - cmp = strcmp(cmds->names[ci]->name, excludes->names[ei]->name); -@@ -82,10 +86,11 @@ void exclude_cmds(struct cmdnames *cmds, - ci++; - cj++; - } else { -- zfree(&cmds->names[cj]); -- cmds->names[cj++] = cmds->names[ci++]; -+ cmds->names[cj++] = cmds->names[ci]; -+ cmds->names[ci++] = NULL; - } - } else if (cmp == 0) { -+ zfree(&cmds->names[ci]); - ci++; - ei++; - } else if (cmp > 0) { -@@ -94,12 +99,12 @@ void exclude_cmds(struct cmdnames *cmds, - } - if (ci != cj) { - while (ci < cmds->cnt) { -- zfree(&cmds->names[cj]); -- cmds->names[cj++] = cmds->names[ci++]; -+ cmds->names[cj++] = cmds->names[ci]; -+ cmds->names[ci++] = NULL; - } - } - for (ci = cj; ci < cmds->cnt; ci++) -- zfree(&cmds->names[ci]); -+ assert(cmds->names[ci] == NULL); - cmds->cnt = cj; - } - -diff -purNx .git BPI-Router-Linux-kernel/tools/lib/subcmd/run-command.c BPI-Router-Linux-kernel-6.16.12/tools/lib/subcmd/run-command.c ---- BPI-Router-Linux-kernel/tools/lib/subcmd/run-command.c 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/lib/subcmd/run-command.c 2025-10-22 13:53:56.863167463 -0400 -@@ -5,6 +5,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -216,10 +217,20 @@ static int wait_or_whine(struct child_pr - return result; - } - -+/* -+ * Conservative estimate of number of characaters needed to hold an a decoded -+ * integer, assume each 3 bits needs a character byte and plus a possible sign -+ * character. -+ */ -+#ifndef is_signed_type -+#define is_signed_type(type) (((type)(-1)) < (type)1) -+#endif -+#define MAX_STRLEN_TYPE(type) (sizeof(type) * 8 / 3 + (is_signed_type(type) ? 1 : 0)) -+ - int check_if_command_finished(struct child_process *cmd) - { - #ifdef __linux__ -- char filename[FILENAME_MAX + 12]; -+ char filename[6 + MAX_STRLEN_TYPE(typeof(cmd->pid)) + 7 + 1]; - char status_line[256]; - FILE *status_file; - -@@ -227,7 +238,7 @@ int check_if_command_finished(struct chi - * Check by reading /proc//status as calling waitpid causes - * stdout/stderr to be closed and data lost. - */ -- sprintf(filename, "/proc/%d/status", cmd->pid); -+ sprintf(filename, "/proc/%u/status", cmd->pid); - status_file = fopen(filename, "r"); - if (status_file == NULL) { - /* Open failed assume finish_command was called. */ -diff -purNx .git BPI-Router-Linux-kernel/tools/net/ynl/pyynl/lib/ynl.py BPI-Router-Linux-kernel-6.16.12/tools/net/ynl/pyynl/lib/ynl.py ---- BPI-Router-Linux-kernel/tools/net/ynl/pyynl/lib/ynl.py 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/net/ynl/pyynl/lib/ynl.py 2025-10-22 13:53:56.863167463 -0400 -@@ -231,14 +231,7 @@ class NlMsg: - self.extack['unknown'].append(extack) - - if attr_space: -- # We don't have the ability to parse nests yet, so only do global -- if 'miss-type' in self.extack and 'miss-nest' not in self.extack: -- miss_type = self.extack['miss-type'] -- if miss_type in attr_space.attrs_by_val: -- spec = attr_space.attrs_by_val[miss_type] -- self.extack['miss-type'] = spec['name'] -- if 'doc' in spec: -- self.extack['miss-type-doc'] = spec['doc'] -+ self.annotate_extack(attr_space) - - def _decode_policy(self, raw): - policy = {} -@@ -264,6 +257,18 @@ class NlMsg: - policy['mask'] = attr.as_scalar('u64') - return policy - -+ def annotate_extack(self, attr_space): -+ """ Make extack more human friendly with attribute information """ -+ -+ # We don't have the ability to parse nests yet, so only do global -+ if 'miss-type' in self.extack and 'miss-nest' not in self.extack: -+ miss_type = self.extack['miss-type'] -+ if miss_type in attr_space.attrs_by_val: -+ spec = attr_space.attrs_by_val[miss_type] -+ self.extack['miss-type'] = spec['name'] -+ if 'doc' in spec: -+ self.extack['miss-type-doc'] = spec['doc'] -+ - def cmd(self): - return self.nl_type - -@@ -277,12 +282,12 @@ class NlMsg: - - - class NlMsgs: -- def __init__(self, data, attr_space=None): -+ def __init__(self, data): - self.msgs = [] - - offset = 0 - while offset < len(data): -- msg = NlMsg(data, offset, attr_space=attr_space) -+ msg = NlMsg(data, offset) - offset += msg.nl_len - self.msgs.append(msg) - -@@ -1034,12 +1039,13 @@ class YnlFamily(SpecFamily): - op_rsp = [] - while not done: - reply = self.sock.recv(self._recv_size) -- nms = NlMsgs(reply, attr_space=op.attr_set) -+ nms = NlMsgs(reply) - self._recv_dbg_print(reply, nms) - for nl_msg in nms: - if nl_msg.nl_seq in reqs_by_seq: - (op, vals, req_msg, req_flags) = reqs_by_seq[nl_msg.nl_seq] - if nl_msg.extack: -+ nl_msg.annotate_extack(op.attr_set) - self._decode_extack(req_msg, op, nl_msg.extack, vals) - else: - op = None -diff -purNx .git BPI-Router-Linux-kernel/tools/net/ynl/pyynl/ynl_gen_c.py BPI-Router-Linux-kernel-6.16.12/tools/net/ynl/pyynl/ynl_gen_c.py ---- BPI-Router-Linux-kernel/tools/net/ynl/pyynl/ynl_gen_c.py 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/net/ynl/pyynl/ynl_gen_c.py 2025-10-22 13:53:56.863167463 -0400 -@@ -830,7 +830,7 @@ class TypeArrayNest(Type): - 'ynl_attr_for_each_nested(attr2, attr) {', - '\tif (ynl_attr_validate(yarg, attr2))', - '\t\treturn YNL_PARSE_CB_ERROR;', -- f'\t{var}->_count.{self.c_name}++;', -+ f'\tn_{self.c_name}++;', - '}'] - return get_lines, None, local_vars - -diff -purNx .git BPI-Router-Linux-kernel/tools/objtool/arch/loongarch/decode.c BPI-Router-Linux-kernel-6.16.12/tools/objtool/arch/loongarch/decode.c ---- BPI-Router-Linux-kernel/tools/objtool/arch/loongarch/decode.c 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/objtool/arch/loongarch/decode.c 2025-10-22 13:53:56.863167463 -0400 -@@ -278,6 +278,25 @@ static bool decode_insn_reg2i16_fomat(un - return true; - } - -+static bool decode_insn_reg3_fomat(union loongarch_instruction inst, -+ struct instruction *insn) -+{ -+ switch (inst.reg3_format.opcode) { -+ case amswapw_op: -+ if (inst.reg3_format.rd == LOONGARCH_GPR_ZERO && -+ inst.reg3_format.rk == LOONGARCH_GPR_RA && -+ inst.reg3_format.rj == LOONGARCH_GPR_ZERO) { -+ /* amswap.w $zero, $ra, $zero */ -+ insn->type = INSN_BUG; -+ } -+ break; -+ default: -+ return false; -+ } -+ -+ return true; -+} -+ - int arch_decode_instruction(struct objtool_file *file, const struct section *sec, - unsigned long offset, unsigned int maxlen, - struct instruction *insn) -@@ -309,11 +328,19 @@ int arch_decode_instruction(struct objto - return 0; - if (decode_insn_reg2i16_fomat(inst, insn)) - return 0; -+ if (decode_insn_reg3_fomat(inst, insn)) -+ return 0; - -- if (inst.word == 0) -+ if (inst.word == 0) { -+ /* andi $zero, $zero, 0x0 */ - insn->type = INSN_NOP; -- else if (inst.reg0i15_format.opcode == break_op) { -- /* break */ -+ } else if (inst.reg0i15_format.opcode == break_op && -+ inst.reg0i15_format.immediate == 0x0) { -+ /* break 0x0 */ -+ insn->type = INSN_TRAP; -+ } else if (inst.reg0i15_format.opcode == break_op && -+ inst.reg0i15_format.immediate == 0x1) { -+ /* break 0x1 */ - insn->type = INSN_BUG; - } else if (inst.reg2_format.opcode == ertn_op) { - /* ertn */ -diff -purNx .git BPI-Router-Linux-kernel/tools/objtool/arch/loongarch/special.c BPI-Router-Linux-kernel-6.16.12/tools/objtool/arch/loongarch/special.c ---- BPI-Router-Linux-kernel/tools/objtool/arch/loongarch/special.c 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/objtool/arch/loongarch/special.c 2025-10-22 13:53:56.863167463 -0400 -@@ -27,6 +27,7 @@ static void get_rodata_table_size_by_tab - struct table_info *next_table; - unsigned long tmp_insn_offset; - unsigned long tmp_rodata_offset; -+ bool is_valid_list = false; - - rsec = find_section_by_name(file->elf, ".rela.discard.tablejump_annotate"); - if (!rsec) -@@ -35,6 +36,12 @@ static void get_rodata_table_size_by_tab - INIT_LIST_HEAD(&table_list); - - for_each_reloc(rsec, reloc) { -+ if (reloc->sym->sec->rodata) -+ continue; -+ -+ if (strcmp(insn->sec->name, reloc->sym->sec->name)) -+ continue; -+ - orig_table = malloc(sizeof(struct table_info)); - if (!orig_table) { - WARN("malloc failed"); -@@ -49,6 +56,22 @@ static void get_rodata_table_size_by_tab - - if (reloc_idx(reloc) + 1 == sec_num_entries(rsec)) - break; -+ -+ if (strcmp(insn->sec->name, (reloc + 1)->sym->sec->name)) { -+ list_for_each_entry(orig_table, &table_list, jump_info) { -+ if (orig_table->insn_offset == insn->offset) { -+ is_valid_list = true; -+ break; -+ } -+ } -+ -+ if (!is_valid_list) { -+ list_del_init(&table_list); -+ continue; -+ } -+ -+ break; -+ } - } - - list_for_each_entry(orig_table, &table_list, jump_info) { -diff -purNx .git BPI-Router-Linux-kernel/tools/objtool/check.c BPI-Router-Linux-kernel-6.16.12/tools/objtool/check.c ---- BPI-Router-Linux-kernel/tools/objtool/check.c 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/objtool/check.c 2025-10-22 13:53:56.863167463 -0400 -@@ -224,6 +224,7 @@ static bool is_rust_noreturn(const struc - str_ends_with(func->name, "_4core9panicking14panic_explicit") || - str_ends_with(func->name, "_4core9panicking14panic_nounwind") || - str_ends_with(func->name, "_4core9panicking18panic_bounds_check") || -+ str_ends_with(func->name, "_4core9panicking18panic_nounwind_fmt") || - str_ends_with(func->name, "_4core9panicking19assert_failed_inner") || - str_ends_with(func->name, "_4core9panicking30panic_null_pointer_dereference") || - str_ends_with(func->name, "_4core9panicking36panic_misaligned_pointer_dereference") || -@@ -2318,6 +2319,7 @@ static int read_annotate(struct objtool_ - - for_each_reloc(sec->rsec, reloc) { - type = *(u32 *)(sec->data->d_buf + (reloc_idx(reloc) * sec->sh.sh_entsize) + 4); -+ type = bswap_if_needed(file->elf, type); - - offset = reloc->sym->offset + reloc_addend(reloc); - insn = find_insn(file, reloc->sym->sec, offset); -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/bench/futex.c BPI-Router-Linux-kernel-6.16.12/tools/perf/bench/futex.c ---- BPI-Router-Linux-kernel/tools/perf/bench/futex.c 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/bench/futex.c 2025-10-22 13:53:56.863167463 -0400 -@@ -2,11 +2,18 @@ - #include - #include - #include --#include - #include - - #include "futex.h" - -+#ifndef PR_FUTEX_HASH -+#define PR_FUTEX_HASH 78 -+# define PR_FUTEX_HASH_SET_SLOTS 1 -+# define FH_FLAG_IMMUTABLE (1ULL << 0) -+# define PR_FUTEX_HASH_GET_SLOTS 2 -+# define PR_FUTEX_HASH_GET_IMMUTABLE 3 -+#endif // PR_FUTEX_HASH -+ - void futex_set_nbuckets_param(struct bench_futex_parameters *params) - { - unsigned long flags; -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/bench/futex-hash.c BPI-Router-Linux-kernel-6.16.12/tools/perf/bench/futex-hash.c ---- BPI-Router-Linux-kernel/tools/perf/bench/futex-hash.c 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/bench/futex-hash.c 2025-10-22 13:53:56.863167463 -0400 -@@ -18,7 +18,6 @@ - #include - #include - #include --#include - #include - #include - #include -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/builtin-sched.c BPI-Router-Linux-kernel-6.16.12/tools/perf/builtin-sched.c ---- BPI-Router-Linux-kernel/tools/perf/builtin-sched.c 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/builtin-sched.c 2025-10-22 13:53:56.863167463 -0400 -@@ -994,7 +994,7 @@ thread_atoms_search(struct rb_root_cache - else if (cmp < 0) - node = node->rb_right; - else { -- BUG_ON(thread != atoms->thread); -+ BUG_ON(!RC_CHK_EQUAL(thread, atoms->thread)); - return atoms; - } - } -@@ -1111,6 +1111,21 @@ add_sched_in_event(struct work_atoms *at - atoms->nb_atoms++; - } - -+static void free_work_atoms(struct work_atoms *atoms) -+{ -+ struct work_atom *atom, *tmp; -+ -+ if (atoms == NULL) -+ return; -+ -+ list_for_each_entry_safe(atom, tmp, &atoms->work_list, list) { -+ list_del(&atom->list); -+ free(atom); -+ } -+ thread__zput(atoms->thread); -+ free(atoms); -+} -+ - static int latency_switch_event(struct perf_sched *sched, - struct evsel *evsel, - struct perf_sample *sample, -@@ -1634,6 +1649,7 @@ static int map_switch_event(struct perf_ - const char *color = PERF_COLOR_NORMAL; - char stimestamp[32]; - const char *str; -+ int ret = -1; - - BUG_ON(this_cpu.cpu >= MAX_CPUS || this_cpu.cpu < 0); - -@@ -1664,17 +1680,20 @@ static int map_switch_event(struct perf_ - sched_in = map__findnew_thread(sched, machine, -1, next_pid); - sched_out = map__findnew_thread(sched, machine, -1, prev_pid); - if (sched_in == NULL || sched_out == NULL) -- return -1; -+ goto out; - - tr = thread__get_runtime(sched_in); -- if (tr == NULL) { -- thread__put(sched_in); -- return -1; -- } -+ if (tr == NULL) -+ goto out; -+ -+ thread__put(sched->curr_thread[this_cpu.cpu]); -+ thread__put(sched->curr_out_thread[this_cpu.cpu]); - - sched->curr_thread[this_cpu.cpu] = thread__get(sched_in); - sched->curr_out_thread[this_cpu.cpu] = thread__get(sched_out); - -+ ret = 0; -+ - str = thread__comm_str(sched_in); - new_shortname = 0; - if (!tr->shortname[0]) { -@@ -1769,12 +1788,10 @@ sched_out: - color_fprintf(stdout, color, "\n"); - - out: -- if (sched->map.task_name) -- thread__put(sched_out); -- -+ thread__put(sched_out); - thread__put(sched_in); - -- return 0; -+ return ret; - } - - static int process_sched_switch_event(const struct perf_tool *tool, -@@ -2018,6 +2035,16 @@ static u64 evsel__get_time(struct evsel - return r->last_time[cpu]; - } - -+static void timehist__evsel_priv_destructor(void *priv) -+{ -+ struct evsel_runtime *r = priv; -+ -+ if (r) { -+ free(r->last_time); -+ free(r); -+ } -+} -+ - static int comm_width = 30; - - static char *timehist_get_commstr(struct thread *thread) -@@ -2311,8 +2338,10 @@ static void save_task_callchain(struct p - return; - } - -- if (!sched->show_callchain || sample->callchain == NULL) -+ if (!sched->show_callchain || sample->callchain == NULL) { -+ thread__put(thread); - return; -+ } - - cursor = get_tls_callchain_cursor(); - -@@ -2321,10 +2350,12 @@ static void save_task_callchain(struct p - if (verbose > 0) - pr_err("Failed to resolve callchain. Skipping\n"); - -+ thread__put(thread); - return; - } - - callchain_cursor_commit(cursor); -+ thread__put(thread); - - while (true) { - struct callchain_cursor_node *node; -@@ -2401,8 +2432,17 @@ static void free_idle_threads(void) - return; - - for (i = 0; i < idle_max_cpu; ++i) { -- if ((idle_threads[i])) -- thread__delete(idle_threads[i]); -+ struct thread *idle = idle_threads[i]; -+ -+ if (idle) { -+ struct idle_thread_runtime *itr; -+ -+ itr = thread__priv(idle); -+ if (itr) -+ thread__put(itr->last_thread); -+ -+ thread__delete(idle); -+ } - } - - free(idle_threads); -@@ -2439,7 +2479,7 @@ static struct thread *get_idle_thread(in - } - } - -- return idle_threads[cpu]; -+ return thread__get(idle_threads[cpu]); - } - - static void save_idle_callchain(struct perf_sched *sched, -@@ -2494,7 +2534,8 @@ static struct thread *timehist_get_threa - if (itr == NULL) - return NULL; - -- itr->last_thread = thread; -+ thread__put(itr->last_thread); -+ itr->last_thread = thread__get(thread); - - /* copy task callchain when entering to idle */ - if (evsel__intval(evsel, sample, "next_pid") == 0) -@@ -2565,6 +2606,7 @@ static void timehist_print_wakeup_event( - /* show wakeup unless both awakee and awaker are filtered */ - if (timehist_skip_sample(sched, thread, evsel, sample) && - timehist_skip_sample(sched, awakened, evsel, sample)) { -+ thread__put(thread); - return; - } - -@@ -2581,6 +2623,8 @@ static void timehist_print_wakeup_event( - printf("awakened: %s", timehist_get_commstr(awakened)); - - printf("\n"); -+ -+ thread__put(thread); - } - - static int timehist_sched_wakeup_ignore(const struct perf_tool *tool __maybe_unused, -@@ -2609,8 +2653,10 @@ static int timehist_sched_wakeup_event(c - return -1; - - tr = thread__get_runtime(thread); -- if (tr == NULL) -+ if (tr == NULL) { -+ thread__put(thread); - return -1; -+ } - - if (tr->ready_to_run == 0) - tr->ready_to_run = sample->time; -@@ -2620,6 +2666,7 @@ static int timehist_sched_wakeup_event(c - !perf_time__skip_sample(&sched->ptime, sample->time)) - timehist_print_wakeup_event(sched, evsel, sample, machine, thread); - -+ thread__put(thread); - return 0; - } - -@@ -2647,6 +2694,7 @@ static void timehist_print_migration_eve - - if (timehist_skip_sample(sched, thread, evsel, sample) && - timehist_skip_sample(sched, migrated, evsel, sample)) { -+ thread__put(thread); - return; - } - -@@ -2674,6 +2722,7 @@ static void timehist_print_migration_eve - printf(" cpu %d => %d", ocpu, dcpu); - - printf("\n"); -+ thread__put(thread); - } - - static int timehist_migrate_task_event(const struct perf_tool *tool, -@@ -2693,8 +2742,10 @@ static int timehist_migrate_task_event(c - return -1; - - tr = thread__get_runtime(thread); -- if (tr == NULL) -+ if (tr == NULL) { -+ thread__put(thread); - return -1; -+ } - - tr->migrations++; - tr->migrated = sample->time; -@@ -2704,6 +2755,7 @@ static int timehist_migrate_task_event(c - timehist_print_migration_event(sched, evsel, sample, - machine, thread); - } -+ thread__put(thread); - - return 0; - } -@@ -2726,10 +2778,10 @@ static void timehist_update_task_prio(st - return; - - tr = thread__get_runtime(thread); -- if (tr == NULL) -- return; -+ if (tr != NULL) -+ tr->prio = next_prio; - -- tr->prio = next_prio; -+ thread__put(thread); - } - - static int timehist_sched_change_event(const struct perf_tool *tool, -@@ -2741,7 +2793,7 @@ static int timehist_sched_change_event(c - struct perf_sched *sched = container_of(tool, struct perf_sched, tool); - struct perf_time_interval *ptime = &sched->ptime; - struct addr_location al; -- struct thread *thread; -+ struct thread *thread = NULL; - struct thread_runtime *tr = NULL; - u64 tprev, t = sample->time; - int rc = 0; -@@ -2865,6 +2917,7 @@ out: - - evsel__save_time(evsel, sample->time, sample->cpu); - -+ thread__put(thread); - addr_location__exit(&al); - return rc; - } -@@ -3286,6 +3339,8 @@ static int perf_sched__timehist(struct p - - setup_pager(); - -+ evsel__set_priv_destructor(timehist__evsel_priv_destructor); -+ - /* prefer sched_waking if it is captured */ - if (evlist__find_tracepoint_by_name(session->evlist, "sched:sched_waking")) - handlers[1].handler = timehist_sched_wakeup_ignore; -@@ -3386,13 +3441,13 @@ static void __merge_work_atoms(struct rb - this->total_runtime += data->total_runtime; - this->nb_atoms += data->nb_atoms; - this->total_lat += data->total_lat; -- list_splice(&data->work_list, &this->work_list); -+ list_splice_init(&data->work_list, &this->work_list); - if (this->max_lat < data->max_lat) { - this->max_lat = data->max_lat; - this->max_lat_start = data->max_lat_start; - this->max_lat_end = data->max_lat_end; - } -- zfree(&data); -+ free_work_atoms(data); - return; - } - } -@@ -3471,7 +3526,6 @@ static int perf_sched__lat(struct perf_s - work_list = rb_entry(next, struct work_atoms, node); - output_lat_thread(sched, work_list); - next = rb_next(next); -- thread__zput(work_list->thread); - } - - printf(" -----------------------------------------------------------------------------------------------------------------\n"); -@@ -3485,6 +3539,13 @@ static int perf_sched__lat(struct perf_s - - rc = 0; - -+ while ((next = rb_first_cached(&sched->sorted_atom_root))) { -+ struct work_atoms *data; -+ -+ data = rb_entry(next, struct work_atoms, node); -+ rb_erase_cached(next, &sched->sorted_atom_root); -+ free_work_atoms(data); -+ } - out_free_cpus_switch_event: - free_cpus_switch_event(sched); - return rc; -@@ -3556,10 +3617,10 @@ static int perf_sched__map(struct perf_s - - sched->curr_out_thread = calloc(MAX_CPUS, sizeof(*(sched->curr_out_thread))); - if (!sched->curr_out_thread) -- return rc; -+ goto out_free_curr_thread; - - if (setup_cpus_switch_event(sched)) -- goto out_free_curr_thread; -+ goto out_free_curr_out_thread; - - if (setup_map_cpus(sched)) - goto out_free_cpus_switch_event; -@@ -3590,7 +3651,14 @@ out_put_map_cpus: - out_free_cpus_switch_event: - free_cpus_switch_event(sched); - -+out_free_curr_out_thread: -+ for (int i = 0; i < MAX_CPUS; i++) -+ thread__put(sched->curr_out_thread[i]); -+ zfree(&sched->curr_out_thread); -+ - out_free_curr_thread: -+ for (int i = 0; i < MAX_CPUS; i++) -+ thread__put(sched->curr_thread[i]); - zfree(&sched->curr_thread); - return rc; - } -@@ -3898,13 +3966,15 @@ int cmd_sched(int argc, const char **arg - if (!argc) - usage_with_options(sched_usage, sched_options); - -+ thread__set_priv_destructor(free); -+ - /* - * Aliased to 'perf script' for now: - */ - if (!strcmp(argv[0], "script")) { -- return cmd_script(argc, argv); -+ ret = cmd_script(argc, argv); - } else if (strlen(argv[0]) > 2 && strstarts("record", argv[0])) { -- return __cmd_record(argc, argv); -+ ret = __cmd_record(argc, argv); - } else if (strlen(argv[0]) > 2 && strstarts("latency", argv[0])) { - sched.tp_handler = &lat_ops; - if (argc > 1) { -@@ -3913,7 +3983,7 @@ int cmd_sched(int argc, const char **arg - usage_with_options(latency_usage, latency_options); - } - setup_sorting(&sched, latency_options, latency_usage); -- return perf_sched__lat(&sched); -+ ret = perf_sched__lat(&sched); - } else if (!strcmp(argv[0], "map")) { - if (argc) { - argc = parse_options(argc, argv, map_options, map_usage, 0); -@@ -3924,13 +3994,14 @@ int cmd_sched(int argc, const char **arg - sched.map.task_names = strlist__new(sched.map.task_name, NULL); - if (sched.map.task_names == NULL) { - fprintf(stderr, "Failed to parse task names\n"); -- return -1; -+ ret = -1; -+ goto out; - } - } - } - sched.tp_handler = &map_ops; - setup_sorting(&sched, latency_options, latency_usage); -- return perf_sched__map(&sched); -+ ret = perf_sched__map(&sched); - } else if (strlen(argv[0]) > 2 && strstarts("replay", argv[0])) { - sched.tp_handler = &replay_ops; - if (argc) { -@@ -3938,7 +4009,7 @@ int cmd_sched(int argc, const char **arg - if (argc) - usage_with_options(replay_usage, replay_options); - } -- return perf_sched__replay(&sched); -+ ret = perf_sched__replay(&sched); - } else if (!strcmp(argv[0], "timehist")) { - if (argc) { - argc = parse_options(argc, argv, timehist_options, -@@ -3954,19 +4025,19 @@ int cmd_sched(int argc, const char **arg - parse_options_usage(NULL, timehist_options, "w", true); - if (sched.show_next) - parse_options_usage(NULL, timehist_options, "n", true); -- return -EINVAL; -+ ret = -EINVAL; -+ goto out; - } - ret = symbol__validate_sym_arguments(); -- if (ret) -- return ret; -- -- return perf_sched__timehist(&sched); -+ if (!ret) -+ ret = perf_sched__timehist(&sched); - } else { - usage_with_options(sched_usage, sched_options); - } - -+out: - /* free usage string allocated by parse_options_subcommand */ - free((void *)sched_usage[0]); - -- return 0; -+ return ret; - } -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/check-headers.sh BPI-Router-Linux-kernel-6.16.12/tools/perf/check-headers.sh ---- BPI-Router-Linux-kernel/tools/perf/check-headers.sh 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/check-headers.sh 2025-10-22 13:53:56.863167463 -0400 -@@ -186,7 +186,7 @@ done - # diff with extra ignore lines - check arch/x86/lib/memcpy_64.S '-I "^EXPORT_SYMBOL" -I "^#include " -I"^SYM_FUNC_START\(_LOCAL\)*(memcpy_\(erms\|orig\))" -I"^#include "' - check arch/x86/lib/memset_64.S '-I "^EXPORT_SYMBOL" -I "^#include " -I"^SYM_FUNC_START\(_LOCAL\)*(memset_\(erms\|orig\))"' --check arch/x86/include/asm/amd/ibs.h '-I "^#include [<\"]\(asm/\)*msr-index.h"' -+check arch/x86/include/asm/amd/ibs.h '-I "^#include .*/msr-index.h"' - check arch/arm64/include/asm/cputype.h '-I "^#include [<\"]\(asm/\)*sysreg.h"' - check include/linux/unaligned.h '-I "^#include " -I "^#include " -I "^#pragma GCC diagnostic"' - check include/uapi/asm-generic/mman.h '-I "^#include <\(uapi/\)*asm-generic/mman-common\(-tools\)*.h>"' -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/Documentation/perf-amd-ibs.txt BPI-Router-Linux-kernel-6.16.12/tools/perf/Documentation/perf-amd-ibs.txt ---- BPI-Router-Linux-kernel/tools/perf/Documentation/perf-amd-ibs.txt 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/Documentation/perf-amd-ibs.txt 2025-10-22 13:53:56.863167463 -0400 -@@ -171,23 +171,48 @@ Below is a simple example of the perf me - # perf mem report - - A normal perf mem report output will provide detailed memory access profile. --However, it can also be aggregated based on output fields. For example: -+New output fields will show related access info together. For example: - -- # perf mem report -F mem,sample,snoop -- Samples: 3M of event 'ibs_op//', Event count (approx.): 23524876 -- Memory access Samples Snoop -- N/A 1903343 N/A -- L1 hit 1056754 N/A -- L2 hit 75231 N/A -- L3 hit 9496 HitM -- L3 hit 2270 N/A -- RAM hit 8710 N/A -- Remote node, same socket RAM hit 3241 N/A -- Remote core, same node Any cache hit 1572 HitM -- Remote core, same node Any cache hit 514 N/A -- Remote node, same socket Any cache hit 1216 HitM -- Remote node, same socket Any cache hit 350 N/A -- Uncached hit 18 N/A -+ # perf mem report -F overhead,cache,snoop,comm -+ ... -+ # Samples: 92K of event 'ibs_op//' -+ # Total weight : 531104 -+ # -+ # ---------- Cache ----------- --- Snoop ---- -+ # Overhead L1 L2 L1-buf Other HitM Other Command -+ # ........ ............................ .............. .......... -+ # -+ 76.07% 5.8% 35.7% 0.0% 34.6% 23.3% 52.8% cc1 -+ 5.79% 0.2% 0.0% 0.0% 5.6% 0.1% 5.7% make -+ 5.78% 0.1% 4.4% 0.0% 1.2% 0.5% 5.3% gcc -+ 5.33% 0.3% 3.9% 0.0% 1.1% 0.2% 5.2% as -+ 5.00% 0.1% 3.8% 0.0% 1.0% 0.3% 4.7% sh -+ 1.56% 0.1% 0.1% 0.0% 1.4% 0.6% 0.9% ld -+ 0.28% 0.1% 0.0% 0.0% 0.2% 0.1% 0.2% pkg-config -+ 0.09% 0.0% 0.0% 0.0% 0.1% 0.0% 0.1% git -+ 0.03% 0.0% 0.0% 0.0% 0.0% 0.0% 0.0% rm -+ ... -+ -+Also, it can be aggregated based on various memory access info using the -+sort keys. For example: -+ -+ # perf mem report -s mem,snoop -+ ... -+ # Samples: 92K of event 'ibs_op//' -+ # Total weight : 531104 -+ # Sort order : mem,snoop -+ # -+ # Overhead Samples Memory access Snoop -+ # ........ ............ ....................................... ............ -+ # -+ 47.99% 1509 L2 hit N/A -+ 25.08% 338 core, same node Any cache hit HitM -+ 10.24% 54374 N/A N/A -+ 6.77% 35938 L1 hit N/A -+ 6.39% 101 core, same node Any cache hit N/A -+ 3.50% 69 RAM hit N/A -+ 0.03% 158 LFB/MAB hit N/A -+ 0.00% 2 Uncached hit N/A - - Please refer to their man page for more detail. - -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/Documentation/perf-mem.txt BPI-Router-Linux-kernel-6.16.12/tools/perf/Documentation/perf-mem.txt ---- BPI-Router-Linux-kernel/tools/perf/Documentation/perf-mem.txt 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/Documentation/perf-mem.txt 2025-10-22 13:53:56.863167463 -0400 -@@ -119,6 +119,22 @@ REPORT OPTIONS - And the default sort keys are changed to local_weight, mem, sym, dso, - symbol_daddr, dso_daddr, snoop, tlb, locked, blocked, local_ins_lat. - -+-F:: -+--fields=:: -+ Specify output field - multiple keys can be specified in CSV format. -+ Please see linkperf:perf-report[1] for details. -+ -+ In addition to the default fields, 'perf mem report' will provide the -+ following fields to break down sample periods. -+ -+ - op: operation in the sample instruction (load, store, prefetch, ...) -+ - cache: location in CPU cache (L1, L2, ...) where the sample hit -+ - mem: location in memory or other places the sample hit -+ - dtlb: location in Data TLB (L1, L2) where the sample hit -+ - snoop: snoop result for the sampled data access -+ -+ Please take a look at the OUTPUT FIELD SELECTION section for caveats. -+ - -T:: - --type-profile:: - Show data-type profile result instead of code symbols. This requires -@@ -156,6 +172,40 @@ but one sample with weight 180 and the o - 90% [k] memcpy - 10% [.] strcmp - -+OUTPUT FIELD SELECTION -+---------------------- -+"perf mem report" adds a number of new output fields specific to data source -+information in the sample. Some of them have the same name with the existing -+sort keys ("mem" and "snoop"). So unlike other fields and sort keys, they'll -+behave differently when it's used by -F/--fields or -s/--sort. -+ -+Using those two as output fields will aggregate samples altogether and show -+breakdown. -+ -+ $ perf mem report -F mem,snoop -+ ... -+ # ------ Memory ------- --- Snoop ---- -+ # RAM Uncach Other HitM Other -+ # ..................... .............. -+ # -+ 3.5% 0.0% 96.5% 25.1% 74.9% -+ -+But using the same name for sort keys will aggregate samples for each type -+separately. -+ -+ $ perf mem report -s mem,snoop -+ # Overhead Samples Memory access Snoop -+ # ........ ............ ....................................... ............ -+ # -+ 47.99% 1509 L2 hit N/A -+ 25.08% 338 core, same node Any cache hit HitM -+ 10.24% 54374 N/A N/A -+ 6.77% 35938 L1 hit N/A -+ 6.39% 101 core, same node Any cache hit N/A -+ 3.50% 69 RAM hit N/A -+ 0.03% 158 LFB/MAB hit N/A -+ 0.00% 2 Uncached hit N/A -+ - SEE ALSO - -------- - linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-arm-spe[1] -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/.gitignore BPI-Router-Linux-kernel-6.16.12/tools/perf/.gitignore ---- BPI-Router-Linux-kernel/tools/perf/.gitignore 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/.gitignore 2025-10-22 13:53:56.863167463 -0400 -@@ -48,8 +48,6 @@ libbpf/ - libperf/ - libsubcmd/ - libsymbol/ --libtraceevent/ --libtraceevent_plugins/ - fixdep - Documentation/doc.dep - python_ext_build/ -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/tests/bp_account.c BPI-Router-Linux-kernel-6.16.12/tools/perf/tests/bp_account.c ---- BPI-Router-Linux-kernel/tools/perf/tests/bp_account.c 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/tests/bp_account.c 2025-10-22 13:53:56.863167463 -0400 -@@ -104,6 +104,7 @@ static int bp_accounting(int wp_cnt, int - fd_wp = wp_event((void *)&the_var, &attr_new); - TEST_ASSERT_VAL("failed to create max wp\n", fd_wp != -1); - pr_debug("wp max created\n"); -+ close(fd_wp); - } - - for (i = 0; i < wp_cnt; i++) -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/tests/shell/stat+event_uniquifying.sh BPI-Router-Linux-kernel-6.16.12/tools/perf/tests/shell/stat+event_uniquifying.sh ---- BPI-Router-Linux-kernel/tools/perf/tests/shell/stat+event_uniquifying.sh 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/tests/shell/stat+event_uniquifying.sh 2025-10-22 13:53:56.863167463 -0400 -@@ -9,7 +9,8 @@ perf_tool=perf - err=0 - - test_event_uniquifying() { -- # We use `clockticks` to verify the uniquify behavior. -+ # We use `clockticks` in `uncore_imc` to verify the uniquify behavior. -+ pmu="uncore_imc" - event="clockticks" - - # If the `-A` option is added, the event should be uniquified. -@@ -43,11 +44,18 @@ test_event_uniquifying() { - echo "stat event uniquifying test" - uniquified_event_array=() - -+ # Skip if the machine does not have `uncore_imc` device. -+ if ! ${perf_tool} list pmu | grep -q ${pmu}; then -+ echo "Target does not support PMU ${pmu} [Skipped]" -+ err=2 -+ return -+ fi -+ - # Check how many uniquified events. - while IFS= read -r line; do - uniquified_event=$(echo "$line" | awk '{print $1}') - uniquified_event_array+=("${uniquified_event}") -- done < <(${perf_tool} list -v ${event} | grep "\[Kernel PMU event\]") -+ done < <(${perf_tool} list -v ${event} | grep ${pmu}) - - perf_command="${perf_tool} stat -e $event -A -o ${stat_output} -- true" - $perf_command -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/tests/tests-scripts.c BPI-Router-Linux-kernel-6.16.12/tools/perf/tests/tests-scripts.c ---- BPI-Router-Linux-kernel/tools/perf/tests/tests-scripts.c 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/tests/tests-scripts.c 2025-10-22 13:53:56.863167463 -0400 -@@ -260,6 +260,7 @@ static void append_scripts_in_dir(int di - continue; /* Skip scripts that have a separate driver. */ - fd = openat(dir_fd, ent->d_name, O_PATH); - append_scripts_in_dir(fd, result, result_sz); -+ close(fd); - } - for (i = 0; i < n_dirs; i++) /* Clean up */ - zfree(&entlist[i]); -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/trace/beauty/include/linux/socket.h BPI-Router-Linux-kernel-6.16.12/tools/perf/trace/beauty/include/linux/socket.h ---- BPI-Router-Linux-kernel/tools/perf/trace/beauty/include/linux/socket.h 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/trace/beauty/include/linux/socket.h 2025-10-22 13:53:56.863167463 -0400 -@@ -168,7 +168,7 @@ static inline struct cmsghdr * cmsg_nxth - return __cmsg_nxthdr(__msg->msg_control, __msg->msg_controllen, __cmsg); - } - --static inline size_t msg_data_left(struct msghdr *msg) -+static inline size_t msg_data_left(const struct msghdr *msg) - { - return iov_iter_count(&msg->msg_iter); - } -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/trace/beauty/include/uapi/linux/fs.h BPI-Router-Linux-kernel-6.16.12/tools/perf/trace/beauty/include/uapi/linux/fs.h ---- BPI-Router-Linux-kernel/tools/perf/trace/beauty/include/uapi/linux/fs.h 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/trace/beauty/include/uapi/linux/fs.h 2025-10-22 13:53:56.863167463 -0400 -@@ -361,6 +361,7 @@ typedef int __bitwise __kernel_rwf_t; - #define PAGE_IS_PFNZERO (1 << 5) - #define PAGE_IS_HUGE (1 << 6) - #define PAGE_IS_SOFT_DIRTY (1 << 7) -+#define PAGE_IS_GUARD (1 << 8) - - /* - * struct page_region - Page region with flags -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/trace/beauty/include/uapi/linux/prctl.h BPI-Router-Linux-kernel-6.16.12/tools/perf/trace/beauty/include/uapi/linux/prctl.h ---- BPI-Router-Linux-kernel/tools/perf/trace/beauty/include/uapi/linux/prctl.h 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/trace/beauty/include/uapi/linux/prctl.h 2025-10-22 13:53:56.867167444 -0400 -@@ -364,4 +364,11 @@ struct prctl_mm_map { - # define PR_TIMER_CREATE_RESTORE_IDS_ON 1 - # define PR_TIMER_CREATE_RESTORE_IDS_GET 2 - -+/* FUTEX hash management */ -+#define PR_FUTEX_HASH 78 -+# define PR_FUTEX_HASH_SET_SLOTS 1 -+# define FH_FLAG_IMMUTABLE (1ULL << 0) -+# define PR_FUTEX_HASH_GET_SLOTS 2 -+# define PR_FUTEX_HASH_GET_IMMUTABLE 3 -+ - #endif /* _LINUX_PRCTL_H */ -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/trace/beauty/include/uapi/linux/stat.h BPI-Router-Linux-kernel-6.16.12/tools/perf/trace/beauty/include/uapi/linux/stat.h ---- BPI-Router-Linux-kernel/tools/perf/trace/beauty/include/uapi/linux/stat.h 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/trace/beauty/include/uapi/linux/stat.h 2025-10-22 13:53:56.867167444 -0400 -@@ -182,8 +182,12 @@ struct statx { - /* File offset alignment for direct I/O reads */ - __u32 stx_dio_read_offset_align; - -- /* 0xb8 */ -- __u64 __spare3[9]; /* Spare space for future expansion */ -+ /* Optimised max atomic write unit in bytes */ -+ __u32 stx_atomic_write_unit_max_opt; -+ __u32 __spare2[1]; -+ -+ /* 0xc0 */ -+ __u64 __spare3[8]; /* Spare space for future expansion */ - - /* 0x100 */ - }; -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/util/bpf-event.c BPI-Router-Linux-kernel-6.16.12/tools/perf/util/bpf-event.c ---- BPI-Router-Linux-kernel/tools/perf/util/bpf-event.c 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/util/bpf-event.c 2025-10-22 13:53:56.867167444 -0400 -@@ -290,9 +290,15 @@ static int perf_event__synthesize_one_bp - - info_node->info_linear = info_linear; - if (!perf_env__insert_bpf_prog_info(env, info_node)) { -- free(info_linear); -+ /* -+ * Insert failed, likely because of a duplicate event -+ * made by the sideband thread. Ignore synthesizing the -+ * metadata. -+ */ - free(info_node); -+ goto out; - } -+ /* info_linear is now owned by info_node and shouldn't be freed below. */ - info_linear = NULL; - - /* -@@ -451,18 +457,18 @@ int perf_event__synthesize_bpf_events(st - return err; - } - --static void perf_env__add_bpf_info(struct perf_env *env, u32 id) -+static int perf_env__add_bpf_info(struct perf_env *env, u32 id) - { - struct bpf_prog_info_node *info_node; - struct perf_bpil *info_linear; - struct btf *btf = NULL; - u64 arrays; - u32 btf_id; -- int fd; -+ int fd, err = 0; - - fd = bpf_prog_get_fd_by_id(id); - if (fd < 0) -- return; -+ return -EINVAL; - - arrays = 1UL << PERF_BPIL_JITED_KSYMS; - arrays |= 1UL << PERF_BPIL_JITED_FUNC_LENS; -@@ -475,6 +481,7 @@ static void perf_env__add_bpf_info(struc - info_linear = get_bpf_prog_info_linear(fd, arrays); - if (IS_ERR_OR_NULL(info_linear)) { - pr_debug("%s: failed to get BPF program info. aborting\n", __func__); -+ err = PTR_ERR(info_linear); - goto out; - } - -@@ -484,38 +491,46 @@ static void perf_env__add_bpf_info(struc - if (info_node) { - info_node->info_linear = info_linear; - if (!perf_env__insert_bpf_prog_info(env, info_node)) { -+ pr_debug("%s: duplicate add bpf info request for id %u\n", -+ __func__, btf_id); - free(info_linear); - free(info_node); -+ goto out; - } -- } else -+ } else { - free(info_linear); -+ err = -ENOMEM; -+ goto out; -+ } - - if (btf_id == 0) - goto out; - - btf = btf__load_from_kernel_by_id(btf_id); -- if (libbpf_get_error(btf)) { -- pr_debug("%s: failed to get BTF of id %u, aborting\n", -- __func__, btf_id); -- goto out; -+ if (!btf) { -+ err = -errno; -+ pr_debug("%s: failed to get BTF of id %u %d\n", __func__, btf_id, err); -+ } else { -+ perf_env__fetch_btf(env, btf_id, btf); - } -- perf_env__fetch_btf(env, btf_id, btf); - - out: - btf__free(btf); - close(fd); -+ return err; - } - - static int bpf_event__sb_cb(union perf_event *event, void *data) - { - struct perf_env *env = data; -+ int ret = 0; - - if (event->header.type != PERF_RECORD_BPF_EVENT) - return -1; - - switch (event->bpf.type) { - case PERF_BPF_EVENT_PROG_LOAD: -- perf_env__add_bpf_info(env, event->bpf.id); -+ ret = perf_env__add_bpf_info(env, event->bpf.id); - - case PERF_BPF_EVENT_PROG_UNLOAD: - /* -@@ -529,7 +544,7 @@ static int bpf_event__sb_cb(union perf_e - break; - } - -- return 0; -+ return ret; - } - - int evlist__add_bpf_sb_event(struct evlist *evlist, struct perf_env *env) -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/util/bpf-utils.c BPI-Router-Linux-kernel-6.16.12/tools/perf/util/bpf-utils.c ---- BPI-Router-Linux-kernel/tools/perf/util/bpf-utils.c 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/util/bpf-utils.c 2025-10-22 13:53:56.867167444 -0400 -@@ -20,7 +20,7 @@ struct bpil_array_desc { - */ - }; - --static struct bpil_array_desc bpil_array_desc[] = { -+static const struct bpil_array_desc bpil_array_desc[] = { - [PERF_BPIL_JITED_INSNS] = { - offsetof(struct bpf_prog_info, jited_prog_insns), - offsetof(struct bpf_prog_info, jited_prog_len), -@@ -115,7 +115,7 @@ get_bpf_prog_info_linear(int fd, __u64 a - __u32 info_len = sizeof(info); - __u32 data_len = 0; - int i, err; -- void *ptr; -+ __u8 *ptr; - - if (arrays >> PERF_BPIL_LAST_ARRAY) - return ERR_PTR(-EINVAL); -@@ -126,15 +126,15 @@ get_bpf_prog_info_linear(int fd, __u64 a - pr_debug("can't get prog info: %s", strerror(errno)); - return ERR_PTR(-EFAULT); - } -+ if (info.type >= __MAX_BPF_PROG_TYPE) -+ pr_debug("%s:%d: unexpected program type %u\n", __func__, __LINE__, info.type); - - /* step 2: calculate total size of all arrays */ - for (i = PERF_BPIL_FIRST_ARRAY; i < PERF_BPIL_LAST_ARRAY; ++i) { -+ const struct bpil_array_desc *desc = &bpil_array_desc[i]; - bool include_array = (arrays & (1UL << i)) > 0; -- struct bpil_array_desc *desc; - __u32 count, size; - -- desc = bpil_array_desc + i; -- - /* kernel is too old to support this field */ - if (info_len < desc->array_offset + sizeof(__u32) || - info_len < desc->count_offset + sizeof(__u32) || -@@ -163,19 +163,20 @@ get_bpf_prog_info_linear(int fd, __u64 a - ptr = info_linear->data; - - for (i = PERF_BPIL_FIRST_ARRAY; i < PERF_BPIL_LAST_ARRAY; ++i) { -- struct bpil_array_desc *desc; -+ const struct bpil_array_desc *desc = &bpil_array_desc[i]; - __u32 count, size; - - if ((arrays & (1UL << i)) == 0) - continue; - -- desc = bpil_array_desc + i; - count = bpf_prog_info_read_offset_u32(&info, desc->count_offset); - size = bpf_prog_info_read_offset_u32(&info, desc->size_offset); - bpf_prog_info_set_offset_u32(&info_linear->info, - desc->count_offset, count); - bpf_prog_info_set_offset_u32(&info_linear->info, - desc->size_offset, size); -+ assert(ptr >= info_linear->data); -+ assert(ptr < &info_linear->data[data_len]); - bpf_prog_info_set_offset_u64(&info_linear->info, - desc->array_offset, - ptr_to_u64(ptr)); -@@ -189,27 +190,45 @@ get_bpf_prog_info_linear(int fd, __u64 a - free(info_linear); - return ERR_PTR(-EFAULT); - } -+ if (info_linear->info.type >= __MAX_BPF_PROG_TYPE) { -+ pr_debug("%s:%d: unexpected program type %u\n", -+ __func__, __LINE__, info_linear->info.type); -+ } - - /* step 6: verify the data */ -+ ptr = info_linear->data; - for (i = PERF_BPIL_FIRST_ARRAY; i < PERF_BPIL_LAST_ARRAY; ++i) { -- struct bpil_array_desc *desc; -- __u32 v1, v2; -+ const struct bpil_array_desc *desc = &bpil_array_desc[i]; -+ __u32 count1, count2, size1, size2; -+ __u64 ptr2; - - if ((arrays & (1UL << i)) == 0) - continue; - -- desc = bpil_array_desc + i; -- v1 = bpf_prog_info_read_offset_u32(&info, desc->count_offset); -- v2 = bpf_prog_info_read_offset_u32(&info_linear->info, -+ count1 = bpf_prog_info_read_offset_u32(&info, desc->count_offset); -+ count2 = bpf_prog_info_read_offset_u32(&info_linear->info, - desc->count_offset); -- if (v1 != v2) -- pr_warning("%s: mismatch in element count\n", __func__); -+ if (count1 != count2) { -+ pr_warning("%s: mismatch in element count %u vs %u\n", __func__, count1, count2); -+ free(info_linear); -+ return ERR_PTR(-ERANGE); -+ } - -- v1 = bpf_prog_info_read_offset_u32(&info, desc->size_offset); -- v2 = bpf_prog_info_read_offset_u32(&info_linear->info, -+ size1 = bpf_prog_info_read_offset_u32(&info, desc->size_offset); -+ size2 = bpf_prog_info_read_offset_u32(&info_linear->info, - desc->size_offset); -- if (v1 != v2) -- pr_warning("%s: mismatch in rec size\n", __func__); -+ if (size1 != size2) { -+ pr_warning("%s: mismatch in rec size %u vs %u\n", __func__, size1, size2); -+ free(info_linear); -+ return ERR_PTR(-ERANGE); -+ } -+ ptr2 = bpf_prog_info_read_offset_u64(&info_linear->info, desc->array_offset); -+ if (ptr_to_u64(ptr) != ptr2) { -+ pr_warning("%s: mismatch in array %p vs %llx\n", __func__, ptr, ptr2); -+ free(info_linear); -+ return ERR_PTR(-ERANGE); -+ } -+ ptr += roundup(count1 * size1, sizeof(__u64)); - } - - /* step 7: update info_len and data_len */ -@@ -224,13 +243,12 @@ void bpil_addr_to_offs(struct perf_bpil - int i; - - for (i = PERF_BPIL_FIRST_ARRAY; i < PERF_BPIL_LAST_ARRAY; ++i) { -- struct bpil_array_desc *desc; -+ const struct bpil_array_desc *desc = &bpil_array_desc[i]; - __u64 addr, offs; - - if ((info_linear->arrays & (1UL << i)) == 0) - continue; - -- desc = bpil_array_desc + i; - addr = bpf_prog_info_read_offset_u64(&info_linear->info, - desc->array_offset); - offs = addr - ptr_to_u64(info_linear->data); -@@ -244,13 +262,12 @@ void bpil_offs_to_addr(struct perf_bpil - int i; - - for (i = PERF_BPIL_FIRST_ARRAY; i < PERF_BPIL_LAST_ARRAY; ++i) { -- struct bpil_array_desc *desc; -+ const struct bpil_array_desc *desc = &bpil_array_desc[i]; - __u64 addr, offs; - - if ((info_linear->arrays & (1UL << i)) == 0) - continue; - -- desc = bpil_array_desc + i; - offs = bpf_prog_info_read_offset_u64(&info_linear->info, - desc->array_offset); - addr = offs + ptr_to_u64(info_linear->data); -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/util/build-id.c BPI-Router-Linux-kernel-6.16.12/tools/perf/util/build-id.c ---- BPI-Router-Linux-kernel/tools/perf/util/build-id.c 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/util/build-id.c 2025-10-22 13:53:56.867167444 -0400 -@@ -864,7 +864,7 @@ static int dso__cache_build_id(struct ds - char *allocated_name = NULL; - int ret = 0; - -- if (!dso__has_build_id(dso)) -+ if (!dso__has_build_id(dso) || !dso__hit(dso)) - return 0; - - if (dso__is_kcore(dso)) { -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/util/evsel.c BPI-Router-Linux-kernel-6.16.12/tools/perf/util/evsel.c ---- BPI-Router-Linux-kernel/tools/perf/util/evsel.c 2025-10-22 13:53:23.691326846 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/util/evsel.c 2025-10-22 13:53:56.867167444 -0400 -@@ -1656,6 +1656,15 @@ static void evsel__free_config_terms(str - free_config_terms(&evsel->config_terms); - } - -+static void (*evsel__priv_destructor)(void *priv); -+ -+void evsel__set_priv_destructor(void (*destructor)(void *priv)) -+{ -+ assert(evsel__priv_destructor == NULL); -+ -+ evsel__priv_destructor = destructor; -+} -+ - void evsel__exit(struct evsel *evsel) - { - assert(list_empty(&evsel->core.node)); -@@ -1686,6 +1695,8 @@ void evsel__exit(struct evsel *evsel) - hashmap__free(evsel->per_pkg_mask); - evsel->per_pkg_mask = NULL; - zfree(&evsel->metric_events); -+ if (evsel__priv_destructor) -+ evsel__priv_destructor(evsel->priv); - perf_evsel__object.fini(evsel); - if (evsel__tool_event(evsel) == TOOL_PMU__EVENT_SYSTEM_TIME || - evsel__tool_event(evsel) == TOOL_PMU__EVENT_USER_TIME) -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/util/evsel.h BPI-Router-Linux-kernel-6.16.12/tools/perf/util/evsel.h ---- BPI-Router-Linux-kernel/tools/perf/util/evsel.h 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/util/evsel.h 2025-10-22 13:53:56.867167444 -0400 -@@ -280,6 +280,8 @@ void evsel__init(struct evsel *evsel, st - void evsel__exit(struct evsel *evsel); - void evsel__delete(struct evsel *evsel); - -+void evsel__set_priv_destructor(void (*destructor)(void *priv)); -+ - struct callchain_param; - - void evsel__config(struct evsel *evsel, struct record_opts *opts, -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/util/hwmon_pmu.c BPI-Router-Linux-kernel-6.16.12/tools/perf/util/hwmon_pmu.c ---- BPI-Router-Linux-kernel/tools/perf/util/hwmon_pmu.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/util/hwmon_pmu.c 2025-10-22 13:53:56.867167444 -0400 -@@ -344,7 +344,7 @@ err_out: - - struct perf_pmu *hwmon_pmu__new(struct list_head *pmus, int hwmon_dir, const char *sysfs_name, const char *name) - { -- char buf[32]; -+ char buf[64]; - struct hwmon_pmu *hwm; - __u32 type = PERF_PMU_TYPE_HWMON_START + strtoul(sysfs_name + 5, NULL, 10); - -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/util/include/linux/linkage.h BPI-Router-Linux-kernel-6.16.12/tools/perf/util/include/linux/linkage.h ---- BPI-Router-Linux-kernel/tools/perf/util/include/linux/linkage.h 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/util/include/linux/linkage.h 2025-10-22 13:53:56.867167444 -0400 -@@ -132,4 +132,8 @@ - SYM_TYPED_START(name, SYM_L_GLOBAL, SYM_A_ALIGN) - #endif - -+#ifndef SYM_PIC_ALIAS -+#define SYM_PIC_ALIAS(sym) SYM_ALIAS(__pi_ ## sym, sym, SYM_T_FUNC, SYM_L_GLOBAL) -+#endif -+ - #endif /* PERF_LINUX_LINKAGE_H_ */ -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/util/maps.c BPI-Router-Linux-kernel-6.16.12/tools/perf/util/maps.c ---- BPI-Router-Linux-kernel/tools/perf/util/maps.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/util/maps.c 2025-10-22 13:53:56.867167444 -0400 -@@ -477,6 +477,7 @@ static int __maps__insert(struct maps *m - } - /* Insert the value at the end. */ - maps_by_address[nr_maps] = map__get(new); -+ map__set_kmap_maps(new, maps); - if (maps_by_name) - maps_by_name[nr_maps] = map__get(new); - -@@ -502,8 +503,6 @@ static int __maps__insert(struct maps *m - if (map__end(new) < map__start(new)) - RC_CHK_ACCESS(maps)->ends_broken = true; - -- map__set_kmap_maps(new, maps); -- - return 0; - } - -@@ -891,6 +890,7 @@ static int __maps__fixup_overlap_and_ins - if (before) { - map__put(maps_by_address[i]); - maps_by_address[i] = before; -+ map__set_kmap_maps(before, maps); - - if (maps_by_name) { - map__put(maps_by_name[ni]); -@@ -918,6 +918,7 @@ static int __maps__fixup_overlap_and_ins - */ - map__put(maps_by_address[i]); - maps_by_address[i] = map__get(new); -+ map__set_kmap_maps(new, maps); - - if (maps_by_name) { - map__put(maps_by_name[ni]); -@@ -942,14 +943,13 @@ static int __maps__fixup_overlap_and_ins - */ - map__put(maps_by_address[i]); - maps_by_address[i] = map__get(new); -+ map__set_kmap_maps(new, maps); - - if (maps_by_name) { - map__put(maps_by_name[ni]); - maps_by_name[ni] = map__get(new); - } - -- map__set_kmap_maps(new, maps); -- - check_invariants(maps); - return err; - } -@@ -1019,6 +1019,7 @@ int maps__copy_from(struct maps *dest, s - err = unwind__prepare_access(dest, new, NULL); - if (!err) { - dest_maps_by_address[i] = new; -+ map__set_kmap_maps(new, dest); - if (dest_maps_by_name) - dest_maps_by_name[i] = map__get(new); - RC_CHK_ACCESS(dest)->nr_maps = i + 1; -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/util/parse-events.c BPI-Router-Linux-kernel-6.16.12/tools/perf/util/parse-events.c ---- BPI-Router-Linux-kernel/tools/perf/util/parse-events.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/util/parse-events.c 2025-10-22 13:53:56.867167444 -0400 -@@ -1829,13 +1829,11 @@ static int parse_events__modifier_list(s - int eH = group ? evsel->core.attr.exclude_host : 0; - int eG = group ? evsel->core.attr.exclude_guest : 0; - int exclude = eu | ek | eh; -- int exclude_GH = group ? evsel->exclude_GH : 0; -+ int exclude_GH = eG | eH; - - if (mod.user) { - if (!exclude) - exclude = eu = ek = eh = 1; -- if (!exclude_GH && !perf_guest && exclude_GH_default) -- eG = 1; - eu = 0; - } - if (mod.kernel) { -@@ -1858,6 +1856,13 @@ static int parse_events__modifier_list(s - exclude_GH = eG = eH = 1; - eH = 0; - } -+ if (!exclude_GH && exclude_GH_default) { -+ if (perf_host) -+ eG = 1; -+ else if (perf_guest) -+ eH = 1; -+ } -+ - evsel->core.attr.exclude_user = eu; - evsel->core.attr.exclude_kernel = ek; - evsel->core.attr.exclude_hv = eh; -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/util/pmu.c BPI-Router-Linux-kernel-6.16.12/tools/perf/util/pmu.c ---- BPI-Router-Linux-kernel/tools/perf/util/pmu.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/util/pmu.c 2025-10-22 13:53:56.867167444 -0400 -@@ -452,7 +452,7 @@ static struct perf_pmu_alias *perf_pmu__ - { - struct perf_pmu_alias *alias; - bool has_sysfs_event; -- char event_file_name[FILENAME_MAX + 8]; -+ char event_file_name[NAME_MAX + 8]; - - if (hashmap__find(pmu->aliases, name, &alias)) - return alias; -@@ -752,7 +752,7 @@ static int pmu_aliases_parse(struct perf - - static int pmu_aliases_parse_eager(struct perf_pmu *pmu, int sysfs_fd) - { -- char path[FILENAME_MAX + 7]; -+ char path[NAME_MAX + 8]; - int ret, events_dir_fd; - - scnprintf(path, sizeof(path), "%s/events", pmu->name); -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/util/print-events.c BPI-Router-Linux-kernel-6.16.12/tools/perf/util/print-events.c ---- BPI-Router-Linux-kernel/tools/perf/util/print-events.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/util/print-events.c 2025-10-22 13:53:56.867167444 -0400 -@@ -268,6 +268,7 @@ bool is_event_supported(u8 type, u64 con - ret = evsel__open(evsel, NULL, tmap) >= 0; - } - -+ evsel__close(evsel); - evsel__delete(evsel); - } - -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/util/python.c BPI-Router-Linux-kernel-6.16.12/tools/perf/util/python.c ---- BPI-Router-Linux-kernel/tools/perf/util/python.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/util/python.c 2025-10-22 13:53:56.867167444 -0400 -@@ -10,6 +10,7 @@ - #endif - #include - #include "callchain.h" -+#include "counts.h" - #include "evlist.h" - #include "evsel.h" - #include "event.h" -@@ -888,12 +889,38 @@ static PyObject *pyrf_evsel__threads(str - return (PyObject *)pthread_map; - } - -+/* -+ * Ensure evsel's counts and prev_raw_counts are allocated, the latter -+ * used by tool PMUs to compute the cumulative count as expected by -+ * stat's process_counter_values. -+ */ -+static int evsel__ensure_counts(struct evsel *evsel) -+{ -+ int nthreads, ncpus; -+ -+ if (evsel->counts != NULL) -+ return 0; -+ -+ nthreads = perf_thread_map__nr(evsel->core.threads); -+ ncpus = perf_cpu_map__nr(evsel->core.cpus); -+ -+ evsel->counts = perf_counts__new(ncpus, nthreads); -+ if (evsel->counts == NULL) -+ return -ENOMEM; -+ -+ evsel->prev_raw_counts = perf_counts__new(ncpus, nthreads); -+ if (evsel->prev_raw_counts == NULL) -+ return -ENOMEM; -+ -+ return 0; -+} -+ - static PyObject *pyrf_evsel__read(struct pyrf_evsel *pevsel, - PyObject *args, PyObject *kwargs) - { - struct evsel *evsel = &pevsel->evsel; - int cpu = 0, cpu_idx, thread = 0, thread_idx; -- struct perf_counts_values counts; -+ struct perf_counts_values *old_count, *new_count; - struct pyrf_counts_values *count_values = PyObject_New(struct pyrf_counts_values, - &pyrf_counts_values__type); - -@@ -909,13 +936,27 @@ static PyObject *pyrf_evsel__read(struct - return NULL; - } - thread_idx = perf_thread_map__idx(evsel->core.threads, thread); -- if (cpu_idx < 0) { -+ if (thread_idx < 0) { - PyErr_Format(PyExc_TypeError, "Thread %d is not part of evsel's threads", - thread); - return NULL; - } -- perf_evsel__read(&(evsel->core), cpu_idx, thread_idx, &counts); -- count_values->values = counts; -+ -+ if (evsel__ensure_counts(evsel)) -+ return PyErr_NoMemory(); -+ -+ /* Set up pointers to the old and newly read counter values. */ -+ old_count = perf_counts(evsel->prev_raw_counts, cpu_idx, thread_idx); -+ new_count = perf_counts(evsel->counts, cpu_idx, thread_idx); -+ /* Update the value in evsel->counts. */ -+ evsel__read_counter(evsel, cpu_idx, thread_idx); -+ /* Copy the value and turn it into the delta from old_count. */ -+ count_values->values = *new_count; -+ count_values->values.val -= old_count->val; -+ count_values->values.ena -= old_count->ena; -+ count_values->values.run -= old_count->run; -+ /* Save the new count over the old_count for the next read. */ -+ *old_count = *new_count; - return (PyObject *)count_values; - } - -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/util/symbol.c BPI-Router-Linux-kernel-6.16.12/tools/perf/util/symbol.c ---- BPI-Router-Linux-kernel/tools/perf/util/symbol.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/util/symbol.c 2025-10-22 13:53:56.867167444 -0400 -@@ -1422,6 +1422,7 @@ static int dso__load_kcore(struct dso *d - goto out_err; - } - } -+ map__zput(new_node->map); - free(new_node); - } - -diff -purNx .git BPI-Router-Linux-kernel/tools/perf/util/symbol-minimal.c BPI-Router-Linux-kernel-6.16.12/tools/perf/util/symbol-minimal.c ---- BPI-Router-Linux-kernel/tools/perf/util/symbol-minimal.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/perf/util/symbol-minimal.c 2025-10-22 13:53:56.867167444 -0400 -@@ -4,7 +4,6 @@ - - #include - #include --#include - #include - #include - #include -@@ -88,11 +87,8 @@ int filename__read_debuglink(const char - */ - int filename__read_build_id(const char *filename, struct build_id *bid) - { -- FILE *fp; -- int ret = -1; -+ int fd, ret = -1; - bool need_swap = false, elf32; -- u8 e_ident[EI_NIDENT]; -- int i; - union { - struct { - Elf32_Ehdr ehdr32; -@@ -103,28 +99,27 @@ int filename__read_build_id(const char * - Elf64_Phdr *phdr64; - }; - } hdrs; -- void *phdr; -- size_t phdr_size; -- void *buf = NULL; -- size_t buf_size = 0; -+ void *phdr, *buf = NULL; -+ ssize_t phdr_size, ehdr_size, buf_size = 0; - -- fp = fopen(filename, "r"); -- if (fp == NULL) -+ fd = open(filename, O_RDONLY); -+ if (fd < 0) - return -1; - -- if (fread(e_ident, sizeof(e_ident), 1, fp) != 1) -+ if (read(fd, hdrs.ehdr32.e_ident, EI_NIDENT) != EI_NIDENT) - goto out; - -- if (memcmp(e_ident, ELFMAG, SELFMAG) || -- e_ident[EI_VERSION] != EV_CURRENT) -+ if (memcmp(hdrs.ehdr32.e_ident, ELFMAG, SELFMAG) || -+ hdrs.ehdr32.e_ident[EI_VERSION] != EV_CURRENT) - goto out; - -- need_swap = check_need_swap(e_ident[EI_DATA]); -- elf32 = e_ident[EI_CLASS] == ELFCLASS32; -- -- if (fread(elf32 ? (void *)&hdrs.ehdr32 : (void *)&hdrs.ehdr64, -- elf32 ? sizeof(hdrs.ehdr32) : sizeof(hdrs.ehdr64), -- 1, fp) != 1) -+ need_swap = check_need_swap(hdrs.ehdr32.e_ident[EI_DATA]); -+ elf32 = hdrs.ehdr32.e_ident[EI_CLASS] == ELFCLASS32; -+ ehdr_size = (elf32 ? sizeof(hdrs.ehdr32) : sizeof(hdrs.ehdr64)) - EI_NIDENT; -+ -+ if (read(fd, -+ (elf32 ? (void *)&hdrs.ehdr32 : (void *)&hdrs.ehdr64) + EI_NIDENT, -+ ehdr_size) != ehdr_size) - goto out; - - if (need_swap) { -@@ -138,14 +133,18 @@ int filename__read_build_id(const char * - hdrs.ehdr64.e_phnum = bswap_16(hdrs.ehdr64.e_phnum); - } - } -- phdr_size = elf32 ? hdrs.ehdr32.e_phentsize * hdrs.ehdr32.e_phnum -- : hdrs.ehdr64.e_phentsize * hdrs.ehdr64.e_phnum; -+ if ((elf32 && hdrs.ehdr32.e_phentsize != sizeof(Elf32_Phdr)) || -+ (!elf32 && hdrs.ehdr64.e_phentsize != sizeof(Elf64_Phdr))) -+ goto out; -+ -+ phdr_size = elf32 ? sizeof(Elf32_Phdr) * hdrs.ehdr32.e_phnum -+ : sizeof(Elf64_Phdr) * hdrs.ehdr64.e_phnum; - phdr = malloc(phdr_size); - if (phdr == NULL) - goto out; - -- fseek(fp, elf32 ? hdrs.ehdr32.e_phoff : hdrs.ehdr64.e_phoff, SEEK_SET); -- if (fread(phdr, phdr_size, 1, fp) != 1) -+ lseek(fd, elf32 ? hdrs.ehdr32.e_phoff : hdrs.ehdr64.e_phoff, SEEK_SET); -+ if (read(fd, phdr, phdr_size) != phdr_size) - goto out_free; - - if (elf32) -@@ -153,8 +152,8 @@ int filename__read_build_id(const char * - else - hdrs.phdr64 = phdr; - -- for (i = 0; i < elf32 ? hdrs.ehdr32.e_phnum : hdrs.ehdr64.e_phnum; i++) { -- size_t p_filesz; -+ for (int i = 0; i < (elf32 ? hdrs.ehdr32.e_phnum : hdrs.ehdr64.e_phnum); i++) { -+ ssize_t p_filesz; - - if (need_swap) { - if (elf32) { -@@ -180,8 +179,8 @@ int filename__read_build_id(const char * - goto out_free; - buf = tmp; - } -- fseek(fp, elf32 ? hdrs.phdr32[i].p_offset : hdrs.phdr64[i].p_offset, SEEK_SET); -- if (fread(buf, p_filesz, 1, fp) != 1) -+ lseek(fd, elf32 ? hdrs.phdr32[i].p_offset : hdrs.phdr64[i].p_offset, SEEK_SET); -+ if (read(fd, buf, p_filesz) != p_filesz) - goto out_free; - - ret = read_build_id(buf, p_filesz, bid, need_swap); -@@ -194,7 +193,7 @@ out_free: - free(buf); - free(phdr); - out: -- fclose(fp); -+ close(fd); - return ret; - } - -diff -purNx .git BPI-Router-Linux-kernel/tools/power/cpupower/Makefile BPI-Router-Linux-kernel-6.16.12/tools/power/cpupower/Makefile ---- BPI-Router-Linux-kernel/tools/power/cpupower/Makefile 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/power/cpupower/Makefile 2025-10-22 13:53:56.867167444 -0400 -@@ -73,6 +73,7 @@ sbindir ?= /usr/sbin - mandir ?= /usr/man - libdir ?= /usr/lib - libexecdir ?= /usr/libexec -+unitdir ?= /usr/lib/systemd/system - includedir ?= /usr/include - localedir ?= /usr/share/locale - docdir ?= /usr/share/doc/packages/cpupower -@@ -309,9 +310,9 @@ install-tools: $(OUTPUT)cpupower - $(INSTALL_DATA) cpupower-service.conf '$(DESTDIR)${confdir}' - $(INSTALL) -d $(DESTDIR)${libexecdir} - $(INSTALL_PROGRAM) cpupower.sh '$(DESTDIR)${libexecdir}/cpupower' -- $(INSTALL) -d $(DESTDIR)${libdir}/systemd/system -- sed 's|___CDIR___|${confdir}|; s|___LDIR___|${libexecdir}|' cpupower.service.in > '$(DESTDIR)${libdir}/systemd/system/cpupower.service' -- $(SETPERM_DATA) '$(DESTDIR)${libdir}/systemd/system/cpupower.service' -+ $(INSTALL) -d $(DESTDIR)${unitdir} -+ sed 's|___CDIR___|${confdir}|; s|___LDIR___|${libexecdir}|' cpupower.service.in > '$(DESTDIR)${unitdir}/cpupower.service' -+ $(SETPERM_DATA) '$(DESTDIR)${unitdir}/cpupower.service' - - install-man: - $(INSTALL_DATA) -D man/cpupower.1 $(DESTDIR)${mandir}/man1/cpupower.1 -@@ -348,7 +349,7 @@ uninstall: - - rm -f $(DESTDIR)${bindir}/utils/cpupower - - rm -f $(DESTDIR)${confdir}cpupower-service.conf - - rm -f $(DESTDIR)${libexecdir}/cpupower -- - rm -f $(DESTDIR)${libdir}/systemd/system/cpupower.service -+ - rm -f $(DESTDIR)${unitdir}/cpupower.service - - rm -f $(DESTDIR)${mandir}/man1/cpupower.1 - - rm -f $(DESTDIR)${mandir}/man1/cpupower-frequency-set.1 - - rm -f $(DESTDIR)${mandir}/man1/cpupower-frequency-info.1 -diff -purNx .git BPI-Router-Linux-kernel/tools/power/cpupower/utils/cpupower-set.c BPI-Router-Linux-kernel-6.16.12/tools/power/cpupower/utils/cpupower-set.c ---- BPI-Router-Linux-kernel/tools/power/cpupower/utils/cpupower-set.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/power/cpupower/utils/cpupower-set.c 2025-10-22 13:53:56.867167444 -0400 -@@ -62,8 +62,8 @@ int cmd_set(int argc, char **argv) - - params.params = 0; - /* parameter parsing */ -- while ((ret = getopt_long(argc, argv, "b:e:m:", -- set_opts, NULL)) != -1) { -+ while ((ret = getopt_long(argc, argv, "b:e:m:t:", -+ set_opts, NULL)) != -1) { - switch (ret) { - case 'b': - if (params.perf_bias) -diff -purNx .git BPI-Router-Linux-kernel/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c BPI-Router-Linux-kernel-6.16.12/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c ---- BPI-Router-Linux-kernel/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c 2025-10-22 13:53:56.867167444 -0400 -@@ -121,10 +121,8 @@ void print_header(int topology_depth) - switch (topology_depth) { - case TOPOLOGY_DEPTH_PKG: - printf(" PKG|"); -- break; - case TOPOLOGY_DEPTH_CORE: - printf("CORE|"); -- break; - case TOPOLOGY_DEPTH_CPU: - printf(" CPU|"); - break; -@@ -167,10 +165,8 @@ void print_results(int topology_depth, i - switch (topology_depth) { - case TOPOLOGY_DEPTH_PKG: - printf("%4d|", cpu_top.core_info[cpu].pkg); -- break; - case TOPOLOGY_DEPTH_CORE: - printf("%4d|", cpu_top.core_info[cpu].core); -- break; - case TOPOLOGY_DEPTH_CPU: - printf("%4d|", cpu_top.core_info[cpu].cpu); - break; -diff -purNx .git BPI-Router-Linux-kernel/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c BPI-Router-Linux-kernel-6.16.12/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c ---- BPI-Router-Linux-kernel/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c 2025-10-22 13:53:56.867167444 -0400 -@@ -240,9 +240,9 @@ static int mperf_stop(void) - int cpu; - - for (cpu = 0; cpu < cpu_count; cpu++) { -- mperf_measure_stats(cpu); -- mperf_get_tsc(&tsc_at_measure_end[cpu]); - clock_gettime(CLOCK_REALTIME, &time_end[cpu]); -+ mperf_get_tsc(&tsc_at_measure_end[cpu]); -+ mperf_measure_stats(cpu); - } - - return 0; -diff -purNx .git BPI-Router-Linux-kernel/tools/power/x86/turbostat/turbostat.c BPI-Router-Linux-kernel-6.16.12/tools/power/x86/turbostat/turbostat.c ---- BPI-Router-Linux-kernel/tools/power/x86/turbostat/turbostat.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/power/x86/turbostat/turbostat.c 2025-10-22 13:53:56.867167444 -0400 -@@ -67,6 +67,7 @@ - #include - #include - #include -+#include - - #define UNUSED(x) (void)(x) - -@@ -840,20 +841,21 @@ static const struct platform_features sp - }; - - static const struct platform_features dmr_features = { -- .has_msr_misc_feature_control = spr_features.has_msr_misc_feature_control, -- .has_msr_misc_pwr_mgmt = spr_features.has_msr_misc_pwr_mgmt, -- .has_nhm_msrs = spr_features.has_nhm_msrs, -- .has_config_tdp = spr_features.has_config_tdp, -- .bclk_freq = spr_features.bclk_freq, -- .supported_cstates = spr_features.supported_cstates, -- .cst_limit = spr_features.cst_limit, -- .has_msr_core_c1_res = spr_features.has_msr_core_c1_res, -- .has_msr_module_c6_res_ms = 1, /* DMR has Dual Core Module and MC6 MSR */ -- .has_irtl_msrs = spr_features.has_irtl_msrs, -- .has_cst_prewake_bit = spr_features.has_cst_prewake_bit, -- .has_fixed_rapl_psys_unit = spr_features.has_fixed_rapl_psys_unit, -- .trl_msrs = spr_features.trl_msrs, -- .rapl_msrs = 0, /* DMR does not have RAPL MSRs */ -+ .has_msr_misc_feature_control = spr_features.has_msr_misc_feature_control, -+ .has_msr_misc_pwr_mgmt = spr_features.has_msr_misc_pwr_mgmt, -+ .has_nhm_msrs = spr_features.has_nhm_msrs, -+ .bclk_freq = spr_features.bclk_freq, -+ .supported_cstates = spr_features.supported_cstates, -+ .cst_limit = spr_features.cst_limit, -+ .has_msr_core_c1_res = spr_features.has_msr_core_c1_res, -+ .has_cst_prewake_bit = spr_features.has_cst_prewake_bit, -+ .has_fixed_rapl_psys_unit = spr_features.has_fixed_rapl_psys_unit, -+ .trl_msrs = spr_features.trl_msrs, -+ .has_msr_module_c6_res_ms = 1, /* DMR has Dual-Core-Module and MC6 MSR */ -+ .rapl_msrs = 0, /* DMR does not have RAPL MSRs */ -+ .plr_msrs = 0, /* DMR does not have PLR MSRs */ -+ .has_irtl_msrs = 0, /* DMR does not have IRTL MSRs */ -+ .has_config_tdp = 0, /* DMR does not have CTDP MSRs */ - }; - - static const struct platform_features srf_features = { -@@ -2429,7 +2431,6 @@ unsigned long long bic_lookup(char *name - - } - if (i == MAX_BIC) { -- fprintf(stderr, "deferred %s\n", name_list); - if (mode == SHOW_LIST) { - deferred_add_names[deferred_add_index++] = name_list; - if (deferred_add_index >= MAX_DEFERRED) { -@@ -6572,8 +6573,16 @@ int check_for_cap_sys_rawio(void) - int ret = 0; - - caps = cap_get_proc(); -- if (caps == NULL) -+ if (caps == NULL) { -+ /* -+ * CONFIG_MULTIUSER=n kernels have no cap_get_proc() -+ * Allow them to continue and attempt to access MSRs -+ */ -+ if (errno == ENOSYS) -+ return 0; -+ - return 1; -+ } - - if (cap_get_flag(caps, CAP_SYS_RAWIO, CAP_EFFECTIVE, &cap_flag_value)) { - ret = 1; -@@ -6740,7 +6749,8 @@ static void probe_intel_uncore_frequency - sprintf(path_base, "/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d", i, - j); - -- if (access(path_base, R_OK)) -+ sprintf(path, "%s/current_freq_khz", path_base); -+ if (access(path, R_OK)) - continue; - - BIC_PRESENT(BIC_UNCORE_MHZ); -@@ -9817,6 +9827,7 @@ int fork_it(char **argv) - timersub(&tv_odd, &tv_even, &tv_delta); - if (for_all_cpus_2(delta_cpu, ODD_COUNTERS, EVEN_COUNTERS)) - fprintf(outf, "%s: Counter reset detected\n", progname); -+ delta_platform(&platform_counters_odd, &platform_counters_even); - - compute_average(EVEN_COUNTERS); - format_all_counters(EVEN_COUNTERS); -@@ -10537,9 +10548,6 @@ void probe_cpuidle_residency(void) - int min_state = 1024, max_state = 0; - char *sp; - -- if (!DO_BIC(BIC_pct_idle)) -- return; -- - for (state = 10; state >= 0; --state) { - - sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name", base_cpu, state); -diff -purNx .git BPI-Router-Linux-kernel/tools/scripts/Makefile.include BPI-Router-Linux-kernel-6.16.12/tools/scripts/Makefile.include ---- BPI-Router-Linux-kernel/tools/scripts/Makefile.include 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/scripts/Makefile.include 2025-10-22 13:53:56.867167444 -0400 -@@ -101,7 +101,9 @@ else ifneq ($(CROSS_COMPILE),) - # Allow userspace to override CLANG_CROSS_FLAGS to specify their own - # sysroots and flags or to avoid the GCC call in pure Clang builds. - ifeq ($(CLANG_CROSS_FLAGS),) --CLANG_CROSS_FLAGS := --target=$(notdir $(CROSS_COMPILE:%-=%)) -+CLANG_TARGET := $(notdir $(CROSS_COMPILE:%-=%)) -+CLANG_TARGET := $(subst s390-linux,s390x-linux,$(CLANG_TARGET)) -+CLANG_CROSS_FLAGS := --target=$(CLANG_TARGET) - GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)gcc 2>/dev/null)) - ifneq ($(GCC_TOOLCHAIN_DIR),) - CLANG_CROSS_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE)) -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/ktest/ktest.pl BPI-Router-Linux-kernel-6.16.12/tools/testing/ktest/ktest.pl ---- BPI-Router-Linux-kernel/tools/testing/ktest/ktest.pl 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/ktest/ktest.pl 2025-10-22 13:53:56.867167444 -0400 -@@ -1371,7 +1371,10 @@ sub __eval_option { - # If a variable contains itself, use the default var - if (($var eq $name) && defined($opt{$var})) { - $o = $opt{$var}; -- $retval = "$retval$o"; -+ # Only append if the default doesn't contain itself -+ if ($o !~ m/\$\{$var\}/) { -+ $retval = "$retval$o"; -+ } - } elsif (defined($opt{$o})) { - $o = $opt{$o}; - $retval = "$retval$o"; -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/alsa/utimer-test.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/alsa/utimer-test.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/alsa/utimer-test.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/alsa/utimer-test.c 2025-10-22 13:53:56.867167444 -0400 -@@ -135,6 +135,7 @@ TEST_F(timer_f, utimer) { - pthread_join(ticking_thread, NULL); - ASSERT_EQ(total_ticks, TICKS_COUNT); - pclose(rfp); -+ free(buf); - } - - TEST(wrong_timers_test) { -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/arm64/fp/sve-ptrace.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/arm64/fp/sve-ptrace.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/arm64/fp/sve-ptrace.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/arm64/fp/sve-ptrace.c 2025-10-22 13:53:56.867167444 -0400 -@@ -170,7 +170,7 @@ static void ptrace_set_get_inherit(pid_t - memset(&sve, 0, sizeof(sve)); - sve.size = sizeof(sve); - sve.vl = sve_vl_from_vq(SVE_VQ_MIN); -- sve.flags = SVE_PT_VL_INHERIT; -+ sve.flags = SVE_PT_VL_INHERIT | SVE_PT_REGS_SVE; - ret = set_sve(child, type, &sve); - if (ret != 0) { - ksft_test_result_fail("Failed to set %s SVE_PT_VL_INHERIT\n", -@@ -235,6 +235,7 @@ static void ptrace_set_get_vl(pid_t chil - /* Set the VL by doing a set with no register payload */ - memset(&sve, 0, sizeof(sve)); - sve.size = sizeof(sve); -+ sve.flags = SVE_PT_REGS_SVE; - sve.vl = vl; - ret = set_sve(child, type, &sve); - if (ret != 0) { -@@ -253,7 +254,7 @@ static void ptrace_set_get_vl(pid_t chil - return; - } - -- ksft_test_result(new_sve->vl = prctl_vl, "Set %s VL %u\n", -+ ksft_test_result(new_sve->vl == prctl_vl, "Set %s VL %u\n", - type->name, vl); - - free(new_sve); -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/bpf/bpf_atomic.h BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/bpf_atomic.h ---- BPI-Router-Linux-kernel/tools/testing/selftests/bpf/bpf_atomic.h 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/bpf_atomic.h 2025-10-22 13:53:56.867167444 -0400 -@@ -61,7 +61,7 @@ extern bool CONFIG_X86_64 __kconfig __we - - #define smp_mb() \ - ({ \ -- unsigned long __val; \ -+ volatile unsigned long __val; \ - __sync_fetch_and_add(&__val, 0); \ - }) - -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/bpf/.gitignore BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/.gitignore ---- BPI-Router-Linux-kernel/tools/testing/selftests/bpf/.gitignore 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/.gitignore 2025-10-22 13:53:56.867167444 -0400 -@@ -21,7 +21,6 @@ test_lirc_mode2_user - flow_dissector_load - test_tcpnotify_user - test_libbpf --test_sysctl - xdping - test_cpp - *.d -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/bpf/Makefile BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/Makefile ---- BPI-Router-Linux-kernel/tools/testing/selftests/bpf/Makefile 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/Makefile 2025-10-22 13:53:56.867167444 -0400 -@@ -73,7 +73,7 @@ endif - # Order correspond to 'make run_tests' order - TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_progs \ - test_sockmap \ -- test_tcpnotify_user test_sysctl \ -+ test_tcpnotify_user \ - test_progs-no_alu32 - TEST_INST_SUBDIRS := no_alu32 - -@@ -220,7 +220,7 @@ ifeq ($(VMLINUX_BTF),) - $(error Cannot find a vmlinux for VMLINUX_BTF at any of "$(VMLINUX_BTF_PATHS)") - endif - --# Define simple and short `make test_progs`, `make test_sysctl`, etc targets -+# Define simple and short `make test_progs`, `make test_maps`, etc targets - # to build individual tests. - # NOTE: Semicolon at the end is critical to override lib.mk's default static - # rule for binaries. -@@ -329,7 +329,6 @@ NETWORK_HELPERS := $(OUTPUT)/network_hel - $(OUTPUT)/test_sockmap: $(CGROUP_HELPERS) $(TESTING_HELPERS) - $(OUTPUT)/test_tcpnotify_user: $(CGROUP_HELPERS) $(TESTING_HELPERS) $(TRACE_HELPERS) - $(OUTPUT)/test_sock_fields: $(CGROUP_HELPERS) $(TESTING_HELPERS) --$(OUTPUT)/test_sysctl: $(CGROUP_HELPERS) $(TESTING_HELPERS) - $(OUTPUT)/test_tag: $(TESTING_HELPERS) - $(OUTPUT)/test_lirc_mode2_user: $(TESTING_HELPERS) - $(OUTPUT)/xdping: $(TESTING_HELPERS) -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/bpf/progs/test_global_map_resize.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/progs/test_global_map_resize.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/bpf/progs/test_global_map_resize.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/progs/test_global_map_resize.c 2025-10-22 13:53:56.871167425 -0400 -@@ -32,6 +32,16 @@ int my_int_last SEC(".data.array_not_las - - int percpu_arr[1] SEC(".data.percpu_arr"); - -+/* at least one extern is included, to ensure that a specific -+ * regression is tested whereby resizing resulted in a free-after-use -+ * bug after type information is invalidated by the resize operation. -+ * -+ * There isn't a particularly good API to test for this specific condition, -+ * but by having externs for the resizing tests it will cover this path. -+ */ -+extern int LINUX_KERNEL_VERSION __kconfig; -+long version_sink; -+ - SEC("tp/syscalls/sys_enter_getpid") - int bss_array_sum(void *ctx) - { -@@ -44,6 +54,9 @@ int bss_array_sum(void *ctx) - for (size_t i = 0; i < bss_array_len; ++i) - sum += array[i]; - -+ /* see above; ensure this is not optimized out */ -+ version_sink = LINUX_KERNEL_VERSION; -+ - return 0; - } - -@@ -59,6 +72,9 @@ int data_array_sum(void *ctx) - for (size_t i = 0; i < data_array_len; ++i) - sum += my_array[i]; - -+ /* see above; ensure this is not optimized out */ -+ version_sink = LINUX_KERNEL_VERSION; -+ - return 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/bpf/progs/test_ringbuf_write.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/progs/test_ringbuf_write.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/bpf/progs/test_ringbuf_write.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/progs/test_ringbuf_write.c 2025-10-22 13:53:56.871167425 -0400 -@@ -26,11 +26,11 @@ int test_ringbuf_write(void *ctx) - if (cur_pid != pid) - return 0; - -- sample1 = bpf_ringbuf_reserve(&ringbuf, 0x3000, 0); -+ sample1 = bpf_ringbuf_reserve(&ringbuf, 0x30000, 0); - if (!sample1) - return 0; - /* first one can pass */ -- sample2 = bpf_ringbuf_reserve(&ringbuf, 0x3000, 0); -+ sample2 = bpf_ringbuf_reserve(&ringbuf, 0x30000, 0); - if (!sample2) { - bpf_ringbuf_discard(sample1, 0); - __sync_fetch_and_add(&discarded, 1); -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/bpf/progs/verifier_unpriv.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/progs/verifier_unpriv.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/bpf/progs/verifier_unpriv.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/progs/verifier_unpriv.c 2025-10-22 13:53:56.871167425 -0400 -@@ -619,7 +619,7 @@ __naked void pass_pointer_to_tail_call(v - - SEC("socket") - __description("unpriv: cmp map pointer with zero") --__success __failure_unpriv __msg_unpriv("R1 pointer comparison") -+__success __success_unpriv - __retval(0) - __naked void cmp_map_pointer_with_zero(void) - { -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/bpf/progs/verifier_vfs_accept.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/progs/verifier_vfs_accept.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/bpf/progs/verifier_vfs_accept.c 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/progs/verifier_vfs_accept.c 2025-10-22 13:53:56.871167425 -0400 -@@ -2,6 +2,7 @@ - /* Copyright (c) 2024 Google LLC. */ - - #include -+#include - #include - #include - -@@ -82,4 +83,21 @@ int BPF_PROG(path_d_path_from_file_argum - return 0; - } - -+SEC("lsm.s/inode_rename") -+__success -+int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry, -+ struct inode *new_dir, struct dentry *new_dentry, -+ unsigned int flags) -+{ -+ struct inode *inode = new_dentry->d_inode; -+ ino_t ino; -+ -+ if (!inode) -+ return 0; -+ ino = inode->i_ino; -+ if (ino == 0) -+ return -EACCES; -+ return 0; -+} -+ - char _license[] SEC("license") = "GPL"; -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/bpf/progs/verifier_vfs_reject.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/progs/verifier_vfs_reject.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/bpf/progs/verifier_vfs_reject.c 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/progs/verifier_vfs_reject.c 2025-10-22 13:53:56.871167425 -0400 -@@ -2,6 +2,7 @@ - /* Copyright (c) 2024 Google LLC. */ - - #include -+#include - #include - #include - #include -@@ -158,4 +159,18 @@ int BPF_PROG(path_d_path_kfunc_non_lsm, - return 0; - } - -+SEC("lsm.s/inode_rename") -+__failure __msg("invalid mem access 'trusted_ptr_or_null_'") -+int BPF_PROG(inode_rename, struct inode *old_dir, struct dentry *old_dentry, -+ struct inode *new_dir, struct dentry *new_dentry, -+ unsigned int flags) -+{ -+ struct inode *inode = new_dentry->d_inode; -+ ino_t ino; -+ -+ ino = inode->i_ino; -+ if (ino == 0) -+ return -EACCES; -+ return 0; -+} - char _license[] SEC("license") = "GPL"; -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/bpf/prog_tests/free_timer.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/prog_tests/free_timer.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/bpf/prog_tests/free_timer.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/prog_tests/free_timer.c 2025-10-22 13:53:56.867167444 -0400 -@@ -124,6 +124,10 @@ void test_free_timer(void) - int err; - - skel = free_timer__open_and_load(); -+ if (!skel && errno == EOPNOTSUPP) { -+ test__skip(); -+ return; -+ } - if (!ASSERT_OK_PTR(skel, "open_load")) - return; - -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/bpf/prog_tests/recursive_attach.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/prog_tests/recursive_attach.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/bpf/prog_tests/recursive_attach.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/prog_tests/recursive_attach.c 2025-10-22 13:53:56.867167444 -0400 -@@ -149,3 +149,70 @@ close_prog: - fentry_recursive_target__destroy(target_skel); - fentry_recursive__destroy(tracing_skel); - } -+ -+static void *fentry_target_test_run(void *arg) -+{ -+ for (;;) { -+ int prog_fd = __atomic_load_n((int *)arg, __ATOMIC_SEQ_CST); -+ LIBBPF_OPTS(bpf_test_run_opts, topts); -+ int err; -+ -+ if (prog_fd == -1) -+ break; -+ err = bpf_prog_test_run_opts(prog_fd, &topts); -+ if (!ASSERT_OK(err, "fentry_target test_run")) -+ break; -+ } -+ -+ return NULL; -+} -+ -+void test_fentry_attach_stress(void) -+{ -+ struct fentry_recursive_target *target_skel = NULL; -+ struct fentry_recursive *tracing_skel = NULL; -+ struct bpf_program *prog; -+ int err, i, tgt_prog_fd; -+ pthread_t thread; -+ -+ target_skel = fentry_recursive_target__open_and_load(); -+ if (!ASSERT_OK_PTR(target_skel, -+ "fentry_recursive_target__open_and_load")) -+ goto close_prog; -+ tgt_prog_fd = bpf_program__fd(target_skel->progs.fentry_target); -+ err = pthread_create(&thread, NULL, -+ fentry_target_test_run, &tgt_prog_fd); -+ if (!ASSERT_OK(err, "bpf_program__set_attach_target")) -+ goto close_prog; -+ -+ for (i = 0; i < 1000; i++) { -+ tracing_skel = fentry_recursive__open(); -+ if (!ASSERT_OK_PTR(tracing_skel, "fentry_recursive__open")) -+ goto stop_thread; -+ -+ prog = tracing_skel->progs.recursive_attach; -+ err = bpf_program__set_attach_target(prog, tgt_prog_fd, -+ "fentry_target"); -+ if (!ASSERT_OK(err, "bpf_program__set_attach_target")) -+ goto stop_thread; -+ -+ err = fentry_recursive__load(tracing_skel); -+ if (!ASSERT_OK(err, "fentry_recursive__load")) -+ goto stop_thread; -+ -+ err = fentry_recursive__attach(tracing_skel); -+ if (!ASSERT_OK(err, "fentry_recursive__attach")) -+ goto stop_thread; -+ -+ fentry_recursive__destroy(tracing_skel); -+ tracing_skel = NULL; -+ } -+ -+stop_thread: -+ __atomic_store_n(&tgt_prog_fd, -1, __ATOMIC_SEQ_CST); -+ err = pthread_join(thread, NULL); -+ ASSERT_OK(err, "pthread_join"); -+close_prog: -+ fentry_recursive__destroy(tracing_skel); -+ fentry_recursive_target__destroy(target_skel); -+} -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/bpf/prog_tests/ringbuf.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/prog_tests/ringbuf.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/bpf/prog_tests/ringbuf.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/prog_tests/ringbuf.c 2025-10-22 13:53:56.867167444 -0400 -@@ -97,7 +97,7 @@ static void ringbuf_write_subtest(void) - if (!ASSERT_OK_PTR(skel, "skel_open")) - return; - -- skel->maps.ringbuf.max_entries = 0x4000; -+ skel->maps.ringbuf.max_entries = 0x40000; - - err = test_ringbuf_write_lskel__load(skel); - if (!ASSERT_OK(err, "skel_load")) -@@ -108,7 +108,7 @@ static void ringbuf_write_subtest(void) - mmap_ptr = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, rb_fd, 0); - if (!ASSERT_OK_PTR(mmap_ptr, "rw_cons_pos")) - goto cleanup; -- *mmap_ptr = 0x3000; -+ *mmap_ptr = 0x30000; - ASSERT_OK(munmap(mmap_ptr, page_size), "unmap_rw"); - - skel->bss->pid = getpid(); -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/bpf/prog_tests/snprintf.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/prog_tests/snprintf.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/bpf/prog_tests/snprintf.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/prog_tests/snprintf.c 2025-10-22 13:53:56.867167444 -0400 -@@ -116,6 +116,8 @@ static void test_snprintf_negative(void) - ASSERT_ERR(load_single_snprintf("%llc"), "invalid specifier 7"); - ASSERT_ERR(load_single_snprintf("\x80"), "non ascii character"); - ASSERT_ERR(load_single_snprintf("\x1"), "non printable character"); -+ ASSERT_ERR(load_single_snprintf("%p%"), "invalid specifier 8"); -+ ASSERT_ERR(load_single_snprintf("%s%"), "invalid specifier 9"); - } - - void test_snprintf(void) -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/prog_tests/sockmap_listen.c 2025-10-22 13:53:56.867167444 -0400 -@@ -924,6 +924,8 @@ static void redir_partial(int family, in - goto close; - - n = xsend(c1, buf, sizeof(buf), 0); -+ if (n == -1) -+ goto close; - if (n < sizeof(buf)) - FAIL("incomplete write"); - -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/bpf/prog_tests/test_sysctl.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/prog_tests/test_sysctl.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/bpf/prog_tests/test_sysctl.c 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/prog_tests/test_sysctl.c 2025-10-22 13:53:56.867167444 -0400 -@@ -0,0 +1,1612 @@ -+// SPDX-License-Identifier: GPL-2.0 -+// Copyright (c) 2019 Facebook -+ -+#include "test_progs.h" -+#include "cgroup_helpers.h" -+ -+#define CG_PATH "/foo" -+#define MAX_INSNS 512 -+#define FIXUP_SYSCTL_VALUE 0 -+ -+char bpf_log_buf[BPF_LOG_BUF_SIZE]; -+ -+struct sysctl_test { -+ const char *descr; -+ size_t fixup_value_insn; -+ struct bpf_insn insns[MAX_INSNS]; -+ const char *prog_file; -+ enum bpf_attach_type attach_type; -+ const char *sysctl; -+ int open_flags; -+ int seek; -+ const char *newval; -+ const char *oldval; -+ enum { -+ LOAD_REJECT, -+ ATTACH_REJECT, -+ OP_EPERM, -+ SUCCESS, -+ } result; -+}; -+ -+static struct sysctl_test tests[] = { -+ { -+ .descr = "sysctl wrong attach_type", -+ .insns = { -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = 0, -+ .sysctl = "kernel/ostype", -+ .open_flags = O_RDONLY, -+ .result = ATTACH_REJECT, -+ }, -+ { -+ .descr = "sysctl:read allow all", -+ .insns = { -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "kernel/ostype", -+ .open_flags = O_RDONLY, -+ .result = SUCCESS, -+ }, -+ { -+ .descr = "sysctl:read deny all", -+ .insns = { -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "kernel/ostype", -+ .open_flags = O_RDONLY, -+ .result = OP_EPERM, -+ }, -+ { -+ .descr = "ctx:write sysctl:read read ok", -+ .insns = { -+ /* If (write) */ -+ BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1, -+ offsetof(struct bpf_sysctl, write)), -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 1, 2), -+ -+ /* return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_JMP_A(1), -+ -+ /* else return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "kernel/ostype", -+ .open_flags = O_RDONLY, -+ .result = SUCCESS, -+ }, -+ { -+ .descr = "ctx:write sysctl:write read ok", -+ .insns = { -+ /* If (write) */ -+ BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1, -+ offsetof(struct bpf_sysctl, write)), -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 1, 2), -+ -+ /* return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_JMP_A(1), -+ -+ /* else return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "kernel/domainname", -+ .open_flags = O_WRONLY, -+ .newval = "(none)", /* same as default, should fail anyway */ -+ .result = OP_EPERM, -+ }, -+ { -+ .descr = "ctx:write sysctl:write read ok narrow", -+ .insns = { -+ /* u64 w = (u16)write & 1; */ -+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -+ BPF_LDX_MEM(BPF_H, BPF_REG_7, BPF_REG_1, -+ offsetof(struct bpf_sysctl, write)), -+#else -+ BPF_LDX_MEM(BPF_H, BPF_REG_7, BPF_REG_1, -+ offsetof(struct bpf_sysctl, write) + 2), -+#endif -+ BPF_ALU64_IMM(BPF_AND, BPF_REG_7, 1), -+ /* return 1 - w; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_7), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "kernel/domainname", -+ .open_flags = O_WRONLY, -+ .newval = "(none)", /* same as default, should fail anyway */ -+ .result = OP_EPERM, -+ }, -+ { -+ .descr = "ctx:write sysctl:read write reject", -+ .insns = { -+ /* write = X */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, -+ offsetof(struct bpf_sysctl, write)), -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "kernel/ostype", -+ .open_flags = O_RDONLY, -+ .result = LOAD_REJECT, -+ }, -+ { -+ .descr = "ctx:file_pos sysctl:read read ok", -+ .insns = { -+ /* If (file_pos == X) */ -+ BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1, -+ offsetof(struct bpf_sysctl, file_pos)), -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 3, 2), -+ -+ /* return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_JMP_A(1), -+ -+ /* else return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "kernel/ostype", -+ .open_flags = O_RDONLY, -+ .seek = 3, -+ .result = SUCCESS, -+ }, -+ { -+ .descr = "ctx:file_pos sysctl:read read ok narrow", -+ .insns = { -+ /* If (file_pos == X) */ -+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -+ BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_1, -+ offsetof(struct bpf_sysctl, file_pos)), -+#else -+ BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_1, -+ offsetof(struct bpf_sysctl, file_pos) + 3), -+#endif -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 4, 2), -+ -+ /* return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_JMP_A(1), -+ -+ /* else return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "kernel/ostype", -+ .open_flags = O_RDONLY, -+ .seek = 4, -+ .result = SUCCESS, -+ }, -+ { -+ .descr = "ctx:file_pos sysctl:read write ok", -+ .insns = { -+ /* file_pos = X */ -+ BPF_MOV64_IMM(BPF_REG_0, 2), -+ BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, -+ offsetof(struct bpf_sysctl, file_pos)), -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "kernel/ostype", -+ .open_flags = O_RDONLY, -+ .oldval = "nux\n", -+ .result = SUCCESS, -+ }, -+ { -+ .descr = "sysctl_get_name sysctl_value:base ok", -+ .insns = { -+ /* sysctl_get_name arg2 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ -+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -+ -+ /* sysctl_get_name arg3 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_3, 8), -+ -+ /* sysctl_get_name arg4 (flags) */ -+ BPF_MOV64_IMM(BPF_REG_4, BPF_F_SYSCTL_BASE_NAME), -+ -+ /* sysctl_get_name(ctx, buf, buf_len, flags) */ -+ BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name), -+ -+ /* if (ret == expected && */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, sizeof("tcp_mem") - 1, 6), -+ /* buf == "tcp_mem\0") */ -+ BPF_LD_IMM64(BPF_REG_8, -+ bpf_be64_to_cpu(0x7463705f6d656d00ULL)), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -+ BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2), -+ -+ /* return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_JMP_A(1), -+ -+ /* else return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/tcp_mem", -+ .open_flags = O_RDONLY, -+ .result = SUCCESS, -+ }, -+ { -+ .descr = "sysctl_get_name sysctl_value:base E2BIG truncated", -+ .insns = { -+ /* sysctl_get_name arg2 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ -+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -+ -+ /* sysctl_get_name arg3 (buf_len) too small */ -+ BPF_MOV64_IMM(BPF_REG_3, 7), -+ -+ /* sysctl_get_name arg4 (flags) */ -+ BPF_MOV64_IMM(BPF_REG_4, BPF_F_SYSCTL_BASE_NAME), -+ -+ /* sysctl_get_name(ctx, buf, buf_len, flags) */ -+ BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name), -+ -+ /* if (ret == expected && */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6), -+ -+ /* buf[0:7] == "tcp_me\0") */ -+ BPF_LD_IMM64(BPF_REG_8, -+ bpf_be64_to_cpu(0x7463705f6d650000ULL)), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -+ BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2), -+ -+ /* return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_JMP_A(1), -+ -+ /* else return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/tcp_mem", -+ .open_flags = O_RDONLY, -+ .result = SUCCESS, -+ }, -+ { -+ .descr = "sysctl_get_name sysctl:full ok", -+ .insns = { -+ /* sysctl_get_name arg2 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -24), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 8), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 16), -+ -+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -+ -+ /* sysctl_get_name arg3 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_3, 17), -+ -+ /* sysctl_get_name arg4 (flags) */ -+ BPF_MOV64_IMM(BPF_REG_4, 0), -+ -+ /* sysctl_get_name(ctx, buf, buf_len, flags) */ -+ BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name), -+ -+ /* if (ret == expected && */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 16, 14), -+ -+ /* buf[0:8] == "net/ipv4" && */ -+ BPF_LD_IMM64(BPF_REG_8, -+ bpf_be64_to_cpu(0x6e65742f69707634ULL)), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -+ BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 10), -+ -+ /* buf[8:16] == "/tcp_mem" && */ -+ BPF_LD_IMM64(BPF_REG_8, -+ bpf_be64_to_cpu(0x2f7463705f6d656dULL)), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 8), -+ BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 6), -+ -+ /* buf[16:24] == "\0") */ -+ BPF_LD_IMM64(BPF_REG_8, 0x0ULL), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 16), -+ BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2), -+ -+ /* return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_JMP_A(1), -+ -+ /* else return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/tcp_mem", -+ .open_flags = O_RDONLY, -+ .result = SUCCESS, -+ }, -+ { -+ .descr = "sysctl_get_name sysctl:full E2BIG truncated", -+ .insns = { -+ /* sysctl_get_name arg2 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -16), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 8), -+ -+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -+ -+ /* sysctl_get_name arg3 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_3, 16), -+ -+ /* sysctl_get_name arg4 (flags) */ -+ BPF_MOV64_IMM(BPF_REG_4, 0), -+ -+ /* sysctl_get_name(ctx, buf, buf_len, flags) */ -+ BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name), -+ -+ /* if (ret == expected && */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 10), -+ -+ /* buf[0:8] == "net/ipv4" && */ -+ BPF_LD_IMM64(BPF_REG_8, -+ bpf_be64_to_cpu(0x6e65742f69707634ULL)), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -+ BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 6), -+ -+ /* buf[8:16] == "/tcp_me\0") */ -+ BPF_LD_IMM64(BPF_REG_8, -+ bpf_be64_to_cpu(0x2f7463705f6d6500ULL)), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 8), -+ BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2), -+ -+ /* return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_JMP_A(1), -+ -+ /* else return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/tcp_mem", -+ .open_flags = O_RDONLY, -+ .result = SUCCESS, -+ }, -+ { -+ .descr = "sysctl_get_name sysctl:full E2BIG truncated small", -+ .insns = { -+ /* sysctl_get_name arg2 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ -+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -+ -+ /* sysctl_get_name arg3 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_3, 7), -+ -+ /* sysctl_get_name arg4 (flags) */ -+ BPF_MOV64_IMM(BPF_REG_4, 0), -+ -+ /* sysctl_get_name(ctx, buf, buf_len, flags) */ -+ BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name), -+ -+ /* if (ret == expected && */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6), -+ -+ /* buf[0:8] == "net/ip\0") */ -+ BPF_LD_IMM64(BPF_REG_8, -+ bpf_be64_to_cpu(0x6e65742f69700000ULL)), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -+ BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2), -+ -+ /* return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_JMP_A(1), -+ -+ /* else return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/tcp_mem", -+ .open_flags = O_RDONLY, -+ .result = SUCCESS, -+ }, -+ { -+ .descr = "sysctl_get_current_value sysctl:read ok, gt", -+ .insns = { -+ /* sysctl_get_current_value arg2 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -+ -+ /* sysctl_get_current_value arg3 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_3, 8), -+ -+ /* sysctl_get_current_value(ctx, buf, buf_len) */ -+ BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value), -+ -+ /* if (ret == expected && */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 6, 6), -+ -+ /* buf[0:6] == "Linux\n\0") */ -+ BPF_LD_IMM64(BPF_REG_8, -+ bpf_be64_to_cpu(0x4c696e75780a0000ULL)), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -+ BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2), -+ -+ /* return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_JMP_A(1), -+ -+ /* else return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "kernel/ostype", -+ .open_flags = O_RDONLY, -+ .result = SUCCESS, -+ }, -+ { -+ .descr = "sysctl_get_current_value sysctl:read ok, eq", -+ .insns = { -+ /* sysctl_get_current_value arg2 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_STX_MEM(BPF_B, BPF_REG_7, BPF_REG_0, 7), -+ -+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -+ -+ /* sysctl_get_current_value arg3 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_3, 7), -+ -+ /* sysctl_get_current_value(ctx, buf, buf_len) */ -+ BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value), -+ -+ /* if (ret == expected && */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 6, 6), -+ -+ /* buf[0:6] == "Linux\n\0") */ -+ BPF_LD_IMM64(BPF_REG_8, -+ bpf_be64_to_cpu(0x4c696e75780a0000ULL)), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -+ BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2), -+ -+ /* return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_JMP_A(1), -+ -+ /* else return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "kernel/ostype", -+ .open_flags = O_RDONLY, -+ .result = SUCCESS, -+ }, -+ { -+ .descr = "sysctl_get_current_value sysctl:read E2BIG truncated", -+ .insns = { -+ /* sysctl_get_current_value arg2 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_STX_MEM(BPF_H, BPF_REG_7, BPF_REG_0, 6), -+ -+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -+ -+ /* sysctl_get_current_value arg3 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_3, 6), -+ -+ /* sysctl_get_current_value(ctx, buf, buf_len) */ -+ BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value), -+ -+ /* if (ret == expected && */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6), -+ -+ /* buf[0:6] == "Linux\0") */ -+ BPF_LD_IMM64(BPF_REG_8, -+ bpf_be64_to_cpu(0x4c696e7578000000ULL)), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -+ BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2), -+ -+ /* return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_JMP_A(1), -+ -+ /* else return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "kernel/ostype", -+ .open_flags = O_RDONLY, -+ .result = SUCCESS, -+ }, -+ { -+ .descr = "sysctl_get_current_value sysctl:read EINVAL", -+ .insns = { -+ /* sysctl_get_current_value arg2 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ -+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -+ -+ /* sysctl_get_current_value arg3 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_3, 8), -+ -+ /* sysctl_get_current_value(ctx, buf, buf_len) */ -+ BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value), -+ -+ /* if (ret == expected && */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 4), -+ -+ /* buf[0:8] is NUL-filled) */ -+ BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 0, 2), -+ -+ /* return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_JMP_A(1), -+ -+ /* else return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv6/conf/lo/stable_secret", /* -EIO */ -+ .open_flags = O_RDONLY, -+ .result = OP_EPERM, -+ }, -+ { -+ .descr = "sysctl_get_current_value sysctl:write ok", -+ .fixup_value_insn = 6, -+ .insns = { -+ /* sysctl_get_current_value arg2 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ -+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -+ -+ /* sysctl_get_current_value arg3 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_3, 8), -+ -+ /* sysctl_get_current_value(ctx, buf, buf_len) */ -+ BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value), -+ -+ /* if (ret == expected && */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 6), -+ -+ /* buf[0:4] == expected) */ -+ BPF_LD_IMM64(BPF_REG_8, FIXUP_SYSCTL_VALUE), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -+ BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2), -+ -+ /* return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_JMP_A(1), -+ -+ /* else return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/route/mtu_expires", -+ .open_flags = O_WRONLY, -+ .newval = "600", /* same as default, should fail anyway */ -+ .result = OP_EPERM, -+ }, -+ { -+ .descr = "sysctl_get_new_value sysctl:read EINVAL", -+ .insns = { -+ /* sysctl_get_new_value arg2 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ -+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -+ -+ /* sysctl_get_new_value arg3 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_3, 8), -+ -+ /* sysctl_get_new_value(ctx, buf, buf_len) */ -+ BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value), -+ -+ /* if (ret == expected) */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2), -+ -+ /* return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_JMP_A(1), -+ -+ /* else return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/tcp_mem", -+ .open_flags = O_RDONLY, -+ .result = SUCCESS, -+ }, -+ { -+ .descr = "sysctl_get_new_value sysctl:write ok", -+ .insns = { -+ /* sysctl_get_new_value arg2 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ -+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -+ -+ /* sysctl_get_new_value arg3 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_3, 4), -+ -+ /* sysctl_get_new_value(ctx, buf, buf_len) */ -+ BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value), -+ -+ /* if (ret == expected && */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4), -+ -+ /* buf[0:4] == "606\0") */ -+ BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_7, 0), -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_9, -+ bpf_ntohl(0x36303600), 2), -+ -+ /* return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_JMP_A(1), -+ -+ /* else return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/route/mtu_expires", -+ .open_flags = O_WRONLY, -+ .newval = "606", -+ .result = OP_EPERM, -+ }, -+ { -+ .descr = "sysctl_get_new_value sysctl:write ok long", -+ .insns = { -+ /* sysctl_get_new_value arg2 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -24), -+ -+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -+ -+ /* sysctl_get_new_value arg3 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_3, 24), -+ -+ /* sysctl_get_new_value(ctx, buf, buf_len) */ -+ BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value), -+ -+ /* if (ret == expected && */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 23, 14), -+ -+ /* buf[0:8] == "3000000 " && */ -+ BPF_LD_IMM64(BPF_REG_8, -+ bpf_be64_to_cpu(0x3330303030303020ULL)), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -+ BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 10), -+ -+ /* buf[8:16] == "4000000 " && */ -+ BPF_LD_IMM64(BPF_REG_8, -+ bpf_be64_to_cpu(0x3430303030303020ULL)), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 8), -+ BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 6), -+ -+ /* buf[16:24] == "6000000\0") */ -+ BPF_LD_IMM64(BPF_REG_8, -+ bpf_be64_to_cpu(0x3630303030303000ULL)), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 16), -+ BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2), -+ -+ /* return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_JMP_A(1), -+ -+ /* else return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/tcp_mem", -+ .open_flags = O_WRONLY, -+ .newval = "3000000 4000000 6000000", -+ .result = OP_EPERM, -+ }, -+ { -+ .descr = "sysctl_get_new_value sysctl:write E2BIG", -+ .insns = { -+ /* sysctl_get_new_value arg2 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_STX_MEM(BPF_B, BPF_REG_7, BPF_REG_0, 3), -+ -+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -+ -+ /* sysctl_get_new_value arg3 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_3, 3), -+ -+ /* sysctl_get_new_value(ctx, buf, buf_len) */ -+ BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value), -+ -+ /* if (ret == expected && */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 4), -+ -+ /* buf[0:3] == "60\0") */ -+ BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_7, 0), -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_9, -+ bpf_ntohl(0x36300000), 2), -+ -+ /* return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_JMP_A(1), -+ -+ /* else return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/route/mtu_expires", -+ .open_flags = O_WRONLY, -+ .newval = "606", -+ .result = OP_EPERM, -+ }, -+ { -+ .descr = "sysctl_set_new_value sysctl:read EINVAL", -+ .insns = { -+ /* sysctl_set_new_value arg2 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_MOV64_IMM(BPF_REG_0, -+ bpf_ntohl(0x36303000)), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ -+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -+ -+ /* sysctl_set_new_value arg3 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_3, 3), -+ -+ /* sysctl_set_new_value(ctx, buf, buf_len) */ -+ BPF_EMIT_CALL(BPF_FUNC_sysctl_set_new_value), -+ -+ /* if (ret == expected) */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2), -+ -+ /* return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_JMP_A(1), -+ -+ /* else return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/route/mtu_expires", -+ .open_flags = O_RDONLY, -+ .result = SUCCESS, -+ }, -+ { -+ .descr = "sysctl_set_new_value sysctl:write ok", -+ .fixup_value_insn = 2, -+ .insns = { -+ /* sysctl_set_new_value arg2 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_LD_IMM64(BPF_REG_0, FIXUP_SYSCTL_VALUE), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ -+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -+ -+ /* sysctl_set_new_value arg3 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_3, 3), -+ -+ /* sysctl_set_new_value(ctx, buf, buf_len) */ -+ BPF_EMIT_CALL(BPF_FUNC_sysctl_set_new_value), -+ -+ /* if (ret == expected) */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2), -+ -+ /* return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_JMP_A(1), -+ -+ /* else return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/route/mtu_expires", -+ .open_flags = O_WRONLY, -+ .newval = "606", -+ .result = SUCCESS, -+ }, -+ { -+ "bpf_strtoul one number string", -+ .insns = { -+ /* arg1 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_MOV64_IMM(BPF_REG_0, -+ bpf_ntohl(0x36303000)), -+ BPF_STX_MEM(BPF_W, BPF_REG_7, BPF_REG_0, 0), -+ -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -+ -+ /* arg2 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_2, 4), -+ -+ /* arg3 (flags) */ -+ BPF_MOV64_IMM(BPF_REG_3, 0), -+ -+ /* arg4 (res) */ -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -+ -+ BPF_EMIT_CALL(BPF_FUNC_strtoul), -+ -+ /* if (ret == expected && */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4), -+ /* res == expected) */ -+ BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 600, 2), -+ -+ /* return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_JMP_A(1), -+ -+ /* else return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/route/mtu_expires", -+ .open_flags = O_RDONLY, -+ .result = SUCCESS, -+ }, -+ { -+ "bpf_strtoul multi number string", -+ .insns = { -+ /* arg1 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ /* "600 602\0" */ -+ BPF_LD_IMM64(BPF_REG_0, -+ bpf_be64_to_cpu(0x3630302036303200ULL)), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -+ -+ /* arg2 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_2, 8), -+ -+ /* arg3 (flags) */ -+ BPF_MOV64_IMM(BPF_REG_3, 0), -+ -+ /* arg4 (res) */ -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -+ -+ BPF_EMIT_CALL(BPF_FUNC_strtoul), -+ -+ /* if (ret == expected && */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 18), -+ /* res == expected) */ -+ BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 600, 16), -+ -+ /* arg1 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_ALU64_REG(BPF_ADD, BPF_REG_7, BPF_REG_0), -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -+ -+ /* arg2 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_2, 8), -+ BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_0), -+ -+ /* arg3 (flags) */ -+ BPF_MOV64_IMM(BPF_REG_3, 0), -+ -+ /* arg4 (res) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -16), -+ BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -+ -+ BPF_EMIT_CALL(BPF_FUNC_strtoul), -+ -+ /* if (ret == expected && */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 4), -+ /* res == expected) */ -+ BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 602, 2), -+ -+ /* return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_JMP_A(1), -+ -+ /* else return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/tcp_mem", -+ .open_flags = O_RDONLY, -+ .result = SUCCESS, -+ }, -+ { -+ "bpf_strtoul buf_len = 0, reject", -+ .insns = { -+ /* arg1 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_MOV64_IMM(BPF_REG_0, -+ bpf_ntohl(0x36303000)), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -+ -+ /* arg2 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_2, 0), -+ -+ /* arg3 (flags) */ -+ BPF_MOV64_IMM(BPF_REG_3, 0), -+ -+ /* arg4 (res) */ -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -+ -+ BPF_EMIT_CALL(BPF_FUNC_strtoul), -+ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/route/mtu_expires", -+ .open_flags = O_RDONLY, -+ .result = LOAD_REJECT, -+ }, -+ { -+ "bpf_strtoul supported base, ok", -+ .insns = { -+ /* arg1 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_MOV64_IMM(BPF_REG_0, -+ bpf_ntohl(0x30373700)), -+ BPF_STX_MEM(BPF_W, BPF_REG_7, BPF_REG_0, 0), -+ -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -+ -+ /* arg2 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_2, 4), -+ -+ /* arg3 (flags) */ -+ BPF_MOV64_IMM(BPF_REG_3, 8), -+ -+ /* arg4 (res) */ -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -+ -+ BPF_EMIT_CALL(BPF_FUNC_strtoul), -+ -+ /* if (ret == expected && */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4), -+ /* res == expected) */ -+ BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 63, 2), -+ -+ /* return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_JMP_A(1), -+ -+ /* else return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/route/mtu_expires", -+ .open_flags = O_RDONLY, -+ .result = SUCCESS, -+ }, -+ { -+ "bpf_strtoul unsupported base, EINVAL", -+ .insns = { -+ /* arg1 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_MOV64_IMM(BPF_REG_0, -+ bpf_ntohl(0x36303000)), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -+ -+ /* arg2 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_2, 4), -+ -+ /* arg3 (flags) */ -+ BPF_MOV64_IMM(BPF_REG_3, 3), -+ -+ /* arg4 (res) */ -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -+ -+ BPF_EMIT_CALL(BPF_FUNC_strtoul), -+ -+ /* if (ret == expected) */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2), -+ -+ /* return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_JMP_A(1), -+ -+ /* else return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/route/mtu_expires", -+ .open_flags = O_RDONLY, -+ .result = SUCCESS, -+ }, -+ { -+ "bpf_strtoul buf with spaces only, EINVAL", -+ .insns = { -+ /* arg1 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_MOV64_IMM(BPF_REG_0, -+ bpf_ntohl(0x0d0c0a09)), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -+ -+ /* arg2 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_2, 4), -+ -+ /* arg3 (flags) */ -+ BPF_MOV64_IMM(BPF_REG_3, 0), -+ -+ /* arg4 (res) */ -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -+ -+ BPF_EMIT_CALL(BPF_FUNC_strtoul), -+ -+ /* if (ret == expected) */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2), -+ -+ /* return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_JMP_A(1), -+ -+ /* else return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/route/mtu_expires", -+ .open_flags = O_RDONLY, -+ .result = SUCCESS, -+ }, -+ { -+ "bpf_strtoul negative number, EINVAL", -+ .insns = { -+ /* arg1 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ /* " -6\0" */ -+ BPF_MOV64_IMM(BPF_REG_0, -+ bpf_ntohl(0x0a2d3600)), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -+ -+ /* arg2 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_2, 4), -+ -+ /* arg3 (flags) */ -+ BPF_MOV64_IMM(BPF_REG_3, 0), -+ -+ /* arg4 (res) */ -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -+ -+ BPF_EMIT_CALL(BPF_FUNC_strtoul), -+ -+ /* if (ret == expected) */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2), -+ -+ /* return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_JMP_A(1), -+ -+ /* else return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/route/mtu_expires", -+ .open_flags = O_RDONLY, -+ .result = SUCCESS, -+ }, -+ { -+ "bpf_strtol negative number, ok", -+ .insns = { -+ /* arg1 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ /* " -6\0" */ -+ BPF_MOV64_IMM(BPF_REG_0, -+ bpf_ntohl(0x0a2d3600)), -+ BPF_STX_MEM(BPF_W, BPF_REG_7, BPF_REG_0, 0), -+ -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -+ -+ /* arg2 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_2, 4), -+ -+ /* arg3 (flags) */ -+ BPF_MOV64_IMM(BPF_REG_3, 10), -+ -+ /* arg4 (res) */ -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -+ -+ BPF_EMIT_CALL(BPF_FUNC_strtol), -+ -+ /* if (ret == expected && */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4), -+ /* res == expected) */ -+ BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_9, -6, 2), -+ -+ /* return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_JMP_A(1), -+ -+ /* else return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/route/mtu_expires", -+ .open_flags = O_RDONLY, -+ .result = SUCCESS, -+ }, -+ { -+ "bpf_strtol hex number, ok", -+ .insns = { -+ /* arg1 (buf) */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ /* "0xfe" */ -+ BPF_MOV64_IMM(BPF_REG_0, -+ bpf_ntohl(0x30786665)), -+ BPF_STX_MEM(BPF_W, BPF_REG_7, BPF_REG_0, 0), -+ -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -+ -+ /* arg2 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_2, 4), -+ -+ /* arg3 (flags) */ -+ BPF_MOV64_IMM(BPF_REG_3, 0), -+ -+ /* arg4 (res) */ -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -+ -+ BPF_EMIT_CALL(BPF_FUNC_strtol), -+ -+ /* if (ret == expected && */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 4), -+ /* res == expected) */ -+ BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 254, 2), -+ -+ /* return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_JMP_A(1), -+ -+ /* else return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/route/mtu_expires", -+ .open_flags = O_RDONLY, -+ .result = SUCCESS, -+ }, -+ { -+ "bpf_strtol max long", -+ .insns = { -+ /* arg1 (buf) 9223372036854775807 */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -24), -+ BPF_LD_IMM64(BPF_REG_0, -+ bpf_be64_to_cpu(0x3932323333373230ULL)), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ BPF_LD_IMM64(BPF_REG_0, -+ bpf_be64_to_cpu(0x3336383534373735ULL)), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 8), -+ BPF_LD_IMM64(BPF_REG_0, -+ bpf_be64_to_cpu(0x3830370000000000ULL)), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 16), -+ -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -+ -+ /* arg2 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_2, 19), -+ -+ /* arg3 (flags) */ -+ BPF_MOV64_IMM(BPF_REG_3, 0), -+ -+ /* arg4 (res) */ -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -+ -+ BPF_EMIT_CALL(BPF_FUNC_strtol), -+ -+ /* if (ret == expected && */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 19, 6), -+ /* res == expected) */ -+ BPF_LD_IMM64(BPF_REG_8, 0x7fffffffffffffffULL), -+ BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -+ BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2), -+ -+ /* return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_JMP_A(1), -+ -+ /* else return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/route/mtu_expires", -+ .open_flags = O_RDONLY, -+ .result = SUCCESS, -+ }, -+ { -+ "bpf_strtol overflow, ERANGE", -+ .insns = { -+ /* arg1 (buf) 9223372036854775808 */ -+ BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -24), -+ BPF_LD_IMM64(BPF_REG_0, -+ bpf_be64_to_cpu(0x3932323333373230ULL)), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ BPF_LD_IMM64(BPF_REG_0, -+ bpf_be64_to_cpu(0x3336383534373735ULL)), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 8), -+ BPF_LD_IMM64(BPF_REG_0, -+ bpf_be64_to_cpu(0x3830380000000000ULL)), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 16), -+ -+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -+ -+ /* arg2 (buf_len) */ -+ BPF_MOV64_IMM(BPF_REG_2, 19), -+ -+ /* arg3 (flags) */ -+ BPF_MOV64_IMM(BPF_REG_3, 0), -+ -+ /* arg4 (res) */ -+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -+ BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -+ BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -+ -+ BPF_EMIT_CALL(BPF_FUNC_strtol), -+ -+ /* if (ret == expected) */ -+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -ERANGE, 2), -+ -+ /* return ALLOW; */ -+ BPF_MOV64_IMM(BPF_REG_0, 1), -+ BPF_JMP_A(1), -+ -+ /* else return DENY; */ -+ BPF_MOV64_IMM(BPF_REG_0, 0), -+ BPF_EXIT_INSN(), -+ }, -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/route/mtu_expires", -+ .open_flags = O_RDONLY, -+ .result = SUCCESS, -+ }, -+ { -+ "C prog: deny all writes", -+ .prog_file = "./test_sysctl_prog.bpf.o", -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/tcp_mem", -+ .open_flags = O_WRONLY, -+ .newval = "123 456 789", -+ .result = OP_EPERM, -+ }, -+ { -+ "C prog: deny access by name", -+ .prog_file = "./test_sysctl_prog.bpf.o", -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/route/mtu_expires", -+ .open_flags = O_RDONLY, -+ .result = OP_EPERM, -+ }, -+ { -+ "C prog: read tcp_mem", -+ .prog_file = "./test_sysctl_prog.bpf.o", -+ .attach_type = BPF_CGROUP_SYSCTL, -+ .sysctl = "net/ipv4/tcp_mem", -+ .open_flags = O_RDONLY, -+ .result = SUCCESS, -+ }, -+}; -+ -+static size_t probe_prog_length(const struct bpf_insn *fp) -+{ -+ size_t len; -+ -+ for (len = MAX_INSNS - 1; len > 0; --len) -+ if (fp[len].code != 0 || fp[len].imm != 0) -+ break; -+ return len + 1; -+} -+ -+static int fixup_sysctl_value(const char *buf, size_t buf_len, -+ struct bpf_insn *prog, size_t insn_num) -+{ -+ union { -+ uint8_t raw[sizeof(uint64_t)]; -+ uint64_t num; -+ } value = {}; -+ -+ if (buf_len > sizeof(value)) { -+ log_err("Value is too big (%zd) to use in fixup", buf_len); -+ return -1; -+ } -+ if (prog[insn_num].code != (BPF_LD | BPF_DW | BPF_IMM)) { -+ log_err("Can fixup only BPF_LD_IMM64 insns"); -+ return -1; -+ } -+ -+ memcpy(value.raw, buf, buf_len); -+ prog[insn_num].imm = (uint32_t)value.num; -+ prog[insn_num + 1].imm = (uint32_t)(value.num >> 32); -+ -+ return 0; -+} -+ -+static int load_sysctl_prog_insns(struct sysctl_test *test, -+ const char *sysctl_path) -+{ -+ struct bpf_insn *prog = test->insns; -+ LIBBPF_OPTS(bpf_prog_load_opts, opts); -+ int ret, insn_cnt; -+ -+ insn_cnt = probe_prog_length(prog); -+ -+ if (test->fixup_value_insn) { -+ char buf[128]; -+ ssize_t len; -+ int fd; -+ -+ fd = open(sysctl_path, O_RDONLY | O_CLOEXEC); -+ if (fd < 0) { -+ log_err("open(%s) failed", sysctl_path); -+ return -1; -+ } -+ len = read(fd, buf, sizeof(buf)); -+ if (len == -1) { -+ log_err("read(%s) failed", sysctl_path); -+ close(fd); -+ return -1; -+ } -+ close(fd); -+ if (fixup_sysctl_value(buf, len, prog, test->fixup_value_insn)) -+ return -1; -+ } -+ -+ opts.log_buf = bpf_log_buf; -+ opts.log_size = BPF_LOG_BUF_SIZE; -+ -+ ret = bpf_prog_load(BPF_PROG_TYPE_CGROUP_SYSCTL, NULL, "GPL", prog, insn_cnt, &opts); -+ if (ret < 0 && test->result != LOAD_REJECT) { -+ log_err(">>> Loading program error.\n" -+ ">>> Verifier output:\n%s\n-------\n", bpf_log_buf); -+ } -+ -+ return ret; -+} -+ -+static int load_sysctl_prog_file(struct sysctl_test *test) -+{ -+ struct bpf_object *obj; -+ int prog_fd; -+ -+ if (bpf_prog_test_load(test->prog_file, BPF_PROG_TYPE_CGROUP_SYSCTL, &obj, &prog_fd)) { -+ if (test->result != LOAD_REJECT) -+ log_err(">>> Loading program (%s) error.\n", -+ test->prog_file); -+ return -1; -+ } -+ -+ return prog_fd; -+} -+ -+static int load_sysctl_prog(struct sysctl_test *test, const char *sysctl_path) -+{ -+ return test->prog_file -+ ? load_sysctl_prog_file(test) -+ : load_sysctl_prog_insns(test, sysctl_path); -+} -+ -+static int access_sysctl(const char *sysctl_path, -+ const struct sysctl_test *test) -+{ -+ int err = 0; -+ int fd; -+ -+ fd = open(sysctl_path, test->open_flags | O_CLOEXEC); -+ if (fd < 0) -+ return fd; -+ -+ if (test->seek && lseek(fd, test->seek, SEEK_SET) == -1) { -+ log_err("lseek(%d) failed", test->seek); -+ goto err; -+ } -+ -+ if (test->open_flags == O_RDONLY) { -+ char buf[128]; -+ -+ if (read(fd, buf, sizeof(buf)) == -1) -+ goto err; -+ if (test->oldval && -+ strncmp(buf, test->oldval, strlen(test->oldval))) { -+ log_err("Read value %s != %s", buf, test->oldval); -+ goto err; -+ } -+ } else if (test->open_flags == O_WRONLY) { -+ if (!test->newval) { -+ log_err("New value for sysctl is not set"); -+ goto err; -+ } -+ if (write(fd, test->newval, strlen(test->newval)) == -1) -+ goto err; -+ } else { -+ log_err("Unexpected sysctl access: neither read nor write"); -+ goto err; -+ } -+ -+ goto out; -+err: -+ err = -1; -+out: -+ close(fd); -+ return err; -+} -+ -+static int run_test_case(int cgfd, struct sysctl_test *test) -+{ -+ enum bpf_attach_type atype = test->attach_type; -+ char sysctl_path[128]; -+ int progfd = -1; -+ int err = 0; -+ -+ printf("Test case: %s .. ", test->descr); -+ -+ snprintf(sysctl_path, sizeof(sysctl_path), "/proc/sys/%s", -+ test->sysctl); -+ -+ progfd = load_sysctl_prog(test, sysctl_path); -+ if (progfd < 0) { -+ if (test->result == LOAD_REJECT) -+ goto out; -+ else -+ goto err; -+ } -+ -+ if (bpf_prog_attach(progfd, cgfd, atype, BPF_F_ALLOW_OVERRIDE) < 0) { -+ if (test->result == ATTACH_REJECT) -+ goto out; -+ else -+ goto err; -+ } -+ -+ errno = 0; -+ if (access_sysctl(sysctl_path, test) == -1) { -+ if (test->result == OP_EPERM && errno == EPERM) -+ goto out; -+ else -+ goto err; -+ } -+ -+ if (test->result != SUCCESS) { -+ log_err("Unexpected success"); -+ goto err; -+ } -+ -+ goto out; -+err: -+ err = -1; -+out: -+ /* Detaching w/o checking return code: best effort attempt. */ -+ if (progfd != -1) -+ bpf_prog_detach(cgfd, atype); -+ close(progfd); -+ printf("[%s]\n", err ? "FAIL" : "PASS"); -+ return err; -+} -+ -+static int run_tests(int cgfd) -+{ -+ int passes = 0; -+ int fails = 0; -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(tests); ++i) { -+ if (run_test_case(cgfd, &tests[i])) -+ ++fails; -+ else -+ ++passes; -+ } -+ printf("Summary: %d PASSED, %d FAILED\n", passes, fails); -+ return fails ? -1 : 0; -+} -+ -+void test_sysctl(void) -+{ -+ int cgfd; -+ -+ cgfd = cgroup_setup_and_join(CG_PATH); -+ if (!ASSERT_OK_FD(cgfd < 0, "create_cgroup")) -+ goto out; -+ -+ if (!ASSERT_OK(run_tests(cgfd), "run_tests")) -+ goto out; -+ -+out: -+ close(cgfd); -+ cleanup_cgroup_environment(); -+ return; -+} -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/bpf/prog_tests/timer.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/prog_tests/timer.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/bpf/prog_tests/timer.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/prog_tests/timer.c 2025-10-22 13:53:56.867167444 -0400 -@@ -86,6 +86,10 @@ void serial_test_timer(void) - int err; - - timer_skel = timer__open_and_load(); -+ if (!timer_skel && errno == EOPNOTSUPP) { -+ test__skip(); -+ return; -+ } - if (!ASSERT_OK_PTR(timer_skel, "timer_skel_load")) - return; - -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/bpf/prog_tests/timer_crash.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/prog_tests/timer_crash.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/bpf/prog_tests/timer_crash.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/prog_tests/timer_crash.c 2025-10-22 13:53:56.867167444 -0400 -@@ -12,6 +12,10 @@ static void test_timer_crash_mode(int mo - struct timer_crash *skel; - - skel = timer_crash__open_and_load(); -+ if (!skel && errno == EOPNOTSUPP) { -+ test__skip(); -+ return; -+ } - if (!ASSERT_OK_PTR(skel, "timer_crash__open_and_load")) - return; - skel->bss->pid = getpid(); -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/bpf/prog_tests/timer_lockup.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/prog_tests/timer_lockup.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/bpf/prog_tests/timer_lockup.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/prog_tests/timer_lockup.c 2025-10-22 13:53:56.867167444 -0400 -@@ -59,6 +59,10 @@ void test_timer_lockup(void) - } - - skel = timer_lockup__open_and_load(); -+ if (!skel && errno == EOPNOTSUPP) { -+ test__skip(); -+ return; -+ } - if (!ASSERT_OK_PTR(skel, "timer_lockup__open_and_load")) - return; - -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/bpf/prog_tests/timer_mim.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/prog_tests/timer_mim.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/bpf/prog_tests/timer_mim.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/prog_tests/timer_mim.c 2025-10-22 13:53:56.867167444 -0400 -@@ -65,6 +65,10 @@ void serial_test_timer_mim(void) - goto cleanup; - - timer_skel = timer_mim__open_and_load(); -+ if (!timer_skel && errno == EOPNOTSUPP) { -+ test__skip(); -+ return; -+ } - if (!ASSERT_OK_PTR(timer_skel, "timer_skel_load")) - goto cleanup; - -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/bpf/prog_tests/user_ringbuf.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/prog_tests/user_ringbuf.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/bpf/prog_tests/user_ringbuf.c 2025-10-22 13:53:23.695326827 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/prog_tests/user_ringbuf.c 2025-10-22 13:53:56.871167425 -0400 -@@ -21,8 +21,7 @@ - #include "../progs/test_user_ringbuf.h" - - static const long c_sample_size = sizeof(struct sample) + BPF_RINGBUF_HDR_SZ; --static const long c_ringbuf_size = 1 << 12; /* 1 small page */ --static const long c_max_entries = c_ringbuf_size / c_sample_size; -+static long c_ringbuf_size, c_max_entries; - - static void drain_current_samples(void) - { -@@ -424,7 +423,9 @@ static void test_user_ringbuf_loop(void) - uint32_t remaining_samples = total_samples; - int err; - -- BUILD_BUG_ON(total_samples <= c_max_entries); -+ if (!ASSERT_LT(c_max_entries, total_samples, "compare_c_max_entries")) -+ return; -+ - err = load_skel_create_user_ringbuf(&skel, &ringbuf); - if (err) - return; -@@ -686,6 +687,9 @@ void test_user_ringbuf(void) - { - int i; - -+ c_ringbuf_size = getpagesize(); /* 1 page */ -+ c_max_entries = c_ringbuf_size / c_sample_size; -+ - for (i = 0; i < ARRAY_SIZE(success_tests); i++) { - if (!test__start_subtest(success_tests[i].test_name)) - continue; -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/bpf/test_lru_map.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/test_lru_map.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/bpf/test_lru_map.c 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/test_lru_map.c 2025-10-22 13:53:56.871167425 -0400 -@@ -138,6 +138,18 @@ static int sched_next_online(int pid, in - return ret; - } - -+/* Derive target_free from map_size, same as bpf_common_lru_populate */ -+static unsigned int __tgt_size(unsigned int map_size) -+{ -+ return (map_size / nr_cpus) / 2; -+} -+ -+/* Inverse of how bpf_common_lru_populate derives target_free from map_size. */ -+static unsigned int __map_size(unsigned int tgt_free) -+{ -+ return tgt_free * nr_cpus * 2; -+} -+ - /* Size of the LRU map is 2 - * Add key=1 (+1 key) - * Add key=2 (+1 key) -@@ -231,11 +243,11 @@ static void test_lru_sanity0(int map_typ - printf("Pass\n"); - } - --/* Size of the LRU map is 1.5*tgt_free -- * Insert 1 to tgt_free (+tgt_free keys) -- * Lookup 1 to tgt_free/2 -- * Insert 1+tgt_free to 2*tgt_free (+tgt_free keys) -- * => 1+tgt_free/2 to LOCALFREE_TARGET will be removed by LRU -+/* Verify that unreferenced elements are recycled before referenced ones. -+ * Insert elements. -+ * Reference a subset of these. -+ * Insert more, enough to trigger recycling. -+ * Verify that unreferenced are recycled. - */ - static void test_lru_sanity1(int map_type, int map_flags, unsigned int tgt_free) - { -@@ -257,7 +269,7 @@ static void test_lru_sanity1(int map_typ - batch_size = tgt_free / 2; - assert(batch_size * 2 == tgt_free); - -- map_size = tgt_free + batch_size; -+ map_size = __map_size(tgt_free) + batch_size; - lru_map_fd = create_map(map_type, map_flags, map_size); - assert(lru_map_fd != -1); - -@@ -266,13 +278,13 @@ static void test_lru_sanity1(int map_typ - - value[0] = 1234; - -- /* Insert 1 to tgt_free (+tgt_free keys) */ -- end_key = 1 + tgt_free; -+ /* Insert map_size - batch_size keys */ -+ end_key = 1 + __map_size(tgt_free); - for (key = 1; key < end_key; key++) - assert(!bpf_map_update_elem(lru_map_fd, &key, value, - BPF_NOEXIST)); - -- /* Lookup 1 to tgt_free/2 */ -+ /* Lookup 1 to batch_size */ - end_key = 1 + batch_size; - for (key = 1; key < end_key; key++) { - assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd, key, value)); -@@ -280,12 +292,13 @@ static void test_lru_sanity1(int map_typ - BPF_NOEXIST)); - } - -- /* Insert 1+tgt_free to 2*tgt_free -- * => 1+tgt_free/2 to LOCALFREE_TARGET will be -+ /* Insert another map_size - batch_size keys -+ * Map will contain 1 to batch_size plus these latest, i.e., -+ * => previous 1+batch_size to map_size - batch_size will have been - * removed by LRU - */ -- key = 1 + tgt_free; -- end_key = key + tgt_free; -+ key = 1 + __map_size(tgt_free); -+ end_key = key + __map_size(tgt_free); - for (; key < end_key; key++) { - assert(!bpf_map_update_elem(lru_map_fd, &key, value, - BPF_NOEXIST)); -@@ -301,17 +314,8 @@ static void test_lru_sanity1(int map_typ - printf("Pass\n"); - } - --/* Size of the LRU map 1.5 * tgt_free -- * Insert 1 to tgt_free (+tgt_free keys) -- * Update 1 to tgt_free/2 -- * => The original 1 to tgt_free/2 will be removed due to -- * the LRU shrink process -- * Re-insert 1 to tgt_free/2 again and do a lookup immeidately -- * Insert 1+tgt_free to tgt_free*3/2 -- * Insert 1+tgt_free*3/2 to tgt_free*5/2 -- * => Key 1+tgt_free to tgt_free*3/2 -- * will be removed from LRU because it has never -- * been lookup and ref bit is not set -+/* Verify that insertions exceeding map size will recycle the oldest. -+ * Verify that unreferenced elements are recycled before referenced. - */ - static void test_lru_sanity2(int map_type, int map_flags, unsigned int tgt_free) - { -@@ -334,7 +338,7 @@ static void test_lru_sanity2(int map_typ - batch_size = tgt_free / 2; - assert(batch_size * 2 == tgt_free); - -- map_size = tgt_free + batch_size; -+ map_size = __map_size(tgt_free) + batch_size; - lru_map_fd = create_map(map_type, map_flags, map_size); - assert(lru_map_fd != -1); - -@@ -343,8 +347,8 @@ static void test_lru_sanity2(int map_typ - - value[0] = 1234; - -- /* Insert 1 to tgt_free (+tgt_free keys) */ -- end_key = 1 + tgt_free; -+ /* Insert map_size - batch_size keys */ -+ end_key = 1 + __map_size(tgt_free); - for (key = 1; key < end_key; key++) - assert(!bpf_map_update_elem(lru_map_fd, &key, value, - BPF_NOEXIST)); -@@ -357,8 +361,7 @@ static void test_lru_sanity2(int map_typ - * shrink the inactive list to get tgt_free - * number of free nodes. - * -- * Hence, the oldest key 1 to tgt_free/2 -- * are removed from the LRU list. -+ * Hence, the oldest key is removed from the LRU list. - */ - key = 1; - if (map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) { -@@ -370,8 +373,7 @@ static void test_lru_sanity2(int map_typ - BPF_EXIST)); - } - -- /* Re-insert 1 to tgt_free/2 again and do a lookup -- * immeidately. -+ /* Re-insert 1 to batch_size again and do a lookup immediately. - */ - end_key = 1 + batch_size; - value[0] = 4321; -@@ -387,17 +389,18 @@ static void test_lru_sanity2(int map_typ - - value[0] = 1234; - -- /* Insert 1+tgt_free to tgt_free*3/2 */ -- end_key = 1 + tgt_free + batch_size; -- for (key = 1 + tgt_free; key < end_key; key++) -+ /* Insert batch_size new elements */ -+ key = 1 + __map_size(tgt_free); -+ end_key = key + batch_size; -+ for (; key < end_key; key++) - /* These newly added but not referenced keys will be - * gone during the next LRU shrink. - */ - assert(!bpf_map_update_elem(lru_map_fd, &key, value, - BPF_NOEXIST)); - -- /* Insert 1+tgt_free*3/2 to tgt_free*5/2 */ -- end_key = key + tgt_free; -+ /* Insert map_size - batch_size elements */ -+ end_key += __map_size(tgt_free); - for (; key < end_key; key++) { - assert(!bpf_map_update_elem(lru_map_fd, &key, value, - BPF_NOEXIST)); -@@ -413,12 +416,12 @@ static void test_lru_sanity2(int map_typ - printf("Pass\n"); - } - --/* Size of the LRU map is 2*tgt_free -- * It is to test the active/inactive list rotation -- * Insert 1 to 2*tgt_free (+2*tgt_free keys) -- * Lookup key 1 to tgt_free*3/2 -- * Add 1+2*tgt_free to tgt_free*5/2 (+tgt_free/2 keys) -- * => key 1+tgt_free*3/2 to 2*tgt_free are removed from LRU -+/* Test the active/inactive list rotation -+ * -+ * Fill the whole map, deplete the free list. -+ * Reference all except the last lru->target_free elements. -+ * Insert lru->target_free new elements. This triggers one shrink. -+ * Verify that the non-referenced elements are replaced. - */ - static void test_lru_sanity3(int map_type, int map_flags, unsigned int tgt_free) - { -@@ -437,8 +440,7 @@ static void test_lru_sanity3(int map_typ - - assert(sched_next_online(0, &next_cpu) != -1); - -- batch_size = tgt_free / 2; -- assert(batch_size * 2 == tgt_free); -+ batch_size = __tgt_size(tgt_free); - - map_size = tgt_free * 2; - lru_map_fd = create_map(map_type, map_flags, map_size); -@@ -449,23 +451,21 @@ static void test_lru_sanity3(int map_typ - - value[0] = 1234; - -- /* Insert 1 to 2*tgt_free (+2*tgt_free keys) */ -- end_key = 1 + (2 * tgt_free); -+ /* Fill the map */ -+ end_key = 1 + map_size; - for (key = 1; key < end_key; key++) - assert(!bpf_map_update_elem(lru_map_fd, &key, value, - BPF_NOEXIST)); - -- /* Lookup key 1 to tgt_free*3/2 */ -- end_key = tgt_free + batch_size; -+ /* Reference all but the last batch_size */ -+ end_key = 1 + map_size - batch_size; - for (key = 1; key < end_key; key++) { - assert(!bpf_map_lookup_elem_with_ref_bit(lru_map_fd, key, value)); - assert(!bpf_map_update_elem(expected_map_fd, &key, value, - BPF_NOEXIST)); - } - -- /* Add 1+2*tgt_free to tgt_free*5/2 -- * (+tgt_free/2 keys) -- */ -+ /* Insert new batch_size: replaces the non-referenced elements */ - key = 2 * tgt_free + 1; - end_key = key + batch_size; - for (; key < end_key; key++) { -@@ -500,7 +500,8 @@ static void test_lru_sanity4(int map_typ - lru_map_fd = create_map(map_type, map_flags, - 3 * tgt_free * nr_cpus); - else -- lru_map_fd = create_map(map_type, map_flags, 3 * tgt_free); -+ lru_map_fd = create_map(map_type, map_flags, -+ 3 * __map_size(tgt_free)); - assert(lru_map_fd != -1); - - expected_map_fd = create_map(BPF_MAP_TYPE_HASH, 0, -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/bpf/test_sysctl.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/test_sysctl.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/bpf/test_sysctl.c 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/test_sysctl.c 1969-12-31 19:00:00.000000000 -0500 -@@ -1,1633 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0 --// Copyright (c) 2019 Facebook -- --#include --#include --#include --#include --#include --#include -- --#include -- --#include --#include -- --#include --#include "bpf_util.h" --#include "cgroup_helpers.h" --#include "testing_helpers.h" -- --#define CG_PATH "/foo" --#define MAX_INSNS 512 --#define FIXUP_SYSCTL_VALUE 0 -- --char bpf_log_buf[BPF_LOG_BUF_SIZE]; -- --struct sysctl_test { -- const char *descr; -- size_t fixup_value_insn; -- struct bpf_insn insns[MAX_INSNS]; -- const char *prog_file; -- enum bpf_attach_type attach_type; -- const char *sysctl; -- int open_flags; -- int seek; -- const char *newval; -- const char *oldval; -- enum { -- LOAD_REJECT, -- ATTACH_REJECT, -- OP_EPERM, -- SUCCESS, -- } result; --}; -- --static struct sysctl_test tests[] = { -- { -- .descr = "sysctl wrong attach_type", -- .insns = { -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_EXIT_INSN(), -- }, -- .attach_type = 0, -- .sysctl = "kernel/ostype", -- .open_flags = O_RDONLY, -- .result = ATTACH_REJECT, -- }, -- { -- .descr = "sysctl:read allow all", -- .insns = { -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "kernel/ostype", -- .open_flags = O_RDONLY, -- .result = SUCCESS, -- }, -- { -- .descr = "sysctl:read deny all", -- .insns = { -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "kernel/ostype", -- .open_flags = O_RDONLY, -- .result = OP_EPERM, -- }, -- { -- .descr = "ctx:write sysctl:read read ok", -- .insns = { -- /* If (write) */ -- BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1, -- offsetof(struct bpf_sysctl, write)), -- BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 1, 2), -- -- /* return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_JMP_A(1), -- -- /* else return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "kernel/ostype", -- .open_flags = O_RDONLY, -- .result = SUCCESS, -- }, -- { -- .descr = "ctx:write sysctl:write read ok", -- .insns = { -- /* If (write) */ -- BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1, -- offsetof(struct bpf_sysctl, write)), -- BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 1, 2), -- -- /* return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_JMP_A(1), -- -- /* else return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "kernel/domainname", -- .open_flags = O_WRONLY, -- .newval = "(none)", /* same as default, should fail anyway */ -- .result = OP_EPERM, -- }, -- { -- .descr = "ctx:write sysctl:write read ok narrow", -- .insns = { -- /* u64 w = (u16)write & 1; */ --#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -- BPF_LDX_MEM(BPF_H, BPF_REG_7, BPF_REG_1, -- offsetof(struct bpf_sysctl, write)), --#else -- BPF_LDX_MEM(BPF_H, BPF_REG_7, BPF_REG_1, -- offsetof(struct bpf_sysctl, write) + 2), --#endif -- BPF_ALU64_IMM(BPF_AND, BPF_REG_7, 1), -- /* return 1 - w; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_7), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "kernel/domainname", -- .open_flags = O_WRONLY, -- .newval = "(none)", /* same as default, should fail anyway */ -- .result = OP_EPERM, -- }, -- { -- .descr = "ctx:write sysctl:read write reject", -- .insns = { -- /* write = X */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, -- offsetof(struct bpf_sysctl, write)), -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "kernel/ostype", -- .open_flags = O_RDONLY, -- .result = LOAD_REJECT, -- }, -- { -- .descr = "ctx:file_pos sysctl:read read ok", -- .insns = { -- /* If (file_pos == X) */ -- BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1, -- offsetof(struct bpf_sysctl, file_pos)), -- BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 3, 2), -- -- /* return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_JMP_A(1), -- -- /* else return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "kernel/ostype", -- .open_flags = O_RDONLY, -- .seek = 3, -- .result = SUCCESS, -- }, -- { -- .descr = "ctx:file_pos sysctl:read read ok narrow", -- .insns = { -- /* If (file_pos == X) */ --#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -- BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_1, -- offsetof(struct bpf_sysctl, file_pos)), --#else -- BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_1, -- offsetof(struct bpf_sysctl, file_pos) + 3), --#endif -- BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 4, 2), -- -- /* return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_JMP_A(1), -- -- /* else return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "kernel/ostype", -- .open_flags = O_RDONLY, -- .seek = 4, -- .result = SUCCESS, -- }, -- { -- .descr = "ctx:file_pos sysctl:read write ok", -- .insns = { -- /* file_pos = X */ -- BPF_MOV64_IMM(BPF_REG_0, 2), -- BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, -- offsetof(struct bpf_sysctl, file_pos)), -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "kernel/ostype", -- .open_flags = O_RDONLY, -- .oldval = "nux\n", -- .result = SUCCESS, -- }, -- { -- .descr = "sysctl_get_name sysctl_value:base ok", -- .insns = { -- /* sysctl_get_name arg2 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- -- BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -- -- /* sysctl_get_name arg3 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_3, 8), -- -- /* sysctl_get_name arg4 (flags) */ -- BPF_MOV64_IMM(BPF_REG_4, BPF_F_SYSCTL_BASE_NAME), -- -- /* sysctl_get_name(ctx, buf, buf_len, flags) */ -- BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name), -- -- /* if (ret == expected && */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, sizeof("tcp_mem") - 1, 6), -- /* buf == "tcp_mem\0") */ -- BPF_LD_IMM64(BPF_REG_8, -- bpf_be64_to_cpu(0x7463705f6d656d00ULL)), -- BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -- BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2), -- -- /* return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_JMP_A(1), -- -- /* else return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/tcp_mem", -- .open_flags = O_RDONLY, -- .result = SUCCESS, -- }, -- { -- .descr = "sysctl_get_name sysctl_value:base E2BIG truncated", -- .insns = { -- /* sysctl_get_name arg2 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- -- BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -- -- /* sysctl_get_name arg3 (buf_len) too small */ -- BPF_MOV64_IMM(BPF_REG_3, 7), -- -- /* sysctl_get_name arg4 (flags) */ -- BPF_MOV64_IMM(BPF_REG_4, BPF_F_SYSCTL_BASE_NAME), -- -- /* sysctl_get_name(ctx, buf, buf_len, flags) */ -- BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name), -- -- /* if (ret == expected && */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6), -- -- /* buf[0:7] == "tcp_me\0") */ -- BPF_LD_IMM64(BPF_REG_8, -- bpf_be64_to_cpu(0x7463705f6d650000ULL)), -- BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -- BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2), -- -- /* return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_JMP_A(1), -- -- /* else return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/tcp_mem", -- .open_flags = O_RDONLY, -- .result = SUCCESS, -- }, -- { -- .descr = "sysctl_get_name sysctl:full ok", -- .insns = { -- /* sysctl_get_name arg2 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -24), -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 8), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 16), -- -- BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -- -- /* sysctl_get_name arg3 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_3, 17), -- -- /* sysctl_get_name arg4 (flags) */ -- BPF_MOV64_IMM(BPF_REG_4, 0), -- -- /* sysctl_get_name(ctx, buf, buf_len, flags) */ -- BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name), -- -- /* if (ret == expected && */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 16, 14), -- -- /* buf[0:8] == "net/ipv4" && */ -- BPF_LD_IMM64(BPF_REG_8, -- bpf_be64_to_cpu(0x6e65742f69707634ULL)), -- BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -- BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 10), -- -- /* buf[8:16] == "/tcp_mem" && */ -- BPF_LD_IMM64(BPF_REG_8, -- bpf_be64_to_cpu(0x2f7463705f6d656dULL)), -- BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 8), -- BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 6), -- -- /* buf[16:24] == "\0") */ -- BPF_LD_IMM64(BPF_REG_8, 0x0ULL), -- BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 16), -- BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2), -- -- /* return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_JMP_A(1), -- -- /* else return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/tcp_mem", -- .open_flags = O_RDONLY, -- .result = SUCCESS, -- }, -- { -- .descr = "sysctl_get_name sysctl:full E2BIG truncated", -- .insns = { -- /* sysctl_get_name arg2 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -16), -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 8), -- -- BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -- -- /* sysctl_get_name arg3 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_3, 16), -- -- /* sysctl_get_name arg4 (flags) */ -- BPF_MOV64_IMM(BPF_REG_4, 0), -- -- /* sysctl_get_name(ctx, buf, buf_len, flags) */ -- BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name), -- -- /* if (ret == expected && */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 10), -- -- /* buf[0:8] == "net/ipv4" && */ -- BPF_LD_IMM64(BPF_REG_8, -- bpf_be64_to_cpu(0x6e65742f69707634ULL)), -- BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -- BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 6), -- -- /* buf[8:16] == "/tcp_me\0") */ -- BPF_LD_IMM64(BPF_REG_8, -- bpf_be64_to_cpu(0x2f7463705f6d6500ULL)), -- BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 8), -- BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2), -- -- /* return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_JMP_A(1), -- -- /* else return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/tcp_mem", -- .open_flags = O_RDONLY, -- .result = SUCCESS, -- }, -- { -- .descr = "sysctl_get_name sysctl:full E2BIG truncated small", -- .insns = { -- /* sysctl_get_name arg2 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- -- BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -- -- /* sysctl_get_name arg3 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_3, 7), -- -- /* sysctl_get_name arg4 (flags) */ -- BPF_MOV64_IMM(BPF_REG_4, 0), -- -- /* sysctl_get_name(ctx, buf, buf_len, flags) */ -- BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name), -- -- /* if (ret == expected && */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6), -- -- /* buf[0:8] == "net/ip\0") */ -- BPF_LD_IMM64(BPF_REG_8, -- bpf_be64_to_cpu(0x6e65742f69700000ULL)), -- BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -- BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2), -- -- /* return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_JMP_A(1), -- -- /* else return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/tcp_mem", -- .open_flags = O_RDONLY, -- .result = SUCCESS, -- }, -- { -- .descr = "sysctl_get_current_value sysctl:read ok, gt", -- .insns = { -- /* sysctl_get_current_value arg2 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -- -- /* sysctl_get_current_value arg3 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_3, 8), -- -- /* sysctl_get_current_value(ctx, buf, buf_len) */ -- BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value), -- -- /* if (ret == expected && */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 6, 6), -- -- /* buf[0:6] == "Linux\n\0") */ -- BPF_LD_IMM64(BPF_REG_8, -- bpf_be64_to_cpu(0x4c696e75780a0000ULL)), -- BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -- BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2), -- -- /* return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_JMP_A(1), -- -- /* else return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "kernel/ostype", -- .open_flags = O_RDONLY, -- .result = SUCCESS, -- }, -- { -- .descr = "sysctl_get_current_value sysctl:read ok, eq", -- .insns = { -- /* sysctl_get_current_value arg2 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_STX_MEM(BPF_B, BPF_REG_7, BPF_REG_0, 7), -- -- BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -- -- /* sysctl_get_current_value arg3 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_3, 7), -- -- /* sysctl_get_current_value(ctx, buf, buf_len) */ -- BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value), -- -- /* if (ret == expected && */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 6, 6), -- -- /* buf[0:6] == "Linux\n\0") */ -- BPF_LD_IMM64(BPF_REG_8, -- bpf_be64_to_cpu(0x4c696e75780a0000ULL)), -- BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -- BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2), -- -- /* return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_JMP_A(1), -- -- /* else return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "kernel/ostype", -- .open_flags = O_RDONLY, -- .result = SUCCESS, -- }, -- { -- .descr = "sysctl_get_current_value sysctl:read E2BIG truncated", -- .insns = { -- /* sysctl_get_current_value arg2 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_STX_MEM(BPF_H, BPF_REG_7, BPF_REG_0, 6), -- -- BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -- -- /* sysctl_get_current_value arg3 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_3, 6), -- -- /* sysctl_get_current_value(ctx, buf, buf_len) */ -- BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value), -- -- /* if (ret == expected && */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6), -- -- /* buf[0:6] == "Linux\0") */ -- BPF_LD_IMM64(BPF_REG_8, -- bpf_be64_to_cpu(0x4c696e7578000000ULL)), -- BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -- BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2), -- -- /* return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_JMP_A(1), -- -- /* else return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "kernel/ostype", -- .open_flags = O_RDONLY, -- .result = SUCCESS, -- }, -- { -- .descr = "sysctl_get_current_value sysctl:read EINVAL", -- .insns = { -- /* sysctl_get_current_value arg2 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- -- BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -- -- /* sysctl_get_current_value arg3 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_3, 8), -- -- /* sysctl_get_current_value(ctx, buf, buf_len) */ -- BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value), -- -- /* if (ret == expected && */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 4), -- -- /* buf[0:8] is NUL-filled) */ -- BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -- BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 0, 2), -- -- /* return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_JMP_A(1), -- -- /* else return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv6/conf/lo/stable_secret", /* -EIO */ -- .open_flags = O_RDONLY, -- .result = OP_EPERM, -- }, -- { -- .descr = "sysctl_get_current_value sysctl:write ok", -- .fixup_value_insn = 6, -- .insns = { -- /* sysctl_get_current_value arg2 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- -- BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -- -- /* sysctl_get_current_value arg3 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_3, 8), -- -- /* sysctl_get_current_value(ctx, buf, buf_len) */ -- BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value), -- -- /* if (ret == expected && */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 6), -- -- /* buf[0:4] == expected) */ -- BPF_LD_IMM64(BPF_REG_8, FIXUP_SYSCTL_VALUE), -- BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -- BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2), -- -- /* return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_JMP_A(1), -- -- /* else return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/route/mtu_expires", -- .open_flags = O_WRONLY, -- .newval = "600", /* same as default, should fail anyway */ -- .result = OP_EPERM, -- }, -- { -- .descr = "sysctl_get_new_value sysctl:read EINVAL", -- .insns = { -- /* sysctl_get_new_value arg2 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- -- BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -- -- /* sysctl_get_new_value arg3 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_3, 8), -- -- /* sysctl_get_new_value(ctx, buf, buf_len) */ -- BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value), -- -- /* if (ret == expected) */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2), -- -- /* return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_JMP_A(1), -- -- /* else return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/tcp_mem", -- .open_flags = O_RDONLY, -- .result = SUCCESS, -- }, -- { -- .descr = "sysctl_get_new_value sysctl:write ok", -- .insns = { -- /* sysctl_get_new_value arg2 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- -- BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -- -- /* sysctl_get_new_value arg3 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_3, 4), -- -- /* sysctl_get_new_value(ctx, buf, buf_len) */ -- BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value), -- -- /* if (ret == expected && */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4), -- -- /* buf[0:4] == "606\0") */ -- BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_7, 0), -- BPF_JMP_IMM(BPF_JNE, BPF_REG_9, -- bpf_ntohl(0x36303600), 2), -- -- /* return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_JMP_A(1), -- -- /* else return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/route/mtu_expires", -- .open_flags = O_WRONLY, -- .newval = "606", -- .result = OP_EPERM, -- }, -- { -- .descr = "sysctl_get_new_value sysctl:write ok long", -- .insns = { -- /* sysctl_get_new_value arg2 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -24), -- -- BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -- -- /* sysctl_get_new_value arg3 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_3, 24), -- -- /* sysctl_get_new_value(ctx, buf, buf_len) */ -- BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value), -- -- /* if (ret == expected && */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 23, 14), -- -- /* buf[0:8] == "3000000 " && */ -- BPF_LD_IMM64(BPF_REG_8, -- bpf_be64_to_cpu(0x3330303030303020ULL)), -- BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -- BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 10), -- -- /* buf[8:16] == "4000000 " && */ -- BPF_LD_IMM64(BPF_REG_8, -- bpf_be64_to_cpu(0x3430303030303020ULL)), -- BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 8), -- BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 6), -- -- /* buf[16:24] == "6000000\0") */ -- BPF_LD_IMM64(BPF_REG_8, -- bpf_be64_to_cpu(0x3630303030303000ULL)), -- BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 16), -- BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2), -- -- /* return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_JMP_A(1), -- -- /* else return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/tcp_mem", -- .open_flags = O_WRONLY, -- .newval = "3000000 4000000 6000000", -- .result = OP_EPERM, -- }, -- { -- .descr = "sysctl_get_new_value sysctl:write E2BIG", -- .insns = { -- /* sysctl_get_new_value arg2 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_STX_MEM(BPF_B, BPF_REG_7, BPF_REG_0, 3), -- -- BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -- -- /* sysctl_get_new_value arg3 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_3, 3), -- -- /* sysctl_get_new_value(ctx, buf, buf_len) */ -- BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value), -- -- /* if (ret == expected && */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 4), -- -- /* buf[0:3] == "60\0") */ -- BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_7, 0), -- BPF_JMP_IMM(BPF_JNE, BPF_REG_9, -- bpf_ntohl(0x36300000), 2), -- -- /* return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_JMP_A(1), -- -- /* else return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/route/mtu_expires", -- .open_flags = O_WRONLY, -- .newval = "606", -- .result = OP_EPERM, -- }, -- { -- .descr = "sysctl_set_new_value sysctl:read EINVAL", -- .insns = { -- /* sysctl_set_new_value arg2 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_MOV64_IMM(BPF_REG_0, -- bpf_ntohl(0x36303000)), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- -- BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -- -- /* sysctl_set_new_value arg3 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_3, 3), -- -- /* sysctl_set_new_value(ctx, buf, buf_len) */ -- BPF_EMIT_CALL(BPF_FUNC_sysctl_set_new_value), -- -- /* if (ret == expected) */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2), -- -- /* return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_JMP_A(1), -- -- /* else return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/route/mtu_expires", -- .open_flags = O_RDONLY, -- .result = SUCCESS, -- }, -- { -- .descr = "sysctl_set_new_value sysctl:write ok", -- .fixup_value_insn = 2, -- .insns = { -- /* sysctl_set_new_value arg2 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_LD_IMM64(BPF_REG_0, FIXUP_SYSCTL_VALUE), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- -- BPF_MOV64_REG(BPF_REG_2, BPF_REG_7), -- -- /* sysctl_set_new_value arg3 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_3, 3), -- -- /* sysctl_set_new_value(ctx, buf, buf_len) */ -- BPF_EMIT_CALL(BPF_FUNC_sysctl_set_new_value), -- -- /* if (ret == expected) */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2), -- -- /* return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_JMP_A(1), -- -- /* else return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/route/mtu_expires", -- .open_flags = O_WRONLY, -- .newval = "606", -- .result = SUCCESS, -- }, -- { -- "bpf_strtoul one number string", -- .insns = { -- /* arg1 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_MOV64_IMM(BPF_REG_0, -- bpf_ntohl(0x36303000)), -- BPF_STX_MEM(BPF_W, BPF_REG_7, BPF_REG_0, 0), -- -- BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -- -- /* arg2 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_2, 4), -- -- /* arg3 (flags) */ -- BPF_MOV64_IMM(BPF_REG_3, 0), -- -- /* arg4 (res) */ -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -- -- BPF_EMIT_CALL(BPF_FUNC_strtoul), -- -- /* if (ret == expected && */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4), -- /* res == expected) */ -- BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -- BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 600, 2), -- -- /* return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_JMP_A(1), -- -- /* else return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/route/mtu_expires", -- .open_flags = O_RDONLY, -- .result = SUCCESS, -- }, -- { -- "bpf_strtoul multi number string", -- .insns = { -- /* arg1 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- /* "600 602\0" */ -- BPF_LD_IMM64(BPF_REG_0, -- bpf_be64_to_cpu(0x3630302036303200ULL)), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -- -- /* arg2 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_2, 8), -- -- /* arg3 (flags) */ -- BPF_MOV64_IMM(BPF_REG_3, 0), -- -- /* arg4 (res) */ -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -- -- BPF_EMIT_CALL(BPF_FUNC_strtoul), -- -- /* if (ret == expected && */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 18), -- /* res == expected) */ -- BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -- BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 600, 16), -- -- /* arg1 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_ALU64_REG(BPF_ADD, BPF_REG_7, BPF_REG_0), -- BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -- -- /* arg2 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_2, 8), -- BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_0), -- -- /* arg3 (flags) */ -- BPF_MOV64_IMM(BPF_REG_3, 0), -- -- /* arg4 (res) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -16), -- BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -- -- BPF_EMIT_CALL(BPF_FUNC_strtoul), -- -- /* if (ret == expected && */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 4), -- /* res == expected) */ -- BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -- BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 602, 2), -- -- /* return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_JMP_A(1), -- -- /* else return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/tcp_mem", -- .open_flags = O_RDONLY, -- .result = SUCCESS, -- }, -- { -- "bpf_strtoul buf_len = 0, reject", -- .insns = { -- /* arg1 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_MOV64_IMM(BPF_REG_0, -- bpf_ntohl(0x36303000)), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- -- BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -- -- /* arg2 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_2, 0), -- -- /* arg3 (flags) */ -- BPF_MOV64_IMM(BPF_REG_3, 0), -- -- /* arg4 (res) */ -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -- -- BPF_EMIT_CALL(BPF_FUNC_strtoul), -- -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/route/mtu_expires", -- .open_flags = O_RDONLY, -- .result = LOAD_REJECT, -- }, -- { -- "bpf_strtoul supported base, ok", -- .insns = { -- /* arg1 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_MOV64_IMM(BPF_REG_0, -- bpf_ntohl(0x30373700)), -- BPF_STX_MEM(BPF_W, BPF_REG_7, BPF_REG_0, 0), -- -- BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -- -- /* arg2 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_2, 4), -- -- /* arg3 (flags) */ -- BPF_MOV64_IMM(BPF_REG_3, 8), -- -- /* arg4 (res) */ -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -- -- BPF_EMIT_CALL(BPF_FUNC_strtoul), -- -- /* if (ret == expected && */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4), -- /* res == expected) */ -- BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -- BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 63, 2), -- -- /* return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_JMP_A(1), -- -- /* else return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/route/mtu_expires", -- .open_flags = O_RDONLY, -- .result = SUCCESS, -- }, -- { -- "bpf_strtoul unsupported base, EINVAL", -- .insns = { -- /* arg1 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_MOV64_IMM(BPF_REG_0, -- bpf_ntohl(0x36303000)), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- -- BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -- -- /* arg2 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_2, 4), -- -- /* arg3 (flags) */ -- BPF_MOV64_IMM(BPF_REG_3, 3), -- -- /* arg4 (res) */ -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -- -- BPF_EMIT_CALL(BPF_FUNC_strtoul), -- -- /* if (ret == expected) */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2), -- -- /* return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_JMP_A(1), -- -- /* else return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/route/mtu_expires", -- .open_flags = O_RDONLY, -- .result = SUCCESS, -- }, -- { -- "bpf_strtoul buf with spaces only, EINVAL", -- .insns = { -- /* arg1 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_MOV64_IMM(BPF_REG_0, -- bpf_ntohl(0x0d0c0a09)), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- -- BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -- -- /* arg2 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_2, 4), -- -- /* arg3 (flags) */ -- BPF_MOV64_IMM(BPF_REG_3, 0), -- -- /* arg4 (res) */ -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -- -- BPF_EMIT_CALL(BPF_FUNC_strtoul), -- -- /* if (ret == expected) */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2), -- -- /* return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_JMP_A(1), -- -- /* else return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/route/mtu_expires", -- .open_flags = O_RDONLY, -- .result = SUCCESS, -- }, -- { -- "bpf_strtoul negative number, EINVAL", -- .insns = { -- /* arg1 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- /* " -6\0" */ -- BPF_MOV64_IMM(BPF_REG_0, -- bpf_ntohl(0x0a2d3600)), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- -- BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -- -- /* arg2 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_2, 4), -- -- /* arg3 (flags) */ -- BPF_MOV64_IMM(BPF_REG_3, 0), -- -- /* arg4 (res) */ -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -- -- BPF_EMIT_CALL(BPF_FUNC_strtoul), -- -- /* if (ret == expected) */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2), -- -- /* return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_JMP_A(1), -- -- /* else return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/route/mtu_expires", -- .open_flags = O_RDONLY, -- .result = SUCCESS, -- }, -- { -- "bpf_strtol negative number, ok", -- .insns = { -- /* arg1 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- /* " -6\0" */ -- BPF_MOV64_IMM(BPF_REG_0, -- bpf_ntohl(0x0a2d3600)), -- BPF_STX_MEM(BPF_W, BPF_REG_7, BPF_REG_0, 0), -- -- BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -- -- /* arg2 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_2, 4), -- -- /* arg3 (flags) */ -- BPF_MOV64_IMM(BPF_REG_3, 10), -- -- /* arg4 (res) */ -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -- -- BPF_EMIT_CALL(BPF_FUNC_strtol), -- -- /* if (ret == expected && */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4), -- /* res == expected) */ -- BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -- BPF_JMP_IMM(BPF_JNE, BPF_REG_9, -6, 2), -- -- /* return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_JMP_A(1), -- -- /* else return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/route/mtu_expires", -- .open_flags = O_RDONLY, -- .result = SUCCESS, -- }, -- { -- "bpf_strtol hex number, ok", -- .insns = { -- /* arg1 (buf) */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- /* "0xfe" */ -- BPF_MOV64_IMM(BPF_REG_0, -- bpf_ntohl(0x30786665)), -- BPF_STX_MEM(BPF_W, BPF_REG_7, BPF_REG_0, 0), -- -- BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -- -- /* arg2 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_2, 4), -- -- /* arg3 (flags) */ -- BPF_MOV64_IMM(BPF_REG_3, 0), -- -- /* arg4 (res) */ -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -- -- BPF_EMIT_CALL(BPF_FUNC_strtol), -- -- /* if (ret == expected && */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 4), -- /* res == expected) */ -- BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -- BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 254, 2), -- -- /* return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_JMP_A(1), -- -- /* else return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/route/mtu_expires", -- .open_flags = O_RDONLY, -- .result = SUCCESS, -- }, -- { -- "bpf_strtol max long", -- .insns = { -- /* arg1 (buf) 9223372036854775807 */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -24), -- BPF_LD_IMM64(BPF_REG_0, -- bpf_be64_to_cpu(0x3932323333373230ULL)), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- BPF_LD_IMM64(BPF_REG_0, -- bpf_be64_to_cpu(0x3336383534373735ULL)), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 8), -- BPF_LD_IMM64(BPF_REG_0, -- bpf_be64_to_cpu(0x3830370000000000ULL)), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 16), -- -- BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -- -- /* arg2 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_2, 19), -- -- /* arg3 (flags) */ -- BPF_MOV64_IMM(BPF_REG_3, 0), -- -- /* arg4 (res) */ -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -- -- BPF_EMIT_CALL(BPF_FUNC_strtol), -- -- /* if (ret == expected && */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 19, 6), -- /* res == expected) */ -- BPF_LD_IMM64(BPF_REG_8, 0x7fffffffffffffffULL), -- BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0), -- BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2), -- -- /* return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_JMP_A(1), -- -- /* else return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/route/mtu_expires", -- .open_flags = O_RDONLY, -- .result = SUCCESS, -- }, -- { -- "bpf_strtol overflow, ERANGE", -- .insns = { -- /* arg1 (buf) 9223372036854775808 */ -- BPF_MOV64_REG(BPF_REG_7, BPF_REG_10), -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -24), -- BPF_LD_IMM64(BPF_REG_0, -- bpf_be64_to_cpu(0x3932323333373230ULL)), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- BPF_LD_IMM64(BPF_REG_0, -- bpf_be64_to_cpu(0x3336383534373735ULL)), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 8), -- BPF_LD_IMM64(BPF_REG_0, -- bpf_be64_to_cpu(0x3830380000000000ULL)), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 16), -- -- BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), -- -- /* arg2 (buf_len) */ -- BPF_MOV64_IMM(BPF_REG_2, 19), -- -- /* arg3 (flags) */ -- BPF_MOV64_IMM(BPF_REG_3, 0), -- -- /* arg4 (res) */ -- BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8), -- BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0), -- BPF_MOV64_REG(BPF_REG_4, BPF_REG_7), -- -- BPF_EMIT_CALL(BPF_FUNC_strtol), -- -- /* if (ret == expected) */ -- BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -ERANGE, 2), -- -- /* return ALLOW; */ -- BPF_MOV64_IMM(BPF_REG_0, 1), -- BPF_JMP_A(1), -- -- /* else return DENY; */ -- BPF_MOV64_IMM(BPF_REG_0, 0), -- BPF_EXIT_INSN(), -- }, -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/route/mtu_expires", -- .open_flags = O_RDONLY, -- .result = SUCCESS, -- }, -- { -- "C prog: deny all writes", -- .prog_file = "./test_sysctl_prog.bpf.o", -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/tcp_mem", -- .open_flags = O_WRONLY, -- .newval = "123 456 789", -- .result = OP_EPERM, -- }, -- { -- "C prog: deny access by name", -- .prog_file = "./test_sysctl_prog.bpf.o", -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/route/mtu_expires", -- .open_flags = O_RDONLY, -- .result = OP_EPERM, -- }, -- { -- "C prog: read tcp_mem", -- .prog_file = "./test_sysctl_prog.bpf.o", -- .attach_type = BPF_CGROUP_SYSCTL, -- .sysctl = "net/ipv4/tcp_mem", -- .open_flags = O_RDONLY, -- .result = SUCCESS, -- }, --}; -- --static size_t probe_prog_length(const struct bpf_insn *fp) --{ -- size_t len; -- -- for (len = MAX_INSNS - 1; len > 0; --len) -- if (fp[len].code != 0 || fp[len].imm != 0) -- break; -- return len + 1; --} -- --static int fixup_sysctl_value(const char *buf, size_t buf_len, -- struct bpf_insn *prog, size_t insn_num) --{ -- union { -- uint8_t raw[sizeof(uint64_t)]; -- uint64_t num; -- } value = {}; -- -- if (buf_len > sizeof(value)) { -- log_err("Value is too big (%zd) to use in fixup", buf_len); -- return -1; -- } -- if (prog[insn_num].code != (BPF_LD | BPF_DW | BPF_IMM)) { -- log_err("Can fixup only BPF_LD_IMM64 insns"); -- return -1; -- } -- -- memcpy(value.raw, buf, buf_len); -- prog[insn_num].imm = (uint32_t)value.num; -- prog[insn_num + 1].imm = (uint32_t)(value.num >> 32); -- -- return 0; --} -- --static int load_sysctl_prog_insns(struct sysctl_test *test, -- const char *sysctl_path) --{ -- struct bpf_insn *prog = test->insns; -- LIBBPF_OPTS(bpf_prog_load_opts, opts); -- int ret, insn_cnt; -- -- insn_cnt = probe_prog_length(prog); -- -- if (test->fixup_value_insn) { -- char buf[128]; -- ssize_t len; -- int fd; -- -- fd = open(sysctl_path, O_RDONLY | O_CLOEXEC); -- if (fd < 0) { -- log_err("open(%s) failed", sysctl_path); -- return -1; -- } -- len = read(fd, buf, sizeof(buf)); -- if (len == -1) { -- log_err("read(%s) failed", sysctl_path); -- close(fd); -- return -1; -- } -- close(fd); -- if (fixup_sysctl_value(buf, len, prog, test->fixup_value_insn)) -- return -1; -- } -- -- opts.log_buf = bpf_log_buf; -- opts.log_size = BPF_LOG_BUF_SIZE; -- -- ret = bpf_prog_load(BPF_PROG_TYPE_CGROUP_SYSCTL, NULL, "GPL", prog, insn_cnt, &opts); -- if (ret < 0 && test->result != LOAD_REJECT) { -- log_err(">>> Loading program error.\n" -- ">>> Verifier output:\n%s\n-------\n", bpf_log_buf); -- } -- -- return ret; --} -- --static int load_sysctl_prog_file(struct sysctl_test *test) --{ -- struct bpf_object *obj; -- int prog_fd; -- -- if (bpf_prog_test_load(test->prog_file, BPF_PROG_TYPE_CGROUP_SYSCTL, &obj, &prog_fd)) { -- if (test->result != LOAD_REJECT) -- log_err(">>> Loading program (%s) error.\n", -- test->prog_file); -- return -1; -- } -- -- return prog_fd; --} -- --static int load_sysctl_prog(struct sysctl_test *test, const char *sysctl_path) --{ -- return test->prog_file -- ? load_sysctl_prog_file(test) -- : load_sysctl_prog_insns(test, sysctl_path); --} -- --static int access_sysctl(const char *sysctl_path, -- const struct sysctl_test *test) --{ -- int err = 0; -- int fd; -- -- fd = open(sysctl_path, test->open_flags | O_CLOEXEC); -- if (fd < 0) -- return fd; -- -- if (test->seek && lseek(fd, test->seek, SEEK_SET) == -1) { -- log_err("lseek(%d) failed", test->seek); -- goto err; -- } -- -- if (test->open_flags == O_RDONLY) { -- char buf[128]; -- -- if (read(fd, buf, sizeof(buf)) == -1) -- goto err; -- if (test->oldval && -- strncmp(buf, test->oldval, strlen(test->oldval))) { -- log_err("Read value %s != %s", buf, test->oldval); -- goto err; -- } -- } else if (test->open_flags == O_WRONLY) { -- if (!test->newval) { -- log_err("New value for sysctl is not set"); -- goto err; -- } -- if (write(fd, test->newval, strlen(test->newval)) == -1) -- goto err; -- } else { -- log_err("Unexpected sysctl access: neither read nor write"); -- goto err; -- } -- -- goto out; --err: -- err = -1; --out: -- close(fd); -- return err; --} -- --static int run_test_case(int cgfd, struct sysctl_test *test) --{ -- enum bpf_attach_type atype = test->attach_type; -- char sysctl_path[128]; -- int progfd = -1; -- int err = 0; -- -- printf("Test case: %s .. ", test->descr); -- -- snprintf(sysctl_path, sizeof(sysctl_path), "/proc/sys/%s", -- test->sysctl); -- -- progfd = load_sysctl_prog(test, sysctl_path); -- if (progfd < 0) { -- if (test->result == LOAD_REJECT) -- goto out; -- else -- goto err; -- } -- -- if (bpf_prog_attach(progfd, cgfd, atype, BPF_F_ALLOW_OVERRIDE) < 0) { -- if (test->result == ATTACH_REJECT) -- goto out; -- else -- goto err; -- } -- -- errno = 0; -- if (access_sysctl(sysctl_path, test) == -1) { -- if (test->result == OP_EPERM && errno == EPERM) -- goto out; -- else -- goto err; -- } -- -- if (test->result != SUCCESS) { -- log_err("Unexpected success"); -- goto err; -- } -- -- goto out; --err: -- err = -1; --out: -- /* Detaching w/o checking return code: best effort attempt. */ -- if (progfd != -1) -- bpf_prog_detach(cgfd, atype); -- close(progfd); -- printf("[%s]\n", err ? "FAIL" : "PASS"); -- return err; --} -- --static int run_tests(int cgfd) --{ -- int passes = 0; -- int fails = 0; -- int i; -- -- for (i = 0; i < ARRAY_SIZE(tests); ++i) { -- if (run_test_case(cgfd, &tests[i])) -- ++fails; -- else -- ++passes; -- } -- printf("Summary: %d PASSED, %d FAILED\n", passes, fails); -- return fails ? -1 : 0; --} -- --int main(int argc, char **argv) --{ -- int cgfd = -1; -- int err = 0; -- -- cgfd = cgroup_setup_and_join(CG_PATH); -- if (cgfd < 0) -- goto err; -- -- /* Use libbpf 1.0 API mode */ -- libbpf_set_strict_mode(LIBBPF_STRICT_ALL); -- -- if (run_tests(cgfd)) -- goto err; -- -- goto out; --err: -- err = -1; --out: -- close(cgfd); -- cleanup_cgroup_environment(); -- return err; --} -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/bpf/veristat.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/veristat.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/bpf/veristat.c 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/bpf/veristat.c 2025-10-22 13:53:56.871167425 -0400 -@@ -344,6 +344,7 @@ static error_t parse_arg(int key, char * - fprintf(stderr, "invalid top N specifier: %s\n", arg); - argp_usage(state); - } -+ break; - case 'C': - env.comparison_mode = true; - break; -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/breakpoints/step_after_suspend_test.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/breakpoints/step_after_suspend_test.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/breakpoints/step_after_suspend_test.c 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/breakpoints/step_after_suspend_test.c 2025-10-22 13:53:56.871167425 -0400 -@@ -127,22 +127,42 @@ int run_test(int cpu) - return KSFT_PASS; - } - -+/* -+ * Reads the suspend success count from sysfs. -+ * Returns the count on success or exits on failure. -+ */ -+static int get_suspend_success_count_or_fail(void) -+{ -+ FILE *fp; -+ int val; -+ -+ fp = fopen("/sys/power/suspend_stats/success", "r"); -+ if (!fp) -+ ksft_exit_fail_msg( -+ "Failed to open suspend_stats/success: %s\n", -+ strerror(errno)); -+ -+ if (fscanf(fp, "%d", &val) != 1) { -+ fclose(fp); -+ ksft_exit_fail_msg( -+ "Failed to read suspend success count\n"); -+ } -+ -+ fclose(fp); -+ return val; -+} -+ - void suspend(void) - { -- int power_state_fd; - int timerfd; - int err; -+ int count_before; -+ int count_after; - struct itimerspec spec = {}; - - if (getuid() != 0) - ksft_exit_skip("Please run the test as root - Exiting.\n"); - -- power_state_fd = open("/sys/power/state", O_RDWR); -- if (power_state_fd < 0) -- ksft_exit_fail_msg( -- "open(\"/sys/power/state\") failed %s)\n", -- strerror(errno)); -- - timerfd = timerfd_create(CLOCK_BOOTTIME_ALARM, 0); - if (timerfd < 0) - ksft_exit_fail_msg("timerfd_create() failed\n"); -@@ -152,14 +172,15 @@ void suspend(void) - if (err < 0) - ksft_exit_fail_msg("timerfd_settime() failed\n"); - -+ count_before = get_suspend_success_count_or_fail(); -+ - system("(echo mem > /sys/power/state) 2> /dev/null"); - -- timerfd_gettime(timerfd, &spec); -- if (spec.it_value.tv_sec != 0 || spec.it_value.tv_nsec != 0) -+ count_after = get_suspend_success_count_or_fail(); -+ if (count_after <= count_before) - ksft_exit_fail_msg("Failed to enter Suspend state\n"); - - close(timerfd); -- close(power_state_fd); - } - - int main(int argc, char **argv) -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/cgroup/test_cpu.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/cgroup/test_cpu.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/cgroup/test_cpu.c 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/cgroup/test_cpu.c 2025-10-22 13:53:56.871167425 -0400 -@@ -2,6 +2,7 @@ - - #define _GNU_SOURCE - #include -+#include - #include - #include - #include -@@ -645,10 +646,16 @@ test_cpucg_nested_weight_underprovisione - static int test_cpucg_max(const char *root) - { - int ret = KSFT_FAIL; -- long usage_usec, user_usec; -- long usage_seconds = 1; -- long expected_usage_usec = usage_seconds * USEC_PER_SEC; -+ long quota_usec = 1000; -+ long default_period_usec = 100000; /* cpu.max's default period */ -+ long duration_seconds = 1; -+ -+ long duration_usec = duration_seconds * USEC_PER_SEC; -+ long usage_usec, n_periods, remainder_usec, expected_usage_usec; - char *cpucg; -+ char quota_buf[32]; -+ -+ snprintf(quota_buf, sizeof(quota_buf), "%ld", quota_usec); - - cpucg = cg_name(root, "cpucg_test"); - if (!cpucg) -@@ -657,13 +664,13 @@ static int test_cpucg_max(const char *ro - if (cg_create(cpucg)) - goto cleanup; - -- if (cg_write(cpucg, "cpu.max", "1000")) -+ if (cg_write(cpucg, "cpu.max", quota_buf)) - goto cleanup; - - struct cpu_hog_func_param param = { - .nprocs = 1, - .ts = { -- .tv_sec = usage_seconds, -+ .tv_sec = duration_seconds, - .tv_nsec = 0, - }, - .clock_type = CPU_HOG_CLOCK_WALL, -@@ -672,14 +679,19 @@ static int test_cpucg_max(const char *ro - goto cleanup; - - usage_usec = cg_read_key_long(cpucg, "cpu.stat", "usage_usec"); -- user_usec = cg_read_key_long(cpucg, "cpu.stat", "user_usec"); -- if (user_usec <= 0) -+ if (usage_usec <= 0) - goto cleanup; - -- if (user_usec >= expected_usage_usec) -- goto cleanup; -+ /* -+ * The following calculation applies only since -+ * the cpu hog is set to run as per wall-clock time -+ */ -+ n_periods = duration_usec / default_period_usec; -+ remainder_usec = duration_usec - n_periods * default_period_usec; -+ expected_usage_usec -+ = n_periods * quota_usec + MIN(remainder_usec, quota_usec); - -- if (values_close(usage_usec, expected_usage_usec, 95)) -+ if (!values_close(usage_usec, expected_usage_usec, 10)) - goto cleanup; - - ret = KSFT_PASS; -@@ -698,10 +710,16 @@ cleanup: - static int test_cpucg_max_nested(const char *root) - { - int ret = KSFT_FAIL; -- long usage_usec, user_usec; -- long usage_seconds = 1; -- long expected_usage_usec = usage_seconds * USEC_PER_SEC; -+ long quota_usec = 1000; -+ long default_period_usec = 100000; /* cpu.max's default period */ -+ long duration_seconds = 1; -+ -+ long duration_usec = duration_seconds * USEC_PER_SEC; -+ long usage_usec, n_periods, remainder_usec, expected_usage_usec; - char *parent, *child; -+ char quota_buf[32]; -+ -+ snprintf(quota_buf, sizeof(quota_buf), "%ld", quota_usec); - - parent = cg_name(root, "cpucg_parent"); - child = cg_name(parent, "cpucg_child"); -@@ -717,13 +735,13 @@ static int test_cpucg_max_nested(const c - if (cg_create(child)) - goto cleanup; - -- if (cg_write(parent, "cpu.max", "1000")) -+ if (cg_write(parent, "cpu.max", quota_buf)) - goto cleanup; - - struct cpu_hog_func_param param = { - .nprocs = 1, - .ts = { -- .tv_sec = usage_seconds, -+ .tv_sec = duration_seconds, - .tv_nsec = 0, - }, - .clock_type = CPU_HOG_CLOCK_WALL, -@@ -732,14 +750,19 @@ static int test_cpucg_max_nested(const c - goto cleanup; - - usage_usec = cg_read_key_long(child, "cpu.stat", "usage_usec"); -- user_usec = cg_read_key_long(child, "cpu.stat", "user_usec"); -- if (user_usec <= 0) -+ if (usage_usec <= 0) - goto cleanup; - -- if (user_usec >= expected_usage_usec) -- goto cleanup; -+ /* -+ * The following calculation applies only since -+ * the cpu hog is set to run as per wall-clock time -+ */ -+ n_periods = duration_usec / default_period_usec; -+ remainder_usec = duration_usec - n_periods * default_period_usec; -+ expected_usage_usec -+ = n_periods * quota_usec + MIN(remainder_usec, quota_usec); - -- if (values_close(usage_usec, expected_usage_usec, 95)) -+ if (!values_close(usage_usec, expected_usage_usec, 10)) - goto cleanup; - - ret = KSFT_PASS; -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/coredump/stackdump_test.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/coredump/stackdump_test.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/coredump/stackdump_test.c 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/coredump/stackdump_test.c 2025-10-22 13:53:56.871167425 -0400 -@@ -461,10 +461,15 @@ TEST_F(coredump, socket_detect_userspace - _exit(EXIT_FAILURE); - } - -+ ret = read(fd_coredump, &c, 1); -+ - close(fd_coredump); - close(fd_server); - close(fd_peer_pidfd); - close(fd_core_file); -+ -+ if (ret < 1) -+ _exit(EXIT_FAILURE); - _exit(EXIT_SUCCESS); - } - self->pid_coredump_server = pid_coredump_server; -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/drivers/net/hw/csum.py BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/drivers/net/hw/csum.py ---- BPI-Router-Linux-kernel/tools/testing/selftests/drivers/net/hw/csum.py 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/drivers/net/hw/csum.py 2025-10-22 13:53:56.871167425 -0400 -@@ -17,7 +17,7 @@ def test_receive(cfg, ipver="6", extra_a - ip_args = f"-{ipver} -S {cfg.remote_addr_v[ipver]} -D {cfg.addr_v[ipver]}" - - rx_cmd = f"{cfg.bin_local} -i {cfg.ifname} -n 100 {ip_args} -r 1 -R {extra_args}" -- tx_cmd = f"{cfg.bin_remote} -i {cfg.ifname} -n 100 {ip_args} -r 1 -T {extra_args}" -+ tx_cmd = f"{cfg.bin_remote} -i {cfg.remote_ifname} -n 100 {ip_args} -r 1 -T {extra_args}" - - with bkg(rx_cmd, exit_wait=True): - wait_port_listen(34000, proto="udp") -@@ -37,7 +37,7 @@ def test_transmit(cfg, ipver="6", extra_ - if extra_args != "-U -Z": - extra_args += " -r 1" - -- rx_cmd = f"{cfg.bin_remote} -i {cfg.ifname} -L 1 -n 100 {ip_args} -R {extra_args}" -+ rx_cmd = f"{cfg.bin_remote} -i {cfg.remote_ifname} -L 1 -n 100 {ip_args} -R {extra_args}" - tx_cmd = f"{cfg.bin_local} -i {cfg.ifname} -L 1 -n 100 {ip_args} -T {extra_args}" - - with bkg(rx_cmd, host=cfg.remote, exit_wait=True): -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/drivers/net/hw/rss_ctx.py BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/drivers/net/hw/rss_ctx.py ---- BPI-Router-Linux-kernel/tools/testing/selftests/drivers/net/hw/rss_ctx.py 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/drivers/net/hw/rss_ctx.py 2025-10-22 13:53:56.871167425 -0400 -@@ -747,6 +747,62 @@ def test_rss_ntuple_addition(cfg): - 'noise' : (0,) }) - - -+def test_rss_default_context_rule(cfg): -+ """ -+ Allocate a port, direct this port to context 0, then create a new RSS -+ context and steer all TCP traffic to it (context 1). Verify that: -+ * Traffic to the specific port continues to use queues of the main -+ context (0/1). -+ * Traffic to any other TCP port is redirected to the new context -+ (queues 2/3). -+ """ -+ -+ require_ntuple(cfg) -+ -+ queue_cnt = len(_get_rx_cnts(cfg)) -+ if queue_cnt < 4: -+ try: -+ ksft_pr(f"Increasing queue count {queue_cnt} -> 4") -+ ethtool(f"-L {cfg.ifname} combined 4") -+ defer(ethtool, f"-L {cfg.ifname} combined {queue_cnt}") -+ except Exception as exc: -+ raise KsftSkipEx("Not enough queues for the test") from exc -+ -+ # Use queues 0 and 1 for the main context -+ ethtool(f"-X {cfg.ifname} equal 2") -+ defer(ethtool, f"-X {cfg.ifname} default") -+ -+ # Create a new RSS context that uses queues 2 and 3 -+ ctx_id = ethtool_create(cfg, "-X", "context new start 2 equal 2") -+ defer(ethtool, f"-X {cfg.ifname} context {ctx_id} delete") -+ -+ # Generic low-priority rule: redirect all TCP traffic to the new context. -+ # Give it an explicit higher location number (lower priority). -+ flow_generic = f"flow-type tcp{cfg.addr_ipver} dst-ip {cfg.addr} context {ctx_id} loc 1" -+ ethtool(f"-N {cfg.ifname} {flow_generic}") -+ defer(ethtool, f"-N {cfg.ifname} delete 1") -+ -+ # Specific high-priority rule for a random port that should stay on context 0. -+ # Assign loc 0 so it is evaluated before the generic rule. -+ port_main = rand_port() -+ flow_main = f"flow-type tcp{cfg.addr_ipver} dst-ip {cfg.addr} dst-port {port_main} context 0 loc 0" -+ ethtool(f"-N {cfg.ifname} {flow_main}") -+ defer(ethtool, f"-N {cfg.ifname} delete 0") -+ -+ _ntuple_rule_check(cfg, 1, ctx_id) -+ -+ # Verify that traffic matching the specific rule still goes to queues 0/1 -+ _send_traffic_check(cfg, port_main, "context 0", -+ { 'target': (0, 1), -+ 'empty' : (2, 3) }) -+ -+ # And that traffic for any other port is steered to the new context -+ port_other = rand_port() -+ _send_traffic_check(cfg, port_other, f"context {ctx_id}", -+ { 'target': (2, 3), -+ 'noise' : (0, 1) }) -+ -+ - def main() -> None: - with NetDrvEpEnv(__file__, nsim_test=False) as cfg: - cfg.context_cnt = None -@@ -760,7 +816,8 @@ def main() -> None: - test_rss_context_overlap, test_rss_context_overlap2, - test_rss_context_out_of_order, test_rss_context4_create_with_cfg, - test_flow_add_context_missing, -- test_delete_rss_context_busy, test_rss_ntuple_addition], -+ test_delete_rss_context_busy, test_rss_ntuple_addition, -+ test_rss_default_context_rule], - args=(cfg, )) - ksft_exit() - -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/drivers/net/hw/rss_input_xfrm.py BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/drivers/net/hw/rss_input_xfrm.py ---- BPI-Router-Linux-kernel/tools/testing/selftests/drivers/net/hw/rss_input_xfrm.py 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/drivers/net/hw/rss_input_xfrm.py 2025-10-22 13:53:56.871167425 -0400 -@@ -38,7 +38,7 @@ def test_rss_input_xfrm(cfg, ipver): - raise KsftSkipEx("socket.SO_INCOMING_CPU was added in Python 3.11") - - input_xfrm = cfg.ethnl.rss_get( -- {'header': {'dev-name': cfg.ifname}}).get('input_xfrm') -+ {'header': {'dev-name': cfg.ifname}}).get('input-xfrm') - - # Check for symmetric xor/or-xor - if not input_xfrm or (input_xfrm != 1 and input_xfrm != 2): -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/drivers/net/hw/tso.py BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/drivers/net/hw/tso.py ---- BPI-Router-Linux-kernel/tools/testing/selftests/drivers/net/hw/tso.py 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/drivers/net/hw/tso.py 2025-10-22 13:53:56.871167425 -0400 -@@ -102,7 +102,7 @@ def build_tunnel(cfg, outer_ipver, tun_i - remote_addr = cfg.remote_addr_v[outer_ipver] - - tun_type = tun_info[0] -- tun_arg = tun_info[2] -+ tun_arg = tun_info[1] - ip(f"link add {tun_type}-ksft type {tun_type} {tun_arg} local {local_addr} remote {remote_addr} dev {cfg.ifname}") - defer(ip, f"link del {tun_type}-ksft") - ip(f"link set dev {tun_type}-ksft up") -@@ -119,15 +119,30 @@ def build_tunnel(cfg, outer_ipver, tun_i - return remote_v4, remote_v6 - - -+def restore_wanted_features(cfg): -+ features_cmd = "" -+ for feature in cfg.hw_features: -+ setting = "on" if feature in cfg.wanted_features else "off" -+ features_cmd += f" {feature} {setting}" -+ try: -+ ethtool(f"-K {cfg.ifname} {features_cmd}") -+ except Exception as e: -+ ksft_pr(f"WARNING: failure restoring wanted features: {e}") -+ -+ - def test_builder(name, cfg, outer_ipver, feature, tun=None, inner_ipver=None): - """Construct specific tests from the common template.""" - def f(cfg): - cfg.require_ipver(outer_ipver) -+ defer(restore_wanted_features, cfg) - - if not cfg.have_stat_super_count and \ - not cfg.have_stat_wire_count: - raise KsftSkipEx(f"Device does not support LSO queue stats") - -+ if feature not in cfg.hw_features: -+ raise KsftSkipEx(f"Device does not support {feature}") -+ - ipver = outer_ipver - if tun: - remote_v4, remote_v6 = build_tunnel(cfg, ipver, tun) -@@ -136,36 +151,21 @@ def test_builder(name, cfg, outer_ipver, - remote_v4 = cfg.remote_addr_v["4"] - remote_v6 = cfg.remote_addr_v["6"] - -- tun_partial = tun and tun[1] -- # Tunnel which can silently fall back to gso-partial -- has_gso_partial = tun and 'tx-gso-partial' in cfg.features -- -- # For TSO4 via partial we need mangleid -- if ipver == "4" and feature in cfg.partial_features: -- ksft_pr("Testing with mangleid enabled") -- if 'tx-tcp-mangleid-segmentation' not in cfg.features: -- ethtool(f"-K {cfg.ifname} tx-tcp-mangleid-segmentation on") -- defer(ethtool, f"-K {cfg.ifname} tx-tcp-mangleid-segmentation off") -- - # First test without the feature enabled. - ethtool(f"-K {cfg.ifname} {feature} off") -- if has_gso_partial: -- ethtool(f"-K {cfg.ifname} tx-gso-partial off") - run_one_stream(cfg, ipver, remote_v4, remote_v6, should_lso=False) - -- # Now test with the feature enabled. -- # For compatible tunnels only - just GSO partial, not specific feature. -- if has_gso_partial: -+ ethtool(f"-K {cfg.ifname} tx-gso-partial off") -+ ethtool(f"-K {cfg.ifname} tx-tcp-mangleid-segmentation off") -+ if feature in cfg.partial_features: - ethtool(f"-K {cfg.ifname} tx-gso-partial on") -- run_one_stream(cfg, ipver, remote_v4, remote_v6, -- should_lso=tun_partial) -+ if ipver == "4": -+ ksft_pr("Testing with mangleid enabled") -+ ethtool(f"-K {cfg.ifname} tx-tcp-mangleid-segmentation on") - - # Full feature enabled. -- if feature in cfg.features: -- ethtool(f"-K {cfg.ifname} {feature} on") -- run_one_stream(cfg, ipver, remote_v4, remote_v6, should_lso=True) -- else: -- raise KsftXfailEx(f"Device does not support {feature}") -+ ethtool(f"-K {cfg.ifname} {feature} on") -+ run_one_stream(cfg, ipver, remote_v4, remote_v6, should_lso=True) - - f.__name__ = name + ((outer_ipver + "_") if tun else "") + "ipv" + inner_ipver - return f -@@ -176,23 +176,39 @@ def query_nic_features(cfg) -> None: - cfg.have_stat_super_count = False - cfg.have_stat_wire_count = False - -- cfg.features = set() - features = cfg.ethnl.features_get({"header": {"dev-index": cfg.ifindex}}) -- for f in features["active"]["bits"]["bit"]: -- cfg.features.add(f["name"]) -+ -+ cfg.wanted_features = set() -+ for f in features["wanted"]["bits"]["bit"]: -+ cfg.wanted_features.add(f["name"]) -+ -+ cfg.hw_features = set() -+ hw_all_features_cmd = "" -+ for f in features["hw"]["bits"]["bit"]: -+ if f.get("value", False): -+ feature = f["name"] -+ cfg.hw_features.add(feature) -+ hw_all_features_cmd += f" {feature} on" -+ try: -+ ethtool(f"-K {cfg.ifname} {hw_all_features_cmd}") -+ except Exception as e: -+ ksft_pr(f"WARNING: failure enabling all hw features: {e}") -+ ksft_pr("partial gso feature detection may be impacted") - - # Check which features are supported via GSO partial - cfg.partial_features = set() -- if 'tx-gso-partial' in cfg.features: -+ if 'tx-gso-partial' in cfg.hw_features: - ethtool(f"-K {cfg.ifname} tx-gso-partial off") - - no_partial = set() - features = cfg.ethnl.features_get({"header": {"dev-index": cfg.ifindex}}) - for f in features["active"]["bits"]["bit"]: - no_partial.add(f["name"]) -- cfg.partial_features = cfg.features - no_partial -+ cfg.partial_features = cfg.hw_features - no_partial - ethtool(f"-K {cfg.ifname} tx-gso-partial on") - -+ restore_wanted_features(cfg) -+ - stats = cfg.netnl.qstats_get({"ifindex": cfg.ifindex}, dump=True) - if stats: - if 'tx-hw-gso-packets' in stats[0]: -@@ -211,13 +227,14 @@ def main() -> None: - query_nic_features(cfg) - - test_info = ( -- # name, v4/v6 ethtool_feature tun:(type, partial, args) -- ("", "4", "tx-tcp-segmentation", None), -- ("", "6", "tx-tcp6-segmentation", None), -- ("vxlan", "", "tx-udp_tnl-segmentation", ("vxlan", True, "id 100 dstport 4789 noudpcsum")), -- ("vxlan_csum", "", "tx-udp_tnl-csum-segmentation", ("vxlan", False, "id 100 dstport 4789 udpcsum")), -- ("gre", "4", "tx-gre-segmentation", ("gre", False, "")), -- ("gre", "6", "tx-gre-segmentation", ("ip6gre", False, "")), -+ # name, v4/v6 ethtool_feature tun:(type, args, inner ip versions) -+ ("", "4", "tx-tcp-segmentation", None), -+ ("", "6", "tx-tcp6-segmentation", None), -+ ("vxlan", "4", "tx-udp_tnl-segmentation", ("vxlan", "id 100 dstport 4789 noudpcsum", ("4", "6"))), -+ ("vxlan", "6", "tx-udp_tnl-segmentation", ("vxlan", "id 100 dstport 4789 udp6zerocsumtx udp6zerocsumrx", ("4", "6"))), -+ ("vxlan_csum", "", "tx-udp_tnl-csum-segmentation", ("vxlan", "id 100 dstport 4789 udpcsum", ("4", "6"))), -+ ("gre", "4", "tx-gre-segmentation", ("gre", "", ("4", "6"))), -+ ("gre", "6", "tx-gre-segmentation", ("ip6gre","", ("4", "6"))), - ) - - cases = [] -@@ -227,11 +244,13 @@ def main() -> None: - if info[1] and outer_ipver != info[1]: - continue - -- cases.append(test_builder(info[0], cfg, outer_ipver, info[2], -- tun=info[3], inner_ipver="4")) - if info[3]: -- cases.append(test_builder(info[0], cfg, outer_ipver, info[2], -- tun=info[3], inner_ipver="6")) -+ cases += [ -+ test_builder(info[0], cfg, outer_ipver, info[2], info[3], inner_ipver) -+ for inner_ipver in info[3][2] -+ ] -+ else: -+ cases.append(test_builder(info[0], cfg, outer_ipver, info[2], None, outer_ipver)) - - ksft_run(cases=cases, args=(cfg, )) - ksft_exit() -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/drivers/net/lib/py/env.py BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/drivers/net/lib/py/env.py ---- BPI-Router-Linux-kernel/tools/testing/selftests/drivers/net/lib/py/env.py 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/drivers/net/lib/py/env.py 2025-10-22 13:53:56.871167425 -0400 -@@ -259,7 +259,7 @@ class NetDrvEpEnv(NetDrvEnvBase): - if not self._require_cmd(comm, "local"): - raise KsftSkipEx("Test requires command: " + comm) - if remote: -- if not self._require_cmd(comm, "remote"): -+ if not self._require_cmd(comm, "remote", host=self.remote): - raise KsftSkipEx("Test requires (remote) command: " + comm) - - def wait_hw_stats_settle(self): -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/drivers/net/lib/py/load.py BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/drivers/net/lib/py/load.py ---- BPI-Router-Linux-kernel/tools/testing/selftests/drivers/net/lib/py/load.py 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/drivers/net/lib/py/load.py 2025-10-22 13:53:56.871167425 -0400 -@@ -1,5 +1,6 @@ - # SPDX-License-Identifier: GPL-2.0 - -+import re - import time - - from lib.py import ksft_pr, cmd, ip, rand_port, wait_port_listen -@@ -10,12 +11,11 @@ class GenerateTraffic: - - self.env = env - -- if port is None: -- port = rand_port() -- self._iperf_server = cmd(f"iperf3 -s -1 -p {port}", background=True) -- wait_port_listen(port) -+ self.port = rand_port() if port is None else port -+ self._iperf_server = cmd(f"iperf3 -s -1 -p {self.port}", background=True) -+ wait_port_listen(self.port) - time.sleep(0.1) -- self._iperf_client = cmd(f"iperf3 -c {env.addr} -P 16 -p {port} -t 86400", -+ self._iperf_client = cmd(f"iperf3 -c {env.addr} -P 16 -p {self.port} -t 86400", - background=True, host=env.remote) - - # Wait for traffic to ramp up -@@ -56,3 +56,16 @@ class GenerateTraffic: - ksft_pr(">> Server:") - ksft_pr(self._iperf_server.stdout) - ksft_pr(self._iperf_server.stderr) -+ self._wait_client_stopped() -+ -+ def _wait_client_stopped(self, sleep=0.005, timeout=5): -+ end = time.monotonic() + timeout -+ -+ live_port_pattern = re.compile(fr":{self.port:04X} 0[^6] ") -+ -+ while time.monotonic() < end: -+ data = cmd("cat /proc/net/tcp*", host=self.env.remote).stdout -+ if not live_port_pattern.search(data): -+ return -+ time.sleep(sleep) -+ raise Exception(f"Waiting for client to stop timed out after {timeout}s") -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/drivers/net/netdevsim/peer.sh BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/drivers/net/netdevsim/peer.sh ---- BPI-Router-Linux-kernel/tools/testing/selftests/drivers/net/netdevsim/peer.sh 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/drivers/net/netdevsim/peer.sh 2025-10-22 13:53:56.871167425 -0400 -@@ -1,7 +1,8 @@ - #!/bin/bash - # SPDX-License-Identifier: GPL-2.0-only - --source ../../../net/lib.sh -+lib_dir=$(dirname $0)/../../../net -+source $lib_dir/lib.sh - - NSIM_DEV_1_ID=$((256 + RANDOM % 256)) - NSIM_DEV_1_SYS=/sys/bus/netdevsim/devices/netdevsim$NSIM_DEV_1_ID -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/filesystems/mount-notify/mount-notify_test.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/filesystems/mount-notify/mount-notify_test.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/filesystems/mount-notify/mount-notify_test.c 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/filesystems/mount-notify/mount-notify_test.c 2025-10-22 13:53:56.871167425 -0400 -@@ -2,6 +2,13 @@ - // Copyright (c) 2025 Miklos Szeredi - - #define _GNU_SOURCE -+ -+// Needed for linux/fanotify.h -+typedef struct { -+ int val[2]; -+} __kernel_fsid_t; -+#define __kernel_fsid_t __kernel_fsid_t -+ - #include - #include - #include -@@ -10,20 +17,12 @@ - #include - #include - #include -+#include - - #include "../../kselftest_harness.h" - #include "../statmount/statmount.h" - #include "../utils.h" - --// Needed for linux/fanotify.h --#ifndef __kernel_fsid_t --typedef struct { -- int val[2]; --} __kernel_fsid_t; --#endif -- --#include -- - static const char root_mntpoint_templ[] = "/tmp/mount-notify_test_root.XXXXXX"; - - static const int mark_cmds[] = { -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/filesystems/mount-notify/mount-notify_test_ns.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/filesystems/mount-notify/mount-notify_test_ns.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/filesystems/mount-notify/mount-notify_test_ns.c 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/filesystems/mount-notify/mount-notify_test_ns.c 2025-10-22 13:53:56.871167425 -0400 -@@ -2,6 +2,13 @@ - // Copyright (c) 2025 Miklos Szeredi - - #define _GNU_SOURCE -+ -+// Needed for linux/fanotify.h -+typedef struct { -+ int val[2]; -+} __kernel_fsid_t; -+#define __kernel_fsid_t __kernel_fsid_t -+ - #include - #include - #include -@@ -10,21 +17,12 @@ - #include - #include - #include -+#include - - #include "../../kselftest_harness.h" --#include "../../pidfd/pidfd.h" - #include "../statmount/statmount.h" - #include "../utils.h" - --// Needed for linux/fanotify.h --#ifndef __kernel_fsid_t --typedef struct { -- int val[2]; --} __kernel_fsid_t; --#endif -- --#include -- - static const char root_mntpoint_templ[] = "/tmp/mount-notify_test_root.XXXXXX"; - - static const int mark_types[] = { -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc ---- BPI-Router-Linux-kernel/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc 2025-10-22 13:53:56.871167425 -0400 -@@ -14,11 +14,35 @@ fail() { #msg - exit_fail - } - -+# As reading trace can last forever, simply look for 3 different -+# events then exit out of reading the file. If there's not 3 different -+# events, then the test has failed. -+check_unique() { -+ cat trace | grep -v '^#' | awk ' -+ BEGIN { cnt = 0; } -+ { -+ for (i = 0; i < cnt; i++) { -+ if (event[i] == $5) { -+ break; -+ } -+ } -+ if (i == cnt) { -+ event[cnt++] = $5; -+ if (cnt > 2) { -+ exit; -+ } -+ } -+ } -+ END { -+ printf "%d", cnt; -+ }' -+} -+ - echo 'sched:*' > set_event - - yield - --count=`head -n 100 trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l` -+count=`check_unique` - if [ $count -lt 3 ]; then - fail "at least fork, exec and exit events should be recorded" - fi -@@ -29,7 +53,7 @@ echo 1 > events/sched/enable - - yield - --count=`head -n 100 trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l` -+count=`check_unique` - if [ $count -lt 3 ]; then - fail "at least fork, exec and exit events should be recorded" - fi -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-glob.tc BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-glob.tc ---- BPI-Router-Linux-kernel/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-glob.tc 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-glob.tc 2025-10-22 13:53:56.871167425 -0400 -@@ -29,7 +29,7 @@ ftrace_filter_check 'schedule*' '^schedu - ftrace_filter_check '*pin*lock' '.*pin.*lock$' - - # filter by start*mid* --ftrace_filter_check 'mutex*try*' '^mutex.*try.*' -+ftrace_filter_check 'mutex*unl*' '^mutex.*unl.*' - - # Advanced full-glob matching feature is recently supported. - # Skip the tests if we are sure the kernel does not support it. -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/futex/functional/futex_numa_mpol.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/futex/functional/futex_numa_mpol.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/futex/functional/futex_numa_mpol.c 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/futex/functional/futex_numa_mpol.c 2025-10-22 13:53:56.871167425 -0400 -@@ -144,7 +144,7 @@ int main(int argc, char *argv[]) - struct futex32_numa *futex_numa; - int mem_size, i; - void *futex_ptr; -- char c; -+ int c; - - while ((c = getopt(argc, argv, "chv:")) != -1) { - switch (c) { -@@ -210,6 +210,10 @@ int main(int argc, char *argv[]) - ret = mbind(futex_ptr, mem_size, MPOL_BIND, &nodemask, - sizeof(nodemask) * 8, 0); - if (ret == 0) { -+ ret = numa_set_mempolicy_home_node(futex_ptr, mem_size, i, 0); -+ if (ret != 0) -+ ksft_exit_fail_msg("Failed to set home node: %m, %d\n", errno); -+ - ksft_print_msg("Node %d test\n", i); - futex_numa->futex = 0; - futex_numa->numa = FUTEX_NO_NODE; -@@ -220,8 +224,8 @@ int main(int argc, char *argv[]) - if (0) - test_futex_mpol(futex_numa, 0); - if (futex_numa->numa != i) { -- ksft_test_result_fail("Returned NUMA node is %d expected %d\n", -- futex_numa->numa, i); -+ ksft_exit_fail_msg("Returned NUMA node is %d expected %d\n", -+ futex_numa->numa, i); - } - } - } -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/futex/functional/futex_priv_hash.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/futex/functional/futex_priv_hash.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/futex/functional/futex_priv_hash.c 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/futex/functional/futex_priv_hash.c 2025-10-22 13:53:56.871167425 -0400 -@@ -130,7 +130,7 @@ int main(int argc, char *argv[]) - pthread_mutexattr_t mutex_attr_pi; - int use_global_hash = 0; - int ret; -- char c; -+ int c; - - while ((c = getopt(argc, argv, "cghv:")) != -1) { - switch (c) { -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/futex/functional/.gitignore BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/futex/functional/.gitignore ---- BPI-Router-Linux-kernel/tools/testing/selftests/futex/functional/.gitignore 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/futex/functional/.gitignore 2025-10-22 13:53:56.871167425 -0400 -@@ -11,3 +11,4 @@ futex_wait_timeout - futex_wait_uninitialized_heap - futex_wait_wouldblock - futex_waitv -+futex_numa -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/futex/include/futex2test.h BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/futex/include/futex2test.h ---- BPI-Router-Linux-kernel/tools/testing/selftests/futex/include/futex2test.h 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/futex/include/futex2test.h 2025-10-22 13:53:56.871167425 -0400 -@@ -4,6 +4,7 @@ - * - * Copyright 2021 Collabora Ltd. - */ -+#include - #include - - #define u64_to_ptr(x) ((void *)(uintptr_t)(x)) -@@ -65,7 +66,12 @@ struct futex32_numa { - static inline int futex_waitv(volatile struct futex_waitv *waiters, unsigned long nr_waiters, - unsigned long flags, struct timespec *timo, clockid_t clockid) - { -- return syscall(__NR_futex_waitv, waiters, nr_waiters, flags, timo, clockid); -+ struct __kernel_timespec ts = { -+ .tv_sec = timo->tv_sec, -+ .tv_nsec = timo->tv_nsec, -+ }; -+ -+ return syscall(__NR_futex_waitv, waiters, nr_waiters, flags, &ts, clockid); - } - - /* -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/futex/include/futextest.h BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/futex/include/futextest.h ---- BPI-Router-Linux-kernel/tools/testing/selftests/futex/include/futextest.h 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/futex/include/futextest.h 2025-10-22 13:53:56.871167425 -0400 -@@ -47,6 +47,17 @@ typedef volatile u_int32_t futex_t; - FUTEX_PRIVATE_FLAG) - #endif - -+/* -+ * SYS_futex is expected from system C library, in glibc some 32-bit -+ * architectures (e.g. RV32) are using 64-bit time_t, therefore it doesn't have -+ * SYS_futex defined but just SYS_futex_time64. Define SYS_futex as -+ * SYS_futex_time64 in this situation to ensure the compilation and the -+ * compatibility. -+ */ -+#if !defined(SYS_futex) && defined(SYS_futex_time64) -+#define SYS_futex SYS_futex_time64 -+#endif -+ - /** - * futex() - SYS_futex syscall wrapper - * @uaddr: address of first futex -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/hid/tests/test_mouse.py BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/hid/tests/test_mouse.py ---- BPI-Router-Linux-kernel/tools/testing/selftests/hid/tests/test_mouse.py 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/hid/tests/test_mouse.py 2025-10-22 13:53:56.871167425 -0400 -@@ -439,6 +439,68 @@ class BadResolutionMultiplierMouse(Resol - return 32 # EPIPE - - -+class BadReportDescriptorMouse(BaseMouse): -+ """ -+ This "device" was one autogenerated by syzbot. There are a lot of issues in -+ it, and the most problematic is that it declares features that have no -+ size. -+ -+ This leads to report->size being set to 0 and can mess up with usbhid -+ internals. Fortunately, uhid merely passes the incoming buffer, without -+ touching it so a buffer of size 0 will be translated to [] without -+ triggering a kernel oops. -+ -+ Because the report descriptor is wrong, no input are created, and we need -+ to tweak a little bit the parameters to make it look correct. -+ """ -+ -+ # fmt: off -+ report_descriptor = [ -+ 0x96, 0x01, 0x00, # Report Count (1) 0 -+ 0x06, 0x01, 0x00, # Usage Page (Generic Desktop) 3 -+ # 0x03, 0x00, 0x00, 0x00, 0x00, # Ignored by the kernel somehow -+ 0x2a, 0x90, 0xa0, # Usage Maximum (41104) 6 -+ 0x27, 0x00, 0x00, 0x00, 0x00, # Logical Maximum (0) 9 -+ 0xb3, 0x81, 0x3e, 0x25, 0x03, # Feature (Cnst,Arr,Abs,Vol) 14 -+ 0x1b, 0xdd, 0xe8, 0x40, 0x50, # Usage Minimum (1346431197) 19 -+ 0x3b, 0x5d, 0x8c, 0x3d, 0xda, # Designator Index 24 -+ ] -+ # fmt: on -+ -+ def __init__( -+ self, rdesc=report_descriptor, name=None, input_info=(3, 0x045E, 0x07DA) -+ ): -+ super().__init__(rdesc, name, input_info) -+ self.high_resolution_report_called = False -+ -+ def get_evdev(self, application=None): -+ assert self._input_nodes is None -+ return ( -+ "Ok" # should be a list or None, but both would fail, so abusing the system -+ ) -+ -+ def next_sync_events(self, application=None): -+ # there are no evdev nodes, so no events -+ return [] -+ -+ def is_ready(self): -+ # we wait for the SET_REPORT command to come -+ return self.high_resolution_report_called -+ -+ def set_report(self, req, rnum, rtype, data): -+ if rtype != self.UHID_FEATURE_REPORT: -+ raise InvalidHIDCommunication(f"Unexpected report type: {rtype}") -+ if rnum != 0x0: -+ raise InvalidHIDCommunication(f"Unexpected report number: {rnum}") -+ -+ if len(data) != 1: -+ raise InvalidHIDCommunication(f"Unexpected data: {data}, expected '[0]'") -+ -+ self.high_resolution_report_called = True -+ -+ return 0 -+ -+ - class ResolutionMultiplierHWheelMouse(TwoWheelMouse): - # fmt: off - report_descriptor = [ -@@ -975,3 +1037,11 @@ class TestMiMouse(TestWheelMouse): - # assert below print out the real error - pass - assert remaining == [] -+ -+ -+class TestBadReportDescriptorMouse(base.BaseTestCase.TestUhid): -+ def create_device(self): -+ return BadReportDescriptorMouse() -+ -+ def assertName(self, uhdev): -+ pass -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/iommu/iommufd.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/iommu/iommufd.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/iommu/iommufd.c 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/iommu/iommufd.c 2025-10-22 13:53:56.871167425 -0400 -@@ -54,6 +54,8 @@ static __attribute__((constructor)) void - - mfd_buffer = memfd_mmap(BUFFER_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, - &mfd); -+ assert(mfd_buffer != MAP_FAILED); -+ assert(mfd > 0); - } - - FIXTURE(iommufd) -@@ -1746,13 +1748,15 @@ TEST_F(iommufd_mock_domain, all_aligns) - unsigned int end; - uint8_t *buf; - int prot = PROT_READ | PROT_WRITE; -- int mfd; -+ int mfd = -1; - - if (variant->file) - buf = memfd_mmap(buf_size, prot, MAP_SHARED, &mfd); - else - buf = mmap(0, buf_size, prot, self->mmap_flags, -1, 0); - ASSERT_NE(MAP_FAILED, buf); -+ if (variant->file) -+ ASSERT_GT(mfd, 0); - check_refs(buf, buf_size, 0); - - /* -@@ -1798,13 +1802,15 @@ TEST_F(iommufd_mock_domain, all_aligns_c - unsigned int end; - uint8_t *buf; - int prot = PROT_READ | PROT_WRITE; -- int mfd; -+ int mfd = -1; - - if (variant->file) - buf = memfd_mmap(buf_size, prot, MAP_SHARED, &mfd); - else - buf = mmap(0, buf_size, prot, self->mmap_flags, -1, 0); - ASSERT_NE(MAP_FAILED, buf); -+ if (variant->file) -+ ASSERT_GT(mfd, 0); - check_refs(buf, buf_size, 0); - - /* -@@ -2008,6 +2014,7 @@ FIXTURE_VARIANT(iommufd_dirty_tracking) - - FIXTURE_SETUP(iommufd_dirty_tracking) - { -+ size_t mmap_buffer_size; - unsigned long size; - int mmap_flags; - void *vrc; -@@ -2022,22 +2029,33 @@ FIXTURE_SETUP(iommufd_dirty_tracking) - self->fd = open("/dev/iommu", O_RDWR); - ASSERT_NE(-1, self->fd); - -- rc = posix_memalign(&self->buffer, HUGEPAGE_SIZE, variant->buffer_size); -- if (rc || !self->buffer) { -- SKIP(return, "Skipping buffer_size=%lu due to errno=%d", -- variant->buffer_size, rc); -- } -- - mmap_flags = MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED; -+ mmap_buffer_size = variant->buffer_size; - if (variant->hugepages) { - /* - * MAP_POPULATE will cause the kernel to fail mmap if THPs are - * not available. - */ - mmap_flags |= MAP_HUGETLB | MAP_POPULATE; -+ -+ /* -+ * Allocation must be aligned to the HUGEPAGE_SIZE, because the -+ * following mmap() will automatically align the length to be a -+ * multiple of the underlying huge page size. Failing to do the -+ * same at this allocation will result in a memory overwrite by -+ * the mmap(). -+ */ -+ if (mmap_buffer_size < HUGEPAGE_SIZE) -+ mmap_buffer_size = HUGEPAGE_SIZE; -+ } -+ -+ rc = posix_memalign(&self->buffer, HUGEPAGE_SIZE, mmap_buffer_size); -+ if (rc || !self->buffer) { -+ SKIP(return, "Skipping buffer_size=%lu due to errno=%d", -+ mmap_buffer_size, rc); - } - assert((uintptr_t)self->buffer % HUGEPAGE_SIZE == 0); -- vrc = mmap(self->buffer, variant->buffer_size, PROT_READ | PROT_WRITE, -+ vrc = mmap(self->buffer, mmap_buffer_size, PROT_READ | PROT_WRITE, - mmap_flags, -1, 0); - assert(vrc == self->buffer); - -@@ -2066,8 +2084,8 @@ FIXTURE_SETUP(iommufd_dirty_tracking) - - FIXTURE_TEARDOWN(iommufd_dirty_tracking) - { -- munmap(self->buffer, variant->buffer_size); -- munmap(self->bitmap, DIV_ROUND_UP(self->bitmap_size, BITS_PER_BYTE)); -+ free(self->buffer); -+ free(self->bitmap); - teardown_iommufd(self->fd, _metadata); - } - -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/iommu/iommufd_utils.h BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/iommu/iommufd_utils.h ---- BPI-Router-Linux-kernel/tools/testing/selftests/iommu/iommufd_utils.h 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/iommu/iommufd_utils.h 2025-10-22 13:53:56.871167425 -0400 -@@ -60,13 +60,18 @@ static inline void *memfd_mmap(size_t le - { - int mfd_flags = (flags & MAP_HUGETLB) ? MFD_HUGETLB : 0; - int mfd = memfd_create("buffer", mfd_flags); -+ void *buf = MAP_FAILED; - - if (mfd <= 0) - return MAP_FAILED; - if (ftruncate(mfd, length)) -- return MAP_FAILED; -+ goto out; - *mfd_p = mfd; -- return mmap(0, length, prot, flags, mfd, 0); -+ buf = mmap(0, length, prot, flags, mfd, 0); -+out: -+ if (buf == MAP_FAILED) -+ close(mfd); -+ return buf; - } - - /* -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/kexec/Makefile BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/kexec/Makefile ---- BPI-Router-Linux-kernel/tools/testing/selftests/kexec/Makefile 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/kexec/Makefile 2025-10-22 13:53:56.871167425 -0400 -@@ -12,7 +12,7 @@ include ../../../scripts/Makefile.arch - - ifeq ($(IS_64_BIT)$(ARCH_PROCESSED),1x86) - TEST_PROGS += test_kexec_jump.sh --test_kexec_jump.sh: $(OUTPUT)/test_kexec_jump -+TEST_GEN_PROGS := test_kexec_jump - endif - - include ../lib.mk -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c 2025-10-22 13:53:56.871167425 -0400 -@@ -22,7 +22,8 @@ - #include "gic.h" - #include "vgic.h" - --static const uint64_t CVAL_MAX = ~0ULL; -+/* Depends on counter width. */ -+static uint64_t CVAL_MAX; - /* tval is a signed 32-bit int. */ - static const int32_t TVAL_MAX = INT32_MAX; - static const int32_t TVAL_MIN = INT32_MIN; -@@ -30,8 +31,8 @@ static const int32_t TVAL_MIN = INT32_MI - /* After how much time we say there is no IRQ. */ - static const uint32_t TIMEOUT_NO_IRQ_US = 50000; - --/* A nice counter value to use as the starting one for most tests. */ --static const uint64_t DEF_CNT = (CVAL_MAX / 2); -+/* Counter value to use as the starting one for most tests. Set to CVAL_MAX/2 */ -+static uint64_t DEF_CNT; - - /* Number of runs. */ - static const uint32_t NR_TEST_ITERS_DEF = 5; -@@ -191,8 +192,8 @@ static void set_tval_irq(enum arch_timer - { - atomic_set(&shared_data.handled, 0); - atomic_set(&shared_data.spurious, 0); -- timer_set_ctl(timer, ctl); - timer_set_tval(timer, tval_cycles); -+ timer_set_ctl(timer, ctl); - } - - static void set_xval_irq(enum arch_timer timer, uint64_t xval, uint32_t ctl, -@@ -732,12 +733,6 @@ static void test_move_counters_ahead_of_ - test_set_cnt_after_tval(timer, 0, tval, (uint64_t) tval + 1, - wm); - } -- -- for (i = 0; i < ARRAY_SIZE(sleep_method); i++) { -- sleep_method_t sm = sleep_method[i]; -- -- test_set_cnt_after_cval_no_irq(timer, 0, DEF_CNT, CVAL_MAX, sm); -- } - } - - /* -@@ -849,17 +844,17 @@ static void guest_code(enum arch_timer t - GUEST_DONE(); - } - -+static cpu_set_t default_cpuset; -+ - static uint32_t next_pcpu(void) - { - uint32_t max = get_nprocs(); - uint32_t cur = sched_getcpu(); - uint32_t next = cur; -- cpu_set_t cpuset; -+ cpu_set_t cpuset = default_cpuset; - - TEST_ASSERT(max > 1, "Need at least two physical cpus"); - -- sched_getaffinity(0, sizeof(cpuset), &cpuset); -- - do { - next = (next + 1) % CPU_SETSIZE; - } while (!CPU_ISSET(next, &cpuset)); -@@ -959,6 +954,8 @@ static void test_init_timer_irq(struct k - pr_debug("ptimer_irq: %d; vtimer_irq: %d\n", ptimer_irq, vtimer_irq); - } - -+static int gic_fd; -+ - static void test_vm_create(struct kvm_vm **vm, struct kvm_vcpu **vcpu, - enum arch_timer timer) - { -@@ -973,8 +970,18 @@ static void test_vm_create(struct kvm_vm - vcpu_args_set(*vcpu, 1, timer); - - test_init_timer_irq(*vm, *vcpu); -- vgic_v3_setup(*vm, 1, 64); -+ gic_fd = vgic_v3_setup(*vm, 1, 64); -+ __TEST_REQUIRE(gic_fd >= 0, "Failed to create vgic-v3"); -+ - sync_global_to_guest(*vm, test_args); -+ sync_global_to_guest(*vm, CVAL_MAX); -+ sync_global_to_guest(*vm, DEF_CNT); -+} -+ -+static void test_vm_cleanup(struct kvm_vm *vm) -+{ -+ close(gic_fd); -+ kvm_vm_free(vm); - } - - static void test_print_help(char *name) -@@ -986,7 +993,7 @@ static void test_print_help(char *name) - pr_info("\t-b: Test both physical and virtual timers (default: true)\n"); - pr_info("\t-l: Delta (in ms) used for long wait time test (default: %u)\n", - LONG_WAIT_TEST_MS); -- pr_info("\t-l: Delta (in ms) used for wait times (default: %u)\n", -+ pr_info("\t-w: Delta (in ms) used for wait times (default: %u)\n", - WAIT_TEST_MS); - pr_info("\t-p: Test physical timer (default: true)\n"); - pr_info("\t-v: Test virtual timer (default: true)\n"); -@@ -1035,6 +1042,17 @@ static bool parse_args(int argc, char *a - return false; - } - -+static void set_counter_defaults(void) -+{ -+ const uint64_t MIN_ROLLOVER_SECS = 40ULL * 365 * 24 * 3600; -+ uint64_t freq = read_sysreg(CNTFRQ_EL0); -+ uint64_t width = ilog2(MIN_ROLLOVER_SECS * freq); -+ -+ width = clamp(width, 56, 64); -+ CVAL_MAX = GENMASK_ULL(width - 1, 0); -+ DEF_CNT = CVAL_MAX / 2; -+} -+ - int main(int argc, char *argv[]) - { - struct kvm_vcpu *vcpu; -@@ -1046,16 +1064,19 @@ int main(int argc, char *argv[]) - if (!parse_args(argc, argv)) - exit(KSFT_SKIP); - -+ sched_getaffinity(0, sizeof(default_cpuset), &default_cpuset); -+ set_counter_defaults(); -+ - if (test_args.test_virtual) { - test_vm_create(&vm, &vcpu, VIRTUAL); - test_run(vm, vcpu); -- kvm_vm_free(vm); -+ test_vm_cleanup(vm); - } - - if (test_args.test_physical) { - test_vm_create(&vm, &vcpu, PHYSICAL); - test_run(vm, vcpu); -- kvm_vm_free(vm); -+ test_vm_cleanup(vm); - } - - return 0; -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/kvm/x86/monitor_mwait_test.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/kvm/x86/monitor_mwait_test.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/kvm/x86/monitor_mwait_test.c 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/kvm/x86/monitor_mwait_test.c 2025-10-22 13:53:56.871167425 -0400 -@@ -74,6 +74,7 @@ int main(int argc, char *argv[]) - int testcase; - char test[80]; - -+ TEST_REQUIRE(this_cpu_has(X86_FEATURE_MWAIT)); - TEST_REQUIRE(kvm_has_cap(KVM_CAP_DISABLE_QUIRKS2)); - - ksft_print_header(); -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/landlock/audit.h BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/landlock/audit.h ---- BPI-Router-Linux-kernel/tools/testing/selftests/landlock/audit.h 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/landlock/audit.h 2025-10-22 13:53:56.871167425 -0400 -@@ -403,11 +403,12 @@ static int audit_init_filter_exe(struct - /* It is assume that there is not already filtering rules. */ - filter->record_type = AUDIT_EXE; - if (!path) { -- filter->exe_len = readlink("/proc/self/exe", filter->exe, -- sizeof(filter->exe) - 1); -- if (filter->exe_len < 0) -+ int ret = readlink("/proc/self/exe", filter->exe, -+ sizeof(filter->exe) - 1); -+ if (ret < 0) - return -errno; - -+ filter->exe_len = ret; - return 0; - } - -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/landlock/audit_test.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/landlock/audit_test.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/landlock/audit_test.c 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/landlock/audit_test.c 2025-10-22 13:53:56.871167425 -0400 -@@ -7,6 +7,7 @@ - - #define _GNU_SOURCE - #include -+#include - #include - #include - #include -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/mm/config BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/mm/config ---- BPI-Router-Linux-kernel/tools/testing/selftests/mm/config 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/mm/config 2025-10-22 13:53:56.871167425 -0400 -@@ -8,3 +8,6 @@ CONFIG_GUP_TEST=y - CONFIG_TRANSPARENT_HUGEPAGE=y - CONFIG_MEM_SOFT_DIRTY=y - CONFIG_ANON_VMA_NAME=y -+CONFIG_FTRACE=y -+CONFIG_PROFILING=y -+CONFIG_UPROBES=y -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/mm/gup_longterm.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/mm/gup_longterm.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/mm/gup_longterm.c 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/mm/gup_longterm.c 2025-10-22 13:53:56.871167425 -0400 -@@ -298,8 +298,11 @@ static void run_with_memfd(test_fn fn, c - log_test_start("%s ... with memfd", desc); - - fd = memfd_create("test", 0); -- if (fd < 0) -+ if (fd < 0) { - ksft_print_msg("memfd_create() failed (%s)\n", strerror(errno)); -+ log_test_result(KSFT_SKIP); -+ return; -+ } - - fn(fd, pagesize); - close(fd); -@@ -366,6 +369,8 @@ static void run_with_memfd_hugetlb(test_ - fd = memfd_create("test", flags); - if (fd < 0) { - ksft_print_msg("memfd_create() failed (%s)\n", strerror(errno)); -+ log_test_result(KSFT_SKIP); -+ return; - } - - fn(fd, hugetlbsize); -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/mm/merge.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/mm/merge.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/mm/merge.c 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/mm/merge.c 2025-10-22 13:53:56.871167425 -0400 -@@ -470,7 +470,9 @@ TEST_F(merge, handle_uprobe_upon_merged_ - ASSERT_GE(fd, 0); - - ASSERT_EQ(ftruncate(fd, page_size), 0); -- ASSERT_EQ(read_sysfs("/sys/bus/event_source/devices/uprobe/type", &type), 0); -+ if (read_sysfs("/sys/bus/event_source/devices/uprobe/type", &type) != 0) { -+ SKIP(goto out, "Failed to read uprobe sysfs file, skipping"); -+ } - - memset(&attr, 0, attr_sz); - attr.size = attr_sz; -@@ -491,6 +493,7 @@ TEST_F(merge, handle_uprobe_upon_merged_ - ASSERT_NE(mremap(ptr2, page_size, page_size, - MREMAP_MAYMOVE | MREMAP_FIXED, ptr1), MAP_FAILED); - -+out: - close(fd); - remove(probe_file); - } -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/mm/settings BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/mm/settings ---- BPI-Router-Linux-kernel/tools/testing/selftests/mm/settings 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/mm/settings 2025-10-22 13:53:56.871167425 -0400 -@@ -1 +1 @@ --timeout=180 -+timeout=900 -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/mm/split_huge_page_test.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/mm/split_huge_page_test.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/mm/split_huge_page_test.c 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/mm/split_huge_page_test.c 2025-10-22 13:53:56.871167425 -0400 -@@ -31,6 +31,7 @@ uint64_t pmd_pagesize; - #define INPUT_MAX 80 - - #define PID_FMT "%d,0x%lx,0x%lx,%d" -+#define PID_FMT_OFFSET "%d,0x%lx,0x%lx,%d,%d" - #define PATH_FMT "%s,0x%lx,0x%lx,%d" - - #define PFN_MASK ((1UL<<55)-1) -@@ -483,7 +484,7 @@ void split_thp_in_pagecache_to_order_at( - write_debugfs(PID_FMT, getpid(), (uint64_t)addr, - (uint64_t)addr + fd_size, order); - else -- write_debugfs(PID_FMT, getpid(), (uint64_t)addr, -+ write_debugfs(PID_FMT_OFFSET, getpid(), (uint64_t)addr, - (uint64_t)addr + fd_size, order, offset); - - for (i = 0; i < fd_size; i++) -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/mm/virtual_address_range.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/mm/virtual_address_range.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/mm/virtual_address_range.c 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/mm/virtual_address_range.c 2025-10-22 13:53:56.871167425 -0400 -@@ -77,8 +77,11 @@ static void validate_addr(char *ptr, int - { - unsigned long addr = (unsigned long) ptr; - -- if (high_addr && addr < HIGH_ADDR_MARK) -- ksft_exit_fail_msg("Bad address %lx\n", addr); -+ if (high_addr) { -+ if (addr < HIGH_ADDR_MARK) -+ ksft_exit_fail_msg("Bad address %lx\n", addr); -+ return; -+ } - - if (addr > HIGH_ADDR_MARK) - ksft_exit_fail_msg("Bad address %lx\n", addr); -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/af_unix/msg_oob.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/af_unix/msg_oob.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/af_unix/msg_oob.c 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/af_unix/msg_oob.c 2025-10-22 13:53:56.871167425 -0400 -@@ -210,7 +210,7 @@ static void __sendpair(struct __test_met - static void __recvpair(struct __test_metadata *_metadata, - FIXTURE_DATA(msg_oob) *self, - const char *expected_buf, int expected_len, -- int buf_len, int flags) -+ int buf_len, int flags, bool is_sender) - { - int i, ret[2], recv_errno[2], expected_errno = 0; - char recv_buf[2][BUF_SZ] = {}; -@@ -221,7 +221,9 @@ static void __recvpair(struct __test_met - errno = 0; - - for (i = 0; i < 2; i++) { -- ret[i] = recv(self->fd[i * 2 + 1], recv_buf[i], buf_len, flags); -+ int index = is_sender ? i * 2 : i * 2 + 1; -+ -+ ret[i] = recv(self->fd[index], recv_buf[i], buf_len, flags); - recv_errno[i] = errno; - } - -@@ -308,6 +310,20 @@ static void __siocatmarkpair(struct __te - ASSERT_EQ(answ[0], answ[1]); - } - -+static void __resetpair(struct __test_metadata *_metadata, -+ FIXTURE_DATA(msg_oob) *self, -+ const FIXTURE_VARIANT(msg_oob) *variant, -+ bool reset) -+{ -+ int i; -+ -+ for (i = 0; i < 2; i++) -+ close(self->fd[i * 2 + 1]); -+ -+ __recvpair(_metadata, self, "", reset ? -ECONNRESET : 0, 1, -+ variant->peek ? MSG_PEEK : 0, true); -+} -+ - #define sendpair(buf, len, flags) \ - __sendpair(_metadata, self, buf, len, flags) - -@@ -316,9 +332,10 @@ static void __siocatmarkpair(struct __te - if (variant->peek) \ - __recvpair(_metadata, self, \ - expected_buf, expected_len, \ -- buf_len, (flags) | MSG_PEEK); \ -+ buf_len, (flags) | MSG_PEEK, false); \ - __recvpair(_metadata, self, \ -- expected_buf, expected_len, buf_len, flags); \ -+ expected_buf, expected_len, \ -+ buf_len, flags, false); \ - } while (0) - - #define epollpair(oob_remaining) \ -@@ -330,6 +347,9 @@ static void __siocatmarkpair(struct __te - #define setinlinepair() \ - __setinlinepair(_metadata, self) - -+#define resetpair(reset) \ -+ __resetpair(_metadata, self, variant, reset) -+ - #define tcp_incompliant \ - for (self->tcp_compliant = false; \ - self->tcp_compliant == false; \ -@@ -344,6 +364,21 @@ TEST_F(msg_oob, non_oob) - recvpair("", -EINVAL, 1, MSG_OOB); - epollpair(false); - siocatmarkpair(false); -+ -+ resetpair(true); -+} -+ -+TEST_F(msg_oob, non_oob_no_reset) -+{ -+ sendpair("x", 1, 0); -+ epollpair(false); -+ siocatmarkpair(false); -+ -+ recvpair("x", 1, 1, 0); -+ epollpair(false); -+ siocatmarkpair(false); -+ -+ resetpair(false); - } - - TEST_F(msg_oob, oob) -@@ -355,6 +390,19 @@ TEST_F(msg_oob, oob) - recvpair("x", 1, 1, MSG_OOB); - epollpair(false); - siocatmarkpair(true); -+ -+ tcp_incompliant { -+ resetpair(false); /* TCP sets -ECONNRESET for ex-OOB. */ -+ } -+} -+ -+TEST_F(msg_oob, oob_reset) -+{ -+ sendpair("x", 1, MSG_OOB); -+ epollpair(true); -+ siocatmarkpair(true); -+ -+ resetpair(true); - } - - TEST_F(msg_oob, oob_drop) -@@ -370,6 +418,8 @@ TEST_F(msg_oob, oob_drop) - recvpair("", -EINVAL, 1, MSG_OOB); - epollpair(false); - siocatmarkpair(false); -+ -+ resetpair(false); - } - - TEST_F(msg_oob, oob_ahead) -@@ -385,6 +435,10 @@ TEST_F(msg_oob, oob_ahead) - recvpair("hell", 4, 4, 0); - epollpair(false); - siocatmarkpair(true); -+ -+ tcp_incompliant { -+ resetpair(false); /* TCP sets -ECONNRESET for ex-OOB. */ -+ } - } - - TEST_F(msg_oob, oob_break) -@@ -403,6 +457,8 @@ TEST_F(msg_oob, oob_break) - - recvpair("", -EAGAIN, 1, 0); - siocatmarkpair(false); -+ -+ resetpair(false); - } - - TEST_F(msg_oob, oob_ahead_break) -@@ -426,6 +482,8 @@ TEST_F(msg_oob, oob_ahead_break) - recvpair("world", 5, 5, 0); - epollpair(false); - siocatmarkpair(false); -+ -+ resetpair(false); - } - - TEST_F(msg_oob, oob_break_drop) -@@ -449,6 +507,8 @@ TEST_F(msg_oob, oob_break_drop) - recvpair("", -EINVAL, 1, MSG_OOB); - epollpair(false); - siocatmarkpair(false); -+ -+ resetpair(false); - } - - TEST_F(msg_oob, ex_oob_break) -@@ -476,6 +536,8 @@ TEST_F(msg_oob, ex_oob_break) - recvpair("ld", 2, 2, 0); - epollpair(false); - siocatmarkpair(false); -+ -+ resetpair(false); - } - - TEST_F(msg_oob, ex_oob_drop) -@@ -498,6 +560,8 @@ TEST_F(msg_oob, ex_oob_drop) - epollpair(false); - siocatmarkpair(true); - } -+ -+ resetpair(false); - } - - TEST_F(msg_oob, ex_oob_drop_2) -@@ -523,6 +587,8 @@ TEST_F(msg_oob, ex_oob_drop_2) - epollpair(false); - siocatmarkpair(true); - } -+ -+ resetpair(false); - } - - TEST_F(msg_oob, ex_oob_oob) -@@ -546,6 +612,54 @@ TEST_F(msg_oob, ex_oob_oob) - recvpair("", -EINVAL, 1, MSG_OOB); - epollpair(false); - siocatmarkpair(false); -+ -+ resetpair(false); -+} -+ -+TEST_F(msg_oob, ex_oob_ex_oob) -+{ -+ sendpair("x", 1, MSG_OOB); -+ epollpair(true); -+ siocatmarkpair(true); -+ -+ recvpair("x", 1, 1, MSG_OOB); -+ epollpair(false); -+ siocatmarkpair(true); -+ -+ sendpair("y", 1, MSG_OOB); -+ epollpair(true); -+ siocatmarkpair(true); -+ -+ recvpair("y", 1, 1, MSG_OOB); -+ epollpair(false); -+ siocatmarkpair(true); -+ -+ tcp_incompliant { -+ resetpair(false); /* TCP sets -ECONNRESET for ex-OOB. */ -+ } -+} -+ -+TEST_F(msg_oob, ex_oob_ex_oob_oob) -+{ -+ sendpair("x", 1, MSG_OOB); -+ epollpair(true); -+ siocatmarkpair(true); -+ -+ recvpair("x", 1, 1, MSG_OOB); -+ epollpair(false); -+ siocatmarkpair(true); -+ -+ sendpair("y", 1, MSG_OOB); -+ epollpair(true); -+ siocatmarkpair(true); -+ -+ recvpair("y", 1, 1, MSG_OOB); -+ epollpair(false); -+ siocatmarkpair(true); -+ -+ sendpair("z", 1, MSG_OOB); -+ epollpair(true); -+ siocatmarkpair(true); - } - - TEST_F(msg_oob, ex_oob_ahead_break) -@@ -576,6 +690,10 @@ TEST_F(msg_oob, ex_oob_ahead_break) - recvpair("d", 1, 1, MSG_OOB); - epollpair(false); - siocatmarkpair(true); -+ -+ tcp_incompliant { -+ resetpair(false); /* TCP sets -ECONNRESET for ex-OOB. */ -+ } - } - - TEST_F(msg_oob, ex_oob_siocatmark) -@@ -595,6 +713,8 @@ TEST_F(msg_oob, ex_oob_siocatmark) - recvpair("hell", 4, 4, 0); /* Intentionally stop at ex-OOB. */ - epollpair(true); - siocatmarkpair(false); -+ -+ resetpair(true); - } - - TEST_F(msg_oob, inline_oob) -@@ -612,6 +732,8 @@ TEST_F(msg_oob, inline_oob) - recvpair("x", 1, 1, 0); - epollpair(false); - siocatmarkpair(false); -+ -+ resetpair(false); - } - - TEST_F(msg_oob, inline_oob_break) -@@ -633,6 +755,8 @@ TEST_F(msg_oob, inline_oob_break) - recvpair("o", 1, 1, 0); - epollpair(false); - siocatmarkpair(false); -+ -+ resetpair(false); - } - - TEST_F(msg_oob, inline_oob_ahead_break) -@@ -661,6 +785,8 @@ TEST_F(msg_oob, inline_oob_ahead_break) - - epollpair(false); - siocatmarkpair(false); -+ -+ resetpair(false); - } - - TEST_F(msg_oob, inline_ex_oob_break) -@@ -686,6 +812,8 @@ TEST_F(msg_oob, inline_ex_oob_break) - recvpair("rld", 3, 3, 0); - epollpair(false); - siocatmarkpair(false); -+ -+ resetpair(false); - } - - TEST_F(msg_oob, inline_ex_oob_no_drop) -@@ -707,6 +835,8 @@ TEST_F(msg_oob, inline_ex_oob_no_drop) - recvpair("y", 1, 1, 0); - epollpair(false); - siocatmarkpair(false); -+ -+ resetpair(false); - } - - TEST_F(msg_oob, inline_ex_oob_drop) -@@ -731,6 +861,8 @@ TEST_F(msg_oob, inline_ex_oob_drop) - epollpair(false); - siocatmarkpair(false); - } -+ -+ resetpair(false); - } - - TEST_F(msg_oob, inline_ex_oob_siocatmark) -@@ -752,6 +884,8 @@ TEST_F(msg_oob, inline_ex_oob_siocatmark - recvpair("hell", 4, 4, 0); /* Intentionally stop at ex-OOB. */ - epollpair(true); - siocatmarkpair(false); -+ -+ resetpair(true); - } - - TEST_HARNESS_MAIN -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/bind_bhash.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/bind_bhash.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/bind_bhash.c 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/bind_bhash.c 2025-10-22 13:53:56.871167425 -0400 -@@ -75,7 +75,7 @@ static void *setup(void *arg) - int *array = (int *)arg; - - for (i = 0; i < MAX_CONNECTIONS; i++) { -- sock_fd = bind_socket(SO_REUSEADDR | SO_REUSEPORT, setup_addr); -+ sock_fd = bind_socket(SO_REUSEPORT, setup_addr); - if (sock_fd < 0) { - ret = sock_fd; - pthread_exit(&ret); -@@ -103,7 +103,7 @@ int main(int argc, const char *argv[]) - - setup_addr = use_v6 ? setup_addr_v6 : setup_addr_v4; - -- listener_fd = bind_socket(SO_REUSEADDR | SO_REUSEPORT, setup_addr); -+ listener_fd = bind_socket(SO_REUSEPORT, setup_addr); - if (listen(listener_fd, 100) < 0) { - perror("listen failed"); - return -1; -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/can/config BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/can/config ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/can/config 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/can/config 2025-10-22 13:53:56.871167425 -0400 -@@ -0,0 +1,3 @@ -+CONFIG_CAN=m -+CONFIG_CAN_DEV=m -+CONFIG_CAN_VCAN=m -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/fib_nexthops.sh BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/fib_nexthops.sh ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/fib_nexthops.sh 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/fib_nexthops.sh 2025-10-22 13:53:56.871167425 -0400 -@@ -467,8 +467,8 @@ ipv6_fdb_grp_fcnal() - log_test $? 0 "Get Fdb nexthop group by id" - - # fdb nexthop group can only contain fdb nexthops -- run_cmd "$IP nexthop add id 63 via 2001:db8:91::4" -- run_cmd "$IP nexthop add id 64 via 2001:db8:91::5" -+ run_cmd "$IP nexthop add id 63 via 2001:db8:91::4 dev veth1" -+ run_cmd "$IP nexthop add id 64 via 2001:db8:91::5 dev veth1" - run_cmd "$IP nexthop add id 103 group 63/64 fdb" - log_test $? 2 "Fdb Nexthop group with non-fdb nexthops" - -@@ -547,15 +547,15 @@ ipv4_fdb_grp_fcnal() - log_test $? 0 "Get Fdb nexthop group by id" - - # fdb nexthop group can only contain fdb nexthops -- run_cmd "$IP nexthop add id 14 via 172.16.1.2" -- run_cmd "$IP nexthop add id 15 via 172.16.1.3" -+ run_cmd "$IP nexthop add id 14 via 172.16.1.2 dev veth1" -+ run_cmd "$IP nexthop add id 15 via 172.16.1.3 dev veth1" - run_cmd "$IP nexthop add id 103 group 14/15 fdb" - log_test $? 2 "Fdb Nexthop group with non-fdb nexthops" - - # Non fdb nexthop group can not contain fdb nexthops - run_cmd "$IP nexthop add id 16 via 172.16.1.2 fdb" - run_cmd "$IP nexthop add id 17 via 172.16.1.3 fdb" -- run_cmd "$IP nexthop add id 104 group 14/15" -+ run_cmd "$IP nexthop add id 104 group 16/17" - log_test $? 2 "Non-Fdb Nexthop group with fdb nexthops" - - # fdb nexthop cannot have blackhole -@@ -582,7 +582,7 @@ ipv4_fdb_grp_fcnal() - run_cmd "$BRIDGE fdb add 02:02:00:00:00:14 dev vx10 nhid 12 self" - log_test $? 255 "Fdb mac add with nexthop" - -- run_cmd "$IP ro add 172.16.0.0/22 nhid 15" -+ run_cmd "$IP ro add 172.16.0.0/22 nhid 16" - log_test $? 2 "Route add with fdb nexthop" - - run_cmd "$IP ro add 172.16.0.0/22 nhid 103" -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/.gitignore BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/.gitignore ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/.gitignore 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/.gitignore 2025-10-22 13:53:56.871167425 -0400 -@@ -50,6 +50,7 @@ tap - tcp_fastopen_backup_key - tcp_inq - tcp_mmap -+tfo - timestamping - tls - toeplitz -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/gre_ipv6_lladdr.sh BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/gre_ipv6_lladdr.sh ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/gre_ipv6_lladdr.sh 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/gre_ipv6_lladdr.sh 2025-10-22 13:53:56.871167425 -0400 -@@ -24,7 +24,10 @@ setup_basenet() - ip -netns "${NS0}" address add dev lo 2001:db8::10/64 nodad - } - --# Check if network device has an IPv6 link-local address assigned. -+# Check the IPv6 configuration of a network device. -+# -+# We currently check the generation of the link-local IPv6 address and the -+# creation of the ff00::/8 multicast route. - # - # Parameters: - # -@@ -35,7 +38,7 @@ setup_basenet() - # a link-local address) - # * $4: The user visible name for the scenario being tested - # --check_ipv6_ll_addr() -+check_ipv6_device_config() - { - local DEV="$1" - local EXTRA_MATCH="$2" -@@ -45,7 +48,11 @@ check_ipv6_ll_addr() - RET=0 - set +e - ip -netns "${NS0}" -6 address show dev "${DEV}" scope link | grep "fe80::" | grep -q "${EXTRA_MATCH}" -- check_err_fail "${XRET}" $? "" -+ check_err_fail "${XRET}" $? "IPv6 link-local address generation" -+ -+ ip -netns "${NS0}" -6 route show table local type multicast ff00::/8 proto kernel | grep -q "${DEV}" -+ check_err_fail 0 $? "IPv6 multicast route creation" -+ - log_test "${MSG}" - set -e - } -@@ -102,20 +109,20 @@ test_gre_device() - ;; - esac - -- # Check that IPv6 link-local address is generated when device goes up -+ # Check the IPv6 device configuration when it goes up - ip netns exec "${NS0}" sysctl -qw net.ipv6.conf.gretest.addr_gen_mode="${ADDR_GEN_MODE}" - ip -netns "${NS0}" link set dev gretest up -- check_ipv6_ll_addr gretest "${MATCH_REGEXP}" "${XRET}" "config: ${MSG}" -+ check_ipv6_device_config gretest "${MATCH_REGEXP}" "${XRET}" "config: ${MSG}" - - # Now disable link-local address generation - ip -netns "${NS0}" link set dev gretest down - ip netns exec "${NS0}" sysctl -qw net.ipv6.conf.gretest.addr_gen_mode=1 - ip -netns "${NS0}" link set dev gretest up - -- # Check that link-local address generation works when re-enabled while -- # the device is already up -+ # Check the IPv6 device configuration when link-local address -+ # generation is re-enabled while the device is already up - ip netns exec "${NS0}" sysctl -qw net.ipv6.conf.gretest.addr_gen_mode="${ADDR_GEN_MODE}" -- check_ipv6_ll_addr gretest "${MATCH_REGEXP}" "${XRET}" "update: ${MSG}" -+ check_ipv6_device_config gretest "${MATCH_REGEXP}" "${XRET}" "update: ${MSG}" - - ip -netns "${NS0}" link del dev gretest - } -@@ -126,7 +133,7 @@ test_gre4() - local MODE - - for GRE_TYPE in "gre" "gretap"; do -- printf "\n####\nTesting IPv6 link-local address generation on ${GRE_TYPE} devices\n####\n\n" -+ printf "\n####\nTesting IPv6 configuration of ${GRE_TYPE} devices\n####\n\n" - - for MODE in "eui64" "none" "stable-privacy" "random"; do - test_gre_device "${GRE_TYPE}" 192.0.2.10 192.0.2.11 "${MODE}" -@@ -142,7 +149,7 @@ test_gre6() - local MODE - - for GRE_TYPE in "ip6gre" "ip6gretap"; do -- printf "\n####\nTesting IPv6 link-local address generation on ${GRE_TYPE} devices\n####\n\n" -+ printf "\n####\nTesting IPv6 configuration of ${GRE_TYPE} devices\n####\n\n" - - for MODE in "eui64" "none" "stable-privacy" "random"; do - test_gre_device "${GRE_TYPE}" 2001:db8::10 2001:db8::11 "${MODE}" -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/lib.sh BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/lib.sh ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/lib.sh 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/lib.sh 2025-10-22 13:53:56.871167425 -0400 -@@ -312,7 +312,7 @@ log_test_result() - local test_name=$1; shift - local opt_str=$1; shift - local result=$1; shift -- local retmsg=$1; shift -+ local retmsg=$1 - - printf "TEST: %-60s [%s]\n" "$test_name $opt_str" "$result" - if [[ $retmsg ]]; then -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/Makefile BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/Makefile ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/Makefile 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/Makefile 2025-10-22 13:53:56.871167425 -0400 -@@ -27,6 +27,7 @@ TEST_PROGS += amt.sh - TEST_PROGS += unicast_extensions.sh - TEST_PROGS += udpgro_fwd.sh - TEST_PROGS += udpgro_frglist.sh -+TEST_PROGS += nat6to4.sh - TEST_PROGS += veth.sh - TEST_PROGS += ioam6.sh - TEST_PROGS += gro.sh -@@ -109,6 +110,8 @@ TEST_GEN_PROGS += proc_net_pktgen - TEST_PROGS += lwt_dst_cache_ref_loop.sh - TEST_PROGS += skf_net_off.sh - TEST_GEN_FILES += skf_net_off -+TEST_GEN_FILES += tfo -+TEST_PROGS += tfo_passive.sh - - # YNL files, must be before "include ..lib.mk" - YNL_GEN_FILES := busy_poller netlink-dumps -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/mptcp/Makefile BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/mptcp/Makefile ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/mptcp/Makefile 2025-10-22 13:53:23.699326809 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/mptcp/Makefile 2025-10-22 13:53:56.875167405 -0400 -@@ -4,7 +4,8 @@ top_srcdir = ../../../../.. - - CFLAGS += -Wall -Wl,--no-as-needed -O2 -g -I$(top_srcdir)/usr/include $(KHDR_INCLUDES) - --TEST_PROGS := mptcp_connect.sh pm_netlink.sh mptcp_join.sh diag.sh \ -+TEST_PROGS := mptcp_connect.sh mptcp_connect_mmap.sh mptcp_connect_sendfile.sh \ -+ mptcp_connect_checksum.sh pm_netlink.sh mptcp_join.sh diag.sh \ - simult_flows.sh mptcp_sockopt.sh userspace_pm.sh - - TEST_GEN_FILES = mptcp_connect pm_nl_ctl mptcp_sockopt mptcp_inq mptcp_diag -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/mptcp/mptcp_connect.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/mptcp/mptcp_connect.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/mptcp/mptcp_connect.c 2025-10-22 13:53:23.703326789 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/mptcp/mptcp_connect.c 2025-10-22 13:53:56.875167405 -0400 -@@ -183,9 +183,10 @@ static void xgetaddrinfo(const char *nod - struct addrinfo *hints, - struct addrinfo **res) - { --again: -- int err = getaddrinfo(node, service, hints, res); -+ int err; - -+again: -+ err = getaddrinfo(node, service, hints, res); - if (err) { - const char *errstr; - -@@ -1092,6 +1093,7 @@ int main_loop_s(int listensock) - struct pollfd polls; - socklen_t salen; - int remotesock; -+ int err = 0; - int fd = 0; - - again: -@@ -1124,7 +1126,7 @@ again: - SOCK_TEST_TCPULP(remotesock, 0); - - memset(&winfo, 0, sizeof(winfo)); -- copyfd_io(fd, remotesock, 1, true, &winfo); -+ err = copyfd_io(fd, remotesock, 1, true, &winfo); - } else { - perror("accept"); - return 1; -@@ -1133,10 +1135,10 @@ again: - if (cfg_input) - close(fd); - -- if (--cfg_repeat > 0) -+ if (!err && --cfg_repeat > 0) - goto again; - -- return 0; -+ return err; - } - - static void init_rng(void) -@@ -1246,7 +1248,7 @@ void xdisconnect(int fd) - else - xerror("bad family"); - -- strcpy(cmd, "ss -M | grep -q "); -+ strcpy(cmd, "ss -Mnt | grep -q "); - cmdlen = strlen(cmd); - if (!inet_ntop(addr.ss_family, raw_addr, &cmd[cmdlen], - sizeof(cmd) - cmdlen)) -@@ -1256,7 +1258,7 @@ void xdisconnect(int fd) - - /* - * wait until the pending data is completely flushed and all -- * the MPTCP sockets reached the closed status. -+ * the sockets reached the closed status. - * disconnect will bypass/ignore/drop any pending data. - */ - for (i = 0; ; i += msec_sleep) { -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/mptcp/mptcp_connect_checksum.sh BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/mptcp/mptcp_connect_checksum.sh ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/mptcp/mptcp_connect_checksum.sh 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/mptcp/mptcp_connect_checksum.sh 2025-10-22 13:53:56.875167405 -0400 -@@ -0,0 +1,5 @@ -+#!/bin/bash -+# SPDX-License-Identifier: GPL-2.0 -+ -+MPTCP_LIB_KSFT_TEST="$(basename "${0}" .sh)" \ -+ "$(dirname "${0}")/mptcp_connect.sh" -C "${@}" -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/mptcp/mptcp_connect_mmap.sh BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/mptcp/mptcp_connect_mmap.sh ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/mptcp/mptcp_connect_mmap.sh 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/mptcp/mptcp_connect_mmap.sh 2025-10-22 13:53:56.875167405 -0400 -@@ -0,0 +1,5 @@ -+#!/bin/bash -+# SPDX-License-Identifier: GPL-2.0 -+ -+MPTCP_LIB_KSFT_TEST="$(basename "${0}" .sh)" \ -+ "$(dirname "${0}")/mptcp_connect.sh" -m mmap "${@}" -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/mptcp/mptcp_connect_sendfile.sh BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/mptcp/mptcp_connect_sendfile.sh ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/mptcp/mptcp_connect_sendfile.sh 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/mptcp/mptcp_connect_sendfile.sh 2025-10-22 13:53:56.875167405 -0400 -@@ -0,0 +1,5 @@ -+#!/bin/bash -+# SPDX-License-Identifier: GPL-2.0 -+ -+MPTCP_LIB_KSFT_TEST="$(basename "${0}" .sh)" \ -+ "$(dirname "${0}")/mptcp_connect.sh" -m sendfile "${@}" -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/mptcp/mptcp_inq.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/mptcp/mptcp_inq.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/mptcp/mptcp_inq.c 2025-10-22 13:53:23.703326789 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/mptcp/mptcp_inq.c 2025-10-22 13:53:56.875167405 -0400 -@@ -75,9 +75,10 @@ static void xgetaddrinfo(const char *nod - struct addrinfo *hints, - struct addrinfo **res) - { --again: -- int err = getaddrinfo(node, service, hints, res); -+ int err; - -+again: -+ err = getaddrinfo(node, service, hints, res); - if (err) { - const char *errstr; - -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/mptcp/mptcp_sockopt.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/mptcp/mptcp_sockopt.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/mptcp/mptcp_sockopt.c 2025-10-22 13:53:23.703326789 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/mptcp/mptcp_sockopt.c 2025-10-22 13:53:56.875167405 -0400 -@@ -162,9 +162,10 @@ static void xgetaddrinfo(const char *nod - struct addrinfo *hints, - struct addrinfo **res) - { --again: -- int err = getaddrinfo(node, service, hints, res); -+ int err; - -+again: -+ err = getaddrinfo(node, service, hints, res); - if (err) { - const char *errstr; - -@@ -666,22 +667,26 @@ static void process_one_client(int fd, i - - do_getsockopts(&s, fd, ret, ret2); - if (s.mptcpi_rcv_delta != (uint64_t)ret + 1) -- xerror("mptcpi_rcv_delta %" PRIu64 ", expect %" PRIu64, s.mptcpi_rcv_delta, ret + 1, s.mptcpi_rcv_delta - ret); -+ xerror("mptcpi_rcv_delta %" PRIu64 ", expect %" PRIu64 ", diff %" PRId64, -+ s.mptcpi_rcv_delta, ret + 1, s.mptcpi_rcv_delta - (ret + 1)); - - /* be nice when running on top of older kernel */ - if (s.pkt_stats_avail) { - if (s.last_sample.mptcpi_bytes_sent != ret2) -- xerror("mptcpi_bytes_sent %" PRIu64 ", expect %" PRIu64, -+ xerror("mptcpi_bytes_sent %" PRIu64 ", expect %" PRIu64 -+ ", diff %" PRId64, - s.last_sample.mptcpi_bytes_sent, ret2, - s.last_sample.mptcpi_bytes_sent - ret2); - if (s.last_sample.mptcpi_bytes_received != ret) -- xerror("mptcpi_bytes_received %" PRIu64 ", expect %" PRIu64, -+ xerror("mptcpi_bytes_received %" PRIu64 ", expect %" PRIu64 -+ ", diff %" PRId64, - s.last_sample.mptcpi_bytes_received, ret, - s.last_sample.mptcpi_bytes_received - ret); - if (s.last_sample.mptcpi_bytes_acked != ret) -- xerror("mptcpi_bytes_acked %" PRIu64 ", expect %" PRIu64, -- s.last_sample.mptcpi_bytes_acked, ret2, -- s.last_sample.mptcpi_bytes_acked - ret2); -+ xerror("mptcpi_bytes_acked %" PRIu64 ", expect %" PRIu64 -+ ", diff %" PRId64, -+ s.last_sample.mptcpi_bytes_acked, ret, -+ s.last_sample.mptcpi_bytes_acked - ret); - } - - close(fd); -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/mptcp/pm_netlink.sh BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/mptcp/pm_netlink.sh ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/mptcp/pm_netlink.sh 2025-10-22 13:53:23.703326789 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/mptcp/pm_netlink.sh 2025-10-22 13:53:56.875167405 -0400 -@@ -198,6 +198,7 @@ set_limits 1 9 2>/dev/null - check "get_limits" "${default_limits}" "subflows above hard limit" - - set_limits 8 8 -+flush_endpoint ## to make sure it doesn't affect the limits - check "get_limits" "$(format_limits 8 8)" "set limits" - - flush_endpoint -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/mptcp/pm_nl_ctl.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/mptcp/pm_nl_ctl.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/mptcp/pm_nl_ctl.c 2025-10-22 13:53:23.703326789 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/mptcp/pm_nl_ctl.c 2025-10-22 13:53:56.875167405 -0400 -@@ -188,6 +188,13 @@ static int capture_events(int fd, int ev - fprintf(stderr, ",error:%u", *(__u8 *)RTA_DATA(attrs)); - else if (attrs->rta_type == MPTCP_ATTR_SERVER_SIDE) - fprintf(stderr, ",server_side:%u", *(__u8 *)RTA_DATA(attrs)); -+ else if (attrs->rta_type == MPTCP_ATTR_FLAGS) { -+ __u16 flags = *(__u16 *)RTA_DATA(attrs); -+ -+ /* only print when present, easier */ -+ if (flags & MPTCP_PM_EV_FLAG_DENY_JOIN_ID0) -+ fprintf(stderr, ",deny_join_id0:1"); -+ } - - attrs = RTA_NEXT(attrs, msg_len); - } -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/mptcp/userspace_pm.sh BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/mptcp/userspace_pm.sh ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/mptcp/userspace_pm.sh 2025-10-22 13:53:23.703326789 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/mptcp/userspace_pm.sh 2025-10-22 13:53:56.875167405 -0400 -@@ -201,6 +201,9 @@ make_connection() - is_v6="v4" - fi - -+ # set this on the client side only: will not affect the rest -+ ip netns exec "$ns2" sysctl -q net.mptcp.allow_join_initial_addr_port=0 -+ - :>"$client_evts" - :>"$server_evts" - -@@ -223,23 +226,28 @@ make_connection() - local client_token - local client_port - local client_serverside -+ local client_nojoin - local server_token - local server_serverside -+ local server_nojoin - - client_token=$(mptcp_lib_evts_get_info token "$client_evts") - client_port=$(mptcp_lib_evts_get_info sport "$client_evts") - client_serverside=$(mptcp_lib_evts_get_info server_side "$client_evts") -+ client_nojoin=$(mptcp_lib_evts_get_info deny_join_id0 "$client_evts") - server_token=$(mptcp_lib_evts_get_info token "$server_evts") - server_serverside=$(mptcp_lib_evts_get_info server_side "$server_evts") -+ server_nojoin=$(mptcp_lib_evts_get_info deny_join_id0 "$server_evts") - - print_test "Established IP${is_v6} MPTCP Connection ns2 => ns1" -- if [ "$client_token" != "" ] && [ "$server_token" != "" ] && [ "$client_serverside" = 0 ] && -- [ "$server_serverside" = 1 ] -+ if [ "${client_token}" != "" ] && [ "${server_token}" != "" ] && -+ [ "${client_serverside}" = 0 ] && [ "${server_serverside}" = 1 ] && -+ [ "${client_nojoin:-0}" = 0 ] && [ "${server_nojoin:-0}" = 1 ] - then - test_pass - print_title "Connection info: ${client_addr}:${client_port} -> ${connect_addr}:${app_port}" - else -- test_fail "Expected tokens (c:${client_token} - s:${server_token}) and server (c:${client_serverside} - s:${server_serverside})" -+ test_fail "Expected tokens (c:${client_token} - s:${server_token}), server (c:${client_serverside} - s:${server_serverside}), nojoin (c:${client_nojoin} - s:${server_nojoin})" - mptcp_lib_result_print_all_tap - exit ${KSFT_FAIL} - fi -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/nat6to4.sh BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/nat6to4.sh ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/nat6to4.sh 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/nat6to4.sh 2025-10-22 13:53:56.875167405 -0400 -@@ -0,0 +1,15 @@ -+#!/bin/bash -+# SPDX-License-Identifier: GPL-2.0 -+ -+NS="ns-peer-$(mktemp -u XXXXXX)" -+ -+ip netns add "${NS}" -+ip -netns "${NS}" link set lo up -+ip -netns "${NS}" route add default via 127.0.0.2 dev lo -+ -+tc -n "${NS}" qdisc add dev lo ingress -+tc -n "${NS}" filter add dev lo ingress prio 4 protocol ip \ -+ bpf object-file nat6to4.bpf.o section schedcls/egress4/snat4 direct-action -+ -+ip netns exec "${NS}" \ -+ bash -c 'echo 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789abc | socat - UDP4-DATAGRAM:224.1.0.1:6666,ip-multicast-loop=1' -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/netfilter/config BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/netfilter/config ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/netfilter/config 2025-10-22 13:53:23.703326789 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/netfilter/config 2025-10-22 13:53:56.875167405 -0400 -@@ -92,4 +92,4 @@ CONFIG_XFRM_STATISTICS=y - CONFIG_NET_PKTGEN=m - CONFIG_TUN=m - CONFIG_INET_DIAG=m --CONFIG_SCTP_DIAG=m -+CONFIG_INET_SCTP_DIAG=m -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/netfilter/conntrack_clash.sh BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/netfilter/conntrack_clash.sh ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/netfilter/conntrack_clash.sh 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/netfilter/conntrack_clash.sh 2025-10-22 13:53:56.875167405 -0400 -@@ -0,0 +1,174 @@ -+#!/bin/bash -+# SPDX-License-Identifier: GPL-2.0 -+ -+source lib.sh -+ -+clash_resolution_active=0 -+dport=22111 -+ret=0 -+ -+cleanup() -+{ -+ # netns cleanup also zaps any remaining socat echo server. -+ cleanup_all_ns -+} -+ -+checktool "nft --version" "run test without nft" -+checktool "conntrack --version" "run test without conntrack" -+checktool "socat -h" "run test without socat" -+ -+trap cleanup EXIT -+ -+setup_ns nsclient1 nsclient2 nsrouter -+ -+ip netns exec "$nsrouter" nft -f -</dev/null & -+ done -+ -+ for port in $ports; do -+ wait_local_port_listen "$ns" $port udp -+ done -+} -+ -+add_addr() -+{ -+ local ns="$1" -+ local dev="$2" -+ local i="$3" -+ local j="$4" -+ -+ ip -net "$ns" link set "$dev" up -+ ip -net "$ns" addr add "10.0.$i.$j/24" dev "$dev" -+} -+ -+ping_test() -+{ -+ local ns="$1" -+ local daddr="$2" -+ -+ if ! ip netns exec "$ns" ping -q -c 1 $daddr > /dev/null;then -+ echo "FAIL: ping from $ns to $daddr" -+ exit 1 -+ fi -+} -+ -+run_one_clash_test() -+{ -+ local ns="$1" -+ local ctns="$2" -+ local daddr="$3" -+ local dport="$4" -+ local entries -+ local cre -+ -+ if ! ip netns exec "$ns" timeout 30 ./udpclash $daddr $dport;then -+ echo "INFO: did not receive expected number of replies for $daddr:$dport" -+ ip netns exec "$ctns" conntrack -S -+ # don't fail: check if clash resolution triggered after all. -+ fi -+ -+ entries=$(ip netns exec "$ctns" conntrack -S | wc -l) -+ cre=$(ip netns exec "$ctns" conntrack -S | grep "clash_resolve=0" | wc -l) -+ -+ if [ "$cre" -ne "$entries" ];then -+ clash_resolution_active=1 -+ return 0 -+ fi -+ -+ # not a failure: clash resolution logic did not trigger. -+ # With right timing, xmit completed sequentially and -+ # no parallel insertion occurs. -+ return $ksft_skip -+} -+ -+run_clash_test() -+{ -+ local ns="$1" -+ local ctns="$2" -+ local daddr="$3" -+ local dport="$4" -+ local softerr=0 -+ -+ for i in $(seq 1 10);do -+ run_one_clash_test "$ns" "$ctns" "$daddr" "$dport" -+ local rv=$? -+ if [ $rv -eq 0 ];then -+ echo "PASS: clash resolution test for $daddr:$dport on attempt $i" -+ return 0 -+ elif [ $rv -eq $ksft_skip ]; then -+ softerr=1 -+ fi -+ done -+ -+ [ $softerr -eq 1 ] && echo "SKIP: clash resolution for $daddr:$dport did not trigger" -+} -+ -+ip link add veth0 netns "$nsclient1" type veth peer name veth0 netns "$nsrouter" -+ip link add veth0 netns "$nsclient2" type veth peer name veth1 netns "$nsrouter" -+add_addr "$nsclient1" veth0 1 1 -+add_addr "$nsclient2" veth0 2 1 -+add_addr "$nsrouter" veth0 1 99 -+add_addr "$nsrouter" veth1 2 99 -+ -+ip -net "$nsclient1" route add default via 10.0.1.99 -+ip -net "$nsclient2" route add default via 10.0.2.99 -+ip netns exec "$nsrouter" sysctl -q net.ipv4.ip_forward=1 -+ -+ping_test "$nsclient1" 10.0.1.99 -+ping_test "$nsclient1" 10.0.2.1 -+ping_test "$nsclient2" 10.0.1.1 -+ -+spawn_servers "$nsclient2" -+ -+# exercise clash resolution with nat: -+# nsrouter is supposed to dnat to 10.0.2.1:900{0,1,2,3}. -+run_clash_test "$nsclient1" "$nsrouter" 10.0.1.99 "$dport" -+ -+# exercise clash resolution without nat. -+load_simple_ruleset "$nsclient2" -+run_clash_test "$nsclient2" "$nsclient2" 127.0.0.1 9001 -+ -+if [ $clash_resolution_active -eq 0 ];then -+ [ "$ret" -eq 0 ] && ret=$ksft_skip -+ echo "SKIP: Clash resolution did not trigger" -+fi -+ -+exit $ret -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/netfilter/conntrack_resize.sh BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/netfilter/conntrack_resize.sh ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/netfilter/conntrack_resize.sh 2025-10-22 13:53:23.703326789 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/netfilter/conntrack_resize.sh 2025-10-22 13:53:56.875167405 -0400 -@@ -12,6 +12,9 @@ tmpfile="" - tmpfile_proc="" - tmpfile_uniq="" - ret=0 -+have_socat=0 -+ -+socat -h > /dev/null && have_socat=1 - - insert_count=2000 - [ "$KSFT_MACHINE_SLOW" = "yes" ] && insert_count=400 -@@ -123,7 +126,7 @@ ctflush() { - done - } - --ctflood() -+ct_pingflood() - { - local ns="$1" - local duration="$2" -@@ -152,6 +155,44 @@ ctflood() - wait - } - -+ct_udpflood() -+{ -+ local ns="$1" -+ local duration="$2" -+ local now=$(date +%s) -+ local end=$((now + duration)) -+ -+ [ $have_socat -ne "1" ] && return -+ -+ while [ $now -lt $end ]; do -+ip netns exec "$ns" bash<<"EOF" -+ for i in $(seq 1 100);do -+ dport=$(((RANDOM%65536)+1)) -+ -+ echo bar | socat -u STDIN UDP:"127.0.0.1:$dport" & -+ done > /dev/null 2>&1 -+ wait -+EOF -+ now=$(date +%s) -+ done -+} -+ -+ct_udpclash() -+{ -+ local ns="$1" -+ local duration="$2" -+ local now=$(date +%s) -+ local end=$((now + duration)) -+ -+ [ -x udpclash ] || return -+ -+ while [ $now -lt $end ]; do -+ ip netns exec "$ns" timeout 30 ./udpclash 127.0.0.1 $((RANDOM%65536)) > /dev/null 2>&1 -+ -+ now=$(date +%s) -+ done -+} -+ - # dump to /dev/null. We don't want dumps to cause infinite loops - # or use-after-free even when conntrack table is altered while dumps - # are in progress. -@@ -169,6 +210,48 @@ ct_nulldump() - wait - } - -+ct_nulldump_loop() -+{ -+ local ns="$1" -+ local duration="$2" -+ local now=$(date +%s) -+ local end=$((now + duration)) -+ -+ while [ $now -lt $end ]; do -+ ct_nulldump "$ns" -+ sleep $((RANDOM%2)) -+ now=$(date +%s) -+ done -+} -+ -+change_timeouts() -+{ -+ local ns="$1" -+ local r1=$((RANDOM%2)) -+ local r2=$((RANDOM%2)) -+ -+ [ "$r1" -eq 1 ] && ip netns exec "$ns" sysctl -q net.netfilter.nf_conntrack_icmp_timeout=$((RANDOM%5)) -+ [ "$r2" -eq 1 ] && ip netns exec "$ns" sysctl -q net.netfilter.nf_conntrack_udp_timeout=$((RANDOM%5)) -+} -+ -+ct_change_timeouts_loop() -+{ -+ local ns="$1" -+ local duration="$2" -+ local now=$(date +%s) -+ local end=$((now + duration)) -+ -+ while [ $now -lt $end ]; do -+ change_timeouts "$ns" -+ sleep $((RANDOM%2)) -+ now=$(date +%s) -+ done -+ -+ # restore defaults -+ ip netns exec "$ns" sysctl -q net.netfilter.nf_conntrack_icmp_timeout=30 -+ ip netns exec "$ns" sysctl -q net.netfilter.nf_conntrack_udp_timeout=30 -+} -+ - check_taint() - { - local tainted_then="$1" -@@ -194,14 +277,19 @@ check_taint() - insert_flood() - { - local n="$1" -+ local timeout="$2" - local r=0 - - r=$((RANDOM%$insert_count)) - -- ctflood "$n" "$timeout" "floodresize" & -+ ct_pingflood "$n" "$timeout" "floodresize" & -+ ct_udpflood "$n" "$timeout" & -+ ct_udpclash "$n" "$timeout" & -+ - insert_ctnetlink "$n" "$r" & - ctflush "$n" "$timeout" & -- ct_nulldump "$n" & -+ ct_nulldump_loop "$n" "$timeout" & -+ ct_change_timeouts_loop "$n" "$timeout" & - - wait - } -@@ -215,7 +303,7 @@ test_floodresize_all() - read tainted_then < /proc/sys/kernel/tainted - - for n in "$nsclient1" "$nsclient2";do -- insert_flood "$n" & -+ insert_flood "$n" "$timeout" & - done - - # resize table constantly while flood/insert/dump/flushs -@@ -306,7 +394,7 @@ test_dump_all() - - ip netns exec "$nsclient1" sysctl -q net.netfilter.nf_conntrack_icmp_timeout=3600 - -- ctflood "$nsclient1" $timeout "dumpall" & -+ ct_pingflood "$nsclient1" $timeout "dumpall" & - insert_ctnetlink "$nsclient2" $insert_count - - wait -@@ -368,7 +456,7 @@ test_conntrack_disable() - ct_flush_once "$nsclient1" - ct_flush_once "$nsclient2" - -- ctflood "$nsclient1" "$timeout" "conntrack disable" -+ ct_pingflood "$nsclient1" "$timeout" "conntrack disable" - ip netns exec "$nsclient2" ping -q -c 1 127.0.0.1 >/dev/null 2>&1 - - # Disabled, should not have picked up any connection. -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/netfilter/.gitignore BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/netfilter/.gitignore ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/netfilter/.gitignore 2025-10-22 13:53:23.703326789 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/netfilter/.gitignore 2025-10-22 13:53:56.875167405 -0400 -@@ -5,3 +5,4 @@ conntrack_dump_flush - conntrack_reverse_clash - sctp_collision - nf_queue -+udpclash -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/netfilter/ipvs.sh BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/netfilter/ipvs.sh ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/netfilter/ipvs.sh 2025-10-22 13:53:23.703326789 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/netfilter/ipvs.sh 2025-10-22 13:53:56.875167405 -0400 -@@ -151,7 +151,7 @@ test_nat() { - test_tun() { - ip netns exec "${ns0}" ip route add "${vip_v4}" via "${gip_v4}" dev br0 - -- ip netns exec "${ns1}" modprobe -q ipip -+ modprobe -q ipip - ip netns exec "${ns1}" ip link set tunl0 up - ip netns exec "${ns1}" sysctl -qw net.ipv4.ip_forward=0 - ip netns exec "${ns1}" sysctl -qw net.ipv4.conf.all.send_redirects=0 -@@ -160,10 +160,10 @@ test_tun() { - ip netns exec "${ns1}" ipvsadm -a -i -t "${vip_v4}:${port}" -r ${rip_v4}:${port} - ip netns exec "${ns1}" ip addr add ${vip_v4}/32 dev lo:1 - -- ip netns exec "${ns2}" modprobe -q ipip - ip netns exec "${ns2}" ip link set tunl0 up - ip netns exec "${ns2}" sysctl -qw net.ipv4.conf.all.arp_ignore=1 - ip netns exec "${ns2}" sysctl -qw net.ipv4.conf.all.arp_announce=2 -+ ip netns exec "${ns2}" sysctl -qw net.ipv4.conf.tunl0.rp_filter=0 - ip netns exec "${ns2}" ip addr add "${vip_v4}/32" dev lo:1 - - test_service -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/netfilter/Makefile BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/netfilter/Makefile ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/netfilter/Makefile 2025-10-22 13:53:23.703326789 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/netfilter/Makefile 2025-10-22 13:53:56.875167405 -0400 -@@ -15,6 +15,7 @@ TEST_PROGS += conntrack_tcp_unreplied.sh - TEST_PROGS += conntrack_resize.sh - TEST_PROGS += conntrack_sctp_collision.sh - TEST_PROGS += conntrack_vrf.sh -+TEST_PROGS += conntrack_clash.sh - TEST_PROGS += conntrack_reverse_clash.sh - TEST_PROGS += ipvs.sh - TEST_PROGS += nf_conntrack_packetdrill.sh -@@ -44,6 +45,7 @@ TEST_GEN_FILES += connect_close nf_queue - TEST_GEN_FILES += conntrack_dump_flush - TEST_GEN_FILES += conntrack_reverse_clash - TEST_GEN_FILES += sctp_collision -+TEST_GEN_FILES += udpclash - - include ../../lib.mk - -@@ -52,6 +54,7 @@ $(OUTPUT)/nf_queue: LDLIBS += $(MNL_LDLI - - $(OUTPUT)/conntrack_dump_flush: CFLAGS += $(MNL_CFLAGS) - $(OUTPUT)/conntrack_dump_flush: LDLIBS += $(MNL_LDLIBS) -+$(OUTPUT)/udpclash: LDLIBS += -lpthread - - TEST_FILES := lib.sh - TEST_FILES += packetdrill -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/netfilter/nft_concat_range.sh BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/netfilter/nft_concat_range.sh ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/netfilter/nft_concat_range.sh 2025-10-22 13:53:23.703326789 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/netfilter/nft_concat_range.sh 2025-10-22 13:53:56.875167405 -0400 -@@ -1311,6 +1311,9 @@ maybe_send_match() { - # - remove some elements, check that packets don't match anymore - test_correctness_main() { - range_size=1 -+ -+ send_nomatch $((end + 1)) $((end + 1 + src_delta)) || return 1 -+ - for i in $(seq "${start}" $((start + count))); do - local elem="" - -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/netfilter/nft_flowtable.sh BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/netfilter/nft_flowtable.sh ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/netfilter/nft_flowtable.sh 2025-10-22 13:53:23.703326789 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/netfilter/nft_flowtable.sh 2025-10-22 13:53:56.875167405 -0400 -@@ -20,6 +20,7 @@ ret=0 - SOCAT_TIMEOUT=60 - - nsin="" -+nsin_small="" - ns1out="" - ns2out="" - -@@ -36,7 +37,7 @@ cleanup() { - - cleanup_all_ns - -- rm -f "$nsin" "$ns1out" "$ns2out" -+ rm -f "$nsin" "$nsin_small" "$ns1out" "$ns2out" - - [ "$log_netns" -eq 0 ] && sysctl -q net.netfilter.nf_log_all_netns="$log_netns" - } -@@ -72,6 +73,7 @@ lmtu=1500 - rmtu=2000 - - filesize=$((2 * 1024 * 1024)) -+filesize_small=$((filesize / 16)) - - usage(){ - echo "nft_flowtable.sh [OPTIONS]" -@@ -89,7 +91,10 @@ do - o) omtu=$OPTARG;; - l) lmtu=$OPTARG;; - r) rmtu=$OPTARG;; -- s) filesize=$OPTARG;; -+ s) -+ filesize=$OPTARG -+ filesize_small=$((OPTARG / 16)) -+ ;; - *) usage;; - esac - done -@@ -215,6 +220,7 @@ if ! ip netns exec "$ns2" ping -c 1 -q 1 - fi - - nsin=$(mktemp) -+nsin_small=$(mktemp) - ns1out=$(mktemp) - ns2out=$(mktemp) - -@@ -265,6 +271,7 @@ check_counters() - check_dscp() - { - local what=$1 -+ local pmtud="$2" - local ok=1 - - local counter -@@ -277,37 +284,39 @@ check_dscp() - local pc4z=${counter%*bytes*} - local pc4z=${pc4z#*packets} - -+ local failmsg="FAIL: pmtu $pmtu: $what counters do not match, expected" -+ - case "$what" in - "dscp_none") - if [ "$pc4" -gt 0 ] || [ "$pc4z" -eq 0 ]; then -- echo "FAIL: dscp counters do not match, expected dscp3 == 0, dscp0 > 0, but got $pc4,$pc4z" 1>&2 -+ echo "$failmsg dscp3 == 0, dscp0 > 0, but got $pc4,$pc4z" 1>&2 - ret=1 - ok=0 - fi - ;; - "dscp_fwd") - if [ "$pc4" -eq 0 ] || [ "$pc4z" -eq 0 ]; then -- echo "FAIL: dscp counters do not match, expected dscp3 and dscp0 > 0 but got $pc4,$pc4z" 1>&2 -+ echo "$failmsg dscp3 and dscp0 > 0 but got $pc4,$pc4z" 1>&2 - ret=1 - ok=0 - fi - ;; - "dscp_ingress") - if [ "$pc4" -eq 0 ] || [ "$pc4z" -gt 0 ]; then -- echo "FAIL: dscp counters do not match, expected dscp3 > 0, dscp0 == 0 but got $pc4,$pc4z" 1>&2 -+ echo "$failmsg dscp3 > 0, dscp0 == 0 but got $pc4,$pc4z" 1>&2 - ret=1 - ok=0 - fi - ;; - "dscp_egress") - if [ "$pc4" -eq 0 ] || [ "$pc4z" -gt 0 ]; then -- echo "FAIL: dscp counters do not match, expected dscp3 > 0, dscp0 == 0 but got $pc4,$pc4z" 1>&2 -+ echo "$failmsg dscp3 > 0, dscp0 == 0 but got $pc4,$pc4z" 1>&2 - ret=1 - ok=0 - fi - ;; - *) -- echo "FAIL: Unknown DSCP check" 1>&2 -+ echo "$failmsg: Unknown DSCP check" 1>&2 - ret=1 - ok=0 - esac -@@ -319,9 +328,9 @@ check_dscp() - - check_transfer() - { -- in=$1 -- out=$2 -- what=$3 -+ local in=$1 -+ local out=$2 -+ local what=$3 - - if ! cmp "$in" "$out" > /dev/null 2>&1; then - echo "FAIL: file mismatch for $what" 1>&2 -@@ -342,25 +351,39 @@ test_tcp_forwarding_ip() - { - local nsa=$1 - local nsb=$2 -- local dstip=$3 -- local dstport=$4 -+ local pmtu=$3 -+ local dstip=$4 -+ local dstport=$5 - local lret=0 -+ local socatc -+ local socatl -+ local infile="$nsin" -+ -+ if [ $pmtu -eq 0 ]; then -+ infile="$nsin_small" -+ fi - -- timeout "$SOCAT_TIMEOUT" ip netns exec "$nsb" socat -4 TCP-LISTEN:12345,reuseaddr STDIO < "$nsin" > "$ns2out" & -+ timeout "$SOCAT_TIMEOUT" ip netns exec "$nsb" socat -4 TCP-LISTEN:12345,reuseaddr STDIO < "$infile" > "$ns2out" & - lpid=$! - - busywait 1000 listener_ready - -- timeout "$SOCAT_TIMEOUT" ip netns exec "$nsa" socat -4 TCP:"$dstip":"$dstport" STDIO < "$nsin" > "$ns1out" -+ timeout "$SOCAT_TIMEOUT" ip netns exec "$nsa" socat -4 TCP:"$dstip":"$dstport" STDIO < "$infile" > "$ns1out" -+ socatc=$? - - wait $lpid -+ socatl=$? - -- if ! check_transfer "$nsin" "$ns2out" "ns1 -> ns2"; then -+ if [ $socatl -ne 0 ] || [ $socatc -ne 0 ];then -+ rc=1 -+ fi -+ -+ if ! check_transfer "$infile" "$ns2out" "ns1 -> ns2"; then - lret=1 - ret=1 - fi - -- if ! check_transfer "$nsin" "$ns1out" "ns1 <- ns2"; then -+ if ! check_transfer "$infile" "$ns1out" "ns1 <- ns2"; then - lret=1 - ret=1 - fi -@@ -370,14 +393,16 @@ test_tcp_forwarding_ip() - - test_tcp_forwarding() - { -- test_tcp_forwarding_ip "$1" "$2" 10.0.2.99 12345 -+ local pmtu="$3" -+ -+ test_tcp_forwarding_ip "$1" "$2" "$pmtu" 10.0.2.99 12345 - - return $? - } - - test_tcp_forwarding_set_dscp() - { -- check_dscp "dscp_none" -+ local pmtu="$3" - - ip netns exec "$nsr1" nft -f - <&2 -@@ -489,8 +519,9 @@ table ip nat { - } - EOF - -+check_dscp "dscp_none" "0" - if ! test_tcp_forwarding_set_dscp "$ns1" "$ns2" 0 ""; then -- echo "FAIL: flow offload for ns1/ns2 with dscp update" 1>&2 -+ echo "FAIL: flow offload for ns1/ns2 with dscp update and no pmtu discovery" 1>&2 - exit 0 - fi - -@@ -513,6 +544,14 @@ ip netns exec "$ns2" sysctl net.ipv4.ip_ - # For earlier tests (large mtus), packets cannot be handled via flowtable - # (except pure acks and other small packets). - ip netns exec "$nsr1" nft reset counters table inet filter >/dev/null -+ip netns exec "$ns2" nft reset counters table inet filter >/dev/null -+ -+if ! test_tcp_forwarding_set_dscp "$ns1" "$ns2" 1 ""; then -+ echo "FAIL: flow offload for ns1/ns2 with dscp update and pmtu discovery" 1>&2 -+ exit 0 -+fi -+ -+ip netns exec "$nsr1" nft reset counters table inet filter >/dev/null - - if ! test_tcp_forwarding_nat "$ns1" "$ns2" 1 ""; then - echo "FAIL: flow offload for ns1/ns2 with NAT and pmtu discovery" 1>&2 -@@ -644,7 +683,7 @@ ip -net "$ns2" route del 192.168.10.1 vi - ip -net "$ns2" route add default via 10.0.2.1 - ip -net "$ns2" route add default via dead:2::1 - --if test_tcp_forwarding "$ns1" "$ns2"; then -+if test_tcp_forwarding "$ns1" "$ns2" 1; then - check_counters "ipsec tunnel mode for ns1/ns2" - else - echo "FAIL: ipsec tunnel mode for ns1/ns2" -@@ -668,7 +707,7 @@ if [ "$1" = "" ]; then - fi - - echo "re-run with random mtus and file size: -o $o -l $l -r $r -s $filesize" -- $0 -o "$o" -l "$l" -r "$r" -s "$filesize" -+ $0 -o "$o" -l "$l" -r "$r" -s "$filesize" || ret=1 - fi - - exit $ret -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/netfilter/nft_interface_stress.sh BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/netfilter/nft_interface_stress.sh ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/netfilter/nft_interface_stress.sh 2025-10-22 13:53:23.707326770 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/netfilter/nft_interface_stress.sh 2025-10-22 13:53:56.875167405 -0400 -@@ -10,6 +10,8 @@ source lib.sh - checktool "nft --version" "run test without nft tool" - checktool "iperf3 --version" "run test without iperf3 tool" - -+read kernel_tainted < /proc/sys/kernel/tainted -+ - # how many seconds to torture the kernel? - # default to 80% of max run time but don't exceed 48s - TEST_RUNTIME=$((${kselftest_timeout:-60} * 8 / 10)) -@@ -135,7 +137,8 @@ else - wait - fi - --[[ $( -+ * -+ * Emit THREAD_COUNT UDP packets sharing the same saddr:daddr pair. -+ * -+ * This mimics DNS resolver libraries that emit A and AAAA requests -+ * in parallel. -+ * -+ * This exercises conntrack clash resolution logic added and later -+ * refined in -+ * -+ * 71d8c47fc653 ("netfilter: conntrack: introduce clash resolution on insertion race") -+ * ed07d9a021df ("netfilter: nf_conntrack: resolve clash for matching conntracks") -+ * 6a757c07e51f ("netfilter: conntrack: allow insertion of clashing entries") -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define THREAD_COUNT 128 -+ -+struct thread_args { -+ const struct sockaddr_in *si_remote; -+ int sockfd; -+}; -+ -+static volatile int wait = 1; -+ -+static void *thread_main(void *varg) -+{ -+ const struct sockaddr_in *si_remote; -+ const struct thread_args *args = varg; -+ static const char msg[] = "foo"; -+ -+ si_remote = args->si_remote; -+ -+ while (wait == 1) -+ ; -+ -+ if (sendto(args->sockfd, msg, strlen(msg), MSG_NOSIGNAL, -+ (struct sockaddr *)si_remote, sizeof(*si_remote)) < 0) -+ exit(111); -+ -+ return varg; -+} -+ -+static int run_test(int fd, const struct sockaddr_in *si_remote) -+{ -+ struct thread_args thread_args = { -+ .si_remote = si_remote, -+ .sockfd = fd, -+ }; -+ pthread_t *tid = calloc(THREAD_COUNT, sizeof(pthread_t)); -+ unsigned int repl_count = 0, timeout = 0; -+ int i; -+ -+ if (!tid) { -+ perror("calloc"); -+ return 1; -+ } -+ -+ for (i = 0; i < THREAD_COUNT; i++) { -+ int err = pthread_create(&tid[i], NULL, &thread_main, &thread_args); -+ -+ if (err != 0) { -+ perror("pthread_create"); -+ exit(1); -+ } -+ } -+ -+ wait = 0; -+ -+ for (i = 0; i < THREAD_COUNT; i++) -+ pthread_join(tid[i], NULL); -+ -+ while (repl_count < THREAD_COUNT) { -+ struct sockaddr_in si_repl; -+ socklen_t si_repl_len = sizeof(si_repl); -+ char repl[512]; -+ ssize_t ret; -+ -+ ret = recvfrom(fd, repl, sizeof(repl), MSG_NOSIGNAL, -+ (struct sockaddr *) &si_repl, &si_repl_len); -+ if (ret < 0) { -+ if (timeout++ > 5000) { -+ fputs("timed out while waiting for reply from thread\n", stderr); -+ break; -+ } -+ -+ /* give reply time to pass though the stack */ -+ usleep(1000); -+ continue; -+ } -+ -+ if (si_repl_len != sizeof(*si_remote)) { -+ fprintf(stderr, "warning: reply has unexpected repl_len %d vs %d\n", -+ (int)si_repl_len, (int)sizeof(si_repl)); -+ } else if (si_remote->sin_addr.s_addr != si_repl.sin_addr.s_addr || -+ si_remote->sin_port != si_repl.sin_port) { -+ char a[64], b[64]; -+ -+ inet_ntop(AF_INET, &si_remote->sin_addr, a, sizeof(a)); -+ inet_ntop(AF_INET, &si_repl.sin_addr, b, sizeof(b)); -+ -+ fprintf(stderr, "reply from wrong source: want %s:%d got %s:%d\n", -+ a, ntohs(si_remote->sin_port), b, ntohs(si_repl.sin_port)); -+ } -+ -+ repl_count++; -+ } -+ -+ printf("got %d of %d replies\n", repl_count, THREAD_COUNT); -+ -+ free(tid); -+ -+ return repl_count == THREAD_COUNT ? 0 : 1; -+} -+ -+int main(int argc, char *argv[]) -+{ -+ struct sockaddr_in si_local = { -+ .sin_family = AF_INET, -+ }; -+ struct sockaddr_in si_remote = { -+ .sin_family = AF_INET, -+ }; -+ int fd, ret; -+ -+ if (argc < 3) { -+ fputs("Usage: send_udp \n", stderr); -+ return 1; -+ } -+ -+ si_remote.sin_port = htons(atoi(argv[2])); -+ si_remote.sin_addr.s_addr = inet_addr(argv[1]); -+ -+ fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_UDP); -+ if (fd < 0) { -+ perror("socket"); -+ return 1; -+ } -+ -+ if (bind(fd, (struct sockaddr *)&si_local, sizeof(si_local)) < 0) { -+ perror("bind"); -+ return 1; -+ } -+ -+ ret = run_test(fd, &si_remote); -+ -+ close(fd); -+ -+ return ret; -+} -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/packetdrill/tcp_ooo-before-and-after-accept.pkt BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/packetdrill/tcp_ooo-before-and-after-accept.pkt ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/packetdrill/tcp_ooo-before-and-after-accept.pkt 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/packetdrill/tcp_ooo-before-and-after-accept.pkt 2025-10-22 13:53:56.875167405 -0400 -@@ -0,0 +1,53 @@ -+// SPDX-License-Identifier: GPL-2.0 -+ -+--mss=1000 -+ -+`./defaults.sh -+sysctl -q net.ipv4.tcp_rmem="4096 131072 $((32*1024*1024))"` -+ -+// Test that a not-yet-accepted socket does not change -+// its initial sk_rcvbuf (tcp_rmem[1]) when receiving ooo packets. -+ -+ +0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 -+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 -+ +0 bind(3, ..., ...) = 0 -+ +0 listen(3, 1) = 0 -+ -+ +0 < S 0:0(0) win 65535 -+ +0 > S. 0:0(0) ack 1 -+ +.1 < . 1:1(0) ack 1 win 257 -+ +0 < . 2001:41001(39000) ack 1 win 257 -+ +0 > . 1:1(0) ack 1 -+ +0 < . 41001:101001(60000) ack 1 win 257 -+ +0 > . 1:1(0) ack 1 -+ +0 < . 1:1001(1000) ack 1 win 257 -+ +0 > . 1:1(0) ack 1001 -+ +0 < . 1001:2001(1000) ack 1 win 257 -+ +0 > . 1:1(0) ack 101001 -+ -+ +0 accept(3, ..., ...) = 4 -+ -+ +0 %{ assert SK_MEMINFO_RCVBUF == 131072, SK_MEMINFO_RCVBUF }% -+ -+ +0 close(4) = 0 -+ +0 close(3) = 0 -+ -+// Test that ooo packets for accepted sockets do increase sk_rcvbuf -+ +0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 -+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 -+ +0 bind(3, ..., ...) = 0 -+ +0 listen(3, 1) = 0 -+ -+ +0 < S 0:0(0) win 65535 -+ +0 > S. 0:0(0) ack 1 -+ +.1 < . 1:1(0) ack 1 win 257 -+ -+ +0 accept(3, ..., ...) = 4 -+ -+ +0 < . 2001:41001(39000) ack 1 win 257 -+ +0 > . 1:1(0) ack 1 -+ +0 < . 41001:101001(60000) ack 1 win 257 -+ +0 > . 1:1(0) ack 1 -+ -+ +0 %{ assert SK_MEMINFO_RCVBUF > 131072, SK_MEMINFO_RCVBUF }% -+ -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/rtnetlink.sh BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/rtnetlink.sh ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/rtnetlink.sh 2025-10-22 13:53:23.707326770 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/rtnetlink.sh 2025-10-22 13:53:56.875167405 -0400 -@@ -673,6 +673,11 @@ kci_test_ipsec_offload() - sysfsf=$sysfsd/ipsec - sysfsnet=/sys/bus/netdevsim/devices/netdevsim0/net/ - probed=false -+ esp4_offload_probed_default=false -+ -+ if lsmod | grep -q esp4_offload; then -+ esp4_offload_probed_default=true -+ fi - - if ! mount | grep -q debugfs; then - mount -t debugfs none /sys/kernel/debug/ &> /dev/null -@@ -766,6 +771,7 @@ EOF - fi - - # clean up any leftovers -+ ! "$esp4_offload_probed_default" && lsmod | grep -q esp4_offload && rmmod esp4_offload - echo 0 > /sys/bus/netdevsim/del_device - $probed && rmmod netdevsim - -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/tfo.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/tfo.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/tfo.c 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/tfo.c 2025-10-22 13:53:56.875167405 -0400 -@@ -0,0 +1,171 @@ -+// SPDX-License-Identifier: GPL-2.0 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static int cfg_server; -+static int cfg_client; -+static int cfg_port = 8000; -+static struct sockaddr_in6 cfg_addr; -+static char *cfg_outfile; -+ -+static int parse_address(const char *str, int port, struct sockaddr_in6 *sin6) -+{ -+ int ret; -+ -+ sin6->sin6_family = AF_INET6; -+ sin6->sin6_port = htons(port); -+ -+ ret = inet_pton(sin6->sin6_family, str, &sin6->sin6_addr); -+ if (ret != 1) { -+ /* fallback to plain IPv4 */ -+ ret = inet_pton(AF_INET, str, &sin6->sin6_addr.s6_addr32[3]); -+ if (ret != 1) -+ return -1; -+ -+ /* add ::ffff prefix */ -+ sin6->sin6_addr.s6_addr32[0] = 0; -+ sin6->sin6_addr.s6_addr32[1] = 0; -+ sin6->sin6_addr.s6_addr16[4] = 0; -+ sin6->sin6_addr.s6_addr16[5] = 0xffff; -+ } -+ -+ return 0; -+} -+ -+static void run_server(void) -+{ -+ unsigned long qlen = 32; -+ int fd, opt, connfd; -+ socklen_t len; -+ char buf[64]; -+ FILE *outfile; -+ -+ outfile = fopen(cfg_outfile, "w"); -+ if (!outfile) -+ error(1, errno, "fopen() outfile"); -+ -+ fd = socket(AF_INET6, SOCK_STREAM, 0); -+ if (fd == -1) -+ error(1, errno, "socket()"); -+ -+ opt = 1; -+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) -+ error(1, errno, "setsockopt(SO_REUSEADDR)"); -+ -+ if (setsockopt(fd, SOL_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen)) < 0) -+ error(1, errno, "setsockopt(TCP_FASTOPEN)"); -+ -+ if (bind(fd, (struct sockaddr *)&cfg_addr, sizeof(cfg_addr)) < 0) -+ error(1, errno, "bind()"); -+ -+ if (listen(fd, 5) < 0) -+ error(1, errno, "listen()"); -+ -+ len = sizeof(cfg_addr); -+ connfd = accept(fd, (struct sockaddr *)&cfg_addr, &len); -+ if (connfd < 0) -+ error(1, errno, "accept()"); -+ -+ len = sizeof(opt); -+ if (getsockopt(connfd, SOL_SOCKET, SO_INCOMING_NAPI_ID, &opt, &len) < 0) -+ error(1, errno, "getsockopt(SO_INCOMING_NAPI_ID)"); -+ -+ read(connfd, buf, 64); -+ fprintf(outfile, "%d\n", opt); -+ -+ fclose(outfile); -+ close(connfd); -+ close(fd); -+} -+ -+static void run_client(void) -+{ -+ int fd; -+ char *msg = "Hello, world!"; -+ -+ fd = socket(AF_INET6, SOCK_STREAM, 0); -+ if (fd == -1) -+ error(1, errno, "socket()"); -+ -+ sendto(fd, msg, strlen(msg), MSG_FASTOPEN, (struct sockaddr *)&cfg_addr, sizeof(cfg_addr)); -+ -+ close(fd); -+} -+ -+static void usage(const char *filepath) -+{ -+ error(1, 0, "Usage: %s (-s|-c) -h -p -o ", filepath); -+} -+ -+static void parse_opts(int argc, char **argv) -+{ -+ struct sockaddr_in6 *addr6 = (void *) &cfg_addr; -+ char *addr = NULL; -+ int ret; -+ int c; -+ -+ if (argc <= 1) -+ usage(argv[0]); -+ -+ while ((c = getopt(argc, argv, "sch:p:o:")) != -1) { -+ switch (c) { -+ case 's': -+ if (cfg_client) -+ error(1, 0, "Pass one of -s or -c"); -+ cfg_server = 1; -+ break; -+ case 'c': -+ if (cfg_server) -+ error(1, 0, "Pass one of -s or -c"); -+ cfg_client = 1; -+ break; -+ case 'h': -+ addr = optarg; -+ break; -+ case 'p': -+ cfg_port = strtoul(optarg, NULL, 0); -+ break; -+ case 'o': -+ cfg_outfile = strdup(optarg); -+ if (!cfg_outfile) -+ error(1, 0, "outfile invalid"); -+ break; -+ } -+ } -+ -+ if (cfg_server && addr) -+ error(1, 0, "Server cannot have -h specified"); -+ -+ memset(addr6, 0, sizeof(*addr6)); -+ addr6->sin6_family = AF_INET6; -+ addr6->sin6_port = htons(cfg_port); -+ addr6->sin6_addr = in6addr_any; -+ if (addr) { -+ ret = parse_address(addr, cfg_port, addr6); -+ if (ret) -+ error(1, 0, "Client address parse error: %s", addr); -+ } -+} -+ -+int main(int argc, char **argv) -+{ -+ parse_opts(argc, argv); -+ -+ if (cfg_server) -+ run_server(); -+ else if (cfg_client) -+ run_client(); -+ -+ return 0; -+} -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/tfo_passive.sh BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/tfo_passive.sh ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/tfo_passive.sh 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/tfo_passive.sh 2025-10-22 13:53:56.879167386 -0400 -@@ -0,0 +1,112 @@ -+#!/bin/bash -+# SPDX-License-Identifier: GPL-2.0 -+source lib.sh -+ -+NSIM_SV_ID=$((256 + RANDOM % 256)) -+NSIM_SV_SYS=/sys/bus/netdevsim/devices/netdevsim$NSIM_SV_ID -+NSIM_CL_ID=$((512 + RANDOM % 256)) -+NSIM_CL_SYS=/sys/bus/netdevsim/devices/netdevsim$NSIM_CL_ID -+ -+NSIM_DEV_SYS_NEW=/sys/bus/netdevsim/new_device -+NSIM_DEV_SYS_DEL=/sys/bus/netdevsim/del_device -+NSIM_DEV_SYS_LINK=/sys/bus/netdevsim/link_device -+NSIM_DEV_SYS_UNLINK=/sys/bus/netdevsim/unlink_device -+ -+SERVER_IP=192.168.1.1 -+CLIENT_IP=192.168.1.2 -+SERVER_PORT=48675 -+ -+setup_ns() -+{ -+ set -e -+ ip netns add nssv -+ ip netns add nscl -+ -+ NSIM_SV_NAME=$(find $NSIM_SV_SYS/net -maxdepth 1 -type d ! \ -+ -path $NSIM_SV_SYS/net -exec basename {} \;) -+ NSIM_CL_NAME=$(find $NSIM_CL_SYS/net -maxdepth 1 -type d ! \ -+ -path $NSIM_CL_SYS/net -exec basename {} \;) -+ -+ ip link set $NSIM_SV_NAME netns nssv -+ ip link set $NSIM_CL_NAME netns nscl -+ -+ ip netns exec nssv ip addr add "${SERVER_IP}/24" dev $NSIM_SV_NAME -+ ip netns exec nscl ip addr add "${CLIENT_IP}/24" dev $NSIM_CL_NAME -+ -+ ip netns exec nssv ip link set dev $NSIM_SV_NAME up -+ ip netns exec nscl ip link set dev $NSIM_CL_NAME up -+ -+ # Enable passive TFO -+ ip netns exec nssv sysctl -w net.ipv4.tcp_fastopen=519 > /dev/null -+ -+ set +e -+} -+ -+cleanup_ns() -+{ -+ ip netns del nscl -+ ip netns del nssv -+} -+ -+### -+### Code start -+### -+ -+modprobe netdevsim -+ -+# linking -+ -+echo $NSIM_SV_ID > $NSIM_DEV_SYS_NEW -+echo $NSIM_CL_ID > $NSIM_DEV_SYS_NEW -+udevadm settle -+ -+setup_ns -+ -+NSIM_SV_FD=$((256 + RANDOM % 256)) -+exec {NSIM_SV_FD} \ -+ $NSIM_DEV_SYS_LINK -+ -+if [ $? -ne 0 ]; then -+ echo "linking netdevsim1 with netdevsim2 should succeed" -+ cleanup_ns -+ exit 1 -+fi -+ -+out_file=$(mktemp) -+ -+timeout -k 1s 30s ip netns exec nssv ./tfo \ -+ -s \ -+ -p ${SERVER_PORT} \ -+ -o ${out_file}& -+ -+wait_local_port_listen nssv ${SERVER_PORT} tcp -+ -+ip netns exec nscl ./tfo -c -h ${SERVER_IP} -p ${SERVER_PORT} -+ -+wait -+ -+res=$(cat $out_file) -+rm $out_file -+ -+if [ $res -eq 0 ]; then -+ echo "got invalid NAPI ID from passive TFO socket" -+ cleanup_ns -+ exit 1 -+fi -+ -+echo "$NSIM_SV_FD:$NSIM_SV_IFIDX" > $NSIM_DEV_SYS_UNLINK -+ -+echo $NSIM_CL_ID > $NSIM_DEV_SYS_DEL -+ -+cleanup_ns -+ -+modprobe -r netdevsim -+ -+exit 0 -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/udpgro.sh BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/udpgro.sh ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/udpgro.sh 2025-10-22 13:53:23.707326770 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/udpgro.sh 2025-10-22 13:53:56.879167386 -0400 -@@ -48,7 +48,7 @@ run_one() { - - cfg_veth - -- ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${rx_args} & -+ ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 100 ${rx_args} & - local PID1=$! - - wait_local_port_listen ${PEER_NS} 8000 udp -@@ -95,7 +95,7 @@ run_one_nat() { - # will land on the 'plain' one - ip netns exec "${PEER_NS}" ./udpgso_bench_rx -G ${family} -b ${addr1} -n 0 & - local PID1=$! -- ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${family} -b ${addr2%/*} ${rx_args} & -+ ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 100 ${family} -b ${addr2%/*} ${rx_args} & - local PID2=$! - - wait_local_port_listen "${PEER_NS}" 8000 udp -@@ -117,9 +117,9 @@ run_one_2sock() { - - cfg_veth - -- ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 10 ${rx_args} -p 12345 & -+ ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 1000 -R 100 ${rx_args} -p 12345 & - local PID1=$! -- ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 2000 -R 10 ${rx_args} & -+ ip netns exec "${PEER_NS}" ./udpgso_bench_rx -C 2000 -R 100 ${rx_args} & - local PID2=$! - - wait_local_port_listen "${PEER_NS}" 12345 udp -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/net/vlan_hw_filter.sh BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/vlan_hw_filter.sh ---- BPI-Router-Linux-kernel/tools/testing/selftests/net/vlan_hw_filter.sh 2025-10-22 13:53:23.707326770 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/net/vlan_hw_filter.sh 2025-10-22 13:53:56.879167386 -0400 -@@ -3,27 +3,101 @@ - - readonly NETNS="ns-$(mktemp -u XXXXXX)" - -+ALL_TESTS=" -+ test_vlan_filter_check -+ test_vlan0_del_crash_01 -+ test_vlan0_del_crash_02 -+ test_vlan0_del_crash_03 -+ test_vid0_memleak -+" -+ - ret=0 - -+setup() { -+ ip netns add ${NETNS} -+} -+ - cleanup() { -- ip netns del $NETNS -+ ip netns del $NETNS 2>/dev/null - } - - trap cleanup EXIT - - fail() { -- echo "ERROR: ${1:-unexpected return code} (ret: $_)" >&2 -- ret=1 -+ echo "ERROR: ${1:-unexpected return code} (ret: $_)" >&2 -+ ret=1 -+} -+ -+tests_run() -+{ -+ local current_test -+ for current_test in ${TESTS:-$ALL_TESTS}; do -+ $current_test -+ done -+} -+ -+test_vlan_filter_check() { -+ setup -+ ip netns exec ${NETNS} ip link add bond0 type bond mode 0 -+ ip netns exec ${NETNS} ip link add bond_slave_1 type veth peer veth2 -+ ip netns exec ${NETNS} ip link set bond_slave_1 master bond0 -+ ip netns exec ${NETNS} ethtool -K bond0 rx-vlan-filter off -+ ip netns exec ${NETNS} ip link add link bond_slave_1 name bond_slave_1.0 type vlan id 0 -+ ip netns exec ${NETNS} ip link add link bond0 name bond0.0 type vlan id 0 -+ ip netns exec ${NETNS} ip link set bond_slave_1 nomaster -+ ip netns exec ${NETNS} ip link del veth2 || fail "Please check vlan HW filter function" -+ cleanup - } - --ip netns add ${NETNS} --ip netns exec ${NETNS} ip link add bond0 type bond mode 0 --ip netns exec ${NETNS} ip link add bond_slave_1 type veth peer veth2 --ip netns exec ${NETNS} ip link set bond_slave_1 master bond0 --ip netns exec ${NETNS} ethtool -K bond0 rx-vlan-filter off --ip netns exec ${NETNS} ip link add link bond_slave_1 name bond_slave_1.0 type vlan id 0 --ip netns exec ${NETNS} ip link add link bond0 name bond0.0 type vlan id 0 --ip netns exec ${NETNS} ip link set bond_slave_1 nomaster --ip netns exec ${NETNS} ip link del veth2 || fail "Please check vlan HW filter function" -+#enable vlan_filter feature of real_dev with vlan0 during running time -+test_vlan0_del_crash_01() { -+ setup -+ ip netns exec ${NETNS} ip link add bond0 type bond mode 0 -+ ip netns exec ${NETNS} ip link add link bond0 name vlan0 type vlan id 0 protocol 802.1q -+ ip netns exec ${NETNS} ethtool -K bond0 rx-vlan-filter off -+ ip netns exec ${NETNS} ip link set dev bond0 up -+ ip netns exec ${NETNS} ethtool -K bond0 rx-vlan-filter on -+ ip netns exec ${NETNS} ip link set dev bond0 down -+ ip netns exec ${NETNS} ip link set dev bond0 up -+ ip netns exec ${NETNS} ip link del vlan0 || fail "Please check vlan HW filter function" -+ cleanup -+} -+ -+#enable vlan_filter feature and add vlan0 for real_dev during running time -+test_vlan0_del_crash_02() { -+ setup -+ ip netns exec ${NETNS} ip link add bond0 type bond mode 0 -+ ip netns exec ${NETNS} ethtool -K bond0 rx-vlan-filter off -+ ip netns exec ${NETNS} ip link set dev bond0 up -+ ip netns exec ${NETNS} ethtool -K bond0 rx-vlan-filter on -+ ip netns exec ${NETNS} ip link add link bond0 name vlan0 type vlan id 0 protocol 802.1q -+ ip netns exec ${NETNS} ip link set dev bond0 down -+ ip netns exec ${NETNS} ip link set dev bond0 up -+ ip netns exec ${NETNS} ip link del vlan0 || fail "Please check vlan HW filter function" -+ cleanup -+} -+ -+#enable vlan_filter feature of real_dev during running time -+#test kernel_bug of vlan unregister -+test_vlan0_del_crash_03() { -+ setup -+ ip netns exec ${NETNS} ip link add bond0 type bond mode 0 -+ ip netns exec ${NETNS} ip link add link bond0 name vlan0 type vlan id 0 protocol 802.1q -+ ip netns exec ${NETNS} ethtool -K bond0 rx-vlan-filter off -+ ip netns exec ${NETNS} ip link set dev bond0 up -+ ip netns exec ${NETNS} ethtool -K bond0 rx-vlan-filter on -+ ip netns exec ${NETNS} ip link set dev bond0 down -+ ip netns exec ${NETNS} ip link del vlan0 || fail "Please check vlan HW filter function" -+ cleanup -+} -+ -+test_vid0_memleak() { -+ setup -+ ip netns exec ${NETNS} ip link add bond0 up type bond mode 0 -+ ip netns exec ${NETNS} ethtool -K bond0 rx-vlan-filter off -+ ip netns exec ${NETNS} ip link del dev bond0 || fail "Please check vlan HW filter function" -+ cleanup -+} - -+tests_run - exit $ret -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/nolibc/nolibc-test.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/nolibc/nolibc-test.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/nolibc/nolibc-test.c 2025-10-22 13:53:23.707326770 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/nolibc/nolibc-test.c 2025-10-22 13:53:56.879167386 -0400 -@@ -1646,6 +1646,28 @@ int test_strerror(void) - return 0; - } - -+static int test_printf_error(void) -+{ -+ int fd, ret, saved_errno; -+ -+ fd = open("/dev/full", O_RDWR); -+ if (fd == -1) -+ return 1; -+ -+ errno = 0; -+ ret = dprintf(fd, "foo"); -+ saved_errno = errno; -+ close(fd); -+ -+ if (ret != -1) -+ return 2; -+ -+ if (saved_errno != ENOSPC) -+ return 3; -+ -+ return 0; -+} -+ - static int run_printf(int min, int max) - { - int test; -@@ -1675,6 +1697,7 @@ static int run_printf(int min, int max) - CASE_TEST(width_trunc); EXPECT_VFPRINTF(25, " ", "%25d", 1); break; - CASE_TEST(scanf); EXPECT_ZR(1, test_scanf()); break; - CASE_TEST(strerror); EXPECT_ZR(1, test_strerror()); break; -+ CASE_TEST(printf_error); EXPECT_ZR(1, test_printf_error()); break; - case __LINE__: - return ret; /* must be last */ - /* note: do not set any defaults so as to permit holes above */ -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/perf_events/.gitignore BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/perf_events/.gitignore ---- BPI-Router-Linux-kernel/tools/testing/selftests/perf_events/.gitignore 2025-10-22 13:53:23.707326770 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/perf_events/.gitignore 2025-10-22 13:53:56.879167386 -0400 -@@ -2,3 +2,4 @@ - sigtrap_threads - remove_on_exec - watermark_signal -+mmap -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/perf_events/Makefile BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/perf_events/Makefile ---- BPI-Router-Linux-kernel/tools/testing/selftests/perf_events/Makefile 2025-10-22 13:53:23.707326770 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/perf_events/Makefile 2025-10-22 13:53:56.879167386 -0400 -@@ -2,5 +2,5 @@ - CFLAGS += -Wl,-no-as-needed -Wall $(KHDR_INCLUDES) - LDFLAGS += -lpthread - --TEST_GEN_PROGS := sigtrap_threads remove_on_exec watermark_signal -+TEST_GEN_PROGS := sigtrap_threads remove_on_exec watermark_signal mmap - include ../lib.mk -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/perf_events/mmap.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/perf_events/mmap.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/perf_events/mmap.c 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/perf_events/mmap.c 2025-10-22 13:53:56.879167386 -0400 -@@ -0,0 +1,236 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+#define _GNU_SOURCE -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "../kselftest_harness.h" -+ -+#define RB_SIZE 0x3000 -+#define AUX_SIZE 0x10000 -+#define AUX_OFFS 0x4000 -+ -+#define HOLE_SIZE 0x1000 -+ -+/* Reserve space for rb, aux with space for shrink-beyond-vma testing. */ -+#define REGION_SIZE (2 * RB_SIZE + 2 * AUX_SIZE) -+#define REGION_AUX_OFFS (2 * RB_SIZE) -+ -+#define MAP_BASE 1 -+#define MAP_AUX 2 -+ -+#define EVENT_SRC_DIR "/sys/bus/event_source/devices" -+ -+FIXTURE(perf_mmap) -+{ -+ int fd; -+ void *ptr; -+ void *region; -+}; -+ -+FIXTURE_VARIANT(perf_mmap) -+{ -+ bool aux; -+ unsigned long ptr_size; -+}; -+ -+FIXTURE_VARIANT_ADD(perf_mmap, rb) -+{ -+ .aux = false, -+ .ptr_size = RB_SIZE, -+}; -+ -+FIXTURE_VARIANT_ADD(perf_mmap, aux) -+{ -+ .aux = true, -+ .ptr_size = AUX_SIZE, -+}; -+ -+static bool read_event_type(struct dirent *dent, __u32 *type) -+{ -+ char typefn[512]; -+ FILE *fp; -+ int res; -+ -+ snprintf(typefn, sizeof(typefn), "%s/%s/type", EVENT_SRC_DIR, dent->d_name); -+ fp = fopen(typefn, "r"); -+ if (!fp) -+ return false; -+ -+ res = fscanf(fp, "%u", type); -+ fclose(fp); -+ return res > 0; -+} -+ -+FIXTURE_SETUP(perf_mmap) -+{ -+ struct perf_event_attr attr = { -+ .size = sizeof(attr), -+ .disabled = 1, -+ .exclude_kernel = 1, -+ .exclude_hv = 1, -+ }; -+ struct perf_event_attr attr_ok = {}; -+ unsigned int eacces = 0, map = 0; -+ struct perf_event_mmap_page *rb; -+ struct dirent *dent; -+ void *aux, *region; -+ DIR *dir; -+ -+ self->ptr = NULL; -+ -+ dir = opendir(EVENT_SRC_DIR); -+ if (!dir) -+ SKIP(return, "perf not available."); -+ -+ region = mmap(NULL, REGION_SIZE, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0); -+ ASSERT_NE(region, MAP_FAILED); -+ self->region = region; -+ -+ // Try to find a suitable event on this system -+ while ((dent = readdir(dir))) { -+ int fd; -+ -+ if (!read_event_type(dent, &attr.type)) -+ continue; -+ -+ fd = syscall(SYS_perf_event_open, &attr, 0, -1, -1, 0); -+ if (fd < 0) { -+ if (errno == EACCES) -+ eacces++; -+ continue; -+ } -+ -+ // Check whether the event supports mmap() -+ rb = mmap(region, RB_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0); -+ if (rb == MAP_FAILED) { -+ close(fd); -+ continue; -+ } -+ -+ if (!map) { -+ // Save the event in case that no AUX capable event is found -+ attr_ok = attr; -+ map = MAP_BASE; -+ } -+ -+ if (!variant->aux) -+ continue; -+ -+ rb->aux_offset = AUX_OFFS; -+ rb->aux_size = AUX_SIZE; -+ -+ // Check whether it supports a AUX buffer -+ aux = mmap(region + REGION_AUX_OFFS, AUX_SIZE, PROT_READ | PROT_WRITE, -+ MAP_SHARED | MAP_FIXED, fd, AUX_OFFS); -+ if (aux == MAP_FAILED) { -+ munmap(rb, RB_SIZE); -+ close(fd); -+ continue; -+ } -+ -+ attr_ok = attr; -+ map = MAP_AUX; -+ munmap(aux, AUX_SIZE); -+ munmap(rb, RB_SIZE); -+ close(fd); -+ break; -+ } -+ closedir(dir); -+ -+ if (!map) { -+ if (!eacces) -+ SKIP(return, "No mappable perf event found."); -+ else -+ SKIP(return, "No permissions for perf_event_open()"); -+ } -+ -+ self->fd = syscall(SYS_perf_event_open, &attr_ok, 0, -1, -1, 0); -+ ASSERT_NE(self->fd, -1); -+ -+ rb = mmap(region, RB_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, self->fd, 0); -+ ASSERT_NE(rb, MAP_FAILED); -+ -+ if (!variant->aux) { -+ self->ptr = rb; -+ return; -+ } -+ -+ if (map != MAP_AUX) -+ SKIP(return, "No AUX event found."); -+ -+ rb->aux_offset = AUX_OFFS; -+ rb->aux_size = AUX_SIZE; -+ aux = mmap(region + REGION_AUX_OFFS, AUX_SIZE, PROT_READ | PROT_WRITE, -+ MAP_SHARED | MAP_FIXED, self->fd, AUX_OFFS); -+ ASSERT_NE(aux, MAP_FAILED); -+ self->ptr = aux; -+} -+ -+FIXTURE_TEARDOWN(perf_mmap) -+{ -+ ASSERT_EQ(munmap(self->region, REGION_SIZE), 0); -+ if (self->fd != -1) -+ ASSERT_EQ(close(self->fd), 0); -+} -+ -+TEST_F(perf_mmap, remap) -+{ -+ void *tmp, *ptr = self->ptr; -+ unsigned long size = variant->ptr_size; -+ -+ // Test the invalid remaps -+ ASSERT_EQ(mremap(ptr, size, HOLE_SIZE, MREMAP_MAYMOVE), MAP_FAILED); -+ ASSERT_EQ(mremap(ptr + HOLE_SIZE, size, HOLE_SIZE, MREMAP_MAYMOVE), MAP_FAILED); -+ ASSERT_EQ(mremap(ptr + size - HOLE_SIZE, HOLE_SIZE, size, MREMAP_MAYMOVE), MAP_FAILED); -+ // Shrink the end of the mapping such that we only unmap past end of the VMA, -+ // which should succeed and poke a hole into the PROT_NONE region -+ ASSERT_NE(mremap(ptr + size - HOLE_SIZE, size, HOLE_SIZE, MREMAP_MAYMOVE), MAP_FAILED); -+ -+ // Remap the whole buffer to a new address -+ tmp = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); -+ ASSERT_NE(tmp, MAP_FAILED); -+ -+ // Try splitting offset 1 hole size into VMA, this should fail -+ ASSERT_EQ(mremap(ptr + HOLE_SIZE, size - HOLE_SIZE, size - HOLE_SIZE, -+ MREMAP_MAYMOVE | MREMAP_FIXED, tmp), MAP_FAILED); -+ // Remapping the whole thing should succeed fine -+ ptr = mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, tmp); -+ ASSERT_EQ(ptr, tmp); -+ ASSERT_EQ(munmap(tmp, size), 0); -+} -+ -+TEST_F(perf_mmap, unmap) -+{ -+ unsigned long size = variant->ptr_size; -+ -+ // Try to poke holes into the mappings -+ ASSERT_NE(munmap(self->ptr, HOLE_SIZE), 0); -+ ASSERT_NE(munmap(self->ptr + HOLE_SIZE, HOLE_SIZE), 0); -+ ASSERT_NE(munmap(self->ptr + size - HOLE_SIZE, HOLE_SIZE), 0); -+} -+ -+TEST_F(perf_mmap, map) -+{ -+ unsigned long size = variant->ptr_size; -+ -+ // Try to poke holes into the mappings by mapping anonymous memory over it -+ ASSERT_EQ(mmap(self->ptr, HOLE_SIZE, PROT_READ | PROT_WRITE, -+ MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0), MAP_FAILED); -+ ASSERT_EQ(mmap(self->ptr + HOLE_SIZE, HOLE_SIZE, PROT_READ | PROT_WRITE, -+ MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0), MAP_FAILED); -+ ASSERT_EQ(mmap(self->ptr + size - HOLE_SIZE, HOLE_SIZE, PROT_READ | PROT_WRITE, -+ MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0), MAP_FAILED); -+} -+ -+TEST_HARNESS_MAIN -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/sched_ext/exit.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/sched_ext/exit.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/sched_ext/exit.c 2025-10-22 13:53:23.707326770 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/sched_ext/exit.c 2025-10-22 13:53:56.879167386 -0400 -@@ -22,6 +22,14 @@ static enum scx_test_status run(void *ct - struct bpf_link *link; - char buf[16]; - -+ /* -+ * On single-CPU systems, ops.select_cpu() is never -+ * invoked, so skip this test to avoid getting stuck -+ * indefinitely. -+ */ -+ if (tc == EXIT_SELECT_CPU && libbpf_num_possible_cpus() == 1) -+ continue; -+ - skel = exit__open(); - SCX_ENUM_INIT(skel); - skel->rodata->exit_point = tc; -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/syscall_user_dispatch/sud_test.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/syscall_user_dispatch/sud_test.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/syscall_user_dispatch/sud_test.c 2025-10-22 13:53:23.707326770 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/syscall_user_dispatch/sud_test.c 2025-10-22 13:53:56.879167386 -0400 -@@ -79,6 +79,21 @@ TEST_SIGNAL(dispatch_trigger_sigsys, SIG - } - } - -+static void prctl_valid(struct __test_metadata *_metadata, -+ unsigned long op, unsigned long off, -+ unsigned long size, void *sel) -+{ -+ EXPECT_EQ(0, prctl(PR_SET_SYSCALL_USER_DISPATCH, op, off, size, sel)); -+} -+ -+static void prctl_invalid(struct __test_metadata *_metadata, -+ unsigned long op, unsigned long off, -+ unsigned long size, void *sel, int err) -+{ -+ EXPECT_EQ(-1, prctl(PR_SET_SYSCALL_USER_DISPATCH, op, off, size, sel)); -+ EXPECT_EQ(err, errno); -+} -+ - TEST(bad_prctl_param) - { - char sel = SYSCALL_DISPATCH_FILTER_ALLOW; -@@ -86,57 +101,42 @@ TEST(bad_prctl_param) - - /* Invalid op */ - op = -1; -- prctl(PR_SET_SYSCALL_USER_DISPATCH, op, 0, 0, &sel); -- ASSERT_EQ(EINVAL, errno); -+ prctl_invalid(_metadata, op, 0, 0, &sel, EINVAL); - - /* PR_SYS_DISPATCH_OFF */ - op = PR_SYS_DISPATCH_OFF; - - /* offset != 0 */ -- prctl(PR_SET_SYSCALL_USER_DISPATCH, op, 0x1, 0x0, 0); -- EXPECT_EQ(EINVAL, errno); -+ prctl_invalid(_metadata, op, 0x1, 0x0, 0, EINVAL); - - /* len != 0 */ -- prctl(PR_SET_SYSCALL_USER_DISPATCH, op, 0x0, 0xff, 0); -- EXPECT_EQ(EINVAL, errno); -+ prctl_invalid(_metadata, op, 0x0, 0xff, 0, EINVAL); - - /* sel != NULL */ -- prctl(PR_SET_SYSCALL_USER_DISPATCH, op, 0x0, 0x0, &sel); -- EXPECT_EQ(EINVAL, errno); -+ prctl_invalid(_metadata, op, 0x0, 0x0, &sel, EINVAL); - - /* Valid parameter */ -- errno = 0; -- prctl(PR_SET_SYSCALL_USER_DISPATCH, op, 0x0, 0x0, 0x0); -- EXPECT_EQ(0, errno); -+ prctl_valid(_metadata, op, 0x0, 0x0, 0x0); - - /* PR_SYS_DISPATCH_ON */ - op = PR_SYS_DISPATCH_ON; - - /* Dispatcher region is bad (offset > 0 && len == 0) */ -- prctl(PR_SET_SYSCALL_USER_DISPATCH, op, 0x1, 0x0, &sel); -- EXPECT_EQ(EINVAL, errno); -- prctl(PR_SET_SYSCALL_USER_DISPATCH, op, -1L, 0x0, &sel); -- EXPECT_EQ(EINVAL, errno); -+ prctl_invalid(_metadata, op, 0x1, 0x0, &sel, EINVAL); -+ prctl_invalid(_metadata, op, -1L, 0x0, &sel, EINVAL); - - /* Invalid selector */ -- prctl(PR_SET_SYSCALL_USER_DISPATCH, op, 0x0, 0x1, (void *) -1); -- ASSERT_EQ(EFAULT, errno); -+ prctl_invalid(_metadata, op, 0x0, 0x1, (void *) -1, EFAULT); - - /* - * Dispatcher range overflows unsigned long - */ -- prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON, 1, -1L, &sel); -- ASSERT_EQ(EINVAL, errno) { -- TH_LOG("Should reject bad syscall range"); -- } -+ prctl_invalid(_metadata, PR_SYS_DISPATCH_ON, 1, -1L, &sel, EINVAL); - - /* - * Allowed range overflows usigned long - */ -- prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON, -1L, 0x1, &sel); -- ASSERT_EQ(EINVAL, errno) { -- TH_LOG("Should reject bad syscall range"); -- } -+ prctl_invalid(_metadata, PR_SYS_DISPATCH_ON, -1L, 0x1, &sel, EINVAL); - } - - /* -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json ---- BPI-Router-Linux-kernel/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json 2025-10-22 13:53:23.707326770 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/tc-testing/tc-tests/infra/qdiscs.json 2025-10-22 13:53:56.879167386 -0400 -@@ -128,6 +128,32 @@ - ] - }, - { -+ "id": "5456", -+ "name": "Test htb_dequeue_tree with deactivation and row emptying", -+ "category": [ -+ "qdisc", -+ "htb" -+ ], -+ "plugins": { -+ "requires": "nsPlugin" -+ }, -+ "setup": [ -+ "$IP link set dev $DUMMY up || true", -+ "$IP addr add 10.10.11.10/24 dev $DUMMY || true", -+ "$TC qdisc add dev $DUMMY root handle 1: htb default 1", -+ "$TC class add dev $DUMMY parent 1: classid 1:1 htb rate 64bit ", -+ "$TC qdisc add dev $DUMMY parent 1:1 handle 2: netem", -+ "$TC qdisc add dev $DUMMY parent 2:1 handle 3: blackhole" -+ ], -+ "cmdUnderTest": "ping -c1 -W0.01 -I $DUMMY 10.10.11.11", -+ "expExitCode": "1", -+ "verifyCmd": "$TC -j qdisc show dev $DUMMY", -+ "matchJSON": [], -+ "teardown": [ -+ "$TC qdisc del dev $DUMMY root" -+ ] -+ }, -+ { - "id": "c024", - "name": "Test TBF with SKBPRIO - catch qlen corner cases", - "category": [ -@@ -635,5 +661,108 @@ - "$TC qdisc del dev $DUMMY handle 1:0 root", - "$IP addr del 10.10.10.10/24 dev $DUMMY || true" - ] -+ }, -+ { -+ "id": "d74b", -+ "name": "Test use-after-free with DRR/NETEM/BLACKHOLE chain", -+ "category": [ -+ "qdisc", -+ "hfsc", -+ "drr", -+ "netem", -+ "blackhole" -+ ], -+ "plugins": { -+ "requires": [ -+ "nsPlugin", -+ "scapyPlugin" -+ ] -+ }, -+ "setup": [ -+ "$IP link set dev $DUMMY up || true", -+ "$IP addr add 10.10.11.10/24 dev $DUMMY || true", -+ "$TC qdisc add dev $DUMMY root handle 1: drr", -+ "$TC filter add dev $DUMMY parent 1: basic classid 1:1", -+ "$TC class add dev $DUMMY parent 1: classid 1:1 drr", -+ "$TC qdisc add dev $DUMMY parent 1:1 handle 2: hfsc def 1", -+ "$TC class add dev $DUMMY parent 2: classid 2:1 hfsc rt m1 8 d 1 m2 0", -+ "$TC qdisc add dev $DUMMY parent 2:1 handle 3: netem", -+ "$TC qdisc add dev $DUMMY parent 3:1 handle 4: blackhole", -+ "ping -c1 -W0.01 -I $DUMMY 10.10.11.11 || true", -+ "$TC class del dev $DUMMY classid 1:1" -+ ], -+ "cmdUnderTest": "ping -c1 -W0.01 -I $DUMMY 10.10.11.11", -+ "expExitCode": "1", -+ "verifyCmd": "$TC -j class ls dev $DUMMY classid 1:1", -+ "matchJSON": [], -+ "teardown": [ -+ "$TC qdisc del dev $DUMMY root handle 1: drr" -+ ] -+ }, -+ { -+ "id": "be28", -+ "name": "Try to add fq_codel qdisc as a child of an hhf qdisc", -+ "category": [ -+ "qdisc", -+ "fq_codel", -+ "hhf" -+ ], -+ "plugins": { -+ "requires": "nsPlugin" -+ }, -+ "setup": [ -+ "$TC qdisc add dev $DUMMY root handle a: hhf" -+ ], -+ "cmdUnderTest": "$TC qdisc add dev $DUMMY parent a: handle b: fq_codel", -+ "expExitCode": "2", -+ "verifyCmd": "$TC -j qdisc ls dev $DUMMY handle b:", -+ "matchJSON": [], -+ "teardown": [ -+ "$TC qdisc del dev $DUMMY root" -+ ] -+ }, -+ { -+ "id": "fcb5", -+ "name": "Try to add pie qdisc as a child of a drr qdisc", -+ "category": [ -+ "qdisc", -+ "pie", -+ "drr" -+ ], -+ "plugins": { -+ "requires": "nsPlugin" -+ }, -+ "setup": [ -+ "$TC qdisc add dev $DUMMY root handle a: drr" -+ ], -+ "cmdUnderTest": "$TC qdisc add dev $DUMMY parent a: handle b: pie", -+ "expExitCode": "2", -+ "verifyCmd": "$TC -j qdisc ls dev $DUMMY handle b:", -+ "matchJSON": [], -+ "teardown": [ -+ "$TC qdisc del dev $DUMMY root" -+ ] -+ }, -+ { -+ "id": "7801", -+ "name": "Try to add fq qdisc as a child of an inexistent hfsc class", -+ "category": [ -+ "qdisc", -+ "sfq", -+ "hfsc" -+ ], -+ "plugins": { -+ "requires": "nsPlugin" -+ }, -+ "setup": [ -+ "$TC qdisc add dev $DUMMY root handle a: hfsc" -+ ], -+ "cmdUnderTest": "$TC qdisc add dev $DUMMY parent a:fff2 sfq limit 4", -+ "expExitCode": "2", -+ "verifyCmd": "$TC -j qdisc ls dev $DUMMY handle b:", -+ "matchJSON": [], -+ "teardown": [ -+ "$TC qdisc del dev $DUMMY root" -+ ] - } - ] -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/ublk/test_stress_03.sh BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/ublk/test_stress_03.sh ---- BPI-Router-Linux-kernel/tools/testing/selftests/ublk/test_stress_03.sh 2025-10-22 13:53:23.707326770 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/ublk/test_stress_03.sh 2025-10-22 13:53:56.879167386 -0400 -@@ -32,22 +32,23 @@ _create_backfile 2 128M - ublk_io_and_remove 8G -t null -q 4 -z & - ublk_io_and_remove 256M -t loop -q 4 -z "${UBLK_BACKFILES[0]}" & - ublk_io_and_remove 256M -t stripe -q 4 -z "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" & -+wait - - if _have_feature "AUTO_BUF_REG"; then - ublk_io_and_remove 8G -t null -q 4 --auto_zc & - ublk_io_and_remove 256M -t loop -q 4 --auto_zc "${UBLK_BACKFILES[0]}" & - ublk_io_and_remove 256M -t stripe -q 4 --auto_zc "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" & - ublk_io_and_remove 8G -t null -q 4 -z --auto_zc --auto_zc_fallback & -+ wait - fi --wait - - if _have_feature "PER_IO_DAEMON"; then - ublk_io_and_remove 8G -t null -q 4 --auto_zc --nthreads 8 --per_io_tasks & - ublk_io_and_remove 256M -t loop -q 4 --auto_zc --nthreads 8 --per_io_tasks "${UBLK_BACKFILES[0]}" & - ublk_io_and_remove 256M -t stripe -q 4 --auto_zc --nthreads 8 --per_io_tasks "${UBLK_BACKFILES[1]}" "${UBLK_BACKFILES[2]}" & - ublk_io_and_remove 8G -t null -q 4 -z --auto_zc --auto_zc_fallback --nthreads 8 --per_io_tasks & -+ wait - fi --wait - - _cleanup_test "stress" - _show_result $TID $ERR_CODE -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/vDSO/vdso_test_chacha.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/vDSO/vdso_test_chacha.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/vDSO/vdso_test_chacha.c 2025-10-22 13:53:23.707326770 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/vDSO/vdso_test_chacha.c 2025-10-22 13:53:56.879167386 -0400 -@@ -76,7 +76,8 @@ static void reference_chacha20_blocks(ui - - void __weak __arch_chacha20_blocks_nostack(uint8_t *dst_bytes, const uint32_t *key, uint32_t *counter, size_t nblocks) - { -- ksft_exit_skip("Not implemented on architecture\n"); -+ ksft_test_result_skip("Not implemented on architecture\n"); -+ ksft_finished(); - } - - int main(int argc, char *argv[]) -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/vDSO/vdso_test_getrandom.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/vDSO/vdso_test_getrandom.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/vDSO/vdso_test_getrandom.c 2025-10-22 13:53:23.707326770 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/vDSO/vdso_test_getrandom.c 2025-10-22 13:53:56.879167386 -0400 -@@ -242,6 +242,7 @@ static void kselftest(void) - pid_t child; - - ksft_print_header(); -+ vgetrandom_init(); - ksft_set_plan(2); - - for (size_t i = 0; i < 1000; ++i) { -@@ -295,8 +296,6 @@ static void usage(const char *argv0) - - int main(int argc, char *argv[]) - { -- vgetrandom_init(); -- - if (argc == 1) { - kselftest(); - return 0; -@@ -306,6 +305,9 @@ int main(int argc, char *argv[]) - usage(argv[0]); - return 1; - } -+ -+ vgetrandom_init(); -+ - if (!strcmp(argv[1], "bench-single")) - bench_single(); - else if (!strcmp(argv[1], "bench-multi")) -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/x86/Makefile BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/x86/Makefile ---- BPI-Router-Linux-kernel/tools/testing/selftests/x86/Makefile 2025-10-22 13:53:23.707326770 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/x86/Makefile 2025-10-22 13:53:56.879167386 -0400 -@@ -12,7 +12,7 @@ CAN_BUILD_WITH_NOPIE := $(shell ./check_ - - TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt test_mremap_vdso \ - check_initial_reg_state sigreturn iopl ioperm \ -- test_vsyscall mov_ss_trap \ -+ test_vsyscall mov_ss_trap sigtrap_loop \ - syscall_arg_fault fsgsbase_restore sigaltstack - TARGETS_C_BOTHBITS += nx_stack - TARGETS_C_32BIT_ONLY := entry_from_vm86 test_syscall_vdso unwind_vdso \ -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/selftests/x86/sigtrap_loop.c BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/x86/sigtrap_loop.c ---- BPI-Router-Linux-kernel/tools/testing/selftests/x86/sigtrap_loop.c 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/selftests/x86/sigtrap_loop.c 2025-10-22 13:53:56.879167386 -0400 -@@ -0,0 +1,101 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+/* -+ * Copyright (C) 2025 Intel Corporation -+ */ -+#define _GNU_SOURCE -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef __x86_64__ -+# define REG_IP REG_RIP -+#else -+# define REG_IP REG_EIP -+#endif -+ -+static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), int flags) -+{ -+ struct sigaction sa; -+ -+ memset(&sa, 0, sizeof(sa)); -+ sa.sa_sigaction = handler; -+ sa.sa_flags = SA_SIGINFO | flags; -+ sigemptyset(&sa.sa_mask); -+ -+ if (sigaction(sig, &sa, 0)) -+ err(1, "sigaction"); -+ -+ return; -+} -+ -+static void sigtrap(int sig, siginfo_t *info, void *ctx_void) -+{ -+ ucontext_t *ctx = (ucontext_t *)ctx_void; -+ static unsigned int loop_count_on_same_ip; -+ static unsigned long last_trap_ip; -+ -+ if (last_trap_ip == ctx->uc_mcontext.gregs[REG_IP]) { -+ printf("\tTrapped at %016lx\n", last_trap_ip); -+ -+ /* -+ * If the same IP is hit more than 10 times in a row, it is -+ * _considered_ an infinite loop. -+ */ -+ if (++loop_count_on_same_ip > 10) { -+ printf("[FAIL]\tDetected SIGTRAP infinite loop\n"); -+ exit(1); -+ } -+ -+ return; -+ } -+ -+ loop_count_on_same_ip = 0; -+ last_trap_ip = ctx->uc_mcontext.gregs[REG_IP]; -+ printf("\tTrapped at %016lx\n", last_trap_ip); -+} -+ -+int main(int argc, char *argv[]) -+{ -+ sethandler(SIGTRAP, sigtrap, 0); -+ -+ /* -+ * Set the Trap Flag (TF) to single-step the test code, therefore to -+ * trigger a SIGTRAP signal after each instruction until the TF is -+ * cleared. -+ * -+ * Because the arithmetic flags are not significant here, the TF is -+ * set by pushing 0x302 onto the stack and then popping it into the -+ * flags register. -+ * -+ * Four instructions in the following asm code are executed with the -+ * TF set, thus the SIGTRAP handler is expected to run four times. -+ */ -+ printf("[RUN]\tSIGTRAP infinite loop detection\n"); -+ asm volatile( -+#ifdef __x86_64__ -+ /* -+ * Avoid clobbering the redzone -+ * -+ * Equivalent to "sub $128, %rsp", however -128 can be encoded -+ * in a single byte immediate while 128 uses 4 bytes. -+ */ -+ "add $-128, %rsp\n\t" -+#endif -+ "push $0x302\n\t" -+ "popf\n\t" -+ "nop\n\t" -+ "nop\n\t" -+ "push $0x202\n\t" -+ "popf\n\t" -+#ifdef __x86_64__ -+ "sub $-128, %rsp\n\t" -+#endif -+ ); -+ -+ printf("[OK]\tNo SIGTRAP infinite loop detected\n"); -+ return 0; -+} -diff -purNx .git BPI-Router-Linux-kernel/tools/testing/vma/vma_internal.h BPI-Router-Linux-kernel-6.16.12/tools/testing/vma/vma_internal.h ---- BPI-Router-Linux-kernel/tools/testing/vma/vma_internal.h 2025-10-22 13:53:23.707326770 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/testing/vma/vma_internal.h 2025-10-22 13:53:56.879167386 -0400 -@@ -159,6 +159,14 @@ typedef __bitwise unsigned int vm_fault_ - - #define ASSERT_EXCLUSIVE_WRITER(x) - -+/** -+ * swap - swap values of @a and @b -+ * @a: first value -+ * @b: second value -+ */ -+#define swap(a, b) \ -+ do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0) -+ - struct kref { - refcount_t refcount; - }; -@@ -1468,4 +1476,12 @@ static inline void fixup_hugetlb_reserva - (void)vma; - } - -+static inline void vma_set_file(struct vm_area_struct *vma, struct file *file) -+{ -+ /* Changing an anonymous vma with this is illegal */ -+ get_file(file); -+ swap(vma->vm_file, file); -+ fput(file); -+} -+ - #endif /* __MM_VMA_INTERNAL_H */ -diff -purNx .git BPI-Router-Linux-kernel/tools/tracing/latency/Makefile.config BPI-Router-Linux-kernel-6.16.12/tools/tracing/latency/Makefile.config ---- BPI-Router-Linux-kernel/tools/tracing/latency/Makefile.config 2025-10-22 13:53:23.707326770 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/tracing/latency/Makefile.config 2025-10-22 13:53:56.879167386 -0400 -@@ -1,7 +1,15 @@ - # SPDX-License-Identifier: GPL-2.0-only - -+include $(srctree)/tools/scripts/utilities.mak -+ - STOP_ERROR := - -+ifndef ($(NO_LIBTRACEEVENT),1) -+ ifeq ($(call get-executable,$(PKG_CONFIG)),) -+ $(error Error: $(PKG_CONFIG) needed by libtraceevent/libtracefs is missing on this system, please install it) -+ endif -+endif -+ - define lib_setup - $(eval LIB_INCLUDES += $(shell sh -c "$(PKG_CONFIG) --cflags lib$(1)")) - $(eval LDFLAGS += $(shell sh -c "$(PKG_CONFIG) --libs-only-L lib$(1)")) -diff -purNx .git BPI-Router-Linux-kernel/tools/tracing/rtla/Makefile.config BPI-Router-Linux-kernel-6.16.12/tools/tracing/rtla/Makefile.config ---- BPI-Router-Linux-kernel/tools/tracing/rtla/Makefile.config 2025-10-22 13:53:23.707326770 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/tracing/rtla/Makefile.config 2025-10-22 13:53:56.879167386 -0400 -@@ -1,10 +1,18 @@ - # SPDX-License-Identifier: GPL-2.0-only - -+include $(srctree)/tools/scripts/utilities.mak -+ - STOP_ERROR := - - LIBTRACEEVENT_MIN_VERSION = 1.5 - LIBTRACEFS_MIN_VERSION = 1.6 - -+ifndef ($(NO_LIBTRACEEVENT),1) -+ ifeq ($(call get-executable,$(PKG_CONFIG)),) -+ $(error Error: $(PKG_CONFIG) needed by libtraceevent/libtracefs is missing on this system, please install it) -+ endif -+endif -+ - define lib_setup - $(eval LIB_INCLUDES += $(shell sh -c "$(PKG_CONFIG) --cflags lib$(1)")) - $(eval LDFLAGS += $(shell sh -c "$(PKG_CONFIG) --libs-only-L lib$(1)")) -diff -purNx .git BPI-Router-Linux-kernel/tools/verification/dot2/dot2k.py BPI-Router-Linux-kernel-6.16.12/tools/verification/dot2/dot2k.py ---- BPI-Router-Linux-kernel/tools/verification/dot2/dot2k.py 2025-10-22 13:53:23.707326770 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/verification/dot2/dot2k.py 2025-10-22 13:53:56.879167386 -0400 -@@ -35,6 +35,7 @@ class dot2k(Dot2c): - self.states = [] - self.main_c = self.__read_file(self.monitor_templates_dir + "main_container.c") - self.main_h = self.__read_file(self.monitor_templates_dir + "main_container.h") -+ self.kconfig = self.__read_file(self.monitor_templates_dir + "Kconfig_container") - else: - super().__init__(file_path, extra_params.get("model_name")) - -@@ -44,7 +45,7 @@ class dot2k(Dot2c): - self.monitor_type = MonitorType - self.main_c = self.__read_file(self.monitor_templates_dir + "main.c") - self.trace_h = self.__read_file(self.monitor_templates_dir + "trace.h") -- self.kconfig = self.__read_file(self.monitor_templates_dir + "Kconfig") -+ self.kconfig = self.__read_file(self.monitor_templates_dir + "Kconfig") - self.enum_suffix = "_%s" % self.name - self.description = extra_params.get("description", self.name) or "auto-generated" - self.auto_patch = extra_params.get("auto_patch") -diff -purNx .git BPI-Router-Linux-kernel/tools/verification/dot2/dot2k_templates/Kconfig_container BPI-Router-Linux-kernel-6.16.12/tools/verification/dot2/dot2k_templates/Kconfig_container ---- BPI-Router-Linux-kernel/tools/verification/dot2/dot2k_templates/Kconfig_container 1969-12-31 19:00:00.000000000 -0500 -+++ BPI-Router-Linux-kernel-6.16.12/tools/verification/dot2/dot2k_templates/Kconfig_container 2025-10-22 13:53:56.879167386 -0400 -@@ -0,0 +1,5 @@ -+config RV_MON_%%MODEL_NAME_UP%% -+ depends on RV -+ bool "%%MODEL_NAME%% monitor" -+ help -+ %%DESCRIPTION%% -diff -purNx .git BPI-Router-Linux-kernel/tools/verification/rv/src/in_kernel.c BPI-Router-Linux-kernel-6.16.12/tools/verification/rv/src/in_kernel.c ---- BPI-Router-Linux-kernel/tools/verification/rv/src/in_kernel.c 2025-10-22 13:53:23.707326770 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/tools/verification/rv/src/in_kernel.c 2025-10-22 13:53:56.879167386 -0400 -@@ -431,7 +431,7 @@ ikm_event_handler(struct trace_seq *s, s - - if (config_has_id && (config_my_pid == id)) - return 0; -- else if (config_my_pid && (config_my_pid == pid)) -+ else if (config_my_pid == pid) - return 0; - - tep_print_event(trace_event->tep, s, record, "%16s-%-8d [%.3d] ", -@@ -734,7 +734,7 @@ static int parse_arguments(char *monitor - config_reactor = optarg; - break; - case 's': -- config_my_pid = 0; -+ config_my_pid = -1; - break; - case 't': - config_trace = 1; -diff -purNx .git BPI-Router-Linux-kernel/virt/kvm/kvm_main.c BPI-Router-Linux-kernel-6.16.12/virt/kvm/kvm_main.c ---- BPI-Router-Linux-kernel/virt/kvm/kvm_main.c 2025-10-22 13:53:23.707326770 -0400 -+++ BPI-Router-Linux-kernel-6.16.12/virt/kvm/kvm_main.c 2025-10-22 13:53:56.879167386 -0400 -@@ -2572,6 +2572,8 @@ static int kvm_vm_set_mem_attributes(str - r = xa_reserve(&kvm->mem_attr_array, i, GFP_KERNEL_ACCOUNT); - if (r) - goto out_unlock; -+ -+ cond_resched(); - } - - kvm_handle_gfn_range(kvm, &pre_set_range); -@@ -2580,6 +2582,7 @@ static int kvm_vm_set_mem_attributes(str - r = xa_err(xa_store(&kvm->mem_attr_array, i, entry, - GFP_KERNEL_ACCOUNT)); - KVM_BUG_ON(r, kvm); -+ cond_resched(); - } - - kvm_handle_gfn_range(kvm, &post_set_range); diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0001-v6-coverletter-net-next-rework-IRQ-handling-in-mtk_e.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0001-v6-coverletter-net-next-rework-IRQ-handling-in-mtk_e.patch new file mode 100644 index 0000000000..e69de29bb2 diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0002-net-ethernet-mtk_eth_soc-support-named-IRQs.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0002-net-ethernet-mtk_eth_soc-support-named-IRQs.patch new file mode 100644 index 0000000000..542dc4ee70 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0002-net-ethernet-mtk_eth_soc-support-named-IRQs.patch @@ -0,0 +1,99 @@ +From ad319b24f3eae33c753c406611d49032333b25da Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Fri, 13 Jun 2025 16:06:37 +0200 +Subject: [PATCH 02/84] net: ethernet: mtk_eth_soc: support named IRQs + +Add named interrupts and keep index based fallback for existing +devicetrees. + +Currently only rx and tx IRQs are defined to be used with mt7988, but +later extended with RSS/LRO support. + +Signed-off-by: Frank Wunderlich +Reviewed-by: Simon Horman +--- +v6: +- change irq names from tx/rx to fe1/fe2 because reserved irqs + are usable and not bound to specific function +- dropped Simons RB because of this +v5: +- fix typo in description +- add comments from previous patch #3 with changes suggested by simon + +v2: +- move irqs loading part into own helper function +- reduce indentation +- place mtk_get_irqs helper before the irq_handler (note for simon) + +net: mtk_eth_soc: change irq name back to fe1 + fe2 +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 46 ++++++++++++++++----- + 1 file changed, 35 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index 880f27ca84d4..1de594a93146 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3344,6 +3344,37 @@ static void mtk_tx_timeout(struct net_device *dev, unsigned int txqueue) + schedule_work(ð->pending_work); + } + ++static int mtk_get_irqs(struct platform_device *pdev, struct mtk_eth *eth) ++{ ++ int i; ++ ++ /* future SoCs beginning with MT7988 should use named IRQs in dts */ ++ eth->irq[1] = platform_get_irq_byname(pdev, "fe1"); ++ eth->irq[2] = platform_get_irq_byname(pdev, "fe2"); ++ if (eth->irq[1] >= 0 && eth->irq[2] >= 0) ++ return 0; ++ ++ /* legacy way: ++ * On MTK_SHARED_INT SoCs (MT7621 + MT7628) the first IRQ is taken ++ * from devicetree and used for both RX and TX - it is shared. ++ * On SoCs with non-shared IRQs the first entry is not used, ++ * the second is for TX, and the third is for RX. ++ */ ++ for (i = 0; i < 3; i++) { ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT) && i > 0) ++ eth->irq[i] = eth->irq[0]; ++ else ++ eth->irq[i] = platform_get_irq(pdev, i); ++ ++ if (eth->irq[i] < 0) { ++ dev_err(&pdev->dev, "no IRQ%d resource found\n", i); ++ return -ENXIO; ++ } ++ } ++ ++ return 0; ++} ++ + static irqreturn_t mtk_handle_irq_rx(int irq, void *_eth) + { + struct mtk_eth *eth = _eth; +@@ -5113,17 +5144,10 @@ static int mtk_probe(struct platform_device *pdev) + } + } + +- for (i = 0; i < 3; i++) { +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT) && i > 0) +- eth->irq[i] = eth->irq[0]; +- else +- eth->irq[i] = platform_get_irq(pdev, i); +- if (eth->irq[i] < 0) { +- dev_err(&pdev->dev, "no IRQ%d resource found\n", i); +- err = -ENXIO; +- goto err_wed_exit; +- } +- } ++ err = mtk_get_irqs(pdev, eth); ++ if (err) ++ goto err_wed_exit; ++ + for (i = 0; i < ARRAY_SIZE(eth->clks); i++) { + eth->clks[i] = devm_clk_get(eth->dev, + mtk_clks_source_name[i]); +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0003-net-ethernet-mtk_eth_soc-add-consts-for-irq-index.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0003-net-ethernet-mtk_eth_soc-add-consts-for-irq-index.patch new file mode 100644 index 0000000000..96ca3c59a0 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0003-net-ethernet-mtk_eth_soc-add-consts-for-irq-index.patch @@ -0,0 +1,129 @@ +From d32c956e9f42925aa91839d127ee2f2c04bf6f7f Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sun, 15 Jun 2025 12:10:44 +0200 +Subject: [PATCH 03/84] net: ethernet: mtk_eth_soc: add consts for irq index + +Use consts instead of fixed integers for accessing IRQ array. + +Signed-off-by: Frank Wunderlich +Reviewed-by: Simon Horman +Reviewed-by: Daniel Golle +--- +v5: +- rename consts to be compatible with upcoming RSS/LRO changes + MTK_ETH_IRQ_SHARED => MTK_FE_IRQ_SHARED + MTK_ETH_IRQ_TX => MTK_FE_IRQ_TX + MTK_ETH_IRQ_RX => MTK_FE_IRQ_RX + MTK_ETH_IRQ_MAX => MTK_FE_IRQ_NUM +v4: +- calculate max from last (rx) irq index and use it for array size too +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 22 ++++++++++----------- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 7 ++++++- + 2 files changed, 17 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index 1de594a93146..2b9c24bbe7c3 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3349,9 +3349,9 @@ static int mtk_get_irqs(struct platform_device *pdev, struct mtk_eth *eth) + int i; + + /* future SoCs beginning with MT7988 should use named IRQs in dts */ +- eth->irq[1] = platform_get_irq_byname(pdev, "fe1"); +- eth->irq[2] = platform_get_irq_byname(pdev, "fe2"); +- if (eth->irq[1] >= 0 && eth->irq[2] >= 0) ++ eth->irq[MTK_FE_IRQ_TX] = platform_get_irq_byname(pdev, "fe1"); ++ eth->irq[MTK_FE_IRQ_RX] = platform_get_irq_byname(pdev, "fe2"); ++ if (eth->irq[MTK_FE_IRQ_TX] >= 0 && eth->irq[MTK_FE_IRQ_RX] >= 0) + return 0; + + /* legacy way: +@@ -3360,9 +3360,9 @@ static int mtk_get_irqs(struct platform_device *pdev, struct mtk_eth *eth) + * On SoCs with non-shared IRQs the first entry is not used, + * the second is for TX, and the third is for RX. + */ +- for (i = 0; i < 3; i++) { ++ for (i = 0; i < MTK_FE_IRQ_NUM; i++) { + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT) && i > 0) +- eth->irq[i] = eth->irq[0]; ++ eth->irq[i] = eth->irq[MTK_FE_IRQ_SHARED]; + else + eth->irq[i] = platform_get_irq(pdev, i); + +@@ -3428,7 +3428,7 @@ static void mtk_poll_controller(struct net_device *dev) + + mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); + mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask); +- mtk_handle_irq_rx(eth->irq[2], dev); ++ mtk_handle_irq_rx(eth->irq[MTK_FE_IRQ_RX], dev); + mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); + mtk_rx_irq_enable(eth, eth->soc->rx.irq_done_mask); + } +@@ -4914,7 +4914,7 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) + eth->netdev[id]->features |= eth->soc->hw_features; + eth->netdev[id]->ethtool_ops = &mtk_ethtool_ops; + +- eth->netdev[id]->irq = eth->irq[0]; ++ eth->netdev[id]->irq = eth->irq[MTK_FE_IRQ_SHARED]; + eth->netdev[id]->dev.of_node = np; + + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) +@@ -5191,17 +5191,17 @@ static int mtk_probe(struct platform_device *pdev) + } + + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) { +- err = devm_request_irq(eth->dev, eth->irq[0], ++ err = devm_request_irq(eth->dev, eth->irq[MTK_FE_IRQ_SHARED], + mtk_handle_irq, 0, + dev_name(eth->dev), eth); + } else { +- err = devm_request_irq(eth->dev, eth->irq[1], ++ err = devm_request_irq(eth->dev, eth->irq[MTK_FE_IRQ_TX], + mtk_handle_irq_tx, 0, + dev_name(eth->dev), eth); + if (err) + goto err_free_dev; + +- err = devm_request_irq(eth->dev, eth->irq[2], ++ err = devm_request_irq(eth->dev, eth->irq[MTK_FE_IRQ_RX], + mtk_handle_irq_rx, 0, + dev_name(eth->dev), eth); + } +@@ -5247,7 +5247,7 @@ static int mtk_probe(struct platform_device *pdev) + } else + netif_info(eth, probe, eth->netdev[i], + "mediatek frame engine at 0x%08lx, irq %d\n", +- eth->netdev[i]->base_addr, eth->irq[0]); ++ eth->netdev[i]->base_addr, eth->irq[MTK_FE_IRQ_SHARED]); + } + + /* we run 2 devices on the same DMA ring so we need a dummy device +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +index 6f72a8c8ae1e..8cdf1317dff5 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -642,6 +642,11 @@ + + #define MTK_MAC_FSM(x) (0x1010C + ((x) * 0x100)) + ++#define MTK_FE_IRQ_SHARED 0 ++#define MTK_FE_IRQ_TX 1 ++#define MTK_FE_IRQ_RX 2 ++#define MTK_FE_IRQ_NUM (MTK_FE_IRQ_RX + 1) ++ + struct mtk_rx_dma { + unsigned int rxd1; + unsigned int rxd2; +@@ -1292,7 +1297,7 @@ struct mtk_eth { + struct net_device *dummy_dev; + struct net_device *netdev[MTK_MAX_DEVS]; + struct mtk_mac *mac[MTK_MAX_DEVS]; +- int irq[3]; ++ int irq[MTK_FE_IRQ_NUM]; + u32 msg_enable; + unsigned long sysclk; + struct regmap *ethsys; +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0004-net-ethernet-mtk_eth_soc-skip-first-IRQ-if-not-used.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0004-net-ethernet-mtk_eth_soc-skip-first-IRQ-if-not-used.patch new file mode 100644 index 0000000000..99f2431f05 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0004-net-ethernet-mtk_eth_soc-skip-first-IRQ-if-not-used.patch @@ -0,0 +1,68 @@ +From 6345b3efe38255c3c0b500c0fbf6b7dcf9055663 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sun, 15 Jun 2025 12:39:14 +0200 +Subject: [PATCH 04/84] net: ethernet: mtk_eth_soc: skip first IRQ if not used + +On SoCs with dedicated RX and TX interrupts (all except MT7621 and +MT7628) platform_get_irq() is called for the first IRQ (eth->irq[0]) +but it is never used. +Skip the first IRQ and reduce the IRQ-count to 2. + +Signed-off-by: Frank Wunderlich +Reviewed-by: Daniel Golle +Reviewed-by: Simon Horman +--- +v6: +- changed commit description a bit +- use MTK_FE_IRQ_SHARED instead of 0 +v5: +- change commit title and description +v4: +- drop >2 condition as max is already 2 and drop the else continue +- update comment to explain which IRQs are taken in legacy way +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 12 ++++++++---- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 ++-- + 2 files changed, 10 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index 2b9c24bbe7c3..0068a983fcd0 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3361,10 +3361,14 @@ static int mtk_get_irqs(struct platform_device *pdev, struct mtk_eth *eth) + * the second is for TX, and the third is for RX. + */ + for (i = 0; i < MTK_FE_IRQ_NUM; i++) { +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT) && i > 0) +- eth->irq[i] = eth->irq[MTK_FE_IRQ_SHARED]; +- else +- eth->irq[i] = platform_get_irq(pdev, i); ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) { ++ if (i == MTK_FE_IRQ_SHARED) ++ eth->irq[MTK_FE_IRQ_SHARED] = platform_get_irq(pdev, i); ++ else ++ eth->irq[i] = eth->irq[MTK_FE_IRQ_SHARED]; ++ } else { ++ eth->irq[i] = platform_get_irq(pdev, i + 1); ++ } + + if (eth->irq[i] < 0) { + dev_err(&pdev->dev, "no IRQ%d resource found\n", i); +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +index 8cdf1317dff5..9261c0e13b59 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -643,8 +643,8 @@ + #define MTK_MAC_FSM(x) (0x1010C + ((x) * 0x100)) + + #define MTK_FE_IRQ_SHARED 0 +-#define MTK_FE_IRQ_TX 1 +-#define MTK_FE_IRQ_RX 2 ++#define MTK_FE_IRQ_TX 0 ++#define MTK_FE_IRQ_RX 1 + #define MTK_FE_IRQ_NUM (MTK_FE_IRQ_RX + 1) + + struct mtk_rx_dma { +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0005-net-ethernet-mtk_eth_soc-only-use-legacy-mode-on-mis.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0005-net-ethernet-mtk_eth_soc-only-use-legacy-mode-on-mis.patch new file mode 100644 index 0000000000..b0f5e489dd --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0005-net-ethernet-mtk_eth_soc-only-use-legacy-mode-on-mis.patch @@ -0,0 +1,37 @@ +From d9c6fd5ac513e0268cffd88d651d14181724c367 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Wed, 18 Jun 2025 19:03:10 +0200 +Subject: [PATCH 05/84] net: ethernet: mtk_eth_soc: only use legacy mode on + missing IRQ name + +If platform_get_irq_byname returns -ENXIO fall back to legacy (index +based) mode, but on other errors function should return this error. + +Suggested-by: Daniel Golle +Signed-off-by: Frank Wunderlich +Reviewed-by: Simon Horman +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index 0068a983fcd0..9333f2b8e1d6 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3354,6 +3354,13 @@ static int mtk_get_irqs(struct platform_device *pdev, struct mtk_eth *eth) + if (eth->irq[MTK_FE_IRQ_TX] >= 0 && eth->irq[MTK_FE_IRQ_RX] >= 0) + return 0; + ++ /* only use legacy mode if platform_get_irq_byname returned -ENXIO */ ++ if (eth->irq[MTK_FE_IRQ_TX] != -ENXIO) ++ return eth->irq[MTK_FE_IRQ_TX]; ++ ++ if (eth->irq[MTK_FE_IRQ_RX] != -ENXIO) ++ return eth->irq[MTK_FE_IRQ_RX]; ++ + /* legacy way: + * On MTK_SHARED_INT SoCs (MT7621 + MT7628) the first IRQ is taken + * from devicetree and used for both RX and TX - it is shared. +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0006-build.sh-add-build-script-config-defconfig-and-fit-s.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0006-build.sh-add-build-script-config-defconfig-and-fit-s.patch new file mode 100644 index 0000000000..8961329bf5 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0006-build.sh-add-build-script-config-defconfig-and-fit-s.patch @@ -0,0 +1,2766 @@ +From aff3d69278291f4138605fd0c62ca7b085e6326e Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Wed, 7 May 2025 19:23:05 +0200 +Subject: [PATCH 06/84] build.sh: add build script,config,defconfig and fit + source + +--- + arch/arm64/configs/mt7988a_bpi-r4_defconfig | 1310 +++++++++++++++++++ + bpi-r4.its | 112 ++ + build.conf | 27 + + build.sh | 1273 ++++++++++++++++++ + 4 files changed, 2722 insertions(+) + create mode 100644 arch/arm64/configs/mt7988a_bpi-r4_defconfig + create mode 100644 bpi-r4.its + create mode 100644 build.conf + create mode 100755 build.sh + +diff --git a/arch/arm64/configs/mt7988a_bpi-r4_defconfig b/arch/arm64/configs/mt7988a_bpi-r4_defconfig +new file mode 100644 +index 000000000000..69de56a20462 +--- /dev/null ++++ b/arch/arm64/configs/mt7988a_bpi-r4_defconfig +@@ -0,0 +1,1310 @@ ++CONFIG_LOCALVERSION="-bpi-r4" ++CONFIG_LOCALVERSION_AUTO=n ++ ++CONFIG_32BIT=y ++CONFIG_64BIT_TIME=y ++CONFIG_ADVISE_SYSCALLS=y ++CONFIG_AEABI=y ++CONFIG_AF_UNIX_OOB=y ++CONFIG_AIO=y ++CONFIG_ALLOW_DEV_COREDUMP=y ++CONFIG_ANON_INODES=y ++CONFIG_ARCH_BINFMT_ELF_STATE=y ++CONFIG_ARCH_FLATMEM_ENABLE=y ++CONFIG_ARM64_SW_TTBR0_PAN=y ++CONFIG_ARM_CPU_TOPOLOGY=y ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_ARM_GIC_MAX_NR=1 ++CONFIG_ATAGS_PROC=y ++CONFIG_ATA_BMDMA=y ++CONFIG_ATA_SFF=y ++CONFIG_ATM_BR2684_IPFILTER=y ++CONFIG_ATM_CLIP_NO_ICMP=y ++CONFIG_BASE_FULL=y ++CONFIG_BASE_SMALL=n ++CONFIG_BCMA_POSSIBLE=y ++CONFIG_BINARY_PRINTF=y ++CONFIG_BINFMT_ELF=y ++CONFIG_BINFMT_SCRIPT=y ++CONFIG_BITREVERSE=y ++CONFIG_BLK_DEV=y ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 ++CONFIG_BLOCK=y ++CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT=3 ++CONFIG_BOOT_RAW=y ++CONFIG_BPF=y ++CONFIG_BPF_JIT=y ++CONFIG_BPF_JIT_DEFAULT_ON=y ++CONFIG_BPF_SYSCALL=y ++CONFIG_BPF_UNPRIV_DEFAULT_OFF=y ++CONFIG_BQL=y ++CONFIG_BRANCH_PROFILE_NONE=y ++CONFIG_BRIDGE=y ++CONFIG_BRIDGE_IGMP_SNOOPING=y ++CONFIG_BRIDGE_VLAN_FILTERING=y ++CONFIG_BROKEN_ON_SMP=y ++CONFIG_BT_BNEP_MC_FILTER=y ++CONFIG_BT_BNEP_PROTO_FILTER=y ++CONFIG_BT_HCIUART_BCSP=y ++CONFIG_BT_HCIUART_H4=y ++CONFIG_BT_RFCOMM_TTY=y ++CONFIG_BUG=y ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++CONFIG_BUILDTIME_TABLE_SORT=y ++CONFIG_BUILD_SALT="" ++CONFIG_CACHE_L2X0_PMU=y ++CONFIG_CARDBUS=y ++CONFIG_CC_CAN_LINK=y ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++CONFIG_CIFS=m ++CONFIG_CIFS_ALLOW_INSECURE_LEGACY=y ++CONFIG_CIFS_POSIX=y ++CONFIG_CIFS_XATTR=y ++CONFIG_CIFS_FSCACHE=y ++CONFIG_CLS_U32_MARK=y ++CONFIG_CMDLINE="" ++CONFIG_COMPACTION=y ++#CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 ++CONFIG_CONSOLE_LOGLEVEL_QUIET=4 ++CONFIG_CONSTRUCTORS=y ++CONFIG_CPU_LITTLE_ENDIAN=y ++CONFIG_CPU_SW_DOMAIN_PAN=y ++CONFIG_CRAMFS_BLOCKDEV=y ++CONFIG_CRC32=y ++CONFIG_CRC32_SARWATE=y ++CONFIG_CROSS_COMPILE="" ++CONFIG_CRYPTO=y ++CONFIG_CRYPTO_ACOMP2=y ++CONFIG_CRYPTO_AEAD=y ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_AES=y ++CONFIG_CRYPTO_AKCIPHER=y ++CONFIG_CRYPTO_AKCIPHER2=y ++CONFIG_CRYPTO_ALGAPI=y ++CONFIG_CRYPTO_ALGAPI2=y ++CONFIG_CRYPTO_CCM=y ++CONFIG_CRYPTO_CTR=y ++CONFIG_CRYPTO_GCM=y ++CONFIG_CRYPTO_GF128MUL=y ++CONFIG_CRYPTO_GHASH=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_KPP=y ++CONFIG_CRYPTO_KPP2=y ++CONFIG_CRYPTO_LIB_AES=y ++CONFIG_CRYPTO_LIB_ARC4=y ++CONFIG_CRYPTO_LIB_POLY1305_RSIZE=9 ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_MANAGER2=y ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++CONFIG_CRYPTO_NULL=y ++CONFIG_CRYPTO_NULL2=y ++CONFIG_CRYPTO_PCRYPT=y ++CONFIG_CRYPTO_SKCIPHER=y ++CONFIG_CRYPTO_SKCIPHER2=y ++CONFIG_DEBUG_FS=y ++CONFIG_DEBUG_FS_ALLOW_ALL=y ++CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y ++CONFIG_DEBUG_KERNEL=y ++CONFIG_DEFAULT_CUBIC=y ++CONFIG_DEFAULT_DEADLINE=y ++CONFIG_DEFAULT_FQ_CODEL=y ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 ++CONFIG_DEFAULT_INIT="" ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++CONFIG_DEFAULT_NET_SCH="fq_codel" ++CONFIG_DEFAULT_SECURITY="" ++CONFIG_DEFAULT_SECURITY_DAC=y ++CONFIG_DEFAULT_TCP_CONG="cubic" ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_DEVPORT=y ++CONFIG_DMA_COHERENT_POOL=y ++CONFIG_DMA_DECLARE_COHERENT=y ++CONFIG_DMA_NONCOHERENT_MMAP=y ++CONFIG_DOUBLEFAULT=y ++CONFIG_DQL=y ++CONFIG_DUMMY_CONSOLE_COLUMNS=80 ++CONFIG_DUMMY_CONSOLE_ROWS=25 ++CONFIG_DVB_MAX_ADAPTERS=16 ++CONFIG_DYNAMIC_DEBUG_CORE=y ++CONFIG_EFI_PARTITION=y ++CONFIG_ELFCORE=y ++CONFIG_EMBEDDED=y ++CONFIG_ENABLE_WARN_DEPRECATED=y ++CONFIG_EPOLL=y ++CONFIG_ETHERNET=y ++CONFIG_ETHTOOL_NETLINK=y ++CONFIG_EVENTFD=y ++CONFIG_EXPERT=y ++CONFIG_EXPORTFS=y ++CONFIG_EXT2_FS_XATTR=y ++CONFIG_EXT4_USE_FOR_EXT2=y ++CONFIG_EXTRA_FIRMWARE="" ++CONFIG_EXTRA_TARGETS="" ++CONFIG_F2FS_FS_XATTR=y ++CONFIG_F2FS_STAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++CONFIG_FB_NOTIFY=y ++CONFIG_FIB_RULES=y ++CONFIG_FILE_LOCKING=y ++CONFIG_FLATMEM=y ++CONFIG_FLATMEM_MANUAL=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_FORCE_MAX_ZONEORDER=11 ++CONFIG_FORTIFY_SOURCE=y ++CONFIG_FRAME_WARN=1024 ++CONFIG_FSNOTIFY=y ++CONFIG_FUTEX=y ++CONFIG_FUTEX_PI=y ++CONFIG_FW_LOADER=y ++CONFIG_FW_LOADER_USER_HELPER=y ++CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y ++CONFIG_GACT_PROB=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_IRQ_IPI=y ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_GENERIC_NET_UTILS=y ++CONFIG_GENERIC_PTDUMP=y ++CONFIG_GENERIC_VDSO_TIME_NS=y ++CONFIG_GPIOLIB_FASTPATH_LIMIT=512 ++CONFIG_GPIO_SYSFS=y ++CONFIG_HARDENED_USERCOPY=y ++CONFIG_HARDEN_BRANCH_HISTORY=y ++CONFIG_HARDEN_EL2_VECTORS=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_HPET_MMAP_DEFAULT=y ++CONFIG_HW_PERF_EVENTS=y ++CONFIG_HW_RANDOM_TPM=y ++CONFIG_HZ=100 ++CONFIG_HZ_100=y ++CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 ++CONFIG_INET=y ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_INIT_STACK_NONE=y ++CONFIG_INOTIFY_USER=y ++CONFIG_INPUT_MISC=y ++CONFIG_IO_STRICT_DEVMEM=y ++CONFIG_IO_WQ=y ++CONFIG_IPV6_NDISC_NODETYPE=y ++CONFIG_IPW2100_MONITOR=y ++CONFIG_IPW2200_MONITOR=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++CONFIG_IP_VS_MH_TAB_INDEX=10 ++CONFIG_ISDN=y ++CONFIG_JFFS2_CMODE_PRIORITY=y ++CONFIG_JFFS2_COMPRESSION_OPTIONS=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++CONFIG_JFFS2_FS_XATTR=y ++CONFIG_JFFS2_LZMA=y ++CONFIG_JFFS2_RTIME=y ++CONFIG_JFFS2_SUMMARY=y ++CONFIG_JOLIET=y ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_KASAN_STACK=y ++CONFIG_KERNEL_MODE_NEON=y ++CONFIG_KERNEL_XZ=y ++CONFIG_KERNFS=y ++CONFIG_KUSER_HELPERS=y ++CONFIG_LBDAF=y ++CONFIG_LDISC_AUTOLOAD=y ++CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y ++CONFIG_LEDS_BRIGHTNESS_HW_CHANGED=y ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_CLASS_MULTICOLOR=y ++CONFIG_LEDS_TRIGGERS=y ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y ++CONFIG_LEDS_TRIGGER_HEARTBEAT=y ++CONFIG_LEDS_TRIGGER_NETDEV=y ++CONFIG_LEDS_TRIGGER_TIMER=y ++CONFIG_LEDS_GPIO=y ++CONFIG_LINEAR_RANGES=y ++CONFIG_LLC=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_LOCKD_V4=y ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity" ++CONFIG_LSM_MMAP_MIN_ADDR=65536 ++CONFIG_LTO_NONE=y ++CONFIG_LZMA_COMPRESS=y ++CONFIG_LZMA_DECOMPRESS=y ++CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 ++CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 ++CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE="" ++CONFIG_MAY_USE_DEVLINK=y ++CONFIG_MEMBARRIER=y ++#CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++CONFIG_MII=y ++CONFIG_MISC_FILESYSTEMS=y ++CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY=y ++CONFIG_MMC_BLOCK_BOUNCE=y ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMU=y ++CONFIG_MMU_GATHER_RCU_TABLE_FREE=y ++CONFIG_MMU_GATHER_TABLE_FREE=y ++CONFIG_MODPROBE_PATH="/sbin/modprobe" ++CONFIG_MODULES=y ++CONFIG_MODULE_COMPRESS_NONE=y ++CONFIG_MODULE_STRIPPED=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MSDOS_PARTITION=y ++CONFIG_MTD=y ++CONFIG_MTD_BLKDEVS=y ++CONFIG_MTD_BLOCK=y ++CONFIG_MTD_CFI=y ++CONFIG_MTD_CFI_AMDSTD=y ++CONFIG_MTD_CFI_I1=y ++CONFIG_MTD_CFI_I2=y ++CONFIG_MTD_CFI_INTELEXT=y ++CONFIG_MTD_CFI_NOSWAP=y ++CONFIG_MTD_CFI_UTIL=y ++CONFIG_MTD_COMPLEX_MAPPINGS=y ++CONFIG_MTD_GEN_PROBE=y ++CONFIG_MTD_MAP_BANK_WIDTH_1=y ++CONFIG_MTD_MAP_BANK_WIDTH_2=y ++CONFIG_MTD_MAP_BANK_WIDTH_4=y ++CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xff108018 ++CONFIG_MTD_NAND_IDS=y ++CONFIG_MTD_OF_PARTS=y ++CONFIG_MTD_PHYSMAP_OF=y ++CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 ++CONFIG_MTD_ROOTFS_ROOT_DEV=y ++CONFIG_MTD_SPI_NOR_SWP_DISABLE_ON_VOLATILE=y ++CONFIG_MTD_SPI_NOR_USE_4K_SECTORS_LIMIT=4096 ++CONFIG_MTD_SPLIT=y ++CONFIG_MTD_SPLIT_FIRMWARE_NAME="firmware" ++CONFIG_MTD_SPLIT_SQUASHFS_ROOT=y ++CONFIG_MTD_SPLIT_SUPPORT=y ++CONFIG_MULTIUSER=y ++CONFIG_NET=y ++CONFIG_NETDEVICES=y ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NET_CADENCE=y ++CONFIG_NET_CLS=y ++CONFIG_NET_CLS_IND=y ++CONFIG_NET_CORE=y ++CONFIG_NET_EMATCH_STACK=32 ++CONFIG_NET_IPGRE_BROADCAST=y ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_NET_SCHED=y ++CONFIG_NET_SCH_DEFAULT=y ++CONFIG_NET_SCH_FIFO=y ++CONFIG_NET_SCH_FQ_CODEL=y ++CONFIG_NET_SCH_CAKE=m ++CONFIG_NET_SOCK_MSG=y ++CONFIG_NET_VENDOR_3COM=y ++CONFIG_NET_VENDOR_8390=y ++CONFIG_NET_VENDOR_ADAPTEC=y ++CONFIG_NET_VENDOR_AGERE=y ++CONFIG_NET_VENDOR_ALACRITECH=y ++CONFIG_NET_VENDOR_ALTEON=y ++CONFIG_NET_VENDOR_AMAZON=y ++CONFIG_NET_VENDOR_AMD=y ++CONFIG_NET_VENDOR_AQUANTIA=y ++CONFIG_NET_VENDOR_ARC=y ++CONFIG_NET_VENDOR_ATHEROS=y ++CONFIG_NET_VENDOR_AURORA=y ++CONFIG_NET_VENDOR_BROADCOM=y ++CONFIG_NET_VENDOR_BROCADE=y ++CONFIG_NET_VENDOR_CADENCE=y ++CONFIG_NET_VENDOR_CAVIUM=y ++CONFIG_NET_VENDOR_CHELSIO=y ++CONFIG_NET_VENDOR_CIRRUS=y ++CONFIG_NET_VENDOR_CISCO=y ++CONFIG_NET_VENDOR_CORTINA=y ++CONFIG_NET_VENDOR_DEC=y ++CONFIG_NET_VENDOR_DLINK=y ++CONFIG_NET_VENDOR_EMULEX=y ++CONFIG_NET_VENDOR_EXAR=y ++CONFIG_NET_VENDOR_EZCHIP=y ++CONFIG_NET_VENDOR_FARADAY=y ++CONFIG_NET_VENDOR_FREESCALE=y ++CONFIG_NET_VENDOR_FUJITSU=y ++CONFIG_NET_VENDOR_GOOGLE=y ++CONFIG_NET_VENDOR_HISILICON=y ++CONFIG_NET_VENDOR_HP=y ++CONFIG_NET_VENDOR_HUAWEI=y ++CONFIG_NET_VENDOR_I825XX=y ++CONFIG_NET_VENDOR_IBM=y ++CONFIG_NET_VENDOR_INTEL=y ++CONFIG_NET_VENDOR_MARVELL=y ++CONFIG_NET_VENDOR_MELLANOX=y ++CONFIG_NET_VENDOR_MICREL=y ++CONFIG_NET_VENDOR_MICROCHIP=y ++CONFIG_NET_VENDOR_MICROSEMI=y ++CONFIG_NET_VENDOR_MYRI=y ++CONFIG_NET_VENDOR_NATSEMI=y ++CONFIG_NET_VENDOR_NETERION=y ++CONFIG_NET_VENDOR_NETRONOME=y ++CONFIG_NET_VENDOR_NI=y ++CONFIG_NET_VENDOR_NVIDIA=y ++CONFIG_NET_VENDOR_OKI=y ++CONFIG_NET_VENDOR_PACKET_ENGINES=y ++CONFIG_NET_VENDOR_PENSANDO=y ++CONFIG_NET_VENDOR_QLOGIC=y ++CONFIG_NET_VENDOR_QUALCOMM=y ++CONFIG_NET_VENDOR_RDC=y ++CONFIG_NET_VENDOR_REALTEK=y ++CONFIG_NET_VENDOR_RENESAS=y ++CONFIG_NET_VENDOR_ROCKER=y ++CONFIG_NET_VENDOR_SAMSUNG=y ++CONFIG_NET_VENDOR_SEEQ=y ++CONFIG_NET_VENDOR_SILAN=y ++CONFIG_NET_VENDOR_SIS=y ++CONFIG_NET_VENDOR_SMSC=y ++CONFIG_NET_VENDOR_SOCIONEXT=y ++CONFIG_NET_VENDOR_SOLARFLARE=y ++CONFIG_NET_VENDOR_STMICRO=y ++CONFIG_NET_VENDOR_SUN=y ++CONFIG_NET_VENDOR_SYNOPSYS=y ++CONFIG_NET_VENDOR_TEHUTI=y ++CONFIG_NET_VENDOR_TI=y ++CONFIG_NET_VENDOR_TOSHIBA=y ++CONFIG_NET_VENDOR_VIA=y ++CONFIG_NET_VENDOR_WIZNET=y ++CONFIG_NET_VENDOR_XILINX=y ++CONFIG_NET_VENDOR_XIRCOM=y ++CONFIG_NEW_LEDS=y ++CONFIG_NFSD_V3=y ++CONFIG_NFS_COMMON=y ++CONFIG_NFS_V3=y ++CONFIG_NF_CONNTRACK_PROCFS=y ++CONFIG_NF_NAT_MASQUERADE_IPV4=y ++CONFIG_NF_NAT_MASQUERADE_IPV6=y ++CONFIG_NF_TABLES_ARP=y ++CONFIG_NF_TABLES_BRIDGE=y ++CONFIG_NF_TABLES_INET=y ++CONFIG_NF_TABLES_IPV4=y ++CONFIG_NF_TABLES_IPV6=y ++CONFIG_NF_TABLES_NETDEV=y ++CONFIG_NLATTR=y ++CONFIG_NLS_DEFAULT="iso8859-1" ++CONFIG_NMI_LOG_BUF_SHIFT=13 ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_OPTIMIZE_INLINING=y ++CONFIG_OVERLAY_FS=y ++CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW=y ++CONFIG_OVERLAY_FS_XINO_AUTO=y ++CONFIG_PACKET=y ++CONFIG_PAGE_SIZE_4KB=y ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PANIC_TIMEOUT=10 ++CONFIG_PARTITION_ADVANCED=y ++CONFIG_PCIE_BUS_DEFAULT=y ++CONFIG_PCI_QUIRKS=y ++CONFIG_PCI_SYSCALL=y ++CONFIG_PINCONF=y ++CONFIG_PINCTRL_SINGLE=y ++CONFIG_PINMUX=y ++CONFIG_POSIX_TIMERS=y ++CONFIG_PPC_4K_PAGES=y ++CONFIG_PPP_FILTER=y ++CONFIG_PPP_MULTILINK=y ++CONFIG_PREEMPT_NONE=y ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++CONFIG_PRINTK=y ++CONFIG_PRINTK_NMI=y ++CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13 ++CONFIG_PRINT_STACK_DEPTH=64 ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PSTORE_DEFAULT_KMSG_BYTES=10240 ++CONFIG_PWRSEQ_EMMC=y ++CONFIG_PWRSEQ_SIMPLE=y ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++CONFIG_RCU_KTHREAD_PRIO=0 ++CONFIG_RCU_NEED_SEGCBLIST=y ++CONFIG_RCU_STALL_COMMON=y ++CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY=3 ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_RFKILL=y ++CONFIG_RTC_DRV_CMOS=y ++CONFIG_RTC_HCTOSYS=y ++CONFIG_RTC_HCTOSYS_DEVICE="rtc0" ++CONFIG_RTC_INTF_DEV=y ++CONFIG_RTC_INTF_PROC=y ++CONFIG_RTC_INTF_SYSFS=y ++CONFIG_RTC_LIB=y ++CONFIG_RTC_SYSTOHC=y ++CONFIG_RTC_SYSTOHC_DEVICE="rtc0" ++CONFIG_RT_MUTEXES=y ++CONFIG_RUNTIME_TESTING_MENU=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++CONFIG_RXKAD=y ++CONFIG_SATA_MOBILE_LPM_POLICY=0 ++CONFIG_SBITMAP=y ++CONFIG_SCHED_HRTICK=y ++CONFIG_SCHED_OMIT_FRAME_POINTER=y ++CONFIG_SCSI_DMA=y ++CONFIG_SCSI_LOWLEVEL=y ++CONFIG_SCSI_MOD=y ++CONFIG_SCSI_PROC_FS=y ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++CONFIG_SECURITY_DMESG_RESTRICT=y ++CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=0 ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_16550A_VARIANTS=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_DMA=y ++CONFIG_SERIAL_8250_NR_UARTS=3 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=3 ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++CONFIG_SERIAL_EARLYCON=y ++CONFIG_SHMEM=y ++CONFIG_SIGNALFD=y ++CONFIG_SLABINFO=y ++CONFIG_SLAB_MERGE_DEFAULT=y ++CONFIG_SLUB=y ++CONFIG_SLUB_CPU_PARTIAL=y ++CONFIG_SND_DRIVERS=y ++CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 ++CONFIG_SND_HDA_PREALLOC_SIZE=64 ++CONFIG_SND_MAX_CARDS=16 ++CONFIG_SND_OSSEMUL=y ++CONFIG_SND_PCI=y ++CONFIG_SND_PCM_OSS_PLUGINS=y ++CONFIG_SND_PROC_FS=y ++CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y ++CONFIG_SND_USB=y ++CONFIG_SND_VERBOSE_PROCFS=y ++CONFIG_SND_X86=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_SQUASHFS=y ++CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y ++CONFIG_SQUASHFS_EMBEDDED=y ++CONFIG_SQUASHFS_FILE_DIRECT=y ++CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 ++CONFIG_SQUASHFS_XZ=y ++CONFIG_SSB_POSSIBLE=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_STAGING=y ++CONFIG_STANDALONE=y ++CONFIG_STDBINUTILS=y ++CONFIG_STP=y ++CONFIG_STRICT_KERNEL_RWX=y ++CONFIG_STRICT_MODULE_RWX=y ++CONFIG_STRIP_ASM_SYMS=y ++CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES=y ++CONFIG_SWAP=y ++CONFIG_SYMBOLIC_ERRNAME=y ++CONFIG_SYN_COOKIES=y ++CONFIG_SYSCTL=y ++CONFIG_SYSFS=y ++CONFIG_SYSTEM_TRUSTED_KEYS="" ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++CONFIG_TCP_CONG_ADVANCED=y ++CONFIG_TCP_CONG_CUBIC=y ++CONFIG_TEXTSEARCH=y ++CONFIG_THIN_ARCHIVES=y ++CONFIG_TICK_ONESHOT=y ++CONFIG_TIMERFD=y ++CONFIG_TINY_RCU=y ++CONFIG_TMPFS=y ++CONFIG_TMPFS_XATTR=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_TRACING_SUPPORT=y ++CONFIG_TRAD_SIGNALS=y ++CONFIG_TTY=y ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_XATTR=y ++CONFIG_UBIFS_FS_ZLIB=y ++CONFIG_UBIFS_FS_ZSTD=y ++CONFIG_UBSAN_ALIGNMENT=y ++CONFIG_UEVENT_HELPER=y ++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++CONFIG_UID16=y ++CONFIG_UNIX=y ++CONFIG_UNIX98_PTYS=y ++CONFIG_UNIX_SCM=y ++CONFIG_USBIP_VHCI_HC_PORTS=8 ++CONFIG_USBIP_VHCI_NR_HCS=1 ++CONFIG_USB_ALI_M5632=y ++CONFIG_USB_AN2720=y ++CONFIG_USB_ARCH_HAS_HCD=y ++CONFIG_USB_ARMLINUX=y ++CONFIG_USB_AUTOSUSPEND_DELAY=2 ++CONFIG_USB_BELKIN=y ++CONFIG_USB_DEFAULT_PERSIST=y ++CONFIG_USB_EHCI_ROOT_HUB_TT=y ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_OHCI_LITTLE_ENDIAN=y ++CONFIG_USB_SERIAL_GENERIC=y ++CONFIG_USB_SERIAL_KEYSPAN_MPR=y ++CONFIG_USB_SERIAL_KEYSPAN_USA18X=y ++CONFIG_USB_SERIAL_KEYSPAN_USA19=y ++CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y ++CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y ++CONFIG_USB_SERIAL_KEYSPAN_USA19W=y ++CONFIG_USB_SERIAL_KEYSPAN_USA28=y ++CONFIG_USB_SERIAL_KEYSPAN_USA28X=y ++CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y ++CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y ++CONFIG_USB_SERIAL_KEYSPAN_USA49W=y ++CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y ++CONFIG_USB_SERIAL_SAFE_PADDED=y ++CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y ++CONFIG_VDSO=y ++CONFIG_VHOST_MENU=y ++CONFIG_VIRTIO_MENU=y ++CONFIG_VIRT_TO_BUS=y ++CONFIG_VLAN_8021Q=y ++CONFIG_VMSPLIT_3G=y ++CONFIG_WATCHDOG=y ++CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y ++CONFIG_WATCHDOG_OPEN_TIMEOUT=0 ++CONFIG_WEXT_CORE=y ++CONFIG_WEXT_PRIV=y ++CONFIG_WEXT_PROC=y ++CONFIG_WEXT_SPY=y ++CONFIG_WILINK_PLATFORM_DATA=y ++CONFIG_WIRELESS=y ++CONFIG_WIRELESS_EXT=y ++CONFIG_WLAN=y ++CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y ++CONFIG_X86_SYSFB=y ++CONFIG_XEN_SCRUB_PAGES_DEFAULT=y ++CONFIG_XFRM=y ++CONFIG_XZ_DEC=y ++CONFIG_ZONE_DMA=y ++CONFIG_64BIT=y ++CONFIG_AQUANTIA_PHY=y ++CONFIG_ARCH_DMA_ADDR_T_64BIT=y ++CONFIG_ARCH_KEEP_MEMBLOCK=y ++CONFIG_ARCH_MEDIATEK=y ++CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y ++CONFIG_ARCH_MMAP_RND_BITS=18 ++CONFIG_ARCH_MMAP_RND_BITS_MAX=24 ++CONFIG_ARCH_MMAP_RND_BITS_MIN=18 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 ++CONFIG_ARCH_PROC_KCORE_TEXT=y ++CONFIG_ARCH_SPARSEMEM_ENABLE=y ++CONFIG_ARCH_STACKWALK=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARCH_WANTS_NO_INSTR=y ++CONFIG_ARM64=y ++CONFIG_ARM64_4K_PAGES=y ++CONFIG_ARM64_CRYPTO=y ++CONFIG_ARM64_ERRATUM_843419=y ++CONFIG_ARM64_ERRATUM_845719=y ++CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y ++CONFIG_ARM64_MODULE_PLTS=y ++CONFIG_ARM64_PAGE_SHIFT=12 ++CONFIG_ARM64_PA_BITS=48 ++CONFIG_ARM64_PA_BITS_48=y ++CONFIG_ARM64_TAGGED_ADDR_ABI=y ++CONFIG_ARM64_VA_BITS=39 ++CONFIG_ARM64_VA_BITS_39=y ++CONFIG_ARM_AMBA=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++CONFIG_ARM_GIC=y ++CONFIG_ARM_GIC_V2M=y ++CONFIG_ARM_GIC_V3=y ++CONFIG_ARM_GIC_V3_ITS=y ++CONFIG_ARM_GIC_V3_ITS_PCI=y ++CONFIG_ARM_MEDIATEK_CPUFREQ=y ++CONFIG_ARM_MEDIATEK_CPUFREQ_HW=y ++CONFIG_PM_DEVFREQ=y ++CONFIG_ARM_MEDIATEK_CCI_DEVFREQ=y ++CONFIG_ARM_PMU=y ++CONFIG_ARM_PSCI_FW=y ++CONFIG_ATA=y ++CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_SD=y ++CONFIG_BLK_MQ_PCI=y ++CONFIG_BLK_PM=y ++CONFIG_BLOCK_COMPAT=y ++CONFIG_BSD_PROCESS_ACCT=y ++CONFIG_BSD_PROCESS_ACCT_V3=y ++CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_CLONE_BACKWARDS=y ++CONFIG_COMMON_CLK=y ++CONFIG_COMMON_CLK_MEDIATEK=y ++CONFIG_COMMON_CLK_MT2712=y ++CONFIG_COMMON_CLK_MT7622=y ++CONFIG_COMMON_CLK_MT7622_AUDSYS=y ++CONFIG_COMMON_CLK_MT7622_ETHSYS=y ++CONFIG_COMMON_CLK_MT7622_HIFSYS=y ++CONFIG_COMMON_CLK_MT7988=y ++CONFIG_COMMON_CLK_MT8183=y ++CONFIG_COMMON_CLK_MT8516=y ++CONFIG_COMPAT=y ++CONFIG_COMPAT_32BIT_TIME=y ++CONFIG_COMPAT_BINFMT_ELF=y ++CONFIG_COMPAT_NETLINK_MESSAGES=y ++CONFIG_COMPAT_OLD_SIGACTION=y ++CONFIG_CONFIGFS_FS=y ++CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15 ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ATTR_SET=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_STAT=y ++CONFIG_CPU_RMAP=y ++CONFIG_CPU_THERMAL=y ++CONFIG_CRC16=y ++CONFIG_CRYPTO_AES_ARM64=y ++CONFIG_CRYPTO_AES_ARM64_CE=y ++CONFIG_CRYPTO_AES_ARM64_CE_BLK=y ++CONFIG_CRYPTO_AES_ARM64_CE_CCM=y ++CONFIG_CRYPTO_CMAC=y ++CONFIG_CRYPTO_CRC32=y ++CONFIG_CRYPTO_CRC32C=y ++CONFIG_CRYPTO_CRYPTD=y ++CONFIG_CRYPTO_DEFLATE=y ++CONFIG_CRYPTO_DRBG=y ++CONFIG_CRYPTO_DRBG_HMAC=y ++CONFIG_CRYPTO_DRBG_MENU=y ++CONFIG_CRYPTO_ECB=y ++CONFIG_CRYPTO_ECC=y ++CONFIG_CRYPTO_ECDH=y ++CONFIG_CRYPTO_GHASH_ARM64_CE=y ++CONFIG_CRYPTO_HASH_INFO=y ++CONFIG_CRYPTO_HMAC=y ++CONFIG_CRYPTO_JITTERENTROPY=y ++CONFIG_CRYPTO_LIB_SHA256=y ++CONFIG_CRYPTO_LZO=y ++CONFIG_CRYPTO_RNG=y ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_RNG_DEFAULT=y ++CONFIG_CRYPTO_SHA256=y ++CONFIG_CRYPTO_SHA256_ARM64=y ++CONFIG_CRYPTO_SHA2_ARM64_CE=y ++CONFIG_CRYPTO_SHA512=y ++CONFIG_CRYPTO_SIMD=y ++CONFIG_CRYPTO_ZSTD=y ++CONFIG_DCACHE_WORD_ACCESS=y ++CONFIG_DEBUG_MISC=y ++CONFIG_DIMLIB=y ++CONFIG_DMADEVICES=y ++CONFIG_DMATEST=y ++CONFIG_DMA_DIRECT_REMAP=y ++CONFIG_DMA_ENGINE=y ++CONFIG_DMA_ENGINE_RAID=y ++CONFIG_DMA_OF=y ++CONFIG_DMA_REMAP=y ++CONFIG_DMA_VIRTUAL_CHANNELS=y ++CONFIG_DTC=y ++CONFIG_DYNAMIC_DEBUG=y ++CONFIG_EDAC_SUPPORT=y ++CONFIG_EINT_MTK=y ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++CONFIG_F2FS_FS=y ++CONFIG_FIT_PARTITION=y ++CONFIG_FIXED_PHY=y ++CONFIG_FIX_EARLYCON_MEM=y ++CONFIG_FRAME_POINTER=y ++CONFIG_FS_IOMAP=y ++CONFIG_FS_MBCACHE=y ++CONFIG_FWNODE_MDIO=y ++CONFIG_FW_LOADER_PAGED_BUF=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_GENERIC_ARCH_TOPOLOGY=y ++CONFIG_GENERIC_BUG=y ++CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++CONFIG_GENERIC_CPU_AUTOPROBE=y ++CONFIG_GENERIC_CPU_VULNERABILITIES=y ++CONFIG_GENERIC_CSUM=y ++CONFIG_GENERIC_EARLY_IOREMAP=y ++CONFIG_GENERIC_FIND_FIRST_BIT=y ++CONFIG_GENERIC_GETTIMEOFDAY=y ++CONFIG_GENERIC_IDLE_POLL_SETUP=y ++CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y ++CONFIG_GENERIC_IRQ_SHOW=y ++CONFIG_GENERIC_IRQ_SHOW_LEVEL=y ++CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y ++CONFIG_GENERIC_MSI_IRQ=y ++CONFIG_GENERIC_MSI_IRQ_DOMAIN=y ++CONFIG_GENERIC_PCI_IOMAP=y ++CONFIG_GENERIC_PHY=y ++CONFIG_GENERIC_PINCONF=y ++CONFIG_GENERIC_PINCTRL_GROUPS=y ++CONFIG_GENERIC_PINMUX_FUNCTIONS=y ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_GENERIC_SMP_IDLE_THREAD=y ++CONFIG_GENERIC_STRNCPY_FROM_USER=y ++CONFIG_GENERIC_STRNLEN_USER=y ++CONFIG_GENERIC_TIME_VSYSCALL=y ++CONFIG_GLOB=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_CDEV=y ++CONFIG_GRO_CELLS=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_HAS_DMA=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HW_RANDOM=y ++CONFIG_HW_RANDOM_MTK=y ++CONFIG_I2C=y ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_CHARDEV=y ++CONFIG_I2C_MT65XX=y ++CONFIG_ICPLUS_PHY=y ++CONFIG_IIO=y ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_IO_URING=y ++CONFIG_IRQCHIP=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_IRQ_DOMAIN_HIERARCHY=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_IRQ_TIME_ACCOUNTING=y ++CONFIG_IRQ_WORK=y ++CONFIG_JBD2=y ++CONFIG_JUMP_LABEL=y ++CONFIG_LIBFDT=y ++CONFIG_LOCK_DEBUGGING_SUPPORT=y ++CONFIG_LOCK_SPIN_ON_OWNER=y ++CONFIG_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_MAXLINEAR_GPHY=y ++CONFIG_MDIO_BUS=y ++CONFIG_MDIO_DEVICE=y ++CONFIG_MDIO_DEVRES=y ++CONFIG_MEDIATEK_GE_PHY=y ++#CONFIG_MEDIATEK_MT6577_AUXADC=y ++CONFIG_MEDIATEK_WATCHDOG=y ++CONFIG_MEMFD_CREATE=y ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7 ++CONFIG_MFD_SYSCON=y ++CONFIG_MIGRATION=y ++CONFIG_MMC=y ++CONFIG_MMC_BLOCK=y ++CONFIG_MMC_CQHCI=y ++CONFIG_MMC_MTK=y ++CONFIG_MODULES_TREE_LOOKUP=y ++CONFIG_MODULES_USE_ELF_RELA=y ++CONFIG_MTD_NAND_CORE=y ++CONFIG_MTD_NAND_ECC=y ++CONFIG_MTD_NAND_ECC_MEDIATEK=y ++CONFIG_MTD_NAND_ECC_SW_HAMMING=y ++CONFIG_MTD_NAND_MTK=y ++CONFIG_MTD_NAND_MTK_BMT=y ++CONFIG_MTD_PARSER_TRX=y ++CONFIG_MTD_RAW_NAND=y ++CONFIG_MTD_SPI_NAND=y ++CONFIG_MTD_SPI_NOR=y ++CONFIG_MTD_SPLIT_FIRMWARE=y ++CONFIG_MTD_SPLIT_FIT_FW=y ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++CONFIG_MTD_UBI_BLOCK=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTK_EFUSE=y ++CONFIG_MTK_HSDMA=y ++CONFIG_MTK_INFRACFG=y ++CONFIG_MTK_PMIC_WRAP=y ++CONFIG_MTK_SCPSYS=y ++CONFIG_MTK_SCPSYS_PM_DOMAINS=y ++CONFIG_MTK_THERMAL=y ++CONFIG_MTK_SOC_THERMAL=y ++CONFIG_MTK_TIMER=y ++CONFIG_MUTEX_SPIN_ON_OWNER=y ++CONFIG_NEED_DMA_MAP_STATE=y ++CONFIG_NEED_SG_DMA_LENGTH=y ++CONFIG_NET_DEVLINK=y ++CONFIG_NET_DSA=y ++CONFIG_NET_DSA_MT7530=y ++CONFIG_NET_DSA_TAG_MTK=y ++CONFIG_LED_TRIGGER_PHY=y ++CONFIG_NET_FLOW_LIMIT=y ++CONFIG_NET_MEDIATEK_SOC=y ++CONFIG_NET_MEDIATEK_SOC_WED=y ++CONFIG_NET_SELFTESTS=y ++CONFIG_NET_SWITCHDEV=y ++CONFIG_NET_VENDOR_MEDIATEK=y ++CONFIG_NLS=y ++CONFIG_NO_HZ_COMMON=y ++CONFIG_NO_HZ_IDLE=y ++CONFIG_NR_CPUS=4 ++CONFIG_NVMEM=y ++CONFIG_NVMEM_SYSFS=y ++CONFIG_OF=y ++CONFIG_OF_ADDRESS=y ++CONFIG_OF_DYNAMIC=y ++CONFIG_OF_EARLY_FLATTREE=y ++CONFIG_OF_FLATTREE=y ++CONFIG_OF_GPIO=y ++CONFIG_OF_IRQ=y ++CONFIG_OF_KOBJ=y ++CONFIG_OF_MDIO=y ++CONFIG_OF_OVERLAY=y ++CONFIG_OF_RESOLVE=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_PADATA=y ++CONFIG_PARTITION_PERCPU=y ++CONFIG_PCI=y ++CONFIG_PCIEAER=y ++CONFIG_PCIEASPM=y ++CONFIG_PCIEASPM_PERFORMANCE=y ++CONFIG_PCIEPORTBUS=y ++CONFIG_PCIE_MEDIATEK=y ++CONFIG_PCIE_MEDIATEK_GEN3=y ++CONFIG_PCIE_PME=y ++CONFIG_PCI_DEBUG=y ++CONFIG_PCI_DOMAINS=y ++CONFIG_PCI_DOMAINS_GENERIC=y ++CONFIG_PCI_MSI=y ++CONFIG_PCI_MSI_IRQ_DOMAIN=y ++CONFIG_PERF_EVENTS=y ++CONFIG_PGTABLE_LEVELS=3 ++CONFIG_PHYLIB=y ++CONFIG_PHYLINK=y ++CONFIG_PHYS_ADDR_T_64BIT=y ++CONFIG_PHY_MTK_TPHY=y ++CONFIG_PINCTRL=y ++CONFIG_PINCTRL_MT7622=y ++CONFIG_PINCTRL_MT7988=y ++CONFIG_PINCTRL_MT8516=y ++CONFIG_PINCTRL_MTK=y ++CONFIG_PINCTRL_MTK_MOORE=y ++CONFIG_PINCTRL_MTK_V2=y ++CONFIG_PM=y ++CONFIG_PM_CLK=y ++CONFIG_PM_GENERIC_DOMAINS=y ++CONFIG_PM_GENERIC_DOMAINS_OF=y ++CONFIG_PM_OPP=y ++CONFIG_POWER_RESET=y ++CONFIG_POWER_RESET_SYSCON=y ++CONFIG_POWER_SUPPLY=y ++CONFIG_PRINTK_TIME=y ++CONFIG_PSTORE=y ++CONFIG_PSTORE_COMPRESS=n ++#CONFIG_PSTORE_COMPRESS_DEFAULT="deflate" ++CONFIG_PSTORE_CONSOLE=y ++#CONFIG_PSTORE_DEFLATE_COMPRESS=y ++#CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT=y ++CONFIG_PSTORE_PMSG=y ++CONFIG_PSTORE_RAM=y ++CONFIG_PTP_1588_CLOCK_OPTIONAL=y ++CONFIG_PWM=y ++CONFIG_PWM_MEDIATEK=y ++CONFIG_PWM_SYSFS=y ++CONFIG_QUEUED_RWLOCKS=y ++CONFIG_QUEUED_SPINLOCKS=y ++CONFIG_RAS=y ++CONFIG_RATIONAL=y ++CONFIG_REALTEK_PHY=y ++CONFIG_REED_SOLOMON=y ++CONFIG_REED_SOLOMON_DEC8=y ++CONFIG_REED_SOLOMON_ENC8=y ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_REGULATOR=y ++CONFIG_REGULATOR_FIXED_VOLTAGE=y ++CONFIG_REGULATOR_MT6380=y ++CONFIG_RESET_CONTROLLER=y ++CONFIG_RFS_ACCEL=y ++CONFIG_RODATA_FULL_DEFAULT_ENABLED=y ++CONFIG_RPS=y ++CONFIG_RTC_CLASS=y ++CONFIG_RTC_DRV_MT7622=y ++CONFIG_RTC_I2C_AND_SPI=y ++CONFIG_RTL8367S_GSW=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_SCHED_MC=y ++CONFIG_SCSI=y ++CONFIG_SCSI_COMMON=y ++CONFIG_SERIAL_8250_FSL=y ++CONFIG_SERIAL_8250_MT6577=y ++CONFIG_SERIAL_DEV_BUS=y ++CONFIG_SERIAL_DEV_CTRL_TTYPORT=y ++CONFIG_SERIAL_MCTRL_GPIO=y ++CONFIG_SERIAL_OF_PLATFORM=y ++CONFIG_SGL_ALLOC=y ++CONFIG_SG_POOL=y ++CONFIG_SMP=y ++CONFIG_SOCK_RX_QUEUE_MAPPING=y ++CONFIG_SPARSEMEM=y ++CONFIG_SPARSEMEM_EXTREME=y ++CONFIG_SPARSEMEM_VMEMMAP=y ++CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_SPI=y ++CONFIG_SPI_DYNAMIC=y ++CONFIG_SPI_MASTER=y ++CONFIG_SPI_MEM=y ++CONFIG_SPI_MT65XX=y ++CONFIG_SPI_MTK_NOR=y ++CONFIG_SPI_MTK_SNFI=y ++CONFIG_SRCU=y ++CONFIG_SWCONFIG=y ++CONFIG_SWIOTLB=y ++CONFIG_SWPHY=y ++CONFIG_SYSCTL_EXCEPTION_TRACE=y ++CONFIG_SYSVIPC_COMPAT=y ++CONFIG_THERMAL=y ++CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y ++CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 ++CONFIG_THERMAL_EMULATION=y ++CONFIG_THERMAL_GOV_BANG_BANG=y ++CONFIG_THERMAL_GOV_FAIR_SHARE=y ++CONFIG_THERMAL_GOV_STEP_WISE=y ++CONFIG_THERMAL_GOV_USER_SPACE=y ++CONFIG_THERMAL_OF=y ++CONFIG_THERMAL_WRITABLE_TRIPS=y ++CONFIG_THREAD_INFO_IN_TASK=y ++CONFIG_TICK_CPU_ACCOUNTING=y ++CONFIG_TIMER_OF=y ++CONFIG_TIMER_PROBE=y ++CONFIG_TREE_RCU=y ++CONFIG_TREE_SRCU=y ++CONFIG_UBIFS_FS=y ++CONFIG_USB=y ++CONFIG_USB_COMMON=y ++CONFIG_USB_SUPPORT=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_MTK=y ++CONFIG_VMAP_STACK=y ++CONFIG_WATCHDOG_CORE=y ++CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y ++CONFIG_WATCHDOG_PRETIMEOUT_GOV=y ++CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y ++CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m ++CONFIG_WATCHDOG_SYSFS=y ++CONFIG_XPS=y ++CONFIG_XXHASH=y ++CONFIG_ZLIB_DEFLATE=y ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZONE_DMA32=y ++CONFIG_ZSTD_COMPRESS=y ++CONFIG_ZSTD_DECOMPRESS=y ++ ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_DEVTMPFS_SAFE=y ++ ++CONFIG_REGULATOR_RT5190A=y ++CONFIG_RESET_TI_SYSCON=y ++CONFIG_REGMAP_I2C=y ++CONFIG_MTK_LVTS_THERMAL=y ++CONFIG_PHY_MTK_XSPHY=y ++CONFIG_NVMEM_MTK_EFUSE=y ++ ++ ++CONFIG_WLAN_VENDOR_MEDIATEK=y ++CONFIG_CFG80211=m ++CONFIG_CFG80211_WEXT=y ++CONFIG_MAC80211=y ++CONFIG_MAC80211_LEDS=y ++CONFIG_MT7996E=m ++ ++CONFIG_VFAT_FS=y ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_CODEPAGE_852=y ++CONFIG_NLS_ISO8859_1=y ++CONFIG_NLS_ISO8859_15=y ++ ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_STORAGE=y ++CONFIG_I2C_GPIO=y ++CONFIG_SFP=y ++CONFIG_BLK_DEV_NVME=y ++CONFIG_NVME_HWMON=y ++ ++#CONFIG_USB_USBNET=m ++#CONFIG_USB_SERIAL=m ++#CONFIG_USB_SERIAL_OPTION=m ++#CONFIG_USB_SERIAL_QUALCOMM=m ++#CONFIG_USB_NET_CDC_MBIM=m ++#CONFIG_USB_NET_QMI_WWAN=m ++ ++#CONFIG_NVMEM_MTK_EFUSE=y ++#CONFIG_SENSORS_PWM_FAN=y ++ ++CONFIG_DUMMY=m ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++CONFIG_IP_PNP_RARP=y ++CONFIG_IPV6_ROUTER_PREF=y ++CONFIG_IPV6_OPTIMISTIC_DAD=y ++CONFIG_INET6_AH=m ++CONFIG_INET6_ESP=m ++CONFIG_INET6_IPCOMP=m ++CONFIG_IPV6_MIP6=m ++CONFIG_IPV6_TUNNEL=m ++CONFIG_IPV6_MULTIPLE_TABLES=y ++CONFIG_NETLINK_DIAG=y ++CONFIG_INET_UDP_DIAG=m ++CONFIG_NET_IPIP=m ++CONFIG_IP_MROUTE=y ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++CONFIG_IPV6=y ++CONFIG_NETFILTER=y ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_IPV4=m ++CONFIG_NF_CONNTRACK_IPV6=m ++CONFIG_NETFILTER_NETLINK=m ++CONFIG_NF_CT_NETLINK=m ++CONFIG_IP_NF_IPTABLES=m ++CONFIG_NF_LOG_IPV4=m ++CONFIG_NF_REJECT_IPV4=m ++CONFIG_IP6_NF_IPTABLES=m ++CONFIG_NF_LOG_IPV6=m ++CONFIG_NF_REJECT_IPV6=m ++CONFIG_IP_NF_NAT=m ++CONFIG_IP6_NF_NAT=m ++CONFIG_NF_NAT_MASQUERADE_IPV4=y ++CONFIG_NF_NAT_MASQUERADE_IPV6=y ++CONFIG_IP_NF_FILTER=m ++CONFIG_IP6_NF_FILTER=m ++CONFIG_IP_NF_TARGET_MASQUERADE=m ++CONFIG_IP6_NF_TARGET_MASQUERADE=m ++CONFIG_IP_NF_MANGLE=m ++CONFIG_IP6_NF_MANGLE=m ++CONFIG_IP_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_MATCH_RT=m ++CONFIG_NETFILTER_SYNPROXY=m ++CONFIG_IP_NF_TARGET_SYNPROXY=m ++CONFIG_IP6_NF_TARGET_SYNPROXY=m ++CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m ++CONFIG_NETFILTER_XT_MATCH_LIMIT=m ++CONFIG_NETFILTER_XT_MATCH_STATE=m ++CONFIG_NETFILTER_XT_TARGET_LOG=m ++CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m ++CONFIG_NETFILTER_XT_MATCH_MAC=m ++CONFIG_NETFILTER_XT_MATCH_RECENT=m ++CONFIG_NETFILTER_XT_MATCH_IPRANGE=m ++CONFIG_NETFILTER_XT_MARK=m ++CONFIG_NETFILTER_XT_CONNMARK=m ++CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m ++CONFIG_IP_VS=m ++CONFIG_NETFILTER_XT_MATCH_IPVS=m ++CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m ++#CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m ++CONFIG_NF_TABLES=m ++CONFIG_NF_TABLES_SET=m ++CONFIG_NF_TPROXY_IPV4=m ++CONFIG_NF_TPROXY_IPV6=m ++CONFIG_NFT_NUMGEN=m ++CONFIG_NFT_CT=m ++CONFIG_NFT_COUNTER=m ++CONFIG_NFT_CONNLIMIT=m ++CONFIG_NFT_LOG=m ++CONFIG_NFT_LIMIT=m ++CONFIG_NFT_MASQ=m ++CONFIG_NFT_NAT=m ++CONFIG_NFT_QUEUE=m ++CONFIG_NFT_REDIR=m ++CONFIG_NFT_TUNNEL=m ++CONFIG_NFT_OBJREF=m ++CONFIG_NFT_QUOTA=m ++CONFIG_NFT_REJECT=m ++CONFIG_NFT_COMPAT=m ++CONFIG_NFT_HASH=m ++CONFIG_NFT_XFRM=m ++CONFIG_NFT_SOCKET=m ++CONFIG_NFT_OSF=m ++CONFIG_NFT_TPROXY=m ++CONFIG_NFT_SYNPROXY=m ++CONFIG_NFTL=m ++CONFIG_NFTL_RW=y ++CONFIG_NFT_FIB_INET=m ++CONFIG_NFT_FIB_IPV4=m ++CONFIG_NFT_FIB_IPV6=m ++CONFIG_NF_FLOW_TABLE=m ++CONFIG_NF_FLOW_TABLE_INET=m ++CONFIG_NF_FLOW_TABLE_IPV4=m ++CONFIG_NF_FLOW_TABLE_IPV6=m ++CONFIG_NFT_FLOW_OFFLOAD=m ++CONFIG_NF_CONNTRACK_FTP=m ++CONFIG_NF_NAT_FTP=m ++CONFIG_PPP=m ++CONFIG_PPPOE=m ++CONFIG_PPP_DEFLATE=m ++CONFIG_PPP_MPPE=m ++CONFIG_VETH=m ++CONFIG_TUN=m ++CONFIG_VLAN_8021Q_GVRP=y ++CONFIG_VLAN_8021Q_MVRP=y ++CONFIG_NET_L3_MASTER_DEV=y ++CONFIG_IPVLAN=m ++CONFIG_IFB=m ++CONFIG_MACVLAN=m ++CONFIG_NET_CLS_ACT=y ++# QoS and/or fair queueing ++CONFIG_NET_SCH_CBQ=m ++CONFIG_NET_SCH_HTB=m ++CONFIG_NET_SCH_CSZ=m ++CONFIG_NET_SCH_PRIO=m ++CONFIG_NET_SCH_RED=m ++CONFIG_NET_SCH_SFQ=m ++CONFIG_NET_SCH_TEQL=m ++CONFIG_NET_SCH_TBF=m ++CONFIG_NET_SCH_GRED=m ++CONFIG_NET_SCH_DSMARK=m ++CONFIG_NET_SCH_INGRESS=m ++#CONFIG_NET_SCH_NETEM=m ++CONFIG_NET_QOS=y ++CONFIG_NET_ESTIMATOR=y ++CONFIG_NET_CLS_TCINDEX=m ++CONFIG_NET_CLS_ROUTE4=m ++CONFIG_NET_CLS_ROUTE=y ++CONFIG_NET_CLS_FW=m ++CONFIG_NET_CLS_U32=m ++CONFIG_NET_CLS_RSVP=m ++CONFIG_NET_CLS_RSVP6=m ++CONFIG_NET_CLS_POLICE=y ++ ++CONFIG_NET_ACT_VLAN=m ++CONFIG_NET_ACT_POLICE=m ++CONFIG_NET_ACT_GACT=m ++CONFIG_NET_ACT_MIRRED=m ++CONFIG_NET_ACT_SAMPLE=y ++CONFIG_NET_ACT_IPT=m ++CONFIG_NET_ACT_NAT=m ++CONFIG_NET_ACT_PEDIT=m ++CONFIG_NET_ACT_SIMP=m ++CONFIG_NET_ACT_SKBEDIT=m ++CONFIG_NET_ACT_CSUM=m ++# CONFIG_NET_ACT_BPF is not set ++CONFIG_NET_ACT_CONNMARK=m ++CONFIG_NET_ACT_CTINFO=m ++CONFIG_NET_ACT_SKBMOD=m ++# CONFIG_NET_ACT_IFE is not set ++CONFIG_NET_ACT_TUNNEL_KEY=m ++CONFIG_NET_ACT_CT=m ++# CONFIG_NET_ACT_GATE is not set ++ ++#NFS Client ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_SWAP=y ++CONFIG_NFS_V4_1=y ++CONFIG_NFS_V4_2=y ++CONFIG_PNFS_FILE_LAYOUT=m ++CONFIG_PNFS_BLOCK=m ++CONFIG_PNFS_FLEXFILE_LAYOUT=m ++CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org" ++CONFIG_NFS_V4_1_MIGRATION=y ++CONFIG_NFS_USE_LEGACY_DNS=y ++CONFIG_ROOT_NFS=y ++ ++#NFS Server ++CONFIG_NFSD=m ++CONFIG_NFSD_V2_ACL=y ++CONFIG_NFSD_V3_ACL=y ++CONFIG_NFSD_V4=y ++CONFIG_NFSD_PNFS=y ++CONFIG_NFSD_BLOCKLAYOUT=y ++CONFIG_NFSD_SCSILAYOUT=y ++CONFIG_NFSD_FLEXFILELAYOUT=y ++CONFIG_NFSD_FAULT_INJECTION=y ++CONFIG_NFS_ACL_SUPPORT=m ++ ++#usb-tethering ++CONFIG_USB_USBNET=m ++CONFIG_USB_NET_CDCETHER=m ++CONFIG_USB_NET_CDC_EEM=m ++CONFIG_USB_NET_RNDIS_HOST=m ++ ++#for lxc ++CONFIG_CGROUPS=y ++CONFIG_NAMESPACES=y ++CONFIG_USER_NS=y ++CONFIG_MEMCG=y ++CONFIG_CGROUP_CPUACCT=y ++CONFIG_CGROUP_DEVICE=y ++CONFIG_CGROUP_SCHED=y ++CONFIG_CPUSETS=y ++CONFIG_UNIX_DIAG=m ++CONFIG_PACKET_DIAG=m ++CONFIG_FUSE_FS=m ++ ++#for docker ++CONFIG_CGROUP_FREEZER=y ++CONFIG_MEMCG_SWAP=y ++CONFIG_MEMCG_SWAP_ENABLED=y ++CONFIG_BLK_CGROUP=y ++CONFIG_CFS_BANDWIDTH=y ++CONFIG_RT_GROUP_SCHED=y ++CONFIG_CGROUP_PIDS=y ++CONFIG_CGROUP_PERF=y ++CONFIG_CGROUP_NET_CLASSID=y ++CONFIG_CGROUP_NET_PRIO=y ++CONFIG_CGROUP_BPF=y ++CONFIG_CFQ_GROUP_IOSCHED=y ++CONFIG_POSIX_MQUEUE=y ++CONFIG_POSIX_MQUEUE_SYSCTL=y ++CONFIG_HAVE_ARCH_SECCOMP_FILTER=y ++CONFIG_SECCOMP_FILTER=y ++CONFIG_SECCOMP=y ++ ++CONFIG_I2C_MUX=y ++CONFIG_I2C_MUX_PCA954x=y ++ ++CONFIG_PCS_MTK_USXGMII=y ++ ++CONFIG_MT7915E=m ++CONFIG_MT798X_WMAC=y ++CONFIG_PHY_MTK_XFI_TPHY=y ++CONFIG_RTC_DRV_PCF8563=y ++CONFIG_EEPROM_AT24=y ++CONFIG_SENSORS_PWM_FAN=y ++ ++#add some 4G/5G modem options ++CONFIG_USB_ACM=m ++CONFIG_USB_SERIAL=m ++CONFIG_USB_SERIAL_OPTION=m ++CONFIG_USB_SERIAL_QUALCOMM=m ++CONFIG_USB_NET_QMI_WWAN=m ++CONFIG_USB_CDNS_SUPPORT=m ++CONFIG_USB_CDNS3=m ++CONFIG_WWAN=m ++CONFIG_MHI_BUS=m ++CONFIG_MHI_NET=m ++CONFIG_MHI_WWAN_CTRL=m ++CONFIG_MHI_WWAN_MBIM=m ++CONFIG_MTK_T7XX=m ++ ++CONFIG_MARVELL_PHY=m ++CONFIG_MARVELL_10G_PHY=m ++CONFIG_MEDIATEK_2P5GE_PHY=m ++#spi display ++#CONFIG_DRM=m ++#CONFIG_FB=m ++#CONFIG_FB_MODE_HELPERS=y ++#CONFIG_DRM_PANEL_MIPI_DBI=m ++#CONFIG_BACKLIGHT_PWM=m +diff --git a/bpi-r4.its b/bpi-r4.its +new file mode 100644 +index 000000000000..4c10360895a7 +--- /dev/null ++++ b/bpi-r4.its +@@ -0,0 +1,112 @@ ++/dts-v1/; ++ ++/ { ++ description = "U-Boot fitImage for bpi-r4 aarch64 kernel"; ++ #address-cells = <1>; ++ ++ images { ++ kernel-1 { ++ description = "Linux Kernel %version%"; ++ data = /incbin/("./arch/arm64/boot/Image.gz"); ++ type = "kernel"; ++ arch = "arm64"; ++ os = "linux"; ++ compression = "gzip"; ++ load = <0x44000000>; ++ entry = <0x44000000>; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ }; ++ fdt-base { ++ description = "Flattened Device Tree blob"; ++ data = /incbin/("./arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtb"); ++ type = "flat_dt"; ++ arch = "arm64"; ++ load = <0x47000000>; ++ compression = "none"; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ }; ++ fdt-base-2g5 { ++ description = "Flattened Device Tree blob"; ++ data = /incbin/("./arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-2g5.dtb"); ++ type = "flat_dt"; ++ arch = "arm64"; ++ load = <0x47000000>; ++ compression = "none"; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ }; ++ fdt-ov-sd { ++ description = "Flattened Device Tree blob"; ++ data = /incbin/("./arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-sd.dtbo"); ++ type = "flat_dt"; ++ }; ++ fdt-ov-emmc { ++ description = "Flattened Device Tree blob"; ++ data = /incbin/("./arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-emmc.dtbo"); ++ type = "flat_dt"; ++ }; ++/* ramdisk-1 { ++ description = "ramdisk"; ++ data = /incbin/("./rootfs_arm64.cpio.gz"); ++ type = "ramdisk"; ++ arch = "arm64"; ++ os = "linux"; ++ compression = "gzip"; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ };*/ ++ }; ++ configurations { ++ default = "conf-sd"; ++ conf-base { ++ description = "Boot Linux kernel with base FDT blob"; ++ kernel = "kernel-1"; ++ fdt = "fdt-base"; ++ //ramdisk = "ramdisk-1"; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ }; ++ conf-base-2g5 { ++ description = "Boot Linux kernel with base FDT blob"; ++ kernel = "kernel-1"; ++ fdt = "fdt-base-2g5"; ++ //ramdisk = "ramdisk-1"; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ }; ++ conf-sd { ++ description = "Boot Linux kernel with SD FDT blob"; ++ kernel = "kernel-1"; ++ fdt = "fdt-base", "fdt-ov-sd"; ++ //ramdisk = "ramdisk-1"; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ }; ++ conf-emmc { ++ description = "Boot Linux kernel with EMMC FDT blob"; ++ kernel = "kernel-1"; ++ fdt = "fdt-base", "fdt-ov-emmc"; ++ //ramdisk = "ramdisk-1"; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ }; ++ ov-sd { ++ description = "SD FDT overlay blob"; ++ fdt = "fdt-ov-sd"; ++ }; ++ ov-emmc { ++ description = "EMMC FDT overlay blob"; ++ fdt = "fdt-ov-emmc"; ++ }; ++ }; ++}; +diff --git a/build.conf b/build.conf +new file mode 100644 +index 000000000000..60d7ff7a4859 +--- /dev/null ++++ b/build.conf +@@ -0,0 +1,27 @@ ++uploaduser=$USER ++uploadserver=r2 ++uploaddir=/var/lib/tftp ++#uploaduser=root ++#uploadserver=192.168.0.11 ++#uploaddir=/boot/bananapi/bpi-r2/linux ++ ++builddir=../build ++ramdisksize=8G ++#numproc=8 ++ ++board=bpi-r2 ++#board=bpi-r64 ++#board=bpi-r2pro ++#board=bpi-r3 ++board=bpi-r4 ++ ++#r64 with rtl8367 ++#boardversion=v0.1 ++#r2pro with rtl8367 ++#boardversion=v00 ++ ++#mainline uboot for r64 (old ATF) needs 64bit uImage ++#uimagearch=arm64 ++ ++#grep whitelist filter for adding modules to initramfs ++ownmodules='mt76\|bluetooth' +diff --git a/build.sh b/build.sh +new file mode 100755 +index 000000000000..ee71e488bb7c +--- /dev/null ++++ b/build.sh +@@ -0,0 +1,1273 @@ ++#!/bin/bash ++if [[ $UID -eq 0 ]]; ++then ++ echo "do not run as root!" ++ exit 1; ++fi ++ ++numproc=$(grep ^processor /proc/cpuinfo | wc -l) ++ ++. build.conf ++ ++r64newswver=1.0 ++if [[ -z "$board" ]];then board="bpi-r2";fi ++ ++kernver=$(make kernelversion | grep -v 'make') ++#echo $kernver ++ ++DOTCONFIG=".config" ++ ++clr_red=$'\e[1;31m' ++clr_green=$'\e[1;32m' ++clr_yellow=$'\e[1;33m' ++clr_blue=$'\e[1;34m' ++clr_reset=$'\e[0m' ++ ++DEFCONFIG="" ++DTS="" ++DTSI="" ++ ++case $board in ++ "bpi-r2pro") ++ ARCH=arm64 ++ CONFIGPATH=arch/$ARCH/configs ++ DEFCONFIG=$CONFIGPATH/rk3568_bpi-r2p_defconfig ++ DEFCONFIG=$CONFIGPATH/quartz64_defconfig ++ if [[ "$boardversion" == "v00" ]];then ++ DTS=arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro-rtl8367.dts ++ else ++ DTS=arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts ++ fi ++ DTSI=arch/arm64/boot/dts/rockchip/rk356x.dtsi ++ ;; ++ "bpi-r64") ++ ARCH=arm64 ++ CONFIGPATH=arch/$ARCH/configs ++ DEFCONFIG=$CONFIGPATH/mt7622_bpi-r64_defconfig ++ if [[ "$boardversion" == "v0.1" ]];then ++ DTS=arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64-rtl8367.dts ++ else ++ DTS=arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++ fi ++ DTSI=arch/arm64/boot/dts/mediatek/mt7622.dtsi ++ ;; ++ "bpi-r3") ++ ARCH=arm64 ++ CONFIGPATH=arch/$ARCH/configs ++ DEFCONFIG=$CONFIGPATH/mt7986a_bpi-r3_defconfig ++ DTS=arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts ++ #DTS=arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-sd.dts ++ DTSI=arch/arm64/boot/dts/mediatek/mt7986a.dtsi ++ ;; ++ "bpi-r4") ++ ARCH=arm64 ++ CONFIGPATH=arch/$ARCH/configs ++ DEFCONFIG=$CONFIGPATH/mt7988a_bpi-r4_defconfig ++ DTS=arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dts ++ DTSI=arch/arm64/boot/dts/mediatek/mt7988a.dtsi ++ ;; ++ *) #bpir2 ++ ARCH=arm ++ CONFIGPATH=arch/$ARCH/configs ++ DEFCONFIG=$CONFIGPATH/mt7623n_evb_fwu_defconfig ++ DTS=arch/arm/boot/dts/mediatek/mt7623n-bananapi-bpi-r2.dts ++ DTSI=arch/arm/boot/dts/mediatek/mt7623.dtsi ++ ;; ++esac ++#echo "DTB:${DTS%.*}.dtb" ++export ARCH=$ARCH; ++ ++#defconfig-override ++if [[ "$1" =~ ^(importconfig|defconfig)$ && -n "$2" ]]; ++then ++ if [[ -e "${CONFIGPATH}/${2}_defconfig" ]];then ++ echo "using defconfig ${2}_defconfig" ++ DEFCONFIG="${CONFIGPATH}/${2}_defconfig" ++ else ++ echo "defconfig ${2}_defconfig not found!" ++ fi ++fi ++ ++#Check Crosscompile ++crosscompile=0 ++hostarch=$(uname -m) #r64:aarch64 r2: armv7l ++ ++if [[ ! $hostarch =~ aarch64|armv ]];then ++ if [[ "$ARCH" == "arm64" ]]; then ++ if [[ -z "$(which aarch64-linux-gnu-gcc)" ]];then echo "please install gcc-aarch64-linux-gnu";exit 1;fi ++ export CROSS_COMPILE='ccache aarch64-linux-gnu-' ++ elif [[ "$ARCH" == "arm" ]]; then ++ if [[ -z "$(which arm-linux-gnueabihf-gcc)" ]];then echo "please install gcc-arm-linux-gnueabihf";exit 1;fi ++ export CROSS_COMPILE='ccache arm-linux-gnueabihf-' ++ fi ++ ++ crosscompile=1 ++fi; ++ ++#if [[ "$builddir" != "" && ! "$1" =~ ^(updatesrc|uenv|defconfig|dts.?|[u]?mount)$ ]]; ++if [[ "$builddir" != "" ]]; ++then ++ if [[ "$1" == "importconfig" ]]; ++ then ++ KBUILD_OUTPUT= make mrproper ++ fi ++ if [[ ! "$builddir" =~ ^/ ]] || [[ "$builddir" == "/" ]];then ++ #make it absolute ++ builddir=$(realpath $(pwd)"/"$builddir) ++# echo "absolute: $builddir" ++ fi ++ ++ mkdir -p $builddir ++ ++ if [[ "$ramdisksize" != "" ]]; ++ then ++ mount | grep '\s'$builddir'\s' &>/dev/null #$?=0 found;1 not found ++ if [[ $? -ne 0 ]];then ++ #make sure directory is clean for mounting ++ if [[ "$(ls -A $builddir)" ]];then ++ rm -rf $builddir/* ++ fi ++ if [[ "$1" == "importconfig" ]]; ++ then ++ echo "mounting tmpfs for building..." ++ sudo mount -t tmpfs -o size=$ramdisksize none $builddir ++ fi ++ fi ++ fi ++ ++ #if builddir is empty then run make mrproper to clean up sourcedir ++ if [[ ! "$(ls -A $builddir)" ]];then make mrproper;fi ++ ++ if ! [[ "$1" =~ "updatesrc" ]];then ++ DOTCONFIG="$builddir/$DOTCONFIG" ++ export KBUILD_OUTPUT=$builddir ++ fi ++fi ++ ++function edit() ++{ ++ file=$1 ++ if [[ -z "$EDITOR" ]];then EDITOR=/usr/bin/editor;fi #use alternatives setting ++ if [[ -e "$file" ]];then ++ if [[ -w "$file" ]];then ++ $EDITOR "$file" ++ else ++ echo "file $file not writable by user using sudo..." ++ sudo $EDITOR "$file" ++ fi ++ else ++ echo "file $file not found" ++ fi ++} ++ ++#Check Dependencies ++ ++function check_dep() ++{ ++ PACKAGE_Error=0 ++ ++ grep -i 'ubuntu\|debian' /etc/issue &>/dev/null ++ if [[ $? -ne 0 ]];then ++ echo "depency-check currently only on debian/ubuntu..." ++ return 0; ++ fi ++ PACKAGES=$(dpkg -l | awk '{print $2}') ++ ++ NEEDED_PKGS="make" ++ ++ #echo "needed: $NEEDED_PKGS" ++ ++ if [[ $# -ge 1 ]]; ++ then ++ if [[ $@ =~ "build" ]];then ++ NEEDED_PKGS+=" u-boot-tools bc gcc libc6-dev libncurses-dev ccache libssl-dev" ++ fi ++ if [[ $@ =~ "deb" ]];then ++ NEEDED_PKGS+=" fakeroot" ++ fi ++ fi ++ ++ echo "needed: $NEEDED_PKGS" ++ for package in $NEEDED_PKGS; do ++ #TESTPKG=$(dpkg -l |grep "\s${package}") ++ TESTPKG=$(echo "$PACKAGES" |grep "^${package}") ++ if [[ -z "${TESTPKG}" ]];then echo "please install ${package}";PACKAGE_Error=1;fi ++ done ++ if [ ${PACKAGE_Error} == 1 ]; then return 1; fi ++ return 0; ++} ++ ++function getuenvpath { ++ if [[ $crosscompile -ne 0 ]];then ++ uenv_base=/media/${USER}/BPI-BOOT/ ++ else ++ uenv_base=/boot/ ++ fi ++ if [[ -d $uenv_base ]];then ++ if [[ "$board" == "bpi-r2" || "$board" == "bpi-r64" ]];then ++ #r2/r64 uboot: ${bpi}/${board}/${service}/${bootenv} ++ uenv=${uenv_base}/bananapi/$board/linux/uEnv.txt ++ else ++ uenv=${uenv_base}/uEnv.txt ++ fi ++ if [[ ! -e $uenv ]];then ++ mkdir -p $(dirname ${uenv}) ++ fi ++ fi ++ echo $uenv ++} ++ ++function get_version() ++{ ++ echo "generate branch vars..." ++ #kernbranch=$(git rev-parse --abbrev-ref HEAD) ++ ++ echo "getting git branch: " ++ #find branches with actual commit and filter out detached head ++ commit=$(git log -n 1 --pretty='%h') ++ branches=$(git branch --contains $commit | grep -v '(HEAD') ++ echo "$branches" ++ ++ kernbranch=$(echo "$branches" | grep '^*') #look for marked branch (local) ++ if [[ "$kernbranch" == "" ]];then #no marked branch (travis) ++ kernbranch=$(echo "$branches" | head -1) #use first one ++ fi ++ #kernbranch=$(git branch --contains $(git log -n 1 --pretty='%h') | grep '^*' | grep -v '(HEAD' | head -1 | sed 's/^..//') ++ kernbranch=$(echo "$kernbranch" | sed 's/^..//') ++ kernbranch=${kernbranch//frank-w_/} ++ #if no branch is selected (e.g. bisect) ++ if [[ "${kernbranch}" =~ ^\(.* ]]; then ++ kernbranch="-$commit"; ++ fi ++ ++ gitbranch=$(echo $kernbranch|sed 's/^[456]\.[0-9]\+//'|sed 's/-rc$//') ++ ++ echo "kernbranch:$kernbranch,gitbranch:$gitbranch" ++} ++ ++function get_r64_switch ++{ ++ grep 'RTL8367S_GSW=y' $DOTCONFIG &>/dev/null ++ if [[ $? -eq 0 ]];then ++ echo "rtl8367" ++ else ++ grep 'MT753X_GSW=y' $DOTCONFIG &>/dev/null ++ if [[ $? -eq 0 ]];then ++ echo "mt7531" ++ else ++ echo "" ++ fi ++ fi ++} ++ ++function increase_kernel { ++ #echo $kernver ++ old_IFS=$IFS ++ IFS='.' ++ read -ra KV <<< "$kernver" ++ IFS=',' ++ newkernver=${KV[0]}"."${KV[1]}"."$(( ${KV[2]} +1 )) ++ echo $newkernver ++} ++ ++function disable_option() { ++ echo "disable $1" ++ if [[ "$1" == "" ]];then echo "option missing ($1)";return;fi ++ #CFG=RTL8367S_GSW; ++ CFG=${1^^}; ++ CFG=${CFG//CONFIG_/} ++ #echo "CFG:$CFG" ++ #grep -i 'mt753x\|rtl8367' .config ++ grep $CFG .config ++ if [[ $? -eq 0 ]]; then ++ sed -i 's:CONFIG_'$CFG'=y:# CONFIG_'$CFG' is not set:g' $DOTCONFIG ++ grep $CFG $DOTCONFIG ++ else ++ echo "option CONFIG_$CFG not found in .config" ++ fi ++} ++ ++function update_kernel_source { ++ changedfiles=$(git diff --name-only) ++ if [[ -z "$changedfiles" ]]; then ++ git fetch stable ++ ret=$? ++ if [[ $ret -eq 0 ]];then ++ newkernver=$(increase_kernel) ++ kernmajorver=$(make kernelversion | sed -e 's/\.[0-9]\+$//') ++ maxkernver=$(git for-each-ref --sort=-taggerdate --count=1 refs/tags/v${kernmajorver}.*| sed 's/^.*refs\/tags\/v//') ++ echo "newkernver:$newkernver (max:$maxkernver)" ++ git merge --no-edit v$newkernver ++ elif [[ $ret -eq 128 ]];then ++ #repo not found ++ git remote add stable https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git ++ fi ++ else ++ echo "please first commit/stash modified files: $changedfiles" ++ fi ++} ++ ++function changelog() { ++ get_version >/dev/null ++ lasttag=$(curl -s "https://api.github.com/repos/frank-w/BPI-R2-4.14/releases?per_page=100" | jq -r '[.[] | select(.tag_name|contains("'${kernbranch}'"))][0]' | grep "tag_name" | sed 's/.*: "\(.*\)",/\1/') ++ echo "changes since $lasttag:" ++ git log --pretty=format:"%h %ad %s %d" --date=short $lasttag..HEAD ++} ++ ++function pack { ++ get_version ++ #if [[ "$board" == "bpi-r64" ]];then ++ # switch=$(get_r64_switch)"_" ++ #fi ++ prepare_SD ++ echo "pack..." ++ olddir=$(pwd) ++ cd ../SD ++ fname=${board}_${switch}${kernver}${gitbranch}.tar.gz ++ tar -cz --owner=root --group=root -f $fname BPI-BOOT BPI-ROOT ++ md5sum $fname > $fname.md5 ++ ls -lh $(pwd)"/"$fname ++ cd $olddir ++} ++ ++function pack_debs { ++ get_version ++ echo "pack linux-headers, linux-image, linux-libc-dev debs..." ++ echo "LOCALVERSION=${gitbranch} board=$board ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE" ++ LOCALVERSION="${gitbranch}" board="$board" KDEB_COMPRESS=gzip make bindeb-pkg ++ if [[ $? -ne 0 ]];then exit 1;fi; ++ ls ../*.deb ++} ++ ++ ++function upload { ++ get_version ++ ++ DTBFILE=${DTS%.*}.dtb ++ echo "using ${DTBFILE}..." ++ bindir=""; ++ if [[ -n "$builddir" ]];then bindir="$builddir/"; fi ++ ++ b=${board//bpi/} ++ if [[ "${gitbranch}" =~ "${b}" ]]; then ++ b="" ++ fi ++ ++ imagename="${kernver}${gitbranch}${b}" ++ read -e -i $imagename -p "Kernel-filename: " input ++ imagename="${input:-$imagename}" ++ ++ echo "Name: $imagename" ++ ++ if [[ "$board" == "bpi-r2" ]];then ++ imagename="uImage_$imagename" ++ else ++ read -e -i y -p "upload fit? " fitupload ++ if [[ "$fitupload" == "y" ]]; ++ then ++ imagename="${imagename}.itb" ++ echo "uploading fit as $imagename" ++ else ++ dtbname="${kernver}${b}${gitbranch}.dtb" ++ read -e -i $dtbname -p "dtb-filename: " input ++ dtbname="${input:-$dtbname}" ++ echo "DTB Name: $dtbname" ++ fi ++ fi ++ ++ echo "DTB Name: $dtbname" ++ echo "uploading to ${uploadserver}:${uploaddir}..." ++ ++ if [[ "$board" == "bpi-r2" ]];then ++ scp uImage ${uploaduser}@${uploadserver}:${uploaddir}/${imagename} ++ else ++ if [[ "$fitupload" == "y" ]]; ++ then ++ scp ${board}.itb ${uploaduser}@${uploadserver}:${uploaddir}/${imagename} ++ else ++ scp uImage_nodt ${uploaduser}@${uploadserver}:${uploaddir}/${imagename} ++ scp ${bindir}${DTBFILE} ${uploaduser}@${uploadserver}:${uploaddir}/${dtbname} ++ fi ++ fi ++} ++ ++function install ++{ ++ get_version ++ ++ DTBFILE=${DTS%.*}.dtb ++ echo "using ${DTBFILE}..." ++ bindir=""; ++ if [[ -n "$builddir" ]];then bindir="$builddir/"; fi ++ ++ imagename="${kernver}${gitbranch}" ++ if [[ "$board" == "bpi-r2pro" ]];then ++ $0 mount ++ fi ++ read -e -i $imagename -p "Image-filename: " input ++ imagename="${input:-$imagename}" ++ ++ echo "Name: $imagename" ++ ++ if [[ $crosscompile -eq 0 ]]; then ++ kerneldir="/boot/bananapi/$board/linux" ++ kernelfile="$kerneldir/$imagename" ++ if [[ -d "$kerneldir" ]];then ++ if [[ -e "$kernelfile" ]];then ++ echo "backup of kernel: $kernelfile.bak" ++ sudo cp "$kernelfile" "$kernelfile.bak" ++ fi ++ echo "installing new kernel..." ++ sudo cp ./uImage "$kernelfile" ++ sudo make modules_install ++ else ++ echo "Kernel directory not found...is /boot mounted?" ++ fi ++ else ++ itbinput=n ++ imginput=n ++ read -p "Press [enter] to copy data to SD-Card..." ++ if [[ -d /media/$USER/BPI-BOOT ]]; then ++ ++ targetdir=/media/$USER/BPI-BOOT ++ if [[ "$board" == "bpi-r2" || "$board" == "bpi-r64" ]];then ++ targetdir=/media/$USER/BPI-BOOT/bananapi/$board/linux ++ fi ++ mkdir -p $targetdir ++ kernelfile=$targetdir/$imagename ++ ++ dtinput=n ++ ndtinput=y ++ imginput=y ++ if [[ -e ${board}.its ]];then ++ read -e -i "y" -p "install FIT kernel (itb) [yn]? " itbinput ++ if [[ "$itbinput" == "y" ]];then ++ itbname=${imagename}.itb ++ itbfile=$targetdir/$itbname ++ if [[ -e $itbfile ]];then ++ echo "backup of kernel: $itbfile.bak" ++ cp $itbfile $itbfile.bak ++ fi ++ echo "copy new kernel" ++ cp ./${board}.itb $itbfile ++ if [[ $? -ne 0 ]];then exit 1;fi ++ ndtinput=n ++ imginput=n ++ fi ++ else ++ read -e -i "y" -p "install kernel with DT [yn]? " dtinput ++ if [[ "$dtinput" == "y" ]];then ++ if [[ -e $kernelfile ]];then ++ echo "backup of kernel: $kernelfile.bak" ++ cp $kernelfile $kernelfile.bak ++ fi ++ echo "copy new kernel" ++ cp ./uImage $kernelfile ++ if [[ $? -ne 0 ]];then exit 1;fi ++ fi ++ ++ ndt="n" ++ if [ "$dtinput" != "y" ];then ndt="y"; fi ++ read -e -i "$ndt" -p "install kernel with separate DT [yn]? " ndtinput ++ ndtsuffix="_nodt" ++ fi ++ ++ if [[ "$board" == "bpi-r2pro" ]];then ++ targetdir=/media/$USER/BPI-BOOT/extlinux ++ read -e -i "$imginput" -p "install img kernel (img.gz) [yn]? " imginput ++ if [[ "$imginput" == "y" ]];then ++ dtbname=${imgname}.dtb ++ imgname=${imagename}.gz ++ imgfile=$targetdir/$imgname ++ if [[ -e ${imgfile} ]];then ++ echo "backup of kernel: $imgfile.bak" ++ cp ${imgfile} ${imgfile}.bak ++ fi ++ echo "copy new kernel" ++ set -x ++ cp ${bindir}arch/arm64/boot/Image.gz $imgfile ++ cp ${bindir}${DTBFILE} ${targetdir}/${dtbname} ++ set +x ++ if [[ $? -ne 0 ]];then exit 1;fi ++ ndtinput=n ++ fi ++ fi ++ if [[ "$ndtinput" == "y" ]];then ++ if [[ -e ${kernelfile}${ndtsuffix} ]];then ++ echo "backup of kernel: $kernelfile.bak" ++ cp ${kernelfile}${ndtsuffix} ${kernelfile}${ndtsuffix}.bak ++ fi ++ echo "copy new nodt kernel" ++ cp ./uImage_nodt ${kernelfile}${ndtsuffix} ++ if [[ $? -ne 0 ]];then exit 1;fi ++ mkdir -p $targetdir/dtb ++ dtbname=${kernver}${gitbranch}.dtb ++ read -e -i $dtbname -p "dtb-filename: " input ++ dtbname="${input:-$dtbname}" ++ echo "DTB Name: $dtbname" ++ ++ dtbfile=$targetdir/dtb/${dtbname} ++ if [[ -e $dtbfile ]];then ++ echo "backup of dtb: $dtbfile.bak" ++ cp $dtbfile $dtbfile.bak ++ fi ++ echo "copy new dtb" ++ cp ${bindir}${DTBFILE} $dtbfile ++ fi ++ ++ if [[ "$dtinput" == "y" ]] || [[ "$ndtinput" == "y" ]] || [[ "$itbinput" == "y" ]] || [[ "$imginput" == "y" ]];then ++ echo "copy modules (root needed because of ext-fs permission)" ++ export INSTALL_MOD_PATH=/media/$USER/BPI-ROOT/; ++ echo "INSTALL_MOD_PATH: $INSTALL_MOD_PATH" ++ sudo make ARCH=$ARCH INSTALL_MOD_PATH=$INSTALL_MOD_PATH KBUILD_OUTPUT=$KBUILD_OUTPUT modules_install ++ ++ echo "uImage:" ++ if [[ "$itbinput" == "y" ]];then ++ echo "${itbfile}" ++ fi ++ if [[ "$dtinput" == "y" ]];then ++ echo "${kernelfile}" ++ fi ++ if [[ "$ndtinput" == "y" ]];then ++ echo "${kernelfile}${ndtsuffix}" ++ echo "DTB: ${dtbfile}" ++ fi ++ ++ kernelname=$(ls -1t $INSTALL_MOD_PATH"/lib/modules" | head -n 1) ++ EXTRA_MODULE_PATH=$INSTALL_MOD_PATH"/lib/modules/"$kernelname"/kernel/extras" ++ #echo $kernelname" - "${EXTRA_MODULE_PATH} ++ CRYPTODEV="utils/cryptodev/cryptodev-linux/cryptodev.ko" ++ if [ -e "${CRYPTODEV}" ]; then ++ echo Copy CryptoDev ++ sudo mkdir -p "${EXTRA_MODULE_PATH}" ++ sudo cp "${CRYPTODEV}" "${EXTRA_MODULE_PATH}" ++ #Build Module Dependencies ++ sudo /sbin/depmod -b $INSTALL_MOD_PATH ${kernelname} ++ fi ++ ++ #sudo cp -r ../mod/lib/modules /media/$USER/BPI-ROOT/lib/ ++ if [[ -n "$(grep 'CONFIG_MT76=' $DOTCONFIG)" ]];then ++ echo "MT76 set,don't forget the firmware-files..."; ++ fi ++ else ++ echo "install of modules skipped because no kernel was installed"; ++ fi ++ ++ echo "syncing sd-card...this will take a while" ++ echo "run 'watch -n 1 grep -e Dirty: /proc/meminfo' to show progress" ++ sync ++ ++ uenv=$(getuenvpath) ++ echo "using bootfile $uenv" ++ openuenv=n ++ ++ if [[ -e "$uenv" ]];then ++ echo "by default this kernel-/dtb-file will be loaded (kernel-var in uEnv.txt):" ++ if [[ "$itbinput" == "y" ]];then ++ curkernel=$(grep '^fit=' $uenv|tail -1| sed 's/fit=//') ++ else ++ curkernel=$(grep '^kernel=' $uenv|tail -1| sed 's/kernel=//') ++ curfdt=$(grep '^fdt=' $uenv|tail -1| sed 's/fdt=//') ++ fi ++ echo "kernel: " $curkernel ++ echo "dtb: " $curfdt ++ if [[ "$curkernel" == "${imagename}" || "$curkernel" == "${imagename}${ndtsuffix}" || "$curkernel" == "${itbname}" ]];then ++ echo "no change needed!" ++ openuenv=n ++ else ++ echo "change needed to boot new kernel (kernel=${imagename}/fit=${itbname})!" ++ openuenv=y ++ fi ++ else ++ echo "no bootconfig...change needed to boot new kernel (kernel=${imagename}/fit=${itbname})!" ++ openuenv=y ++ fi ++ ++ read -e -i "$openuenv" -p "open boot config file (uEnv/extlinux.conf) [yn]? " input ++ if [[ "$input" == "y" ]];then ++ $0 uenv ++ fi ++ ++ read -e -i "y" -p "umount SD card [yn]? " input ++ if [[ "$input" == "y" ]];then ++ $0 umount ++ fi ++ else ++ echo "SD-Card not found!" ++ fi ++ fi ++} ++ ++function install_modules { ++ echo "cleaning up modules" ++ rm -r $(pwd)/mod/* 2> /dev/null ++ mkdir $(pwd)/mod ++ echo "building and installing modules" ++# export LOCALVERSION="${gitbranch}" ++# #MAKEFLAGS="V=1" ++# make ${MAKEFLAGS} ${CFLAGS} modules ++ build ++ INSTALL_MOD_PATH=$(pwd)/mod make modules_install ++} ++ ++function mod2initrd { ++ size=$(du -s mod | awk '{ print $1}') #65580 working ++ echo $size ++ if [[ $size -eq 0 ]]; ++ then ++ install_modules ++ fi ++ #first reset initrd ++ echo "reset initramfs..." ++ git checkout utils/buildroot/rootfs_${board}.cpio.gz ++ ls -lh utils/buildroot/rootfs_${board}.cpio.gz ++ ( ++ echo "adding modules to initramfs..." ++ cd mod ++ #need to create dirs and common files first ++ find . -not -iname '*.ko' > mod.lst ++ if [[ "$ownmodules" != "" ]];then ++ find . | grep $ownmodules >> mod.lst ++ fi ++ cat mod.lst | cpio -H newc -o | gzip >> ../utils/buildroot/rootfs_${board}.cpio.gz ++ #to show whats inside cpio: ++ #gunzip -c < ../utils/buildroot/rootfs_${board}.cpio.gz | while LANG=C cpio -itv 2>/dev/null; do :; done| grep lib/modules ++ ls -lh ../utils/buildroot/rootfs_${board}.cpio.gz ++ ) ++ initrdsize=$(ls -l --block-size=M utils/buildroot/rootfs_bpi-r2.cpio.gz | awk '{print $5}' | sed 's/M$//') ++ if [[ $initrdsize -lt 100 ]]; #lower than 40MB leaves 10MB for kernel uImage ++ then ++ echo "re-building kernel with initramfs... ($DOTCONFIG)" ++ OWNCONFIGS="CONFIG_INITRAMFS_SOURCE=\"utils/buildroot/rootfs_${board}.cpio.gz\" CONFIG_INITRAMFS_FORCE=y" ++ build ++ installchoice ++ else ++ echo "kernel with initrd may exceed uboot limit of ~100MB (Bad Data CRC)" ++ fi ++} ++ ++function deb { ++#set -x ++ check_dep "deb" ++ if [[ $? -ne 0 ]];then exit 1;fi ++ get_version ++ ver=${kernver}-${board}${gitbranch} ++ uimagename=uImage_${kernver}${gitbranch} ++ echo "deb package ${ver}" ++ prepare_SD ++ boardv=${board:4} ++ targetdir=debian/bananapi-$boardv-image ++ ++# cd ../SD ++# fname=bpi-r2_${kernver}_${gitbranch}.tar.gz ++# tar -cz --owner=root --group=root -f $fname BPI-BOOT BPI-ROOT ++ ++ rm -rf $targetdir/boot/bananapi/$board/linux/* ++ rm -rf $targetdir/lib/modules/* ++ mkdir -p $targetdir/boot/bananapi/$board/linux/dtb/ ++ mkdir -p $targetdir/lib/modules/ ++ mkdir -p $targetdir/DEBIAN/ ++ ++ #sudo mount --bind ../SD/BPI-ROOT/lib/modules debian/bananapi-r2-image/lib/modules/ ++ if [[ -e ./uImage || -e ./uImage_nodt ]] && [[ -d ../SD/BPI-ROOT/lib/modules/${ver} ]]; then ++ if [[ -e ./uImage ]];then ++ cp ./uImage $targetdir/boot/bananapi/$board/linux/${uimagename} ++ fi ++ if [[ -e ./uImage_nodt && -e ./$board.dtb ]];then ++ cp ./uImage_nodt $targetdir/boot/bananapi/$board/linux/${uimagename}_nodt ++ cp ./$board.dtb $targetdir/boot/bananapi/$board/linux/dtb/$board-${kernver}${gitbranch}.dtb ++ fi ++# pwd ++ cp -r ../SD/BPI-ROOT/lib/modules/${ver} $targetdir/lib/modules/ ++ #rm debian/bananapi-r2-image/lib/modules/${ver}/{build,source} ++ #mkdir debian/bananapi-r2-image/lib/modules/${ver}/kernel/extras ++ #cp cryptodev-linux/cryptodev.ko debian/bananapi-r2-image/lib/modules/${ver}/kernel/extra ++ cat > $targetdir/DEBIAN/preinst << EOF ++#!/bin/bash ++clr_red=\$'\e[1;31m' ++clr_green=\$'\e[1;32m' ++clr_yellow=\$'\e[1;33m' ++clr_blue=\$'\e[1;34m' ++clr_reset=\$'\e[0m' ++m=\$(mount | grep '/boot[^/]') ++if [[ -z "\$m" ]]; ++then ++ echo "\${clr_red}/boot needs to be mountpoint for /dev/mmcblk0p1\${clr_reset}"; ++ exit 1; ++fi ++kernelfile=/boot/bananapi/$board/linux/${uimagename} ++if [[ -e "\${kernelfile}" ]];then ++ echo "\${clr_red}\${kernelfile} already exists\${clr_reset}" ++ echo "\${clr_red}please remove/rename it or uninstall previous installed kernel-package\${clr_reset}" ++ exit 2; ++fi ++EOF ++ chmod +x $targetdir/DEBIAN/preinst ++ cat > $targetdir/DEBIAN/postinst << EOF ++#!/bin/bash ++clr_red=\$'\e[1;31m' ++clr_green=\$'\e[1;32m' ++clr_yellow=\$'\e[1;33m' ++clr_blue=\$'\e[1;34m' ++clr_reset=\$'\e[0m' ++case "\$1" in ++ configure) ++ #install|upgrade) ++ echo "kernel=${uimagename}">>/boot/bananapi/$board/linux/uEnv.txt ++ ++ #check for non-dsa-kernel (4.4.x) ++ kernver=\$(uname -r) ++ if [[ "\${kernver:0:3}" == "4.4" ]]; ++ then ++ echo "\${clr_yellow}you are upgrading from kernel 4.4.\${clr_reset}"; ++ echo "\${clr_yellow}Please make sure your network-config (/etc/network/interfaces) matches dsa-driver\${clr_reset}"; ++ echo "\${clr_yellow}(bring cpu-ports ethx up, ip-configuration to wan/lanx)\${clr_reset}"; ++ fi ++ ;; ++ *) echo "unhandled \$1 in postinst-script" ++esac ++EOF ++ chmod +x $targetdir/DEBIAN/postinst ++ cat > $targetdir/DEBIAN/postrm << EOF ++#!/bin/bash ++case "\$1" in ++ abort-install) ++ echo "installation aborted" ++ ;; ++ remove|purge) ++ if [[ -e /boot/bananapi/$board/linux/uEnv.txt ]];then ++ cp /boot/bananapi/$board/linux/uEnv.txt /boot/bananapi/$board/linux/uEnv.txt.bak ++ grep -v ${uimagename} /boot/bananapi/$board/linux/uEnv.txt.bak > /boot/bananapi/$board/linux/uEnv.txt ++ else ++ cp /boot/uEnv.txt /boot/uEnv.txt.bak ++ grep -v ${uimagename} /boot/uEnv.txt.bak > /boot/uEnv.txt ++ fi ++ ;; ++esac ++EOF ++ chmod +x $targetdir/DEBIAN/postrm ++ if [[ "$board" == "bpi-r2" ]];then ++ debarch=armhf ++ else ++ debarch=arm64 ++ fi ++ ++ cat > $targetdir/DEBIAN/control << EOF ++Package: bananapi-$boardv-image-${kernbranch} ++Version: ${kernver}-1 ++Section: custom ++Priority: optional ++Architecture: $debarch ++Multi-Arch: no ++Essential: no ++Maintainer: Frank Wunderlich ++Description: ${BOARD^^} linux image ${ver} ++EOF ++ cd debian ++ fakeroot dpkg-deb --build bananapi-$boardv-image ../debian ++ cd .. ++ ls -lh debian/*.deb ++ debfile=debian/bananapi-$boardv-image-${kernbranch,,}_${kernver}-1_$debarch.deb ++ dpkg -c $debfile ++ ++ dpkg -I $debfile ++ else ++ echo "First build kernel ${ver}" ++ echo "eg: ./build" ++ fi ++} ++ ++function build { ++ echo Cleanup Kernel Build ++ rm arch/arm/boot/zImage 2>/dev/null ++ rm arch/arm/boot/zImage-dtb 2>/dev/null ++ rm arch/arm64/boot/Image 2>/dev/null ++ rm ./uImage* 2>/dev/null ++ rm ${board}.dtb 2>/dev/null ++ ++ check_dep "build" ++ if [[ $? -ne 0 ]];then exit 1;fi ++ ++ get_version ++ ++ if [ -e $DOTCONFIG ]; then ++ exec 3> >(tee build.log) ++ export LOCALVERSION="${gitbranch}" ++ #MAKEFLAGS="V=1" ++ export DTC_FLAGS="-@" ++ make ${MAKEFLAGS} ${CFLAGS} ${OWNCONFIGS} 2>&3 ++ ret=$? ++ exec 3>&- ++ ++ if [[ $ret == 0 ]]; then ++ if [[ -z "${uimagearch}" ]];then uimagearch=arm;fi ++ ++ DTBFILE=${DTS%.*}.dtb ++ case "$board" in ++ "bpi-r2pro") ++ IMAGE=arch/arm64/boot/Image ++ LADDR=0x7f000001 ++ ENTRY=0x7f000001 ++ ;; ++ "bpi-r64") ++ IMAGE=arch/arm64/boot/Image ++ LADDR=40080000 ++ ENTRY=40080000 ++ ;; ++ "bpi-r3") ++ IMAGE=arch/arm64/boot/Image ++ LADDR=40080000 ++ ENTRY=40080000 ++ if [[ -e mt7986a-bananapi-bpi-r3-nor.dts ]];then ++ echo "compiling r3 dt overlays" ++ #dtc -O dtb -o bpi-r3-nor.dtbo mt7986a-bananapi-bpi-r3-nor.dts ++ #dtc -O dtb -o bpi-r3-nand.dtbo mt7986a-bananapi-bpi-r3-nand.dts ++ fi ++ ;; ++ "bpi-r4") ++ IMAGE=arch/arm64/boot/Image ++ LADDR=40080000 ++ ENTRY=40080000 ++ ;; ++ "bpi-r2") ++ IMAGE=arch/arm/boot/zImage ++ LADDR=80008000 ++ ENTRY=80008000 ++ ;; ++ esac ++ ++ if [[ "$builddir" != "" ]]; ++ then ++ cp $builddir/${IMAGE%.*}* ${IMAGE%/*} ++ DTBBASE=${DTBFILE%.*} ++ if [[ -e $builddir/${DTBBASE}.dtb ]];then ++ cp $builddir/${DTBBASE}*.dtb ${DTBFILE%/*} ++ cp $builddir/$DTBFILE $board.dtb ++ fi ++ if [[ -e $builddir/${DTBBASE}-sd.dtbo ]];then ++ cp $builddir/${DTBBASE}-*.dtbo ${DTBFILE%/*} ++ fi ++ elif [[ -e $DTBFILE ]];then ++ cp $DTBFILE $board.dtb ++ fi ++ ++ #if [[ "$board" == "bpi-r2pro" ]];then ++ # #skipping mkimage causes no choice, but uImage is not bootable on r2pro ++ # mkimage -A ${uimagearch} -O linux -T kernel -C none -a $LADDR -e $ENTRY -n "Linux Kernel $kernver$gitbranch" -d $IMAGE ./uImage_nodt ++ if [[ -e ${board}.its ]];then #"$board" == "bpi-r64" || "$board" == "bpi-r3" ]];then ++ mkimage -A ${uimagearch} -O linux -T kernel -C none -a $LADDR -e $ENTRY -n "Linux Kernel $kernver$gitbranch" -d $IMAGE ./uImage_nodt ++ sed "s/%version%/$kernver$gitbranch/" ${board}.its > ${board}.its.tmp ++ mkimage -f ${board}.its.tmp ${board}.itb ++ cp ${board}.itb ${board}-$kernver$gitbranch.itb ++ rm ${board}.its.tmp ++ else ++ cat $IMAGE $DTBFILE > arch/arm/boot/zImage-dtb ++ mkimage -A arm -O linux -T kernel -C none -a $LADDR -e $ENTRY -n "Linux Kernel $kernver$gitbranch" -d arch/arm/boot/zImage-dtb ./uImage ++ ++ echo "build uImage without appended DTB..." ++ export DTC_FLAGS="-@ --space 32768" ++ make ${CFLAGS} CONFIG_ARM_APPENDED_DTB=n &>/dev/null #output/errors can be ignored because they are printed before ++ ret=$? ++ if [[ $ret == 0 ]]; then ++ mkimage -A arm -O linux -T kernel -C none -a $LADDR -e $ENTRY -n "Linux Kernel $kernver$gitbranch" -d $IMAGE ./uImage_nodt ++ fi ++ fi ++ ++ if [[ "$builddir" != "" ]]; ++ then ++ if [[ -e uImage ]];then ++ cp {,$builddir/}uImage ++ fi ++ cp {,$builddir/}uImage_nodt ++ if [[ -e ${board}.itb ]];then ++ cp {,$builddir/}${board}.itb ++ fi ++ fi ++ fi ++ else ++ echo "No Configfile found, Please Configure Kernel" ++ fi ++ return $ret ++} ++ ++function prepare_SD { ++ SD=../SD ++ cd $(dirname $0) ++ mkdir -p ../SD >/dev/null 2>/dev/null ++ ++ echo "cleanup..." ++ for toDel in "$SD/BPI-BOOT/" "$SD/BPI-ROOT/"; do ++ rm -r ${toDel} 2>/dev/null ++ done ++ ++ echo "copy..." ++ ++ bindir=""; ++ if [[ -n "$builddir" ]];then bindir="$builddir/"; fi ++ ++ export INSTALL_MOD_PATH=$SD/BPI-ROOT/; ++ echo "INSTALL_MOD_PATH: $INSTALL_MOD_PATH" ++ kerndir="$SD/BPI-BOOT" ++ fdtdir=$kerndir ++ if [[ "$board" == "bpi-r2pro" ]];then ++ mkdir -p $kerndir/extlinux/ ++ cp ${bindir}arch/arm64/boot/Image.gz $kerndir/extlinux/ ++ cp ./$board.dtb $kerndir/extlinux/$board.dtb ++ else ++ if [[ "$board" =~ bpi-r2|bpi-r64 ]];then ++ kerndir=$SD/BPI-BOOT/bananapi/$board/linux ++ fdtdir="$kerndir/dtb" ++ fi ++ for createDir in "$kerndir" "$fdtdir" "$SD/BPI-ROOT/lib/modules" "$SD/BPI-ROOT/lib/firmware"; do ++ mkdir -p ${createDir} >/dev/null 2>/dev/null ++ done ++ if [[ -e ./uImage ]];then ++ cp ./uImage $kerndir/uImage ++ fi ++ if [[ -e ./uImage_nodt ]];then ++ cp ./uImage_nodt $kerndir/uImage_nodt ++ cp ./$board.dtb $fdtdir/$board.dtb ++ fi ++ fi ++ if [[ -e ./$board.itb ]];then ++ cp ./$board.itb $kerndir/$board.itb ++ fi ++ make modules_install ++ ++ #Add CryptoDev Module if exists or Blacklist ++ CRYPTODEV="utils/cryptodev/cryptodev-linux/cryptodev.ko" ++ mkdir -p "${INSTALL_MOD_PATH}/etc/modules-load.d" ++ mkdir -p "${INSTALL_MOD_PATH}/etc/modprobe.d" ++ ++ LOCALVERSION=$(find ../SD/BPI-ROOT/lib/modules/* -maxdepth 0 -type d |rev|cut -d"/" -f1 | rev) ++ EXTRA_MODUL_PATH="${SD}/BPI-ROOT/lib/modules/${LOCALVERSION}/kernel/extras" ++ if [ -e "${CRYPTODEV}" ]; then ++ echo Copy CryptoDev ++ mkdir -p "${EXTRA_MODUL_PATH}" ++ cp "${CRYPTODEV}" "${EXTRA_MODUL_PATH}" ++ #Load Cryptodev on BOOT ++ echo "cryptodev" >${INSTALL_MOD_PATH}/etc/modules-load.d/cryptodev.conf ++ ++ #Build Module Dependencies ++ /sbin/depmod -b "${SD}/BPI-ROOT/" ${LOCALVERSION} ++ else ++ #Blacklist Cryptodev Module ++ echo "blacklist cryptodev" >${INSTALL_MOD_PATH}/etc/modprobe.d/cryptodev.conf ++ fi ++ ++ if [[ -n "$(grep 'CONFIG_MT76=' $DOTCONFIG)" ]];then ++ echo "MT76 set, including the firmware-files..."; ++ cp drivers/net/wireless/mediatek/mt76/firmware/* $SD/BPI-ROOT/lib/firmware/ ++ fi ++ ++ if [[ "$board" == "bpi-r64" ]];then ++ mkdir -p $SD/BPI-ROOT/lib/firmware/mediatek ++ cp utils/firmware/mediatek/mt7622* $SD/BPI-ROOT/lib/firmware/mediatek/ ++ fi ++} ++ ++function installchoice ++{ ++ if [ -e "./uImage" ] || [ -e "./uImage_nodt" ]; then ++ echo "===========================================" ++ echo "1) pack" ++ if [[ $crosscompile -eq 0 ]];then ++ echo "2) install to System" ++ else ++ echo "2) install to SD-Card" ++ fi; ++ echo "3) deb-package" ++ echo "4) upload" ++ read -n1 -p "choice [1234]:" choice ++ echo ++ if [[ "$choice" == "1" ]]; then ++ $0 pack ++ elif [[ "$choice" == "2" ]];then ++ $0 install ++ elif [[ "$choice" == "3" ]];then ++ $0 deb ++ elif [[ "$choice" == "4" ]];then ++ $0 upload ++ else ++ echo "wrong option: $choice" ++ fi ++ fi ++} ++ ++function release ++{ ++ lc=$(git log -n 1 --pretty=format:'%s') ++ reltag="Release_${kernver}" ++ if [[ ${lc} =~ ^Merge ]]; ++ then ++ echo Merge; ++ else ++ echo "normal commit"; ++ lc=${lc//[^a-zA-Z0-9]/_} ++ reltag="${reltag}_${lc}" ++ fi ++ echo "RelTag:"$reltag ++ if [[ -z "$(git tag -l $reltag)" ]]; then ++ git tag $reltag ++ git push origin $reltag ++ else ++ echo "Tag already used, please use another" ++ fi ++} ++ ++#Test if the Kernel is there ++if [ -n "$kernver" ]; then ++ action=$1 ++ file=$2 ++ LANG=C ++ CFLAGS=-j${numproc} ++ ++ #echo $action ++ ++ case "$action" in ++ "checkdep") ++ echo "checking depencies..." ++ check_dep "build"; ++ if [[ $? -eq 0 ]];then echo "OK";else echo "failed";fi ++ ;; ++ "changelog") ++ echo "print changelog from last release of branch" ++ changelog ++ ;; ++ "changelog_file") ++ echo "write changelog from last release of branch to file" ++ changelog > changelog.txt ++ ;; ++ "reset") ++ echo "Reset Git" ++ ##Reset Git ++ git reset --hard HEAD ++ #call self and Import Config ++ $0 importconfig ++ ;; ++ ++ "update") ++ echo "Update Git Repo" ++ git pull ++ ;; ++ ++ "updatesrc") ++ echo "Update kernel source" ++ update_kernel_source ++ ;; ++ ++ "mount") ++ mount | grep "BPI-BOOT" > /dev/null ++ if [[ $? -ne 0 ]];then ++ udisksctl mount -b /dev/disk/by-label/BPI-BOOT ++ fi ++ mount | grep "BPI-ROOT" > /dev/null ++ if [[ $? -ne 0 ]];then ++ udisksctl mount -b /dev/disk/by-label/BPI-ROOT ++ fi ++ ;; ++ ++ "umount") ++ echo "umount SD Media" ++ dev=$(mount | grep BPI-ROOT | head -1 | sed -e 's/[0-9] .*$/?/' | sort -u) ++ echo "$dev" ++ if [[ ! -z "$dev" ]];then ++ umount $dev ++ fi ++ ;; ++ ++ "uenv") ++ echo "edit uEnv.txt on sd-card" ++ uenv=$(getuenvpath) ++ if [[ -n "$uenv" ]];then ++ edit $uenv ++ else ++ echo "uenv.txt not found" ++ fi ++ ;; ++ ++ "lskernel") ++ echo "list kernels on sd-card" ++ ls -lh /media/$USER/BPI-BOOT/bananapi/$board/linux/ ++ echo "available DTBs:" ++ ls -lh /media/$USER/BPI-BOOT/bananapi/$board/linux/dtb ++ ;; ++ ++ "defconfig") ++ echo "edit def config" ++ edit $DEFCONFIG ++ ;; ++ "deb") ++ echo "deb-package (currently testing-state)" ++ deb ++ ;; ++ "dtsi") ++ edit $DTSI ++ ;; ++ ++ "dts") ++ edit $DTS ++ ;; ++ "dtbs_check") ++ make dtbs_check 2>&1 | tee -a dtbs_check.log ++ ;; ++ ++ "importmylconfig") ++ echo "import myl config" ++ make mt7623n_myl_defconfig ++ ;; ++ ++ ++ "importconfig") ++ echo "import a defconfig file" ++ if [[ -e "${DEFCONFIG}" ]];then ++ DEFCONF="${DEFCONFIG##*/}" ++ echo "import $DEFCONF ($DEFCONFIG)" ++ make ${DEFCONF} ++ if [[ -n "$disable" ]];then ++ disable_option "$disable" ++ fi ++ else ++ echo "file ${DEFCONFIG} not found" ++ fi ++ ;; ++ ++ "importfullconfig") ++ echo "import full config" ++ if [[ -e "${DEFCONFIG}" ]];then ++ tmpfile=${DEFCONFIG%/*}/temp_defconfig ++ cat $DEFCONFIG > ${tmpfile} ++ if [[ -e config_generic ]];then ++ echo "append generic config" ++ cat config_generic >> $tmpfile ++ fi ++ if [[ -e config_${board} ]];then ++ echo "append board config" ++ cat config_${board} >> $tmpfile ++ fi ++ make temp_defconfig ++ else ++ echo "file ${DEFCONFIG} not found" ++ fi ++ ;; ++ ++ "ic") ++ echo "menu for multiple conf-files...currently in developement" ++ files=(); ++ i=1; ++ if [[ "$board" == "bpi-r2pro" ]];then ++ p=arch/arm64/configs/ ++ ff=rk3568_bpi-r2p_defconfig ++ elif [[ "$board" == "bpi-r64" ]];then ++ p=arch/arm64/configs/ ++ ff="mt7622*defconfig" ++ else ++ p=arch/arm/configs/ ++ ff="mt7623n*defconfig" ++ fi ++ for f in $(cd $p; ls $ff) ++ do ++ echo "[$i] $f" ++ files+=($f) ++ i=$(($i+1)) ++ done ++ read -n1 -p "choice [1..${#files[@]}]:" choice ++ echo ++ set -x ++ make ${files[$(($choice-1))]} ++ set +x ++ ;; ++ "config") ++ echo "change kernel-configuration (menuconfig)" ++ make menuconfig ++ ;; ++ ++ "pack") ++ echo "Pack Kernel to Archive" ++ pack ++ ;; ++ ++ "pack_debs") ++ echo "Pack Kernel to linux-*.deb" ++ pack_debs ++ ;; ++ ++ "install") ++ echo "Install Kernel to SD Card" ++ install ++ ;; ++ ++ "upload") ++ echo "Upload Kernel to TFTP-Server" ++ upload ++ ;; ++ ++ "build") ++ echo "Build Kernel" ++ echo "building with ${numproc} threads" ++ time build ++ #$0 cryptodev ++ ;; ++ "clean") ++ echo clean ++ make clean ++ if [[ "$builddir" != "" ]];then ++ rm -r $builddir/debian || true; ++ else ++ rm -r debian || true; ++ fi ++ ;; ++ "spidev") ++ echo "Build SPIDEV-Test" ++ ( ++ cd tools/spi; ++ make ++ ) ++ ;; ++ ++ "cryptodev") ++ echo "Build CryptoDev" ++ cdbuildscript=utils/cryptodev/build.sh ++ if [[ -e $cdbuildscript ]];then ++ $cdbuildscript ++ fi ++ ;; ++ ++ "utils") ++ echo "Build utils" ++ ( cd utils; make ) ++ ;; ++ ++ "release") ++ echo "create release tag for travis-ci build" ++ release ++ ;; ++ "all-pack") ++ echo "update repo, create kernel & build archive" ++ $0 update ++ $0 importconfig ++ $0 build ++ #$0 cryptodev ++ $0 pack ++ ;; ++ "install_modules") ++ install_modules ++ ;; ++ "mod2initrd") ++ mod2initrd ++ ;; ++ "help") ++ echo "print help" ++ sed -n -e '/case "$action" in/,/esac/{//!p}' $0 | grep -A1 '")$' | sed -e 's/echo "\(.*\)"/\1/' ++ ;; ++ *) ++ if [[ -n "$action" ]];then ++ echo "unknown command $action"; ++ exit 1; ++ fi; ++ $0 build ++ #$0 cryptodev ++ installchoice ++ ;; ++ esac ++fi +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0007-build.sh-add-additional-build-script-config-defconfi.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0007-build.sh-add-additional-build-script-config-defconfi.patch new file mode 100644 index 0000000000..ac2910f3a1 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0007-build.sh-add-additional-build-script-config-defconfi.patch @@ -0,0 +1,3796 @@ +From 162c49815bc0911957610b77dbdb8fc82fa0c659 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sat, 1 Feb 2025 14:49:06 +0100 +Subject: [PATCH 07/84] build.sh: add additional build-script,config, + defconfigs and fit sources + +--- + arch/arm/configs/mt7623n_evb_fwu_defconfig | 732 +++++++++++ + arch/arm64/configs/mt7622_bpi-r64_defconfig | 523 ++++++++ + arch/arm64/configs/mt7986a_bpi-r3_defconfig | 1265 +++++++++++++++++++ + arch/arm64/configs/quartz64_defconfig | 922 ++++++++++++++ + bpi-r2pro.its | 55 + + bpi-r3.its | 162 +++ + bpi-r64.its | 55 + + build.conf | 2 +- + 8 files changed, 3715 insertions(+), 1 deletion(-) + create mode 100644 arch/arm/configs/mt7623n_evb_fwu_defconfig + create mode 100644 arch/arm64/configs/mt7622_bpi-r64_defconfig + create mode 100644 arch/arm64/configs/mt7986a_bpi-r3_defconfig + create mode 100644 arch/arm64/configs/quartz64_defconfig + create mode 100644 bpi-r2pro.its + create mode 100644 bpi-r3.its + create mode 100644 bpi-r64.its + +diff --git a/arch/arm/configs/mt7623n_evb_fwu_defconfig b/arch/arm/configs/mt7623n_evb_fwu_defconfig +new file mode 100644 +index 000000000000..be9e0b2a691b +--- /dev/null ++++ b/arch/arm/configs/mt7623n_evb_fwu_defconfig +@@ -0,0 +1,732 @@ ++CONFIG_LOCALVERSION="-bpi-r2" ++CONFIG_LOCALVERSION_AUTO=n ++ ++CONFIG_EARLY_PRINTK=y ++ ++#spectre/meltdown ++CONFIG_PAGE_TABLE_ISOLATION=y ++ ++CONFIG_SYSVIPC=y ++CONFIG_IRQ_DOMAIN_DEBUG=y ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_CGROUPS=y ++CONFIG_NAMESPACES=y ++ ++#for lxc ++CONFIG_USER_NS=y ++CONFIG_MEMCG=y ++CONFIG_CGROUP_CPUACCT=y ++CONFIG_CGROUP_DEVICE=y ++CONFIG_CGROUP_SCHED=y ++CONFIG_CPUSETS=y ++#some options for docker ++CONFIG_CGROUP_FREEZER=y ++CONFIG_OVERLAY_FS=y ++CONFIG_MEMCG_SWAP=y ++CONFIG_MEMCG_SWAP_ENABLED=y ++CONFIG_BLK_CGROUP=y ++CONFIG_CFS_BANDWIDTH=y ++CONFIG_RT_GROUP_SCHED=y ++CONFIG_CGROUP_PIDS=y ++CONFIG_CGROUP_PERF=y ++CONFIG_CGROUP_NET_CLASSID=y ++CONFIG_CGROUP_NET_PRIO=y ++CONFIG_CFQ_GROUP_IOSCHED=y ++ ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_KALLSYMS_ALL=y ++CONFIG_EMBEDDED=y ++CONFIG_PERF_EVENTS=y ++CONFIG_MODULES=y ++CONFIG_MODULE_FORCE_LOAD=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_PARTITION_ADVANCED=y ++CONFIG_CMDLINE_PARTITION=y ++CONFIG_ARCH_MEDIATEK=y ++CONFIG_ARM_THUMB=y ++CONFIG_ARM_THUMBEE=y ++CONFIG_ARM_ERRATA_720789=y ++CONFIG_ARM_ERRATA_754322=y ++CONFIG_ARM_ERRATA_754327=y ++CONFIG_ARM_ERRATA_764369=y ++CONFIG_ARM_ERRATA_775420=y ++CONFIG_ARM_ERRATA_798181=y ++ ++CONFIG_PL310_ERRATA_588369=y ++CONFIG_PL310_ERRATA_727915=y ++CONFIG_PL310_ERRATA_753970=y ++CONFIG_PL310_ERRATA_769419=y ++ ++CONFIG_PCI=y ++CONFIG_PCI_MSI=y ++CONFIG_SMP=y ++CONFIG_HAVE_ARM_ARCH_TIMER=y ++CONFIG_NR_CPUS=16 ++CONFIG_AEABI=y ++CONFIG_HIGHMEM=y ++CONFIG_CMA=y ++CONFIG_FORCE_MAX_ZONEORDER=12 ++CONFIG_ARM_APPENDED_DTB=y ++CONFIG_ARM_ATAG_DTB_COMPAT=y ++CONFIG_CMDLINE="earlyprintk console=ttyS0,115200 vmalloc=496M debug=7 no_console_suspend" ++#CONFIG_CMDLINE_FORCE=y ++ ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++ ++CONFIG_KEXEC=y ++ ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_STAT=y ++CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y ++CONFIG_ARM_MEDIATEK_CPUFREQ=y ++ ++CONFIG_VFP=y ++CONFIG_NEON=y ++CONFIG_KERNEL_MODE_NEON=y ++CONFIG_PM_AUTOSLEEP=y ++CONFIG_PM_DEBUG=y ++CONFIG_PM_ADVANCED_DEBUG=y ++CONFIG_APM_EMULATION=y ++ ++CONFIG_NET=y ++CONFIG_DUMMY=m ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_INET=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++CONFIG_IP_PNP_RARP=y ++CONFIG_IPV6_ROUTER_PREF=y ++CONFIG_IPV6_OPTIMISTIC_DAD=y ++CONFIG_INET6_AH=m ++CONFIG_INET6_ESP=m ++CONFIG_INET6_IPCOMP=m ++CONFIG_IPV6_MIP6=m ++CONFIG_IPV6_TUNNEL=m ++CONFIG_IPV6_MULTIPLE_TABLES=y ++CONFIG_BRIDGE=y ++CONFIG_NET_DSA=y ++CONFIG_VLAN_8021Q=y ++CONFIG_NETLINK_DIAG=y ++CONFIG_INET_UDP_DIAG=m ++CONFIG_NET_IPIP=m ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_MROUTE=y ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++ ++#added for lxc ++CONFIG_UNIX_DIAG=m ++CONFIG_PACKET_DIAG=m ++ ++#added for docker ++CONFIG_POSIX_MQUEUE=y ++CONFIG_POSIX_MQUEUE_SYSCTL=y ++CONFIG_HAVE_ARCH_SECCOMP_FILTER=y ++CONFIG_SECCOMP_FILTER=y ++CONFIG_SECCOMP=y ++ ++CONFIG_IPV6=y ++CONFIG_NETFILTER=y ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_IPV4=m ++CONFIG_NF_CONNTRACK_IPV6=m ++CONFIG_NETFILTER_NETLINK=m ++CONFIG_NF_CT_NETLINK=m ++CONFIG_IP_NF_IPTABLES=m ++CONFIG_NF_LOG_IPV4=m ++CONFIG_NF_REJECT_IPV4=m ++CONFIG_IP6_NF_IPTABLES=m ++CONFIG_NF_LOG_IPV6=m ++CONFIG_NF_REJECT_IPV6=m ++CONFIG_IP_NF_NAT=m ++CONFIG_IP6_NF_NAT=m ++CONFIG_NF_NAT_MASQUERADE_IPV4=y ++CONFIG_NF_NAT_MASQUERADE_IPV6=y ++CONFIG_IP_NF_FILTER=m ++CONFIG_IP6_NF_FILTER=m ++CONFIG_IP_NF_TARGET_MASQUERADE=m ++CONFIG_IP6_NF_TARGET_MASQUERADE=m ++CONFIG_IP_NF_MANGLE=m ++CONFIG_IP6_NF_MANGLE=m ++CONFIG_IP_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_MATCH_RT=m ++ ++CONFIG_NETFILTER_SYNPROXY=m ++CONFIG_IP_NF_TARGET_SYNPROXY=m ++CONFIG_IP6_NF_TARGET_SYNPROXY=m ++ ++CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m ++CONFIG_NETFILTER_XT_MATCH_LIMIT=m ++CONFIG_NETFILTER_XT_MATCH_STATE=m ++CONFIG_NETFILTER_XT_TARGET_LOG=m ++CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m ++CONFIG_NETFILTER_XT_MATCH_MAC=m ++CONFIG_NETFILTER_XT_MATCH_RECENT=m ++CONFIG_NETFILTER_XT_MATCH_IPRANGE=m ++CONFIG_NETFILTER_XT_MARK=m ++CONFIG_NETFILTER_XT_CONNMARK=m ++CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m ++CONFIG_IP_VS=m ++CONFIG_NETFILTER_XT_MATCH_IPVS=m ++CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m ++ ++CONFIG_NF_TABLES=m ++CONFIG_NF_TABLES_IPV4=y ++CONFIG_NF_TABLES_IPV6=y ++CONFIG_NF_TABLES_SET=m ++CONFIG_NF_TABLES_INET=y ++CONFIG_NF_TABLES_NETDEV=y ++CONFIG_NF_TPROXY_IPV4=m ++CONFIG_NF_TABLES_ARP=y ++CONFIG_NF_TPROXY_IPV6=m ++CONFIG_NF_TABLES_BRIDGE=m ++CONFIG_NFT_NUMGEN=m ++CONFIG_NFT_CT=m ++CONFIG_NFT_COUNTER=m ++CONFIG_NFT_CONNLIMIT=m ++CONFIG_NFT_LOG=m ++CONFIG_NFT_LIMIT=m ++CONFIG_NFT_MASQ=m ++CONFIG_NFT_NAT=m ++CONFIG_NFT_REDIR=m ++CONFIG_NFT_TUNNEL=m ++CONFIG_NFT_OBJREF=m ++CONFIG_NFT_QUOTA=m ++CONFIG_NFT_REJECT=m ++CONFIG_NFT_COMPAT=m ++CONFIG_NFT_HASH=m ++CONFIG_NFT_XFRM=m ++CONFIG_NFT_SOCKET=m ++CONFIG_NFT_OSF=m ++CONFIG_NFT_TPROXY=m ++CONFIG_NFT_SYNPROXY=m ++CONFIG_NFTL=m ++CONFIG_NFTL_RW=y ++ ++CONFIG_NF_FLOW_TABLE=m ++CONFIG_NF_FLOW_TABLE_INET=m ++CONFIG_NF_FLOW_TABLE_IPV4=m ++CONFIG_NF_FLOW_TABLE_IPV6=m ++CONFIG_NFT_FLOW_OFFLOAD=m ++ ++CONFIG_NET_MEDIATEK_HNAT=m ++CONFIG_DEBUG_SECTION_MISMATCH=y ++ ++#active ftp-support ++CONFIG_NF_CONNTRACK_FTP=m ++CONFIG_NF_NAT_FTP=m ++ ++ ++CONFIG_SYN_COOKIES=y ++ ++CONFIG_PPP=m ++CONFIG_PPPOE=m ++CONFIG_PPP_FILTER=y ++CONFIG_PPP_DEFLATE=m ++CONFIG_PPP_MPPE=m ++ ++#veth for lxc ++CONFIG_VETH=m ++ ++#for systemd ++CONFIG_AF_KCM=y ++CONFIG_CGROUP_BPF=y ++ ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_DMA_CMA=y ++CONFIG_CMA_SIZE_MBYTES=64 ++CONFIG_ARM_CCI400_PMU=y ++CONFIG_MTD=y ++CONFIG_OF_OVERLAY=y ++CONFIG_CONFIGFS_FS=m ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_SRAM=y ++CONFIG_EEPROM_93CX6=y ++CONFIG_IDE=y ++CONFIG_BLK_DEV_SD=y ++CONFIG_ATA=y ++CONFIG_SATA_AHCI=y ++CONFIG_AHCI_MTK=m ++ ++CONFIG_NETDEVICES=y ++CONFIG_NET_DSA_MT7530=y ++CONFIG_NET_VENDOR_MEDIATEK=y ++CONFIG_NET_MEDIATEK_SOC=y ++ ++CONFIG_ICPLUS_PHY=y ++CONFIG_INPUT_EVDEV=y ++#CONFIG_INPUT_EVBUG=m ++CONFIG_KEYBOARD_MATRIX=y ++CONFIG_KEYBOARD_SAMSUNG=y ++CONFIG_KEYBOARD_MTK_PMIC=m ++CONFIG_MOUSE_PS2_ELANTECH=y ++CONFIG_MOUSE_PS2_SENTELIC=y ++CONFIG_INPUT_MOUSEDEV=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++CONFIG_INPUT_TOUCHSCREEN=y ++# CONFIG_SERIO_SERPORT is not set ++CONFIG_VT_HW_CONSOLE_BINDING=y ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_NR_UARTS=4 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=4 ++CONFIG_SERIAL_8250_MT6577=y ++CONFIG_SERIAL_8250_BTIF=y ++CONFIG_HW_RANDOM=y ++CONFIG_I2C=y ++CONFIG_I2C_MT65XX=y ++CONFIG_PINCTRL_MT2701=y ++# CONFIG_PINCTRL_MT6397 is not set ++CONFIG_WATCHDOG=y ++CONFIG_MEDIATEK_WATCHDOG=y ++CONFIG_MFD_MT6397=y ++CONFIG_REGULATOR=y ++CONFIG_REGULATOR_MT6323=y ++CONFIG_REGULATOR_FIXED_VOLTAGE=y ++CONFIG_MEDIA_SUPPORT=y ++CONFIG_MEDIA_RC_SUPPORT=y ++CONFIG_RC_CORE=y ++CONFIG_RC_DEVICES=y ++CONFIG_LIRC=y ++CONFIG_IR_MTK=y ++CONFIG_RC_DECODERS=y ++CONFIG_IR_NEC_DECODER=m ++CONFIG_IR_RC5_DECODER=m ++CONFIG_IR_RC6_DECODER=m ++CONFIG_IR_JVC_DECODER=m ++CONFIG_IR_SONY_DECODER=m ++CONFIG_IR_SHARP_DECODER=m ++CONFIG_IR_SANYO_DECODER=m ++CONFIG_IR_RCMM_DECODER=m ++CONFIG_IR_XMP_DECODER=m ++CONFIG_MMC=y ++CONFIG_MMC_MTK=y ++CONFIG_NEW_LEDS=y ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_MT6323=y ++CONFIG_LEDS_GPIO=y ++CONFIG_LEDS_PCA963X=y ++CONFIG_LEDS_TRIGGERS=y ++CONFIG_LEDS_TRIGGER_TIMER=y ++CONFIG_LEDS_TRIGGER_ONESHOT=y ++CONFIG_LEDS_TRIGGER_HEARTBEAT=y ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y ++CONFIG_DMADEVICES=y ++CONFIG_DMATEST=m ++CONFIG_COMMON_CLK_MT2701_HIFSYS=y ++CONFIG_COMMON_CLK_MT2701_ETHSYS=y ++CONFIG_ARM_TIMER_SP804=y ++CONFIG_MTK_IOMMU_V1=y ++CONFIG_MTK_PMIC_WRAP=y ++CONFIG_IIO=y ++CONFIG_RESET_CONTROLLER=y ++CONFIG_PHY_MT65XX_USB3=y ++CONFIG_PSTORE=y ++CONFIG_PSTORE_CONSOLE=y ++CONFIG_PSTORE_PMSG=y ++CONFIG_PSTORE_FTRACE=y ++CONFIG_PSTORE_RAM=y ++CONFIG_PRINTK_TIME=y ++CONFIG_DYNAMIC_DEBUG=y ++CONFIG_DEBUG_INFO=y ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_DETECT_HUNG_TASK=y ++CONFIG_DEBUG_LIST=y ++CONFIG_FUNCTION_TRACER=y ++CONFIG_FTRACE_SYSCALLS=y ++CONFIG_FUNCTION_PROFILER=y ++CONFIG_DEBUG_LL=y ++CONFIG_DEBUG_UART_PHYS=0x11002000 ++CONFIG_DEBUG_UART_VIRT=0xf1002000 ++CONFIG_KEYS=y ++CONFIG_CRYPTO_RSA=y ++CONFIG_CRYPTO_CCM=m ++CONFIG_CRYPTO_GCM=m ++CONFIG_CRYPTO_ECB=m ++CONFIG_CRYPTO_CMAC=m ++CONFIG_CRYPTO_ARC4=m ++CONFIG_CRYPTO_DEFLATE=y ++CONFIG_CRYPTO_LZO=y ++CONFIG_CRC_CCITT=m ++CONFIG_CRC_ITU_T=m ++CONFIG_CRYPTO_DEV_MEDIATEK=y ++ ++#ARM Accelerated Cryptographic Algorithms ++CONFIG_ARM_CRYPTO=y ++CONFIG_CRYPTO_SHA1_ARM=m ++CONFIG_CRYPTO_SHA1_ARM_NEON=m ++CONFIG_CRYPTO_SHA1_ARM_CE=m ++CONFIG_CRYPTO_SHA2_ARM_CE=m ++CONFIG_CRYPTO_SHA512_ARM=m ++CONFIG_CRYPTO_AES_ARM=m ++CONFIG_CRYPTO_AES_ARM_BS=m ++CONFIG_CRYPTO_AES_ARM_CE=m ++CONFIG_CRYPTO_GHASH_ARM_CE=m ++CONFIG_CRYPTO_CRC32_ARM_CE=m ++CONFIG_CRYPTO_CHACHA20_NEON=m ++ ++#LVM ++CONFIG_MD=y ++CONFIG_BLK_DEV_DM=y ++CONFIG_DM_BUFIO=y ++CONFIG_DM_CRYPT=y ++CONFIG_DM_SNAPSHOT=y ++CONFIG_DM_MIRROR=y ++CONFIG_DM_MULTIPATH=y ++CONFIG_DM_MULTIPATH_QL=y ++CONFIG_DM_MULTIPATH_ST=y ++CONFIG_DM_THIN_PROVISIONING=m ++CONFIG_DAX=y ++CONFIG_CRYPTO_CBC=y ++ ++#RAID ++CONFIG_DM_RAID=y ++CONFIG_MD_RAID0=y ++CONFIG_MD_RAID1=y ++CONFIG_MD_RAID10=y ++CONFIG_MD_RAID456=y ++ ++#RamFS ++#CONFIG_INITRAMFS_SOURCE="../rootfs_ttys0_rng.cpio.gz" ++#CONFIG_INITRAMFS_SOURCE="../initramfs.cpio" ++#CONFIG_INITRAMFS_FORCE=y ++ ++#Filesystem ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++CONFIG_AUTOFS4_FS=y ++CONFIG_FUSE_FS=m ++CONFIG_MSDOS_FS=m ++CONFIG_VFAT_FS=y ++CONFIG_NTFS_FS=m ++CONFIG_TMPFS=y ++CONFIG_TMPFS_POSIX_ACL=y ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_ISO8859_1=y ++CONFIG_NLS_UTF8=y ++CONFIG_CIFS=m ++CONFIG_F2FS_FS=m ++CONFIG_BTRFS_FS=m ++CONFIG_SQUASHFS=m ++ ++#GPIO ++CONFIG_DEBUG_FS=y ++CONFIG_DEBUG_GPIO=y ++CONFIG_GPIO_SYSFS=y ++ ++#wlan ++CONFIG_MAC80211=y ++CONFIG_MAC80211_MESH=y ++CONFIG_CFG80211=m ++ ++#internal wlan (not working yet) ++# CONFIG_MTK_CONN_LTE_IDC_SUPPORT is not set ++CONFIG_MTK_COMBO=y ++CONFIG_MTK_COMBO_CHIP_CONSYS_7623=y ++#used in 4.4, but should be set in Kconfig by selecting mt7623 COMBO ++#CONFIG_MTK_PLATFORM="mt7623" ++ ++CONFIG_MTK_COMBO_COMM=y ++CONFIG_MTK_COMBO_WIFI=y ++CONFIG_NL80211_TESTMODE=y ++ ++#internal Bluetooth (also not working yet) ++CONFIG_BT=y ++CONFIG_MTK_COMBO_BT=m ++CONFIG_MTK_COMBO_BT_HCI=y ++#needed for BT? ++#Bluetooth Classic (BR/EDR) features ++CONFIG_BT_BREDR=y ++#Bluetooth High Speed (HS) features ++CONFIG_BT_HS=y ++#Bluetooth Low Energy (LE) features ++CONFIG_BT_LE=y ++#Export Bluetooth internals in debugfs ++CONFIG_BT_DEBUGFS=y ++CONFIG_BT_RFCOMM=m ++CONFIG_BT_RFCOMM_TTY=y ++CONFIG_BT_HIDP=m ++CONFIG_BT_BNEP=m ++ ++#to run bluetoothd rfkill needed ++CONFIG_RFKILL=y ++CONFIG_RFKILL_LEDS=y ++CONFIG_RFKILL_INPUT=y ++CONFIG_RFKILL_GPIO=y ++ ++#if you use a mt76x2 or mt76x3 pcie-card ++CONFIG_MT76x2E=m ++CONFIG_MT7615E=m ++CONFIG_MT7915E=m ++ ++#pcie ++CONFIG_PCIEPORTBUS=y ++CONFIG_PCIE_MEDIATEK=y ++CONFIG_PHY_MTK_TPHY=y ++ ++CONFIG_I2C_CHARDEV=m ++CONFIG_RTC_CLASS=y ++CONFIG_RTC_DRV_DS1307=m ++CONFIG_RTC_DRV_DS1307_CENTURY=y ++CONFIG_RTC_DRV_MT6397=y ++ ++CONFIG_SPI=y ++CONFIG_SPI_MASTER=y ++CONFIG_SPI_SPIDEV=m ++CONFIG_SPI_MT65XX=m ++ ++CONFIG_PWM=y ++CONFIG_PWM_MEDIATEK=m ++ ++#Temperature sensor driver for mediatek SoCs ++CONFIG_MEDIATEK_MT6577_AUXADC=y ++CONFIG_THERMAL=y ++CONFIG_MTK_THERMAL=y ++CONFIG_MTK_EFUSE=y ++CONFIG_HWMON=y ++CONFIG_THERMAL_HWMON=y ++CONFIG_CPU_THERMAL=y ++ ++#HDMI ++CONFIG_DRM=y ++CONFIG_DRM_ARM=y ++CONFIG_DRM_MALI_DISPLAY=y ++CONFIG_DRM_MEDIATEK=y ++CONFIG_DRM_MEDIATEK_HDMI=y ++CONFIG_COMMON_CLK_MT2701_MMSYS=y ++CONFIG_COMMON_CLK_MT2701_IMGSYS=y ++CONFIG_COMMON_CLK_MT2701_VDECSYS=y ++CONFIG_FB=y ++CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_DRM_FBDEV_EMULATION=y ++ ++#mali ++CONFIG_MEDIA_CAMERA_SUPPORT=y ++CONFIG_VIDEO_DEV=y ++CONFIG_VIDEO_V4L2=y ++CONFIG_V4L_MEM2MEM_DRIVERS=y ++CONFIG_VIDEO_MEDIATEK_JPEG=y ++CONFIG_DRM_LIMA=m ++CONFIG_COMMON_CLK_MT2701_G3DSYS=y ++ ++#Sound ++CONFIG_SOUND=y ++CONFIG_SND=y #alsa core ++CONFIG_SND_SOC=y ++ ++#CONFIG_SOUND_OSS_CORE=y ++#CONFIG_SOUND_OSS_CORE_PRECLAIM=y ++#CONFIG_SND_OSSEMUL=y ++#CONFIG_SND_MIXER_OSS=m ++#CONFIG_SND_PCM_OSS=m #alsa The PCM OSS emulation module. ++ ++#USB/HID ++CONFIG_USB=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_MTK=y ++CONFIG_USB_STORAGE=y ++CONFIG_USB_SERIAL=y ++#CONFIG_NOP_USB_XCEIV=y ++#CONFIG_USB_GPIO_VBUS=y ++#CONFIG_USB_GADGET=y ++#CONFIG_USB_CONFIGFS=y ++CONFIG_USB_CONFIGFS_SERIAL=y ++#CONFIG_USB_CONFIGFS_ACM=y ++#CONFIG_USB_CONFIGFS_OBEX=y ++#CONFIG_USB_CONFIGFS_NCM=y ++#CONFIG_USB_CONFIGFS_ECM=y ++#CONFIG_USB_CONFIGFS_ECM_SUBSET=y ++#CONFIG_USB_CONFIGFS_RNDIS=y ++#CONFIG_USB_CONFIGFS_EEM=y ++CONFIG_USB_CONFIGFS_MASS_STORAGE=y ++ ++CONFIG_HID=y ++CONFIG_HIDRAW=y ++#CONFIG_UHID=m ++CONFIG_HID_GENERIC=y ++ ++CONFIG_USB_HID=y ++#CONFIG_HID_PID=y ++CONFIG_USB_HIDDEV=y ++ ++# CONFIG_USB_OHCI_LITTLE_ENDIAN=y ? ++CONFIG_USB_SUPPORT=y ++CONFIG_USB_COMMON=y ++# CONFIG_USB_ARCH_HAS_HCD=y ? ++ ++#additional NET (e.g. tunneling incl. openvpn,vlan-base-support) ++CONFIG_TUN=m ++#vlan ++CONFIG_BRIDGE_VLAN_FILTERING=y ++CONFIG_VLAN_8021Q_GVRP=y ++CONFIG_VLAN_8021Q_MVRP=y ++CONFIG_NET_L3_MASTER_DEV=y ++CONFIG_IPVLAN=m ++CONFIG_MACVLAN=m ++CONFIG_NET_ACT_VLAN=m ++CONFIG_NET_CLS_ACT=y ++ ++# QoS and/or fair queueing ++CONFIG_NET_SCHED=y ++CONFIG_NET_SCH_CBQ=m ++CONFIG_NET_SCH_HTB=m ++CONFIG_NET_SCH_CSZ=m ++CONFIG_NET_SCH_PRIO=m ++CONFIG_NET_SCH_RED=m ++CONFIG_NET_SCH_SFQ=m ++CONFIG_NET_SCH_TEQL=m ++CONFIG_NET_SCH_TBF=m ++CONFIG_NET_SCH_GRED=m ++CONFIG_NET_SCH_DSMARK=m ++CONFIG_NET_SCH_INGRESS=m ++#CONFIG_NET_SCH_NETEM=m ++CONFIG_NET_QOS=y ++CONFIG_NET_ESTIMATOR=y ++CONFIG_NET_CLS=y ++CONFIG_NET_CLS_TCINDEX=m ++CONFIG_NET_CLS_ROUTE4=m ++CONFIG_NET_CLS_ROUTE=y ++CONFIG_NET_CLS_FW=m ++CONFIG_NET_CLS_U32=m ++CONFIG_NET_CLS_RSVP=m ++CONFIG_NET_CLS_RSVP6=m ++CONFIG_NET_CLS_POLICE=y ++ ++#unused drivers which are set by default ++CONFIG_WLAN_VENDOR_ADMTEK=n ++CONFIG_WLAN_VENDOR_ATH=y ++CONFIG_ATH9K=m ++CONFIG_ATH10K=m ++CONFIG_ATH10K_PCI=m ++CONFIG_ATH10K_USB=m ++CONFIG_WLAN_VENDOR_ATMEL=n ++CONFIG_WLAN_VENDOR_BROADCOM=n ++CONFIG_WLAN_VENDOR_CISCO=n ++CONFIG_WLAN_VENDOR_INTEL=n ++CONFIG_WLAN_VENDOR_INTERSIL=n ++CONFIG_WLAN_VENDOR_MARVELL=n ++CONFIG_WLAN_VENDOR_REALTEK=n ++CONFIG_WLAN_VENDOR_RALINK=n ++CONFIG_WLAN_VENDOR_RSI=n ++CONFIG_WLAN_VENDOR_ST=n ++CONFIG_WLAN_VENDOR_TI=n ++CONFIG_WLAN_VENDOR_ZYDAS=n ++CONFIG_WLAN_VENDOR_QUANTENNA=n ++# CONFIG_ADAPTEC_STARFIRE is not set ++# CONFIG_NET_VENDOR_ADAPTEC is not set ++# CONFIG_NET_VENDOR_AGERE is not set ++# CONFIG_NET_VENDOR_ALACRITECH is not set ++# CONFIG_NET_VENDOR_ALTEON is not set ++# CONFIG_NET_VENDOR_AMAZON is not set ++# CONFIG_NET_VENDOR_AMD is not set ++# CONFIG_NET_VENDOR_AQUANTIA is not set ++# CONFIG_NET_VENDOR_ARC is not set ++# CONFIG_NET_VENDOR_ATHEROS is not set ++# CONFIG_NET_VENDOR_AURORA is not set ++# CONFIG_NET_CADENCE is not set ++# CONFIG_NET_VENDOR_BROADCOM is not set ++# CONFIG_NET_VENDOR_BROCADE is not set ++# CONFIG_NET_VENDOR_CAVIUM is not set ++# CONFIG_NET_VENDOR_CHELSIO is not set ++# CONFIG_NET_VENDOR_CIRRUS is not set ++# CONFIG_NET_VENDOR_CISCO is not set ++# CONFIG_NET_VENDOR_MELLANOX is not set ++# CONFIG_NET_VENDOR_MICREL is not set ++# CONFIG_NET_VENDOR_MICROCHIP is not set ++# CONFIG_NET_VENDOR_MYRI is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++# CONFIG_NET_VENDOR_NETRONOME is not set ++# CONFIG_NET_VENDOR_NVIDIA is not set ++# CONFIG_NET_VENDOR_OKI is not set ++# CONFIG_NET_PACKET_ENGINE is not set ++# CONFIG_NET_VENDOR_QLOGIC is not set ++# CONFIG_NET_VENDOR_QUALCOMM is not set ++# CONFIG_NET_VENDOR_REALTEK is not set ++# CONFIG_NET_VENDOR_RENESAS is not set ++# CONFIG_NET_VENDOR_RDC is not set ++# CONFIG_NET_VENDOR_ROCKER is not set ++# CONFIG_NET_VENDOR_SAMSUNG is not set ++# CONFIG_NET_VENDOR_SEEQ is not set ++# CONFIG_NET_VENDOR_SILAN is not set ++# CONFIG_NET_VENDOR_SIS is not set ++# CONFIG_NET_VENDOR_SOLARFLARE is not set ++# CONFIG_NET_VENDOR_SMSC is not set ++# CONFIG_NET_VENDOR_STMICRO is not set ++# CONFIG_NET_VENDOR_SUN is not set ++# CONFIG_NET_VENDOR_TEHUTI is not set ++# CONFIG_NET_VENDOR_TI is not set ++# CONFIG_NET_VENDOR_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++# CONFIG_NET_VENDOR_SYNOPSYS is not set ++# CONFIG_NET_VENDOR_DEC is not set ++# CONFIG_NET_VENDOR_DLINK is not set ++# CONFIG_NET_VENDOR_EMULEX is not set ++# CONFIG_NET_VENDOR_EZCHIP is not set ++# CONFIG_NET_VENDOR_EXAR is not set ++# CONFIG_NET_VENDOR_FARADAY is not set ++# CONFIG_NET_VENDOR_HISILICON is not set ++# CONFIG_NET_VENDOR_HP is not set ++# CONFIG_NET_VENDOR_HUAWEI is not set ++# CONFIG_NET_VENDOR_INTEL is not set ++# CONFIG_NET_VENDOR_MARVELL is not set ++# CONFIG_NET_VENDOR_3COM is not set ++ ++#NFS Client ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_SWAP=y ++CONFIG_NFS_V4_1=y ++CONFIG_NFS_V4_2=y ++CONFIG_PNFS_FILE_LAYOUT=m ++CONFIG_PNFS_BLOCK=m ++CONFIG_PNFS_FLEXFILE_LAYOUT=m ++CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org" ++CONFIG_NFS_V4_1_MIGRATION=y ++CONFIG_NFS_USE_LEGACY_DNS=y ++ ++#NFS Server ++CONFIG_NFSD=m ++CONFIG_NFSD_V2_ACL=y ++CONFIG_NFSD_V3=y ++CONFIG_NFSD_V3_ACL=y ++CONFIG_NFSD_V4=y ++CONFIG_NFSD_PNFS=y ++CONFIG_NFSD_BLOCKLAYOUT=y ++CONFIG_NFSD_SCSILAYOUT=y ++CONFIG_NFSD_FLEXFILELAYOUT=y ++CONFIG_NFSD_FAULT_INJECTION=y ++CONFIG_NFS_ACL_SUPPORT=m ++CONFIG_NFS_COMMON=y ++ ++CONFIG_ROOT_NFS=y ++ ++#xfs ++CONFIG_XFS_FS=m ++ ++#RTC/POWER ++CONFIG_POWER_RESET=y ++CONFIG_POWER_RESET_MT6323=y ++CONFIG_POWER_RESET_MT6397_RTC=y ++ ++#CONFIG_NET_MEDIATEK_HW_QOS=m ++ +diff --git a/arch/arm64/configs/mt7622_bpi-r64_defconfig b/arch/arm64/configs/mt7622_bpi-r64_defconfig +new file mode 100644 +index 000000000000..72359b09879a +--- /dev/null ++++ b/arch/arm64/configs/mt7622_bpi-r64_defconfig +@@ -0,0 +1,523 @@ ++CONFIG_LOCALVERSION="-bpi-r64" ++CONFIG_LOCALVERSION_AUTO=n ++ ++#CONFIG_COMPILE_TEST=y ++CONFIG_DEFAULT_HOSTNAME="(mt7622)" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++# CONFIG_CROSS_MEMORY_ATTACH is not set ++CONFIG_AUDIT=y ++CONFIG_NO_HZ_IDLE=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_IRQ_TIME_ACCOUNTING=y ++CONFIG_BSD_PROCESS_ACCT=y ++CONFIG_BSD_PROCESS_ACCT_V3=y ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_CGROUPS=y ++# CONFIG_UTS_NS is not set ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_PERF_EVENTS=y ++# CONFIG_COMPAT_BRK is not set ++CONFIG_JUMP_LABEL=y ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++# CONFIG_BLK_DEV_BSG is not set ++# CONFIG_IOSCHED_DEADLINE is not set ++CONFIG_ARCH_MEDIATEK=y ++CONFIG_PCI=y ++CONFIG_PCI_DEBUG=y ++CONFIG_PCIE_MEDIATEK=y ++CONFIG_SCHED_MC=y ++CONFIG_NR_CPUS=2 ++CONFIG_PREEMPT=y ++# CONFIG_COMPACTION is not set ++# CONFIG_EFI is not set ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++CONFIG_COMPAT=y ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_STAT=y ++CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y ++CONFIG_ARM_MEDIATEK_CPUFREQ=y ++CONFIG_SYNC_FILE=y ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_UNIX_DIAG=y ++CONFIG_PACKET_DIAG=m ++CONFIG_INET=y ++CONFIG_DUMMY=m ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++CONFIG_IP_PNP_RARP=y ++CONFIG_IPV6_ROUTER_PREF=y ++CONFIG_IPV6_OPTIMISTIC_DAD=y ++CONFIG_INET6_AH=m ++CONFIG_INET6_ESP=m ++CONFIG_INET6_IPCOMP=m ++CONFIG_IPV6_MIP6=m ++CONFIG_IPV6_TUNNEL=m ++CONFIG_IPV6_MULTIPLE_TABLES=y ++CONFIG_BRIDGE=y ++CONFIG_VLAN_8021Q=y ++CONFIG_BRIDGE_VLAN_FILTERING=y ++CONFIG_NETLINK_DIAG=y ++CONFIG_INET_UDP_DIAG=m ++CONFIG_NET_IPIP=m ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_MROUTE=y ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++ ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++# CONFIG_INET_DIAG is not set ++CONFIG_RFKILL=m ++ ++CONFIG_BT=y ++CONFIG_BT_RFCOMM=y ++CONFIG_BT_RFCOMM_TTY=y ++CONFIG_BT_BNEP=y ++CONFIG_BT_BNEP_MC_FILTER=y ++CONFIG_BT_BNEP_PROTO_FILTER=y ++CONFIG_BT_HIDP=y ++# CONFIG_BT_HS is not set ++# CONFIG_BT_LE is not set ++CONFIG_BT_HCIVHCI=y ++CONFIG_BT_MTKUART=m ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_MTD=y ++# CONFIG_MTD_OF_PARTS is not set ++CONFIG_MTD_NAND=y ++CONFIG_MTD_NAND_MTK=y ++CONFIG_MTD_SPI_NOR=y ++CONFIG_MTD_MT81xx_NOR=y ++# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set ++# CONFIG_BLK_DEV is not set ++CONFIG_BLK_DEV_SD=y ++CONFIG_ATA=y ++CONFIG_AHCI_MTK=y ++CONFIG_NETDEVICES=y ++# CONFIG_NET_VENDOR_3COM is not set ++# CONFIG_NET_VENDOR_ADAPTEC is not set ++# CONFIG_NET_VENDOR_AGERE is not set ++# CONFIG_NET_VENDOR_ALACRITECH is not set ++# CONFIG_NET_VENDOR_ALTEON is not set ++# CONFIG_NET_VENDOR_AMAZON is not set ++# CONFIG_NET_VENDOR_AMD is not set ++# CONFIG_NET_VENDOR_AQUANTIA is not set ++# CONFIG_NET_VENDOR_ARC is not set ++# CONFIG_NET_VENDOR_ATHEROS is not set ++# CONFIG_NET_CADENCE is not set ++# CONFIG_NET_VENDOR_BROADCOM is not set ++# CONFIG_NET_VENDOR_BROCADE is not set ++# CONFIG_NET_VENDOR_CAVIUM is not set ++# CONFIG_NET_VENDOR_CHELSIO is not set ++# CONFIG_NET_VENDOR_CISCO is not set ++# CONFIG_NET_VENDOR_DEC is not set ++# CONFIG_NET_VENDOR_DLINK is not set ++# CONFIG_NET_VENDOR_EMULEX is not set ++# CONFIG_NET_VENDOR_EZCHIP is not set ++# CONFIG_NET_VENDOR_EXAR is not set ++# CONFIG_NET_VENDOR_HISILICON is not set ++# CONFIG_NET_VENDOR_HP is not set ++# CONFIG_NET_VENDOR_HUAWEI is not set ++# CONFIG_NET_VENDOR_INTEL is not set ++# CONFIG_NET_VENDOR_MARVELL is not set ++CONFIG_NET_VENDOR_MEDIATEK=y ++CONFIG_NET_MEDIATEK_SOC=y ++# CONFIG_NET_VENDOR_MELLANOX is not set ++# CONFIG_NET_VENDOR_MICREL is not set ++# CONFIG_NET_VENDOR_MICROCHIP is not set ++# CONFIG_NET_VENDOR_MYRI is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++# CONFIG_NET_VENDOR_NETRONOME is not set ++# CONFIG_NET_VENDOR_NVIDIA is not set ++# CONFIG_NET_VENDOR_OKI is not set ++# CONFIG_NET_PACKET_ENGINE is not set ++# CONFIG_NET_VENDOR_QLOGIC is not set ++# CONFIG_NET_VENDOR_QUALCOMM is not set ++# CONFIG_NET_VENDOR_REALTEK is not set ++# CONFIG_NET_VENDOR_RENESAS is not set ++# CONFIG_NET_VENDOR_RDC is not set ++# CONFIG_NET_VENDOR_ROCKER is not set ++# CONFIG_NET_VENDOR_SAMSUNG is not set ++# CONFIG_NET_VENDOR_SEEQ is not set ++# CONFIG_NET_VENDOR_SILAN is not set ++# CONFIG_NET_VENDOR_SIS is not set ++# CONFIG_NET_VENDOR_SOLARFLARE is not set ++# CONFIG_NET_VENDOR_SMSC is not set ++# CONFIG_NET_VENDOR_STMICRO is not set ++# CONFIG_NET_VENDOR_SUN is not set ++# CONFIG_NET_VENDOR_TEHUTI is not set ++# CONFIG_NET_VENDOR_TI is not set ++# CONFIG_NET_VENDOR_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++# CONFIG_NET_VENDOR_SYNOPSYS is not set ++CONFIG_ICPLUS_PHY=y ++CONFIG_USB_CATC=y ++CONFIG_USB_KAWETH=y ++CONFIG_USB_PEGASUS=y ++CONFIG_USB_RTL8150=y ++CONFIG_USB_RTL8152=y ++CONFIG_USB_LAN78XX=y ++CONFIG_USB_USBNET=y ++CONFIG_USB_NET_CDC_EEM=y ++CONFIG_USB_NET_HUAWEI_CDC_NCM=y ++CONFIG_USB_NET_CDC_MBIM=y ++CONFIG_USB_NET_DM9601=y ++CONFIG_USB_NET_SR9700=y ++CONFIG_USB_NET_SR9800=y ++CONFIG_USB_NET_SMSC75XX=y ++CONFIG_USB_NET_SMSC95XX=y ++CONFIG_USB_NET_GL620A=y ++CONFIG_USB_NET_PLUSB=y ++CONFIG_USB_NET_MCS7830=y ++CONFIG_USB_NET_RNDIS_HOST=y ++CONFIG_USB_ALI_M5632=y ++CONFIG_USB_AN2720=y ++CONFIG_USB_EPSON2888=y ++CONFIG_USB_KC2190=y ++CONFIG_USB_NET_CX82310_ETH=y ++CONFIG_USB_NET_KALMIA=y ++CONFIG_USB_NET_QMI_WWAN=y ++CONFIG_USB_NET_INT51X1=y ++CONFIG_USB_IPHETH=y ++CONFIG_USB_SIERRA_NET=y ++CONFIG_USB_VL600=y ++CONFIG_USB_NET_CH9200=y ++CONFIG_INPUT_POLLDEV=y ++CONFIG_INPUT_EVDEV=y ++#CONFIG_INPUT_EVBUG=y ++# CONFIG_KEYBOARD_ATKBD is not set ++CONFIG_KEYBOARD_GPIO=y ++# CONFIG_INPUT_MOUSE is not set ++CONFIG_SERIO_LIBPS2=y ++CONFIG_VT_HW_CONSOLE_BINDING=y ++CONFIG_LEGACY_PTY_COUNT=16 ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_NR_UARTS=3 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=3 ++CONFIG_SERIAL_8250_MT6577=y ++CONFIG_SERIAL_OF_PLATFORM=y ++CONFIG_SERIAL_DEV_BUS=y ++CONFIG_HW_RANDOM=y ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=y ++CONFIG_I2C_MT65XX=y ++CONFIG_I2C_SLAVE=y ++CONFIG_I2C_DEBUG_CORE=y ++CONFIG_I2C_DEBUG_ALGO=y ++CONFIG_I2C_DEBUG_BUS=y ++CONFIG_SPI=y ++CONFIG_SPI_MT65XX=y ++CONFIG_PINCTRL_MT2701=y ++CONFIG_PINCTRL_MT8135=y ++CONFIG_PINCTRL_MT8127=y ++CONFIG_PINCTRL_MT7622=y ++CONFIG_POWER_RESET_SYSCON=y ++CONFIG_THERMAL=y ++CONFIG_THERMAL_WRITABLE_TRIPS=y ++CONFIG_THERMAL_GOV_FAIR_SHARE=y ++CONFIG_THERMAL_GOV_BANG_BANG=y ++CONFIG_THERMAL_GOV_USER_SPACE=y ++CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y ++CONFIG_CPU_THERMAL=y ++CONFIG_CLOCK_THERMAL=y ++CONFIG_THERMAL_EMULATION=y ++CONFIG_HWMON=y ++CONFIG_THERMAL_HWMON=y ++CONFIG_WATCHDOG=y ++CONFIG_WATCHDOG_SYSFS=y ++CONFIG_MEDIATEK_WATCHDOG=y ++CONFIG_WATCHDOG_PRETIMEOUT_GOV=y ++CONFIG_MFD_MT6397=y ++# CONFIG_ABX500_CORE is not set ++CONFIG_REGULATOR=y ++CONFIG_REGULATOR_FIXED_VOLTAGE=y ++CONFIG_REGULATOR_MT6323=y ++CONFIG_REGULATOR_MT6380=y ++#CONFIG_RC_CORE=y ++CONFIG_RC_DEVICES=y ++CONFIG_IR_MTK=y ++CONFIG_MEDIA_SUPPORT=y ++CONFIG_USB=y ++# CONFIG_USB_PCI is not set ++# CONFIG_USB_DEFAULT_PERSIST is not set ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_MTK=y ++CONFIG_USB_STORAGE=y ++CONFIG_MMC=y ++CONFIG_MMC_MTK=y ++CONFIG_NEW_LEDS=y ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_USER=y ++CONFIG_LEDS_TRIGGERS=y ++CONFIG_LEDS_TRIGGER_TIMER=y ++CONFIG_LEDS_TRIGGER_ONESHOT=y ++CONFIG_LEDS_TRIGGER_HEARTBEAT=y ++CONFIG_LEDS_TRIGGER_BACKLIGHT=y ++CONFIG_LEDS_TRIGGER_CPU=y ++#CONFIG_LEDS_TRIGGER_ACTIVITY=y ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y ++CONFIG_LEDS_GPIO=y ++CONFIG_RTC_CLASS=y ++CONFIG_RTC_DRV_MT7622=y ++CONFIG_DMADEVICES=y ++CONFIG_MTK_HSDMA=y ++CONFIG_DMATEST=y ++# CONFIG_COMMON_CLK_XGENE is not set ++# CONFIG_COMMON_CLK_MT6797 is not set ++CONFIG_COMMON_CLK_MT7622_ETHSYS=y ++CONFIG_COMMON_CLK_MT7622_HIFSYS=y ++CONFIG_COMMON_CLK_MT7622_AUDSYS=y ++# CONFIG_COMMON_CLK_MT8173 is not set ++# CONFIG_IOMMU_SUPPORT is not set ++CONFIG_MTK_PMIC_WRAP=y ++CONFIG_IIO=y ++CONFIG_MEDIATEK_MT6577_AUXADC=y ++CONFIG_PWM=y ++CONFIG_PWM_MEDIATEK=y ++CONFIG_PHY_MTK_TPHY=y ++CONFIG_NVMEM_MTK_EFUSE=y ++CONFIG_EXT4_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_TMPFS=y ++CONFIG_PRINTK_TIME=y ++CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15 ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7 ++CONFIG_DYNAMIC_DEBUG=y ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_DEBUG_FS=y ++CONFIG_DEBUG_SECTION_MISMATCH=y ++# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_DEBUG_KERNEL=y ++# CONFIG_FTRACE is not set ++CONFIG_CRYPTO_ECHAINIV=y ++CONFIG_CRYPTO_CRC32=y ++CONFIG_CRYPTO_CRC32C=y ++CONFIG_CRYPTO_DEFLATE=y ++CONFIG_CRYPTO_LZ4=y ++CONFIG_CRYPTO_ZSTD=y ++ ++#for lxc ++CONFIG_USER_NS=y ++CONFIG_MEMCG=y ++CONFIG_CGROUP_CPUACCT=y ++CONFIG_CGROUP_DEVICE=y ++CONFIG_CGROUP_SCHED=y ++CONFIG_CPUSETS=y ++#some options for docker ++CONFIG_CGROUP_FREEZER=y ++CONFIG_OVERLAY_FS=y ++CONFIG_MEMCG_SWAP=y ++CONFIG_MEMCG_SWAP_ENABLED=y ++CONFIG_BLK_CGROUP=y ++CONFIG_CFS_BANDWIDTH=y ++CONFIG_RT_GROUP_SCHED=y ++CONFIG_CGROUP_PIDS=y ++CONFIG_CGROUP_PERF=y ++CONFIG_CGROUP_NET_CLASSID=y ++CONFIG_CGROUP_NET_PRIO=y ++CONFIG_CFQ_GROUP_IOSCHED=y ++ ++#added for docker ++CONFIG_POSIX_MQUEUE=y ++CONFIG_POSIX_MQUEUE_SYSCTL=y ++CONFIG_HAVE_ARCH_SECCOMP_FILTER=y ++CONFIG_SECCOMP_FILTER=y ++CONFIG_SECCOMP=y ++ ++CONFIG_GPIO_SYSFS=y ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_ISO8859_1=y ++ ++#IP / net ++CONFIG_IPV6=y ++CONFIG_NETFILTER=y ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_IPV4=m ++CONFIG_NF_CONNTRACK_IPV6=m ++CONFIG_NETFILTER_NETLINK=m ++CONFIG_NF_CT_NETLINK=m ++CONFIG_IP_NF_IPTABLES=m ++CONFIG_NF_LOG_IPV4=m ++CONFIG_NF_REJECT_IPV4=m ++CONFIG_IP6_NF_IPTABLES=m ++CONFIG_NF_LOG_IPV6=m ++CONFIG_NF_REJECT_IPV6=m ++CONFIG_IP_NF_NAT=m ++CONFIG_IP6_NF_NAT=m ++CONFIG_NF_NAT_MASQUERADE_IPV4=y ++CONFIG_NF_NAT_MASQUERADE_IPV6=y ++CONFIG_IP_NF_FILTER=m ++CONFIG_IP6_NF_FILTER=m ++CONFIG_IP_NF_TARGET_MASQUERADE=m ++CONFIG_IP6_NF_TARGET_MASQUERADE=m ++CONFIG_IP_NF_MANGLE=m ++CONFIG_IP6_NF_MANGLE=m ++CONFIG_IP_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_MATCH_RT=m ++ ++CONFIG_NETFILTER_SYNPROXY=m ++CONFIG_IP_NF_TARGET_SYNPROXY=m ++CONFIG_IP6_NF_TARGET_SYNPROXY=m ++ ++CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m ++CONFIG_NETFILTER_XT_MATCH_LIMIT=m ++CONFIG_NETFILTER_XT_MATCH_STATE=m ++CONFIG_NETFILTER_XT_TARGET_LOG=m ++CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m ++CONFIG_NETFILTER_XT_MATCH_MAC=m ++CONFIG_NETFILTER_XT_MATCH_RECENT=m ++CONFIG_NETFILTER_XT_MATCH_IPRANGE=m ++CONFIG_NETFILTER_XT_MARK=m ++CONFIG_NETFILTER_XT_CONNMARK=m ++CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m ++CONFIG_IP_VS=m ++CONFIG_NETFILTER_XT_MATCH_IPVS=m ++CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m ++ ++CONFIG_NF_TABLES=m ++CONFIG_NF_TABLES_IPV4=y ++CONFIG_NF_TABLES_IPV6=y ++CONFIG_NF_TABLES_SET=m ++CONFIG_NF_TABLES_INET=y ++CONFIG_NF_TABLES_NETDEV=y ++CONFIG_NF_TPROXY_IPV4=m ++CONFIG_NF_TABLES_ARP=y ++CONFIG_NF_TPROXY_IPV6=m ++CONFIG_NF_TABLES_BRIDGE=m ++CONFIG_NFT_NUMGEN=m ++CONFIG_NFT_CT=m ++CONFIG_NFT_COUNTER=m ++CONFIG_NFT_CONNLIMIT=m ++CONFIG_NFT_LOG=m ++CONFIG_NFT_LIMIT=m ++CONFIG_NFT_MASQ=m ++CONFIG_NFT_NAT=m ++CONFIG_NFT_REDIR=m ++CONFIG_NFT_TUNNEL=m ++CONFIG_NFT_OBJREF=m ++CONFIG_NFT_QUOTA=m ++CONFIG_NFT_REJECT=m ++CONFIG_NFT_COMPAT=m ++CONFIG_NFT_HASH=m ++CONFIG_NFT_XFRM=m ++CONFIG_NFT_SOCKET=m ++CONFIG_NFT_OSF=m ++CONFIG_NFT_TPROXY=m ++CONFIG_NFT_SYNPROXY=m ++CONFIG_NFTL=m ++CONFIG_NFTL_RW=y ++ ++CONFIG_NF_FLOW_TABLE=m ++CONFIG_NF_FLOW_TABLE_INET=m ++CONFIG_NF_FLOW_TABLE_IPV4=m ++CONFIG_NF_FLOW_TABLE_IPV6=m ++CONFIG_NFT_FLOW_OFFLOAD=m ++ ++ ++#active ftp-support ++CONFIG_NF_CONNTRACK_FTP=m ++CONFIG_NF_NAT_FTP=m ++ ++CONFIG_SYN_COOKIES=y ++ ++CONFIG_PPP=m ++CONFIG_PPPOE=m ++CONFIG_PPP_FILTER=y ++CONFIG_PPP_DEFLATE=m ++CONFIG_PPP_MPPE=m ++ ++#veth for lxc ++CONFIG_VETH=m ++ ++ ++CONFIG_CFG80211=m ++CONFIG_MAC80211=m ++CONFIG_MAC80211_MESH=y ++CONFIG_MT7615E=m ++CONFIG_MT7915E=m ++CONFIG_MT7622=m ++ ++CONFIG_NET_DSA=y ++CONFIG_NET_DSA_MT7530=y ++ ++#NFS Client ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_SWAP=y ++CONFIG_NFS_V4_1=y ++CONFIG_NFS_V4_2=y ++CONFIG_PNFS_FILE_LAYOUT=m ++CONFIG_PNFS_BLOCK=m ++CONFIG_PNFS_FLEXFILE_LAYOUT=m ++CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org" ++CONFIG_NFS_V4_1_MIGRATION=y ++CONFIG_NFS_USE_LEGACY_DNS=y ++ ++#NFS Server ++CONFIG_NFSD=m ++CONFIG_NFSD_V2_ACL=y ++CONFIG_NFSD_V3=y ++CONFIG_NFSD_V3_ACL=y ++CONFIG_NFSD_V4=y ++CONFIG_NFSD_PNFS=y ++CONFIG_NFSD_BLOCKLAYOUT=y ++CONFIG_NFSD_SCSILAYOUT=y ++CONFIG_NFSD_FLEXFILELAYOUT=y ++CONFIG_NFSD_FAULT_INJECTION=y ++CONFIG_NFS_ACL_SUPPORT=m ++CONFIG_NFS_COMMON=y ++ ++CONFIG_ROOT_NFS=y ++ ++#xfs ++CONFIG_XFS_FS=m ++ ++#pstore/ramoops ++CONFIG_CPU_IDLE=y ++CONFIG_ARM_PSCI_CPUIDLE=y ++CONFIG_ARM_PSCI_CPUIDLE_DOMAIN=y ++CONFIG_MISC_FILESYSTEMS=y ++CONFIG_PSTORE=y ++CONFIG_PSTORE_COMPRESS=n ++#CONFIG_PSTORE_COMPRESS_DEFAULT="deflate" ++CONFIG_PSTORE_CONSOLE=y ++#CONFIG_PSTORE_DEFLATE_COMPRESS=y ++#CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT=y ++CONFIG_PSTORE_PMSG=y ++CONFIG_PSTORE_RAM=y ++ ++#CONFIG_BLK_DEV_INITRD=y ++#CONFIG_INITRAMFS_SOURCE="../buildroot/arm64_rootfs.cpio" ++CONFIG_SENSORS_PWM_FAN=m ++ ++#reduced phy driver ++#CONFIG_NET_REALTEK_MDIO=y ++ ++#real dsa driver ++#CONFIG_NET_DSA_REALTEK=y ++ ++#thermal since 6.3 ++CONFIG_MTK_THERMAL=y ++CONFIG_MTK_SOC_THERMAL=y ++ ++CONFIG_PANIC_TIMEOUT=30 +diff --git a/arch/arm64/configs/mt7986a_bpi-r3_defconfig b/arch/arm64/configs/mt7986a_bpi-r3_defconfig +new file mode 100644 +index 000000000000..fccecc3b2375 +--- /dev/null ++++ b/arch/arm64/configs/mt7986a_bpi-r3_defconfig +@@ -0,0 +1,1265 @@ ++CONFIG_LOCALVERSION="-bpi-r3" ++CONFIG_LOCALVERSION_AUTO=n ++ ++CONFIG_32BIT=y ++CONFIG_64BIT_TIME=y ++CONFIG_ADVISE_SYSCALLS=y ++CONFIG_AEABI=y ++CONFIG_AF_UNIX_OOB=y ++CONFIG_AIO=y ++CONFIG_ALLOW_DEV_COREDUMP=y ++CONFIG_ANON_INODES=y ++CONFIG_ARCH_BINFMT_ELF_STATE=y ++CONFIG_ARCH_FLATMEM_ENABLE=y ++CONFIG_ARM64_SW_TTBR0_PAN=y ++CONFIG_ARM_CPU_TOPOLOGY=y ++CONFIG_ARM_DMA_MEM_BUFFERABLE=y ++CONFIG_ARM_GIC_MAX_NR=1 ++CONFIG_ATAGS_PROC=y ++CONFIG_ATA_BMDMA=y ++CONFIG_ATA_SFF=y ++CONFIG_ATM_BR2684_IPFILTER=y ++CONFIG_ATM_CLIP_NO_ICMP=y ++CONFIG_BASE_FULL=y ++CONFIG_BASE_SMALL=0 ++CONFIG_BCMA_POSSIBLE=y ++CONFIG_BINARY_PRINTF=y ++CONFIG_BINFMT_ELF=y ++CONFIG_BINFMT_SCRIPT=y ++CONFIG_BITREVERSE=y ++CONFIG_BLK_DEV=y ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 ++CONFIG_BLOCK=y ++CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT=3 ++CONFIG_BOOT_RAW=y ++CONFIG_BPF=y ++CONFIG_BPF_JIT=y ++CONFIG_BPF_JIT_DEFAULT_ON=y ++CONFIG_BPF_SYSCALL=y ++CONFIG_BPF_UNPRIV_DEFAULT_OFF=y ++CONFIG_BQL=y ++CONFIG_BRANCH_PROFILE_NONE=y ++CONFIG_BRIDGE=y ++CONFIG_BRIDGE_IGMP_SNOOPING=y ++CONFIG_BRIDGE_VLAN_FILTERING=y ++CONFIG_BROKEN_ON_SMP=y ++CONFIG_BT_BNEP_MC_FILTER=y ++CONFIG_BT_BNEP_PROTO_FILTER=y ++CONFIG_BT_HCIUART_BCSP=y ++CONFIG_BT_HCIUART_H4=y ++CONFIG_BT_RFCOMM_TTY=y ++CONFIG_BUG=y ++CONFIG_BUILDTIME_EXTABLE_SORT=y ++CONFIG_BUILDTIME_TABLE_SORT=y ++CONFIG_BUILD_SALT="" ++CONFIG_CACHE_L2X0_PMU=y ++CONFIG_CARDBUS=y ++CONFIG_CC_CAN_LINK=y ++CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y ++CONFIG_CIFS=m ++CONFIG_CIFS_ALLOW_INSECURE_LEGACY=y ++CONFIG_CIFS_POSIX=y ++CONFIG_CIFS_XATTR=y ++CONFIG_CIFS_FSCACHE=y ++CONFIG_CLS_U32_MARK=y ++CONFIG_CMDLINE="" ++CONFIG_COMPACTION=y ++#CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 ++CONFIG_CONSOLE_LOGLEVEL_QUIET=4 ++CONFIG_CONSTRUCTORS=y ++CONFIG_CPU_LITTLE_ENDIAN=y ++CONFIG_CPU_SW_DOMAIN_PAN=y ++CONFIG_CRAMFS_BLOCKDEV=y ++CONFIG_CRC32=y ++CONFIG_CRC32_SARWATE=y ++CONFIG_CROSS_COMPILE="" ++CONFIG_CRYPTO=y ++CONFIG_CRYPTO_ACOMP2=y ++CONFIG_CRYPTO_AEAD=y ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_AES=y ++CONFIG_CRYPTO_AKCIPHER=y ++CONFIG_CRYPTO_AKCIPHER2=y ++CONFIG_CRYPTO_ALGAPI=y ++CONFIG_CRYPTO_ALGAPI2=y ++CONFIG_CRYPTO_CCM=y ++CONFIG_CRYPTO_CTR=y ++CONFIG_CRYPTO_GCM=y ++CONFIG_CRYPTO_GF128MUL=y ++CONFIG_CRYPTO_GHASH=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_KPP=y ++CONFIG_CRYPTO_KPP2=y ++CONFIG_CRYPTO_LIB_AES=y ++CONFIG_CRYPTO_LIB_ARC4=y ++CONFIG_CRYPTO_LIB_POLY1305_RSIZE=9 ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_MANAGER2=y ++CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y ++CONFIG_CRYPTO_NULL=y ++CONFIG_CRYPTO_NULL2=y ++CONFIG_CRYPTO_PCRYPT=y ++CONFIG_CRYPTO_SKCIPHER=y ++CONFIG_CRYPTO_SKCIPHER2=y ++CONFIG_DEBUG_FS=y ++CONFIG_DEBUG_FS_ALLOW_ALL=y ++CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y ++CONFIG_DEBUG_KERNEL=y ++CONFIG_DEFAULT_CUBIC=y ++CONFIG_DEFAULT_DEADLINE=y ++CONFIG_DEFAULT_FQ_CODEL=y ++CONFIG_DEFAULT_HOSTNAME="(none)" ++CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 ++CONFIG_DEFAULT_INIT="" ++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 ++CONFIG_DEFAULT_NET_SCH="fq_codel" ++CONFIG_DEFAULT_SECURITY="" ++CONFIG_DEFAULT_SECURITY_DAC=y ++CONFIG_DEFAULT_TCP_CONG="cubic" ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++CONFIG_DEVPORT=y ++CONFIG_DMA_COHERENT_POOL=y ++CONFIG_DMA_DECLARE_COHERENT=y ++CONFIG_DMA_NONCOHERENT_MMAP=y ++CONFIG_DOUBLEFAULT=y ++CONFIG_DQL=y ++CONFIG_DUMMY_CONSOLE_COLUMNS=80 ++CONFIG_DUMMY_CONSOLE_ROWS=25 ++CONFIG_DVB_MAX_ADAPTERS=16 ++CONFIG_DYNAMIC_DEBUG_CORE=y ++CONFIG_EFI_PARTITION=y ++CONFIG_ELFCORE=y ++CONFIG_EMBEDDED=y ++CONFIG_ENABLE_WARN_DEPRECATED=y ++CONFIG_EPOLL=y ++CONFIG_ETHERNET=y ++CONFIG_ETHTOOL_NETLINK=y ++CONFIG_EVENTFD=y ++CONFIG_EXPERT=y ++CONFIG_EXPORTFS=y ++CONFIG_EXT2_FS_XATTR=y ++CONFIG_EXT4_USE_FOR_EXT2=y ++CONFIG_EXTRA_TARGETS="" ++CONFIG_F2FS_FS_XATTR=y ++CONFIG_F2FS_STAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++CONFIG_FB_NOTIFY=y ++CONFIG_FIB_RULES=y ++CONFIG_FILE_LOCKING=y ++CONFIG_FLATMEM=y ++CONFIG_FLATMEM_MANUAL=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_FORCE_MAX_ZONEORDER=11 ++CONFIG_FORTIFY_SOURCE=y ++CONFIG_FRAME_WARN=1024 ++CONFIG_FSNOTIFY=y ++CONFIG_FUTEX=y ++CONFIG_FUTEX_PI=y ++CONFIG_FW_LOADER=y ++CONFIG_FW_LOADER_USER_HELPER=y ++CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y ++CONFIG_GACT_PROB=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_IRQ_IPI=y ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_GENERIC_NET_UTILS=y ++CONFIG_GENERIC_PTDUMP=y ++CONFIG_GENERIC_VDSO_TIME_NS=y ++CONFIG_GPIOLIB_FASTPATH_LIMIT=512 ++CONFIG_GPIO_SYSFS=y ++CONFIG_HARDENED_USERCOPY=y ++CONFIG_HARDEN_BRANCH_HISTORY=y ++CONFIG_HARDEN_EL2_VECTORS=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_HPET_MMAP_DEFAULT=y ++CONFIG_HW_PERF_EVENTS=y ++CONFIG_HW_RANDOM_TPM=y ++CONFIG_HZ=100 ++CONFIG_HZ_100=y ++CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 ++CONFIG_INET=y ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_INIT_STACK_NONE=y ++CONFIG_INOTIFY_USER=y ++CONFIG_INPUT_MISC=y ++CONFIG_IO_STRICT_DEVMEM=y ++CONFIG_IO_WQ=y ++CONFIG_IPV6_NDISC_NODETYPE=y ++CONFIG_IPW2100_MONITOR=y ++CONFIG_IPW2200_MONITOR=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++CONFIG_IP_VS_MH_TAB_INDEX=10 ++CONFIG_ISDN=y ++CONFIG_JFFS2_CMODE_PRIORITY=y ++CONFIG_JFFS2_COMPRESSION_OPTIONS=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++CONFIG_JFFS2_FS_XATTR=y ++CONFIG_JFFS2_LZMA=y ++CONFIG_JFFS2_RTIME=y ++CONFIG_JFFS2_SUMMARY=y ++CONFIG_JOLIET=y ++CONFIG_KALLSYMS_BASE_RELATIVE=y ++CONFIG_KASAN_STACK=y ++CONFIG_KERNEL_MODE_NEON=y ++CONFIG_KERNEL_XZ=y ++CONFIG_KERNFS=y ++CONFIG_KUSER_HELPERS=y ++CONFIG_LBDAF=y ++CONFIG_LDISC_AUTOLOAD=y ++CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y ++CONFIG_LEDS_BRIGHTNESS_HW_CHANGED=y ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_CLASS_MULTICOLOR=y ++CONFIG_LEDS_TRIGGERS=y ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y ++CONFIG_LEDS_TRIGGER_HEARTBEAT=y ++CONFIG_LEDS_TRIGGER_NETDEV=y ++CONFIG_LEDS_TRIGGER_TIMER=y ++CONFIG_LEDS_GPIO=y ++CONFIG_LINEAR_RANGES=y ++CONFIG_LLC=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_LOCKD_V4=y ++CONFIG_LOG_BUF_SHIFT=17 ++CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 ++CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity" ++CONFIG_LSM_MMAP_MIN_ADDR=65536 ++CONFIG_LTO_NONE=y ++CONFIG_LZMA_COMPRESS=y ++CONFIG_LZMA_DECOMPRESS=y ++CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 ++CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 ++CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE="" ++CONFIG_MAY_USE_DEVLINK=y ++CONFIG_MEMBARRIER=y ++#CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 ++CONFIG_MII=y ++CONFIG_MISC_FILESYSTEMS=y ++CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY=y ++CONFIG_MMC_BLOCK_BOUNCE=y ++CONFIG_MMC_BLOCK_MINORS=8 ++CONFIG_MMU=y ++CONFIG_MMU_GATHER_RCU_TABLE_FREE=y ++CONFIG_MMU_GATHER_TABLE_FREE=y ++CONFIG_MODPROBE_PATH="/sbin/modprobe" ++CONFIG_MODULES=y ++CONFIG_MODULE_COMPRESS_NONE=y ++CONFIG_MODULE_STRIPPED=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MSDOS_PARTITION=y ++CONFIG_MTD=y ++CONFIG_MTD_BLKDEVS=y ++CONFIG_MTD_BLOCK=y ++CONFIG_MTD_CFI=y ++CONFIG_MTD_CFI_AMDSTD=y ++CONFIG_MTD_CFI_I1=y ++CONFIG_MTD_CFI_I2=y ++CONFIG_MTD_CFI_INTELEXT=y ++CONFIG_MTD_CFI_NOSWAP=y ++CONFIG_MTD_CFI_UTIL=y ++CONFIG_MTD_COMPLEX_MAPPINGS=y ++CONFIG_MTD_GEN_PROBE=y ++CONFIG_MTD_MAP_BANK_WIDTH_1=y ++CONFIG_MTD_MAP_BANK_WIDTH_2=y ++CONFIG_MTD_MAP_BANK_WIDTH_4=y ++CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xff108018 ++CONFIG_MTD_NAND_IDS=y ++CONFIG_MTD_OF_PARTS=y ++CONFIG_MTD_PHYSMAP_OF=y ++CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 ++CONFIG_MTD_ROOTFS_ROOT_DEV=y ++CONFIG_MTD_SPI_NOR_SWP_DISABLE_ON_VOLATILE=y ++CONFIG_MTD_SPI_NOR_USE_4K_SECTORS_LIMIT=4096 ++CONFIG_MTD_SPLIT=y ++CONFIG_MTD_SPLIT_FIRMWARE_NAME="firmware" ++CONFIG_MTD_SPLIT_SQUASHFS_ROOT=y ++CONFIG_MTD_SPLIT_SUPPORT=y ++CONFIG_MULTIUSER=y ++CONFIG_NET=y ++CONFIG_NETDEVICES=y ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NET_CADENCE=y ++CONFIG_NET_CLS=y ++CONFIG_NET_CLS_IND=y ++CONFIG_NET_CORE=y ++CONFIG_NET_EMATCH_STACK=32 ++CONFIG_NET_IPGRE_BROADCAST=y ++CONFIG_NET_RX_BUSY_POLL=y ++CONFIG_NET_SCHED=y ++CONFIG_NET_SCH_DEFAULT=y ++CONFIG_NET_SCH_FIFO=y ++CONFIG_NET_SCH_FQ_CODEL=y ++CONFIG_NET_SOCK_MSG=y ++CONFIG_NET_VENDOR_3COM=y ++CONFIG_NET_VENDOR_8390=y ++CONFIG_NET_VENDOR_ADAPTEC=y ++CONFIG_NET_VENDOR_AGERE=y ++CONFIG_NET_VENDOR_ALACRITECH=y ++CONFIG_NET_VENDOR_ALTEON=y ++CONFIG_NET_VENDOR_AMAZON=y ++CONFIG_NET_VENDOR_AMD=y ++CONFIG_NET_VENDOR_AQUANTIA=y ++CONFIG_NET_VENDOR_ARC=y ++CONFIG_NET_VENDOR_ATHEROS=y ++CONFIG_NET_VENDOR_AURORA=y ++CONFIG_NET_VENDOR_BROADCOM=y ++CONFIG_NET_VENDOR_BROCADE=y ++CONFIG_NET_VENDOR_CADENCE=y ++CONFIG_NET_VENDOR_CAVIUM=y ++CONFIG_NET_VENDOR_CHELSIO=y ++CONFIG_NET_VENDOR_CIRRUS=y ++CONFIG_NET_VENDOR_CISCO=y ++CONFIG_NET_VENDOR_CORTINA=y ++CONFIG_NET_VENDOR_DEC=y ++CONFIG_NET_VENDOR_DLINK=y ++CONFIG_NET_VENDOR_EMULEX=y ++CONFIG_NET_VENDOR_EXAR=y ++CONFIG_NET_VENDOR_EZCHIP=y ++CONFIG_NET_VENDOR_FARADAY=y ++CONFIG_NET_VENDOR_FREESCALE=y ++CONFIG_NET_VENDOR_FUJITSU=y ++CONFIG_NET_VENDOR_GOOGLE=y ++CONFIG_NET_VENDOR_HISILICON=y ++CONFIG_NET_VENDOR_HP=y ++CONFIG_NET_VENDOR_HUAWEI=y ++CONFIG_NET_VENDOR_I825XX=y ++CONFIG_NET_VENDOR_IBM=y ++CONFIG_NET_VENDOR_INTEL=y ++CONFIG_NET_VENDOR_MARVELL=y ++CONFIG_NET_VENDOR_MELLANOX=y ++CONFIG_NET_VENDOR_MICREL=y ++CONFIG_NET_VENDOR_MICROCHIP=y ++CONFIG_NET_VENDOR_MICROSEMI=y ++CONFIG_NET_VENDOR_MYRI=y ++CONFIG_NET_VENDOR_NATSEMI=y ++CONFIG_NET_VENDOR_NETERION=y ++CONFIG_NET_VENDOR_NETRONOME=y ++CONFIG_NET_VENDOR_NI=y ++CONFIG_NET_VENDOR_NVIDIA=y ++CONFIG_NET_VENDOR_OKI=y ++CONFIG_NET_VENDOR_PACKET_ENGINES=y ++CONFIG_NET_VENDOR_PENSANDO=y ++CONFIG_NET_VENDOR_QLOGIC=y ++CONFIG_NET_VENDOR_QUALCOMM=y ++CONFIG_NET_VENDOR_RDC=y ++CONFIG_NET_VENDOR_REALTEK=y ++CONFIG_NET_VENDOR_RENESAS=y ++CONFIG_NET_VENDOR_ROCKER=y ++CONFIG_NET_VENDOR_SAMSUNG=y ++CONFIG_NET_VENDOR_SEEQ=y ++CONFIG_NET_VENDOR_SILAN=y ++CONFIG_NET_VENDOR_SIS=y ++CONFIG_NET_VENDOR_SMSC=y ++CONFIG_NET_VENDOR_SOCIONEXT=y ++CONFIG_NET_VENDOR_SOLARFLARE=y ++CONFIG_NET_VENDOR_STMICRO=y ++CONFIG_NET_VENDOR_SUN=y ++CONFIG_NET_VENDOR_SYNOPSYS=y ++CONFIG_NET_VENDOR_TEHUTI=y ++CONFIG_NET_VENDOR_TI=y ++CONFIG_NET_VENDOR_TOSHIBA=y ++CONFIG_NET_VENDOR_VIA=y ++CONFIG_NET_VENDOR_WIZNET=y ++CONFIG_NET_VENDOR_XILINX=y ++CONFIG_NET_VENDOR_XIRCOM=y ++CONFIG_NEW_LEDS=y ++CONFIG_NFSD_V3=y ++CONFIG_NFS_COMMON=y ++CONFIG_NFS_V3=y ++CONFIG_NF_CONNTRACK_PROCFS=y ++CONFIG_NF_NAT_MASQUERADE_IPV4=y ++CONFIG_NF_NAT_MASQUERADE_IPV6=y ++CONFIG_NF_TABLES_ARP=y ++CONFIG_NF_TABLES_BRIDGE=y ++CONFIG_NF_TABLES_INET=y ++CONFIG_NF_TABLES_IPV4=y ++CONFIG_NF_TABLES_IPV6=y ++CONFIG_NF_TABLES_NETDEV=y ++CONFIG_NLATTR=y ++CONFIG_NLS_DEFAULT="iso8859-1" ++CONFIG_NMI_LOG_BUF_SHIFT=13 ++CONFIG_OF_RESERVED_MEM=y ++CONFIG_OPTIMIZE_INLINING=y ++CONFIG_OVERLAY_FS=y ++CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW=y ++CONFIG_OVERLAY_FS_XINO_AUTO=y ++CONFIG_PACKET=y ++CONFIG_PAGE_SIZE_4KB=y ++CONFIG_PANIC_ON_OOPS=y ++CONFIG_PANIC_ON_OOPS_VALUE=1 ++CONFIG_PARTITION_ADVANCED=y ++CONFIG_PCIE_BUS_DEFAULT=y ++CONFIG_PCI_QUIRKS=y ++CONFIG_PCI_SYSCALL=y ++CONFIG_PINCONF=y ++CONFIG_PINCTRL_SINGLE=y ++CONFIG_PINMUX=y ++CONFIG_POSIX_TIMERS=y ++CONFIG_PPC_4K_PAGES=y ++CONFIG_PPP_FILTER=y ++CONFIG_PPP_MULTILINK=y ++CONFIG_PREEMPT_NONE=y ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++CONFIG_PRINTK=y ++CONFIG_PRINTK_NMI=y ++CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13 ++CONFIG_PRINT_STACK_DEPTH=64 ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PSTORE_DEFAULT_KMSG_BYTES=10240 ++CONFIG_PWRSEQ_EMMC=y ++CONFIG_PWRSEQ_SIMPLE=y ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++CONFIG_RCU_KTHREAD_PRIO=0 ++CONFIG_RCU_NEED_SEGCBLIST=y ++CONFIG_RCU_STALL_COMMON=y ++CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY=3 ++CONFIG_REISERFS_FS_XATTR=y ++CONFIG_RFKILL=y ++CONFIG_RTC_DRV_CMOS=y ++CONFIG_RTC_HCTOSYS=y ++CONFIG_RTC_HCTOSYS_DEVICE="rtc0" ++CONFIG_RTC_INTF_DEV=y ++CONFIG_RTC_INTF_PROC=y ++CONFIG_RTC_INTF_SYSFS=y ++CONFIG_RTC_LIB=y ++CONFIG_RTC_SYSTOHC=y ++CONFIG_RTC_SYSTOHC_DEVICE="rtc0" ++CONFIG_RT_MUTEXES=y ++CONFIG_RUNTIME_TESTING_MENU=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++CONFIG_RXKAD=y ++CONFIG_SATA_MOBILE_LPM_POLICY=0 ++CONFIG_SBITMAP=y ++CONFIG_SCHED_HRTICK=y ++CONFIG_SCHED_OMIT_FRAME_POINTER=y ++CONFIG_SCSI_DMA=y ++CONFIG_SCSI_LOWLEVEL=y ++CONFIG_SCSI_MOD=y ++CONFIG_SCSI_PROC_FS=y ++CONFIG_SECTION_MISMATCH_WARN_ONLY=y ++CONFIG_SECURITY_DMESG_RESTRICT=y ++CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=0 ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_16550A_VARIANTS=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_DMA=y ++CONFIG_SERIAL_8250_NR_UARTS=3 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=3 ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++CONFIG_SERIAL_EARLYCON=y ++CONFIG_SHMEM=y ++CONFIG_SIGNALFD=y ++CONFIG_SLABINFO=y ++CONFIG_SLAB_MERGE_DEFAULT=y ++CONFIG_SLUB=y ++CONFIG_SLUB_CPU_PARTIAL=y ++CONFIG_SND_DRIVERS=y ++CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 ++CONFIG_SND_HDA_PREALLOC_SIZE=64 ++CONFIG_SND_MAX_CARDS=16 ++CONFIG_SND_OSSEMUL=y ++CONFIG_SND_PCI=y ++CONFIG_SND_PCM_OSS_PLUGINS=y ++CONFIG_SND_PROC_FS=y ++CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y ++CONFIG_SND_USB=y ++CONFIG_SND_VERBOSE_PROCFS=y ++CONFIG_SND_X86=y ++CONFIG_SPLIT_PTLOCK_CPUS=4 ++CONFIG_SQUASHFS=y ++CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y ++CONFIG_SQUASHFS_EMBEDDED=y ++CONFIG_SQUASHFS_FILE_DIRECT=y ++CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 ++CONFIG_SQUASHFS_XZ=y ++CONFIG_SSB_POSSIBLE=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_STAGING=y ++CONFIG_STANDALONE=y ++CONFIG_STDBINUTILS=y ++CONFIG_STP=y ++CONFIG_STRICT_KERNEL_RWX=y ++CONFIG_STRICT_MODULE_RWX=y ++CONFIG_STRIP_ASM_SYMS=y ++CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES=y ++CONFIG_SWAP=y ++CONFIG_SYMBOLIC_ERRNAME=y ++CONFIG_SYN_COOKIES=y ++CONFIG_SYSCTL=y ++CONFIG_SYSFS=y ++CONFIG_SYSTEM_TRUSTED_KEYS="" ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++CONFIG_TCP_CONG_ADVANCED=y ++CONFIG_TCP_CONG_CUBIC=y ++CONFIG_TEXTSEARCH=y ++CONFIG_THIN_ARCHIVES=y ++CONFIG_TICK_ONESHOT=y ++CONFIG_TIMERFD=y ++CONFIG_TINY_RCU=y ++CONFIG_TMPFS=y ++CONFIG_TMPFS_XATTR=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_TRACING_SUPPORT=y ++CONFIG_TRAD_SIGNALS=y ++CONFIG_TTY=y ++CONFIG_UBIFS_FS_LZO=y ++CONFIG_UBIFS_FS_XATTR=y ++CONFIG_UBIFS_FS_ZLIB=y ++CONFIG_UBIFS_FS_ZSTD=y ++CONFIG_UBSAN_ALIGNMENT=y ++CONFIG_UEVENT_HELPER=y ++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++CONFIG_UID16=y ++CONFIG_UNIX=y ++CONFIG_UNIX98_PTYS=y ++CONFIG_UNIX_SCM=y ++CONFIG_USBIP_VHCI_HC_PORTS=8 ++CONFIG_USBIP_VHCI_NR_HCS=1 ++CONFIG_USB_ALI_M5632=y ++CONFIG_USB_AN2720=y ++CONFIG_USB_ARCH_HAS_HCD=y ++CONFIG_USB_ARMLINUX=y ++CONFIG_USB_AUTOSUSPEND_DELAY=2 ++CONFIG_USB_BELKIN=y ++CONFIG_USB_DEFAULT_PERSIST=y ++CONFIG_USB_EHCI_ROOT_HUB_TT=y ++CONFIG_USB_EHCI_TT_NEWSCHED=y ++CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_OHCI_LITTLE_ENDIAN=y ++CONFIG_USB_SERIAL_GENERIC=y ++CONFIG_USB_SERIAL_KEYSPAN_MPR=y ++CONFIG_USB_SERIAL_KEYSPAN_USA18X=y ++CONFIG_USB_SERIAL_KEYSPAN_USA19=y ++CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y ++CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y ++CONFIG_USB_SERIAL_KEYSPAN_USA19W=y ++CONFIG_USB_SERIAL_KEYSPAN_USA28=y ++CONFIG_USB_SERIAL_KEYSPAN_USA28X=y ++CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y ++CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y ++CONFIG_USB_SERIAL_KEYSPAN_USA49W=y ++CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y ++CONFIG_USB_SERIAL_SAFE_PADDED=y ++CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y ++CONFIG_VDSO=y ++CONFIG_VHOST_MENU=y ++CONFIG_VIRTIO_MENU=y ++CONFIG_VIRT_TO_BUS=y ++CONFIG_VLAN_8021Q=y ++CONFIG_VMSPLIT_3G=y ++CONFIG_WATCHDOG=y ++CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y ++CONFIG_WATCHDOG_OPEN_TIMEOUT=0 ++CONFIG_WEXT_CORE=y ++CONFIG_WEXT_PRIV=y ++CONFIG_WEXT_PROC=y ++CONFIG_WEXT_SPY=y ++CONFIG_WILINK_PLATFORM_DATA=y ++CONFIG_WIRELESS=y ++CONFIG_WIRELESS_EXT=y ++CONFIG_WLAN=y ++CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y ++CONFIG_X86_SYSFB=y ++CONFIG_XEN_SCRUB_PAGES_DEFAULT=y ++CONFIG_XFRM=y ++CONFIG_XZ_DEC=y ++CONFIG_ZONE_DMA=y ++CONFIG_64BIT=y ++CONFIG_AQUANTIA_PHY=y ++CONFIG_ARCH_DMA_ADDR_T_64BIT=y ++CONFIG_ARCH_KEEP_MEMBLOCK=y ++CONFIG_ARCH_MEDIATEK=y ++CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y ++CONFIG_ARCH_MMAP_RND_BITS=18 ++CONFIG_ARCH_MMAP_RND_BITS_MAX=24 ++CONFIG_ARCH_MMAP_RND_BITS_MIN=18 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 ++CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 ++CONFIG_ARCH_PROC_KCORE_TEXT=y ++CONFIG_ARCH_SPARSEMEM_ENABLE=y ++CONFIG_ARCH_STACKWALK=y ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_ARCH_WANTS_NO_INSTR=y ++CONFIG_ARM64=y ++CONFIG_ARM64_4K_PAGES=y ++CONFIG_ARM64_CRYPTO=y ++CONFIG_ARM64_ERRATUM_843419=y ++CONFIG_ARM64_ERRATUM_845719=y ++CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y ++CONFIG_ARM64_MODULE_PLTS=y ++CONFIG_ARM64_PAGE_SHIFT=12 ++CONFIG_ARM64_PA_BITS=48 ++CONFIG_ARM64_PA_BITS_48=y ++CONFIG_ARM64_TAGGED_ADDR_ABI=y ++CONFIG_ARM64_VA_BITS=39 ++CONFIG_ARM64_VA_BITS_39=y ++CONFIG_ARM_AMBA=y ++CONFIG_ARM_ARCH_TIMER=y ++CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y ++CONFIG_ARM_GIC=y ++CONFIG_ARM_GIC_V2M=y ++CONFIG_ARM_GIC_V3=y ++CONFIG_ARM_GIC_V3_ITS=y ++CONFIG_ARM_GIC_V3_ITS_PCI=y ++CONFIG_ARM_MEDIATEK_CPUFREQ=y ++CONFIG_ARM_PMU=y ++CONFIG_ARM_PSCI_FW=y ++CONFIG_ATA=y ++CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_SD=y ++CONFIG_BLK_MQ_PCI=y ++CONFIG_BLK_PM=y ++CONFIG_BLOCK_COMPAT=y ++CONFIG_BSD_PROCESS_ACCT=y ++CONFIG_BSD_PROCESS_ACCT_V3=y ++CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y ++CONFIG_CLKSRC_MMIO=y ++CONFIG_CLONE_BACKWARDS=y ++CONFIG_COMMON_CLK=y ++CONFIG_COMMON_CLK_MEDIATEK=y ++CONFIG_COMMON_CLK_MT2712=y ++CONFIG_COMMON_CLK_MT7622=y ++CONFIG_COMMON_CLK_MT7622_AUDSYS=y ++CONFIG_COMMON_CLK_MT7622_ETHSYS=y ++CONFIG_COMMON_CLK_MT7622_HIFSYS=y ++CONFIG_COMMON_CLK_MT7986=y ++CONFIG_COMMON_CLK_MT7986_ETHSYS=y ++CONFIG_COMMON_CLK_MT8183=y ++CONFIG_COMMON_CLK_MT8516=y ++CONFIG_COMPAT=y ++CONFIG_COMPAT_32BIT_TIME=y ++CONFIG_COMPAT_BINFMT_ELF=y ++CONFIG_COMPAT_NETLINK_MESSAGES=y ++CONFIG_COMPAT_OLD_SIGACTION=y ++CONFIG_CONFIGFS_FS=y ++CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15 ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ATTR_SET=y ++CONFIG_CPU_FREQ_GOV_COMMON=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_STAT=y ++CONFIG_CPU_RMAP=y ++CONFIG_CPU_THERMAL=y ++CONFIG_CRC16=y ++CONFIG_CRYPTO_AES_ARM64=y ++CONFIG_CRYPTO_AES_ARM64_CE=y ++CONFIG_CRYPTO_AES_ARM64_CE_BLK=y ++CONFIG_CRYPTO_AES_ARM64_CE_CCM=y ++CONFIG_CRYPTO_CMAC=y ++CONFIG_CRYPTO_CRC32=y ++CONFIG_CRYPTO_CRC32C=y ++CONFIG_CRYPTO_CRYPTD=y ++CONFIG_CRYPTO_DEFLATE=y ++CONFIG_CRYPTO_DRBG=y ++CONFIG_CRYPTO_DRBG_HMAC=y ++CONFIG_CRYPTO_DRBG_MENU=y ++CONFIG_CRYPTO_ECB=y ++CONFIG_CRYPTO_ECC=y ++CONFIG_CRYPTO_ECDH=y ++CONFIG_CRYPTO_GHASH_ARM64_CE=y ++CONFIG_CRYPTO_HASH_INFO=y ++CONFIG_CRYPTO_HMAC=y ++CONFIG_CRYPTO_JITTERENTROPY=y ++CONFIG_CRYPTO_LIB_SHA256=y ++CONFIG_CRYPTO_LZO=y ++CONFIG_CRYPTO_RNG=y ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_RNG_DEFAULT=y ++CONFIG_CRYPTO_SHA256=y ++CONFIG_CRYPTO_SHA256_ARM64=y ++CONFIG_CRYPTO_SHA2_ARM64_CE=y ++CONFIG_CRYPTO_SHA512=y ++CONFIG_CRYPTO_SIMD=y ++CONFIG_CRYPTO_ZSTD=y ++CONFIG_DCACHE_WORD_ACCESS=y ++CONFIG_DEBUG_MISC=y ++CONFIG_DIMLIB=y ++CONFIG_DMADEVICES=y ++CONFIG_DMATEST=y ++CONFIG_DMA_DIRECT_REMAP=y ++CONFIG_DMA_ENGINE=y ++CONFIG_DMA_ENGINE_RAID=y ++CONFIG_DMA_OF=y ++CONFIG_DMA_REMAP=y ++CONFIG_DMA_VIRTUAL_CHANNELS=y ++CONFIG_DTC=y ++CONFIG_DYNAMIC_DEBUG=y ++CONFIG_EDAC_SUPPORT=y ++CONFIG_EINT_MTK=y ++CONFIG_EXT4_FS=y ++CONFIG_F2FS_FS=y ++CONFIG_FIT_PARTITION=y ++CONFIG_FIXED_PHY=y ++CONFIG_FIX_EARLYCON_MEM=y ++CONFIG_FRAME_POINTER=y ++CONFIG_FS_IOMAP=y ++CONFIG_FS_MBCACHE=y ++CONFIG_FWNODE_MDIO=y ++CONFIG_FW_LOADER_PAGED_BUF=y ++CONFIG_GENERIC_ALLOCATOR=y ++CONFIG_GENERIC_ARCH_TOPOLOGY=y ++CONFIG_GENERIC_BUG=y ++CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y ++CONFIG_GENERIC_CPU_AUTOPROBE=y ++CONFIG_GENERIC_CPU_VULNERABILITIES=y ++CONFIG_GENERIC_CSUM=y ++CONFIG_GENERIC_EARLY_IOREMAP=y ++CONFIG_GENERIC_FIND_FIRST_BIT=y ++CONFIG_GENERIC_GETTIMEOFDAY=y ++CONFIG_GENERIC_IDLE_POLL_SETUP=y ++CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y ++CONFIG_GENERIC_IRQ_SHOW=y ++CONFIG_GENERIC_IRQ_SHOW_LEVEL=y ++CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y ++CONFIG_GENERIC_MSI_IRQ=y ++CONFIG_GENERIC_MSI_IRQ_DOMAIN=y ++CONFIG_GENERIC_PCI_IOMAP=y ++CONFIG_GENERIC_PHY=y ++CONFIG_GENERIC_PINCONF=y ++CONFIG_GENERIC_PINCTRL_GROUPS=y ++CONFIG_GENERIC_PINMUX_FUNCTIONS=y ++CONFIG_GENERIC_SCHED_CLOCK=y ++CONFIG_GENERIC_SMP_IDLE_THREAD=y ++CONFIG_GENERIC_STRNCPY_FROM_USER=y ++CONFIG_GENERIC_STRNLEN_USER=y ++CONFIG_GENERIC_TIME_VSYSCALL=y ++CONFIG_GLOB=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_CDEV=y ++CONFIG_GRO_CELLS=y ++CONFIG_HANDLE_DOMAIN_IRQ=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_HAS_DMA=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT_MAP=y ++CONFIG_HW_RANDOM=y ++CONFIG_HW_RANDOM_MTK=y ++CONFIG_I2C=y ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_CHARDEV=y ++CONFIG_I2C_MT65XX=y ++CONFIG_ICPLUS_PHY=y ++CONFIG_IIO=y ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_IO_URING=y ++CONFIG_IRQCHIP=y ++CONFIG_IRQ_DOMAIN=y ++CONFIG_IRQ_DOMAIN_HIERARCHY=y ++CONFIG_IRQ_FORCED_THREADING=y ++CONFIG_IRQ_TIME_ACCOUNTING=y ++CONFIG_IRQ_WORK=y ++CONFIG_JBD2=y ++CONFIG_JUMP_LABEL=y ++CONFIG_LIBFDT=y ++CONFIG_LOCK_DEBUGGING_SUPPORT=y ++CONFIG_LOCK_SPIN_ON_OWNER=y ++CONFIG_LZO_COMPRESS=y ++CONFIG_LZO_DECOMPRESS=y ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_MAXLINEAR_GPHY=y ++CONFIG_MDIO_BUS=y ++CONFIG_MDIO_DEVICE=y ++CONFIG_MDIO_DEVRES=y ++CONFIG_MEDIATEK_GE_PHY=y ++#CONFIG_MEDIATEK_MT6577_AUXADC=y ++CONFIG_MEDIATEK_WATCHDOG=y ++CONFIG_MEMFD_CREATE=y ++CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7 ++CONFIG_MFD_SYSCON=y ++CONFIG_MIGRATION=y ++CONFIG_MMC=y ++CONFIG_MMC_BLOCK=y ++CONFIG_MMC_CQHCI=y ++CONFIG_MMC_MTK=y ++CONFIG_MODULES_TREE_LOOKUP=y ++CONFIG_MODULES_USE_ELF_RELA=y ++CONFIG_MTD_NAND_CORE=y ++CONFIG_MTD_NAND_ECC=y ++CONFIG_MTD_NAND_ECC_MEDIATEK=y ++CONFIG_MTD_NAND_ECC_SW_HAMMING=y ++CONFIG_MTD_NAND_MTK=y ++CONFIG_MTD_NAND_MTK_BMT=y ++CONFIG_MTD_PARSER_TRX=y ++CONFIG_MTD_RAW_NAND=y ++CONFIG_MTD_SPI_NAND=y ++CONFIG_MTD_SPI_NOR=y ++CONFIG_MTD_SPLIT_FIRMWARE=y ++CONFIG_MTD_SPLIT_FIT_FW=y ++CONFIG_MTD_UBI=y ++CONFIG_MTD_UBI_BEB_LIMIT=20 ++CONFIG_MTD_UBI_BLOCK=y ++CONFIG_MTD_UBI_WL_THRESHOLD=4096 ++CONFIG_MTK_EFUSE=y ++CONFIG_MTK_HSDMA=y ++CONFIG_MTK_INFRACFG=y ++CONFIG_MTK_PMIC_WRAP=y ++CONFIG_MTK_SCPSYS=y ++CONFIG_MTK_SCPSYS_PM_DOMAINS=y ++CONFIG_MTK_THERMAL=y ++CONFIG_MTK_SOC_THERMAL=y ++CONFIG_MTK_TIMER=y ++CONFIG_MUTEX_SPIN_ON_OWNER=y ++CONFIG_NEED_DMA_MAP_STATE=y ++CONFIG_NEED_SG_DMA_LENGTH=y ++CONFIG_NET_DEVLINK=y ++CONFIG_NET_DSA=y ++CONFIG_NET_DSA_MT7530=y ++CONFIG_NET_DSA_TAG_MTK=y ++CONFIG_NET_FLOW_LIMIT=y ++CONFIG_NET_MEDIATEK_SOC=y ++CONFIG_NET_MEDIATEK_SOC_WED=y ++CONFIG_NET_SELFTESTS=y ++CONFIG_NET_SWITCHDEV=y ++CONFIG_NET_VENDOR_MEDIATEK=y ++CONFIG_NLS=y ++CONFIG_NO_HZ_COMMON=y ++CONFIG_NO_HZ_IDLE=y ++CONFIG_NR_CPUS=4 ++CONFIG_NVMEM=y ++CONFIG_NVMEM_SYSFS=y ++CONFIG_OF=y ++CONFIG_OF_ADDRESS=y ++CONFIG_OF_DYNAMIC=y ++CONFIG_OF_EARLY_FLATTREE=y ++CONFIG_OF_FLATTREE=y ++CONFIG_OF_GPIO=y ++CONFIG_OF_IRQ=y ++CONFIG_OF_KOBJ=y ++CONFIG_OF_MDIO=y ++CONFIG_OF_OVERLAY=y ++CONFIG_OF_RESOLVE=y ++CONFIG_OLD_SIGSUSPEND3=y ++CONFIG_PADATA=y ++CONFIG_PARTITION_PERCPU=y ++CONFIG_PCI=y ++CONFIG_PCIEAER=y ++CONFIG_PCIEASPM=y ++CONFIG_PCIEASPM_PERFORMANCE=y ++CONFIG_PCIEPORTBUS=y ++CONFIG_PCIE_MEDIATEK=y ++CONFIG_PCIE_MEDIATEK_GEN3=y ++CONFIG_PCIE_PME=y ++CONFIG_PCI_DEBUG=y ++CONFIG_PCI_DOMAINS=y ++CONFIG_PCI_DOMAINS_GENERIC=y ++CONFIG_PCI_MSI=y ++CONFIG_PCI_MSI_IRQ_DOMAIN=y ++CONFIG_PERF_EVENTS=y ++CONFIG_PGTABLE_LEVELS=3 ++CONFIG_PHYLIB=y ++CONFIG_PHYLINK=y ++CONFIG_PHYS_ADDR_T_64BIT=y ++CONFIG_PHY_MTK_TPHY=y ++CONFIG_PINCTRL=y ++CONFIG_PINCTRL_MT7622=y ++CONFIG_PINCTRL_MT7986=y ++CONFIG_PINCTRL_MT8516=y ++CONFIG_PINCTRL_MTK=y ++CONFIG_PINCTRL_MTK_MOORE=y ++CONFIG_PINCTRL_MTK_V2=y ++CONFIG_PM=y ++CONFIG_PM_CLK=y ++CONFIG_PM_GENERIC_DOMAINS=y ++CONFIG_PM_GENERIC_DOMAINS_OF=y ++CONFIG_PM_OPP=y ++CONFIG_POWER_RESET=y ++CONFIG_POWER_RESET_SYSCON=y ++CONFIG_POWER_SUPPLY=y ++CONFIG_PRINTK_TIME=y ++CONFIG_PSTORE=y ++CONFIG_PSTORE_COMPRESS=n ++#CONFIG_PSTORE_COMPRESS_DEFAULT="deflate" ++CONFIG_PSTORE_CONSOLE=y ++#CONFIG_PSTORE_DEFLATE_COMPRESS=y ++#CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT=y ++CONFIG_PSTORE_PMSG=y ++CONFIG_PSTORE_RAM=y ++CONFIG_PTP_1588_CLOCK_OPTIONAL=y ++CONFIG_PWM=y ++CONFIG_PWM_MEDIATEK=y ++CONFIG_PWM_SYSFS=y ++CONFIG_QUEUED_RWLOCKS=y ++CONFIG_QUEUED_SPINLOCKS=y ++CONFIG_RAS=y ++CONFIG_RATIONAL=y ++CONFIG_REALTEK_PHY=y ++CONFIG_REED_SOLOMON=y ++CONFIG_REED_SOLOMON_DEC8=y ++CONFIG_REED_SOLOMON_ENC8=y ++CONFIG_REGMAP=y ++CONFIG_REGMAP_MMIO=y ++CONFIG_REGULATOR=y ++CONFIG_REGULATOR_FIXED_VOLTAGE=y ++CONFIG_REGULATOR_MT6380=y ++CONFIG_RESET_CONTROLLER=y ++CONFIG_RFS_ACCEL=y ++CONFIG_RODATA_FULL_DEFAULT_ENABLED=y ++CONFIG_RPS=y ++CONFIG_RTC_CLASS=y ++CONFIG_RTC_DRV_MT7622=y ++CONFIG_RTC_I2C_AND_SPI=y ++CONFIG_RTL8367S_GSW=y ++CONFIG_RWSEM_SPIN_ON_OWNER=y ++CONFIG_SCHED_MC=y ++CONFIG_SCSI=y ++CONFIG_SCSI_COMMON=y ++CONFIG_SERIAL_8250_FSL=y ++CONFIG_SERIAL_8250_MT6577=y ++CONFIG_SERIAL_DEV_BUS=y ++CONFIG_SERIAL_DEV_CTRL_TTYPORT=y ++CONFIG_SERIAL_MCTRL_GPIO=y ++CONFIG_SERIAL_OF_PLATFORM=y ++CONFIG_SGL_ALLOC=y ++CONFIG_SG_POOL=y ++CONFIG_SMP=y ++CONFIG_SOCK_RX_QUEUE_MAPPING=y ++CONFIG_SPARSEMEM=y ++CONFIG_SPARSEMEM_EXTREME=y ++CONFIG_SPARSEMEM_VMEMMAP=y ++CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y ++CONFIG_SPARSE_IRQ=y ++CONFIG_SPI=y ++CONFIG_SPI_DYNAMIC=y ++CONFIG_SPI_MASTER=y ++CONFIG_SPI_MEM=y ++CONFIG_SPI_MT65XX=y ++CONFIG_SPI_MTK_NOR=y ++CONFIG_SPI_MTK_SNFI=y ++CONFIG_SRCU=y ++CONFIG_SWCONFIG=y ++CONFIG_SWIOTLB=y ++CONFIG_SWPHY=y ++CONFIG_SYSCTL_EXCEPTION_TRACE=y ++CONFIG_SYSVIPC_COMPAT=y ++CONFIG_THERMAL=y ++CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y ++CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 ++CONFIG_THERMAL_EMULATION=y ++CONFIG_THERMAL_GOV_BANG_BANG=y ++CONFIG_THERMAL_GOV_FAIR_SHARE=y ++CONFIG_THERMAL_GOV_STEP_WISE=y ++CONFIG_THERMAL_GOV_USER_SPACE=y ++CONFIG_THERMAL_OF=y ++CONFIG_THERMAL_WRITABLE_TRIPS=y ++CONFIG_THREAD_INFO_IN_TASK=y ++CONFIG_TICK_CPU_ACCOUNTING=y ++CONFIG_TIMER_OF=y ++CONFIG_TIMER_PROBE=y ++CONFIG_TREE_RCU=y ++CONFIG_TREE_SRCU=y ++CONFIG_UBIFS_FS=y ++CONFIG_USB=y ++CONFIG_USB_COMMON=y ++CONFIG_USB_SUPPORT=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_MTK=y ++CONFIG_VMAP_STACK=y ++CONFIG_WATCHDOG_CORE=y ++CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y ++CONFIG_WATCHDOG_PRETIMEOUT_GOV=y ++CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y ++CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m ++CONFIG_WATCHDOG_SYSFS=y ++CONFIG_XPS=y ++CONFIG_XXHASH=y ++CONFIG_ZLIB_DEFLATE=y ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZONE_DMA32=y ++CONFIG_ZSTD_COMPRESS=y ++CONFIG_ZSTD_DECOMPRESS=y ++ ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_DEVTMPFS_SAFE=y ++ ++CONFIG_WLAN_VENDOR_MEDIATEK=y ++CONFIG_CFG80211=m ++CONFIG_CFG80211_WEXT=y ++CONFIG_MAC80211=y ++CONFIG_MAC80211_LEDS=y ++CONFIG_MT7915E=m ++CONFIG_MT798X_WMAC=y ++ ++CONFIG_VFAT_FS=y ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_CODEPAGE_852=y ++CONFIG_NLS_ISO8859_1=y ++CONFIG_NLS_ISO8859_15=y ++ ++CONFIG_USB_STORAGE=y ++CONFIG_I2C_GPIO=y ++CONFIG_SFP=y ++CONFIG_BLK_DEV_NVME=y ++CONFIG_NVME_HWMON=y ++ ++CONFIG_USB_USBNET=m ++CONFIG_USB_SERIAL=m ++CONFIG_USB_SERIAL_OPTION=m ++CONFIG_USB_SERIAL_QUALCOMM=m ++CONFIG_USB_NET_CDC_MBIM=m ++CONFIG_USB_NET_QMI_WWAN=m ++ ++CONFIG_NVMEM_MTK_EFUSE=y ++CONFIG_SENSORS_PWM_FAN=y ++ ++CONFIG_DUMMY=m ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++CONFIG_IP_PNP_RARP=y ++CONFIG_IPV6_ROUTER_PREF=y ++CONFIG_IPV6_OPTIMISTIC_DAD=y ++CONFIG_INET6_AH=m ++CONFIG_INET6_ESP=m ++CONFIG_INET6_IPCOMP=m ++CONFIG_IPV6_MIP6=m ++CONFIG_IPV6_TUNNEL=m ++CONFIG_IPV6_MULTIPLE_TABLES=y ++CONFIG_NETLINK_DIAG=y ++CONFIG_INET_UDP_DIAG=m ++CONFIG_NET_IPIP=m ++CONFIG_IP_MROUTE=y ++CONFIG_IP_PIMSM_V1=y ++CONFIG_IP_PIMSM_V2=y ++CONFIG_IPV6=y ++CONFIG_NETFILTER=y ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_IPV4=m ++CONFIG_NF_CONNTRACK_IPV6=m ++CONFIG_NETFILTER_NETLINK=m ++CONFIG_NF_CT_NETLINK=m ++CONFIG_IP_NF_IPTABLES=m ++CONFIG_NF_LOG_IPV4=m ++CONFIG_NF_REJECT_IPV4=m ++CONFIG_IP6_NF_IPTABLES=m ++CONFIG_NF_LOG_IPV6=m ++CONFIG_NF_REJECT_IPV6=m ++CONFIG_IP_NF_NAT=m ++CONFIG_IP6_NF_NAT=m ++CONFIG_NF_NAT_MASQUERADE_IPV4=y ++CONFIG_NF_NAT_MASQUERADE_IPV6=y ++CONFIG_IP_NF_FILTER=m ++CONFIG_IP6_NF_FILTER=m ++CONFIG_IP_NF_TARGET_MASQUERADE=m ++CONFIG_IP6_NF_TARGET_MASQUERADE=m ++CONFIG_IP_NF_MANGLE=m ++CONFIG_IP6_NF_MANGLE=m ++CONFIG_IP_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_MATCH_RT=m ++CONFIG_NETFILTER_SYNPROXY=m ++CONFIG_IP_NF_TARGET_SYNPROXY=m ++CONFIG_IP6_NF_TARGET_SYNPROXY=m ++CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m ++CONFIG_NETFILTER_XT_MATCH_LIMIT=m ++CONFIG_NETFILTER_XT_MATCH_STATE=m ++CONFIG_NETFILTER_XT_TARGET_LOG=m ++CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m ++CONFIG_NETFILTER_XT_MATCH_MAC=m ++CONFIG_NETFILTER_XT_MATCH_RECENT=m ++CONFIG_NETFILTER_XT_MATCH_IPRANGE=m ++CONFIG_NETFILTER_XT_MARK=m ++CONFIG_NETFILTER_XT_CONNMARK=m ++CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m ++CONFIG_IP_VS=m ++CONFIG_NETFILTER_XT_MATCH_IPVS=m ++CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m ++#CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m ++CONFIG_NF_TABLES=m ++CONFIG_NF_TABLES_SET=m ++CONFIG_NF_TPROXY_IPV4=m ++CONFIG_NF_TPROXY_IPV6=m ++CONFIG_NFT_NUMGEN=m ++CONFIG_NFT_CT=m ++CONFIG_NFT_COUNTER=m ++CONFIG_NFT_CONNLIMIT=m ++CONFIG_NFT_LOG=m ++CONFIG_NFT_LIMIT=m ++CONFIG_NFT_MASQ=m ++CONFIG_NFT_NAT=m ++CONFIG_NFT_QUEUE=m ++CONFIG_NFT_REDIR=m ++CONFIG_NFT_TUNNEL=m ++CONFIG_NFT_OBJREF=m ++CONFIG_NFT_QUOTA=m ++CONFIG_NFT_REJECT=m ++CONFIG_NFT_COMPAT=m ++CONFIG_NFT_HASH=m ++CONFIG_NFT_XFRM=m ++CONFIG_NFT_SOCKET=m ++CONFIG_NFT_OSF=m ++CONFIG_NFT_TPROXY=m ++CONFIG_NFT_SYNPROXY=m ++CONFIG_NFTL=m ++CONFIG_NFTL_RW=y ++CONFIG_NFT_FIB_INET=m ++CONFIG_NFT_FIB_IPV4=m ++CONFIG_NFT_FIB_IPV6=m ++CONFIG_NF_FLOW_TABLE=m ++CONFIG_NF_FLOW_TABLE_INET=m ++CONFIG_NF_FLOW_TABLE_IPV4=m ++CONFIG_NF_FLOW_TABLE_IPV6=m ++CONFIG_NFT_FLOW_OFFLOAD=m ++CONFIG_NF_CONNTRACK_FTP=m ++CONFIG_NF_NAT_FTP=m ++CONFIG_PPP=m ++CONFIG_PPPOE=m ++CONFIG_PPP_DEFLATE=m ++CONFIG_PPP_MPPE=m ++CONFIG_VETH=m ++CONFIG_TUN=m ++CONFIG_VLAN_8021Q_GVRP=y ++CONFIG_VLAN_8021Q_MVRP=y ++CONFIG_NET_L3_MASTER_DEV=y ++CONFIG_IPVLAN=m ++CONFIG_MACVLAN=m ++CONFIG_NET_CLS_ACT=y ++# QoS and/or fair queueing ++CONFIG_NET_SCH_CBQ=m ++CONFIG_NET_SCH_HTB=m ++CONFIG_NET_SCH_CSZ=m ++CONFIG_NET_SCH_PRIO=m ++CONFIG_NET_SCH_RED=m ++CONFIG_NET_SCH_SFQ=m ++CONFIG_NET_SCH_TEQL=m ++CONFIG_NET_SCH_TBF=m ++CONFIG_NET_SCH_GRED=m ++CONFIG_NET_SCH_DSMARK=m ++CONFIG_NET_SCH_INGRESS=m ++#CONFIG_NET_SCH_NETEM=m ++CONFIG_NET_QOS=y ++CONFIG_NET_ESTIMATOR=y ++CONFIG_NET_CLS_TCINDEX=m ++CONFIG_NET_CLS_ROUTE4=m ++CONFIG_NET_CLS_ROUTE=y ++CONFIG_NET_CLS_FW=m ++CONFIG_NET_CLS_U32=m ++CONFIG_NET_CLS_RSVP=m ++CONFIG_NET_CLS_RSVP6=m ++CONFIG_NET_CLS_POLICE=y ++ ++CONFIG_NET_ACT_VLAN=m ++CONFIG_NET_ACT_POLICE=m ++CONFIG_NET_ACT_GACT=m ++CONFIG_NET_ACT_MIRRED=m ++CONFIG_NET_ACT_SAMPLE=y ++CONFIG_NET_ACT_IPT=m ++CONFIG_NET_ACT_NAT=m ++CONFIG_NET_ACT_PEDIT=m ++CONFIG_NET_ACT_SIMP=m ++CONFIG_NET_ACT_SKBEDIT=m ++CONFIG_NET_ACT_CSUM=m ++# CONFIG_NET_ACT_BPF is not set ++CONFIG_NET_ACT_CONNMARK=m ++CONFIG_NET_ACT_CTINFO=m ++CONFIG_NET_ACT_SKBMOD=m ++# CONFIG_NET_ACT_IFE is not set ++CONFIG_NET_ACT_TUNNEL_KEY=m ++CONFIG_NET_ACT_CT=m ++# CONFIG_NET_ACT_GATE is not set ++ ++#NFS Client ++CONFIG_NFS_FS=y ++CONFIG_NFS_V2=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_SWAP=y ++CONFIG_NFS_V4_1=y ++CONFIG_NFS_V4_2=y ++CONFIG_PNFS_FILE_LAYOUT=m ++CONFIG_PNFS_BLOCK=m ++CONFIG_PNFS_FLEXFILE_LAYOUT=m ++CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org" ++CONFIG_NFS_V4_1_MIGRATION=y ++CONFIG_NFS_USE_LEGACY_DNS=y ++CONFIG_ROOT_NFS=y ++ ++#NFS Server ++CONFIG_NFSD=m ++CONFIG_NFSD_V2_ACL=y ++CONFIG_NFSD_V3_ACL=y ++CONFIG_NFSD_V4=y ++CONFIG_NFSD_PNFS=y ++CONFIG_NFSD_BLOCKLAYOUT=y ++CONFIG_NFSD_SCSILAYOUT=y ++CONFIG_NFSD_FLEXFILELAYOUT=y ++CONFIG_NFSD_FAULT_INJECTION=y ++CONFIG_NFS_ACL_SUPPORT=m ++ ++#usb-tethering ++CONFIG_USB_NET_CDCETHER=m ++CONFIG_USB_NET_CDC_EEM=m ++CONFIG_USB_NET_RNDIS_HOST=m ++ ++#for lxc ++CONFIG_CGROUPS=y ++CONFIG_NAMESPACES=y ++CONFIG_USER_NS=y ++CONFIG_MEMCG=y ++CONFIG_CGROUP_CPUACCT=y ++CONFIG_CGROUP_DEVICE=y ++CONFIG_CGROUP_SCHED=y ++CONFIG_CPUSETS=y ++CONFIG_UNIX_DIAG=m ++CONFIG_PACKET_DIAG=m ++CONFIG_FUSE_FS=m ++ ++#for docker ++CONFIG_CGROUP_FREEZER=y ++CONFIG_MEMCG_SWAP=y ++CONFIG_MEMCG_SWAP_ENABLED=y ++CONFIG_BLK_CGROUP=y ++CONFIG_CFS_BANDWIDTH=y ++CONFIG_RT_GROUP_SCHED=y ++CONFIG_CGROUP_PIDS=y ++CONFIG_CGROUP_PERF=y ++CONFIG_CGROUP_NET_CLASSID=y ++CONFIG_CGROUP_NET_PRIO=y ++CONFIG_CFQ_GROUP_IOSCHED=y ++CONFIG_POSIX_MQUEUE=y ++CONFIG_POSIX_MQUEUE_SYSCTL=y ++CONFIG_HAVE_ARCH_SECCOMP_FILTER=y ++CONFIG_SECCOMP_FILTER=y ++CONFIG_SECCOMP=y ++ ++CONFIG_NET_IPGRE=m ++CONFIG_NET_IPGRE_DEMUX=m ++ ++#for r3mini ++CONFIG_AIR_EN8811H_PHY=y ++CONFIG_LED_TRIGGER_PHY=y ++ ++CONFIG_EXTRA_FIRMWARE="airoha/EthMD32.dm.bin airoha/EthMD32.DSP.bin" ++CONFIG_EXTRA_FIRMWARE_DIR="utils/firmware/" ++ ++CONFIG_PANIC_TIMEOUT=30 +diff --git a/arch/arm64/configs/quartz64_defconfig b/arch/arm64/configs/quartz64_defconfig +new file mode 100644 +index 000000000000..0d079383b0c0 +--- /dev/null ++++ b/arch/arm64/configs/quartz64_defconfig +@@ -0,0 +1,922 @@ ++CONFIG_LOCALVERSION="-bpi-r2pro" ++CONFIG_LOCALVERSION_AUTO=n ++ ++CONFIG_SYSVIPC=y ++CONFIG_POSIX_MQUEUE=y ++CONFIG_AUDIT=y ++CONFIG_GENERIC_IRQ_DEBUGFS=y ++CONFIG_NO_HZ_IDLE=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_BPF_JIT=y ++CONFIG_PREEMPT=y ++CONFIG_IRQ_TIME_ACCOUNTING=y ++CONFIG_BSD_PROCESS_ACCT=y ++CONFIG_BSD_PROCESS_ACCT_V3=y ++CONFIG_TASKSTATS=y ++CONFIG_TASK_DELAY_ACCT=y ++CONFIG_TASK_XACCT=y ++CONFIG_TASK_IO_ACCOUNTING=y ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_LOG_BUF_SHIFT=18 ++CONFIG_NUMA_BALANCING=y ++CONFIG_MEMCG=y ++CONFIG_BLK_CGROUP=y ++CONFIG_CGROUP_PIDS=y ++CONFIG_CGROUP_HUGETLB=y ++CONFIG_CPUSETS=y ++CONFIG_CGROUP_DEVICE=y ++CONFIG_CGROUP_CPUACCT=y ++CONFIG_CGROUP_PERF=y ++CONFIG_CGROUP_MISC=y ++CONFIG_USER_NS=y ++CONFIG_SCHED_AUTOGROUP=y ++CONFIG_KALLSYMS_ALL=y ++# CONFIG_COMPAT_BRK is not set ++CONFIG_PROFILING=y ++CONFIG_ARCH_ROCKCHIP=y ++CONFIG_SCHED_MC=y ++CONFIG_SCHED_SMT=y ++CONFIG_NUMA=y ++CONFIG_KEXEC=y ++CONFIG_KEXEC_FILE=y ++CONFIG_CRASH_DUMP=y ++CONFIG_XEN=y ++CONFIG_RANDOMIZE_BASE=y ++CONFIG_HIBERNATION=y ++CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y ++CONFIG_ENERGY_MODEL=y ++CONFIG_ARM_CPUIDLE=y ++CONFIG_ARM_PSCI_CPUIDLE=y ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_STAT=y ++#CONFIG_CPU_FREQ_GOV_POWERSAVE=m ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++#CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m ++CONFIG_CPUFREQ_DT=y ++#CONFIG_ACPI_CPPC_CPUFREQ=m ++CONFIG_ARM_SCPI_CPUFREQ=y ++CONFIG_ARM_SCMI_CPUFREQ=y ++CONFIG_ACPI=y ++CONFIG_ACPI_APEI=y ++CONFIG_ACPI_APEI_GHES=y ++CONFIG_ACPI_APEI_MEMORY_FAILURE=y ++CONFIG_ACPI_APEI_EINJ=y ++CONFIG_VIRTUALIZATION=y ++CONFIG_KVM=y ++CONFIG_ARM64_CRYPTO=y ++CONFIG_CRYPTO_SHA1_ARM64_CE=y ++CONFIG_CRYPTO_SHA2_ARM64_CE=y ++#CONFIG_CRYPTO_SHA512_ARM64_CE=m ++#CONFIG_CRYPTO_SHA3_ARM64=m ++#CONFIG_CRYPTO_SM3_ARM64_CE=m ++CONFIG_CRYPTO_GHASH_ARM64_CE=y ++#CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=m ++CONFIG_CRYPTO_AES_ARM64=y ++CONFIG_CRYPTO_AES_ARM64_CE_CCM=y ++CONFIG_CRYPTO_AES_ARM64_CE_BLK=y ++#CONFIG_CRYPTO_CHACHA20_NEON=m ++#CONFIG_CRYPTO_AES_ARM64_BS=m ++CONFIG_JUMP_LABEL=y ++CONFIG_COMPAT_32BIT_TIME=y ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++CONFIG_KSM=y ++CONFIG_MEMORY_FAILURE=y ++CONFIG_TRANSPARENT_HUGEPAGE=y ++CONFIG_CMA=y ++CONFIG_ZSWAP=y ++CONFIG_ZSWAP_COMPRESSOR_DEFAULT_ZSTD=y ++CONFIG_ZSWAP_ZPOOL_DEFAULT_ZSMALLOC=y ++CONFIG_ZSWAP_DEFAULT_ON=y ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++#CONFIG_IP_PNP_BOOTP=y ++#CONFIG_IPV6=m ++#CONFIG_NETFILTER=y ++#CONFIG_NF_CONNTRACK=m ++#CONFIG_NF_CONNTRACK_EVENTS=y ++#CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m ++#CONFIG_NETFILTER_XT_TARGET_LOG=m ++#CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m ++#CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m ++#CONFIG_NF_LOG_IPV4=m ++#CONFIG_IP_NF_IPTABLES=m ++#CONFIG_IP_NF_FILTER=m ++#CONFIG_IP_NF_TARGET_REJECT=m ++#CONFIG_IP_NF_NAT=m ++#CONFIG_IP_NF_TARGET_MASQUERADE=m ++#CONFIG_IP_NF_MANGLE=m ++#CONFIG_IP6_NF_IPTABLES=m ++#CONFIG_IP6_NF_FILTER=m ++#CONFIG_IP6_NF_TARGET_REJECT=m ++#CONFIG_IP6_NF_MANGLE=m ++#CONFIG_IP6_NF_NAT=m ++#CONFIG_IP6_NF_TARGET_MASQUERADE=m ++CONFIG_BRIDGE=y ++CONFIG_BRIDGE_VLAN_FILTERING=y ++CONFIG_NET_DSA=y ++#CONFIG_VLAN_8021Q=m ++#CONFIG_VLAN_8021Q_GVRP=y ++#CONFIG_VLAN_8021Q_MVRP=y ++CONFIG_NET_SCHED=y ++#CONFIG_NET_SCH_CBS=m ++#CONFIG_NET_SCH_ETF=m ++#CONFIG_NET_SCH_TAPRIO=m ++#CONFIG_NET_SCH_MQPRIO=m ++#CONFIG_NET_SCH_INGRESS=m ++#CONFIG_NET_CLS_BASIC=m ++#CONFIG_NET_CLS_FLOWER=m ++#CONFIG_NET_CLS_ACT=y ++#CONFIG_NET_ACT_GACT=m ++#CONFIG_NET_ACT_MIRRED=m ++#CONFIG_NET_ACT_GATE=m ++#CONFIG_QRTR=m ++#CONFIG_QRTR_TUN=m ++#CONFIG_CAN=m ++#CONFIG_CAN_FLEXCAN=m ++#CONFIG_BT=m ++#CONFIG_BT_RFCOMM=y ++#CONFIG_BT_RFCOMM_TTY=y ++#CONFIG_BT_BNEP=y ++#CONFIG_BT_BNEP_MC_FILTER=y ++#CONFIG_BT_BNEP_PROTO_FILTER=y ++#CONFIG_BT_HIDP=y ++#CONFIG_BT_HS=y ++#CONFIG_BT_LEDS=y ++#CONFIG_BT_MSFTEXT=y ++#CONFIG_BT_HCIBTUSB=m ++# CONFIG_BT_HCIBTUSB_BCM is not set ++#CONFIG_BT_HCIBTSDIO=m ++#CONFIG_BT_HCIUART=m ++#CONFIG_BT_HCIUART_LL=y ++#CONFIG_BT_HCIUART_BCM=y ++#CONFIG_BT_HCIUART_RTL=y ++CONFIG_CFG80211=y ++CONFIG_MAC80211=y ++CONFIG_MAC80211_LEDS=y ++CONFIG_RFKILL=y ++#CONFIG_NET_9P=y ++#CONFIG_NET_9P_VIRTIO=y ++#CONFIG_NFC=m ++#CONFIG_NFC_NCI=m ++#CONFIG_NFC_S3FWRN5_I2C=m ++CONFIG_PCI=y ++#CONFIG_PCIEPORTBUS=y ++CONFIG_PCI_DEBUG=y ++#CONFIG_PCI_REALLOC_ENABLE_AUTO=y ++#CONFIG_PCI_IOV=y ++#CONFIG_PCI_PASID=y ++#CONFIG_HOTPLUG_PCI=y ++#CONFIG_HOTPLUG_PCI_ACPI=y ++CONFIG_PCI_HOST_GENERIC=y ++CONFIG_PCI_MSI_IRQ_DOMAIN=y ++CONFIG_PCIE_ROCKCHIP_HOST=y ++#CONFIG_PCIE_DW_PLAT_HOST=y ++CONFIG_PCI_ENDPOINT=y ++CONFIG_PCIE_ROCKCHIP_EP=y ++CONFIG_PCIE_ROCKCHIP_DW_HOST=y ++#CONFIG_PCI_ENDPOINT_CONFIGFS=y ++#CONFIG_PCI_EPF_TEST=m ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++#CONFIG_FW_LOADER_USER_HELPER=y ++#CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y ++#CONFIG_BRCMSTB_GISB_ARB=y ++#CONFIG_VEXPRESS_CONFIG=y ++CONFIG_ARM_SCMI_PROTOCOL=y ++CONFIG_ARM_SCPI_PROTOCOL=y ++CONFIG_SYSFB_SIMPLEFB=y ++#CONFIG_EFI_CAPSULE_LOADER=y ++#CONFIG_MTD=y ++#CONFIG_MTD_BLOCK=y ++#CONFIG_MTD_CFI=y ++#CONFIG_MTD_CFI_ADV_OPTIONS=y ++#CONFIG_MTD_CFI_INTELEXT=y ++#CONFIG_MTD_CFI_AMDSTD=y ++#CONFIG_MTD_CFI_STAA=y ++#CONFIG_MTD_PHYSMAP=y ++#CONFIG_MTD_PHYSMAP_OF=y ++#CONFIG_MTD_DATAFLASH=y ++#CONFIG_MTD_SST25L=y ++#CONFIG_MTD_RAW_NAND=y ++#CONFIG_MTD_NAND_DENALI_DT=y ++#CONFIG_MTD_SPI_NOR=y ++CONFIG_OF_OVERLAY=y ++CONFIG_ZRAM=y ++CONFIG_ZRAM_MEMORY_TRACKING=y ++CONFIG_BLK_DEV_LOOP=y ++#CONFIG_BLK_DEV_NBD=m ++CONFIG_BLK_DEV_RAM=y ++CONFIG_VIRTIO_BLK=y ++CONFIG_BLK_DEV_NVME=y ++CONFIG_NVME_HWMON=y ++CONFIG_SRAM=y ++#CONFIG_DW_XDATA_PCIE=y ++#CONFIG_PCI_ENDPOINT_TEST=m ++#CONFIG_EEPROM_AT24=m ++#CONFIG_EEPROM_AT25=m ++#CONFIG_UACCE=m ++# CONFIG_SCSI_PROC_FS is not set ++CONFIG_BLK_DEV_SD=y ++#CONFIG_SCSI_SAS_ATA=y ++#CONFIG_SCSI_HISI_SAS=y ++#CONFIG_SCSI_HISI_SAS_PCI=y ++#CONFIG_MEGARAID_SAS=y ++#CONFIG_SCSI_MPT3SAS=m ++#CONFIG_SCSI_UFSHCD=y ++#CONFIG_SCSI_UFSHCD_PLATFORM=y ++CONFIG_ATA=y ++CONFIG_SATA_AHCI=y ++CONFIG_SATA_AHCI_PLATFORM=y ++#CONFIG_AHCI_CEVA=y ++#CONFIG_AHCI_QORIQ=y ++#CONFIG_SATA_SIL24=y ++#CONFIG_SATA_MV=y ++CONFIG_AHCI_DWC=y ++CONFIG_PATA_PLATFORM=y ++CONFIG_PATA_OF_PLATFORM=y ++#CONFIG_MD=y ++#CONFIG_BLK_DEV_MD=m ++#CONFIG_BLK_DEV_DM=m ++#CONFIG_DM_MIRROR=m ++#CONFIG_DM_ZERO=m ++CONFIG_NETDEVICES=y ++#CONFIG_MACVLAN=m ++#CONFIG_MACVTAP=m ++CONFIG_TUN=y ++#CONFIG_VETH=m ++CONFIG_VIRTIO_NET=y ++# CONFIG_NET_VENDOR_3COM is not set ++# CONFIG_NET_VENDOR_ADAPTEC is not set ++# CONFIG_NET_VENDOR_AGERE is not set ++# CONFIG_NET_VENDOR_ALACRITECH is not set ++# CONFIG_NET_VENDOR_ALTEON is not set ++# CONFIG_NET_VENDOR_AMAZON is not set ++# CONFIG_NET_VENDOR_AMD is not set ++# CONFIG_NET_VENDOR_AQUANTIA is not set ++# CONFIG_NET_VENDOR_ARC is not set ++# CONFIG_NET_VENDOR_ASIX is not set ++# CONFIG_NET_VENDOR_ATHEROS is not set ++# CONFIG_NET_VENDOR_BROADCOM is not set ++# CONFIG_NET_VENDOR_BROCADE is not set ++# CONFIG_NET_VENDOR_CADENCE is not set ++# CONFIG_NET_VENDOR_CAVIUM is not set ++# CONFIG_NET_VENDOR_CHELSIO is not set ++# CONFIG_NET_VENDOR_CISCO is not set ++# CONFIG_NET_VENDOR_CORTINA is not set ++# CONFIG_NET_VENDOR_DEC is not set ++# CONFIG_NET_VENDOR_DLINK is not set ++# CONFIG_NET_VENDOR_EMULEX is not set ++# CONFIG_NET_VENDOR_ENGLEDER is not set ++# CONFIG_NET_VENDOR_EZCHIP is not set ++# CONFIG_NET_VENDOR_GOOGLE is not set ++# CONFIG_NET_VENDOR_HISILICON is not set ++# CONFIG_NET_VENDOR_HUAWEI is not set ++#CONFIG_E100=y ++#CONFIG_E1000=y ++#CONFIG_E1000E=y ++#CONFIG_IGB=y ++#CONFIG_IGBVF=y ++#CONFIG_IXGB=y ++#CONFIG_IXGBE=y ++#CONFIG_IXGBEVF=y ++#CONFIG_I40E=y ++#CONFIG_I40EVF=y ++#CONFIG_ICE=y ++#CONFIG_FM10K=y ++#CONFIG_IGC=y ++# CONFIG_NET_VENDOR_MICROSOFT is not set ++# CONFIG_NET_VENDOR_LITEX is not set ++# CONFIG_NET_VENDOR_MARVELL is not set ++# CONFIG_NET_VENDOR_MELLANOX is not set ++# CONFIG_NET_VENDOR_MICREL is not set ++# CONFIG_NET_VENDOR_MICROCHIP is not set ++# CONFIG_NET_VENDOR_MICROSEMI is not set ++# CONFIG_NET_VENDOR_MYRI is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++# CONFIG_NET_VENDOR_NETERION is not set ++# CONFIG_NET_VENDOR_NETRONOME is not set ++# CONFIG_NET_VENDOR_NI is not set ++# CONFIG_NET_VENDOR_NVIDIA is not set ++# CONFIG_NET_VENDOR_OKI is not set ++# CONFIG_NET_VENDOR_PENSANDO is not set ++# CONFIG_NET_VENDOR_QLOGIC is not set ++# CONFIG_NET_VENDOR_QUALCOMM is not set ++# CONFIG_NET_VENDOR_RDC is not set ++#CONFIG_R8169=y ++# CONFIG_NET_VENDOR_RENESAS is not set ++# CONFIG_NET_VENDOR_ROCKER is not set ++# CONFIG_NET_VENDOR_SAMSUNG is not set ++# CONFIG_NET_VENDOR_SEEQ is not set ++# CONFIG_NET_VENDOR_SOLARFLARE is not set ++# CONFIG_NET_VENDOR_SILAN is not set ++# CONFIG_NET_VENDOR_SIS is not set ++# CONFIG_NET_VENDOR_SMSC is not set ++# CONFIG_NET_VENDOR_SOCIONEXT is not set ++CONFIG_STMMAC_ETH=y ++CONFIG_DWMAC_DWC_QOS_ETH=y ++# CONFIG_NET_VENDOR_SUN is not set ++# CONFIG_NET_VENDOR_TEHUTI is not set ++# CONFIG_NET_VENDOR_TI is not set ++# CONFIG_NET_VENDOR_VERTEXCOM is not set ++# CONFIG_NET_VENDOR_VIA is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++# CONFIG_NET_VENDOR_XILINX is not set ++#CONFIG_AQUANTIA_PHY=y ++#CONFIG_BROADCOM_PHY=m ++#CONFIG_BCM54140_PHY=m ++#CONFIG_BCM7XXX_PHY=m ++#CONFIG_MARVELL_PHY=m ++#CONFIG_MARVELL_10G_PHY=m ++#CONFIG_MICREL_PHY=y ++#CONFIG_MICROSEMI_PHY=y ++#CONFIG_MOTORCOMM_PHY=y ++#CONFIG_AT803X_PHY=y ++CONFIG_ROCKCHIP_PHY=y ++#CONFIG_VITESSE_PHY=y ++CONFIG_MDIO_BITBANG=y ++CONFIG_MDIO_BUS_MUX_GPIO=y ++CONFIG_MDIO_BUS_MUX_MULTIPLEXER=y ++CONFIG_MDIO_BUS_MUX_MMIOREG=y ++#CONFIG_USB_PEGASUS=m ++#CONFIG_USB_RTL8150=m ++#CONFIG_USB_RTL8152=m ++#CONFIG_USB_LAN78XX=m ++#CONFIG_USB_USBNET=y ++#CONFIG_USB_NET_AX8817X=m ++#CONFIG_USB_NET_CDCETHER=m ++#CONFIG_USB_NET_CDC_NCM=m ++#CONFIG_USB_NET_DM9601=m ++#CONFIG_USB_NET_SR9800=m ++#CONFIG_USB_NET_SMSC75XX=m ++#CONFIG_USB_NET_SMSC95XX=m ++#CONFIG_USB_NET_NET1080=m ++#CONFIG_USB_NET_PLUSB=m ++#CONFIG_USB_NET_MCS7830=m ++#CONFIG_USB_NET_CDC_SUBSET=m ++#CONFIG_USB_NET_ZAURUS=m ++# CONFIG_WLAN_VENDOR_ADMTEK is not set ++# CONFIG_WLAN_VENDOR_ATH is not set ++# CONFIG_WLAN_VENDOR_ATMEL is not set ++#CONFIG_BRCMFMAC=m ++#CONFIG_BRCM_TRACING=y ++#CONFIG_BRCMDBG=y ++# CONFIG_WLAN_VENDOR_CISCO is not set ++# CONFIG_WLAN_VENDOR_INTEL is not set ++# CONFIG_WLAN_VENDOR_INTERSIL is not set ++# CONFIG_WLAN_VENDOR_MARVELL is not set ++# CONFIG_WLAN_VENDOR_MEDIATEK is not set ++# CONFIG_WLAN_VENDOR_MICROCHIP is not set ++# CONFIG_WLAN_VENDOR_RALINK is not set ++#CONFIG_RTL8192CE=y ++#CONFIG_RTL8192SE=y ++#CONFIG_RTL8192DE=y ++#CONFIG_RTL8723AE=y ++#CONFIG_RTL8723BE=y ++#CONFIG_RTL8188EE=y ++#CONFIG_RTL8192EE=y ++#CONFIG_RTL8821AE=y ++#CONFIG_RTL8192CU=y ++#CONFIG_RTL8XXXU=y ++#CONFIG_RTL8XXXU_UNTESTED=y ++#CONFIG_RTW88=y ++#CONFIG_RTW88_8822BE=y ++#CONFIG_RTW88_8822CE=y ++#CONFIG_RTW88_8723DE=y ++#CONFIG_RTW88_8821CE=y ++#CONFIG_RTW88_DEBUG=y ++#CONFIG_RTW88_DEBUGFS=y ++# CONFIG_WLAN_VENDOR_RSI is not set ++# CONFIG_WLAN_VENDOR_ST is not set ++# CONFIG_WLAN_VENDOR_TI is not set ++# CONFIG_WLAN_VENDOR_ZYDAS is not set ++# CONFIG_WLAN_VENDOR_QUANTENNA is not set ++#CONFIG_INPUT_FF_MEMLESS=y ++#CONFIG_INPUT_MATRIXKMAP=y ++CONFIG_INPUT_EVDEV=y ++#CONFIG_KEYBOARD_ADC=m ++#CONFIG_KEYBOARD_GPIO=y ++#CONFIG_INPUT_TOUCHSCREEN=y ++#CONFIG_TOUCHSCREEN_CYTTSP5=y ++#CONFIG_TOUCHSCREEN_GOODIX=y ++CONFIG_INPUT_MISC=y ++#CONFIG_INPUT_PWM_VIBRA=m ++CONFIG_INPUT_RK805_PWRKEY=y ++#CONFIG_INPUT_WS8100_PEN=y ++# CONFIG_SERIO_SERPORT is not set ++CONFIG_SERIO_AMBAKMI=y ++CONFIG_LEGACY_PTY_COUNT=16 ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_EXTENDED=y ++CONFIG_SERIAL_8250_SHARE_IRQ=y ++CONFIG_SERIAL_8250_DW=y ++# CONFIG_SERIAL_8250_PERICOM is not set ++CONFIG_SERIAL_OF_PLATFORM=y ++#CONFIG_SERIAL_AMBA_PL011=y ++#CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++#CONFIG_SERIAL_XILINX_PS_UART=y ++#CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y ++#CONFIG_SERIAL_FSL_LPUART=y ++#CONFIG_SERIAL_FSL_LPUART_CONSOLE=y ++#CONFIG_SERIAL_FSL_LINFLEXUART=y ++#CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE=y ++CONFIG_SERIAL_DEV_BUS=y ++CONFIG_VIRTIO_CONSOLE=y ++#CONFIG_IPMI_HANDLER=m ++#CONFIG_IPMI_DEVICE_INTERFACE=m ++#CONFIG_IPMI_SI=m ++# CONFIG_HW_RANDOM_CN10K is not set ++#CONFIG_TCG_TPM=y ++#CONFIG_TCG_TIS_I2C_INFINEON=y ++CONFIG_I2C_CHARDEV=y ++CONFIG_I2C_MUX=y ++#CONFIG_I2C_MUX_PCA954x=y ++CONFIG_I2C_DESIGNWARE_PLATFORM=y ++CONFIG_I2C_GPIO=y ++CONFIG_I2C_RK3X=y ++CONFIG_I2C_SLAVE=y ++CONFIG_SPI=y ++#CONFIG_SPI_CADENCE_QUADSPI=y ++#CONFIG_SPI_NXP_FLEXSPI=y ++CONFIG_SPI_GPIO=y ++#CONFIG_SPI_PL022=y ++CONFIG_SPI_ROCKCHIP=y ++#CONFIG_SPI_ROCKCHIP_SFC=y ++CONFIG_SPI_SPIDEV=y ++CONFIG_SPMI=y ++CONFIG_PINCTRL_RK805=y ++CONFIG_PINCTRL_SINGLE=y ++CONFIG_GPIO_DWAPB=y ++CONFIG_GPIO_GENERIC_PLATFORM=y ++#CONFIG_GPIO_MB86S7X=y ++#CONFIG_GPIO_PL061=y ++#CONFIG_GPIO_SYSCON=y ++#CONFIG_GPIO_XGENE=y ++#CONFIG_GPIO_MAX732X=y ++#CONFIG_GPIO_PCA953X=y ++#CONFIG_GPIO_PCA953X_IRQ=y ++CONFIG_POWER_RESET_GPIO=y ++#CONFIG_PDA_POWER=m ++#CONFIG_GENERIC_ADC_BATTERY=m ++#CONFIG_BATTERY_SBS=m ++#CONFIG_CHARGER_SBS=m ++#CONFIG_MANAGER_SBS=m ++CONFIG_CHARGER_RK817=y ++CONFIG_SENSORS_ARM_SCMI=y ++CONFIG_SENSORS_ARM_SCPI=y ++CONFIG_SENSORS_GPIO_FAN=y ++CONFIG_SENSORS_PWM_FAN=y ++CONFIG_THERMAL_NETLINK=y ++CONFIG_THERMAL_STATISTICS=y ++CONFIG_THERMAL_WRITABLE_TRIPS=y ++CONFIG_THERMAL_GOV_FAIR_SHARE=y ++CONFIG_THERMAL_GOV_BANG_BANG=y ++CONFIG_THERMAL_GOV_USER_SPACE=y ++CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y ++CONFIG_CPU_THERMAL=y ++CONFIG_DEVFREQ_THERMAL=y ++CONFIG_THERMAL_EMULATION=y ++#CONFIG_THERMAL_MMIO=m ++CONFIG_ROCKCHIP_THERMAL=y ++#CONFIG_GENERIC_ADC_THERMAL=m ++CONFIG_WATCHDOG=y ++CONFIG_WATCHDOG_NOWAYOUT=y ++CONFIG_WATCHDOG_SYSFS=y ++CONFIG_DW_WATCHDOG=y ++CONFIG_MFD_RK8XX=y ++CONFIG_MFD_RK8XX_I2C=y ++# CONFIG_MFD_VEXPRESS_SYSREG is not set ++CONFIG_REGULATOR=y ++CONFIG_REGULATOR_DEBUG=y ++CONFIG_REGULATOR_FIXED_VOLTAGE=y ++CONFIG_REGULATOR_USERSPACE_CONSUMER=y ++#CONFIG_REGULATOR_FAN53555=y ++CONFIG_REGULATOR_GPIO=y ++CONFIG_REGULATOR_PWM=y ++CONFIG_REGULATOR_RK808=y ++#CONFIG_REGULATOR_TPS65185=y ++CONFIG_REGULATOR_VCTRL=y ++#CONFIG_RC_CORE=m ++#CONFIG_RC_DECODERS=y ++#CONFIG_RC_DEVICES=y ++CONFIG_MEDIA_CEC_SUPPORT=y ++CONFIG_CEC_GPIO=y ++#CONFIG_MEDIA_SUPPORT=m ++#CONFIG_MEDIA_CAMERA_SUPPORT=y ++#CONFIG_MEDIA_ANALOG_TV_SUPPORT=y ++#CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y ++#CONFIG_MEDIA_SDR_SUPPORT=y ++#CONFIG_MEDIA_PLATFORM_SUPPORT=y ++# CONFIG_DVB_NET is not set ++#CONFIG_MEDIA_USB_SUPPORT=y ++#CONFIG_USB_VIDEO_CLASS=m ++#CONFIG_USB_GSPCA=m ++#CONFIG_V4L_PLATFORM_DRIVERS=y ++#CONFIG_V4L_MEM2MEM_DRIVERS=y ++#CONFIG_SDR_PLATFORM_DRIVERS=y ++#CONFIG_VIDEO_IMX219=m ++#CONFIG_VIDEO_OV5645=m ++CONFIG_DRM=y ++#CONFIG_DRM_I2C_CH7006=m ++#CONFIG_DRM_I2C_SIL164=m ++#CONFIG_DRM_I2C_NXP_TDA998X=m ++#CONFIG_DRM_MALI_DISPLAY=m ++CONFIG_DRM_ROCKCHIP=y ++CONFIG_ROCKCHIP_VOP2=y ++CONFIG_ROCKCHIP_DW_HDMI=y ++CONFIG_ROCKCHIP_DW_MIPI_DSI=y ++CONFIG_ROCKCHIP_INNO_HDMI=y ++#CONFIG_ROCKCHIP_LVDS=y ++#CONFIG_DRM_ROCKCHIP_EBC=m ++#CONFIG_DRM_PANEL_LVDS=m ++#CONFIG_DRM_PANEL_SIMPLE=m ++#CONFIG_DRM_PANEL_EDP=m ++#CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D=y ++#CONFIG_DRM_PANEL_MANTIX_MLAF057WE51=m ++#CONFIG_DRM_PANEL_RAYDIUM_RM67191=m ++#CONFIG_DRM_PANEL_SITRONIX_ST7703=m ++#CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA=m ++CONFIG_DRM_DISPLAY_CONNECTOR=y ++#CONFIG_DRM_LONTIUM_LT9611=m ++#CONFIG_DRM_LONTIUM_LT9611UXC=m ++#CONFIG_DRM_NWL_MIPI_DSI=m ++#CONFIG_DRM_SII902X=m ++#CONFIG_DRM_SIMPLE_BRIDGE=m ++#CONFIG_DRM_THINE_THC63LVD1024=m ++#CONFIG_DRM_TI_SN65DSI86=m ++#CONFIG_DRM_I2C_ADV7511=m ++#CONFIG_DRM_I2C_ADV7511_AUDIO=y ++CONFIG_DRM_DW_HDMI_CEC=y ++#CONFIG_DRM_PL111=m ++CONFIG_DRM_PANFROST=y ++CONFIG_FB=y ++# CONFIG_XEN_FBDEV_FRONTEND is not set ++CONFIG_FB_SIMPLE=y ++#CONFIG_BACKLIGHT_CLASS_DEVICE=y ++#CONFIG_BACKLIGHT_PWM=m ++#CONFIG_BACKLIGHT_LM3630A=y ++#CONFIG_BACKLIGHT_LP855X=m ++CONFIG_SOUND=y ++CONFIG_SND=y ++CONFIG_SND_HDA_INTEL=y ++CONFIG_SND_HDA_CODEC_HDMI=y ++CONFIG_SND_HDA_GENERIC=y ++CONFIG_SND_SOC=y ++#CONFIG_SND_SOC_FSL_ASRC=m ++#CONFIG_SND_SOC_FSL_SAI=m ++#CONFIG_SND_SOC_FSL_AUDMIX=m ++#CONFIG_SND_SOC_FSL_SSI=m ++#CONFIG_SND_SOC_FSL_SPDIF=m ++#CONFIG_SND_SOC_FSL_ESAI=m ++#CONFIG_SND_SOC_FSL_MICFIL=m ++#CONFIG_SND_SOC_FSL_EASRC=m ++#CONFIG_SND_SOC_IMX_AUDMUX=m ++CONFIG_SND_SOC_ROCKCHIP=y ++CONFIG_SND_SOC_ROCKCHIP_I2S_TDM=y ++CONFIG_SND_SOC_ROCKCHIP_PDM=y ++CONFIG_SND_SOC_ROCKCHIP_SPDIF=y ++#CONFIG_SND_SOC_ROCKCHIP_MAX98090=y ++#CONFIG_SND_SOC_ROCKCHIP_RT5645=y ++#CONFIG_SND_SOC_RK3288_HDMI_ANALOG=y ++#CONFIG_SND_SOC_RK3399_GRU_SOUND=y ++#CONFIG_SND_SOC_AK4613=m ++#CONFIG_SND_SOC_ES7134=m ++#CONFIG_SND_SOC_ES7241=m ++#CONFIG_SND_SOC_GTM601=m ++#CONFIG_SND_SOC_MAX98927=m ++#CONFIG_SND_SOC_PCM3168A_I2C=m ++#CONFIG_SND_SOC_RK3328=y ++CONFIG_SND_SOC_RK817=y ++#CONFIG_SND_SOC_RT5659=m ++#CONFIG_SND_SOC_SGTL5000=m ++CONFIG_SND_SOC_SIMPLE_AMPLIFIER=y ++CONFIG_SND_SOC_SIMPLE_MUX=y ++CONFIG_SND_SOC_SPDIF=y ++#CONFIG_SND_SOC_TAS571X=m ++#CONFIG_SND_SOC_WM8904=m ++#CONFIG_SND_SOC_WM8960=m ++#CONFIG_SND_SOC_WM8962=m ++#CONFIG_SND_SOC_WSA881X=m ++#CONFIG_SND_SOC_LPASS_WSA_MACRO=m ++#CONFIG_SND_SOC_LPASS_VA_MACRO=m ++CONFIG_SND_SIMPLE_CARD=y ++#CONFIG_SND_AUDIO_GRAPH_CARD=y ++#CONFIG_HID_BATTERY_STRENGTH=y ++# CONFIG_HID_A4TECH is not set ++# CONFIG_HID_APPLE is not set ++# CONFIG_HID_BELKIN is not set ++# CONFIG_HID_EZKEY is not set ++# CONFIG_HID_ITE is not set ++# CONFIG_HID_KENSINGTON is not set ++#CONFIG_HID_LOGITECH_HIDPP=m ++#CONFIG_HID_REDRAGON=m ++#CONFIG_HID_MICROSOFT=m ++#CONFIG_HID_MONTEREY=m ++#CONFIG_HID_MULTITOUCH=y ++#CONFIG_I2C_HID_ACPI=m ++#CONFIG_I2C_HID_OF=m ++#CONFIG_I2C_HID_OF_GOODIX=m ++#CONFIG_USB_LED_TRIG=y ++#CONFIG_USB_ULPI_BUS=y ++CONFIG_USB_CONN_GPIO=y ++CONFIG_USB=y ++CONFIG_USB_OTG=y ++#CONFIG_USB_LEDS_TRIGGER_USBPORT=y ++#CONFIG_USB_MON=m ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_EHCI_ROOT_HUB_TT=y ++CONFIG_USB_EHCI_HCD_PLATFORM=y ++CONFIG_USB_OHCI_HCD=y ++CONFIG_USB_OHCI_HCD_PLATFORM=y ++#CONFIG_USB_ACM=m ++CONFIG_USB_STORAGE=y ++CONFIG_USB_DWC3=y ++CONFIG_USB_DWC2=y ++#CONFIG_USB_SERIAL=m ++CONFIG_USB_SERIAL_GENERIC=y ++#CONFIG_USB_SERIAL_SIMPLE=m ++#CONFIG_USB_SERIAL_CH341=m ++#CONFIG_USB_SERIAL_CP210X=m ++#CONFIG_USB_SERIAL_FTDI_SIO=m ++#CONFIG_USB_SERIAL_OPTION=m ++#CONFIG_USB_SERIAL_DEBUG=m ++CONFIG_NOP_USB_XCEIV=y ++#CONFIG_USB_ULPI=y ++#CONFIG_USB_GADGET=y ++#CONFIG_USB_SNP_UDC_PLAT=y ++#CONFIG_USB_BDC_UDC=y ++#CONFIG_USB_CONFIGFS=y ++#CONFIG_USB_CONFIGFS_SERIAL=y ++#CONFIG_USB_CONFIGFS_ACM=y ++#CONFIG_USB_CONFIGFS_OBEX=y ++#CONFIG_USB_CONFIGFS_NCM=y ++#CONFIG_USB_CONFIGFS_ECM=y ++#CONFIG_USB_CONFIGFS_ECM_SUBSET=y ++#CONFIG_USB_CONFIGFS_RNDIS=y ++#CONFIG_USB_CONFIGFS_EEM=y ++#CONFIG_USB_CONFIGFS_MASS_STORAGE=y ++#CONFIG_USB_CONFIGFS_F_FS=y ++#CONFIG_TYPEC=y ++#CONFIG_TYPEC_TCPM=y ++#CONFIG_TYPEC_TCPCI=y ++#CONFIG_TYPEC_FUSB302=y ++#CONFIG_TYPEC_UCSI=y ++#CONFIG_TYPEC_TPS6598X=m ++#CONFIG_TYPEC_HD3SS3220=m ++#CONFIG_TYPEC_WUSB3801=y ++CONFIG_MMC=y ++CONFIG_MMC_BLOCK_MINORS=32 ++CONFIG_SDIO_UART=y ++CONFIG_MMC_DEBUG=y ++CONFIG_MMC_ARMMMCI=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_ACPI=y ++CONFIG_MMC_SDHCI_PLTFM=y ++CONFIG_MMC_SDHCI_OF_DWCMSHC=y ++CONFIG_MMC_SDHCI_F_SDH30=y ++CONFIG_MMC_SPI=y ++CONFIG_MMC_DW=y ++CONFIG_MMC_DW_ROCKCHIP=y ++CONFIG_MMC_CQHCI=y ++CONFIG_MMC_HSQ=y ++CONFIG_NEW_LEDS=y ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_GPIO=y ++CONFIG_LEDS_PWM=y ++CONFIG_LEDS_REGULATOR=y ++CONFIG_LEDS_SYSCON=y ++CONFIG_LEDS_USER=y ++#CONFIG_LEDS_TRIGGER_TIMER=y ++#CONFIG_LEDS_TRIGGER_ONESHOT=y ++#CONFIG_LEDS_TRIGGER_DISK=y ++#CONFIG_LEDS_TRIGGER_MTD=y ++#CONFIG_LEDS_TRIGGER_HEARTBEAT=y ++#CONFIG_LEDS_TRIGGER_BACKLIGHT=y ++#CONFIG_LEDS_TRIGGER_CPU=y ++#CONFIG_LEDS_TRIGGER_ACTIVITY=y ++#CONFIG_LEDS_TRIGGER_GPIO=y ++#CONFIG_LEDS_TRIGGER_DEFAULT_ON=y ++#CONFIG_LEDS_TRIGGER_TRANSIENT=y ++#CONFIG_LEDS_TRIGGER_CAMERA=y ++#CONFIG_LEDS_TRIGGER_PANIC=y ++#CONFIG_LEDS_TRIGGER_NETDEV=y ++#CONFIG_LEDS_TRIGGER_PATTERN=y ++#CONFIG_LEDS_TRIGGER_AUDIO=y ++#CONFIG_LEDS_TRIGGER_TTY=y ++CONFIG_EDAC=y ++CONFIG_EDAC_GHES=y ++CONFIG_RTC_CLASS=y ++CONFIG_RTC_DRV_RK808=y ++CONFIG_RTC_DRV_HYM8563=y ++#CONFIG_RTC_DRV_PCF85063=y ++#CONFIG_RTC_DRV_EFI=y ++CONFIG_DMADEVICES=y ++#CONFIG_AMBA_PL08X=y ++CONFIG_PL330_DMA=y ++#CONFIG_DW_DMAC=m ++#CONFIG_DW_DMAC_PCI=m ++#CONFIG_DW_EDMA_PCIE=m ++#CONFIG_UIO=m ++CONFIG_VFIO=y ++CONFIG_VFIO_NOIOMMU=y ++CONFIG_VFIO_PCI=y ++CONFIG_VIRTIO_PCI=y ++CONFIG_VIRTIO_BALLOON=y ++CONFIG_VIRTIO_INPUT=y ++CONFIG_VIRTIO_MMIO=y ++# CONFIG_XEN_BALLOON is not set ++# CONFIG_XEN_DEV_EVTCHN is not set ++# CONFIG_XEN_BACKEND is not set ++# CONFIG_XENFS is not set ++# CONFIG_XEN_SYS_HYPERVISOR is not set ++# CONFIG_XEN_GNTDEV is not set ++# CONFIG_XEN_GRANT_DEV_ALLOC is not set ++#CONFIG_STAGING=y ++#CONFIG_RTL8192U=m ++#CONFIG_RTLLIB=m ++#CONFIG_RTL8192E=m ++#CONFIG_RTL8723BS=m ++#CONFIG_R8712U=m ++#CONFIG_R8188EU=m ++#CONFIG_STAGING_MEDIA=y ++#CONFIG_VIDEO_HANTRO=m ++#CONFIG_VIDEO_ROCKCHIP_VDEC=m ++#CONFIG_ASHMEM=y ++# CONFIG_SURFACE_PLATFORMS is not set ++CONFIG_COMMON_CLK_RK808=y ++CONFIG_COMMON_CLK_SCMI=y ++CONFIG_COMMON_CLK_SCPI=y ++CONFIG_COMMON_CLK_PWM=y ++CONFIG_COMMON_CLK_FIXED_MMIO=y ++CONFIG_HWSPINLOCK=y ++# CONFIG_FSL_ERRATUM_A008585 is not set ++# CONFIG_HISILICON_ERRATUM_161010101 is not set ++CONFIG_ARM_MHU=y ++CONFIG_PLATFORM_MHU=y ++CONFIG_ROCKCHIP_MBOX=y ++CONFIG_IOMMU_IO_PGTABLE_ARMV7S=y ++CONFIG_IOMMU_DEFAULT_PASSTHROUGH=y ++CONFIG_ROCKCHIP_IOMMU=y ++CONFIG_ARM_SMMU=y ++CONFIG_ARM_SMMU_V3=y ++CONFIG_ARM_SMMU_V3_SVA=y ++CONFIG_REMOTEPROC=y ++CONFIG_REMOTEPROC_CDEV=y ++#CONFIG_SOUNDWIRE=m ++#CONFIG_SOUNDWIRE_INTEL=m ++#CONFIG_SOUNDWIRE_QCOM=m ++CONFIG_ROCKCHIP_IODOMAIN=y ++CONFIG_ROCKCHIP_PM_DOMAINS=y ++#CONFIG_DEVFREQ_GOV_PERFORMANCE=m ++#CONFIG_DEVFREQ_GOV_POWERSAVE=m ++#CONFIG_DEVFREQ_GOV_USERSPACE=m ++#CONFIG_DEVFREQ_GOV_PASSIVE=m ++#CONFIG_ARM_RK3399_DMC_DEVFREQ=m ++CONFIG_EXTCON_ADC_JACK=y ++CONFIG_EXTCON_GPIO=y ++CONFIG_EXTCON_USB_GPIO=y ++CONFIG_MEMORY=y ++CONFIG_IIO=y ++CONFIG_IIO_ST_ACCEL_3AXIS=y ++#CONFIG_MAX9611=m ++#CONFIG_QCOM_SPMI_ADC5=m ++CONFIG_ROCKCHIP_SARADC=y ++#CONFIG_IIO_ST_LSM6DSX=m ++#CONFIG_SENSORS_ISL29018=m ++#CONFIG_VCNL4000=m ++#CONFIG_IIO_ST_MAGN_3AXIS=m ++#CONFIG_MPL3115=m ++CONFIG_PWM=y ++CONFIG_PWM_ROCKCHIP=y ++#CONFIG_PHY_ROCKCHIP_DP=y ++#CONFIG_PHY_ROCKCHIP_DPHY_RX0=y ++CONFIG_PHY_ROCKCHIP_EMMC=y ++CONFIG_PHY_ROCKCHIP_INNO_HDMI=y ++CONFIG_PHY_ROCKCHIP_INNO_USB2=y ++#CONFIG_PHY_ROCKCHIP_INNO_CSIDPHY=y ++#CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY=y ++CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY=y ++CONFIG_PHY_ROCKCHIP_PCIE=y ++CONFIG_PHY_ROCKCHIP_SNPS_PCIE3=y ++#CONFIG_PHY_ROCKCHIP_TYPEC=y ++CONFIG_PHY_ROCKCHIP_USB=y ++#CONFIG_ARM_SMMU_V3_PMU=m ++#CONFIG_ANDROID=y ++#CONFIG_ANDROID_BINDER_IPC=y ++#CONFIG_ANDROID_BINDERFS=y ++CONFIG_ROCKCHIP_EFUSE=y ++CONFIG_ROCKCHIP_OTP=y ++#CONFIG_NVMEM_RMEM=m ++#CONFIG_TEE=y ++#CONFIG_OPTEE=y ++CONFIG_MUX_MMIO=y ++# CONFIG_SLIMBUS is not set ++CONFIG_INTERCONNECT=y ++CONFIG_EXT2_FS=y ++CONFIG_EXT3_FS=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++#CONFIG_BTRFS_FS=m ++#CONFIG_BTRFS_FS_POSIX_ACL=y ++#CONFIG_F2FS_FS=m ++#CONFIG_FANOTIFY=y ++#CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y ++#CONFIG_QUOTA=y ++CONFIG_AUTOFS4_FS=y ++#CONFIG_FUSE_FS=m ++#CONFIG_CUSE=m ++#CONFIG_OVERLAY_FS=m ++CONFIG_VFAT_FS=y ++#CONFIG_NTFS3_FS=y ++#CONFIG_NTFS3_LZX_XPRESS=y ++CONFIG_TMPFS=y ++CONFIG_TMPFS_POSIX_ACL=y ++CONFIG_HUGETLBFS=y ++#CONFIG_EFIVAR_FS=y ++#CONFIG_SQUASHFS=y ++CONFIG_NFS_FS=y ++CONFIG_NFS_V4=y ++CONFIG_NFS_V4_1=y ++CONFIG_NFS_V4_2=y ++CONFIG_ROOT_NFS=y ++CONFIG_SMB_SERVER=y ++CONFIG_SMB_SERVER_KERBEROS5=y ++#CONFIG_9P_FS=y ++CONFIG_NLS_CODEPAGE_437=y ++CONFIG_NLS_ISO8859_1=y ++CONFIG_UNICODE=y ++CONFIG_SECURITY=y ++CONFIG_CRYPTO_CRYPTD=y ++CONFIG_CRYPTO_ECDH=y ++CONFIG_CRYPTO_ECHAINIV=y ++CONFIG_CRYPTO_MD4=y ++#CONFIG_CRYPTO_DES=m ++CONFIG_CRYPTO_ANSI_CPRNG=y ++#CONFIG_CRYPTO_USER_API_RNG=m ++#CONFIG_CRYPTO_DEV_CCREE=m ++#CONFIG_CRYPTO_DEV_HISI_SEC2=m ++#CONFIG_CRYPTO_DEV_HISI_ZIP=m ++#CONFIG_CRYPTO_DEV_HISI_HPRE=m ++#CONFIG_CRYPTO_DEV_HISI_TRNG=m ++#CONFIG_CRYPTO_DEV_AMLOGIC_GXL=m ++CONFIG_PACKING=y ++CONFIG_INDIRECT_PIO=y ++#CONFIG_CRC_CCITT=m ++CONFIG_CRC8=y ++CONFIG_DMA_CMA=y ++CONFIG_CMA_SIZE_MBYTES=32 ++CONFIG_PRINTK_TIME=y ++CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15 ++CONFIG_DEBUG_INFO=y ++CONFIG_DEBUG_INFO_REDUCED=y ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_DEBUG_FS=y ++CONFIG_DEBUG_KERNEL=y ++CONFIG_SOFTLOCKUP_DETECTOR=y ++CONFIG_WQ_WATCHDOG=y ++# CONFIG_SCHED_DEBUG is not set ++CONFIG_BOOTTIME_TRACING=y ++CONFIG_FUNCTION_TRACER=y ++CONFIG_FUNCTION_PROFILER=y ++CONFIG_MEMTEST=y ++ ++CONFIG_REGULATOR_FAN53555=y ++ ++#CONFIG_NET_REALTEK_MDIO=y ++#CONFIG_NET_DSA_REALTEK=y ++#CONFIG_NET_DSA_REALTEK_MDIO=y ++CONFIG_MT753X_GSW=y ++CONFIG_NET_DSA_MT7530=y ++ ++CONFIG_DRM_DW_HDMI_I2S_AUDIO=y ++ ++CONFIG_RK_HEADSET=y ++ ++#IR_Driver ++CONFIG_RC_CORE=y ++CONFIG_LIRC=y ++CONFIG_RC_DEVICES=y ++CONFIG_IR_GPIO_CIR=y ++CONFIG_RC_MAP=y ++# Decoders (might be optional) ++CONFIG_RC_DECODERS=y ++CONFIG_IR_IMON_DECODER=y ++CONFIG_IR_JVC_DECODER=y ++CONFIG_IR_MCE_KBD_DECODER=y ++CONFIG_IR_NEC_DECODER=y ++CONFIG_IR_RC5_DECODER=y ++CONFIG_IR_RC6_DECODER=y ++CONFIG_IR_RCMM_DECODER=y ++CONFIG_IR_SANYO_DECODER=y ++CONFIG_IR_SHARP_DECODER=y ++CONFIG_IR_SONY_DECODER=y ++CONFIG_IR_XMP_DECODER=y +diff --git a/bpi-r2pro.its b/bpi-r2pro.its +new file mode 100644 +index 000000000000..48f4031aca1e +--- /dev/null ++++ b/bpi-r2pro.its +@@ -0,0 +1,55 @@ ++/* ++ * Copyright (C) 2020 Rockchip Electronics Co., Ltd ++ * ++ * SPDX-License-Identifier: GPL-2.0 ++ */ ++ ++/dts-v1/; ++ ++/ { ++ description = "U-Boot fitImage for bpi-r2pro aarch64 kernel"; ++ images { ++ kernel { ++ description = "Linux Kernel %version%"; ++ data = /incbin/("arch/arm64/boot/Image.gz"); ++ type = "kernel"; ++ arch = "arm64"; ++ os = "linux"; ++ compression = "gzip"; ++ entry = <0x02080000>; ++ load = <0x02080000>; ++ hash { ++ algo = "sha256"; ++ }; ++ }; ++ fdt { ++ description = "Flattened Device Tree blob"; ++ data = /incbin/("arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dtb"); ++ type = "flat_dt"; ++ arch = "arm64"; ++ compression = "none"; ++ hash { ++ algo = "sha256"; ++ }; ++ }; ++/* ramdisk { ++ data = /incbin/("out/ramdisk"); ++ type = "ramdisk"; ++ arch = "arm64"; ++ os = "linux"; ++ compression = "none"; ++ load = <0xffffff02>; ++ hash { ++ algo = "sha256"; ++ }; ++ };*/ ++ }; ++ configurations { ++ default = "conf"; ++ conf { ++ fdt = "fdt"; ++ kernel = "kernel"; ++ //ramdisk = "ramdisk"; ++ }; ++ }; ++}; +diff --git a/bpi-r3.its b/bpi-r3.its +new file mode 100644 +index 000000000000..c92291da749a +--- /dev/null ++++ b/bpi-r3.its +@@ -0,0 +1,162 @@ ++/dts-v1/; ++ ++/ { ++ description = "U-Boot fitImage for bpi-r3 aarch64 kernel"; ++ #address-cells = <1>; ++ ++ images { ++ kernel-1 { ++ description = "Linux Kernel %version%"; ++ data = /incbin/("./arch/arm64/boot/Image.gz"); ++ type = "kernel"; ++ arch = "arm64"; ++ os = "linux"; ++ compression = "gzip"; ++ load = <0x44000000>; ++ entry = <0x44000000>; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ }; ++ fdt-base { ++ description = "Flattened Device Tree blob"; ++ data = /incbin/("./arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dtb"); ++ type = "flat_dt"; ++ arch = "arm64"; ++ load = <0x47000000>; ++ compression = "none"; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ }; ++ fdt-base-mini { ++ description = "Flattened Device Tree blob for r3 mini"; ++ data = /incbin/("./arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-mini.dtb"); ++ type = "flat_dt"; ++ arch = "arm64"; ++ load = <0x47000000>; ++ compression = "none"; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ }; ++ fdt-ov-sd { ++ description = "Flattened Device Tree blob"; ++ data = /incbin/("./arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-sd.dtbo"); ++ type = "flat_dt"; ++ }; ++ fdt-ov-emmc { ++ description = "Flattened Device Tree blob"; ++ data = /incbin/("./arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-emmc.dtbo"); ++ type = "flat_dt"; ++ }; ++ fdt-ov-nand{ ++ data = /incbin/("./arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nand.dtbo"); ++ type = "flat_dt"; ++ arch = "arm64"; ++ }; ++ fdt-ov-nor{ ++ data = /incbin/("./arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3-nor.dtbo"); ++ type = "flat_dt"; ++ arch = "arm64"; ++ }; ++/* ramdisk-1 { ++ description = "ramdisk"; ++ data = /incbin/("./rootfs_arm64.cpio.gz"); ++ type = "ramdisk"; ++ arch = "arm64"; ++ os = "linux"; ++ compression = "gzip"; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ };*/ ++ }; ++ configurations { ++ default = "conf-sd"; ++ conf-sd { ++ description = "Boot Linux kernel with SD FDT blob"; ++ kernel = "kernel-1"; ++ fdt = "fdt-base", "fdt-ov-sd"; ++ //ramdisk = "ramdisk-1"; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ }; ++ conf-emmc { ++ description = "Boot Linux kernel with EMMC FDT blob"; ++ kernel = "kernel-1"; ++ fdt = "fdt-base", "fdt-ov-emmc"; ++ //ramdisk = "ramdisk-1"; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ }; ++ conf-emmc-mini { ++ description = "Boot Linux kernel with R3mini + EMMC FDT blob"; ++ kernel = "kernel-1"; ++ fdt = "fdt-base-mini", "fdt-ov-emmc"; ++ //ramdisk = "ramdisk-1"; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ }; ++ conf-sd-nand { ++ description = "Boot Linux kernel with SD+NAND FDT blob"; ++ kernel = "kernel-1"; ++ fdt = "fdt-base", "fdt-ov-sd", "fdt-ov-nand"; ++ //ramdisk = "ramdisk-1"; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ }; ++ conf-emmc-nand { ++ description = "Boot Linux kernel with EMMC+NAND FDT blob"; ++ kernel = "kernel-1"; ++ fdt = "fdt-base", "fdt-ov-emmc", "fdt-ov-nand"; ++ //ramdisk = "ramdisk-1"; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ }; ++ conf-sd-nor { ++ description = "Boot Linux kernel with SD+NOR FDT blob"; ++ kernel = "kernel-1"; ++ fdt = "fdt-base", "fdt-ov-sd", "fdt-ov-nor"; ++ //ramdisk = "ramdisk-1"; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ }; ++ conf-emmc-nor { ++ description = "Boot Linux kernel with EMMC+NOR FDT blob"; ++ kernel = "kernel-1"; ++ fdt = "fdt-base", "fdt-ov-emmc", "fdt-ov-nor"; ++ //ramdisk = "ramdisk-1"; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ }; ++ nand { ++ description = "NAND overlay"; ++ fdt = "fdt-ov-nand"; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ }; ++ nor { ++ description = "NOR overlay"; ++ fdt = "fdt-ov-nor"; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ }; ++ sata { ++ description = "SATA overlay"; ++ fdt = "fdt-ov-sata"; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ }; ++ }; ++}; +diff --git a/bpi-r64.its b/bpi-r64.its +new file mode 100644 +index 000000000000..c6b012255a16 +--- /dev/null ++++ b/bpi-r64.its +@@ -0,0 +1,55 @@ ++/dts-v1/; ++ ++/ { ++ description = "U-Boot fitImage for bpi-r64 aarch64 kernel"; ++ #address-cells = <1>; ++ ++ images { ++ kernel-1 { ++ description = "Linux Kernel %version%"; ++ data = /incbin/("./arch/arm64/boot/Image.gz"); ++ type = "kernel"; ++ arch = "arm64"; ++ os = "linux"; ++ compression = "gzip"; ++ load = <0x40080000>; ++ entry = <0x40080000>; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ }; ++ fdt-1 { ++ description = "Flattened Device Tree blob"; ++ data = /incbin/("./arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dtb"); ++ type = "flat_dt"; ++ arch = "arm64"; ++ compression = "none"; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ }; ++/* ramdisk@0 { ++ description = "ramdisk"; ++ data = /incbin/("./ramdisk.cpio"); ++ type = "ramdisk"; ++ arch = "arm64"; ++ os = "linux"; ++ compression = "none"; ++ hash@1 { ++ algo = "sha1"; ++ }; ++ };*/ ++ }; ++ configurations { ++ default = "conf-1"; ++ conf-1 { ++ description = "Boot Linux kernel with FDT blob"; ++ kernel = "kernel-1"; ++ fdt = "fdt-1"; ++ //ramdisk = "ramdisk@0"; ++ hash-1 { ++ algo = "sha1"; ++ }; ++ }; ++ }; ++}; +diff --git a/build.conf b/build.conf +index 60d7ff7a4859..7681a4e75ce5 100644 +--- a/build.conf ++++ b/build.conf +@@ -13,7 +13,7 @@ board=bpi-r2 + #board=bpi-r64 + #board=bpi-r2pro + #board=bpi-r3 +-board=bpi-r4 ++#board=bpi-r4 + + #r64 with rtl8367 + #boardversion=v0.1 +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0008-defconfig-r3-fix-warning-about-BASE_SMALL.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0008-defconfig-r3-fix-warning-about-BASE_SMALL.patch new file mode 100644 index 0000000000..e2ed87a836 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0008-defconfig-r3-fix-warning-about-BASE_SMALL.patch @@ -0,0 +1,25 @@ +From 4b3f2fdb02d16d5346b4b6c14f51a7000a3c5325 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Mon, 16 Jun 2025 09:03:11 +0200 +Subject: [PATCH 08/84] defconfig: r3: fix warning about BASE_SMALL + +--- + arch/arm64/configs/mt7986a_bpi-r3_defconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/configs/mt7986a_bpi-r3_defconfig b/arch/arm64/configs/mt7986a_bpi-r3_defconfig +index fccecc3b2375..32710280133d 100644 +--- a/arch/arm64/configs/mt7986a_bpi-r3_defconfig ++++ b/arch/arm64/configs/mt7986a_bpi-r3_defconfig +@@ -21,7 +21,7 @@ CONFIG_ATA_SFF=y + CONFIG_ATM_BR2684_IPFILTER=y + CONFIG_ATM_CLIP_NO_ICMP=y + CONFIG_BASE_FULL=y +-CONFIG_BASE_SMALL=0 ++CONFIG_BASE_SMALL=n + CONFIG_BCMA_POSSIBLE=y + CONFIG_BINARY_PRINTF=y + CONFIG_BINFMT_ELF=y +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0009-build.conf-change-upload-target.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0009-build.conf-change-upload-target.patch new file mode 100644 index 0000000000..57f4f3b865 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0009-build.conf-change-upload-target.patch @@ -0,0 +1,23 @@ +From b72f0fe031ab48a161637592b03012372dc6bcc7 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Mon, 16 Jun 2025 09:03:51 +0200 +Subject: [PATCH 09/84] build.conf: change upload target + +--- + build.conf | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/build.conf b/build.conf +index 7681a4e75ce5..c6521172e2da 100644 +--- a/build.conf ++++ b/build.conf +@@ -1,5 +1,5 @@ + uploaduser=$USER +-uploadserver=r2 ++uploadserver=r3 + uploaddir=/var/lib/tftp + #uploaduser=root + #uploadserver=192.168.0.11 +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0010-arm-dts-mt7623-swap-mmc-and-put-uart2-first.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0010-arm-dts-mt7623-swap-mmc-and-put-uart2-first.patch new file mode 100644 index 0000000000..1644d3eecf --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0010-arm-dts-mt7623-swap-mmc-and-put-uart2-first.patch @@ -0,0 +1,87 @@ +From 1d780489e2f3b5de6d922d30a1a258113a031cef Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Mon, 12 Jul 2021 09:00:02 +0200 +Subject: [PATCH 10/84] arm: dts: mt7623: swap mmc and put uart2 first + +--- + arch/arm/boot/dts/mediatek/mt7623.dtsi | 42 +++++++++++++------------- + 1 file changed, 21 insertions(+), 21 deletions(-) + +diff --git a/arch/arm/boot/dts/mediatek/mt7623.dtsi b/arch/arm/boot/dts/mediatek/mt7623.dtsi +index fd7a89cc337d..0ad545ec0734 100644 +--- a/arch/arm/boot/dts/mediatek/mt7623.dtsi ++++ b/arch/arm/boot/dts/mediatek/mt7623.dtsi +@@ -372,6 +372,17 @@ auxadc: adc@11001000 { + #io-channel-cells = <1>; + }; + ++ uart2: serial@11004000 { ++ compatible = "mediatek,mt7623-uart", ++ "mediatek,mt6577-uart"; ++ reg = <0 0x11004000 0 0x400>; ++ interrupts = ; ++ clocks = <&pericfg CLK_PERI_UART2_SEL>, ++ <&pericfg CLK_PERI_UART2>; ++ clock-names = "baud", "bus"; ++ status = "disabled"; ++ }; ++ + uart0: serial@11002000 { + compatible = "mediatek,mt7623-uart", + "mediatek,mt6577-uart"; +@@ -394,17 +405,6 @@ uart1: serial@11003000 { + status = "disabled"; + }; + +- uart2: serial@11004000 { +- compatible = "mediatek,mt7623-uart", +- "mediatek,mt6577-uart"; +- reg = <0 0x11004000 0 0x400>; +- interrupts = ; +- clocks = <&pericfg CLK_PERI_UART2_SEL>, +- <&pericfg CLK_PERI_UART2>; +- clock-names = "baud", "bus"; +- status = "disabled"; +- }; +- + uart3: serial@11005000 { + compatible = "mediatek,mt7623-uart", + "mediatek,mt6577-uart"; +@@ -712,24 +712,24 @@ afe: audio-controller { + }; + }; + +- mmc0: mmc@11230000 { ++ mmc1: mmc@11240000 { + compatible = "mediatek,mt7623-mmc", + "mediatek,mt2701-mmc"; +- reg = <0 0x11230000 0 0x1000>; +- interrupts = ; +- clocks = <&pericfg CLK_PERI_MSDC30_0>, +- <&topckgen CLK_TOP_MSDC30_0_SEL>; ++ reg = <0 0x11240000 0 0x1000>; ++ interrupts = ; ++ clocks = <&pericfg CLK_PERI_MSDC30_1>, ++ <&topckgen CLK_TOP_MSDC30_1_SEL>; + clock-names = "source", "hclk"; + status = "disabled"; + }; + +- mmc1: mmc@11240000 { ++ mmc0: mmc@11230000 { + compatible = "mediatek,mt7623-mmc", + "mediatek,mt2701-mmc"; +- reg = <0 0x11240000 0 0x1000>; +- interrupts = ; +- clocks = <&pericfg CLK_PERI_MSDC30_1>, +- <&topckgen CLK_TOP_MSDC30_1_SEL>; ++ reg = <0 0x11230000 0 0x1000>; ++ interrupts = ; ++ clocks = <&pericfg CLK_PERI_MSDC30_0>, ++ <&topckgen CLK_TOP_MSDC30_0_SEL>; + clock-names = "source", "hclk"; + status = "disabled"; + }; +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0011-arm64-dts-disable-dtbs-for-dtbs_check.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0011-arm64-dts-disable-dtbs-for-dtbs_check.patch new file mode 100644 index 0000000000..38240e1f45 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0011-arm64-dts-disable-dtbs-for-dtbs_check.patch @@ -0,0 +1,307 @@ +From 475a62480df18eb13c58fcfd75f0337cb2749104 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Fri, 11 Apr 2025 08:45:54 +0200 +Subject: [PATCH 11/84] arm64: dts: disable dtbs for dtbs_check + +--- + arch/arm64/boot/dts/Makefile | 70 ++++----- + arch/arm64/boot/dts/mediatek/Makefile | 204 +++++++++++++------------- + 2 files changed, 137 insertions(+), 137 deletions(-) + +diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile +index 79b73a21ddc2..42ebeaeedf3b 100644 +--- a/arch/arm64/boot/dts/Makefile ++++ b/arch/arm64/boot/dts/Makefile +@@ -1,37 +1,37 @@ + # SPDX-License-Identifier: GPL-2.0 +-subdir-y += actions +-subdir-y += airoha +-subdir-y += allwinner +-subdir-y += altera +-subdir-y += amazon +-subdir-y += amd +-subdir-y += amlogic +-subdir-y += apm +-subdir-y += apple +-subdir-y += arm +-subdir-y += bitmain +-subdir-y += blaize +-subdir-y += broadcom +-subdir-y += cavium +-subdir-y += exynos +-subdir-y += freescale +-subdir-y += hisilicon +-subdir-y += intel +-subdir-y += lg +-subdir-y += marvell ++#subdir-y += actions ++#subdir-y += airoha ++#subdir-y += allwinner ++#subdir-y += altera ++#subdir-y += amazon ++#subdir-y += amd ++#subdir-y += amlogic ++#subdir-y += apm ++#subdir-y += apple ++#subdir-y += arm ++#subdir-y += bitmain ++#subdir-y += blaize ++#subdir-y += broadcom ++#subdir-y += cavium ++#subdir-y += exynos ++#subdir-y += freescale ++#subdir-y += hisilicon ++#subdir-y += intel ++#subdir-y += lg ++#subdir-y += marvell + subdir-y += mediatek +-subdir-y += microchip +-subdir-y += nuvoton +-subdir-y += nvidia +-subdir-y += qcom +-subdir-y += realtek +-subdir-y += renesas +-subdir-y += rockchip +-subdir-y += socionext +-subdir-y += sprd +-subdir-y += st +-subdir-y += synaptics +-subdir-y += tesla +-subdir-y += ti +-subdir-y += toshiba +-subdir-y += xilinx ++#subdir-y += microchip ++#subdir-y += nuvoton ++#subdir-y += nvidia ++#subdir-y += qcom ++#subdir-y += realtek ++#subdir-y += renesas ++#subdir-y += rockchip ++#subdir-y += socionext ++#subdir-y += sprd ++#subdir-y += st ++#subdir-y += synaptics ++#subdir-y += tesla ++#subdir-y += ti ++#subdir-y += toshiba ++#subdir-y += xilinx +diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile +index f68865d06edd..e60462fa2b6f 100644 +--- a/arch/arm64/boot/dts/mediatek/Makefile ++++ b/arch/arm64/boot/dts/mediatek/Makefile +@@ -1,110 +1,110 @@ + # SPDX-License-Identifier: GPL-2.0 +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt2712-evb.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt6755-evb.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt6779-evb.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt6795-evb.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt6795-sony-xperia-m5.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-evb.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-x20-dev.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-rfb1.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-bananapi-bpi-r64.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt7981b-cudy-wr3000-v1.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt7981b-openwrt-one.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt7981b-xiaomi-ax3000t.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-acelink-ew-7886cax.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-mini.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-emmc.dtbo +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-nand.dtbo +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-nor.dtbo +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-sata.dtbo +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-sd.dtbo +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-rfb.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986b-rfb.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt2712-evb.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt6755-evb.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt6779-evb.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt6795-evb.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt6795-sony-xperia-m5.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-evb.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-x20-dev.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-rfb1.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-bananapi-bpi-r64.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7981b-cudy-wr3000-v1.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7981b-openwrt-one.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7981b-xiaomi-ax3000t.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-acelink-ew-7886cax.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-mini.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-emmc.dtbo ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-nand.dtbo ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-nor.dtbo ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-sata.dtbo ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-sd.dtbo ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-rfb.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986b-rfb.dtb + dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4.dtb + dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-2g5.dtb + dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-emmc.dtbo + dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-sd.dtbo +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8167-pumpkin.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-elm.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-elm-hana.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-elm-hana-rev7.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-evb.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-evb.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-burnet.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-cozmo.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-damu.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel-sku1.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel-sku6.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel-sku7.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel14.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel14-sku2.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-juniper-sku16.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-kappa.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-kenzo.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-makomo-sku0.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-makomo-sku1.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-pico.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-pico6.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-willow-sku0.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-willow-sku1.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kakadu.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kakadu-sku22.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-katsu-sku32.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-katsu-sku38.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku16.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku272.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku288.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku32.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-krane-sku0.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-krane-sku176.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-pumpkin.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-chinchou-sku0.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-chinchou-sku1.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-chinchou-sku16.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-magneton-sku393216.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-magneton-sku393217.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-magneton-sku393218.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-ponyta-sku0.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-ponyta-sku1.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-rusty-sku196608.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-starmie-sku0.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-starmie-sku1.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-steelix-sku131072.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-steelix-sku131073.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacool-sku327681.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacool-sku327683.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacruel-sku262144.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacruel-sku262148.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-voltorb-sku589824.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-voltorb-sku589825.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-evb.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-evb.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-geralt-ciri-sku0.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-geralt-ciri-sku1.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-geralt-ciri-sku2.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-geralt-ciri-sku3.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-geralt-ciri-sku4.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-geralt-ciri-sku5.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-geralt-ciri-sku6.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-geralt-ciri-sku7.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8192-asurada-hayato-r1.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8192-asurada-spherion-r0.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8192-evb.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8195-cherry-dojo-r1.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8195-cherry-tomato-r1.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8195-cherry-tomato-r2.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8195-cherry-tomato-r3.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8195-demo.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8195-evb.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8365-evk.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8370-genio-510-evk.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8395-genio-1200-evk.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8390-genio-700-evk.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8395-kontron-3-5-sbc-i1200.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8395-radxa-nio-12l.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8395-radxa-nio-12l-8-hd-panel.dtbo +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8516-pumpkin.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8167-pumpkin.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-elm.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-elm-hana.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-elm-hana-rev7.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-evb.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-evb.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-burnet.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-cozmo.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-damu.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel-sku1.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel-sku6.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel-sku7.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel14.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel14-sku2.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-juniper-sku16.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-kappa.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-kenzo.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-makomo-sku0.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-makomo-sku1.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-pico.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-pico6.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-willow-sku0.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-willow-sku1.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kakadu.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kakadu-sku22.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-katsu-sku32.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-katsu-sku38.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku16.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku272.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku288.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku32.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-krane-sku0.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-krane-sku176.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-pumpkin.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-chinchou-sku0.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-chinchou-sku1.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-chinchou-sku16.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-magneton-sku393216.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-magneton-sku393217.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-magneton-sku393218.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-ponyta-sku0.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-ponyta-sku1.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-rusty-sku196608.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-starmie-sku0.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-starmie-sku1.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-steelix-sku131072.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-steelix-sku131073.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacool-sku327681.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacool-sku327683.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacruel-sku262144.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacruel-sku262148.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-voltorb-sku589824.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-voltorb-sku589825.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-evb.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-evb.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-geralt-ciri-sku0.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-geralt-ciri-sku1.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-geralt-ciri-sku2.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-geralt-ciri-sku3.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-geralt-ciri-sku4.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-geralt-ciri-sku5.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-geralt-ciri-sku6.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-geralt-ciri-sku7.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8192-asurada-hayato-r1.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8192-asurada-spherion-r0.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8192-evb.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8195-cherry-dojo-r1.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8195-cherry-tomato-r1.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8195-cherry-tomato-r2.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8195-cherry-tomato-r3.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8195-demo.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8195-evb.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8365-evk.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8370-genio-510-evk.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8395-genio-1200-evk.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8390-genio-700-evk.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8395-kontron-3-5-sbc-i1200.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8395-radxa-nio-12l.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8395-radxa-nio-12l-8-hd-panel.dtbo ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8516-pumpkin.dtb + + # Device tree overlays support + DTC_FLAGS_mt7986a-bananapi-bpi-r3 := -@ +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0012-dt-bindings-interconnect-add-mt7988-cci-compatible.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0012-dt-bindings-interconnect-add-mt7988-cci-compatible.patch new file mode 100644 index 0000000000..4c1af16c0d --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0012-dt-bindings-interconnect-add-mt7988-cci-compatible.patch @@ -0,0 +1,45 @@ +From 8aa7779a777a3b78193affeca2676039052f7a08 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Tue, 20 May 2025 19:04:22 +0200 +Subject: [PATCH 12/84] dt-bindings: interconnect: add mt7988-cci compatible + +Add compatible for Mediatek MT7988 SoC with mediatek,mt8183-cci fallback +which is taken by driver. + +Signed-off-by: Frank Wunderlich +Acked-by: Rob Herring (Arm) +Reviewed-by: AngeloGioacchino Del Regno +Acked-by: Georgi Djakov +--- +v2: +- no RFC +- drop "items" as sugested by conor +--- + .../bindings/interconnect/mediatek,cci.yaml | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/Documentation/devicetree/bindings/interconnect/mediatek,cci.yaml b/Documentation/devicetree/bindings/interconnect/mediatek,cci.yaml +index 58611ba2a0f4..4d72525f407e 100644 +--- a/Documentation/devicetree/bindings/interconnect/mediatek,cci.yaml ++++ b/Documentation/devicetree/bindings/interconnect/mediatek,cci.yaml +@@ -17,9 +17,14 @@ description: | + + properties: + compatible: +- enum: +- - mediatek,mt8183-cci +- - mediatek,mt8186-cci ++ oneOf: ++ - enum: ++ - mediatek,mt8183-cci ++ - mediatek,mt8186-cci ++ - items: ++ - enum: ++ - mediatek,mt7988-cci ++ - const: mediatek,mt8183-cci + + clocks: + items: +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0013-arm64-dts-mediatek-mt7988-add-cci-node.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0013-arm64-dts-mediatek-mt7988-add-cci-node.patch new file mode 100644 index 0000000000..c5161bad8f --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0013-arm64-dts-mediatek-mt7988-add-cci-node.patch @@ -0,0 +1,92 @@ +From a6bb99087048bd61a6f71a76f6d5bda171da5fd7 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sat, 1 Feb 2025 15:22:59 +0100 +Subject: [PATCH 13/84] arm64: dts: mediatek: mt7988: add cci node + +Add cci devicetree node for cpu frequency scaling. + +Signed-off-by: Daniel Golle +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +--- +v3: +- add mt7988-cci compatible as suggested by angelo +--- + arch/arm64/boot/dts/mediatek/mt7988a.dtsi | 33 +++++++++++++++++++++++ + 1 file changed, 33 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi +index c46b31f8d653..560ec86dbec0 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi +@@ -12,6 +12,35 @@ / { + #address-cells = <2>; + #size-cells = <2>; + ++ cci: cci { ++ compatible = "mediatek,mt7988-cci", "mediatek,mt8183-cci"; ++ clocks = <&mcusys CLK_MCU_BUS_DIV_SEL>, ++ <&topckgen CLK_TOP_XTAL>; ++ clock-names = "cci", "intermediate"; ++ operating-points-v2 = <&cci_opp>; ++ }; ++ ++ cci_opp: opp-table-cci { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ opp-480000000 { ++ opp-hz = /bits/ 64 <480000000>; ++ opp-microvolt = <850000>; ++ }; ++ opp-660000000 { ++ opp-hz = /bits/ 64 <660000000>; ++ opp-microvolt = <850000>; ++ }; ++ opp-900000000 { ++ opp-hz = /bits/ 64 <900000000>; ++ opp-microvolt = <850000>; ++ }; ++ opp-1080000000 { ++ opp-hz = /bits/ 64 <1080000000>; ++ opp-microvolt = <900000>; ++ }; ++ }; ++ + cpus { + #address-cells = <1>; + #size-cells = <0>; +@@ -25,6 +54,7 @@ cpu0: cpu@0 { + <&topckgen CLK_TOP_XTAL>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster0_opp>; ++ mediatek,cci = <&cci>; + }; + + cpu1: cpu@1 { +@@ -36,6 +66,7 @@ cpu1: cpu@1 { + <&topckgen CLK_TOP_XTAL>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster0_opp>; ++ mediatek,cci = <&cci>; + }; + + cpu2: cpu@2 { +@@ -47,6 +78,7 @@ cpu2: cpu@2 { + <&topckgen CLK_TOP_XTAL>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster0_opp>; ++ mediatek,cci = <&cci>; + }; + + cpu3: cpu@3 { +@@ -58,6 +90,7 @@ cpu3: cpu@3 { + <&topckgen CLK_TOP_XTAL>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster0_opp>; ++ mediatek,cci = <&cci>; + }; + + cluster0_opp: opp-table-0 { +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0014-arm64-dts-mediatek-mt7988a-bpi-r4-add-proc-supply-fo.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0014-arm64-dts-mediatek-mt7988a-bpi-r4-add-proc-supply-fo.patch new file mode 100644 index 0000000000..3b029f2c57 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0014-arm64-dts-mediatek-mt7988a-bpi-r4-add-proc-supply-fo.patch @@ -0,0 +1,32 @@ +From 6d1ea6d069461b0a97af8295fc5c46542b5b1cb4 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sun, 4 May 2025 15:17:13 +0200 +Subject: [PATCH 14/84] arm64: dts: mediatek: mt7988a-bpi-r4: add proc-supply + for cci + +CCI requires proc-supply. Add it on board level. + +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +--- + arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi +index 81ba045e0e0e..afa9e3b2b16a 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi +@@ -40,6 +40,10 @@ reg_3p3v: regulator-3p3v { + }; + }; + ++&cci { ++ proc-supply = <&rt5190_buck3>; ++}; ++ + &cpu0 { + proc-supply = <&rt5190_buck3>; + }; +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0015-arm64-dts-mediatek-mt7988a-bpi-r4-drop-unused-pins.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0015-arm64-dts-mediatek-mt7988a-bpi-r4-drop-unused-pins.patch new file mode 100644 index 0000000000..2ba6f3a745 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0015-arm64-dts-mediatek-mt7988a-bpi-r4-drop-unused-pins.patch @@ -0,0 +1,151 @@ +From 84dc2ca96d2acd136085ab98fcc92176c1be1aa9 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sat, 17 May 2025 09:04:19 +0200 +Subject: [PATCH 15/84] arm64: dts: mediatek: mt7988a-bpi-r4: drop unused pins + +Pins were moved from SoC dtsi to Board level dtsi without cleaning up +to needed ones. Drop the unused pins now. + +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +--- + .../dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi | 89 ------------------- + 1 file changed, 89 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi +index afa9e3b2b16a..30affedf84d4 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi +@@ -223,18 +223,6 @@ &pcie3 { + }; + + &pio { +- mdio0_pins: mdio0-pins { +- mux { +- function = "eth"; +- groups = "mdc_mdio0"; +- }; +- +- conf { +- pins = "SMI_0_MDC", "SMI_0_MDIO"; +- drive-strength = <8>; +- }; +- }; +- + i2c0_pins: i2c0-g0-pins { + mux { + function = "i2c"; +@@ -249,20 +237,6 @@ mux { + }; + }; + +- i2c1_sfp_pins: i2c1-sfp-g0-pins { +- mux { +- function = "i2c"; +- groups = "i2c1_sfp"; +- }; +- }; +- +- i2c2_0_pins: i2c2-g0-pins { +- mux { +- function = "i2c"; +- groups = "i2c2_0"; +- }; +- }; +- + i2c2_1_pins: i2c2-g1-pins { + mux { + function = "i2c"; +@@ -298,34 +272,6 @@ mux { + }; + }; + +- gbe0_led1_pins: gbe0-led1-pins { +- mux { +- function = "led"; +- groups = "gbe0_led1"; +- }; +- }; +- +- gbe1_led1_pins: gbe1-led1-pins { +- mux { +- function = "led"; +- groups = "gbe1_led1"; +- }; +- }; +- +- gbe2_led1_pins: gbe2-led1-pins { +- mux { +- function = "led"; +- groups = "gbe2_led1"; +- }; +- }; +- +- gbe3_led1_pins: gbe3-led1-pins { +- mux { +- function = "led"; +- groups = "gbe3_led1"; +- }; +- }; +- + i2p5gbe_led0_pins: 2p5gbe-led0-pins { + mux { + function = "led"; +@@ -333,13 +279,6 @@ mux { + }; + }; + +- i2p5gbe_led1_pins: 2p5gbe-led1-pins { +- mux { +- function = "led"; +- groups = "2p5gbe_led1"; +- }; +- }; +- + mmc0_pins_emmc_45: mmc0-emmc-45-pins { + mux { + function = "flash"; +@@ -361,40 +300,12 @@ mux { + }; + }; + +- snfi_pins: snfi-pins { +- mux { +- function = "flash"; +- groups = "snfi"; +- }; +- }; +- +- spi0_pins: spi0-pins { +- mux { +- function = "spi"; +- groups = "spi0"; +- }; +- }; +- + spi0_flash_pins: spi0-flash-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + }; +- +- spi2_pins: spi2-pins { +- mux { +- function = "spi"; +- groups = "spi2"; +- }; +- }; +- +- spi2_flash_pins: spi2-flash-pins { +- mux { +- function = "spi"; +- groups = "spi2", "spi2_wp_hold"; +- }; +- }; + }; + + &pwm { +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0016-arm64-dts-mediatek-mt7988a-bpi-r4-add-gpio-leds.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0016-arm64-dts-mediatek-mt7988a-bpi-r4-add-gpio-leds.patch new file mode 100644 index 0000000000..d985f8ce91 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0016-arm64-dts-mediatek-mt7988a-bpi-r4-add-gpio-leds.patch @@ -0,0 +1,50 @@ +From c5a6b9feed48fc85b9dcae3b0a171df317e159f7 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Wed, 4 Jun 2025 17:50:22 +0200 +Subject: [PATCH 16/84] arm64: dts: mediatek: mt7988a-bpi-r4: add gpio leds + +Bananapi R4 has a green and a blue led which can be switched by gpio. +Green led is for running state so default on. + +Green led also shares pin with eeprom writeprotect where led off allows +writing to eeprom. + +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +--- + .../dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi +index 30affedf84d4..21eb91c8609f 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi +@@ -21,6 +21,25 @@ fan: pwm-fan { + status = "okay"; + }; + ++ gpio-leds { ++ compatible = "gpio-leds"; ++ ++ led_green: led-green { ++ function = LED_FUNCTION_STATUS; ++ color = ; ++ gpios = <&pio 79 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ ++ led_blue: led-blue { ++ function = LED_FUNCTION_WPS; ++ color = ; ++ gpios = <&pio 63 GPIO_ACTIVE_HIGH>; ++ default-state = "off"; ++ }; ++ }; ++ ++ + reg_1p8v: regulator-1p8v { + compatible = "regulator-fixed"; + regulator-name = "fixed-1.8V"; +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0017-v9-coverletter-further-mt7988-devicetree-work.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0017-v9-coverletter-further-mt7988-devicetree-work.patch new file mode 100644 index 0000000000..e69de29bb2 diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0018-dt-bindings-net-mediatek-net-update-mac-subnode-patt.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0018-dt-bindings-net-mediatek-net-update-mac-subnode-patt.patch new file mode 100644 index 0000000000..23026e3488 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0018-dt-bindings-net-mediatek-net-update-mac-subnode-patt.patch @@ -0,0 +1,32 @@ +From a156ad0546aec9ecca31c219f9658be8475d752b Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Thu, 3 Jul 2025 20:19:35 +0200 +Subject: [PATCH 18/84] dt-bindings: net: mediatek,net: update mac subnode + pattern for mt7988 + +MT7888 have 3 Macs and so its nodes have names from mac0 - mac2. Update +pattern to fix this. + +Fixes: c94a9aabec36 ("dt-bindings: net: mediatek,net: add mt7988-eth binding") +Signed-off-by: Frank Wunderlich +Reviewed-by: Krzysztof Kozlowski +--- + Documentation/devicetree/bindings/net/mediatek,net.yaml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/net/mediatek,net.yaml b/Documentation/devicetree/bindings/net/mediatek,net.yaml +index 9e02fd80af83..175d1d011dc6 100644 +--- a/Documentation/devicetree/bindings/net/mediatek,net.yaml ++++ b/Documentation/devicetree/bindings/net/mediatek,net.yaml +@@ -382,7 +382,7 @@ allOf: + - const: xgp3 + + patternProperties: +- "^mac@[0-1]$": ++ "^mac@[0-2]$": + type: object + unevaluatedProperties: false + allOf: +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0019-dt-bindings-net-mediatek-net-allow-up-to-8-IRQs.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0019-dt-bindings-net-mediatek-net-allow-up-to-8-IRQs.patch new file mode 100644 index 0000000000..f5749a79c5 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0019-dt-bindings-net-mediatek-net-allow-up-to-8-IRQs.patch @@ -0,0 +1,90 @@ +From 35f241527f0146b5608a2239684005469bca4d4d Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Thu, 3 Jul 2025 20:22:18 +0200 +Subject: [PATCH 19/84] dt-bindings: net: mediatek,net: allow up to 8 IRQs + +Increase the maximum IRQ count to 8 (4 FE + 4 RSS/LRO). + +Frame-engine-IRQs (max 4): +MT7621, MT7628: 1 FE-IRQ +MT7622, MT7623: 3 FE-IRQs (only two used by the driver for now) +MT7981, MT7986, MT7988: 4 FE-IRQs (only two used by the driver for now) + +Mediatek Filogic SoCs (mt798x) have 4 additional IRQs for RSS and/or +LRO. So MT798x have 8 IRQs in total. + +MT7981 does not have a ethernet-node yet. +MT7986 Ethernet node is updated with RSS/LRO IRQs in this series. +MT7988 Ethernet node is added in this series. + +Signed-off-by: Frank Wunderlich +Reviewed-by: Krzysztof Kozlowski +--- +v9: +- set interrupt minitems to 8 for filogic + - mt7981 does not have a ethernet node yet, so no ABI break + - devicetree for mt7986 is updated later in this series, ABI-Break, + but RSS/LRO should use interrupt names and is simply disabled when + using older DT +- extend mt7986 example with PDMA-IRQs because minItems now 8 +v8: separate irq-count change from interrupt-names patch +--- + .../devicetree/bindings/net/mediatek,net.yaml | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/Documentation/devicetree/bindings/net/mediatek,net.yaml b/Documentation/devicetree/bindings/net/mediatek,net.yaml +index 175d1d011dc6..99dc0401eb9a 100644 +--- a/Documentation/devicetree/bindings/net/mediatek,net.yaml ++++ b/Documentation/devicetree/bindings/net/mediatek,net.yaml +@@ -40,7 +40,7 @@ properties: + + interrupts: + minItems: 1 +- maxItems: 4 ++ maxItems: 8 + + power-domains: + maxItems: 1 +@@ -272,7 +272,7 @@ allOf: + then: + properties: + interrupts: +- minItems: 4 ++ minItems: 8 + + clocks: + minItems: 15 +@@ -310,7 +310,7 @@ allOf: + then: + properties: + interrupts: +- minItems: 4 ++ minItems: 8 + + clocks: + minItems: 15 +@@ -348,7 +348,7 @@ allOf: + then: + properties: + interrupts: +- minItems: 4 ++ minItems: 8 + + clocks: + minItems: 24 +@@ -507,7 +507,11 @@ examples: + interrupts = , + , + , +- ; ++ , ++ , ++ , ++ , ++ ; + clocks = <ðsys CLK_ETH_FE_EN>, + <ðsys CLK_ETH_GP2_EN>, + <ðsys CLK_ETH_GP1_EN>, +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0020-dt-bindings-net-mediatek-net-allow-irq-names.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0020-dt-bindings-net-mediatek-net-allow-irq-names.patch new file mode 100644 index 0000000000..49ddcda03c --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0020-dt-bindings-net-mediatek-net-allow-irq-names.patch @@ -0,0 +1,141 @@ +From 2c7be45741bd444a44e0bf18a010ce378396d8ac Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Thu, 3 Jul 2025 20:31:42 +0200 +Subject: [PATCH 20/84] dt-bindings: net: mediatek,net: allow irq names + +In preparation for MT7988 and RSS/LRO allow the interrupt-names +property. +In this way driver can request the interrupts by name which is much +more readable in the driver code and SoC's dtsi than relying on a +specific order. + +Frame-engine-IRQs (fe0..3): +MT7621, MT7628: 1 FE-IRQ +MT7622, MT7623: 3 FE-IRQs (only two used by the driver for now) +MT7981, MT7986: 4 FE-IRQs (only two used by the driver for now) + +RSS/LRO IRQs (pdma0..3) additional only on Filogic (MT798x) with +count of 4. So all IRQ-names (8) for Filogic. + +Set boundaries for all compatibles same as irq count. + +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: Krzysztof Kozlowski +--- +v9: +- add interrupt-names minitems to 8 for filogic + - mt7981 does not have a ethernet node yet + - devicetree for mt7986 is updated later in this series +- small rephrase IRQ => FE-IRQ and mention total count of IRQs on Filogic. +- kept angelos RB because of small change, i hope it is ok :) + +v8: + - fixed typo in mt7621 section "interrupt-namess" + - separated interrupt count from interrupt-names + - rephrased description a bit to explain the "why" +v7: fixed wrong rebase +v6: new patch splitted from the mt7988 changes +--- + .../devicetree/bindings/net/mediatek,net.yaml | 36 +++++++++++++++++++ + 1 file changed, 36 insertions(+) + +diff --git a/Documentation/devicetree/bindings/net/mediatek,net.yaml b/Documentation/devicetree/bindings/net/mediatek,net.yaml +index 99dc0401eb9a..d2b5461e73bc 100644 +--- a/Documentation/devicetree/bindings/net/mediatek,net.yaml ++++ b/Documentation/devicetree/bindings/net/mediatek,net.yaml +@@ -42,6 +42,18 @@ properties: + minItems: 1 + maxItems: 8 + ++ interrupt-names: ++ minItems: 1 ++ items: ++ - const: fe0 ++ - const: fe1 ++ - const: fe2 ++ - const: fe3 ++ - const: pdma0 ++ - const: pdma1 ++ - const: pdma2 ++ - const: pdma3 ++ + power-domains: + maxItems: 1 + +@@ -135,6 +147,10 @@ allOf: + minItems: 3 + maxItems: 3 + ++ interrupt-names: ++ minItems: 3 ++ maxItems: 3 ++ + clocks: + minItems: 4 + maxItems: 4 +@@ -166,6 +182,9 @@ allOf: + interrupts: + maxItems: 1 + ++ interrupt-names: ++ maxItems: 1 ++ + clocks: + minItems: 2 + maxItems: 2 +@@ -192,6 +211,10 @@ allOf: + minItems: 3 + maxItems: 3 + ++ interrupt-names: ++ minItems: 3 ++ maxItems: 3 ++ + clocks: + minItems: 11 + maxItems: 11 +@@ -232,6 +255,10 @@ allOf: + minItems: 3 + maxItems: 3 + ++ interrupt-names: ++ minItems: 3 ++ maxItems: 3 ++ + clocks: + minItems: 17 + maxItems: 17 +@@ -274,6 +301,9 @@ allOf: + interrupts: + minItems: 8 + ++ interrupt-names: ++ minItems: 8 ++ + clocks: + minItems: 15 + maxItems: 15 +@@ -312,6 +342,9 @@ allOf: + interrupts: + minItems: 8 + ++ interrupt-names: ++ minItems: 8 ++ + clocks: + minItems: 15 + maxItems: 15 +@@ -350,6 +383,9 @@ allOf: + interrupts: + minItems: 8 + ++ interrupt-names: ++ minItems: 8 ++ + clocks: + minItems: 24 + maxItems: 24 +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0021-dt-bindings-net-mediatek-net-add-sram-property.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0021-dt-bindings-net-mediatek-net-add-sram-property.patch new file mode 100644 index 0000000000..c94f2164dd --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0021-dt-bindings-net-mediatek-net-add-sram-property.patch @@ -0,0 +1,107 @@ +From ceafe6027cde06a1216ceb52a1f2da05d4c564fd Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sat, 28 Jun 2025 10:42:49 +0200 +Subject: [PATCH 21/84] dt-bindings: net: mediatek,net: add sram property + +Meditak Filogic SoCs (MT798x) have dedicated MMIO-SRAM for dma operations. + +MT7981 and MT7986 currently use static offset to ethernet MAC register +which will be changed in separate patch once this way is accepted. + +Add "sram" property to map ethernet controller to dedicated mmio-sram node. + +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: Krzysztof Kozlowski +--- +v9: +- add "sram: false" for non-filogic + +v8: +- splitted out mac subnode pattern +- dropped reg naming change +- rephrased description +- drop change of reg-name + +v6: +- split out the interrupt-names into separate patch +- update irq(name) min count to 4 +- add sram-property +- drop second reg entry and minitems as there is only 1 item left again + +v5: +- fix v4 logmessage and change description a bit describing how i get + the irq count. +- update binding for 8 irqs with different names (rx,tx => fe0..fe3) + including the 2 reserved irqs which can be used later +- change rx-ringX to pdmaX to be closer to hardware documentation + +v4: +- increase max interrupts to 6 because of adding RSS/LRO interrupts (4) + and dropping 2 reserved irqs (0+3) around rx+tx +- dropped Robs RB due to this change +- allow interrupt names +- add interrupt-names without reserved IRQs on mt7988 + this requires mtk driver patch: + https://patchwork.kernel.org/project/netdevbpf/patch/20250616080738.117993-2-linux@fw-web.de/ + +v2: +- change reg to list of items +--- + .../devicetree/bindings/net/mediatek,net.yaml | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/Documentation/devicetree/bindings/net/mediatek,net.yaml b/Documentation/devicetree/bindings/net/mediatek,net.yaml +index d2b5461e73bc..b45f67f92e80 100644 +--- a/Documentation/devicetree/bindings/net/mediatek,net.yaml ++++ b/Documentation/devicetree/bindings/net/mediatek,net.yaml +@@ -66,6 +66,10 @@ properties: + - const: gmac + - const: ppe + ++ sram: ++ $ref: /schemas/types.yaml#/definitions/phandle ++ description: phandle to mmio SRAM ++ + mediatek,ethsys: + $ref: /schemas/types.yaml#/definitions/phandle + description: +@@ -162,6 +166,8 @@ allOf: + - const: gp1 + - const: gp2 + ++ sram: false ++ + mediatek,infracfg: false + + mediatek,wed: false +@@ -194,6 +200,8 @@ allOf: + - const: ethif + - const: fe + ++ sram: false ++ + mediatek,infracfg: false + + mediatek,wed: false +@@ -233,6 +241,8 @@ allOf: + - const: sgmii_ck + - const: eth2pll + ++ sram: false ++ + mediatek,infracfg: false + + mediatek,sgmiisys: +@@ -283,6 +293,8 @@ allOf: + - const: sgmii_ck + - const: eth2pll + ++ sram: false ++ + mediatek,sgmiisys: + minItems: 2 + maxItems: 2 +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0022-dt-bindings-net-dsa-mediatek-mt7530-add-dsa-port-def.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0022-dt-bindings-net-dsa-mediatek-mt7530-add-dsa-port-def.patch new file mode 100644 index 0000000000..72a22527cd --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0022-dt-bindings-net-dsa-mediatek-mt7530-add-dsa-port-def.patch @@ -0,0 +1,51 @@ +From 7334c38f35771ab025253b803990d07864ca1ffb Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Tue, 6 May 2025 17:29:16 +0200 +Subject: [PATCH 22/84] dt-bindings: net: dsa: mediatek,mt7530: add dsa-port + definition for mt7988 + +Add own dsa-port binding for SoC with internal switch where only phy-mode +'internal' is valid. + +Signed-off-by: Frank Wunderlich +Reviewed-by: Rob Herring (Arm) +Reviewed-by: AngeloGioacchino Del Regno +--- + .../bindings/net/dsa/mediatek,mt7530.yaml | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/net/dsa/mediatek,mt7530.yaml b/Documentation/devicetree/bindings/net/dsa/mediatek,mt7530.yaml +index 51205f9f2985..9b983fdbf3c7 100644 +--- a/Documentation/devicetree/bindings/net/dsa/mediatek,mt7530.yaml ++++ b/Documentation/devicetree/bindings/net/dsa/mediatek,mt7530.yaml +@@ -190,6 +190,18 @@ required: + - reg + + $defs: ++ builtin-dsa-port: ++ patternProperties: ++ "^(ethernet-)?ports$": ++ patternProperties: ++ "^(ethernet-)?port@[0-6]$": ++ if: ++ required: [ ethernet ] ++ then: ++ properties: ++ phy-mode: ++ const: internal ++ + mt7530-dsa-port: + patternProperties: + "^(ethernet-)?ports$": +@@ -297,7 +309,7 @@ allOf: + - airoha,en7581-switch + - airoha,an7583-switch + then: +- $ref: "#/$defs/mt7530-dsa-port" ++ $ref: "#/$defs/builtin-dsa-port" + properties: + gpio-controller: false + mediatek,mcm: false +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0023-dt-bindings-net-dsa-mediatek-mt7530-add-internal-mdi.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0023-dt-bindings-net-dsa-mediatek-mt7530-add-internal-mdi.patch new file mode 100644 index 0000000000..60a0b7a9a1 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0023-dt-bindings-net-dsa-mediatek-mt7530-add-internal-mdi.patch @@ -0,0 +1,44 @@ +From 71bb13e3a85a6efd666cb698acb3f8227a7f2fa5 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Tue, 6 May 2025 18:56:25 +0200 +Subject: [PATCH 23/84] dt-bindings: net: dsa: mediatek,mt7530: add internal + mdio bus + +Mt7988 buildin switch has own mdio bus where ge-phys are connected. +Add related property for this. + +Signed-off-by: Frank Wunderlich +Reviewed-by: Rob Herring (Arm) +Reviewed-by: AngeloGioacchino Del Regno +--- +v2: +- change from patternproperty to property +- add unevaluatedProperties and mediatek,pio subproperty +--- + .../devicetree/bindings/net/dsa/mediatek,mt7530.yaml | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/Documentation/devicetree/bindings/net/dsa/mediatek,mt7530.yaml b/Documentation/devicetree/bindings/net/dsa/mediatek,mt7530.yaml +index 9b983fdbf3c7..815a90808901 100644 +--- a/Documentation/devicetree/bindings/net/dsa/mediatek,mt7530.yaml ++++ b/Documentation/devicetree/bindings/net/dsa/mediatek,mt7530.yaml +@@ -136,6 +136,16 @@ properties: + See Documentation/devicetree/bindings/regulator/mt6323-regulator.txt for + details for the regulator setup on these boards. + ++ mdio: ++ $ref: /schemas/net/mdio.yaml# ++ unevaluatedProperties: false ++ ++ properties: ++ mediatek,pio: ++ $ref: /schemas/types.yaml#/definitions/phandle ++ description: ++ Phandle pointing to the mediatek pinctrl node. ++ + mediatek,mcm: + type: boolean + description: +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0024-arm64-dts-mediatek-mt7986-add-sram-node.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0024-arm64-dts-mediatek-mt7986-add-sram-node.patch new file mode 100644 index 0000000000..54b10c9aa8 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0024-arm64-dts-mediatek-mt7986-add-sram-node.patch @@ -0,0 +1,53 @@ +From 088c4b18aeb6c7be84f381549a331a26735db576 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Fri, 27 Jun 2025 22:58:16 +0200 +Subject: [PATCH 24/84] arm64: dts: mediatek: mt7986: add sram node + +Currently sram is allocated in driver via offset from reg of ethernet +node. Change it to use a dedicated sram node like mt7988. + +Signed-off-by: Frank Wunderlich +--- + arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +index 559990dcd1d1..550f569451fb 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +@@ -523,7 +523,7 @@ wed1: wed@15011000 { + + eth: ethernet@15100000 { + compatible = "mediatek,mt7986-eth"; +- reg = <0 0x15100000 0 0x80000>; ++ reg = <0 0x15100000 0 0x40000>; + interrupts = , + , + , +@@ -553,6 +553,7 @@ eth: ethernet@15100000 { + <&topckgen CLK_TOP_SGM_325M_SEL>; + assigned-clock-parents = <&apmixedsys CLK_APMIXED_NET2PLL>, + <&apmixedsys CLK_APMIXED_SGMPLL>; ++ sram = <ð_sram>; + #address-cells = <1>; + #size-cells = <0>; + mediatek,ethsys = <ðsys>; +@@ -562,6 +563,15 @@ eth: ethernet@15100000 { + status = "disabled"; + }; + ++ /*15100000+0x40000*/ ++ eth_sram: sram@15140000 { ++ compatible = "mmio-sram"; ++ reg = <0 0x15140000 0 0x40000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0 0x15140000 0 0x40000>; ++ }; ++ + wo_ccif0: syscon@151a5000 { + compatible = "mediatek,mt7986-wo-ccif", "syscon"; + reg = <0 0x151a5000 0 0x1000>; +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0025-arm64-dts-mediatek-mt7986-add-interrupts-for-RSS-and.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0025-arm64-dts-mediatek-mt7986-add-interrupts-for-RSS-and.patch new file mode 100644 index 0000000000..7ed03b3da9 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0025-arm64-dts-mediatek-mt7986-add-interrupts-for-RSS-and.patch @@ -0,0 +1,36 @@ +From 676b92ba3ccac93969807ec86cfde2acbe80f99a Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Wed, 12 Mar 2025 18:11:21 +0100 +Subject: [PATCH 25/84] arm64: dts: mediatek: mt7986: add interrupts for RSS + and interrupt names + +Add interrupts for RSS/LRO and names to access them via name instead of +index. + +Signed-off-by: Frank Wunderlich +--- + arch/arm64/boot/dts/mediatek/mt7986a.dtsi | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +index 550f569451fb..a9e079fd42c6 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +@@ -527,7 +527,13 @@ eth: ethernet@15100000 { + interrupts = , + , + , +- ; ++ , ++ , ++ , ++ , ++ ; ++ interrupt-names = "fe0", "fe1", "fe2", "fe3", "pdma0", ++ "pdma1", "pdma2", "pdma3"; + clocks = <ðsys CLK_ETH_FE_EN>, + <ðsys CLK_ETH_GP2_EN>, + <ðsys CLK_ETH_GP1_EN>, +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0026-arm64-dts-mediatek-mt7988-add-basic-ethernet-nodes.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0026-arm64-dts-mediatek-mt7988-add-basic-ethernet-nodes.patch new file mode 100644 index 0000000000..1a11f351f3 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0026-arm64-dts-mediatek-mt7988-add-basic-ethernet-nodes.patch @@ -0,0 +1,208 @@ +From db0b8ad2dbed7ab767af5684c83aea353d11e327 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Thu, 28 Nov 2024 18:48:07 +0100 +Subject: [PATCH 26/84] arm64: dts: mediatek: mt7988: add basic ethernet-nodes + +Add basic ethernet related nodes. + +Mac1+2 needs pcs (sgmii+usxgmii) to work correctly which will be linked +later when driver is merged. + +Signed-off-by: Daniel Golle +Signed-off-by: Frank Wunderlich +--- +v8: +- change ethernet register size to 0x40000 + range from 0x15140000 ~ 0x1517ffff is not usable on mt7988 => 0xDEADBEEF + +v6: +- fix whitespace-errors for pdma irqs (spaces vs. tabs) +- move sram from eth reg to own sram node (needs CONFIG_SRAM) + +v5: +- add reserved irqs and change names to fe0..fe3 +- change rx-ringX to pdmaX to be closer to documentation + +v4: +- comment for fixed-link on gmac0 +- update 2g5 phy node + - unit-name dec instead of hex to match reg property + - move compatible before reg + - drop phy-mode +- add interrupts for RSS +- add interrupt-names and drop reserved irqs for ethernet +- some reordering +- eth-reg and clock whitespace-fix based on angelos review +--- + arch/arm64/boot/dts/mediatek/mt7988a.dtsi | 137 +++++++++++++++++++++- + 1 file changed, 134 insertions(+), 3 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi +index 560ec86dbec0..897b5a82b53e 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi +@@ -680,7 +680,28 @@ xphyu3port0: usb-phy@11e13000 { + }; + }; + +- clock-controller@11f40000 { ++ xfi_tphy0: phy@11f20000 { ++ compatible = "mediatek,mt7988-xfi-tphy"; ++ reg = <0 0x11f20000 0 0x10000>; ++ clocks = <&xfi_pll CLK_XFIPLL_PLL_EN>, ++ <&topckgen CLK_TOP_XFI_PHY_0_XTAL_SEL>; ++ clock-names = "xfipll", "topxtal"; ++ resets = <&watchdog 14>; ++ mediatek,usxgmii-performance-errata; ++ #phy-cells = <0>; ++ }; ++ ++ xfi_tphy1: phy@11f30000 { ++ compatible = "mediatek,mt7988-xfi-tphy"; ++ reg = <0 0x11f30000 0 0x10000>; ++ clocks = <&xfi_pll CLK_XFIPLL_PLL_EN>, ++ <&topckgen CLK_TOP_XFI_PHY_1_XTAL_SEL>; ++ clock-names = "xfipll", "topxtal"; ++ resets = <&watchdog 15>; ++ #phy-cells = <0>; ++ }; ++ ++ xfi_pll: clock-controller@11f40000 { + compatible = "mediatek,mt7988-xfi-pll"; + reg = <0 0x11f40000 0 0x1000>; + resets = <&watchdog 16>; +@@ -714,19 +735,129 @@ phy_calibration_p3: calib@97c { + }; + }; + +- clock-controller@15000000 { ++ ethsys: clock-controller@15000000 { + compatible = "mediatek,mt7988-ethsys", "syscon"; + reg = <0 0x15000000 0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + +- clock-controller@15031000 { ++ ethwarp: clock-controller@15031000 { + compatible = "mediatek,mt7988-ethwarp"; + reg = <0 0x15031000 0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; ++ ++ eth: ethernet@15100000 { ++ compatible = "mediatek,mt7988-eth"; ++ reg = <0 0x15100000 0 0x40000>; ++ interrupts = , ++ , ++ , ++ , ++ , ++ , ++ , ++ ; ++ interrupt-names = "fe0", "fe1", "fe2", "fe3", "pdma0", ++ "pdma1", "pdma2", "pdma3"; ++ clocks = <ðsys CLK_ETHDMA_CRYPT0_EN>, ++ <ðsys CLK_ETHDMA_FE_EN>, ++ <ðsys CLK_ETHDMA_GP2_EN>, ++ <ðsys CLK_ETHDMA_GP1_EN>, ++ <ðsys CLK_ETHDMA_GP3_EN>, ++ <ðwarp CLK_ETHWARP_WOCPU2_EN>, ++ <ðwarp CLK_ETHWARP_WOCPU1_EN>, ++ <ðwarp CLK_ETHWARP_WOCPU0_EN>, ++ <ðsys CLK_ETHDMA_ESW_EN>, ++ <&topckgen CLK_TOP_ETH_GMII_SEL>, ++ <&topckgen CLK_TOP_ETH_REFCK_50M_SEL>, ++ <&topckgen CLK_TOP_ETH_SYS_200M_SEL>, ++ <&topckgen CLK_TOP_ETH_SYS_SEL>, ++ <&topckgen CLK_TOP_ETH_XGMII_SEL>, ++ <&topckgen CLK_TOP_ETH_MII_SEL>, ++ <&topckgen CLK_TOP_NETSYS_SEL>, ++ <&topckgen CLK_TOP_NETSYS_500M_SEL>, ++ <&topckgen CLK_TOP_NETSYS_PAO_2X_SEL>, ++ <&topckgen CLK_TOP_NETSYS_SYNC_250M_SEL>, ++ <&topckgen CLK_TOP_NETSYS_PPEFB_250M_SEL>, ++ <&topckgen CLK_TOP_NETSYS_WARP_SEL>, ++ <ðsys CLK_ETHDMA_XGP1_EN>, ++ <ðsys CLK_ETHDMA_XGP2_EN>, ++ <ðsys CLK_ETHDMA_XGP3_EN>; ++ clock-names = "crypto", "fe", "gp2", "gp1", "gp3", ++ "ethwarp_wocpu2", "ethwarp_wocpu1", ++ "ethwarp_wocpu0", "esw", "top_eth_gmii_sel", ++ "top_eth_refck_50m_sel", "top_eth_sys_200m_sel", ++ "top_eth_sys_sel", "top_eth_xgmii_sel", ++ "top_eth_mii_sel", "top_netsys_sel", ++ "top_netsys_500m_sel", "top_netsys_pao_2x_sel", ++ "top_netsys_sync_250m_sel", ++ "top_netsys_ppefb_250m_sel", ++ "top_netsys_warp_sel","xgp1", "xgp2", "xgp3"; ++ assigned-clocks = <&topckgen CLK_TOP_NETSYS_2X_SEL>, ++ <&topckgen CLK_TOP_NETSYS_GSW_SEL>, ++ <&topckgen CLK_TOP_USXGMII_SBUS_0_SEL>, ++ <&topckgen CLK_TOP_USXGMII_SBUS_1_SEL>, ++ <&topckgen CLK_TOP_SGM_0_SEL>, ++ <&topckgen CLK_TOP_SGM_1_SEL>; ++ assigned-clock-parents = <&apmixedsys CLK_APMIXED_NET2PLL>, ++ <&topckgen CLK_TOP_NET1PLL_D4>, ++ <&topckgen CLK_TOP_NET1PLL_D8_D4>, ++ <&topckgen CLK_TOP_NET1PLL_D8_D4>, ++ <&apmixedsys CLK_APMIXED_SGMPLL>, ++ <&apmixedsys CLK_APMIXED_SGMPLL>; ++ sram = <ð_sram>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ mediatek,ethsys = <ðsys>; ++ mediatek,infracfg = <&topmisc>; ++ ++ gmac0: mac@0 { ++ compatible = "mediatek,eth-mac"; ++ reg = <0>; ++ phy-mode = "internal"; ++ ++ /* Connected to internal switch */ ++ fixed-link { ++ speed = <10000>; ++ full-duplex; ++ pause; ++ }; ++ }; ++ ++ gmac1: mac@1 { ++ compatible = "mediatek,eth-mac"; ++ reg = <1>; ++ status = "disabled"; ++ }; ++ ++ gmac2: mac@2 { ++ compatible = "mediatek,eth-mac"; ++ reg = <2>; ++ status = "disabled"; ++ }; ++ ++ mdio_bus: mdio-bus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ /* internal 2.5G PHY */ ++ int_2p5g_phy: ethernet-phy@15 { ++ compatible = "ethernet-phy-ieee802.3-c45"; ++ reg = <15>; ++ }; ++ }; ++ }; ++ ++ eth_sram: sram@15400000 { ++ compatible = "mmio-sram"; ++ reg = <0 0x15400000 0 0x200000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ranges = <0 0x15400000 0 0x200000>; ++ }; + }; + + thermal-zones { +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0027-arm64-dts-mediatek-mt7988-add-switch-node.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0027-arm64-dts-mediatek-mt7988-add-switch-node.patch new file mode 100644 index 0000000000..3f59f75ab5 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0027-arm64-dts-mediatek-mt7988-add-switch-node.patch @@ -0,0 +1,184 @@ +From 2292b669f7c265c39f2836b894270305b1d32a39 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sat, 1 Feb 2025 15:18:12 +0100 +Subject: [PATCH 27/84] arm64: dts: mediatek: mt7988: add switch node + +Add mt7988 builtin mt753x switch nodes. + +Signed-off-by: Daniel Golle +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +--- +v4: +- drop phy-mode for gsw-phy +- reorder phy-mode after phy-handle +- drop interrupt parent from switch + +v2: +- drop labels and led-function too (have to be in board) +--- + arch/arm64/boot/dts/mediatek/mt7988a.dtsi | 148 ++++++++++++++++++++++ + 1 file changed, 148 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi +index 897b5a82b53e..366203a72d6d 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi +@@ -742,6 +742,154 @@ ethsys: clock-controller@15000000 { + #reset-cells = <1>; + }; + ++ switch: switch@15020000 { ++ compatible = "mediatek,mt7988-switch"; ++ reg = <0 0x15020000 0 0x8000>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ interrupts = ; ++ resets = <ðwarp MT7988_ETHWARP_RST_SWITCH>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ gsw_port0: port@0 { ++ reg = <0>; ++ phy-handle = <&gsw_phy0>; ++ phy-mode = "internal"; ++ }; ++ ++ gsw_port1: port@1 { ++ reg = <1>; ++ phy-handle = <&gsw_phy1>; ++ phy-mode = "internal"; ++ }; ++ ++ gsw_port2: port@2 { ++ reg = <2>; ++ phy-handle = <&gsw_phy2>; ++ phy-mode = "internal"; ++ }; ++ ++ gsw_port3: port@3 { ++ reg = <3>; ++ phy-handle = <&gsw_phy3>; ++ phy-mode = "internal"; ++ }; ++ ++ port@6 { ++ reg = <6>; ++ ethernet = <&gmac0>; ++ phy-mode = "internal"; ++ ++ fixed-link { ++ speed = <10000>; ++ full-duplex; ++ pause; ++ }; ++ }; ++ }; ++ ++ mdio { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ mediatek,pio = <&pio>; ++ ++ gsw_phy0: ethernet-phy@0 { ++ compatible = "ethernet-phy-ieee802.3-c22"; ++ reg = <0>; ++ interrupts = <0>; ++ nvmem-cells = <&phy_calibration_p0>; ++ nvmem-cell-names = "phy-cal-data"; ++ ++ leds { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ gsw_phy0_led0: led@0 { ++ reg = <0>; ++ status = "disabled"; ++ }; ++ ++ gsw_phy0_led1: led@1 { ++ reg = <1>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ gsw_phy1: ethernet-phy@1 { ++ compatible = "ethernet-phy-ieee802.3-c22"; ++ reg = <1>; ++ interrupts = <1>; ++ nvmem-cells = <&phy_calibration_p1>; ++ nvmem-cell-names = "phy-cal-data"; ++ ++ leds { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ gsw_phy1_led0: led@0 { ++ reg = <0>; ++ status = "disabled"; ++ }; ++ ++ gsw_phy1_led1: led@1 { ++ reg = <1>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ gsw_phy2: ethernet-phy@2 { ++ compatible = "ethernet-phy-ieee802.3-c22"; ++ reg = <2>; ++ interrupts = <2>; ++ nvmem-cells = <&phy_calibration_p2>; ++ nvmem-cell-names = "phy-cal-data"; ++ ++ leds { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ gsw_phy2_led0: led@0 { ++ reg = <0>; ++ status = "disabled"; ++ }; ++ ++ gsw_phy2_led1: led@1 { ++ reg = <1>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ gsw_phy3: ethernet-phy@3 { ++ compatible = "ethernet-phy-ieee802.3-c22"; ++ reg = <3>; ++ interrupts = <3>; ++ nvmem-cells = <&phy_calibration_p3>; ++ nvmem-cell-names = "phy-cal-data"; ++ ++ leds { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ gsw_phy3_led0: led@0 { ++ reg = <0>; ++ status = "disabled"; ++ }; ++ ++ gsw_phy3_led1: led@1 { ++ reg = <1>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ }; ++ }; ++ + ethwarp: clock-controller@15031000 { + compatible = "mediatek,mt7988-ethwarp"; + reg = <0 0x15031000 0 0x1000>; +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0028-arm64-dts-mediatek-mt7988a-bpi-r4-add-aliases-for-et.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0028-arm64-dts-mediatek-mt7988a-bpi-r4-add-aliases-for-et.patch new file mode 100644 index 0000000000..9522fa9742 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0028-arm64-dts-mediatek-mt7988a-bpi-r4-add-aliases-for-et.patch @@ -0,0 +1,34 @@ +From 27b63d1a7ead4d934e1557bed3ee44f2a8295f61 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Thu, 5 Jun 2025 18:38:51 +0200 +Subject: [PATCH 28/84] arm64: dts: mediatek: mt7988a-bpi-r4: add aliases for + ethernet + +Add aliases for gmacs to allow bootloader setting mac-adresses. + +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +--- + arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi +index 21eb91c8609f..20073eb4d1bd 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi +@@ -8,6 +8,12 @@ + #include "mt7988a.dtsi" + + / { ++ aliases { ++ ethernet0 = &gmac0; ++ ethernet1 = &gmac1; ++ ethernet2 = &gmac2; ++ }; ++ + chosen { + stdout-path = "serial0:115200n8"; + }; +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0029-arm64-dts-mediatek-mt7988a-bpi-r4-add-sfp-cages-and-.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0029-arm64-dts-mediatek-mt7988a-bpi-r4-add-sfp-cages-and-.patch new file mode 100644 index 0000000000..18d9e57d0d --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0029-arm64-dts-mediatek-mt7988a-bpi-r4-add-sfp-cages-and-.patch @@ -0,0 +1,114 @@ +From f4e52f16c979828597c900959d7a955f699903be Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sat, 3 May 2025 11:02:27 +0200 +Subject: [PATCH 29/84] arm64: dts: mediatek: mt7988a-bpi-r4: add sfp cages and + link to gmac + +Add SFP cages to Bananapi-R4 board. The 2.5g phy variant only contains the +wan-SFP, so add this to common dtsi and the lan-sfp only to the dual-SFP +variant. + +Signed-off-by: Daniel Golle +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +--- +v4: +- update 2g5-board (reorder and drop phy-connection-type) +- order sfp properties +v3: +- enable mac with 2.5g phy on r4 phy variant because driver is now mainline +--- + .../mediatek/mt7988a-bananapi-bpi-r4-2g5.dts | 11 +++++++++++ + .../dts/mediatek/mt7988a-bananapi-bpi-r4.dts | 19 +++++++++++++++++++ + .../dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi | 19 +++++++++++++++++++ + 3 files changed, 49 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-2g5.dts b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-2g5.dts +index 53de9c113f60..6f0c81e3fd94 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-2g5.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4-2g5.dts +@@ -9,3 +9,14 @@ / { + model = "Banana Pi BPI-R4 (1x SFP+, 1x 2.5GbE)"; + chassis-type = "embedded"; + }; ++ ++&gmac1 { ++ phy = <&int_2p5g_phy>; ++ phy-mode = "internal"; ++ status = "okay"; ++}; ++ ++&int_2p5g_phy { ++ pinctrl-0 = <&i2p5gbe_led0_pins>; ++ pinctrl-names = "i2p5gbe-led"; ++}; +diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dts b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dts +index 36bd1ef2efab..4b3796ba82e3 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dts +@@ -8,6 +8,25 @@ / { + compatible = "bananapi,bpi-r4", "mediatek,mt7988a"; + model = "Banana Pi BPI-R4 (2x SFP+)"; + chassis-type = "embedded"; ++ ++ /* SFP2 cage (LAN) */ ++ sfp2: sfp2 { ++ compatible = "sff,sfp"; ++ i2c-bus = <&i2c_sfp2>; ++ maximum-power-milliwatt = <3000>; ++ ++ los-gpios = <&pio 2 GPIO_ACTIVE_HIGH>; ++ mod-def0-gpios = <&pio 83 GPIO_ACTIVE_LOW>; ++ rate-select0-gpios = <&pio 3 GPIO_ACTIVE_LOW>; ++ tx-disable-gpios = <&pio 0 GPIO_ACTIVE_HIGH>; ++ tx-fault-gpios = <&pio 1 GPIO_ACTIVE_HIGH>; ++ }; ++}; ++ ++&gmac1 { ++ managed = "in-band-status"; ++ phy-mode = "usxgmii"; ++ sfp = <&sfp2>; + }; + + &pca9545 { +diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi +index 20073eb4d1bd..4d709ee527df 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi +@@ -63,6 +63,19 @@ reg_3p3v: regulator-3p3v { + regulator-boot-on; + regulator-always-on; + }; ++ ++ /* SFP1 cage (WAN) */ ++ sfp1: sfp1 { ++ compatible = "sff,sfp"; ++ i2c-bus = <&i2c_sfp1>; ++ maximum-power-milliwatt = <3000>; ++ ++ los-gpios = <&pio 54 GPIO_ACTIVE_HIGH>; ++ mod-def0-gpios = <&pio 82 GPIO_ACTIVE_LOW>; ++ rate-select0-gpios = <&pio 21 GPIO_ACTIVE_LOW>; ++ tx-disable-gpios = <&pio 70 GPIO_ACTIVE_HIGH>; ++ tx-fault-gpios = <&pio 69 GPIO_ACTIVE_HIGH>; ++ }; + }; + + &cci { +@@ -133,6 +146,12 @@ map-cpu-active-low { + }; + }; + ++&gmac2 { ++ managed = "in-band-status"; ++ phy-mode = "usxgmii"; ++ sfp = <&sfp1>; ++}; ++ + &i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0030-arm64-dts-mediatek-mt7988a-bpi-r4-configure-switch-p.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0030-arm64-dts-mediatek-mt7988a-bpi-r4-configure-switch-p.patch new file mode 100644 index 0000000000..b965813035 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0030-arm64-dts-mediatek-mt7988a-bpi-r4-configure-switch-p.patch @@ -0,0 +1,102 @@ +From 50fb825ca91959e8c00e3d792df1e09c0ef011c1 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sat, 3 May 2025 13:06:40 +0200 +Subject: [PATCH 30/84] arm64: dts: mediatek: mt7988a-bpi-r4: configure switch + phys and leds + +Assign pinctrl to switch phys and leds. + +Signed-off-by: Daniel Golle +Signed-off-by: Frank Wunderlich +Reviewed-by: AngeloGioacchino Del Regno +--- +v4: +- reorder switch phy(-led) properties +v2: +- add labels and led-function and include after dropping from soc dtsi +--- + .../dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi | 61 +++++++++++++++++++ + 1 file changed, 61 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi +index 4d709ee527df..7c9df606f60d 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi +@@ -4,6 +4,7 @@ + + #include + #include ++#include + + #include "mt7988a.dtsi" + +@@ -152,6 +153,66 @@ &gmac2 { + sfp = <&sfp1>; + }; + ++&gsw_phy0 { ++ pinctrl-0 = <&gbe0_led0_pins>; ++ pinctrl-names = "gbe-led"; ++}; ++ ++&gsw_phy0_led0 { ++ function = LED_FUNCTION_WAN; ++ color = ; ++ status = "okay"; ++}; ++ ++&gsw_port0 { ++ label = "wan"; ++}; ++ ++&gsw_phy1 { ++ pinctrl-0 = <&gbe1_led0_pins>; ++ pinctrl-names = "gbe-led"; ++}; ++ ++&gsw_phy1_led0 { ++ function = LED_FUNCTION_LAN; ++ color = ; ++ status = "okay"; ++}; ++ ++&gsw_port1 { ++ label = "lan1"; ++}; ++ ++&gsw_phy2 { ++ pinctrl-0 = <&gbe2_led0_pins>; ++ pinctrl-names = "gbe-led"; ++}; ++ ++&gsw_phy2_led0 { ++ function = LED_FUNCTION_LAN; ++ color = ; ++ status = "okay"; ++}; ++ ++&gsw_port2 { ++ label = "lan2"; ++}; ++ ++&gsw_phy3 { ++ pinctrl-0 = <&gbe3_led0_pins>; ++ pinctrl-names = "gbe-led"; ++}; ++ ++&gsw_phy3_led0 { ++ function = LED_FUNCTION_LAN; ++ color = ; ++ status = "okay"; ++}; ++ ++&gsw_port3 { ++ label = "lan3"; ++}; ++ + &i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0031-arm64-dts-mediatek-mt7988a-bpi-r4-drop-readonly-from.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0031-arm64-dts-mediatek-mt7988a-bpi-r4-drop-readonly-from.patch new file mode 100644 index 0000000000..ab05a8300c --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0031-arm64-dts-mediatek-mt7988a-bpi-r4-drop-readonly-from.patch @@ -0,0 +1,31 @@ +From 060ce20b9896abbb7bd44f9637d78fbfd0ff1f23 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sat, 5 Jul 2025 22:58:15 +0200 +Subject: [PATCH 31/84] arm64: dts: mediatek: mt7988a-bpi-r4: drop readonly + from bl2 partition + +This flag must be removed to allow nand install scripts writing the bl2. + +Fixes: 6b7642e9d095 ("arm64: dts: mediatek: mt7988a-bpi-r4: configure spi-nodes") +Signed-off-by: Frank Wunderlich +--- +v8: new patch +--- + arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi +index 7c9df606f60d..6436263d2328 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi +@@ -448,7 +448,6 @@ partitions { + partition@0 { + label = "bl2"; + reg = <0x0 0x200000>; +- read-only; + }; + }; + }; +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0032-dt-bindings-net-pcs-mediatek-sgmiisys-add-phys-and-r.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0032-dt-bindings-net-pcs-mediatek-sgmiisys-add-phys-and-r.patch new file mode 100644 index 0000000000..58c3c6d24e --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0032-dt-bindings-net-pcs-mediatek-sgmiisys-add-phys-and-r.patch @@ -0,0 +1,52 @@ +From 1d055f70cc1e201be29bbaf05947b2ef1644b259 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Thu, 1 May 2025 21:18:27 +0200 +Subject: [PATCH 32/84] dt-bindings: net: pcs: mediatek,sgmiisys: add phys and + resets + +For mt7988 we need 2 additional properties: + +- phys +- resets + +Signed-off-by: Frank Wunderlich +--- + .../bindings/net/pcs/mediatek,sgmiisys.yaml | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/Documentation/devicetree/bindings/net/pcs/mediatek,sgmiisys.yaml b/Documentation/devicetree/bindings/net/pcs/mediatek,sgmiisys.yaml +index 1bacc0eeff75..ca0f4f4ec765 100644 +--- a/Documentation/devicetree/bindings/net/pcs/mediatek,sgmiisys.yaml ++++ b/Documentation/devicetree/bindings/net/pcs/mediatek,sgmiisys.yaml +@@ -58,6 +58,11 @@ properties: + - const: sgmii_tx + - const: sgmii_rx + ++ phys: ++ $ref: /schemas/types.yaml#/definitions/phandle ++ description: ++ Phandle to the (xfi) phy. ++ + required: + - compatible + - clocks +@@ -65,6 +70,16 @@ properties: + + additionalProperties: false + ++ resets: ++ description: ++ A phandle to reset the sgmiisys controller. ++ items: ++ - items: ++ - description: ++ Phandle to the reset controller ++ - description: ++ value for reset ++ + required: + - compatible + - reg +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0033-dt-binding-sgmiisys-re-add-pcs-cells.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0033-dt-binding-sgmiisys-re-add-pcs-cells.patch new file mode 100644 index 0000000000..586d237bfc --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0033-dt-binding-sgmiisys-re-add-pcs-cells.patch @@ -0,0 +1,26 @@ +From dfcf69513fa1161889f0ae09bd20d00cce92b7af Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Mon, 5 May 2025 19:58:25 +0200 +Subject: [PATCH 33/84] dt-binding: sgmiisys: re-add pcs-cells" + +--- + .../devicetree/bindings/net/pcs/mediatek,sgmiisys.yaml | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/Documentation/devicetree/bindings/net/pcs/mediatek,sgmiisys.yaml b/Documentation/devicetree/bindings/net/pcs/mediatek,sgmiisys.yaml +index ca0f4f4ec765..375c166727c5 100644 +--- a/Documentation/devicetree/bindings/net/pcs/mediatek,sgmiisys.yaml ++++ b/Documentation/devicetree/bindings/net/pcs/mediatek,sgmiisys.yaml +@@ -58,6 +58,9 @@ properties: + - const: sgmii_tx + - const: sgmii_rx + ++ "#pcs-cells": ++ const: 0 ++ + phys: + $ref: /schemas/types.yaml#/definitions/phandle + description: +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0034-dts-re-add-sgmiisys.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0034-dts-re-add-sgmiisys.patch new file mode 100644 index 0000000000..876de17fb9 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0034-dts-re-add-sgmiisys.patch @@ -0,0 +1,61 @@ +From c656470a7109031ebafa95174a0ecd11d251b788 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Mon, 5 May 2025 20:01:00 +0200 +Subject: [PATCH 34/84] dts: re-add sgmiisys + +--- + arch/arm64/boot/dts/mediatek/mt7988a.dtsi | 38 +++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi +index 366203a72d6d..e4833dbdd7af 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi +@@ -277,6 +277,44 @@ pwm: pwm@10048000 { + status = "disabled"; + }; + ++ sgmiisys0: syscon@10060000 { ++ compatible = "mediatek,mt7988-sgmiisys0", ++ "simple-mfd", ++ "syscon"; ++ reg = <0 0x10060000 0 0x1000>; ++ resets = <&watchdog 1>; ++ #clock-cells = <1>; ++ ++ sgmiipcs0: pcs { ++ compatible = "mediatek,mt7988-sgmii"; ++ clocks = <&topckgen CLK_TOP_SGM_0_SEL>, ++ <&sgmiisys0 CLK_SGM0_TX_EN>, ++ <&sgmiisys0 CLK_SGM0_RX_EN>; ++ clock-names = "sgmii_sel", "sgmii_tx", "sgmii_rx"; ++ phys = <&xfi_tphy0>; ++ #pcs-cells = <0>; ++ }; ++ }; ++ ++ sgmiisys1: syscon@10070000 { ++ compatible = "mediatek,mt7988-sgmiisys1", ++ "simple-mfd", ++ "syscon"; ++ reg = <0 0x10070000 0 0x1000>; ++ resets = <&watchdog 2>; ++ #clock-cells = <1>; ++ ++ sgmiipcs1: pcs { ++ compatible = "mediatek,mt7988-sgmii"; ++ clocks = <&topckgen CLK_TOP_SGM_1_SEL>, ++ <&sgmiisys1 CLK_SGM1_TX_EN>, ++ <&sgmiisys1 CLK_SGM1_RX_EN>; ++ clock-names = "sgmii_sel", "sgmii_tx", "sgmii_rx"; ++ phys = <&xfi_tphy1>; ++ #pcs-cells = <0>; ++ }; ++ }; ++ + mcusys: mcusys@100e0000 { + compatible = "mediatek,mt7988-mcusys", "syscon"; + reg = <0 0x100e0000 0 0x1000>; +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0035-arm64-dts-mt7988-add-cpufreq-calibration-efuse-subno.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0035-arm64-dts-mt7988-add-cpufreq-calibration-efuse-subno.patch new file mode 100644 index 0000000000..61e800ef4c --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0035-arm64-dts-mt7988-add-cpufreq-calibration-efuse-subno.patch @@ -0,0 +1,27 @@ +From eeeadc20f05134123868769f8def2ce1ab0933ec Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Fri, 2 May 2025 12:29:54 +0200 +Subject: [PATCH 35/84] arm64: dts: mt7988: add cpufreq calibration efuse + subnode + +--- + arch/arm64/boot/dts/mediatek/mt7988a.dtsi | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi +index e4833dbdd7af..88f201ad78cf 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi +@@ -752,6 +752,9 @@ efuse@11f50000 { + #address-cells = <1>; + #size-cells = <1>; + ++ cpufreq_calibration: calib@278 { ++ reg = <0x278 0x1>; ++ }; + lvts_calibration: calib@918 { + reg = <0x918 0x28>; + }; +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0036-net-ethernet-mtk_eth_soc-move-desc-assignment-below-.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0036-net-ethernet-mtk_eth_soc-move-desc-assignment-below-.patch new file mode 100644 index 0000000000..3ef28ddd56 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0036-net-ethernet-mtk_eth_soc-move-desc-assignment-below-.patch @@ -0,0 +1,39 @@ +From 682eb678991b3dde629df9178e7e088bbe4b7039 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Wed, 26 Mar 2025 19:44:18 +0100 +Subject: [PATCH 36/84] net: ethernet: mtk_eth_soc: move desc assignment below + check for its txd3 + +The field desc->txd3 should be checked for TX_DMA_OWNER_CPU flag before +assign a new desc. + +old MTK-SDK uses same order: +https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/refs/heads/master/21.02/files/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c#2895 +new SDK seems not changing it. + +Fixes: 656e705243fd ("net-next: mediatek: add support for MT7623 ethernet") +Signed-off-by: Frank Wunderlich +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index 9333f2b8e1d6..5b201c0214a0 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -2439,10 +2439,11 @@ static int mtk_poll_tx_qdma(struct mtk_eth *eth, int budget, + while ((cpu != dma) && budget) { + u32 next_cpu = desc->txd2; + +- desc = mtk_qdma_phys_to_virt(ring, desc->txd2); + if ((desc->txd3 & TX_DMA_OWNER_CPU) == 0) + break; + ++ desc = mtk_qdma_phys_to_virt(ring, desc->txd2); ++ + tx_buf = mtk_desc_to_tx_buf(ring, desc, + eth->soc->tx.desc_size); + if (!tx_buf->data) +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0037-dts-enable-mt818-36-for-cci-testing.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0037-dts-enable-mt818-36-for-cci-testing.patch new file mode 100644 index 0000000000..dd6dbed678 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0037-dts-enable-mt818-36-for-cci-testing.patch @@ -0,0 +1,121 @@ +From b5d5dcd4cbbed8369b58ee562cc7717c39496c48 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sat, 31 May 2025 13:09:24 +0200 +Subject: [PATCH 37/84] dts: enable mt818[36] for cci testing + +--- + arch/arm64/boot/dts/mediatek/Makefile | 98 +++++++++++++-------------- + 1 file changed, 49 insertions(+), 49 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile +index e60462fa2b6f..87608df68fab 100644 +--- a/arch/arm64/boot/dts/mediatek/Makefile ++++ b/arch/arm64/boot/dts/mediatek/Makefile +@@ -30,55 +30,55 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-sd.dtbo + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-elm-hana.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-elm-hana-rev7.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-evb.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-evb.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-burnet.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-cozmo.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-damu.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel-sku1.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel-sku6.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel-sku7.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel14.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel14-sku2.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-juniper-sku16.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-kappa.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-kenzo.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-makomo-sku0.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-makomo-sku1.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-pico.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-pico6.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-willow-sku0.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-willow-sku1.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kakadu.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kakadu-sku22.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-katsu-sku32.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-katsu-sku38.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku16.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku272.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku288.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku32.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-krane-sku0.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-krane-sku176.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-pumpkin.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-chinchou-sku0.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-chinchou-sku1.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-chinchou-sku16.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-magneton-sku393216.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-magneton-sku393217.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-magneton-sku393218.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-ponyta-sku0.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-ponyta-sku1.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-rusty-sku196608.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-starmie-sku0.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-starmie-sku1.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-steelix-sku131072.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-steelix-sku131073.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacool-sku327681.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacool-sku327683.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacruel-sku262144.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacruel-sku262148.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-voltorb-sku589824.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-voltorb-sku589825.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-evb.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-evb.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-burnet.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-cozmo.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-damu.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel-sku1.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel-sku6.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel-sku7.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel14.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel14-sku2.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-juniper-sku16.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-kappa.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-kenzo.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-makomo-sku0.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-makomo-sku1.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-pico.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-pico6.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-willow-sku0.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-willow-sku1.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kakadu.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kakadu-sku22.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-katsu-sku32.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-katsu-sku38.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku16.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku272.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku288.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku32.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-krane-sku0.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-krane-sku176.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-pumpkin.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-chinchou-sku0.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-chinchou-sku1.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-chinchou-sku16.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-magneton-sku393216.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-magneton-sku393217.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-magneton-sku393218.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-ponyta-sku0.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-ponyta-sku1.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-rusty-sku196608.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-starmie-sku0.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-starmie-sku1.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-steelix-sku131072.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-steelix-sku131073.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacool-sku327681.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacool-sku327683.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacruel-sku262144.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacruel-sku262148.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-voltorb-sku589824.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-voltorb-sku589825.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-evb.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-evb.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-geralt-ciri-sku0.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-geralt-ciri-sku1.dtb +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0038-Revert-dts-enable-mt818-36-for-cci-testing.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0038-Revert-dts-enable-mt818-36-for-cci-testing.patch new file mode 100644 index 0000000000..91ddabbdda --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0038-Revert-dts-enable-mt818-36-for-cci-testing.patch @@ -0,0 +1,122 @@ +From bac17b5f648913aef5ff8b2559631dffbed56ab8 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Wed, 4 Jun 2025 22:33:49 +0200 +Subject: [PATCH 38/84] Revert "dts: enable mt818[36] for cci testing" + +This reverts commit 1e0327fc048d602fbc85ce160202bbe998a62cb0. +--- + arch/arm64/boot/dts/mediatek/Makefile | 98 +++++++++++++-------------- + 1 file changed, 49 insertions(+), 49 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile +index 87608df68fab..e60462fa2b6f 100644 +--- a/arch/arm64/boot/dts/mediatek/Makefile ++++ b/arch/arm64/boot/dts/mediatek/Makefile +@@ -30,55 +30,55 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-sd.dtbo + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-elm-hana.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-elm-hana-rev7.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-evb.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-evb.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-burnet.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-cozmo.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-damu.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel-sku1.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel-sku6.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel-sku7.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel14.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel14-sku2.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-juniper-sku16.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-kappa.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-kenzo.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-makomo-sku0.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-makomo-sku1.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-pico.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-pico6.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-willow-sku0.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-willow-sku1.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kakadu.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kakadu-sku22.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-katsu-sku32.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-katsu-sku38.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku16.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku272.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku288.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku32.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-krane-sku0.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-krane-sku176.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-pumpkin.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-chinchou-sku0.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-chinchou-sku1.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-chinchou-sku16.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-magneton-sku393216.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-magneton-sku393217.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-magneton-sku393218.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-ponyta-sku0.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-ponyta-sku1.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-rusty-sku196608.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-starmie-sku0.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-starmie-sku1.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-steelix-sku131072.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-steelix-sku131073.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacool-sku327681.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacool-sku327683.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacruel-sku262144.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacruel-sku262148.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-voltorb-sku589824.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-voltorb-sku589825.dtb +-dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-evb.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-evb.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-burnet.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-cozmo.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-damu.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel-sku1.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel-sku6.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel-sku7.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel14.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-fennel14-sku2.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-juniper-sku16.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-kappa.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-kenzo.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-makomo-sku0.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-makomo-sku1.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-pico.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-pico6.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-willow-sku0.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-willow-sku1.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kakadu.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kakadu-sku22.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-katsu-sku32.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-katsu-sku38.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku16.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku272.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku288.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-kodama-sku32.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-krane-sku0.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-krane-sku176.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-pumpkin.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-chinchou-sku0.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-chinchou-sku1.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-chinchou-sku16.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-magneton-sku393216.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-magneton-sku393217.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-magneton-sku393218.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-ponyta-sku0.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-ponyta-sku1.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-rusty-sku196608.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-starmie-sku0.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-starmie-sku1.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-steelix-sku131072.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-steelix-sku131073.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacool-sku327681.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacool-sku327683.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacruel-sku262144.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-tentacruel-sku262148.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-voltorb-sku589824.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-corsola-voltorb-sku589825.dtb ++#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8186-evb.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-evb.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-geralt-ciri-sku0.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt8188-geralt-ciri-sku1.dtb +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0039-enable-bpi-r3-DTBs-for-testing.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0039-enable-bpi-r3-DTBs-for-testing.patch new file mode 100644 index 0000000000..8c3fa18b18 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0039-enable-bpi-r3-DTBs-for-testing.patch @@ -0,0 +1,37 @@ +From b012720e24c54270538cdb6808f895791084da49 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sun, 15 Jun 2025 16:49:01 +0200 +Subject: [PATCH 39/84] enable bpi-r3 DTBs for testing + +--- + arch/arm64/boot/dts/mediatek/Makefile | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile +index e60462fa2b6f..d4f56f8e8463 100644 +--- a/arch/arm64/boot/dts/mediatek/Makefile ++++ b/arch/arm64/boot/dts/mediatek/Makefile +@@ -12,13 +12,13 @@ + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt7981b-openwrt-one.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt7981b-xiaomi-ax3000t.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-acelink-ew-7886cax.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-mini.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-emmc.dtbo +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-nand.dtbo +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-nor.dtbo +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-sata.dtbo +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-sd.dtbo ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-mini.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-emmc.dtbo ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-nand.dtbo ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-nor.dtbo ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-sata.dtbo ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-bananapi-bpi-r3-sd.dtbo + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986a-rfb.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt7986b-rfb.dtb + dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4.dtb +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0040-only-enable-mediatek-for-arm-to-increase-dtbs_check.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0040-only-enable-mediatek-for-arm-to-increase-dtbs_check.patch new file mode 100644 index 0000000000..cfa1803532 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0040-only-enable-mediatek-for-arm-to-increase-dtbs_check.patch @@ -0,0 +1,97 @@ +From 606aeff7dcc0f97ace6cb54e8098b9ca72a30c32 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Mon, 23 Jun 2025 22:17:54 +0200 +Subject: [PATCH 40/84] only enable mediatek for arm to increase dtbs_check + +--- + arch/arm/boot/dts/Makefile | 78 +++++++++++++++++++------------------- + 1 file changed, 39 insertions(+), 39 deletions(-) + +diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +index efe38eb25301..8afa52394d6d 100644 +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -1,41 +1,41 @@ + # SPDX-License-Identifier: GPL-2.0 +-subdir-y += actions +-subdir-y += airoha +-subdir-y += allwinner +-subdir-y += alphascale +-subdir-y += amazon +-subdir-y += amlogic +-subdir-y += arm +-subdir-y += aspeed +-subdir-y += axis +-subdir-y += broadcom +-subdir-y += calxeda +-subdir-y += cirrus +-subdir-y += cnxt +-subdir-y += gemini +-subdir-y += hisilicon +-subdir-y += hpe +-subdir-y += intel +-subdir-y += marvell ++#subdir-y += actions ++#subdir-y += airoha ++#subdir-y += allwinner ++#subdir-y += alphascale ++#subdir-y += amazon ++#subdir-y += amlogic ++#subdir-y += arm ++#subdir-y += aspeed ++#subdir-y += axis ++#subdir-y += broadcom ++#subdir-y += calxeda ++#subdir-y += cirrus ++#subdir-y += cnxt ++#subdir-y += gemini ++#subdir-y += hisilicon ++#subdir-y += hpe ++#subdir-y += intel ++#subdir-y += marvell + subdir-y += mediatek +-subdir-y += microchip +-subdir-y += moxa +-subdir-y += nspire +-subdir-y += nuvoton +-subdir-y += nvidia +-subdir-y += nxp +-subdir-y += qcom +-subdir-y += realtek +-subdir-y += renesas +-subdir-y += rockchip +-subdir-y += samsung +-subdir-y += sigmastar +-subdir-y += socionext +-subdir-y += st +-subdir-y += sunplus +-subdir-y += synaptics +-subdir-y += ti +-subdir-y += unisoc +-subdir-y += vt8500 +-subdir-y += xen +-subdir-y += xilinx ++#subdir-y += microchip ++#subdir-y += moxa ++#subdir-y += nspire ++#subdir-y += nuvoton ++#subdir-y += nvidia ++#subdir-y += nxp ++#subdir-y += qcom ++#subdir-y += realtek ++#subdir-y += renesas ++#subdir-y += rockchip ++#subdir-y += samsung ++#subdir-y += sigmastar ++#subdir-y += socionext ++#subdir-y += st ++#subdir-y += sunplus ++#subdir-y += synaptics ++#subdir-y += ti ++#subdir-y += unisoc ++#subdir-y += vt8500 ++#subdir-y += xen ++#subdir-y += xilinx +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0041-enable-some-arm64-dts-to-check-binding.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0041-enable-some-arm64-dts-to-check-binding.patch new file mode 100644 index 0000000000..7095998831 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0041-enable-some-arm64-dts-to-check-binding.patch @@ -0,0 +1,41 @@ +From f66d885af3510cd9fbe765354bea75955b791b95 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Mon, 23 Jun 2025 22:18:41 +0200 +Subject: [PATCH 41/84] enable some arm64 dts to check binding + +--- + arch/arm64/boot/dts/mediatek/Makefile | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile +index d4f56f8e8463..d728953c10ad 100644 +--- a/arch/arm64/boot/dts/mediatek/Makefile ++++ b/arch/arm64/boot/dts/mediatek/Makefile +@@ -7,7 +7,7 @@ + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-evb.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-x20-dev.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-rfb1.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-bananapi-bpi-r64.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-bananapi-bpi-r64.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt7981b-cudy-wr3000-v1.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt7981b-openwrt-one.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt7981b-xiaomi-ax3000t.dtb +@@ -25,12 +25,12 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4.dtb + dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-2g5.dtb + dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-emmc.dtbo + dtb-$(CONFIG_ARCH_MEDIATEK) += mt7988a-bananapi-bpi-r4-sd.dtbo +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8167-pumpkin.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-elm.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8167-pumpkin.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-elm.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-elm-hana.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-elm-hana-rev7.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-evb.dtb +-#dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-evb.dtb ++dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-evb.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-burnet.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-cozmo.dtb + #dtb-$(CONFIG_ARCH_MEDIATEK) += mt8183-kukui-jacuzzi-damu.dtb +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0042-defconfig-r4-add-sram-driver.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0042-defconfig-r4-add-sram-driver.patch new file mode 100644 index 0000000000..077439e3a0 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0042-defconfig-r4-add-sram-driver.patch @@ -0,0 +1,25 @@ +From ba3dd9a702c9ba546f569fdd0da5e3dc0e533b8d Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Wed, 25 Jun 2025 21:08:16 +0200 +Subject: [PATCH 42/84] defconfig: r4: add sram driver + +--- + arch/arm64/configs/mt7988a_bpi-r4_defconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/configs/mt7988a_bpi-r4_defconfig b/arch/arm64/configs/mt7988a_bpi-r4_defconfig +index 69de56a20462..29bc60ce564f 100644 +--- a/arch/arm64/configs/mt7988a_bpi-r4_defconfig ++++ b/arch/arm64/configs/mt7988a_bpi-r4_defconfig +@@ -1274,7 +1274,7 @@ CONFIG_SECCOMP=y + + CONFIG_I2C_MUX=y + CONFIG_I2C_MUX_PCA954x=y +- ++CONFIG_SRAM=y + CONFIG_PCS_MTK_USXGMII=y + + CONFIG_MT7915E=m +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0043-net-ethernet-mtk_eth_soc-improve-support-for-named-i.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0043-net-ethernet-mtk_eth_soc-improve-support-for-named-i.patch new file mode 100644 index 0000000000..5e435f7420 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0043-net-ethernet-mtk_eth_soc-improve-support-for-named-i.patch @@ -0,0 +1,52 @@ +From 67cbba9936c2fabc97392f3ac67ffd289a205c2f Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Wed, 2 Jul 2025 14:14:29 +0100 +Subject: [PATCH 43/84] net: ethernet: mtk_eth_soc: improve support for named + interrupts + +Use platform_get_irq_byname_optional() to avoid outputting error +messages when using legacy device trees which rely identifying +interrupts only by index. Instead, output a warning notifying the user +to update their device tree. + +Signed-off-by: Daniel Golle +Reviewed-by: Andrew Lunn +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index 5b201c0214a0..a119094645e4 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3350,17 +3350,22 @@ static int mtk_get_irqs(struct platform_device *pdev, struct mtk_eth *eth) + int i; + + /* future SoCs beginning with MT7988 should use named IRQs in dts */ +- eth->irq[MTK_FE_IRQ_TX] = platform_get_irq_byname(pdev, "fe1"); +- eth->irq[MTK_FE_IRQ_RX] = platform_get_irq_byname(pdev, "fe2"); ++ eth->irq[MTK_FE_IRQ_TX] = platform_get_irq_byname_optional(pdev, "fe1"); ++ eth->irq[MTK_FE_IRQ_RX] = platform_get_irq_byname_optional(pdev, "fe2"); + if (eth->irq[MTK_FE_IRQ_TX] >= 0 && eth->irq[MTK_FE_IRQ_RX] >= 0) + return 0; + +- /* only use legacy mode if platform_get_irq_byname returned -ENXIO */ ++ /* only use legacy mode if platform_get_irq_byname_optional returned -ENXIO */ + if (eth->irq[MTK_FE_IRQ_TX] != -ENXIO) +- return eth->irq[MTK_FE_IRQ_TX]; ++ return dev_err_probe(&pdev->dev, eth->irq[MTK_FE_IRQ_TX], ++ "Error requesting FE TX IRQ\n"); + + if (eth->irq[MTK_FE_IRQ_RX] != -ENXIO) +- return eth->irq[MTK_FE_IRQ_RX]; ++ return dev_err_probe(&pdev->dev, eth->irq[MTK_FE_IRQ_RX], ++ "Error requesting FE RX IRQ\n"); ++ ++ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) ++ dev_warn(&pdev->dev, "legacy DT: missing interrupt-names."); + + /* legacy way: + * On MTK_SHARED_INT SoCs (MT7621 + MT7628) the first IRQ is taken +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0044-net-ethernet-mtk_eth_soc-fix-kernel-doc-comment.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0044-net-ethernet-mtk_eth_soc-fix-kernel-doc-comment.patch new file mode 100644 index 0000000000..23eb7b60c0 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0044-net-ethernet-mtk_eth_soc-fix-kernel-doc-comment.patch @@ -0,0 +1,32 @@ +From 5a3c93c4023f57befd6cf590088e6095b70a001f Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Wed, 2 Jul 2025 14:14:39 +0100 +Subject: [PATCH 44/84] net: ethernet: mtk_eth_soc: fix kernel-doc comment + +Fix and add some missing field descriptions to kernel-doc comment of +struct mtk_eth. + +Signed-off-by: Daniel Golle +Reviewed-by: Andrew Lunn +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +index 9261c0e13b59..1ad9075a9b69 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -1243,8 +1243,9 @@ struct mtk_soc_data { + /* struct mtk_eth - This is the main datasructure for holding the state + * of the driver + * @dev: The device pointer +- * @dev: The device pointer used for dma mapping/alloc ++ * @dma_dev: The device pointer used for dma mapping/alloc + * @base: The mapped register i/o base ++ * @sram_base: The mapped SRAM base + * @page_lock: Make sure that register operations are atomic + * @tx_irq__lock: Make sure that IRQ register operations are atomic + * @rx_irq__lock: Make sure that IRQ register operations are atomic +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0045-net-ethernet-mtk_eth_soc-use-generic-allocator-for-S.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0045-net-ethernet-mtk_eth_soc-use-generic-allocator-for-S.patch new file mode 100644 index 0000000000..e00f572142 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0045-net-ethernet-mtk_eth_soc-use-generic-allocator-for-S.patch @@ -0,0 +1,324 @@ +From 4ba463a09585baacc97b544c939f379a4d784e5b Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Wed, 2 Jul 2025 14:14:56 +0100 +Subject: [PATCH 45/84] net: ethernet: mtk_eth_soc: use generic allocator for + SRAM + +Use a dedicated "mmio-sram" node and the generic allocator +instead of open-coding SRAM allocation for DMA rings. +Keep support for legacy device trees but notify the user via a +warning to update, and let the ethernet driver create the +gen_pool in this case. + +Co-developed-by: Frank Wunderlich +Signed-off-by: Frank Wunderlich +Signed-off-by: Daniel Golle +Reviewed-by: Andrew Lunn +--- + drivers/net/ethernet/mediatek/Kconfig | 1 + + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 152 +++++++++++--------- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 10 +- + 3 files changed, 90 insertions(+), 73 deletions(-) + +diff --git a/drivers/net/ethernet/mediatek/Kconfig b/drivers/net/ethernet/mediatek/Kconfig +index 7bfd3f230ff5..2ba361f8ce7d 100644 +--- a/drivers/net/ethernet/mediatek/Kconfig ++++ b/drivers/net/ethernet/mediatek/Kconfig +@@ -17,6 +17,7 @@ config NET_MEDIATEK_SOC + select PINCTRL + select PHYLINK + select DIMLIB ++ select GENERIC_ALLOCATOR + select PAGE_POOL + select PAGE_POOL_STATS + select PCS_MTK_LYNXI +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index a119094645e4..7916c99d5ebb 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + #include "mtk_eth_soc.h" + #include "mtk_wed.h" +@@ -1267,6 +1268,34 @@ static void *mtk_max_lro_buf_alloc(gfp_t gfp_mask) + return (void *)data; + } + ++static void *mtk_dma_ring_alloc(struct mtk_eth *eth, size_t size, ++ dma_addr_t *dma_handle, bool use_sram) ++{ ++ void *dma_ring; ++ ++ if (use_sram && eth->sram_pool) { ++ dma_ring = (void *)gen_pool_alloc(eth->sram_pool, size); ++ if (!dma_ring) ++ return dma_ring; ++ *dma_handle = gen_pool_virt_to_phys(eth->sram_pool, ++ (unsigned long)dma_ring); ++ } else { ++ dma_ring = dma_alloc_coherent(eth->dma_dev, size, dma_handle, ++ GFP_KERNEL); ++ } ++ ++ return dma_ring; ++} ++ ++static void mtk_dma_ring_free(struct mtk_eth *eth, size_t size, void *dma_ring, ++ dma_addr_t dma_handle, bool in_sram) ++{ ++ if (in_sram && eth->sram_pool) ++ gen_pool_free(eth->sram_pool, (unsigned long)dma_ring, size); ++ else ++ dma_free_coherent(eth->dma_dev, size, dma_ring, dma_handle); ++} ++ + /* the qdma core needs scratch memory to be setup */ + static int mtk_init_fq_dma(struct mtk_eth *eth) + { +@@ -1276,13 +1305,8 @@ static int mtk_init_fq_dma(struct mtk_eth *eth) + dma_addr_t dma_addr; + int i, j, len; + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM)) +- eth->scratch_ring = eth->sram_base; +- else +- eth->scratch_ring = dma_alloc_coherent(eth->dma_dev, +- cnt * soc->tx.desc_size, +- ð->phy_scratch_ring, +- GFP_KERNEL); ++ eth->scratch_ring = mtk_dma_ring_alloc(eth, cnt * soc->tx.desc_size, ++ ð->phy_scratch_ring, true); + + if (unlikely(!eth->scratch_ring)) + return -ENOMEM; +@@ -2629,14 +2653,7 @@ static int mtk_tx_alloc(struct mtk_eth *eth) + if (!ring->buf) + goto no_tx_mem; + +- if (MTK_HAS_CAPS(soc->caps, MTK_SRAM)) { +- ring->dma = eth->sram_base + soc->tx.fq_dma_size * sz; +- ring->phys = eth->phy_scratch_ring + soc->tx.fq_dma_size * (dma_addr_t)sz; +- } else { +- ring->dma = dma_alloc_coherent(eth->dma_dev, ring_size * sz, +- &ring->phys, GFP_KERNEL); +- } +- ++ ring->dma = mtk_dma_ring_alloc(eth, ring_size * sz, &ring->phys, true); + if (!ring->dma) + goto no_tx_mem; + +@@ -2735,10 +2752,10 @@ static void mtk_tx_clean(struct mtk_eth *eth) + kfree(ring->buf); + ring->buf = NULL; + } +- if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && ring->dma) { +- dma_free_coherent(eth->dma_dev, +- ring->dma_size * soc->tx.desc_size, +- ring->dma, ring->phys); ++ ++ if (ring->dma) { ++ mtk_dma_ring_free(eth, ring->dma_size * soc->tx.desc_size, ++ ring->dma, ring->phys, true); + ring->dma = NULL; + } + +@@ -2755,14 +2772,9 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag) + const struct mtk_reg_map *reg_map = eth->soc->reg_map; + const struct mtk_soc_data *soc = eth->soc; + struct mtk_rx_ring *ring; +- int rx_data_len, rx_dma_size, tx_ring_size; ++ int rx_data_len, rx_dma_size; + int i; + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) +- tx_ring_size = MTK_QDMA_RING_SIZE; +- else +- tx_ring_size = soc->tx.dma_size; +- + if (rx_flag == MTK_RX_FLAGS_QDMA) { + if (ring_no) + return -EINVAL; +@@ -2797,20 +2809,10 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag) + ring->page_pool = pp; + } + +- if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM) || +- rx_flag != MTK_RX_FLAGS_NORMAL) { +- ring->dma = dma_alloc_coherent(eth->dma_dev, +- rx_dma_size * eth->soc->rx.desc_size, +- &ring->phys, GFP_KERNEL); +- } else { +- struct mtk_tx_ring *tx_ring = ð->tx_ring; +- +- ring->dma = tx_ring->dma + tx_ring_size * +- eth->soc->tx.desc_size * (ring_no + 1); +- ring->phys = tx_ring->phys + tx_ring_size * +- eth->soc->tx.desc_size * (ring_no + 1); +- } +- ++ ring->dma = mtk_dma_ring_alloc(eth, ++ rx_dma_size * eth->soc->rx.desc_size, ++ &ring->phys, ++ rx_flag == MTK_RX_FLAGS_NORMAL); + if (!ring->dma) + return -ENOMEM; + +@@ -2925,10 +2927,9 @@ static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, bool in_ + ring->data = NULL; + } + +- if (!in_sram && ring->dma) { +- dma_free_coherent(eth->dma_dev, +- ring->dma_size * eth->soc->rx.desc_size, +- ring->dma, ring->phys); ++ if (ring->dma) { ++ mtk_dma_ring_free(eth, ring->dma_size * eth->soc->rx.desc_size, ++ ring->dma, ring->phys, in_sram); + ring->dma = NULL; + } + +@@ -3296,15 +3297,16 @@ static void mtk_dma_free(struct mtk_eth *eth) + netdev_tx_reset_subqueue(eth->netdev[i], j); + } + +- if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && eth->scratch_ring) { +- dma_free_coherent(eth->dma_dev, +- MTK_QDMA_RING_SIZE * soc->tx.desc_size, +- eth->scratch_ring, eth->phy_scratch_ring); ++ if (eth->scratch_ring) { ++ mtk_dma_ring_free(eth, soc->tx.fq_dma_size * soc->tx.desc_size, ++ eth->scratch_ring, eth->phy_scratch_ring, ++ true); + eth->scratch_ring = NULL; + eth->phy_scratch_ring = 0; + } ++ + mtk_tx_clean(eth); +- mtk_rx_clean(eth, ð->rx_ring[0], MTK_HAS_CAPS(soc->caps, MTK_SRAM)); ++ mtk_rx_clean(eth, ð->rx_ring[0], true); + mtk_rx_clean(eth, ð->rx_ring_qdma, false); + + if (eth->hwlro) { +@@ -5016,9 +5018,30 @@ static int mtk_sgmii_init(struct mtk_eth *eth) + return 0; + } + ++static int mtk_setup_legacy_sram(struct mtk_eth *eth, struct resource *res) ++{ ++ dev_warn(eth->dev, "legacy DT: using hard-coded SRAM offset.\n"); ++ ++ if (res->start + MTK_ETH_SRAM_OFFSET + MTK_ETH_NETSYS_V2_SRAM_SIZE - 1 > ++ res->end) ++ return -EINVAL; ++ ++ eth->sram_pool = devm_gen_pool_create(eth->dev, ++ const_ilog2(MTK_ETH_SRAM_GRANULARITY), ++ NUMA_NO_NODE, dev_name(eth->dev)); ++ ++ if (IS_ERR(eth->sram_pool)) ++ return PTR_ERR(eth->sram_pool); ++ ++ return gen_pool_add_virt(eth->sram_pool, ++ (unsigned long)eth->base + MTK_ETH_SRAM_OFFSET, ++ res->start + MTK_ETH_SRAM_OFFSET, ++ MTK_ETH_NETSYS_V2_SRAM_SIZE, NUMA_NO_NODE); ++} ++ + static int mtk_probe(struct platform_device *pdev) + { +- struct resource *res = NULL, *res_sram; ++ struct resource *res = NULL; + struct device_node *mac_np; + struct mtk_eth *eth; + int err, i; +@@ -5038,20 +5061,6 @@ static int mtk_probe(struct platform_device *pdev) + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) + eth->ip_align = NET_IP_ALIGN; + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM)) { +- /* SRAM is actual memory and supports transparent access just like DRAM. +- * Hence we don't require __iomem being set and don't need to use accessor +- * functions to read from or write to SRAM. +- */ +- if (mtk_is_netsys_v3_or_greater(eth)) { +- eth->sram_base = (void __force *)devm_platform_ioremap_resource(pdev, 1); +- if (IS_ERR(eth->sram_base)) +- return PTR_ERR(eth->sram_base); +- } else { +- eth->sram_base = (void __force *)eth->base + MTK_ETH_SRAM_OFFSET; +- } +- } +- + if (MTK_HAS_CAPS(eth->soc->caps, MTK_36BIT_DMA)) { + err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(36)); + if (!err) +@@ -5126,16 +5135,21 @@ static int mtk_probe(struct platform_device *pdev) + err = -EINVAL; + goto err_destroy_sgmii; + } ++ + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM)) { +- if (mtk_is_netsys_v3_or_greater(eth)) { +- res_sram = platform_get_resource(pdev, IORESOURCE_MEM, 1); +- if (!res_sram) { ++ eth->sram_pool = of_gen_pool_get(pdev->dev.of_node, ++ "sram", 0); ++ if (!eth->sram_pool) { ++ if (!mtk_is_netsys_v3_or_greater(eth)) { ++ err = mtk_setup_legacy_sram(eth, res); ++ if (err) ++ goto err_destroy_sgmii; ++ } else { ++ dev_err(&pdev->dev, ++ "Could not get SRAM pool\n"); + err = -EINVAL; + goto err_destroy_sgmii; + } +- eth->phy_scratch_ring = res_sram->start; +- } else { +- eth->phy_scratch_ring = res->start + MTK_ETH_SRAM_OFFSET; + } + } + } +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +index 1ad9075a9b69..0168e2fbc619 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -141,8 +141,10 @@ + #define MTK_GDMA_MAC_ADRH(x) ({ typeof(x) _x = (x); (_x == MTK_GMAC3_ID) ? \ + 0x54C : 0x50C + (_x * 0x1000); }) + +-/* Internal SRAM offset */ +-#define MTK_ETH_SRAM_OFFSET 0x40000 ++/* legacy DT support for internal SRAM */ ++#define MTK_ETH_SRAM_OFFSET 0x40000 ++#define MTK_ETH_SRAM_GRANULARITY 32 ++#define MTK_ETH_NETSYS_V2_SRAM_SIZE 0x40000 + + /* FE global misc reg*/ + #define MTK_FE_GLO_MISC 0x124 +@@ -1245,7 +1247,7 @@ struct mtk_soc_data { + * @dev: The device pointer + * @dma_dev: The device pointer used for dma mapping/alloc + * @base: The mapped register i/o base +- * @sram_base: The mapped SRAM base ++ * @sram_pool: Pointer to SRAM pool used for DMA descriptor rings + * @page_lock: Make sure that register operations are atomic + * @tx_irq__lock: Make sure that IRQ register operations are atomic + * @rx_irq__lock: Make sure that IRQ register operations are atomic +@@ -1291,7 +1293,7 @@ struct mtk_eth { + struct device *dev; + struct device *dma_dev; + void __iomem *base; +- void *sram_base; ++ struct gen_pool *sram_pool; + spinlock_t page_lock; + spinlock_t tx_irq_lock; + spinlock_t rx_irq_lock; +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0046-defconfig-r3-add-sram.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0046-defconfig-r3-add-sram.patch new file mode 100644 index 0000000000..1594de5650 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0046-defconfig-r3-add-sram.patch @@ -0,0 +1,21 @@ +From 00ef5d4e0a6d6e118b03706c3e2bae2bf9a906a6 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Fri, 27 Jun 2025 22:58:49 +0200 +Subject: [PATCH 46/84] defconfig: r3: add sram + +--- + arch/arm64/configs/mt7986a_bpi-r3_defconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm64/configs/mt7986a_bpi-r3_defconfig b/arch/arm64/configs/mt7986a_bpi-r3_defconfig +index 32710280133d..29421f5f3e1f 100644 +--- a/arch/arm64/configs/mt7986a_bpi-r3_defconfig ++++ b/arch/arm64/configs/mt7986a_bpi-r3_defconfig +@@ -1263,3 +1263,4 @@ CONFIG_EXTRA_FIRMWARE="airoha/EthMD32.dm.bin airoha/EthMD32.DSP.bin" + CONFIG_EXTRA_FIRMWARE_DIR="utils/firmware/" + + CONFIG_PANIC_TIMEOUT=30 ++CONFIG_SRAM=y +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0047-WIP-dts64-r4-add-ubi-partition-to-spin-nand.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0047-WIP-dts64-r4-add-ubi-partition-to-spin-nand.patch new file mode 100644 index 0000000000..9118fa811c --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0047-WIP-dts64-r4-add-ubi-partition-to-spin-nand.patch @@ -0,0 +1,53 @@ +From b452c304864e95f043e8ea2cd5696fbd98bf0041 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Fri, 4 Jul 2025 19:51:42 +0200 +Subject: [PATCH 47/84] WIP: dts64: r4: add ubi partition to spin nand + +--- + .../dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi | 30 +++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi +index 6436263d2328..38e27ef6bc0c 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi +@@ -449,6 +449,36 @@ partition@0 { + label = "bl2"; + reg = <0x0 0x200000>; + }; ++ ++ partition@200000 { ++ label = "ubi"; ++ reg = <0x200000 0x7e00000>; ++ compatible = "linux,ubi"; ++ ++ /*volumes { ++ ubi-volume-fip { ++ volname = "fip"; ++ }; ++ ++ ubi-volume-ubootenv { ++ volname = "ubootenv"; ++ nvmem-layout { ++ compatible = "u-boot,env-redundant-bool-layout"; ++ }; ++ }; ++ ++ ubi-volume-ubootenv2 { ++ volname = "ubootenv2"; ++ nvmem-layout { ++ compatible = "u-boot,env-redundant-bool-layout"; ++ }; ++ }; ++ ++ ubi_rootfs: ubi-volume-rootfs { ++ volname = "rootfs"; ++ }; ++ };*/ ++ }; + }; + }; + +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0048-add-mtd-rw-driver.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0048-add-mtd-rw-driver.patch new file mode 100644 index 0000000000..c9d11745cb --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0048-add-mtd-rw-driver.patch @@ -0,0 +1,594 @@ +From 33e651e124d1f4fc3dabcc9b83da1fb7c52ce88c Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sun, 6 Jul 2025 17:00:18 +0200 +Subject: [PATCH 48/84] add mtd-rw driver + +from https://github.com/jclehner/mtd-rw +--- + drivers/mtd/Kconfig | 2 + + drivers/mtd/Makefile | 2 + + drivers/mtd/mtdrw/Kconfig | 8 + + drivers/mtd/mtdrw/LICENSE | 339 ++++++++++++++++++++++++++++++++++++ + drivers/mtd/mtdrw/Makefile | 15 ++ + drivers/mtd/mtdrw/README.md | 25 +++ + drivers/mtd/mtdrw/mtd-rw.c | 132 ++++++++++++++ + 7 files changed, 523 insertions(+) + create mode 100644 drivers/mtd/mtdrw/Kconfig + create mode 100644 drivers/mtd/mtdrw/LICENSE + create mode 100644 drivers/mtd/mtdrw/Makefile + create mode 100644 drivers/mtd/mtdrw/README.md + create mode 100644 drivers/mtd/mtdrw/mtd-rw.c + +diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig +index 796a2eccbef0..7bd7ea0d5ddc 100644 +--- a/drivers/mtd/Kconfig ++++ b/drivers/mtd/Kconfig +@@ -222,4 +222,6 @@ source "drivers/mtd/ubi/Kconfig" + + source "drivers/mtd/hyperbus/Kconfig" + ++source "drivers/mtd/mtdrw/Kconfig" ++ + endif # MTD +diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile +index 593d0593a038..4c2437657a9c 100644 +--- a/drivers/mtd/Makefile ++++ b/drivers/mtd/Makefile +@@ -31,3 +31,5 @@ obj-y += chips/ lpddr/ maps/ devices/ nand/ tests/ + obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/ + obj-$(CONFIG_MTD_UBI) += ubi/ + obj-$(CONFIG_MTD_HYPERBUS) += hyperbus/ ++ ++obj-y += mtdrw/ +diff --git a/drivers/mtd/mtdrw/Kconfig b/drivers/mtd/mtdrw/Kconfig +new file mode 100644 +index 000000000000..a81af6f11b91 +--- /dev/null ++++ b/drivers/mtd/mtdrw/Kconfig +@@ -0,0 +1,8 @@ ++config MTD_RW ++ tristate "Module to make all MTD partitions writeable" ++ default n ++ help ++ Say M here to build a module which, upon loading, will make ++ all read-only MTD partitions writeable. Do not say Y here. ++ ++ If unsure, say N. +diff --git a/drivers/mtd/mtdrw/LICENSE b/drivers/mtd/mtdrw/LICENSE +new file mode 100644 +index 000000000000..23cb790338e1 +--- /dev/null ++++ b/drivers/mtd/mtdrw/LICENSE +@@ -0,0 +1,339 @@ ++ GNU GENERAL PUBLIC LICENSE ++ Version 2, June 1991 ++ ++ Copyright (C) 1989, 1991 Free Software Foundation, Inc., ++ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ Everyone is permitted to copy and distribute verbatim copies ++ of this license document, but changing it is not allowed. ++ ++ Preamble ++ ++ The licenses for most software are designed to take away your ++freedom to share and change it. By contrast, the GNU General Public ++License is intended to guarantee your freedom to share and change free ++software--to make sure the software is free for all its users. This ++General Public License applies to most of the Free Software ++Foundation's software and to any other program whose authors commit to ++using it. (Some other Free Software Foundation software is covered by ++the GNU Lesser General Public License instead.) You can apply it to ++your programs, too. ++ ++ When we speak of free software, we are referring to freedom, not ++price. Our General Public Licenses are designed to make sure that you ++have the freedom to distribute copies of free software (and charge for ++this service if you wish), that you receive source code or can get it ++if you want it, that you can change the software or use pieces of it ++in new free programs; and that you know you can do these things. ++ ++ To protect your rights, we need to make restrictions that forbid ++anyone to deny you these rights or to ask you to surrender the rights. ++These restrictions translate to certain responsibilities for you if you ++distribute copies of the software, or if you modify it. ++ ++ For example, if you distribute copies of such a program, whether ++gratis or for a fee, you must give the recipients all the rights that ++you have. You must make sure that they, too, receive or can get the ++source code. And you must show them these terms so they know their ++rights. ++ ++ We protect your rights with two steps: (1) copyright the software, and ++(2) offer you this license which gives you legal permission to copy, ++distribute and/or modify the software. ++ ++ Also, for each author's protection and ours, we want to make certain ++that everyone understands that there is no warranty for this free ++software. If the software is modified by someone else and passed on, we ++want its recipients to know that what they have is not the original, so ++that any problems introduced by others will not reflect on the original ++authors' reputations. ++ ++ Finally, any free program is threatened constantly by software ++patents. We wish to avoid the danger that redistributors of a free ++program will individually obtain patent licenses, in effect making the ++program proprietary. To prevent this, we have made it clear that any ++patent must be licensed for everyone's free use or not licensed at all. ++ ++ The precise terms and conditions for copying, distribution and ++modification follow. ++ ++ GNU GENERAL PUBLIC LICENSE ++ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION ++ ++ 0. This License applies to any program or other work which contains ++a notice placed by the copyright holder saying it may be distributed ++under the terms of this General Public License. The "Program", below, ++refers to any such program or work, and a "work based on the Program" ++means either the Program or any derivative work under copyright law: ++that is to say, a work containing the Program or a portion of it, ++either verbatim or with modifications and/or translated into another ++language. (Hereinafter, translation is included without limitation in ++the term "modification".) Each licensee is addressed as "you". ++ ++Activities other than copying, distribution and modification are not ++covered by this License; they are outside its scope. The act of ++running the Program is not restricted, and the output from the Program ++is covered only if its contents constitute a work based on the ++Program (independent of having been made by running the Program). ++Whether that is true depends on what the Program does. ++ ++ 1. You may copy and distribute verbatim copies of the Program's ++source code as you receive it, in any medium, provided that you ++conspicuously and appropriately publish on each copy an appropriate ++copyright notice and disclaimer of warranty; keep intact all the ++notices that refer to this License and to the absence of any warranty; ++and give any other recipients of the Program a copy of this License ++along with the Program. ++ ++You may charge a fee for the physical act of transferring a copy, and ++you may at your option offer warranty protection in exchange for a fee. ++ ++ 2. You may modify your copy or copies of the Program or any portion ++of it, thus forming a work based on the Program, and copy and ++distribute such modifications or work under the terms of Section 1 ++above, provided that you also meet all of these conditions: ++ ++ a) You must cause the modified files to carry prominent notices ++ stating that you changed the files and the date of any change. ++ ++ b) You must cause any work that you distribute or publish, that in ++ whole or in part contains or is derived from the Program or any ++ part thereof, to be licensed as a whole at no charge to all third ++ parties under the terms of this License. ++ ++ c) If the modified program normally reads commands interactively ++ when run, you must cause it, when started running for such ++ interactive use in the most ordinary way, to print or display an ++ announcement including an appropriate copyright notice and a ++ notice that there is no warranty (or else, saying that you provide ++ a warranty) and that users may redistribute the program under ++ these conditions, and telling the user how to view a copy of this ++ License. (Exception: if the Program itself is interactive but ++ does not normally print such an announcement, your work based on ++ the Program is not required to print an announcement.) ++ ++These requirements apply to the modified work as a whole. If ++identifiable sections of that work are not derived from the Program, ++and can be reasonably considered independent and separate works in ++themselves, then this License, and its terms, do not apply to those ++sections when you distribute them as separate works. But when you ++distribute the same sections as part of a whole which is a work based ++on the Program, the distribution of the whole must be on the terms of ++this License, whose permissions for other licensees extend to the ++entire whole, and thus to each and every part regardless of who wrote it. ++ ++Thus, it is not the intent of this section to claim rights or contest ++your rights to work written entirely by you; rather, the intent is to ++exercise the right to control the distribution of derivative or ++collective works based on the Program. ++ ++In addition, mere aggregation of another work not based on the Program ++with the Program (or with a work based on the Program) on a volume of ++a storage or distribution medium does not bring the other work under ++the scope of this License. ++ ++ 3. You may copy and distribute the Program (or a work based on it, ++under Section 2) in object code or executable form under the terms of ++Sections 1 and 2 above provided that you also do one of the following: ++ ++ a) Accompany it with the complete corresponding machine-readable ++ source code, which must be distributed under the terms of Sections ++ 1 and 2 above on a medium customarily used for software interchange; or, ++ ++ b) Accompany it with a written offer, valid for at least three ++ years, to give any third party, for a charge no more than your ++ cost of physically performing source distribution, a complete ++ machine-readable copy of the corresponding source code, to be ++ distributed under the terms of Sections 1 and 2 above on a medium ++ customarily used for software interchange; or, ++ ++ c) Accompany it with the information you received as to the offer ++ to distribute corresponding source code. (This alternative is ++ allowed only for noncommercial distribution and only if you ++ received the program in object code or executable form with such ++ an offer, in accord with Subsection b above.) ++ ++The source code for a work means the preferred form of the work for ++making modifications to it. For an executable work, complete source ++code means all the source code for all modules it contains, plus any ++associated interface definition files, plus the scripts used to ++control compilation and installation of the executable. However, as a ++special exception, the source code distributed need not include ++anything that is normally distributed (in either source or binary ++form) with the major components (compiler, kernel, and so on) of the ++operating system on which the executable runs, unless that component ++itself accompanies the executable. ++ ++If distribution of executable or object code is made by offering ++access to copy from a designated place, then offering equivalent ++access to copy the source code from the same place counts as ++distribution of the source code, even though third parties are not ++compelled to copy the source along with the object code. ++ ++ 4. You may not copy, modify, sublicense, or distribute the Program ++except as expressly provided under this License. Any attempt ++otherwise to copy, modify, sublicense or distribute the Program is ++void, and will automatically terminate your rights under this License. ++However, parties who have received copies, or rights, from you under ++this License will not have their licenses terminated so long as such ++parties remain in full compliance. ++ ++ 5. You are not required to accept this License, since you have not ++signed it. However, nothing else grants you permission to modify or ++distribute the Program or its derivative works. These actions are ++prohibited by law if you do not accept this License. Therefore, by ++modifying or distributing the Program (or any work based on the ++Program), you indicate your acceptance of this License to do so, and ++all its terms and conditions for copying, distributing or modifying ++the Program or works based on it. ++ ++ 6. Each time you redistribute the Program (or any work based on the ++Program), the recipient automatically receives a license from the ++original licensor to copy, distribute or modify the Program subject to ++these terms and conditions. You may not impose any further ++restrictions on the recipients' exercise of the rights granted herein. ++You are not responsible for enforcing compliance by third parties to ++this License. ++ ++ 7. If, as a consequence of a court judgment or allegation of patent ++infringement or for any other reason (not limited to patent issues), ++conditions are imposed on you (whether by court order, agreement or ++otherwise) that contradict the conditions of this License, they do not ++excuse you from the conditions of this License. If you cannot ++distribute so as to satisfy simultaneously your obligations under this ++License and any other pertinent obligations, then as a consequence you ++may not distribute the Program at all. For example, if a patent ++license would not permit royalty-free redistribution of the Program by ++all those who receive copies directly or indirectly through you, then ++the only way you could satisfy both it and this License would be to ++refrain entirely from distribution of the Program. ++ ++If any portion of this section is held invalid or unenforceable under ++any particular circumstance, the balance of the section is intended to ++apply and the section as a whole is intended to apply in other ++circumstances. ++ ++It is not the purpose of this section to induce you to infringe any ++patents or other property right claims or to contest validity of any ++such claims; this section has the sole purpose of protecting the ++integrity of the free software distribution system, which is ++implemented by public license practices. Many people have made ++generous contributions to the wide range of software distributed ++through that system in reliance on consistent application of that ++system; it is up to the author/donor to decide if he or she is willing ++to distribute software through any other system and a licensee cannot ++impose that choice. ++ ++This section is intended to make thoroughly clear what is believed to ++be a consequence of the rest of this License. ++ ++ 8. If the distribution and/or use of the Program is restricted in ++certain countries either by patents or by copyrighted interfaces, the ++original copyright holder who places the Program under this License ++may add an explicit geographical distribution limitation excluding ++those countries, so that distribution is permitted only in or among ++countries not thus excluded. In such case, this License incorporates ++the limitation as if written in the body of this License. ++ ++ 9. The Free Software Foundation may publish revised and/or new versions ++of the General Public License from time to time. Such new versions will ++be similar in spirit to the present version, but may differ in detail to ++address new problems or concerns. ++ ++Each version is given a distinguishing version number. If the Program ++specifies a version number of this License which applies to it and "any ++later version", you have the option of following the terms and conditions ++either of that version or of any later version published by the Free ++Software Foundation. If the Program does not specify a version number of ++this License, you may choose any version ever published by the Free Software ++Foundation. ++ ++ 10. If you wish to incorporate parts of the Program into other free ++programs whose distribution conditions are different, write to the author ++to ask for permission. For software which is copyrighted by the Free ++Software Foundation, write to the Free Software Foundation; we sometimes ++make exceptions for this. Our decision will be guided by the two goals ++of preserving the free status of all derivatives of our free software and ++of promoting the sharing and reuse of software generally. ++ ++ NO WARRANTY ++ ++ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY ++FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN ++OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES ++PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED ++OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ++MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS ++TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE ++PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, ++REPAIR OR CORRECTION. ++ ++ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING ++WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR ++REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, ++INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING ++OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED ++TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY ++YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER ++PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE ++POSSIBILITY OF SUCH DAMAGES. ++ ++ END OF TERMS AND CONDITIONS ++ ++ How to Apply These Terms to Your New Programs ++ ++ If you develop a new program, and you want it to be of the greatest ++possible use to the public, the best way to achieve this is to make it ++free software which everyone can redistribute and change under these terms. ++ ++ To do so, attach the following notices to the program. It is safest ++to attach them to the start of each source file to most effectively ++convey the exclusion of warranty; and each file should have at least ++the "copyright" line and a pointer to where the full notice is found. ++ ++ {description} ++ Copyright (C) {year} {fullname} ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License along ++ with this program; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++Also add information on how to contact you by electronic and paper mail. ++ ++If the program is interactive, make it output a short notice like this ++when it starts in an interactive mode: ++ ++ Gnomovision version 69, Copyright (C) year name of author ++ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. ++ This is free software, and you are welcome to redistribute it ++ under certain conditions; type `show c' for details. ++ ++The hypothetical commands `show w' and `show c' should show the appropriate ++parts of the General Public License. Of course, the commands you use may ++be called something other than `show w' and `show c'; they could even be ++mouse-clicks or menu items--whatever suits your program. ++ ++You should also get your employer (if you work as a programmer) or your ++school, if any, to sign a "copyright disclaimer" for the program, if ++necessary. Here is a sample; alter the names: ++ ++ Yoyodyne, Inc., hereby disclaims all copyright interest in the program ++ `Gnomovision' (which makes passes at compilers) written by James Hacker. ++ ++ {signature of Ty Coon}, 1 April 1989 ++ Ty Coon, President of Vice ++ ++This General Public License does not permit incorporating your program into ++proprietary programs. If your program is a subroutine library, you may ++consider it more useful to permit linking proprietary applications with the ++library. If this is what you want to do, use the GNU Lesser General ++Public License instead of this License. +diff --git a/drivers/mtd/mtdrw/Makefile b/drivers/mtd/mtdrw/Makefile +new file mode 100644 +index 000000000000..d1061ccf3a67 +--- /dev/null ++++ b/drivers/mtd/mtdrw/Makefile +@@ -0,0 +1,15 @@ ++# Build module only if kernel supports MTD ++ifdef CONFIG_MTD ++obj-m += mtd-rw.o ++endif ++ ++KDIR ?= /lib/modules/$(shell uname -r)/build ++ ++modules: ++ $(MAKE) -C $(KDIR) M=$$PWD modules ++ ++modules_install: ++ $(MAKE) -C $(KDIR) M=$$PWD modules_install ++ ++clean: ++ $(MAKE) -C $(KDIR) M=$$PWD clean +diff --git a/drivers/mtd/mtdrw/README.md b/drivers/mtd/mtdrw/README.md +new file mode 100644 +index 000000000000..dc3b08894ae5 +--- /dev/null ++++ b/drivers/mtd/mtdrw/README.md +@@ -0,0 +1,25 @@ ++mtd-rw - Write-enabler for MTD partitions ++========================================= ++ ++Sets the `MTD_WRITEABLE` flag on all MTD partitions that are marked readonly. ++When unloading, read-only partitions will be restored. This module is intended ++for embedded devices where the mtd partition layout may be hard-coded in the ++firmware. If, for some reason, you DO have to write to a read-only partition ++(which is often a bad idea), this module is the way to go. ++ ++The module is currently limited to the first 64 partitions, but this ++should suffice for most purposes. ++ ++Inspired by dougg3@electronics.stackexchange.com: ++https://electronics.stackexchange.com/a/116133/97342 ++ ++Usage: ++``` ++# insmod mtd-rw.ko i_want_a_brick=1 ++# dmesg | grep mtd-rw ++[52997.620000] mtd-rw: mtd0: setting writeable flag ++[52997.630000] mtd-rw: mtd1: setting writeable flag ++[52997.640000] mtd-rw: mtd3: setting writeable flag ++[52997.650000] mtd-rw: mtd4: setting writeable flag ++[52997.660000] mtd-rw: mtd6: setting writeable flag ++``` +diff --git a/drivers/mtd/mtdrw/mtd-rw.c b/drivers/mtd/mtdrw/mtd-rw.c +new file mode 100644 +index 000000000000..706714d3db77 +--- /dev/null ++++ b/drivers/mtd/mtdrw/mtd-rw.c +@@ -0,0 +1,132 @@ ++/* ++ * mtd-rw - Make all MTD partitions writeable. ++ * ++ * Copyright (C) 2016 Joseph C. Lehner ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. ++ * If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++ ++/* ++ * This module is intended for embedded devices where the mtd partition ++ * layout may be hard-coded in the firmware. If, for some reason, you ++ * DO have to write to a read-only partition (which is often a bad idea), ++ * this module is the way to go. ++ * ++ * The module is currently limited to the first 64 partitions, but this ++ * should suffice for most purposes. ++ * ++ * Inspired by dougg3@electronics.stackexchange.com: ++ * https://electronics.stackexchange.com/a/116133/97342 ++ */ ++ ++#ifndef MODULE ++#error "Must be compiled as a module." ++#endif ++ ++#define MOD_WARNING KERN_WARNING "mtd-rw: " ++#define MOD_INFO KERN_INFO "mtd-rw: " ++#define MOD_ERR KERN_ERR "mtd-rw: " ++ ++#define MTD_MAX (8 * sizeof(unlocked)) ++ ++static uint64_t unlocked = 0; ++static unsigned mtd_last = 0; ++ ++static bool i_want_a_brick = false; ++module_param(i_want_a_brick, bool, S_IRUGO); ++MODULE_PARM_DESC(i_want_a_brick, "Make all partitions writeable"); ++ ++static int set_writeable(unsigned n, bool w) ++{ ++ struct mtd_info *mtd = get_mtd_device(NULL, n); ++ int err; ++ ++ if (IS_ERR(mtd)) { ++ if (PTR_ERR(mtd) != -ENODEV || !w) { ++ printk(MOD_ERR "mtd%d: error %ld\n", n, PTR_ERR(mtd)); ++ } ++ return PTR_ERR(mtd); ++ } ++ ++ err = -EEXIST; ++ ++ if (w && !(mtd->flags & MTD_WRITEABLE)) { ++ printk(MOD_INFO "mtd%d: setting writeable flag\n", n); ++ mtd->flags |= MTD_WRITEABLE; ++ err = 0; ++ } else if (!w && (mtd->flags & MTD_WRITEABLE)) { ++ printk(MOD_INFO "mtd%d: clearing writeable flag\n", n); ++ mtd->flags &= ~MTD_WRITEABLE; ++ err = 0; ++ } ++ ++ put_mtd_device(mtd); ++ return err; ++} ++ ++static int __init mtd_rw_init(void) ++{ ++ int i, err; ++ ++ if (!i_want_a_brick) { ++ printk(MOD_ERR "must specify i_want_a_brick=1 to continue\n"); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < MTD_MAX; ++i) { ++ err = set_writeable(i, true); ++ if (!err) { ++ unlocked |= (1 << i); ++ } else if (err == -ENODEV) { ++ break; ++ } ++ } ++ ++ if (i == MTD_MAX) { ++ printk(MOD_WARNING "partitions beyond mtd%d are ignored\n", i - 1); ++ } ++ ++ if (!unlocked) { ++ printk(MOD_INFO "no partitions to unlock\n"); ++ return -ENODEV; ++ } ++ ++ mtd_last = i; ++ ++ return 0; ++} ++ ++static void __exit mtd_rw_exit(void) ++{ ++ unsigned i; ++ ++ for (i = 0; i < mtd_last; ++i) { ++ if (unlocked & (1 << i)) { ++ set_writeable(i, false); ++ } ++ } ++} ++ ++module_init(mtd_rw_init); ++module_exit(mtd_rw_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Joseph C. Lehner "); ++MODULE_DESCRIPTION("Write-enabler for MTD partitions"); ++MODULE_VERSION("1"); +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0049-arm64-dts-add-usxgmii-pcs-and-link-both-pcs.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0049-arm64-dts-add-usxgmii-pcs-and-link-both-pcs.patch new file mode 100644 index 0000000000..9a51259799 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0049-arm64-dts-add-usxgmii-pcs-and-link-both-pcs.patch @@ -0,0 +1,56 @@ +From 2141bb55b2e6e0ce036206ada409d588588ed8ef Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Thu, 1 May 2025 19:46:37 +0200 +Subject: [PATCH 49/84] arm64: dts: add usxgmii pcs and link both pcs + +--- + arch/arm64/boot/dts/mediatek/mt7988a.dtsi | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi +index 88f201ad78cf..bbe088ea620f 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi +@@ -315,6 +315,24 @@ sgmiipcs1: pcs { + }; + }; + ++ usxgmiisys0: pcs@10080000 { ++ compatible = "mediatek,mt7988-usxgmiisys"; ++ reg = <0 0x10080000 0 0x1000>; ++ resets = <&watchdog 12>; ++ clocks = <&topckgen CLK_TOP_USXGMII_SBUS_0_SEL>; ++ phys = <&xfi_tphy0>; ++ #pcs-cells = <0>; ++ }; ++ ++ usxgmiisys1: pcs@10081000 { ++ compatible = "mediatek,mt7988-usxgmiisys"; ++ reg = <0 0x10081000 0 0x1000>; ++ resets = <&watchdog 13>; ++ clocks = <&topckgen CLK_TOP_USXGMII_SBUS_1_SEL>; ++ phys = <&xfi_tphy1>; ++ #pcs-cells = <0>; ++ }; ++ + mcusys: mcusys@100e0000 { + compatible = "mediatek,mt7988-mcusys", "syscon"; + reg = <0 0x100e0000 0 0x1000>; +@@ -1020,12 +1038,14 @@ gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + status = "disabled"; ++ pcs-handle = <&sgmiipcs1>, <&usxgmiisys1>; + }; + + gmac2: mac@2 { + compatible = "mediatek,eth-mac"; + reg = <2>; + status = "disabled"; ++ pcs-handle = <&sgmiipcs0>, <&usxgmiisys0>; + }; + + mdio_bus: mdio-bus { +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0050-arm64-dts-update-bpi-r4.dtsi-to-actual-state.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0050-arm64-dts-update-bpi-r4.dtsi-to-actual-state.patch new file mode 100644 index 0000000000..268f011df0 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0050-arm64-dts-update-bpi-r4.dtsi-to-actual-state.patch @@ -0,0 +1,142 @@ +From 6c08db21a2f0d37c9ffeba6c327aff67e3be28da Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sun, 3 Nov 2024 11:18:31 +0100 +Subject: [PATCH 50/84] arm64: dts: update bpi-r4.dtsi to actual state + +--- + .../dts/mediatek/mt7988a-bananapi-bpi-r4.dts | 1 + + .../dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi | 40 +++++++++++++++++-- + 2 files changed, 38 insertions(+), 3 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dts b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dts +index 4b3796ba82e3..499f0c91c213 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dts +@@ -27,6 +27,7 @@ &gmac1 { + managed = "in-band-status"; + phy-mode = "usxgmii"; + sfp = <&sfp2>; ++ status = "okay"; + }; + + &pca9545 { +diff --git a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi +index 38e27ef6bc0c..a614729e9e47 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7988a-bananapi-bpi-r4.dtsi +@@ -3,6 +3,7 @@ + /dts-v1/; + + #include ++#include + #include + #include + +@@ -13,10 +14,20 @@ aliases { + ethernet0 = &gmac0; + ethernet1 = &gmac1; + ethernet2 = &gmac2; ++ led-boot = &led_green; ++ led-failsafe = &led_green; ++ led-running = &led_green; ++ led-upgrade = &led_green; + }; + + chosen { + stdout-path = "serial0:115200n8"; ++ bootargs = "loglevel=8 pci=pcie_bus_perf ubi.block=0,fit root=/dev/fit0"; ++ rootdisk-spim-nand = <&ubi_rootfs>; ++ }; ++ ++ memory { ++ reg = <0x00 0x40000000 0x00 0x10000000>; + }; + + fan: pwm-fan { +@@ -28,6 +39,16 @@ fan: pwm-fan { + status = "okay"; + }; + ++ gpio-keys { ++ compatible = "gpio-keys"; ++ ++ wps { ++ label = "WPS"; ++ linux,code = ; ++ gpios = <&pio 14 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++ + gpio-leds { + compatible = "gpio-leds"; + +@@ -151,6 +172,7 @@ &gmac2 { + managed = "in-band-status"; + phy-mode = "usxgmii"; + sfp = <&sfp1>; ++ status = "okay"; + }; + + &gsw_phy0 { +@@ -280,7 +302,7 @@ pca9545: i2c-mux@70 { + #address-cells = <1>; + #size-cells = <0>; + +- i2c@0 { ++ i2c@0 { //eeprom,rtc,ngff + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; +@@ -288,12 +310,16 @@ i2c@0 { + pcf8563: rtc@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; ++ //interrupts = <&pio 6 IRQ_TYPE_LEVEL_LOW>; + #clock-cells = <0>; ++ //status = "disabled"; + }; + + eeprom@57 { + compatible = "atmel,24c02"; + reg = <0x57>; ++ address-bits = <8>; ++ page-size = <8>; + size = <256>; + }; + +@@ -304,6 +330,14 @@ i2c_sfp1: i2c@1 { + #size-cells = <0>; + reg = <1>; + }; ++ ++ i2c_wifi: i2c@3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <3>; ++ ++ status = "disabled"; ++ }; + }; + }; + +@@ -455,7 +489,7 @@ partition@200000 { + reg = <0x200000 0x7e00000>; + compatible = "linux,ubi"; + +- /*volumes { ++ volumes { + ubi-volume-fip { + volname = "fip"; + }; +@@ -477,7 +511,7 @@ nvmem-layout { + ubi_rootfs: ubi-volume-rootfs { + volname = "rootfs"; + }; +- };*/ ++ }; + }; + }; + }; +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0051-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0051-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch new file mode 100644 index 0000000000..4f75225d27 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0051-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch @@ -0,0 +1,578 @@ +From 2130ea2c451f40a26214c6702ea8230dd6da2044 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 12 Dec 2023 03:51:14 +0000 +Subject: [PATCH 51/84] net: ethernet: mtk_eth_soc: add paths and SerDes modes + for MT7988 + +MT7988 comes with two SerDes interfaces to connect external PHYs or +transceivers in USXGMII, 10GBase-R, 5GBase-R, 2500Base-X, 1000Base-X and +Cisco SGMII interface modes. + +Implement support for configuring for the new paths to SerDes interfaces. + +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/mtk_eth_path.c | 81 +++++++++- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 149 +++++++++++++++---- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 48 +++++- + 3 files changed, 238 insertions(+), 40 deletions(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_path.c b/drivers/net/ethernet/mediatek/mtk_eth_path.c +index b4c01e2878f6..249b2fe7c10d 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_path.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_path.c +@@ -35,8 +35,16 @@ static const char *mtk_eth_path_name(u64 path) + return "gmac2_2p5gphy"; + case MTK_ETH_PATH_GMAC2_GEPHY: + return "gmac2_gephy"; ++ case MTK_ETH_PATH_GMAC3_SGMII: ++ return "gmac3_sgmii"; + case MTK_ETH_PATH_GDM1_ESW: + return "gdm1_esw"; ++ case MTK_ETH_PATH_GMAC1_USXGMII: ++ return "gmac1_usxgmii"; ++ case MTK_ETH_PATH_GMAC2_USXGMII: ++ return "gmac2_usxgmii"; ++ case MTK_ETH_PATH_GMAC3_USXGMII: ++ return "gmac3_usxgmii"; + default: + return "unknown path"; + } +@@ -190,7 +198,48 @@ static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, u64 path) + return 0; + } + +-static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, u64 path) ++static int set_mux_gmac123_to_usxgmii(struct mtk_eth *eth, u64 path) ++{ ++ unsigned int val = 0; ++ bool updated = true; ++ int mac_id = 0; ++ ++ /* Disable SYSCFG1 SGMII */ ++ regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val); ++ ++ switch (path) { ++ case MTK_ETH_PATH_GMAC1_USXGMII: ++ val &= ~(u32)SYSCFG0_SGMII_GMAC1_V2; ++ mac_id = MTK_GMAC1_ID; ++ break; ++ case MTK_ETH_PATH_GMAC2_USXGMII: ++ val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2; ++ mac_id = MTK_GMAC2_ID; ++ break; ++ case MTK_ETH_PATH_GMAC3_USXGMII: ++ val &= ~(u32)SYSCFG0_SGMII_GMAC3_V2; ++ mac_id = MTK_GMAC3_ID; ++ break; ++ default: ++ updated = false; ++ }; ++ ++ if (updated) { ++ regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0, ++ SYSCFG0_SGMII_MASK, val); ++ ++ if (mac_id == MTK_GMAC2_ID) ++ regmap_set_bits(eth->infra, TOP_MISC_NETSYS_PCS_MUX, ++ MUX_G2_USXGMII_SEL); ++ } ++ ++ dev_dbg(eth->dev, "path %s in %s updated = %d\n", ++ mtk_eth_path_name(path), __func__, updated); ++ ++ return 0; ++} ++ ++static int set_mux_gmac123_to_gephy_sgmii(struct mtk_eth *eth, u64 path) + { + unsigned int val = 0; + bool updated = true; +@@ -207,6 +256,9 @@ static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, u64 path) + case MTK_ETH_PATH_GMAC2_SGMII: + val |= SYSCFG0_SGMII_GMAC2_V2; + break; ++ case MTK_ETH_PATH_GMAC3_SGMII: ++ val |= SYSCFG0_SGMII_GMAC3_V2; ++ break; + default: + updated = false; + } +@@ -245,7 +297,15 @@ static const struct mtk_eth_muxc mtk_eth_muxc[] = { + }, { + .name = "mux_gmac12_to_gephy_sgmii", + .cap_bit = MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII, +- .set_path = set_mux_gmac12_to_gephy_sgmii, ++ .set_path = set_mux_gmac123_to_gephy_sgmii, ++ }, { ++ .name = "mux_gmac123_to_gephy_sgmii", ++ .cap_bit = MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII, ++ .set_path = set_mux_gmac123_to_gephy_sgmii, ++ }, { ++ .name = "mux_gmac123_to_usxgmii", ++ .cap_bit = MTK_ETH_MUX_GMAC123_TO_USXGMII, ++ .set_path = set_mux_gmac123_to_usxgmii, + }, + }; + +@@ -278,12 +338,25 @@ static int mtk_eth_mux_setup(struct mtk_eth *eth, u64 path) + return err; + } + ++int mtk_gmac_usxgmii_path_setup(struct mtk_eth *eth, int mac_id) ++{ ++ u64 path; ++ ++ path = (mac_id == MTK_GMAC1_ID) ? MTK_ETH_PATH_GMAC1_USXGMII : ++ (mac_id == MTK_GMAC2_ID) ? MTK_ETH_PATH_GMAC2_USXGMII : ++ MTK_ETH_PATH_GMAC3_USXGMII; ++ ++ /* Setup proper MUXes along the path */ ++ return mtk_eth_mux_setup(eth, path); ++} ++ + int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id) + { + u64 path; + +- path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_SGMII : +- MTK_ETH_PATH_GMAC2_SGMII; ++ path = (mac_id == MTK_GMAC1_ID) ? MTK_ETH_PATH_GMAC1_SGMII : ++ (mac_id == MTK_GMAC2_ID) ? MTK_ETH_PATH_GMAC2_SGMII : ++ MTK_ETH_PATH_GMAC3_SGMII; + + /* Setup proper MUXes along the path */ + return mtk_eth_mux_setup(eth, path); +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index 7916c99d5ebb..ac7250003b1d 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -22,6 +22,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +@@ -514,23 +516,28 @@ static void mtk_setup_bridge_switch(struct mtk_eth *eth) + MTK_GSW_CFG); + } + +-static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *config, +- phy_interface_t interface) ++static bool mtk_check_gmac23_idle(struct mtk_mac *mac) + { +- struct mtk_mac *mac = container_of(config, struct mtk_mac, +- phylink_config); +- struct mtk_eth *eth = mac->hw; +- unsigned int sid; ++ u32 mac_fsm, gdm_fsm; + +- if (interface == PHY_INTERFACE_MODE_SGMII || +- phy_interface_mode_is_8023z(interface)) { +- sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ? +- 0 : mac->id; ++ mac_fsm = mtk_r32(mac->hw, MTK_MAC_FSM(mac->id)); + +- return eth->sgmii_pcs[sid]; +- } ++ switch (mac->id) { ++ case MTK_GMAC2_ID: ++ gdm_fsm = mtk_r32(mac->hw, MTK_FE_GDM2_FSM); ++ break; ++ case MTK_GMAC3_ID: ++ gdm_fsm = mtk_r32(mac->hw, MTK_FE_GDM3_FSM); ++ break; ++ default: ++ return true; ++ }; + +- return NULL; ++ if ((mac_fsm & 0xFFFF0000) == 0x01010000 && ++ (gdm_fsm & 0xFFFF0000) == 0x00000000) ++ return true; ++ ++ return false; + } + + static int mtk_mac_prepare(struct phylink_config *config, unsigned int mode, +@@ -593,6 +600,15 @@ static void mtk_mac_config(struct phylink_config *config, unsigned int mode, + goto init_err; + } + break; ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ case PHY_INTERFACE_MODE_5GBASER: ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_USXGMII)) { ++ err = mtk_gmac_usxgmii_path_setup(eth, mac->id); ++ if (err) ++ goto init_err; ++ } ++ break; + case PHY_INTERFACE_MODE_INTERNAL: + if (mac->id == MTK_GMAC2_ID && + MTK_HAS_CAPS(eth->soc->caps, MTK_2P5GPHY)) { +@@ -646,8 +662,6 @@ static void mtk_mac_config(struct phylink_config *config, unsigned int mode, + val &= ~SYSCFG0_GE_MODE(SYSCFG0_GE_MASK, mac->id); + val |= SYSCFG0_GE_MODE(ge_mode, mac->id); + regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val); +- +- mac->interface = state->interface; + } + + /* SGMII */ +@@ -664,9 +678,12 @@ static void mtk_mac_config(struct phylink_config *config, unsigned int mode, + + /* Save the syscfg0 value for mac_finish */ + mac->syscfg0 = val; +- } else if (phylink_autoneg_inband(mode)) { ++ } else if (state->interface != PHY_INTERFACE_MODE_USXGMII && ++ state->interface != PHY_INTERFACE_MODE_10GBASER && ++ state->interface != PHY_INTERFACE_MODE_5GBASER && ++ phylink_autoneg_inband(mode)) { + dev_err(eth->dev, +- "In-band mode not supported in non SGMII mode!\n"); ++ "In-band mode not supported in non-SerDes modes!\n"); + return; + } + +@@ -677,8 +694,22 @@ static void mtk_mac_config(struct phylink_config *config, unsigned int mode, + + if (mac->id == MTK_GMAC1_ID) + mtk_setup_bridge_switch(eth); ++ } else if (mtk_is_netsys_v3_or_greater(eth)) { ++ mtk_w32(eth, 0, MTK_GDMA_EG_CTRL(mac->id)); ++ ++ /* FIXME: In current hardware design, we have to reset FE ++ * when swtiching XGDM to GDM. Therefore, here trigger an SER ++ * to let GDM go back to the initial state. ++ */ ++ if ((mtk_interface_mode_is_xgmii(eth, mac->interface) || ++ mac->interface == PHY_INTERFACE_MODE_NA) && ++ !mtk_check_gmac23_idle(mac) && ++ !test_bit(MTK_RESETTING, ð->state)) ++ schedule_work(ð->pending_work); + } + ++ mac->interface = state->interface; ++ + return; + + err_phy: +@@ -729,6 +760,9 @@ static void mtk_mac_link_down(struct phylink_config *config, unsigned int mode, + mtk_m32(mac->hw, + MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK, 0, + MTK_MAC_MCR(mac->id)); ++ if (mtk_is_netsys_v3_or_greater(mac->hw)) ++ mtk_m32(mac->hw, MTK_XGMAC_FORCE_LINK(mac->id), 0, ++ MTK_XGMAC_STS(mac->id)); + } else if (mac->id != MTK_GMAC1_ID) { + /* XGMAC except for built-in switch */ + mtk_m32(mac->hw, XMAC_MCR_TRX_DISABLE, XMAC_MCR_TRX_DISABLE, +@@ -947,7 +981,6 @@ static int mtk_mac_enable_tx_lpi(struct phylink_config *config, u32 timer, + + static const struct phylink_mac_ops mtk_phylink_ops = { + .mac_prepare = mtk_mac_prepare, +- .mac_select_pcs = mtk_mac_select_pcs, + .mac_config = mtk_mac_config, + .mac_finish = mtk_mac_finish, + .mac_link_down = mtk_mac_link_down, +@@ -4774,7 +4807,8 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) + phy_interface_t phy_mode; + struct phylink *phylink; + struct mtk_mac *mac; +- int id, err; ++ int id, err, count; ++ unsigned int sid; + int txqs = 1; + u32 val; + +@@ -4856,6 +4890,7 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) + mac->phylink_config.lpi_capabilities = MAC_100FD | MAC_1000FD | + MAC_2500FD; + mac->phylink_config.lpi_timer_default = 1000; ++ mac->phylink_config.num_available_pcs = 0; + + /* MT7623 gmac0 is now missing its speed-specific PLL configuration + * in its .mac_config method (since state->speed is not valid there. +@@ -4886,13 +4921,52 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) + + if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_SGMII)) { + __set_bit(PHY_INTERFACE_MODE_SGMII, +- mac->phylink_config.supported_interfaces); ++ mac->phylink_config.pcs_interfaces); + __set_bit(PHY_INTERFACE_MODE_1000BASEX, +- mac->phylink_config.supported_interfaces); ++ mac->phylink_config.pcs_interfaces); + __set_bit(PHY_INTERFACE_MODE_2500BASEX, +- mac->phylink_config.supported_interfaces); ++ mac->phylink_config.pcs_interfaces); ++ ++ if (mtk_is_netsys_v3_or_greater(mac->hw)) { ++ __set_bit(PHY_INTERFACE_MODE_5GBASER, ++ mac->phylink_config.pcs_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_10GBASER, ++ mac->phylink_config.pcs_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_USXGMII, ++ mac->phylink_config.pcs_interfaces); ++ ++ err = fwnode_phylink_pcs_parse(of_fwnode_handle(np), NULL, &count); ++ if (err == -ENODEV) { ++ err = 0; ++ goto no_pcs; ++ } ++ ++ if (count > 2) ++ err = -ENOMEM; ++ ++ if (err) ++ goto free_netdev; ++ ++ err = fwnode_phylink_pcs_parse(of_fwnode_handle(np), mac->available_pcs, &count); ++ if (err) ++ goto free_netdev; ++ ++ mac->phylink_config.available_pcs = mac->available_pcs; ++ mac->phylink_config.num_available_pcs = count; ++ } else { ++ sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ? ++ 0 : id; ++ ++ mac->phylink_config.available_pcs = ð->sgmii_pcs[sid]; ++ mac->phylink_config.num_available_pcs = 1; ++ } ++ ++ phy_interface_or(mac->phylink_config.supported_interfaces, ++ mac->phylink_config.supported_interfaces, ++ mac->phylink_config.pcs_interfaces); + } + ++no_pcs: + if (mtk_is_netsys_v3_or_greater(mac->hw) && + MTK_HAS_CAPS(mac->hw->soc->caps, MTK_ESW) && + id == MTK_GMAC1_ID) { +@@ -4902,18 +4976,16 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) + phy_interface_zero(mac->phylink_config.supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_INTERNAL, + mac->phylink_config.supported_interfaces); ++ } else if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_USXGMII)) { ++ mac->phylink_config.mac_capabilities |= MAC_5000FD | MAC_10000FD; ++ __set_bit(PHY_INTERFACE_MODE_5GBASER, ++ mac->phylink_config.supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_10GBASER, ++ mac->phylink_config.supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_USXGMII, ++ mac->phylink_config.supported_interfaces); + } + +- phylink = phylink_create(&mac->phylink_config, +- of_fwnode_handle(mac->of_node), +- phy_mode, &mtk_phylink_ops); +- if (IS_ERR(phylink)) { +- err = PTR_ERR(phylink); +- goto free_netdev; +- } +- +- mac->phylink = phylink; +- + if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_2P5GPHY) && + id == MTK_GMAC2_ID) + __set_bit(PHY_INTERFACE_MODE_INTERNAL, +@@ -4936,6 +5008,16 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) + eth->netdev[id]->irq = eth->irq[MTK_FE_IRQ_SHARED]; + eth->netdev[id]->dev.of_node = np; + ++ phylink = phylink_create(&mac->phylink_config, ++ of_fwnode_handle(mac->of_node), ++ phy_mode, &mtk_phylink_ops); ++ if (IS_ERR(phylink)) { ++ err = PTR_ERR(phylink); ++ goto free_netdev; ++ } ++ ++ mac->phylink = phylink; ++ + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) + eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH - MTK_RX_ETH_HLEN; + else +@@ -5112,7 +5194,8 @@ static int mtk_probe(struct platform_device *pdev) + regmap_write(cci, 0, 3); + } + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) { ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII) && ++ !mtk_is_netsys_v3_or_greater(eth)) { + err = mtk_sgmii_init(eth); + + if (err) +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +index 0168e2fbc619..88406e80dfec 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -567,6 +568,7 @@ + #define SYSCFG0_SGMII_GMAC2 ((3 << 8) & SYSCFG0_SGMII_MASK) + #define SYSCFG0_SGMII_GMAC1_V2 BIT(9) + #define SYSCFG0_SGMII_GMAC2_V2 BIT(8) ++#define SYSCFG0_SGMII_GMAC3_V2 BIT(7) + + + /* ethernet subsystem clock register */ +@@ -608,6 +610,7 @@ + #define TOP_MISC_NETSYS_PCS_MUX 0x0 + #define NETSYS_PCS_MUX_MASK GENMASK(1, 0) + #define MUX_G2_USXGMII_SEL BIT(1) ++#define MUX_HSGMII1_G1_SEL BIT(0) + + #define USB_PHY_SWITCH_REG 0x218 + #define QPHY_SEL_MASK GENMASK(1, 0) +@@ -633,6 +636,8 @@ + #define MT7628_SDM_RBCNT (MT7628_SDM_OFFSET + 0x10c) + #define MT7628_SDM_CS_ERR (MT7628_SDM_OFFSET + 0x110) + ++/* Debug Purpose Register */ ++#define MTK_PSE_FQFC_CFG 0x100 + #define MTK_FE_CDM1_FSM 0x220 + #define MTK_FE_CDM2_FSM 0x224 + #define MTK_FE_CDM3_FSM 0x238 +@@ -641,6 +646,11 @@ + #define MTK_FE_CDM6_FSM 0x328 + #define MTK_FE_GDM1_FSM 0x228 + #define MTK_FE_GDM2_FSM 0x22C ++#define MTK_FE_GDM3_FSM 0x23C ++#define MTK_FE_PSE_FREE 0x240 ++#define MTK_FE_DROP_FQ 0x244 ++#define MTK_FE_DROP_FC 0x248 ++#define MTK_FE_DROP_PPE 0x24C + + #define MTK_MAC_FSM(x) (0x1010C + ((x) * 0x100)) + +@@ -978,6 +988,7 @@ enum mkt_eth_capabilities { + MTK_RGMII_BIT = 0, + MTK_TRGMII_BIT, + MTK_SGMII_BIT, ++ MTK_USXGMII_BIT, + MTK_2P5GPHY_BIT, + MTK_ESW_BIT, + MTK_GEPHY_BIT, +@@ -1002,6 +1013,8 @@ enum mkt_eth_capabilities { + MTK_ETH_MUX_GMAC2_TO_2P5GPHY_BIT, + MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT, + MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT, ++ MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII_BIT, ++ MTK_ETH_MUX_GMAC123_TO_USXGMII_BIT, + + /* PATH BITS */ + MTK_ETH_PATH_GMAC1_RGMII_BIT, +@@ -1011,13 +1024,18 @@ enum mkt_eth_capabilities { + MTK_ETH_PATH_GMAC2_SGMII_BIT, + MTK_ETH_PATH_GMAC2_2P5GPHY_BIT, + MTK_ETH_PATH_GMAC2_GEPHY_BIT, ++ MTK_ETH_PATH_GMAC3_SGMII_BIT, + MTK_ETH_PATH_GDM1_ESW_BIT, ++ MTK_ETH_PATH_GMAC1_USXGMII_BIT, ++ MTK_ETH_PATH_GMAC2_USXGMII_BIT, ++ MTK_ETH_PATH_GMAC3_USXGMII_BIT, + }; + + /* Supported hardware group on SoCs */ + #define MTK_RGMII BIT_ULL(MTK_RGMII_BIT) + #define MTK_TRGMII BIT_ULL(MTK_TRGMII_BIT) + #define MTK_SGMII BIT_ULL(MTK_SGMII_BIT) ++#define MTK_USXGMII BIT_ULL(MTK_USXGMII_BIT) + #define MTK_2P5GPHY BIT_ULL(MTK_2P5GPHY_BIT) + #define MTK_ESW BIT_ULL(MTK_ESW_BIT) + #define MTK_GEPHY BIT_ULL(MTK_GEPHY_BIT) +@@ -1047,6 +1065,10 @@ enum mkt_eth_capabilities { + BIT_ULL(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT) + #define MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII \ + BIT_ULL(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT) ++#define MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII \ ++ BIT_ULL(MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII_BIT) ++#define MTK_ETH_MUX_GMAC123_TO_USXGMII \ ++ BIT_ULL(MTK_ETH_MUX_GMAC123_TO_USXGMII_BIT) + + /* Supported path present on SoCs */ + #define MTK_ETH_PATH_GMAC1_RGMII BIT_ULL(MTK_ETH_PATH_GMAC1_RGMII_BIT) +@@ -1056,7 +1078,11 @@ enum mkt_eth_capabilities { + #define MTK_ETH_PATH_GMAC2_SGMII BIT_ULL(MTK_ETH_PATH_GMAC2_SGMII_BIT) + #define MTK_ETH_PATH_GMAC2_2P5GPHY BIT_ULL(MTK_ETH_PATH_GMAC2_2P5GPHY_BIT) + #define MTK_ETH_PATH_GMAC2_GEPHY BIT_ULL(MTK_ETH_PATH_GMAC2_GEPHY_BIT) ++#define MTK_ETH_PATH_GMAC3_SGMII BIT_ULL(MTK_ETH_PATH_GMAC3_SGMII_BIT) + #define MTK_ETH_PATH_GDM1_ESW BIT_ULL(MTK_ETH_PATH_GDM1_ESW_BIT) ++#define MTK_ETH_PATH_GMAC1_USXGMII BIT_ULL(MTK_ETH_PATH_GMAC1_USXGMII_BIT) ++#define MTK_ETH_PATH_GMAC2_USXGMII BIT_ULL(MTK_ETH_PATH_GMAC2_USXGMII_BIT) ++#define MTK_ETH_PATH_GMAC3_USXGMII BIT_ULL(MTK_ETH_PATH_GMAC3_USXGMII_BIT) + + #define MTK_GMAC1_RGMII (MTK_ETH_PATH_GMAC1_RGMII | MTK_RGMII) + #define MTK_GMAC1_TRGMII (MTK_ETH_PATH_GMAC1_TRGMII | MTK_TRGMII) +@@ -1065,7 +1091,11 @@ enum mkt_eth_capabilities { + #define MTK_GMAC2_SGMII (MTK_ETH_PATH_GMAC2_SGMII | MTK_SGMII) + #define MTK_GMAC2_GEPHY (MTK_ETH_PATH_GMAC2_GEPHY | MTK_GEPHY) + #define MTK_GMAC2_2P5GPHY (MTK_ETH_PATH_GMAC2_2P5GPHY | MTK_2P5GPHY) ++#define MTK_GMAC3_SGMII (MTK_ETH_PATH_GMAC3_SGMII | MTK_SGMII) + #define MTK_GDM1_ESW (MTK_ETH_PATH_GDM1_ESW | MTK_ESW) ++#define MTK_GMAC1_USXGMII (MTK_ETH_PATH_GMAC1_USXGMII | MTK_USXGMII) ++#define MTK_GMAC2_USXGMII (MTK_ETH_PATH_GMAC2_USXGMII | MTK_USXGMII) ++#define MTK_GMAC3_USXGMII (MTK_ETH_PATH_GMAC3_USXGMII | MTK_USXGMII) + + /* MUXes present on SoCs */ + /* 0: GDM1 -> GMAC1, 1: GDM1 -> ESW */ +@@ -1092,6 +1122,12 @@ enum mkt_eth_capabilities { + #define MTK_MUX_GMAC12_TO_GEPHY_SGMII \ + (MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII | MTK_MUX) + ++#define MTK_MUX_GMAC123_TO_GEPHY_SGMII \ ++ (MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII | MTK_MUX) ++ ++#define MTK_MUX_GMAC123_TO_USXGMII \ ++ (MTK_ETH_MUX_GMAC123_TO_USXGMII | MTK_MUX | MTK_INFRA) ++ + #define MTK_HAS_CAPS(caps, _x) (((caps) & (_x)) == (_x)) + + #define MT7621_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | \ +@@ -1123,9 +1159,12 @@ enum mkt_eth_capabilities { + MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ + MTK_RSTCTRL_PPE1 | MTK_SRAM) + +-#define MT7988_CAPS (MTK_36BIT_DMA | MTK_GDM1_ESW | MTK_GMAC2_2P5GPHY | \ +- MTK_MUX_GMAC2_TO_2P5GPHY | MTK_QDMA | MTK_RSTCTRL_PPE1 | \ +- MTK_RSTCTRL_PPE2 | MTK_SRAM) ++#define MT7988_CAPS (MTK_36BIT_DMA | MTK_GDM1_ESW | MTK_GMAC1_SGMII | \ ++ MTK_GMAC2_2P5GPHY | MTK_GMAC2_SGMII | MTK_GMAC2_USXGMII | \ ++ MTK_GMAC3_SGMII | MTK_GMAC3_USXGMII | \ ++ MTK_MUX_GMAC123_TO_GEPHY_SGMII | \ ++ MTK_MUX_GMAC123_TO_USXGMII | MTK_MUX_GMAC2_TO_2P5GPHY | \ ++ MTK_QDMA | MTK_RSTCTRL_PPE1 | MTK_RSTCTRL_PPE2 | MTK_SRAM) + + struct mtk_tx_dma_desc_info { + dma_addr_t addr; +@@ -1372,6 +1411,8 @@ struct mtk_mac { + struct device_node *of_node; + struct phylink *phylink; + struct phylink_config phylink_config; ++ struct phylink_pcs *current_pcs; ++ struct phylink_pcs *available_pcs[2]; + struct mtk_eth *hw; + struct mtk_hw_stats *hw_stats; + __be32 hwlro_ip[MTK_MAX_LRO_IP_CNT]; +@@ -1506,6 +1547,7 @@ int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id); + int mtk_gmac_2p5gphy_path_setup(struct mtk_eth *eth, int mac_id); + int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id); + int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id); ++int mtk_gmac_usxgmii_path_setup(struct mtk_eth *eth, int mac_id); + + int mtk_eth_offload_init(struct mtk_eth *eth, u8 id); + int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type, +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0052-net-phylink-keep-and-use-MAC-supported_interfaces-in.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0052-net-phylink-keep-and-use-MAC-supported_interfaces-in.patch new file mode 100644 index 0000000000..3517db358b --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0052-net-phylink-keep-and-use-MAC-supported_interfaces-in.patch @@ -0,0 +1,108 @@ +From 7d9a25bf143c3edee1ad46a57ac64acc0c49316d Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 7 Apr 2025 00:13:55 +0200 +Subject: [PATCH 52/84] net: phylink: keep and use MAC supported_interfaces in + phylink struct + +Add in phylink struct a copy of supported_interfaces from phylink_config +and make use of that instead of relying on phylink_config value. + +This in preparation for support of PCS handling internally to phylink +where a PCS can be removed or added after the phylink is created and we +need both a reference of the supported_interfaces value from +phylink_config and an internal value that can be updated with the new +PCS info. + +Signed-off-by: Christian Marangi +--- + drivers/net/phy/phylink.c | 22 +++++++++++++++------- + 1 file changed, 15 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c +index 229a503d601e..a0cfa49fe84c 100644 +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -59,6 +59,11 @@ struct phylink { + /* The link configuration settings */ + struct phylink_link_state link_config; + ++ /* What interface are supported by the current link. ++ * Can change on removal or addition of new PCS. ++ */ ++ DECLARE_PHY_INTERFACE_MASK(supported_interfaces); ++ + /* The current settings */ + phy_interface_t cur_interface; + +@@ -612,7 +617,7 @@ static int phylink_validate_mask(struct phylink *pl, struct phy_device *phy, + static int phylink_validate(struct phylink *pl, unsigned long *supported, + struct phylink_link_state *state) + { +- const unsigned long *interfaces = pl->config->supported_interfaces; ++ const unsigned long *interfaces = pl->supported_interfaces; + + if (state->interface == PHY_INTERFACE_MODE_NA) + return phylink_validate_mask(pl, NULL, supported, state, +@@ -1825,6 +1830,9 @@ struct phylink *phylink_create(struct phylink_config *config, + mutex_init(&pl->state_mutex); + INIT_WORK(&pl->resolve, phylink_resolve); + ++ phy_interface_copy(pl->supported_interfaces, ++ config->supported_interfaces); ++ + pl->config = config; + if (config->type == PHYLINK_NETDEV) { + pl->netdev = to_net_dev(config->dev); +@@ -1983,7 +1991,7 @@ static int phylink_validate_phy(struct phylink *pl, struct phy_device *phy, + * those which the host supports. + */ + phy_interface_and(interfaces, phy->possible_interfaces, +- pl->config->supported_interfaces); ++ pl->supported_interfaces); + + if (phy_interface_empty(interfaces)) { + phylink_err(pl, "PHY has no common interfaces\n"); +@@ -2706,12 +2714,12 @@ static phy_interface_t phylink_sfp_select_interface(struct phylink *pl, + return interface; + } + +- if (!test_bit(interface, pl->config->supported_interfaces)) { ++ if (!test_bit(interface, pl->supported_interfaces)) { + phylink_err(pl, + "selection of interface failed, SFP selected %s (%u) but MAC supports %*pbl\n", + phy_modes(interface), interface, + (int)PHY_INTERFACE_MODE_MAX, +- pl->config->supported_interfaces); ++ pl->supported_interfaces); + return PHY_INTERFACE_MODE_NA; + } + +@@ -3598,14 +3606,14 @@ static int phylink_sfp_config_optical(struct phylink *pl) + + phylink_dbg(pl, "optical SFP: interfaces=[mac=%*pbl, sfp=%*pbl]\n", + (int)PHY_INTERFACE_MODE_MAX, +- pl->config->supported_interfaces, ++ pl->supported_interfaces, + (int)PHY_INTERFACE_MODE_MAX, + pl->sfp_interfaces); + + /* Find the union of the supported interfaces by the PCS/MAC and + * the SFP module. + */ +- phy_interface_and(interfaces, pl->config->supported_interfaces, ++ phy_interface_and(interfaces, pl->supported_interfaces, + pl->sfp_interfaces); + if (phy_interface_empty(interfaces)) { + phylink_err(pl, "unsupported SFP module: no common interface modes\n"); +@@ -3751,7 +3759,7 @@ static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy) + + /* Set the PHY's host supported interfaces */ + phy_interface_and(phy->host_interfaces, phylink_sfp_interfaces, +- pl->config->supported_interfaces); ++ pl->supported_interfaces); + + /* Do the initial configuration */ + return phylink_sfp_config_phy(pl, phy); +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0053-net-phy-introduce-phy_interface_copy-helper.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0053-net-phy-introduce-phy_interface_copy-helper.patch new file mode 100644 index 0000000000..f8eb386bbf --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0053-net-phy-introduce-phy_interface_copy-helper.patch @@ -0,0 +1,36 @@ +From 8ba5b5a70e5c337ecbb42de895dc06c50f129de3 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 7 Apr 2025 00:13:56 +0200 +Subject: [PATCH 53/84] net: phy: introduce phy_interface_copy helper + +Introduce phy_interface_copy helper as a shorthand to copy the PHY +interface bitmap to a different location. + +This is useful if a PHY interface bitmap needs to be stored in a +different variable and needs to be reset to an original value saved in a +different bitmap. + +Signed-off-by: Christian Marangi +--- + include/linux/phy.h | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/include/linux/phy.h b/include/linux/phy.h +index e194dad1623d..6e09b2290726 100644 +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -173,6 +173,11 @@ static inline void phy_interface_or(unsigned long *dst, const unsigned long *a, + bitmap_or(dst, a, b, PHY_INTERFACE_MODE_MAX); + } + ++static inline void phy_interface_copy(unsigned long *dst, const unsigned long *src) ++{ ++ bitmap_copy(dst, src, PHY_INTERFACE_MODE_MAX); ++} ++ + static inline void phy_interface_set_rgmii(unsigned long *intf) + { + __set_bit(PHY_INTERFACE_MODE_RGMII, intf); +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0054-net-phylink-introduce-internal-phylink-PCS-handling.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0054-net-phylink-introduce-internal-phylink-PCS-handling.patch new file mode 100644 index 0000000000..28dc27d7a6 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0054-net-phylink-introduce-internal-phylink-PCS-handling.patch @@ -0,0 +1,388 @@ +From 5515ca927f396489c7bc2224289777e60295e0f0 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 7 Apr 2025 00:13:57 +0200 +Subject: [PATCH 54/84] net: phylink: introduce internal phylink PCS handling + +Introduce internal handling of PCS for phylink. This is an alternative +to .mac_select_pcs that moves the selection logic of the PCS entirely to +phylink with the usage of supported_interface value in the PCS struct. + +MAC should now provide an array of available PCS in phylink_config in +.available_pcs and fill the .num_available_pcs with the number of +elements in the array. MAC should also define a new bitmap, +pcs_interfaces, in phylink_config to define for what interface mode a +dedicated PCS is required. + +On phylink_create() this array is parsed and a linked list of PCS is +created based on the PCS passed in phylink_config. +Also the supported_interface value in phylink struct is updated with the +new supported_interface from the provided PCS. + +On phylink_start() every PCS in phylink PCS list gets attached to the +phylink instance. This is done by setting the phylink value in +phylink_pcs struct to the phylink instance. + +On phylink_stop(), every PCS in phylink PCS list is detached from the +phylink instance. This is done by setting the phylink value in +phylink_pcs struct to NULL. + +On phylink_stop(), every PCS in phylink PCS list is removed from the +list. + +phylink_validate_mac_and_pcs(), phylink_major_config() and +phylink_inband_caps() are updated to support this new implementation +with the PCS list stored in phylink. + +They will make use of phylink_validate_pcs_interface() that will loop +for every PCS in the phylink PCS available list and find one that supports +the passed interface. + +phylink_validate_pcs_interface() apply the same logic of .mac_select_pcs +where if a supported_interface value is not set for the PCS struct, then +it's assumed every interface is supported. + +It's required for a MAC that implement either a .mac_select_pcs or make +use of the PCS list implementation. Implementing both will result in a fail +on MAC/PCS validation. + +phylink value in phylink_pcs struct with this implementation is used to +track from PCS side when it's attached to a phylink instance. PCS driver +will make use of this information to correctly detach from a phylink +instance if needed. + +The .mac_select_pcs implementation is not changed but it's expected that +every MAC driver migrates to the new implementation to later deprecate +and remove .mac_select_pcs. + +Signed-off-by: Christian Marangi +--- + drivers/net/phy/phylink.c | 147 +++++++++++++++++++++++++++++++++----- + include/linux/phylink.h | 10 +++ + 2 files changed, 139 insertions(+), 18 deletions(-) + +diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c +index a0cfa49fe84c..8539519536b2 100644 +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -59,6 +59,9 @@ struct phylink { + /* The link configuration settings */ + struct phylink_link_state link_config; + ++ /* List of available PCS */ ++ struct list_head pcs_list; ++ + /* What interface are supported by the current link. + * Can change on removal or addition of new PCS. + */ +@@ -146,6 +149,8 @@ static const phy_interface_t phylink_sfp_interface_preference[] = { + + static DECLARE_PHY_INTERFACE_MASK(phylink_sfp_interfaces); + ++static void phylink_run_resolve(struct phylink *pl); ++ + /** + * phylink_set_port_modes() - set the port type modes in the ethtool mask + * @mask: ethtool link mode mask +@@ -501,22 +506,59 @@ static void phylink_validate_mask_caps(unsigned long *supported, + linkmode_and(state->advertising, state->advertising, mask); + } + ++static int phylink_validate_pcs_interface(struct phylink_pcs *pcs, ++ phy_interface_t interface) ++{ ++ /* If PCS define an empty supported_interfaces value, assume ++ * all interface are supported. ++ */ ++ if (phy_interface_empty(pcs->supported_interfaces)) ++ return 0; ++ ++ /* Ensure that this PCS supports the interface mode */ ++ if (!test_bit(interface, pcs->supported_interfaces)) ++ return -EINVAL; ++ ++ return 0; ++} ++ + static int phylink_validate_mac_and_pcs(struct phylink *pl, + unsigned long *supported, + struct phylink_link_state *state) + { +- struct phylink_pcs *pcs = NULL; + unsigned long capabilities; ++ struct phylink_pcs *pcs; ++ bool pcs_found = false; + int ret; + + /* Get the PCS for this interface mode */ + if (pl->mac_ops->mac_select_pcs) { ++ /* Make sure either PCS internal validation or .mac_select_pcs ++ * is used. Return error if both are defined. ++ */ ++ if (!list_empty(&pl->pcs_list)) { ++ phylink_err(pl, "either phylink_pcs_add() or .mac_select_pcs must be used\n"); ++ return -EINVAL; ++ } ++ + pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface); + if (IS_ERR(pcs)) + return PTR_ERR(pcs); ++ ++ pcs_found = !!pcs; ++ } else { ++ /* Check every assigned PCS and search for one that supports ++ * the interface. ++ */ ++ list_for_each_entry(pcs, &pl->pcs_list, list) { ++ if (!phylink_validate_pcs_interface(pcs, state->interface)) { ++ pcs_found = true; ++ break; ++ } ++ } + } + +- if (pcs) { ++ if (pcs_found) { + /* The PCS, if present, must be setup before phylink_create() + * has been called. If the ops is not initialised, print an + * error and backtrace rather than oopsing the kernel. +@@ -528,13 +570,10 @@ static int phylink_validate_mac_and_pcs(struct phylink *pl, + return -EINVAL; + } + +- /* Ensure that this PCS supports the interface which the MAC +- * returned it for. It is an error for the MAC to return a PCS +- * that does not support the interface mode. +- */ +- if (!phy_interface_empty(pcs->supported_interfaces) && +- !test_bit(state->interface, pcs->supported_interfaces)) { +- phylink_err(pl, "MAC returned PCS which does not support %s\n", ++ /* Recheck PCS to handle legacy way for .mac_select_pcs */ ++ ret = phylink_validate_pcs_interface(pcs, state->interface); ++ if (ret) { ++ phylink_err(pl, "selected PCS does not support %s\n", + phy_modes(state->interface)); + return -EINVAL; + } +@@ -939,12 +978,22 @@ static unsigned int phylink_inband_caps(struct phylink *pl, + phy_interface_t interface) + { + struct phylink_pcs *pcs; ++ bool pcs_found = false; + +- if (!pl->mac_ops->mac_select_pcs) +- return 0; ++ if (pl->mac_ops->mac_select_pcs) { ++ pcs = pl->mac_ops->mac_select_pcs(pl->config, ++ interface); ++ pcs_found = !!pcs; ++ } else { ++ list_for_each_entry(pcs, &pl->pcs_list, list) { ++ if (!phylink_validate_pcs_interface(pcs, interface)) { ++ pcs_found = true; ++ break; ++ } ++ } ++ } + +- pcs = pl->mac_ops->mac_select_pcs(pl->config, interface); +- if (!pcs) ++ if (!pcs_found) + return 0; + + return phylink_pcs_inband_caps(pcs, interface); +@@ -1230,10 +1279,36 @@ static void phylink_major_config(struct phylink *pl, bool restart, + pl->major_config_failed = true; + return; + } ++ /* Find a PCS in available PCS list for the requested interface. ++ * This doesn't overwrite the previous .mac_select_pcs as either ++ * .mac_select_pcs or PCS list implementation are permitted. ++ * ++ * Skip searching if the MAC doesn't require a dedicaed PCS for ++ * the requested interface. ++ */ ++ } else if (test_bit(state->interface, pl->config->pcs_interfaces)) { ++ bool pcs_found = false; ++ ++ list_for_each_entry(pcs, &pl->pcs_list, list) { ++ if (!phylink_validate_pcs_interface(pcs, ++ state->interface)) { ++ pcs_found = true; ++ break; ++ } ++ } ++ ++ if (!pcs_found) { ++ phylink_err(pl, ++ "couldn't find a PCS for %s\n", ++ phy_modes(state->interface)); + +- pcs_changed = pl->pcs != pcs; ++ pl->major_config_failed = true; ++ return; ++ } + } + ++ pcs_changed = pl->pcs != pcs; ++ + phylink_pcs_neg_mode(pl, pcs, state->interface, state->advertising); + + phylink_dbg(pl, "major config, active %s/%s/%s\n", +@@ -1260,10 +1335,12 @@ static void phylink_major_config(struct phylink *pl, bool restart, + if (pcs_changed) { + phylink_pcs_disable(pl->pcs); + +- if (pl->pcs) +- pl->pcs->phylink = NULL; ++ if (pl->mac_ops->mac_select_pcs) { ++ if (pl->pcs) ++ pl->pcs->phylink = NULL; + +- pcs->phylink = pl; ++ pcs->phylink = pl; ++ } + + pl->pcs = pcs; + } +@@ -1812,8 +1889,9 @@ struct phylink *phylink_create(struct phylink_config *config, + phy_interface_t iface, + const struct phylink_mac_ops *mac_ops) + { ++ struct phylink_pcs *pcs; + struct phylink *pl; +- int ret; ++ int i, ret; + + /* Validate the supplied configuration */ + if (phy_interface_empty(config->supported_interfaces)) { +@@ -1829,9 +1907,21 @@ struct phylink *phylink_create(struct phylink_config *config, + mutex_init(&pl->phydev_mutex); + mutex_init(&pl->state_mutex); + INIT_WORK(&pl->resolve, phylink_resolve); ++ INIT_LIST_HEAD(&pl->pcs_list); ++ ++ /* Fill the PCS list with available PCS from phylink config */ ++ for (i = 0; i < config->num_available_pcs; i++) { ++ pcs = config->available_pcs[i]; ++ ++ list_add(&pcs->list, &pl->pcs_list); ++ } + + phy_interface_copy(pl->supported_interfaces, + config->supported_interfaces); ++ list_for_each_entry(pcs, &pl->pcs_list, list) ++ phy_interface_or(pl->supported_interfaces, ++ pl->supported_interfaces, ++ pcs->supported_interfaces); + + pl->config = config; + if (config->type == PHYLINK_NETDEV) { +@@ -1910,10 +2000,16 @@ EXPORT_SYMBOL_GPL(phylink_create); + */ + void phylink_destroy(struct phylink *pl) + { ++ struct phylink_pcs *pcs, *tmp; ++ + sfp_bus_del_upstream(pl->sfp_bus); + if (pl->link_gpio) + gpiod_put(pl->link_gpio); + ++ /* Remove every PCS from phylink PCS list */ ++ list_for_each_entry_safe(pcs, tmp, &pl->pcs_list, list) ++ list_del(&pcs->list); ++ + cancel_work_sync(&pl->resolve); + kfree(pl); + } +@@ -2396,6 +2492,7 @@ static irqreturn_t phylink_link_handler(int irq, void *data) + */ + void phylink_start(struct phylink *pl) + { ++ struct phylink_pcs *pcs; + bool poll = false; + + ASSERT_RTNL(); +@@ -2422,6 +2519,10 @@ void phylink_start(struct phylink *pl) + + pl->pcs_state = PCS_STATE_STARTED; + ++ /* link available PCS to phylink struct */ ++ list_for_each_entry(pcs, &pl->pcs_list, list) ++ pcs->phylink = pl; ++ + phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_STOPPED); + + if (pl->cfg_link_an_mode == MLO_AN_FIXED && pl->link_gpio) { +@@ -2466,6 +2567,8 @@ EXPORT_SYMBOL_GPL(phylink_start); + */ + void phylink_stop(struct phylink *pl) + { ++ struct phylink_pcs *pcs; ++ + ASSERT_RTNL(); + + if (pl->sfp_bus) +@@ -2483,6 +2586,14 @@ void phylink_stop(struct phylink *pl) + pl->pcs_state = PCS_STATE_DOWN; + + phylink_pcs_disable(pl->pcs); ++ ++ /* Drop link between phylink and PCS */ ++ list_for_each_entry(pcs, &pl->pcs_list, list) ++ pcs->phylink = NULL; ++ ++ /* Restore original supported interfaces */ ++ phy_interface_copy(pl->supported_interfaces, ++ pl->config->supported_interfaces); + } + EXPORT_SYMBOL_GPL(phylink_stop); + +diff --git a/include/linux/phylink.h b/include/linux/phylink.h +index 30659b615fca..ef0b5a0729c8 100644 +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -150,12 +150,16 @@ enum phylink_op_type { + * if MAC link is at %MLO_AN_FIXED mode. + * @supported_interfaces: bitmap describing which PHY_INTERFACE_MODE_xxx + * are supported by the MAC/PCS. ++ * @pcs_interfaces: bitmap describing for which PHY_INTERFACE_MODE_xxx a ++ * dedicated PCS is required. + * @lpi_interfaces: bitmap describing which PHY interface modes can support + * LPI signalling. + * @mac_capabilities: MAC pause/speed/duplex capabilities. + * @lpi_capabilities: MAC speeds which can support LPI signalling + * @lpi_timer_default: Default EEE LPI timer setting. + * @eee_enabled_default: If set, EEE will be enabled by phylink at creation time ++ * @available_pcs: array of available phylink_pcs PCS ++ * @num_available_pcs: num of available phylink_pcs PCS + */ + struct phylink_config { + struct device *dev; +@@ -168,11 +172,14 @@ struct phylink_config { + void (*get_fixed_state)(struct phylink_config *config, + struct phylink_link_state *state); + DECLARE_PHY_INTERFACE_MASK(supported_interfaces); ++ DECLARE_PHY_INTERFACE_MASK(pcs_interfaces); + DECLARE_PHY_INTERFACE_MASK(lpi_interfaces); + unsigned long mac_capabilities; + unsigned long lpi_capabilities; + u32 lpi_timer_default; + bool eee_enabled_default; ++ struct phylink_pcs **available_pcs; ++ unsigned int num_available_pcs; + }; + + void phylink_limit_mac_speed(struct phylink_config *config, u32 max_speed); +@@ -469,6 +476,9 @@ struct phylink_pcs { + struct phylink *phylink; + bool poll; + bool rxc_always_on; ++ ++ /* private: */ ++ struct list_head list; + }; + + /** +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0055-net-phylink-add-phylink_release_pcs-to-externally-re.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0055-net-phylink-add-phylink_release_pcs-to-externally-re.patch new file mode 100644 index 0000000000..e6c517471b --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0055-net-phylink-add-phylink_release_pcs-to-externally-re.patch @@ -0,0 +1,142 @@ +From b9b90aa82fedf47b035bc1f7196037e0cb481e41 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 7 Apr 2025 00:13:58 +0200 +Subject: [PATCH 55/84] net: phylink: add phylink_release_pcs() to externally + release a PCS + +Add phylink_release_pcs() to externally release a PCS from a phylink +instance. This can be used to handle case when a single PCS needs to be +removed and the phylink instance needs to be refreshed. + +On calling phylink_release_pcs(), the PCS will be removed from the +phylink internal PCS list and the phylink supported_interfaces value is +reparsed with the remaining PCS interfaces. + +Also a phylink resolve is triggered to handle the PCS removal. + +It's also added to phylink a flag to make phylink resolve reconfigure +the interface mode (even if it didn't change). This is needed to handle +the special case when the current PCS used by phylink is removed and a +major_config is needed to propagae the configuration change. With this +option enabled we also force mac_config even if the PHY link is not up +for the in-band case. + +Signed-off-by: Christian Marangi +--- + drivers/net/phy/phylink.c | 58 ++++++++++++++++++++++++++++++++++++++- + include/linux/phylink.h | 2 ++ + 2 files changed, 59 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c +index 8539519536b2..ef393e49a314 100644 +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -86,6 +86,7 @@ struct phylink { + bool link_failed; + bool suspend_link_up; + bool major_config_failed; ++ bool reconfig_interface; + bool mac_supports_eee_ops; + bool mac_supports_eee; + bool phy_enable_tx_lpi; +@@ -897,6 +898,55 @@ static void phylink_resolve_an_pause(struct phylink_link_state *state) + } + } + ++/** ++ * phylink_release_pcs - Removes a PCS from the phylink PCS available list ++ * @pcs: a pointer to the phylink_pcs struct to be released ++ * ++ * This function release a PCS from the phylink PCS available list if ++ * actually in use. It also refreshes the supported interfaces of the ++ * phylink instance by copying the supported interfaces from the phylink ++ * conf and merging the supported interfaces of the remaining available PCS ++ * in the list and trigger a resolve. ++ */ ++void phylink_release_pcs(struct phylink_pcs *pcs) ++{ ++ struct phylink *pl; ++ ++ ASSERT_RTNL(); ++ ++ pl = pcs->phylink; ++ if (!pl) ++ return; ++ ++ list_del(&pcs->list); ++ pcs->phylink = NULL; ++ ++ /* Check if we are removing the PCS currently ++ * in use by phylink. If this is the case, ++ * force phylink resolve to reconfigure the interface ++ * mode and set the phylink PCS to NULL. ++ */ ++ if (pl->pcs == pcs) { ++ mutex_lock(&pl->state_mutex); ++ ++ pl->reconfig_interface = true; ++ pl->pcs = NULL; ++ ++ mutex_unlock(&pl->state_mutex); ++ } ++ ++ /* Refresh supported interfaces */ ++ phy_interface_copy(pl->supported_interfaces, ++ pl->config->supported_interfaces); ++ list_for_each_entry(pcs, &pl->pcs_list, list) ++ phy_interface_or(pl->supported_interfaces, ++ pl->supported_interfaces, ++ pcs->supported_interfaces); ++ ++ phylink_run_resolve(pl); ++} ++EXPORT_SYMBOL_GPL(phylink_release_pcs); ++ + static unsigned int phylink_pcs_inband_caps(struct phylink_pcs *pcs, + phy_interface_t interface) + { +@@ -1700,6 +1750,10 @@ static void phylink_resolve(struct work_struct *w) + if (phy) + link_state.link &= pl->phy_state.link; + ++ /* Force mac_config if we need to reconfig the interface */ ++ if (pl->reconfig_interface) ++ mac_config = true; ++ + /* Only update if the PHY link is up */ + if (phy && pl->phy_state.link) { + /* If the interface has changed, force a link down +@@ -1734,7 +1788,8 @@ static void phylink_resolve(struct work_struct *w) + phylink_apply_manual_flow(pl, &link_state); + + if (mac_config) { +- if (link_state.interface != pl->link_config.interface) { ++ if (link_state.interface != pl->link_config.interface || ++ pl->reconfig_interface) { + /* The interface has changed, force the link down and + * then reconfigure. + */ +@@ -1744,6 +1799,7 @@ static void phylink_resolve(struct work_struct *w) + } + phylink_major_config(pl, false, &link_state); + pl->link_config.interface = link_state.interface; ++ pl->reconfig_interface = false; + } + } + +diff --git a/include/linux/phylink.h b/include/linux/phylink.h +index ef0b5a0729c8..c5496c063b6a 100644 +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -717,6 +717,8 @@ void phylink_disconnect_phy(struct phylink *); + int phylink_set_fixed_link(struct phylink *, + const struct phylink_link_state *); + ++void phylink_release_pcs(struct phylink_pcs *pcs); ++ + void phylink_mac_change(struct phylink *, bool up); + void phylink_pcs_change(struct phylink_pcs *, bool up); + +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0056-net-pcs-implement-Firmware-node-support-for-PCS-driv.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0056-net-pcs-implement-Firmware-node-support-for-PCS-driv.patch new file mode 100644 index 0000000000..06d310ccef --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0056-net-pcs-implement-Firmware-node-support-for-PCS-driv.patch @@ -0,0 +1,401 @@ +From 05d36511b44291340cdb31205d39b3e53ab56e04 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 7 Apr 2025 00:13:59 +0200 +Subject: [PATCH 56/84] net: pcs: implement Firmware node support for PCS + driver + +Implement the foundation of Firmware node support for PCS driver. + +To support this, implement a simple Provider API where a PCS driver can +expose multiple PCS with an xlate .get function. + +PCS driver will have to call fwnode_pcs_add_provider() and pass the +firmware node pointer and a xlate function to return the correct PCS for +the passed #pcs-cells. + +This will register the PCS in a global list of providers so that +consumer can access it. + +Consumer will then use fwnode_pcs_get() to get the actual PCS by passing +the firmware node pointer and the index for #pcs-cells. + +For simple implementation where #pcs-cells is 0 and the PCS driver +expose a single PCS, the xlate function fwnode_pcs_simple_get() is +provided. + +For advanced implementation a custom xlate function is required. + +PCS driver on removal should first delete as a provider with +the usage of fwnode_pcs_del_provider() and then call +phylink_release_pcs() on every PCS the driver provides and + +A generic function fwnode_phylink_pcs_parse() is provided for any MAC +driver that will declare PCS in DT (or ACPI). +This function will parse "pcs-handle" property and fill the passed array +with the parsed PCS in availabel_pcs up to the passed num_pcs value. +It's also possible to pass NULL as array to only parse the PCS and +update the num_pcs value with the count of scanned PCS. + +Co-developed-by: Daniel Golle +Signed-off-by: Daniel Golle +Signed-off-by: Christian Marangi +--- + drivers/net/pcs/Kconfig | 7 ++ + drivers/net/pcs/Makefile | 1 + + drivers/net/pcs/pcs.c | 201 +++++++++++++++++++++++++++++++ + include/linux/pcs/pcs-provider.h | 41 +++++++ + include/linux/pcs/pcs.h | 56 +++++++++ + 5 files changed, 306 insertions(+) + create mode 100644 drivers/net/pcs/pcs.c + create mode 100644 include/linux/pcs/pcs-provider.h + create mode 100644 include/linux/pcs/pcs.h + +diff --git a/drivers/net/pcs/Kconfig b/drivers/net/pcs/Kconfig +index f6aa437473de..2951aa2f4cda 100644 +--- a/drivers/net/pcs/Kconfig ++++ b/drivers/net/pcs/Kconfig +@@ -5,6 +5,13 @@ + + menu "PCS device drivers" + ++config FWNODE_PCS ++ tristate ++ depends on (ACPI || OF) ++ depends on PHYLINK ++ help ++ Firmware node PCS accessors ++ + config PCS_XPCS + tristate "Synopsys DesignWare Ethernet XPCS" + select PHYLINK +diff --git a/drivers/net/pcs/Makefile b/drivers/net/pcs/Makefile +index 4f7920618b90..3005cdd89ab7 100644 +--- a/drivers/net/pcs/Makefile ++++ b/drivers/net/pcs/Makefile +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + # Makefile for Linux PCS drivers + ++obj-$(CONFIG_FWNODE_PCS) += pcs.o + pcs_xpcs-$(CONFIG_PCS_XPCS) := pcs-xpcs.o pcs-xpcs-plat.o \ + pcs-xpcs-nxp.o pcs-xpcs-wx.o + +diff --git a/drivers/net/pcs/pcs.c b/drivers/net/pcs/pcs.c +new file mode 100644 +index 000000000000..14a5cd3eeda1 +--- /dev/null ++++ b/drivers/net/pcs/pcs.c +@@ -0,0 +1,201 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++ ++#include ++#include ++#include ++#include ++#include ++ ++MODULE_DESCRIPTION("PCS library"); ++MODULE_AUTHOR("Christian Marangi "); ++MODULE_LICENSE("GPL"); ++ ++struct fwnode_pcs_provider { ++ struct list_head link; ++ ++ struct fwnode_handle *fwnode; ++ struct phylink_pcs *(*get)(struct fwnode_reference_args *pcsspec, ++ void *data); ++ ++ void *data; ++}; ++ ++static LIST_HEAD(fwnode_pcs_providers); ++static DEFINE_MUTEX(fwnode_pcs_mutex); ++ ++struct phylink_pcs *fwnode_pcs_simple_get(struct fwnode_reference_args *pcsspec, ++ void *data) ++{ ++ return data; ++} ++EXPORT_SYMBOL_GPL(fwnode_pcs_simple_get); ++ ++int fwnode_pcs_add_provider(struct fwnode_handle *fwnode, ++ struct phylink_pcs *(*get)(struct fwnode_reference_args *pcsspec, ++ void *data), ++ void *data) ++{ ++ struct fwnode_pcs_provider *pp; ++ ++ if (!fwnode) ++ return 0; ++ ++ pp = kzalloc(sizeof(*pp), GFP_KERNEL); ++ if (!pp) ++ return -ENOMEM; ++ ++ pp->fwnode = fwnode_handle_get(fwnode); ++ pp->data = data; ++ pp->get = get; ++ ++ mutex_lock(&fwnode_pcs_mutex); ++ list_add(&pp->link, &fwnode_pcs_providers); ++ mutex_unlock(&fwnode_pcs_mutex); ++ pr_debug("Added pcs provider from %pfwf\n", fwnode); ++ ++ fwnode_dev_initialized(fwnode, true); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(fwnode_pcs_add_provider); ++ ++void fwnode_pcs_del_provider(struct fwnode_handle *fwnode) ++{ ++ struct fwnode_pcs_provider *pp; ++ ++ if (!fwnode) ++ return; ++ ++ mutex_lock(&fwnode_pcs_mutex); ++ list_for_each_entry(pp, &fwnode_pcs_providers, link) { ++ if (pp->fwnode == fwnode) { ++ list_del(&pp->link); ++ fwnode_dev_initialized(pp->fwnode, false); ++ fwnode_handle_put(pp->fwnode); ++ kfree(pp); ++ break; ++ } ++ } ++ mutex_unlock(&fwnode_pcs_mutex); ++} ++EXPORT_SYMBOL_GPL(fwnode_pcs_del_provider); ++ ++static int fwnode_parse_pcsspec(const struct fwnode_handle *fwnode, int index, ++ const char *name, ++ struct fwnode_reference_args *out_args) ++{ ++ int ret = -ENOENT; ++ ++ if (!fwnode) ++ return -ENOENT; ++ ++ if (name) ++ index = fwnode_property_match_string(fwnode, "pcs-names", ++ name); ++ ++ ret = fwnode_property_get_reference_args(fwnode, "pcs-handle", ++ "#pcs-cells", ++ -1, index, out_args); ++ if (ret || (name && index < 0)) ++ return ret; ++ ++ return 0; ++} ++ ++static struct phylink_pcs * ++fwnode_pcs_get_from_pcsspec(struct fwnode_reference_args *pcsspec) ++{ ++ struct fwnode_pcs_provider *provider; ++ struct phylink_pcs *pcs = ERR_PTR(-EPROBE_DEFER); ++ ++ if (!pcsspec) ++ return ERR_PTR(-EINVAL); ++ ++ mutex_lock(&fwnode_pcs_mutex); ++ list_for_each_entry(provider, &fwnode_pcs_providers, link) { ++ if (provider->fwnode == pcsspec->fwnode) { ++ pcs = provider->get(pcsspec, provider->data); ++ if (!IS_ERR(pcs)) ++ break; ++ } ++ } ++ mutex_unlock(&fwnode_pcs_mutex); ++ ++ return pcs; ++} ++ ++static struct phylink_pcs *__fwnode_pcs_get(struct fwnode_handle *fwnode, ++ int index, const char *con_id) ++{ ++ struct fwnode_reference_args pcsspec; ++ struct phylink_pcs *pcs; ++ int ret; ++ ++ ret = fwnode_parse_pcsspec(fwnode, index, con_id, &pcsspec); ++ if (ret) ++ return ERR_PTR(ret); ++ ++ pcs = fwnode_pcs_get_from_pcsspec(&pcsspec); ++ fwnode_handle_put(pcsspec.fwnode); ++ ++ return pcs; ++} ++ ++struct phylink_pcs *fwnode_pcs_get(struct fwnode_handle *fwnode, int index) ++{ ++ return __fwnode_pcs_get(fwnode, index, NULL); ++} ++EXPORT_SYMBOL_GPL(fwnode_pcs_get); ++ ++static int fwnode_phylink_pcs_count(struct fwnode_handle *fwnode, ++ unsigned int *num_pcs) ++{ ++ struct fwnode_reference_args out_args; ++ int index = 0; ++ int ret; ++ ++ while (true) { ++ ret = fwnode_property_get_reference_args(fwnode, "pcs-handle", ++ "#pcs-cells", ++ -1, index, &out_args); ++ /* We expect to reach an -ENOENT error while counting */ ++ if (ret) ++ break; ++ ++ fwnode_handle_put(out_args.fwnode); ++ index++; ++ } ++ ++ /* Update num_pcs with parsed PCS */ ++ *num_pcs = index; ++ ++ /* Return error if we didn't found any PCS */ ++ return index > 0 ? 0 : -ENOENT; ++} ++ ++int fwnode_phylink_pcs_parse(struct fwnode_handle *fwnode, ++ struct phylink_pcs **available_pcs, ++ unsigned int *num_pcs) ++{ ++ int i; ++ ++ if (!fwnode_property_present(fwnode, "pcs-handle")) ++ return -ENODEV; ++ ++ /* With available_pcs NULL, only count the PCS */ ++ if (!available_pcs) ++ return fwnode_phylink_pcs_count(fwnode, num_pcs); ++ ++ for (i = 0; i < *num_pcs; i++) { ++ struct phylink_pcs *pcs; ++ ++ pcs = fwnode_pcs_get(fwnode, i); ++ if (IS_ERR(pcs)) ++ return PTR_ERR(pcs); ++ ++ available_pcs[i] = pcs; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(fwnode_phylink_pcs_parse); +diff --git a/include/linux/pcs/pcs-provider.h b/include/linux/pcs/pcs-provider.h +new file mode 100644 +index 000000000000..2fcc1d696c97 +--- /dev/null ++++ b/include/linux/pcs/pcs-provider.h +@@ -0,0 +1,41 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++#ifndef __LINUX_PCS_PROVIDER_H ++#define __LINUX_PCS_PROVIDER_H ++ ++/** ++ * fwnode_pcs_simple_get - Simple xlate function to retrieve PCS ++ * @pcsspec: reference arguments ++ * @data: Context data (assumed assigned to the single PCS) ++ * ++ * Returns the PCS. (pointed by data) ++ */ ++struct phylink_pcs *fwnode_pcs_simple_get(struct fwnode_reference_args *pcsspec, ++ void *data); ++ ++/** ++ * fwnode_pcs_add_provider - Registers a new PCS provider ++ * @np: Firmware node ++ * @get: xlate function to retrieve the PCS ++ * @data: Context data ++ * ++ * Register and add a new PCS to the global providers list ++ * for the firmware node. A function to get the PCS from ++ * firmware node with the use fwnode reference arguments. ++ * To the get function is also passed the interface type ++ * requested for the PHY. PCS driver will use the passed ++ * interface to understand if the PCS can support it or not. ++ * ++ * Returns 0 on success or -ENOMEM on allocation failure. ++ */ ++int fwnode_pcs_add_provider(struct fwnode_handle *fwnode, ++ struct phylink_pcs *(*get)(struct fwnode_reference_args *pcsspec, ++ void *data), ++ void *data); ++ ++/** ++ * fwnode_pcs_del_provider - Removes a PCS provider ++ * @fwnode: Firmware node ++ */ ++void fwnode_pcs_del_provider(struct fwnode_handle *fwnode); ++ ++#endif /* __LINUX_PCS_PROVIDER_H */ +diff --git a/include/linux/pcs/pcs.h b/include/linux/pcs/pcs.h +new file mode 100644 +index 000000000000..c7a4d63bcd6d +--- /dev/null ++++ b/include/linux/pcs/pcs.h +@@ -0,0 +1,56 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++#ifndef __LINUX_PCS_H ++#define __LINUX_PCS_H ++ ++#include ++ ++#if IS_ENABLED(CONFIG_FWNODE_PCS) ++/** ++ * fwnode_pcs_get - Retrieves a PCS from a firmware node ++ * @fwnode: firmware node ++ * @index: index fwnode PCS handle in firmware node ++ * ++ * Get a PCS from the firmware node at index. ++ * ++ * Returns a pointer to the phylink_pcs or a negative ++ * error pointer. Can return -EPROBE_DEFER if the PCS is not ++ * present in global providers list (either due to driver ++ * still needs to be probed or it failed to probe/removed) ++ */ ++struct phylink_pcs *fwnode_pcs_get(struct fwnode_handle *fwnode, ++ int index); ++ ++/** ++ * fwnode_phylink_pcs_parse - generic PCS parse for fwnode PCS provider ++ * @fwnode: firmware node ++ * @available_pcs: pointer to preallocated array of PCS ++ * @num_pcs: where to store count of parsed PCS ++ * ++ * Generic helper function to fill available_pcs array with PCS parsed ++ * from a "pcs-handle" fwnode property defined in firmware node up to ++ * passed num_pcs. ++ * ++ * If available_pcs is NULL, num_pcs is updated with the count of the ++ * parsed PCS. ++ * ++ * Returns 0 or a negative error. ++ */ ++int fwnode_phylink_pcs_parse(struct fwnode_handle *fwnode, ++ struct phylink_pcs **available_pcs, ++ unsigned int *num_pcs); ++#else ++static inline struct phylink_pcs *fwnode_pcs_get(struct fwnode_handle *fwnode, ++ int index) ++{ ++ return ERR_PTR(-ENOENT); ++} ++ ++static inline int fwnode_phylink_pcs_parse(struct fwnode_handle *fwnode, ++ struct phylink_pcs **available_pcs, ++ unsigned int *num_pcs) ++{ ++ return -EOPNOTSUPP; ++} ++#endif ++ ++#endif /* __LINUX_PCS_H */ +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0057-net-phylink-support-late-PCS-provider-attach.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0057-net-phylink-support-late-PCS-provider-attach.patch new file mode 100644 index 0000000000..69610599a9 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0057-net-phylink-support-late-PCS-provider-attach.patch @@ -0,0 +1,263 @@ +From eb72f36586bb4c7f52180d6c3158e5a33de99c7f Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 7 Apr 2025 00:14:00 +0200 +Subject: [PATCH 57/84] net: phylink: support late PCS provider attach + +Add support in phylink for late PCS provider attach to a phylink +instance. This works by creating a global notifier for the PCS provider +and making each phylink instance that makes use of fwnode subscribe to +this notifier. + +The PCS notifier will emit the event FWNODE_PCS_PROVIDER_ADD every time +a new PCS provider is added. + +phylink will then react to this event and will call the new function +fwnode_phylink_pcs_get_from_fwnode() that will check if the PCS fwnode +provided by the event is present in the phy-handle property of the +phylink instance. + +If a related PCS is found, then such PCS is added to the phylink +instance PCS list. + +Then we link the PCS to the phylink instance if it's not disable and we +refresh the supported interfaces of the phylink instance. + +Finally we check if we are in a major_config_failed scenario and trigger +an interface reconfiguration in the next phylink resolve. + +If link was previously torn down due to removal of PCS, the link will be +established again as the PCS came back and is not available to phylink. + +Signed-off-by: Christian Marangi +--- + drivers/net/pcs/pcs.c | 34 +++++++++++++++++++++++++ + drivers/net/phy/phylink.c | 52 +++++++++++++++++++++++++++++++++++++++ + include/linux/pcs/pcs.h | 48 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 134 insertions(+) + +diff --git a/drivers/net/pcs/pcs.c b/drivers/net/pcs/pcs.c +index 14a5cd3eeda1..a7352effa92f 100644 +--- a/drivers/net/pcs/pcs.c ++++ b/drivers/net/pcs/pcs.c +@@ -22,6 +22,13 @@ struct fwnode_pcs_provider { + + static LIST_HEAD(fwnode_pcs_providers); + static DEFINE_MUTEX(fwnode_pcs_mutex); ++static BLOCKING_NOTIFIER_HEAD(fwnode_pcs_notify_list); ++ ++int register_fwnode_pcs_notifier(struct notifier_block *nb) ++{ ++ return blocking_notifier_chain_register(&fwnode_pcs_notify_list, nb); ++} ++EXPORT_SYMBOL_GPL(register_fwnode_pcs_notifier); + + struct phylink_pcs *fwnode_pcs_simple_get(struct fwnode_reference_args *pcsspec, + void *data) +@@ -55,6 +62,10 @@ int fwnode_pcs_add_provider(struct fwnode_handle *fwnode, + + fwnode_dev_initialized(fwnode, true); + ++ blocking_notifier_call_chain(&fwnode_pcs_notify_list, ++ FWNODE_PCS_PROVIDER_ADD, ++ fwnode); ++ + return 0; + } + EXPORT_SYMBOL_GPL(fwnode_pcs_add_provider); +@@ -147,6 +158,29 @@ struct phylink_pcs *fwnode_pcs_get(struct fwnode_handle *fwnode, int index) + } + EXPORT_SYMBOL_GPL(fwnode_pcs_get); + ++struct phylink_pcs * ++fwnode_phylink_pcs_get_from_fwnode(struct fwnode_handle *fwnode, ++ struct fwnode_handle *pcs_fwnode) ++{ ++ struct fwnode_reference_args pcsspec; ++ int i = 0; ++ int ret; ++ ++ while (true) { ++ ret = fwnode_parse_pcsspec(fwnode, i, NULL, &pcsspec); ++ if (ret) ++ break; ++ ++ if (pcsspec.fwnode == pcs_fwnode) ++ break; ++ ++ i++; ++ } ++ ++ return fwnode_pcs_get(fwnode, i); ++} ++EXPORT_SYMBOL_GPL(fwnode_phylink_pcs_get_from_fwnode); ++ + static int fwnode_phylink_pcs_count(struct fwnode_handle *fwnode, + unsigned int *num_pcs) + { +diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c +index ef393e49a314..409a5dbb1cfc 100644 +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -61,6 +62,7 @@ struct phylink { + + /* List of available PCS */ + struct list_head pcs_list; ++ struct notifier_block fwnode_pcs_nb; + + /* What interface are supported by the current link. + * Can change on removal or addition of new PCS. +@@ -1924,6 +1926,51 @@ int phylink_set_fixed_link(struct phylink *pl, + } + EXPORT_SYMBOL_GPL(phylink_set_fixed_link); + ++static int pcs_provider_notify(struct notifier_block *self, ++ unsigned long val, void *data) ++{ ++ struct phylink *pl = container_of(self, struct phylink, fwnode_pcs_nb); ++ struct fwnode_handle *pcs_fwnode = data; ++ struct phylink_pcs *pcs; ++ ++ /* Check if the just added PCS provider is ++ * in the phylink instance phy-handle property ++ */ ++ pcs = fwnode_phylink_pcs_get_from_fwnode(dev_fwnode(pl->config->dev), ++ pcs_fwnode); ++ if (IS_ERR(pcs)) ++ return NOTIFY_DONE; ++ ++ /* Add the PCS */ ++ rtnl_lock(); ++ ++ list_add(&pcs->list, &pl->pcs_list); ++ ++ /* Link phylink if we are started */ ++ if (!pl->phylink_disable_state) ++ pcs->phylink = pl; ++ ++ /* Refresh supported interfaces */ ++ phy_interface_copy(pl->supported_interfaces, ++ pl->config->supported_interfaces); ++ list_for_each_entry(pcs, &pl->pcs_list, list) ++ phy_interface_or(pl->supported_interfaces, ++ pl->supported_interfaces, ++ pcs->supported_interfaces); ++ ++ mutex_lock(&pl->state_mutex); ++ /* Force an interface reconfig if major config fail */ ++ if (pl->major_config_failed) ++ pl->reconfig_interface = true; ++ mutex_unlock(&pl->state_mutex); ++ ++ rtnl_unlock(); ++ ++ phylink_run_resolve(pl); ++ ++ return NOTIFY_OK; ++} ++ + /** + * phylink_create() - create a phylink instance + * @config: a pointer to the target &struct phylink_config +@@ -1979,6 +2026,11 @@ struct phylink *phylink_create(struct phylink_config *config, + pl->supported_interfaces, + pcs->supported_interfaces); + ++ if (!phy_interface_empty(config->pcs_interfaces)) { ++ pl->fwnode_pcs_nb.notifier_call = pcs_provider_notify; ++ register_fwnode_pcs_notifier(&pl->fwnode_pcs_nb); ++ } ++ + pl->config = config; + if (config->type == PHYLINK_NETDEV) { + pl->netdev = to_net_dev(config->dev); +diff --git a/include/linux/pcs/pcs.h b/include/linux/pcs/pcs.h +index c7a4d63bcd6d..480c155a3f03 100644 +--- a/include/linux/pcs/pcs.h ++++ b/include/linux/pcs/pcs.h +@@ -4,7 +4,24 @@ + + #include + ++enum fwnode_pcs_notify_event { ++ FWNODE_PCS_PROVIDER_ADD, ++}; ++ + #if IS_ENABLED(CONFIG_FWNODE_PCS) ++/** ++ * register_fwnode_pcs_notifier - Register a notifier block for fwnode ++ * PCS events ++ * @nb: pointer to the notifier block ++ * ++ * Registers a notifier block to the fwnode_pcs_notify_list blocking ++ * notifier chain. This allows phylink instance to subscribe for ++ * PCS provider events. ++ * ++ * Returns 0 or a negative error. ++ */ ++int register_fwnode_pcs_notifier(struct notifier_block *nb); ++ + /** + * fwnode_pcs_get - Retrieves a PCS from a firmware node + * @fwnode: firmware node +@@ -20,6 +37,25 @@ + struct phylink_pcs *fwnode_pcs_get(struct fwnode_handle *fwnode, + int index); + ++/** ++ * fwnode_phylink_pcs_get_from_fwnode - Retrieves the PCS provided ++ * by the firmware node from a ++ * firmware node ++ * @fwnode: firmware node ++ * @pcs_fwnode: PCS firmware node ++ * ++ * Parse 'pcs-handle' in 'fwnode' and get the PCS that match ++ * 'pcs_fwnode' firmware node. ++ * ++ * Returns a pointer to the phylink_pcs or a negative ++ * error pointer. Can return -EPROBE_DEFER if the PCS is not ++ * present in global providers list (either due to driver ++ * still needs to be probed or it failed to probe/removed) ++ */ ++struct phylink_pcs * ++fwnode_phylink_pcs_get_from_fwnode(struct fwnode_handle *fwnode, ++ struct fwnode_handle *pcs_fwnode); ++ + /** + * fwnode_phylink_pcs_parse - generic PCS parse for fwnode PCS provider + * @fwnode: firmware node +@@ -39,12 +75,24 @@ int fwnode_phylink_pcs_parse(struct fwnode_handle *fwnode, + struct phylink_pcs **available_pcs, + unsigned int *num_pcs); + #else ++static int register_fwnode_pcs_notifier(struct notifier_block *nb) ++{ ++ return -EOPNOTSUPP; ++} ++ + static inline struct phylink_pcs *fwnode_pcs_get(struct fwnode_handle *fwnode, + int index) + { + return ERR_PTR(-ENOENT); + } + ++static struct phylink_pcs * ++fwnode_phylink_pcs_get_from_fwnode(struct fwnode_handle *fwnode, ++ struct fwnode_handle *pcs_fwnode) ++{ ++ return ERR_PTR(-ENOENT); ++} ++ + static inline int fwnode_phylink_pcs_parse(struct fwnode_handle *fwnode, + struct phylink_pcs **available_pcs, + unsigned int *num_pcs) +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0058-dt-bindings-net-ethernet-controller-permit-to-define.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0058-dt-bindings-net-ethernet-controller-permit-to-define.patch new file mode 100644 index 0000000000..124dfd7185 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0058-dt-bindings-net-ethernet-controller-permit-to-define.patch @@ -0,0 +1,34 @@ +From 2f5f92f20fe06d54b826a446be6504063207f82b Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 7 Apr 2025 00:14:01 +0200 +Subject: [PATCH 58/84] dt-bindings: net: ethernet-controller: permit to define + multiple PCS + +Drop the limitation of a single PCS in pcs-handle property. Multiple PCS +can be defined for an ethrnet-controller node to support various PHY +interface mode type. + +It's very common for SoCs to have a dedicated PCS for SGMII mode and one +for USXGMII mode. + +Signed-off-by: Christian Marangi +--- + Documentation/devicetree/bindings/net/ethernet-controller.yaml | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/Documentation/devicetree/bindings/net/ethernet-controller.yaml b/Documentation/devicetree/bindings/net/ethernet-controller.yaml +index 7cbf11bbe99c..60605b34d242 100644 +--- a/Documentation/devicetree/bindings/net/ethernet-controller.yaml ++++ b/Documentation/devicetree/bindings/net/ethernet-controller.yaml +@@ -84,8 +84,6 @@ properties: + + pcs-handle: + $ref: /schemas/types.yaml#/definitions/phandle-array +- items: +- maxItems: 1 + description: + Specifies a reference to a node representing a PCS PHY device on a MDIO + bus to link with an external PHY (phy-handle) if exists. +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0059-net-pcs-airoha-add-PCS-driver-for-Airoha-SoC.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0059-net-pcs-airoha-add-PCS-driver-for-Airoha-SoC.patch new file mode 100644 index 0000000000..8c696e7f26 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0059-net-pcs-airoha-add-PCS-driver-for-Airoha-SoC.patch @@ -0,0 +1,2938 @@ +From 0b4dee7b6010c4b2c45ade25a2063cc5e7e3e631 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 7 Apr 2025 00:14:02 +0200 +Subject: [PATCH 59/84] net: pcs: airoha: add PCS driver for Airoha SoC + +Add PCS driver for Airoha SoC for Ethernet Serdes and PCS and permit +usage of external PHY or connected SFP cage. Supported modes are +USXGMII, 10-BASER, 2500BASE-X, 1000BASE-X and SGMII. + +The driver register as a PCS provider and supports poll mode to detect +PCS port state. While interrupt is supported by the HW, there are some +defect with the interrupt not fired on cable detach. + +The PCS require complex calibration to correctly work and might require +multiple try until the signal detection module "lock" on the signal +level to correct work with the attached PHY. + +Signed-off-by: Christian Marangi +--- + drivers/net/pcs/Kconfig | 7 + + drivers/net/pcs/Makefile | 1 + + drivers/net/pcs/pcs-airoha.c | 2855 ++++++++++++++++++++++++++++++++ + include/linux/pcs/pcs-airoha.h | 11 + + 4 files changed, 2874 insertions(+) + create mode 100644 drivers/net/pcs/pcs-airoha.c + create mode 100644 include/linux/pcs/pcs-airoha.h + +diff --git a/drivers/net/pcs/Kconfig b/drivers/net/pcs/Kconfig +index 2951aa2f4cda..69d28cd1e624 100644 +--- a/drivers/net/pcs/Kconfig ++++ b/drivers/net/pcs/Kconfig +@@ -12,6 +12,13 @@ config FWNODE_PCS + help + Firmware node PCS accessors + ++config PCS_AIROHA ++ select FWNODE_PCS ++ tristate "Airoha PCS driver" ++ help ++ This module provides helper to phylink for managing the Airoha ++ PCS for SoC Ethernet Serdes and PCS. ++ + config PCS_XPCS + tristate "Synopsys DesignWare Ethernet XPCS" + select PHYLINK +diff --git a/drivers/net/pcs/Makefile b/drivers/net/pcs/Makefile +index 3005cdd89ab7..c48450f08fb7 100644 +--- a/drivers/net/pcs/Makefile ++++ b/drivers/net/pcs/Makefile +@@ -2,6 +2,7 @@ + # Makefile for Linux PCS drivers + + obj-$(CONFIG_FWNODE_PCS) += pcs.o ++obj-$(CONFIG_PCS_AIROHA) += pcs-airoha.o + pcs_xpcs-$(CONFIG_PCS_XPCS) := pcs-xpcs.o pcs-xpcs-plat.o \ + pcs-xpcs-nxp.o pcs-xpcs-wx.o + +diff --git a/drivers/net/pcs/pcs-airoha.c b/drivers/net/pcs/pcs-airoha.c +new file mode 100644 +index 000000000000..945b959a4e26 +--- /dev/null ++++ b/drivers/net/pcs/pcs-airoha.c +@@ -0,0 +1,2855 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2024 AIROHA Inc ++ * Author: Christian Marangi ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* SCU*/ ++#define AIROHA_SCU_WAN_CONF 0x70 ++#define AIROHA_SCU_WAN_SEL GENMASK(7, 0) ++#define AIROHA_SCU_WAN_SEL_SGMII FIELD_PREP_CONST(AIROHA_SCU_WAN_SEL, 0x10) ++#define AIROHA_SCU_WAN_SEL_HSGMII FIELD_PREP_CONST(AIROHA_SCU_WAN_SEL, 0x11) ++#define AIROHA_SCU_WAN_SEL_USXGMII FIELD_PREP_CONST(AIROHA_SCU_WAN_SEL, 0x12) ++#define AIROHA_SCU_SSR3 0x94 ++#define AIROHA_SCU_ETH_XSI_SEL GENMASK(14, 13) ++#define AIROHA_SCU_ETH_XSI_USXGMII FIELD_PREP_CONST(AIROHA_SCU_ETH_XSI_SEL, 0x1) ++#define AIROHA_SCU_ETH_XSI_HSGMII FIELD_PREP_CONST(AIROHA_SCU_ETH_XSI_SEL, 0x2) ++#define AIROHA_SCU_SSTR 0x9c ++#define AIROHA_SCU_PON_XSI_SEL GENMASK(10, 9) ++#define AIROHA_SCU_PON_XSI_USXGMII FIELD_PREP_CONST(AIROHA_SCU_PON_XSI_SEL, 0x1) ++#define AIROHA_SCU_PON_XSI_HSGMII FIELD_PREP_CONST(AIROHA_SCU_PON_XSI_SEL, 0x2) ++ ++/* HSGMII_AN */ ++#define AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_0 0x0 ++#define AIROHA_PCS_HSGMII_AN_SGMII_RA_ENABLE BIT(12) ++#define AIROHA_PCS_HSGMII_AN_SGMII_AN_RESTART BIT(9) ++#define AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_1 0x4 /* BMSR */ ++#define AIROHA_PCS_HSGMII_AN_SGMII_UNIDIR_ABILITY BIT(6) ++#define AIROHA_PCS_HSGMII_AN_SGMII_AN_COMPLETE BIT(5) ++#define AIROHA_PCS_HSGMII_AN_SGMII_REMOTE_FAULT BIT(4) ++#define AIROHA_PCS_HSGMII_AN_SGMII_AN_ABILITY BIT(3) ++#define AIROHA_PCS_HSGMII_AN_SGMII_LINK_STATUS BIT(2) ++#define AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_4 0x10 ++#define AIROHA_PCS_HSGMII_AN_SGMII_DEV_ABILITY GENMASK(15, 0) ++#define AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_5 0x14 /* LPA */ ++#define AIROHA_PCS_HSGMII_AN_SGMII_PARTNER_ABILITY GENMASK(15, 0) ++#define AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_11 0x2c ++#define AIROHA_PCS_HSGMII_AN_SGMII_LINK_TIMER GENMASK(19, 0) ++#define AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_13 0x34 ++#define AIROHA_PCS_HSGMII_AN_SGMII_REMOTE_FAULT_DIS BIT(8) ++#define AIROHA_PCS_HSGMII_AN_SGMII_IF_MODE_5_0 GENMASK(5, 0) ++#define AIROHA_PCS_HSGMII_AN_SGMII_COMPAT_EN BIT(5) ++#define AIROHA_PCS_HSGMII_AN_DUPLEX_FORCE_MODE BIT(4) ++#define AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE GENMASK(3, 2) ++#define AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE_1000 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE, 0x2) ++#define AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE_100 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE, 0x1) ++#define AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE_10 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE, 0x0) ++#define AIROHA_PCS_HSGMII_AN_SIDEBAND_EN BIT(1) ++#define AIROHA_PCS_HSGMII_AN_SGMII_EN BIT(0) ++#define AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_FORCE_CL37 0x60 ++#define AIROHA_PCS_HSGMII_AN_FORCE_AN_DONE BIT(0) ++ ++/* HSGMII_PCS */ ++#define AIROHA_PCS_HSGMII_PCS_CTROL_1 0x0 ++#define AIROHA_PCS_TBI_10B_MODE BIT(30) ++#define AIROHA_PCS_SGMII_SEND_AN_ERR_EN BIT(24) ++#define AIROHA_PCS_REMOTE_FAULT_DIS BIT(12) ++#define AIROHA_PCS_HSGMII_PCS_CTROL_3 0x8 ++#define AIROHA_PCS_HSGMII_PCS_LINK_STSTIME GENMASK(19, 0) ++#define AIROHA_PCS_HSGMII_PCS_CTROL_6 0x14 ++#define AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_10 BIT(14) ++#define AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_100 BIT(13) ++#define AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_1000 BIT(12) ++#define AIROHA_PCS_HSGMII_PCS_MAC_MODE BIT(8) ++#define AIROHA_PCS_HSGMII_PCS_TX_ENABLE BIT(4) ++#define AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL GENMASK(3, 2) ++#define AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL_1000 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL, 0x0) ++#define AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL_100 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL, 0x1) ++#define AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL_10 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL, 0x2) ++#define AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT BIT(1) ++#define AIROHA_PCS_HSGMII_PCS_MODE2_EN BIT(0) ++#define AIROHA_PCS_HSGMII_PCS_HSGMII_MODE_INTERRUPT 0x20 ++#define AIROHA_PCS_HSGMII_MODE2_REMOVE_FAULT_OCCUR_INT_CLEAR BIT(11) ++#define AIROHA_PCS_HSGMII_MODE2_REMOVE_FAULT_OCCUR_INT BIT(10) ++#define AIROHA_PCS_HSGMII_MODE2_AN_CL37_TIMERDONE_INT_CLEAR BIT(9) ++#define AIROHA_PCS_HSGMII_MODE2_AN_CL37_TIMERDONE_INT BIT(8) ++#define AIROHA_PCS_HSGMII_MODE2_AN_MIS_INT_CLEAR BIT(5) ++#define AIROHA_PCS_HSGMII_MODE2_AN_MIS_INT BIT(4) ++#define AIROHA_PCS_HSGMII_MODE2_RX_SYN_DONE_INT_CLEAR BIT(3) ++#define AIROHA_PCS_HSGMII_MODE2_AN_DONE_INT_CLEAR BIT(2) ++#define AIROHA_PCS_HSGMII_MODE2_RX_SYN_DONE_INT BIT(1) ++#define AIROHA_PCS_HSGMII_MODE2_AN_DONE_INT BIT(0) ++#define AIROHA_PCS_HSGMII_PCS_AN_SGMII_MODE_FORCE 0x24 ++#define AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE GENMASK(5, 4) ++#define AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_1000 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE, 0x0) ++#define AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_100 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE, 0x1) ++#define AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_10 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE, 0x2) ++#define AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_SEL BIT(0) ++#define ARIOHA_PCS_HSGMII_PCS_STATE_2 0x104 ++#define AIROHA_PCS_HSGMII_PCS_RX_SYNC BIT(5) ++#define AIROHA_PCS_HSGMII_PCS_AN_DONE BIT(0) ++#define AIROHA_PCS_HSGMII_PCS_INT_STATE 0x15c ++#define AIROHA_PCS_HSGMII_PCS_MODE2_REMOTE_FAULT_OCCUR_INT BIT(4) ++#define AIROHA_PCS_HSGMII_PCS_MODE2_AN_MLS BIT(3) ++#define AIROHA_PCS_HSGMII_PCS_MODE2_AN_CL37_TIMERDONE_INT BIT(2) ++#define AIROHA_PCS_HSGMII_PCS_MODE2_RX_SYNC BIT(1) ++#define AIROHA_PCS_HSGMII_PCS_MODE2_AN_DONE BIT(0) ++ ++/* MULTI_SGMII */ ++#define AIROHA_PCS_MULTI_SGMII_INTERRUPT_EN_0 0x14 ++#define AIROHA_PCS_MULTI_SGMII_PCS_INT_EN_0 BIT(0) ++#define AIROHA_PCS_MULTI_SGMII_SGMII_STS_CTRL_0 0x18 ++#define AIROHA_PCS_LINK_MODE_P0 GENMASK(5, 4) ++#define AIROHA_PCS_LINK_MODE_P0_2_5G FIELD_PREP_CONST(AIROHA_PCS_LINK_MODE_P0, 0x3) ++#define AIROHA_PCS_LINK_MODE_P0_1G FIELD_PREP_CONST(AIROHA_PCS_LINK_MODE_P0, 0x2) ++#define AIROHA_PCS_LINK_MODE_P0_100M FIELD_PREP_CONST(AIROHA_PCS_LINK_MODE_P0, 0x1) ++#define AIROHA_PCS_LINK_MODE_P0_10M FIELD_PREP_CONST(AIROHA_PCS_LINK_MODE_P0, 0x0) ++#define AIROHA_PCS_FORCE_SPD_MODE_P0 BIT(2) ++#define AIROHA_PCS_FORCE_LINKDOWN_P0 BIT(1) ++#define AIROHA_PCS_FORCE_LINKUP_P0 BIT(0) ++#define AIROHA_PCS_MULTI_SGMII_MSG_RX_CTRL_0 0x100 ++#define AIROHA_PCS_HSGMII_XFI_SEL BIT(28) ++#define AIROHA_PCS_MULTI_SGMII_INTERRUPT_SEL 0x14c ++#define AIROHA_PCS_HSGMII_PCS_INT BIT(0) ++#define AIROHA_PCS_MULTI_SGMII_MSG_RX_STS_15 0x43c ++#define AIROHA_PCS_LINK_STS_P0 BIT(3) ++#define AIROHA_PCS_SPEED_STS_P0 GENMASK(2, 0) ++#define AIROHA_PCS_SPEED_STS_P0_1G FIELD_PREP_CONST(AIROHA_PCS_SPEED_STS_P0, 0x2) ++#define AIROHA_PCS_SPEED_STS_P0_100M FIELD_PREP_CONST(AIROHA_PCS_SPEED_STS_P0, 0x1) ++#define AIROHA_PCS_SPEED_STS_P0_10M FIELD_PREP_CONST(AIROHA_PCS_SPEED_STS_P0, 0x0) ++#define AIROHA_PCS_MULTI_SGMII_MSG_RX_STS_18 0x448 ++#define AIROHA_PCS_P0_SGMII_IS_10 BIT(2) ++#define AIROHA_PCS_P0_SGMII_IS_100 BIT(1) ++#define AIROHA_PCS_P0_SGMII_IS_1000 BIT(0) ++ ++/* HSGMII_RATE_ADP */ ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_0 0x0 ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_RX_BYPASS BIT(27) ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_TX_BYPASS BIT(26) ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_RX_EN BIT(4) ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_TX_EN BIT(0) ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_1 0x4 ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_WR_THR GENMASK(20, 16) ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_RD_THR GENMASK(28, 24) ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_6 0x18 ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_DOUT_L GENMASK(31, 0) ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_8 0x20 ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_DOUT_C GENMASK(7, 0) ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_11 0x2c ++#define AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_EN BIT(8) ++#define AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE GENMASK(15, 12) ++#define AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_10000 \ ++ FIELD_PREP_CONST(AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE, 0x0) ++#define AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_5000 \ ++ FIELD_PREP_CONST(AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE, 0x1) ++#define AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_2500 \ ++ FIELD_PREP_CONST(AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE, 0x2) ++#define AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_1000 \ ++ FIELD_PREP_CONST(AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE, 0x4) ++#define AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_100 \ ++ FIELD_PREP_CONST(AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE, 0x6) ++#define AIROHA_PCS_HSGMII_RATE_ADP_P0_CTRL_0 0x100 ++#define AIROHA_PCS_HSGMII_P0_DIS_MII_MODE BIT(31) ++ ++/* USXGMII */ ++#define AIROHA_PCS_USXGMII_PCS_CTROL_1 0x0 ++#define AIROHA_PCS_USXGMII_SPEED_SEL_H BIT(13) ++#define AIROHA_PCS_USXGMII_PCS_STUS_1 0x30 ++#define AIROHA_PCS_USXGMII_RX_LINK_STUS BIT(12) ++#define AIROHA_PCS_USXGMII_PRBS9_PATT_TST_ABILITY BIT(3) ++#define AIROHA_PCS_USXGMII_PRBS31_PATT_TST_ABILITY BIT(2) ++#define AIROHA_PCS_USXGMII_PCS_BLK_LK BIT(0) ++#define AIROHA_PCS_USGMII_VENDOR_DEFINE_116 0x22c ++#define AIROHA_PCS_USXGMII_PCS_CTRL_0 0x2c0 ++#define AIROHA_PCS_USXGMII_T_TYPE_T_INT_EN BIT(24) ++#define AIROHA_PCS_USXGMII_T_TYPE_D_INT_EN BIT(16) ++#define AIROHA_PCS_USXGMII_T_TYPE_C_INT_EN BIT(8) ++#define AIROHA_PCS_USXGMII_T_TYPE_S_INT_EN BIT(0) ++#define AIROHA_PCS_USXGMII_PCS_CTRL_1 0x2c4 ++#define AIROHA_PCS_USXGMII_R_TYPE_C_INT_EN BIT(24) ++#define AIROHA_PCS_USXGMII_R_TYPE_S_INT_EN BIT(16) ++#define AIROHA_PCS_USXGMII_TXPCS_FSM_ENC_ERR_INT_EN BIT(8) ++#define AIROHA_PCS_USXGMII_T_TYPE_E_INT_EN BIT(0) ++#define AIROHA_PCS_USXGMII_PCS_CTRL_2 0x2c8 ++#define AIROHA_PCS_USXGMII_RPCS_FSM_DEC_ERR_INT_EN BIT(24) ++#define AIROHA_PCS_USXGMII_R_TYPE_E_INT_EN BIT(16) ++#define AIROHA_PCS_USXGMII_R_TYPE_T_INT_EN BIT(8) ++#define AIROHA_PCS_USXGMII_R_TYPE_D_INT_EN BIT(0) ++#define AIROHA_PCS_USXGMII_PCS_CTRL_3 0x2cc ++#define AIROHA_PCS_USXGMII_FAIL_SYNC_XOR_ST_INT_EN BIT(24) ++#define AIROHA_PCS_USXGMII_RX_BLOCK_LOCK_ST_INT_EN BIT(16) ++#define AIROHA_PCS_USXGMII_LINK_UP_ST_INT_EN BIT(8) ++#define AIROHA_PCS_USXGMII_HI_BER_ST_INT_EN BIT(0) ++#define AIROHA_PCS_USXGMII_PCS_INT_STA_2 0x2d8 ++#define AIROHA_PCS_USXGMII_RPCS_FSM_DEC_ERR_INT BIT(24) ++#define AIROHA_PCS_USXGMII_R_TYPE_E_INT BIT(16) ++#define AIROHA_PCS_USXGMII_R_TYPE_T_INT BIT(8) ++#define AIROHA_PCS_USXGMII_R_TYPE_D_INT BIT(0) ++#define AIROHA_PCS_USXGMII_PCS_INT_STA_3 0x2dc ++#define AIROHA_PCS_USXGMII_FAIL_SYNC_XOR_ST_INT BIT(24) ++#define AIROHA_PCS_USXGMII_RX_BLOCK_LOCK_ST_INT BIT(16) ++#define AIROHA_PCS_USXGMII_LINK_UP_ST_INT BIT(8) ++#define AIROHA_PCS_USXGMII_HI_BER_ST_INT BIT(0) ++#define AIROHA_PCS_USXGMII_PCS_CTRL_4 0x2e0 ++#define AIROHA_PCS_USXGMII_LINK_DOWN_ST_INT_EN BIT(0) ++#define AIROHA_PCS_USXGMII_PCS_INT_STA_4 0x2e4 ++#define AIROHA_PCS_USXGMII_LINK_DOWN_ST_INT BIT(0) ++#define AIROHA_PCS_USXGMII_PCS_AN_CONTROL_0 0x2f8 ++#define AIROHA_PCS_USXGMII_AN_RESTART BIT(8) ++#define AIROHA_PCS_USXGMII_AN_ENABLE BIT(0) ++#define AIROHA_PCS_USXGMII_PCS_AN_STATS_0 0x310 ++#define AIROHA_PCS_USXGMII_CUR_USXGMII_MODE GENMASK(30, 28) ++#define AIROHA_PCS_USXGMII_CUR_USXGMII_MODE_10G FIELD_PREP_CONST(AIROHA_PCS_USXGMII_CUR_USXGMII_MODE, 0x0) ++#define AIROHA_PCS_USXGMII_CUR_USXGMII_MODE_5G FIELD_PREP_CONST(AIROHA_PCS_USXGMII_CUR_USXGMII_MODE, 0x1) ++#define AIROHA_PCS_USXGMII_CUR_USXGMII_MODE_2_5G FIELD_PREP_CONST(AIROHA_PCS_USXGMII_CUR_USXGMII_MODE, 0x2) ++#define AIROHA_PCS_USXGMII_CUR_USXGMII_MODE_1G FIELD_PREP_CONST(AIROHA_PCS_USXGMII_CUR_USXGMII_MODE, 0x3) ++#define AIROHA_PCS_USXGMII_CUR_USXGMII_MODE_100M FIELD_PREP_CONST(AIROHA_PCS_USXGMII_CUR_USXGMII_MODE, 0x4) ++#define AIROHA_PCS_USXGMII_PARTNER_ABILITY GENMASK(15, 0) ++#define AIROHA_PCS_USXGMII_PCS_AN_STATS_2 0x318 ++#define AIROHA_PCS_USXGMII_PCS_AN_COMPLETE BIT(24) ++#define AIROHA_PCS_USXGMII_PCS_AN_CONTROL_6 0x31c ++#define AIROHA_PCS_USXGMII_TOG_PCS_AUTONEG_STS BIT(0) ++#define AIROHA_PCS_USXGMII_PCS_AN_CONTROL_7 0x320 ++#define AIROHA_PCS_USXGMII_RATE_UPDATE_MODE BIT(12) ++#define AIROHA_PCS_USXGMII_MODE GENMASK(10, 8) ++#define AIROHA_PCS_USXGMII_MODE_10000 FIELD_PREP(AIROHA_PCS_USXGMII_MODE, 0x0) ++#define AIROHA_PCS_USXGMII_MODE_5000 FIELD_PREP(AIROHA_PCS_USXGMII_MODE, 0x1) ++#define AIROHA_PCS_USXGMII_MODE_2500 FIELD_PREP(AIROHA_PCS_USXGMII_MODE, 0x2) ++#define AIROHA_PCS_USXGMII_MODE_1000 FIELD_PREP(AIROHA_PCS_USXGMII_MODE, 0x3) ++#define AIROHA_PCS_USXGMII_MODE_100 FIELD_PREP(AIROHA_PCS_USXGMII_MODE, 0x4) ++ ++/* PMA_PHYA */ ++#define AIROHA_PCS_ANA_PXP_CMN_EN 0x0 ++#define AIROHA_PCS_ANA_CMN_EN BIT(0) ++#define AIROHA_PCS_ANA_PXP_JCPLL_IB_EXT_EN 0x4 ++#define AIROHA_PCS_ANA_JCPLL_CHP_IOFST GENMASK(29, 24) ++#define AIROHA_PCS_ANA_JCPLL_CHP_IBIAS GENMASK(21, 16) ++#define AIROHA_PCS_ANA_JCPLL_LPF_SHCK_EN BIT(8) ++#define AIROHA_PCS_ANA_PXP_JCPLL_LPF_BR 0x8 ++#define AIROHA_PCS_ANA_JCPLL_LPF_BWR GENMASK(28, 24) ++#define AIROHA_PCS_ANA_JCPLL_LPF_BP GENMASK(20, 16) ++#define AIROHA_PCS_ANA_JCPLL_LPF_BC GENMASK(12, 8) ++#define AIROHA_PCS_ANA_JCPLL_LPF_BR GENMASK(4, 0) ++#define AIROHA_PCS_ANA_PXP_JCPLL_LPF_BWC 0xc ++#define AIROHA_PCS_ANA_JCPLL_KBAND_DIV GENMASK(26, 24) ++#define AIROHA_PCS_ANA_JCPLL_KBAND_CODE GENMASK(23, 16) ++#define AIROHA_PCS_ANA_JCPLL_KBAND_OPTION BIT(8) ++#define AIROHA_PCS_ANA_JCPLL_LPF_BWC GENMASK(4, 0) ++#define AIROHA_PCS_ANA_PXP_JCPLL_KBAND_KFC 0x10 ++#define AIROHA_PCS_ANA_JCPLL_KBAND_KS GENMASK(17, 16) ++#define AIROHA_PCS_ANA_JCPLL_KBAND_KF GENMASK(9, 8) ++#define AIROHA_PCS_ANA_JCPLL_KBAND_KFC GENMASK(1, 0) ++#define AIROHA_PCS_ANA_PXP_JCPLL_MMD_PREDIV_MODE 0x14 ++#define AIROHA_PCS_ANA_JCPLL_POSTDIV_D5 BIT(24) ++#define AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE GENMASK(1, 0) ++#define AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE, 0x0) ++#define AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE_3 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE, 0x1) ++#define AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE, 0x2) ++#define AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE, 0x3) ++#define AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY 0x1c ++#define AIROHA_PCS_ANA_JCPLL_SDM_DI_LS GENMASK(25, 24) ++#define AIROHA_PCS_ANA_JCPLL_SDM_DI_LS_2_23 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_DI_LS, 0x0) ++#define AIROHA_PCS_ANA_JCPLL_SDM_DI_LS_2_21 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_DI_LS, 0x1) ++#define AIROHA_PCS_ANA_JCPLL_SDM_DI_LS_2_19 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_DI_LS, 0x2) ++#define AIROHA_PCS_ANA_JCPLL_SDM_DI_LS_2_15 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_DI_LS, 0x3) ++#define AIROHA_PCS_ANA_JCPLL_SDM_DI_EN BIT(16) ++#define AIROHA_PCS_ANA_JCPLL_PLL_RSTB BIT(8) ++#define AIROHA_PCS_ANA_JCPLL_RST_DLY GENMASK(2, 0) ++#define AIROHA_PCS_ANA_JCPLL_RST_DLY_20_25 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_RST_DLY, 0x1) ++#define AIROHA_PCS_ANA_JCPLL_RST_DLY_40_50 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_RST_DLY, 0x2) ++#define AIROHA_PCS_ANA_JCPLL_RST_DLY_80_100 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_RST_DLY, 0x3) ++#define AIROHA_PCS_ANA_JCPLL_RST_DLY_150_200 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_RST_DLY, 0x4) ++#define AIROHA_PCS_ANA_JCPLL_RST_DLY_300_400 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_RST_DLY, 0x5) ++#define AIROHA_PCS_ANA_JCPLL_RST_DLY_600_800 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_RST_DLY, 0x6) ++#define AIROHA_PCS_ANA_PXP_JCPLL_SDM_IFM 0x20 ++#define AIROHA_PCS_ANA_JCPLL_SDM_OUT BIT(24) ++#define AIROHA_PCS_ANA_JCPLL_SDM_ORD GENMASK(17, 16) ++#define AIROHA_PCS_ANA_JCPLL_SDM_ORD_INT FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_ORD, 0x0) ++#define AIROHA_PCS_ANA_JCPLL_SDM_ORD_1SDM FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_ORD, 0x1) ++#define AIROHA_PCS_ANA_JCPLL_SDM_ORD_2SDM FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_ORD, 0x2) ++#define AIROHA_PCS_ANA_JCPLL_SDM_ORD_3SDM FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_ORD, 0x3) ++#define AIROHA_PCS_ANA_JCPLL_SDM_MODE GENMASK(9, 8) ++#define AIROHA_PCS_ANA_JCPLL_SDM_IFM BIT(0) ++#define AIROHA_PCS_ANA_PXP_JCPLL_SDM_HREN 0x24 ++#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_VREF GENMASK(28, 24) ++#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN GENMASK(18, 16) ++#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN, 0x0) ++#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN, 0x1) ++#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN_6 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN, 0x2) ++#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN_8 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN, 0x3) ++#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN_10 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN, 0x4) ++#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_EN BIT(8) ++#define AIROHA_PCS_ANA_JCPLL_SDM_HREN BIT(0) ++#define AIROHA_PCS_ANA_PXP_JCPLL_TCL_CMP_EN 0x28 ++#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW GENMASK(26, 24) ++#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW_0_5 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW, 0x0) ++#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW, 0x1) ++#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW, 0x2) ++#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW, 0x3) ++#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW_8 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW, 0x4) ++#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW_16 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW, 0x6) ++#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_EN BIT(16) ++#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW GENMASK(26, 24) ++#define AIROHA_PCS_ANA_PXP_JCPLL_VCODIV 0x2c ++#define AIROHA_PCS_ANA_JCPLL_VCO_SCAPWR GENMASK(26, 24) ++#define AIROHA_PCS_ANA_JCPLL_VCO_HALFLSB_EN BIT(16) ++#define AIROHA_PCS_ANA_JCPLL_VCO_CFIX GENMASK(9, 8) ++#define AIROHA_PCS_ANA_JCPLL_VCODIV GENMASK(1, 0) ++#define AIROHA_PCS_ANA_JCPLL_VCODIV_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_VCODIV, 0x0) ++#define AIROHA_PCS_ANA_JCPLL_VCODIV_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_VCODIV, 0x1) ++#define AIROHA_PCS_ANA_PXP_JCPLL_VCO_TCLVAR 0x30 ++#define AIROHA_PCS_ANA_JCPLL_SSC_PHASE_INI BIT(17) ++#define AIROHA_PCS_ANA_JCPLL_SSC_EN BIT(16) ++#define AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_L GENMASK(10, 8) ++#define AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_H GENMASK(5, 3) ++#define AIROHA_PCS_ANA_JCPLL_VCO_TCLVAR GENMASK(2, 0) ++#define AIROHA_PCS_ANA_PXP_JCPLL_SSC_TRI_EN 0x34 ++#define AIROHA_PCS_ANA_JCPLL_SSC_DELTA1 GENMASK(23, 8) ++#define AIROHA_PCS_ANA_JCPLL_SSC_TRI_EN BIT(0) ++#define AIROHA_PCS_ANA_PXP_JCPLL_SSC_DELTA 0x38 ++#define AIROHA_PCS_ANA_JCPLL_SSC_PERIOD GENMASK(31, 16) ++#define AIROHA_PCS_ANA_JCPLL_SSC_DELTA GENMASK(15, 0) ++#define AIROHA_PCS_ANA_PXP_JCPLL_SPARE_H 0x48 ++#define AIROHA_PCS_ANA_JCPLL_TCL_KBAND_VREF GENMASK(20, 16) ++#define AIROHA_PCS_ANA_JCPLL_SPARE_L GENMASK(15, 8) ++#define AIROHA_PCS_ANA_JCPLL_SPARE_L_LDO FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SPARE_L, BIT(5)) ++#define AIROHA_PCS_ANA_PXP_TXPLL_CHP_IBIAS 0x50 ++#define AIROHA_PCS_ANA_TXPLL_LPF_BC GENMASK(28, 24) ++#define AIROHA_PCS_ANA_TXPLL_LPF_BR GENMASK(20, 16) ++#define AIROHA_PCS_ANA_TXPLL_CHP_IOFST GENMASK(13, 8) ++#define AIROHA_PCS_ANA_TXPLL_CHP_IBIAS GENMASK(5, 0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_LPF_BP 0x54 ++#define AIROHA_PCS_ANA_TXPLL_KBAND_OPTION BIT(24) ++#define AIROHA_PCS_ANA_TXPLL_LPF_BWC GENMASK(20, 16) ++#define AIROHA_PCS_ANA_TXPLL_LPF_BWR GENMASK(12, 8) ++#define AIROHA_PCS_ANA_TXPLL_LPF_BP GENMASK(4, 0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_KBAND_CODE 0x58 ++#define AIROHA_PCS_ANA_TXPLL_KBAND_KF GENMASK(25, 24) ++#define AIROHA_PCS_ANA_TXPLL_KBAND_KFC GENMASK(17, 16) ++#define AIROHA_PCS_ANA_TXPLL_KBAND_DIV GENMASK(10, 8) ++#define AIROHA_PCS_ANA_TXPLL_KBAND_CODE GENMASK(7, 0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_KBAND_KS 0x5c ++#define AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE GENMASK(17, 16) ++#define AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE, 0x0) ++#define AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE_3 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE, 0x1) ++#define AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE, 0x2) ++#define AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE, 0x3) ++#define AIROHA_PCS_ANA_TXPLL_POSTDIV_EN BIT(8) ++#define AIROHA_PCS_ANA_TXPLL_KBAND_KS GENMASK(1, 0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_REFIN_INTERNAL 0x64 ++#define AIROHA_PCS_ANA_TXPLL_PLL_RSTB BIT(24) ++#define AIROHA_PCS_ANA_TXPLL_RST_DLY GENMASK(18, 16) ++#define AIROHA_PCS_ANA_TXPLL_REFIN_DIV GENMASK(9, 8) ++#define AIROHA_PCS_ANA_TXPLL_REFIN_DIV_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_REFIN_DIV, 0x0) ++#define AIROHA_PCS_ANA_TXPLL_REFIN_DIV_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_REFIN_DIV, 0x1) ++#define AIROHA_PCS_ANA_TXPLL_REFIN_DIV_3 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_REFIN_DIV, 0x2) ++#define AIROHA_PCS_ANA_TXPLL_REFIN_DIV_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_REFIN_DIV, 0x3) ++#define AIROHA_PCS_ANA_TXPLL_REFIN_INTERNAL BIT(0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_SDM_DI_EN 0x68 ++#define AIROHA_PCS_ANA_TXPLL_SDM_MODE GENMASK(25, 24) ++#define AIROHA_PCS_ANA_TXPLL_SDM_IFM BIT(16) ++#define AIROHA_PCS_ANA_TXPLL_SDM_DI_LS GENMASK(9, 8) ++#define AIROHA_PCS_ANA_TXPLL_SDM_DI_LS_2_23 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_DI_LS, 0x0) ++#define AIROHA_PCS_ANA_TXPLL_SDM_DI_LS_2_21 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_DI_LS, 0x1) ++#define AIROHA_PCS_ANA_TXPLL_SDM_DI_LS_2_19 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_DI_LS, 0x2) ++#define AIROHA_PCS_ANA_TXPLL_SDM_DI_LS_2_15 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_DI_LS, 0x3) ++#define AIROHA_PCS_ANA_TXPLL_SDM_DI_EN BIT(0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_SDM_ORD 0x6c ++#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_EN BIT(24) ++#define AIROHA_PCS_ANA_TXPLL_SDM_HREN BIT(16) ++#define AIROHA_PCS_ANA_TXPLL_SDM_OUT BIT(8) ++#define AIROHA_PCS_ANA_TXPLL_SDM_ORD GENMASK(1, 0) ++#define AIROHA_PCS_ANA_TXPLL_SDM_ORD_INT FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_ORD, 0x0) ++#define AIROHA_PCS_ANA_TXPLL_SDM_ORD_1SDM FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_ORD, 0x1) ++#define AIROHA_PCS_ANA_TXPLL_SDM_ORD_2SDM FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_ORD, 0x2) ++#define AIROHA_PCS_ANA_TXPLL_SDM_ORD_3SDM FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_ORD, 0x3) ++#define AIROHA_PCS_ANA_PXP_TXPLL_TCL_AMP_GAIN 0x70 ++#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_VREF GENMASK(12, 8) ++#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN GENMASK(2, 0) ++#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN, 0x0) ++#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN_2_5 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN, 0x1) ++#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN_3 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN, 0x2) ++#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN, 0x3) ++#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN_6 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN, 0x4) ++#define AIROHA_PCS_ANA_PXP_TXPLL_TCL_LPF_EN 0x74 ++#define AIROHA_PCS_ANA_TXPLL_VCO_CFIX GENMASK(25, 24) ++#define AIROHA_PCS_ANA_TXPLL_VCODIV GENMASK(17, 16) ++#define AIROHA_PCS_ANA_TXPLL_VCODIV_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_VCODIV, 0x0) ++#define AIROHA_PCS_ANA_TXPLL_VCODIV_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_VCODIV, 0x1) ++#define AIROHA_PCS_ANA_TXPLL_VCODIV_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_VCODIV, 0x1) ++#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW GENMASK(10, 8) ++#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW_0_5 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW, 0x0) ++#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW, 0x1) ++#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW, 0x2) ++#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW, 0x3) ++#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW_8 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW, 0x4) ++#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW_16 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW, 0x6) ++#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_EN BIT(0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_VCO_HALFLSB_EN 0x78 ++#define AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_L GENMASK(29, 27) ++#define AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_H GENMASK(26, 24) ++#define AIROHA_PCS_ANA_TXPLL_VCO_TCLVAR GENMASK(18, 16) ++#define AIROHA_PCS_ANA_TXPLL_VCO_SCAPWR GENMASK(10, 8) ++#define AIROHA_PCS_ANA_TXPLL_VCO_HALFLSB_EN BIT(0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_SSC_EN 0x7c ++#define AIROHA_PCS_ANA_TXPLL_SSC_TRI_EN BIT(16) ++#define AIROHA_PCS_ANA_TXPLL_SSC_PHASE_INI BIT(8) ++#define AIROHA_PCS_ANA_TXPLL_SSC_EN BIT(0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_SSC_DELTA1 0x80 ++#define AIROHA_PCS_ANA_TXPLL_SSC_DELTA GENMASK(31, 16) ++#define AIROHA_PCS_ANA_TXPLL_SSC_DELTA1 GENMASK(15, 0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_SSC_PERIOD 0x84 ++#define AIROHA_PCS_ANA_TXPLL_LDO_VCO_OUT GENMASK(25, 24) ++#define AIROHA_PCS_ANA_TXPLL_LDO_OUT GENMASK(17, 16) ++#define AIROHA_PCS_ANA_TXPLL_SSC_PERIOD GENMASK(15, 0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_TCL_KBAND_VREF 0x94 ++#define AIROHA_PCS_ANA_TXPLL_TCL_KBAND_VREF GENMASK(4, 0) ++#define AIROHA_PCS_ANA_PXP_TX_CKLDO_EN 0xc4 ++#define AIROHA_PCS_ANA_TX_DMEDGEGEN_EN BIT(24) ++#define AIROHA_PCS_ANA_TX_CKLDO_EN BIT(0) ++#define AIROHA_PCS_ANA_PXP_RX_BUSBIT_SEL 0xcc ++#define AIROHA_PCS_ANA_RX_PHY_CK_SEL_FORCE BIT(24) ++#define AIROHA_PCS_ANA_RX_PHY_CK_SEL BIT(16) /* 0: from PR 1: from DES */ ++#define AIROHA_PCS_ANA_PXP_RX_REV_0 0xd4 ++#define AIROHA_PCS_ANA_RX_REV_1 GENMASK(31, 16) ++#define AIROHA_PCS_ANA_REV_1_FE_EQ_BIAS_CTRL GENMASK(30, 28) ++#define AIROHA_PCS_ANA_REV_1_FE_BUF1_BIAS_CTRL GENMASK(26, 24) ++#define AIROHA_PCS_ANA_REV_1_FE_BUF2_BIAS_CTRL GENMASK(22, 20) ++#define AIROHA_PCS_ANA_REV_1_SIGDET_ILEAK GENMASK(19, 18) ++#define AIROHA_PCS_ANA_REV_1_FECUR_PWDB BIT(16) ++#define AIROHA_PCS_ANA_PXP_RX_PHYCK_DIV 0xd8 ++#define AIROHA_PCS_ANA_RX_TDC_CK_SEL BIT(24) ++#define AIROHA_PCS_ANA_RX_PHYCK_RSTB BIT(16) ++#define AIROHA_PCS_ANA_RX_PHYCK_SEL GENMASK(9, 8) ++#define AIROHA_PCS_ANA_RX_PHYCK_DIV GENMASK(7, 0) ++#define AIROHA_PCS_ANA_PXP_CDR_PD_PICAL_CKD8_INV 0xdc ++#define AIROHA_PCS_ANA_CDR_PD_EDGE_DIS BIT(8) ++#define AIROHA_PCS_ANA_CDR_PD_PICAL_CKD8_INV BIT(0) ++#define AIROHA_PCS_ANA_PXP_CDR_LPF_RATIO 0xe8 ++#define AIROHA_PCS_ANA_CDR_LPF_TOP_LIM GENMASK(26, 8) ++#define AIROHA_PCS_ANA_CDR_LPF_RATIO GENMASK(1, 0) ++#define AIROHA_PCS_ANA_PXP_CDR_PR_INJ_MODE 0xf4 ++#define AIROHA_PCS_ANA_CDR_PR_INJ_FORCE_OFF BIT(24) ++#define AIROHA_PCS_ANA_PXP_CDR_PR_BETA_DAC 0xf8 ++#define AIROHA_PCS_ANA_CDR_PR_KBAND_DIV GENMASK(26, 24) ++#define AIROHA_PCS_ANA_CDR_PR_BETA_SEL GENMASK(19, 16) ++#define AIROHA_PCS_ANA_CDR_PR_VCOADC_OS GENMASK(11, 8) ++#define AIROHA_PCS_ANA_CDR_PR_BETA_DAC GENMASK(6, 0) ++#define AIROHA_PCS_ANA_PXP_CDR_PR_VREG_IBAND_VAL 0xfc ++#define AIROHA_PCS_ANA_CDR_PR_FBKSEL GENMASK(25, 24) ++#define AIROHA_PCS_ANA_CDR_PR_VREG_DAC_BAND GENMASK(20, 16) ++#define AIROHA_PCS_ANA_CDR_PR_VREG_CKBUF_VAL GENMASK(10, 8) ++#define AIROHA_PCS_ANA_CDR_PR_VREG_IBAND_VAL GENMASK(2, 0) ++#define AIROHA_PCS_ANA_PXP_CDR_PR_MONPR_EN 0x10c ++#define AIROHA_PCS_ANA_RX_DAC_MON GENMASK(28, 24) ++#define AIROHA_PCS_ANA_CDR_PR_CAP_EN BIT(19) ++#define AIROHA_PCS_ANA_CDR_BUF_IN_SR GENMASK(18, 16) ++#define AIROHA_PCS_ANA_CDR_PR_XFICK_EN BIT(2) ++#define AIROHA_PCS_ANA_CDR_PR_MONDPI_EN BIT(1) ++#define AIROHA_PCS_ANA_CDR_PR_MONDPR_EN BIT(0) ++#define AIROHA_PCS_ANA_PXP_RX_DAC_RANGE 0x110 ++#define AIROHA_PCS_ANA_RX_SIGDET_LPF_CTRL GENMASK(25, 24) ++#define AIROHA_PCS_ANA_PXP_RX_SIGDET_NOVTH 0x114 ++#define AIROHA_PCS_ANA_RX_FE_50OHMS_SEL GENMASK(25, 24) ++#define AIROHA_PCS_ANA_RX_SIGDET_VTH_SEL GENMASK(20, 16) ++#define AIROHA_PCS_ANA_RX_SIGDET_PEAK GENMASK(9, 8) ++#define AIROHA_PCS_ANA_PXP_RX_FE_EQ_HZEN 0x118 ++#define AIROHA_PCS_ANA_RX_FE_VB_EQ3_EN BIT(24) ++#define AIROHA_PCS_ANA_RX_FE_VB_EQ2_EN BIT(16) ++#define AIROHA_PCS_ANA_RX_FE_VB_EQ1_EN BIT(8) ++#define AIROHA_PCS_ANA_RX_FE_EQ_HZEN BIT(0) ++#define AIROHA_PCS_ANA_PXP_RX_FE_VCM_GEN_PWDB 0x11c ++#define AIROHA_PCS_ANA_FE_VCM_GEN_PWDB BIT(0) ++#define AIROHA_PCS_ANA_PXP_RX_OSCAL_WATCH_WNDW 0x120 ++#define AIROHA_PCS_ANA_RX_OSCAL_FORCE GENMASK(17, 8) ++#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA2VOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(0)) ++#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA2IOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(1)) ++#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA1VOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(2)) ++#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA1IOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(3)) ++#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE2VOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(4)) ++#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE2IOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(5)) ++#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE1VOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(6)) ++#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE1IOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(7)) ++#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_LVSH FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(8)) ++#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_COMPOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(9)) ++#define AIROHA_PCS_ANA_PXP_AEQ_CFORCE 0x13c ++#define AIROHA_PCS_ANA_AEQ_OFORCE GENMASK(19, 8) ++#define AIROHA_PCS_ANA_AEQ_OFORCE_SAOS FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(0)) ++#define AIROHA_PCS_ANA_AEQ_OFORCE_DFETP1 FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(1)) ++#define AIROHA_PCS_ANA_AEQ_OFORCE_DFETP2 FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(2)) ++#define AIROHA_PCS_ANA_AEQ_OFORCE_DFETP3 FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(3)) ++#define AIROHA_PCS_ANA_AEQ_OFORCE_DFETP4 FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(4)) ++#define AIROHA_PCS_ANA_AEQ_OFORCE_DFETP5 FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(5)) ++#define AIROHA_PCS_ANA_AEQ_OFORCE_DFETP6 FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(6)) ++#define AIROHA_PCS_ANA_AEQ_OFORCE_DFETP7 FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(7)) ++#define AIROHA_PCS_ANA_AEQ_OFORCE_VGA FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(8)) ++#define AIROHA_PCS_ANA_AEQ_OFORCE_CTLE FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(9)) ++#define AIROHA_PCS_ANA_AEQ_OFORCE_ATT FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(10)) ++#define AIROHA_PCS_ANA_PXP_RX_FE_PEAKING_CTRL_MSB 0x144 ++#define AIROHA_PCS_ANA_RX_DAC_D0_BYPASS_AEQ BIT(24) ++#define AIROHA_PCS_ANA_PXP_RX_DAC_D1_BYPASS_AEQ 0x148 ++#define AIROHA_PCS_ANA_RX_DAC_EYE_BYPASS_AEQ BIT(24) ++#define AIROHA_PCS_ANA_RX_DAC_E1_BYPASS_AEQ BIT(16) ++#define AIROHA_PCS_ANA_RX_DAC_E0_BYPASS_AEQ BIT(8) ++#define AIROHA_PCS_ANA_RX_DAC_D1_BYPASS_AEQ BIT(0) ++ ++/* PMA_PHYD */ ++#define AIROHA_PCS_PMA_SS_LCPLL_PWCTL_SETTING_0 0x0 ++#define AIROHA_PCS_PMA_SW_LCPLL_EN BIT(24) ++#define AIROHA_PCS_PMA_SS_LCPLL_PWCTL_SETTING_1 0x4 ++#define AIROHA_PCS_PMA_LCPLL_MAN_PWDB BIT(0) ++#define AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_2 0x88 ++#define AIROHA_PCS_PMA_DATA_SHIFT BIT(8) ++#define AIROHA_PCS_PMA_EYECNT_FAST BIT(0) ++#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_0 0x8c ++#define AIROHA_PCS_PMA_RX_OS_START GENMASK(23, 8) ++#define AIROHA_PCS_PMA_OSC_SPEED_OPT GENMASK(2, 0) ++#define AIROHA_PCS_PMA_OSC_SPEED_OPT_0_05 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x0) ++#define AIROHA_PCS_PMA_OSC_SPEED_OPT_0_1 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x1) ++#define AIROHA_PCS_PMA_OSC_SPEED_OPT_0_2 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x2) ++#define AIROHA_PCS_PMA_OSC_SPEED_OPT_0_4 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x3) ++#define AIROHA_PCS_PMA_OSC_SPEED_OPT_0_8 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x4) ++#define AIROHA_PCS_PMA_OSC_SPEED_OPT_1_6 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x5) ++#define AIROHA_PCS_PMA_OSC_SPEED_OPT_3_2 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x6) ++#define AIROHA_PCS_PMA_OSC_SPEED_OPT_6_4 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x7) ++#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_1 0x90 ++#define AIROHA_PCS_PMA_RX_PICAL_END GENMASK(31, 16) ++#define AIROHA_PCS_PMA_RX_PICAL_START GENMASK(15, 0) ++#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_2 0x94 ++#define AIROHA_PCS_PMA_RX_PDOS_END GENMASK(31, 16) ++#define AIROHA_PCS_PMA_RX_PDOS_START GENMASK(15, 0) ++#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_3 0x98 ++#define AIROHA_PCS_PMA_RX_FEOS_END GENMASK(31, 16) ++#define AIROHA_PCS_PMA_RX_FEOS_START GENMASK(15, 0) ++#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_4 0x9c ++#define AIROHA_PCS_PMA_RX_SDCAL_END GENMASK(31, 16) ++#define AIROHA_PCS_PMA_RX_SDCAL_START GENMASK(15, 0) ++#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_5 0x100 ++#define AIROHA_PCS_PMA_RX_RDY GENMASK(31, 16) ++#define AIROHA_PCS_PMA_RX_BLWC_RDY_EN GENMASK(15, 0) ++#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_6 0x104 ++#define AIROHA_PCS_PMA_RX_OS_END GENMASK(15, 0) ++#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1 0x10c ++#define AIROHA_PCS_PMA_DISB_RX_RDY BIT(24) ++#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1 0x114 ++#define AIROHA_PCS_PMA_FORCE_RX_RDY BIT(24) ++#define AIROHA_PCS_PMA_PHY_EQ_CTRL_3 0x120 ++#define AIROHA_PCS_PMA_EQ_DEBUG_SEL GENMASK(17, 16) ++#define AIROHA_PCS_PMA_FOM_NUM_ORDER GENMASK(12, 8) ++#define AIROHA_PCS_PMA_A_SEL GENMASK(1, 0) ++#define AIROHA_PCS_PMA_SS_RX_FREQ_DET_1 0x14c ++#define AIROHA_PCS_PMA_UNLOCK_CYCLECNT GENMASK(31, 16) ++#define AIROHA_PCS_PMA_LOCK_CYCLECNT GENMASK(15, 0) ++#define AIROHA_PCS_PMA_SS_RX_FREQ_DET_2 0x150 ++#define AIROHA_PCS_PMA_LOCK_TARGET_END GENMASK(31, 16) ++#define AIROHA_PCS_PMA_LOCK_TARGET_BEG GENMASK(15, 0) ++#define AIROHA_PCS_PMA_SS_RX_FREQ_DET_3 0x154 ++#define AIROHA_PCS_PMA_UNLOCK_TARGET_END GENMASK(31, 16) ++#define AIROHA_PCS_PMA_UNLOCK_TARGET_BEG GENMASK(15, 0) ++#define AIROHA_PCS_PMA_SS_RX_FREQ_DET_4 0x158 ++#define AIROHA_PCS_PMA_LOCK_UNLOCKTH GENMASK(15, 12) ++#define AIROHA_PCS_PMA_LOCK_LOCKTH GENMASK(11, 8) ++#define AIROHA_PCS_PMA_FREQLOCK_DET_EN GENMASK(2, 0) ++#define AIROHA_PCS_PMA_FREQLOCK_DET_EN_FORCE_0 FIELD_PREP_CONST(AIROHA_PCS_PMA_FREQLOCK_DET_EN, 0x0) ++#define AIROHA_PCS_PMA_FREQLOCK_DET_EN_FORCE_1 FIELD_PREP_CONST(AIROHA_PCS_PMA_FREQLOCK_DET_EN, 0x1) ++#define AIROHA_PCS_PMA_FREQLOCK_DET_EN_WAIT FIELD_PREP_CONST(AIROHA_PCS_PMA_FREQLOCK_DET_EN, 0x2) ++#define AIROHA_PCS_PMA_FREQLOCK_DET_EN_NORMAL FIELD_PREP_CONST(AIROHA_PCS_PMA_FREQLOCK_DET_EN, 0x3) ++#define AIROHA_PCS_PMA_FREQLOCK_DET_EN_RX_STATE FIELD_PREP_CONST(AIROHA_PCS_PMA_FREQLOCK_DET_EN, 0x7) ++#define AIROHA_PCS_PMA_SS_RX_SIGDET_1 0x16c ++#define AIROHA_PCS_PMA_SIGDET_EN BIT(0) ++#define AIROHA_PCS_PMA_RX_FLL_1 0x174 ++#define AIROHA_PCS_PMA_LPATH_IDAC GENMASK(10, 0) ++#define AIROHA_PCS_PMA_RX_FLL_2 0x178 ++#define AIROHA_PCS_PMA_CK_RATE GENMASK(18, 16) ++#define AIROHA_PCS_PMA_CK_RATE_20 FIELD_PREP_CONST(AIROHA_PCS_PMA_CK_RATE, 0x0) ++#define AIROHA_PCS_PMA_CK_RATE_10 FIELD_PREP_CONST(AIROHA_PCS_PMA_CK_RATE, 0x1) ++#define AIROHA_PCS_PMA_CK_RATE_5 FIELD_PREP_CONST(AIROHA_PCS_PMA_CK_RATE, 0x2) ++#define AIROHA_PCS_PMA_RX_FLL_5 0x184 ++#define AIROHA_PCS_PMA_FLL_IDAC_MIN GENMASK(26, 16) ++#define AIROHA_PCS_PMA_FLL_IDAC_MAX GENMASK(10, 0) ++#define AIROHA_PCS_PMA_RX_FLL_B 0x19c ++#define AIROHA_PCS_PMA_LOAD_EN BIT(0) ++#define AIROHA_PCS_PMA_RX_RESET_1 0x208 ++#define AIROHA_PCS_PMA_SIGDET_RST_B BIT(8) ++#define AIROHA_PCS_PMA_TX_RST_B 0x260 ++#define AIROHA_PCS_PMA_TXCALIB_RST_B BIT(8) ++#define AIROHA_PCS_PMA_TX_TOP_RST_B BIT(0) ++#define AIROHA_PCS_PMA_RX_DISB_MODE_4 0x320 ++#define AIROHA_PCS_PMA_DISB_BLWC_OFFSET BIT(24) ++#define AIROHA_PCS_PMA_RX_FORCE_MODE_9 0x330 ++#define AIROHA_PCS_PMA_FORCE_FBCK_LOCK BIT(0) ++#define AIROHA_PCS_PMA_RX_DISB_MODE_8 0x33c ++#define AIROHA_PCS_PMA_DISB_FBCK_LOCK BIT(0) ++#define AIROHA_PCS_PMA_RX_SYS_EN_SEL_0 0x38c ++#define AIROHA_PCS_PMA_RX_SYS_EN_SEL GENMASK(1, 0) ++#define AIROHA_PCS_PMA_PLL_TDC_FREQDET_0 0x390 ++#define AIROHA_PCS_PMA_PLL_LOCK_CYCLECNT GENMASK(15, 0) ++#define AIROHA_PCS_PMA_PLL_TDC_FREQDET_1 0x394 ++#define AIROHA_PCS_PMA_PLL_LOCK_TARGET_END GENMASK(31, 16) ++#define AIROHA_PCS_PMA_PLL_LOCK_TARGET_BEG GENMASK(15, 0) ++#define AIROHA_PCS_PMA_PLL_TDC_FREQDET_3 0x39c ++#define AIROHA_PCS_PMA_PLL_LOCK_LOCKTH GENMASK(11, 8) ++#define AIROHA_PCS_PMA_RX_EXTRAL_CTRL 0x48c ++#define AIROHA_PCS_PMA_DISB_LEQ BIT(0) ++#define AIROHA_PCS_PMA_SS_DA_XPON_PWDB_0 0x34c ++#define AIROHA_PCS_PMA_XPON_CDR_PR_PD_PWDB BIT(24) ++#define AIROHA_PCS_PMA_XPON_CDR_PR_PIEYE_PWDB BIT(16) ++#define AIROHA_PCS_PMA_XPON_CDR_PW_PWDB BIT(8) ++#define AIROHA_PCS_PMA_XPON_RX_FE_PWDB BIT(0) ++#define AIROHA_PCS_PMA_SS_DA_XPON_PWDB_1 0x350 ++#define AIROHA_PCS_PMA_RX_SIDGET_PWDB BIT(0) ++#define AIROHA_PCS_PMA_DIG_RESERVE_0 0x360 ++#define AIROHA_PCS_PMA_DIG_RO_RESERVE_2 0x380 ++#define AIROHA_PCS_PMA_XPON_RX_RESERVED_1 0x374 ++#define AIROHA_PCS_PMA_XPON_RX_RATE_CTRL GENMASK(1, 0) ++#define AIROHA_PCS_PMA_SW_RST_SET 0x460 ++#define AIROHA_PCS_PMA_SW_HSG_RXPCS_RST_N BIT(11) ++#define AIROHA_PCS_PMA_SW_HSG_TXPCS_RST_N BIT(10) ++#define AIROHA_PCS_PMA_SW_HSG_RXPCS_BIST_RST_N BIT(9) ++#define AIROHA_PCS_PMA_SW_XFI_RXPCS_RST_N BIT(8) ++#define AIROHA_PCS_PMA_SW_XFI_TXPCS_RST_N BIT(7) ++#define AIROHA_PCS_PMA_SW_TX_FIFO_RST_N BIT(6) ++#define AIROHA_PCS_PMA_SW_REF_RST_N BIT(5) ++#define AIROHA_PCS_PMA_SW_ALLPCS_RST_N BIT(4) ++#define AIROHA_PCS_PMA_SW_PMA_RST_N BIT(3) ++#define AIROHA_PCS_PMA_SW_TX_RST_N BIT(2) ++#define AIROHA_PCS_PMA_SW_RX_RST_N BIT(1) ++#define AIROHA_PCS_PMA_SW_RX_FIFO_RST_N BIT(0) ++#define AIROHA_PCS_PMA_XPON_INT_EN_3 0x474 ++#define AIROHA_PCS_PMA_RX_SIGDET_INT_EN BIT(16) ++#define AIROHA_PCS_PMA_XPON_INT_STA_3 0x47c ++#define AIROHA_PCS_PMA_RX_SIGDET_INT BIT(16) ++#define AIROHA_PCS_PMA_RX_EXTRAL_CTRL 0x48c ++#define AIROHA_PCS_PMA_DISB_LEQ BIT(0) ++#define AIROHA_PCS_PMA_RX_FREQDET 0x530 ++#define AIROHA_PCS_PMA_FL_OUT GENMASK(31, 16) ++#define AIROHA_PCS_PMA_FBCK_LOCK BIT(0) ++#define AIROHA_PCS_PMA_XPON_TX_RATE_CTRL 0x580 ++#define AIROHA_PCS_PMA_PON_TX_RATE_CTRL GENMASK(1, 0) ++#define AIROHA_PCS_PMA_PXP_JCPLL_SDM_SCAN 0x768 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_PEAKING_CTRL BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_RX_PEAKING_CTRL GENMASK(19, 16) ++#define AIROHA_PCS_PMA_PXP_AEQ_SPEED 0x76c ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_OSR_SEL BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_OSR_SEL GENMASK(17, 16) ++#define AIROHA_PCS_PMA_PXP_TX_FIR_C0B 0x778 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_CN1 BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_TX_FIR_CN1 GENMASK(20, 16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C0B BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C0B GENMASK(5, 0) ++#define AIROHA_PCS_PMA_PXP_TX_TERM_SEL 0x77c ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_CKIN_DIVISOR BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_TX_CKIN_DIVISOR GENMASK(19, 16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_TERM_SEL BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_TX_TERM_SEL GENMASK(2, 0) ++#define AIROHA_PCS_PMA_PXP_TX_FIR_C1 0x780 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C2 BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C2 GENMASK(20, 16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C1 BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C1 GENMASK(5, 0) ++#define AIROHA_PCS_PMA_PXP_TX_RATE_CTRL 0x784 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_RATE_CTRL BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_TX_RATE_CTRL GENMASK(1, 0) ++#define AIROHA_PCS_PMA_PXP_CDR_PR_IDAC 0x794 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_SDM_PCW BIT(24) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_IDAC BIT(16) ++#define AIROHA_PCS_PMA_FORCE_CDR_PR_IDAC GENMASK(10, 0) ++#define AIROHA_PCS_PMA_FORCE_CDR_PR_IDAC_MAJOR GENMASK(10, 8) ++#define AIROHA_PCS_PMA_PXP_TXPLL_SDM_PCW 0x798 ++#define AIROHA_PCS_PMA_FORCE_DA_TXPLL_SDM_PCW GENMASK(30, 0) ++#define AIROHA_PCS_PMA_PXP_RX_FE_VOS 0x79c ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_JCPLL_SDM_PCW BIT(16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_FE_VOS BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_FE_VOS GENMASK(5, 0) ++#define AIROHA_PCS_PMA_PXP_JCPLL_SDM_PCW 0x800 ++#define AIROHA_PCS_PMA_FORCE_DA_JCPLL_SDM_PCW GENMASK(30, 0) ++#define AIROHA_PCS_PMA_PXP_AEQ_BYPASS 0x80c ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_AEQ_CKON BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_AEQ_CKON BIT(16) ++#define AIROHA_PCS_PMA_PXP_AEQ_RSTB 0x814 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_INJCK_SEL BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_CDR_INJCK_SEL BIT(16) ++#define AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA 0x818 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB BIT(16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA BIT(0) ++#define AIROHA_PCS_PMA_PXP_CDR_PD_PWDB 0x81c ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_KBAND_RSTB BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_CDR_PR_KBAND_RSTB BIT(16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PD_PWDB BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PD_PWDB BIT(0) ++#define AIROHA_PCS_PMA_PXP_CDR_PR_LPF_C_EN 0x820 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_LPF_R_EN BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_CDR_PR_LPF_R_EN BIT(16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_LPF_C_EN BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_CDR_PR_LPF_C_EN BIT(0) ++#define AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB 0x824 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PWDB BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PWDB BIT(16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PIEYE_PWDB BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PIEYE_PWDB BIT(0) ++#define AIROHA_PCS_PMA_PXP_JCPLL_CKOUT_EN 0x828 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_JCPLL_EN BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_JCPLL_EN BIT(16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_JCPLL_CKOUT_EN BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_JCPLL_CKOUT_EN BIT(0) ++#define AIROHA_PCS_PMA_PXP_RX_SCAN_RST_B 0x84c ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SIGDET_PWDB BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_RX_SIGDET_PWDB BIT(16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SCAN_RST_B BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_RX_SCAN_RST_B BIT(0) ++#define AIROHA_PCS_PMA_PXP_TXPLL_CKOUT_EN 0x854 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_EN BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_TXPLL_EN BIT(16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_CKOUT_EN BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_TXPLL_CKOUT_EN BIT(0) ++#define AIROHA_PCS_PMA_PXP_TX_ACJTAG_EN 0x874 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_CKIN_SEL BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_TX_CKIN_SEL BIT(16) ++#define AIROHA_PCS_PMA_PXP_FE_GAIN_CTRL 0x88c ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_GAIN_CTRL BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_RX_FE_GAIN_CTRL GENMASK(1, 0) ++#define AIROHA_PCS_PMA_PXP_RX_FE_PWDB 0x894 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_PDOSCAL_EN BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_RX_PDOSCAL_EN BIT(16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PWDB BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_RX_FE_PWDB BIT(0) ++ ++#define AIROHA_PCS_MAX_CALIBRATION_TRY 50 ++#define AIROHA_PCS_MAX_NUM_RSTS 2 ++ ++enum xfi_port_type { ++ AIROHA_PCS_ETH, ++ AIROHA_PCS_PON, ++}; ++ ++struct airoha_pcs_match_data { ++ enum xfi_port_type port_type; ++}; ++ ++struct airoha_pcs_priv { ++ struct device *dev; ++ const struct airoha_pcs_match_data *data; ++ phy_interface_t interface; ++ ++ struct regmap *scu; ++ ++ struct regmap *xfi_mac; ++ struct regmap *hsgmii_an; ++ struct regmap *hsgmii_pcs; ++ struct regmap *hsgmii_rate_adp; ++ struct regmap *multi_sgmii; ++ struct regmap *usxgmii_pcs; ++ ++ struct regmap *xfi_pma; ++ struct regmap *xfi_ana; ++ ++ struct reset_control_bulk_data rsts[AIROHA_PCS_MAX_NUM_RSTS]; ++ ++ struct phylink_pcs pcs; ++}; ++ ++static struct airoha_pcs_priv *phylink_pcs_to_airoha_pcs_port(struct phylink_pcs *pcs) ++{ ++ return container_of(pcs, struct airoha_pcs_priv, pcs); ++} ++ ++static void airoha_pcs_setup_scu_eth(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ u32 xsi_sel; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ xsi_sel = AIROHA_SCU_ETH_XSI_HSGMII; ++ break; ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ default: ++ xsi_sel = AIROHA_SCU_ETH_XSI_USXGMII; ++ } ++ ++ regmap_update_bits(priv->scu, AIROHA_SCU_SSR3, ++ AIROHA_SCU_ETH_XSI_SEL, ++ xsi_sel); ++} ++ ++static void airoha_pcs_setup_scu_pon(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ u32 xsi_sel, wan_sel; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ wan_sel = AIROHA_SCU_WAN_SEL_SGMII; ++ xsi_sel = AIROHA_SCU_PON_XSI_HSGMII; ++ break; ++ case PHY_INTERFACE_MODE_2500BASEX: ++ wan_sel = AIROHA_SCU_WAN_SEL_HSGMII; ++ xsi_sel = AIROHA_SCU_PON_XSI_HSGMII; ++ break; ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ default: ++ wan_sel = AIROHA_SCU_WAN_SEL_USXGMII; ++ xsi_sel = AIROHA_SCU_PON_XSI_USXGMII; ++ } ++ ++ regmap_update_bits(priv->scu, AIROHA_SCU_SSTR, ++ AIROHA_SCU_PON_XSI_SEL, ++ xsi_sel); ++ ++ regmap_update_bits(priv->scu, AIROHA_SCU_WAN_CONF, ++ AIROHA_SCU_WAN_SEL, ++ wan_sel); ++} ++ ++static int airoha_pcs_setup_scu(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ int ret; ++ ++ switch (priv->data->port_type) { ++ case AIROHA_PCS_ETH: ++ airoha_pcs_setup_scu_eth(priv, interface); ++ break; ++ case AIROHA_PCS_PON: ++ airoha_pcs_setup_scu_pon(priv, interface); ++ break; ++ } ++ ++ ret = reset_control_bulk_assert(ARRAY_SIZE(priv->rsts), ++ priv->rsts); ++ if (ret) ++ return ret; ++ ++ ret = reset_control_bulk_deassert(ARRAY_SIZE(priv->rsts), ++ priv->rsts); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static void airoha_pcs_init_usxgmii(struct airoha_pcs_priv *priv) ++{ ++ regmap_set_bits(priv->multi_sgmii, AIROHA_PCS_MULTI_SGMII_MSG_RX_CTRL_0, ++ AIROHA_PCS_HSGMII_XFI_SEL); ++ ++ /* Disable Hibernation */ ++ regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_CTROL_1, ++ AIROHA_PCS_USXGMII_SPEED_SEL_H); ++ ++ /* FIXME: wait Airoha */ ++ /* Avoid PCS sending garbage to MAC in some HW revision (E0) */ ++ regmap_write(priv->usxgmii_pcs, AIROHA_PCS_USGMII_VENDOR_DEFINE_116, 0); ++} ++ ++static void airoha_pcs_init_hsgmii(struct airoha_pcs_priv *priv) ++{ ++ regmap_clear_bits(priv->multi_sgmii, AIROHA_PCS_MULTI_SGMII_MSG_RX_CTRL_0, ++ AIROHA_PCS_HSGMII_XFI_SEL); ++ ++ regmap_set_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_1, ++ AIROHA_PCS_TBI_10B_MODE); ++} ++ ++static void airoha_pcs_init_sgmii(struct airoha_pcs_priv *priv) ++{ ++ regmap_clear_bits(priv->multi_sgmii, AIROHA_PCS_MULTI_SGMII_MSG_RX_CTRL_0, ++ AIROHA_PCS_HSGMII_XFI_SEL); ++ ++ regmap_set_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_1, ++ AIROHA_PCS_TBI_10B_MODE); ++ ++ regmap_update_bits(priv->hsgmii_rate_adp, AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_6, ++ AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_DOUT_L, ++ FIELD_PREP(AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_DOUT_L, 0x07070707)); ++ ++ regmap_update_bits(priv->hsgmii_rate_adp, AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_8, ++ AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_DOUT_C, ++ FIELD_PREP(AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_DOUT_C, 0xff)); ++} ++ ++static void airoha_pcs_init(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ airoha_pcs_init_sgmii(priv); ++ break; ++ case PHY_INTERFACE_MODE_2500BASEX: ++ airoha_pcs_init_hsgmii(priv); ++ break; ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ airoha_pcs_init_usxgmii(priv); ++ break; ++ default: ++ return; ++ } ++} ++ ++static void airoha_pcs_interrupt_init_sgmii(struct airoha_pcs_priv *priv) ++{ ++ /* Disable every interrupt */ ++ regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_HSGMII_PCS_HSGMII_MODE_INTERRUPT, ++ AIROHA_PCS_HSGMII_MODE2_REMOVE_FAULT_OCCUR_INT | ++ AIROHA_PCS_HSGMII_MODE2_AN_CL37_TIMERDONE_INT | ++ AIROHA_PCS_HSGMII_MODE2_AN_MIS_INT | ++ AIROHA_PCS_HSGMII_MODE2_RX_SYN_DONE_INT | ++ AIROHA_PCS_HSGMII_MODE2_AN_DONE_INT); ++ ++ /* Clear interrupt */ ++ regmap_set_bits(priv->usxgmii_pcs, AIROHA_PCS_HSGMII_PCS_HSGMII_MODE_INTERRUPT, ++ AIROHA_PCS_HSGMII_MODE2_REMOVE_FAULT_OCCUR_INT_CLEAR | ++ AIROHA_PCS_HSGMII_MODE2_AN_CL37_TIMERDONE_INT_CLEAR | ++ AIROHA_PCS_HSGMII_MODE2_AN_MIS_INT_CLEAR | ++ AIROHA_PCS_HSGMII_MODE2_RX_SYN_DONE_INT_CLEAR | ++ AIROHA_PCS_HSGMII_MODE2_AN_DONE_INT_CLEAR); ++ ++ regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_HSGMII_PCS_HSGMII_MODE_INTERRUPT, ++ AIROHA_PCS_HSGMII_MODE2_REMOVE_FAULT_OCCUR_INT_CLEAR | ++ AIROHA_PCS_HSGMII_MODE2_AN_CL37_TIMERDONE_INT_CLEAR | ++ AIROHA_PCS_HSGMII_MODE2_AN_MIS_INT_CLEAR | ++ AIROHA_PCS_HSGMII_MODE2_RX_SYN_DONE_INT_CLEAR | ++ AIROHA_PCS_HSGMII_MODE2_AN_DONE_INT_CLEAR); ++} ++ ++static void airoha_pcs_interrupt_init_usxgmii(struct airoha_pcs_priv *priv) ++{ ++ /* Disable every Interrupt */ ++ regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_CTRL_0, ++ AIROHA_PCS_USXGMII_T_TYPE_T_INT_EN | ++ AIROHA_PCS_USXGMII_T_TYPE_D_INT_EN | ++ AIROHA_PCS_USXGMII_T_TYPE_C_INT_EN | ++ AIROHA_PCS_USXGMII_T_TYPE_S_INT_EN); ++ ++ regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_CTRL_1, ++ AIROHA_PCS_USXGMII_R_TYPE_C_INT_EN | ++ AIROHA_PCS_USXGMII_R_TYPE_S_INT_EN | ++ AIROHA_PCS_USXGMII_TXPCS_FSM_ENC_ERR_INT_EN | ++ AIROHA_PCS_USXGMII_T_TYPE_E_INT_EN); ++ ++ regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_CTRL_2, ++ AIROHA_PCS_USXGMII_RPCS_FSM_DEC_ERR_INT_EN | ++ AIROHA_PCS_USXGMII_R_TYPE_E_INT_EN | ++ AIROHA_PCS_USXGMII_R_TYPE_T_INT_EN | ++ AIROHA_PCS_USXGMII_R_TYPE_D_INT_EN); ++ ++ regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_CTRL_3, ++ AIROHA_PCS_USXGMII_FAIL_SYNC_XOR_ST_INT_EN | ++ AIROHA_PCS_USXGMII_RX_BLOCK_LOCK_ST_INT_EN | ++ AIROHA_PCS_USXGMII_LINK_UP_ST_INT_EN | ++ AIROHA_PCS_USXGMII_HI_BER_ST_INT_EN); ++ ++ regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_CTRL_4, ++ AIROHA_PCS_USXGMII_LINK_DOWN_ST_INT_EN); ++ ++ /* Clear any pending interrupt */ ++ regmap_set_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_INT_STA_2, ++ AIROHA_PCS_USXGMII_RPCS_FSM_DEC_ERR_INT | ++ AIROHA_PCS_USXGMII_R_TYPE_E_INT | ++ AIROHA_PCS_USXGMII_R_TYPE_T_INT | ++ AIROHA_PCS_USXGMII_R_TYPE_D_INT); ++ ++ regmap_set_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_INT_STA_3, ++ AIROHA_PCS_USXGMII_FAIL_SYNC_XOR_ST_INT | ++ AIROHA_PCS_USXGMII_RX_BLOCK_LOCK_ST_INT | ++ AIROHA_PCS_USXGMII_LINK_UP_ST_INT | ++ AIROHA_PCS_USXGMII_HI_BER_ST_INT); ++ ++ regmap_set_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_INT_STA_4, ++ AIROHA_PCS_USXGMII_LINK_DOWN_ST_INT); ++ ++ /* Interrupt saddly seems to be not weel supported for Link Down. ++ * PCS Poll is a must to correctly read and react on Cable Deatch ++ * as only cable attach interrupt are fired and Link Down interrupt ++ * are fired only in special case like AN restart. ++ */ ++} ++ ++static void airoha_pcs_interrupt_init(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ return airoha_pcs_interrupt_init_sgmii(priv); ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ return airoha_pcs_interrupt_init_usxgmii(priv); ++ default: ++ return; ++ } ++} ++ ++static void airoha_pcs_jcpll_bringup(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ u32 kband_vref; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ kband_vref = 0x10; ++ break; ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ kband_vref = 0xf; ++ break; ++ default: ++ return; ++ } ++ ++ /* Setup LDO */ ++ usleep_range(200, 300); ++ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_SPARE_H, ++ AIROHA_PCS_ANA_JCPLL_SPARE_L_LDO); ++ ++ /* Setup RSTB */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY, ++ AIROHA_PCS_ANA_JCPLL_RST_DLY, ++ AIROHA_PCS_ANA_JCPLL_RST_DLY_150_200); ++ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY, ++ AIROHA_PCS_ANA_JCPLL_PLL_RSTB); ++ ++ /* Enable PLL force selection and Force Disable */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_CKOUT_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_JCPLL_EN | ++ AIROHA_PCS_PMA_FORCE_DA_JCPLL_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_JCPLL_EN); ++ ++ /* Setup SDM */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY, ++ AIROHA_PCS_ANA_JCPLL_SDM_DI_LS | ++ AIROHA_PCS_ANA_JCPLL_SDM_DI_EN, ++ AIROHA_PCS_ANA_JCPLL_SDM_DI_LS_2_23); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_SDM_IFM, ++ AIROHA_PCS_ANA_JCPLL_SDM_OUT | ++ AIROHA_PCS_ANA_JCPLL_SDM_ORD | ++ AIROHA_PCS_ANA_JCPLL_SDM_MODE | ++ AIROHA_PCS_ANA_JCPLL_SDM_IFM, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_SDM_ORD, 0x0) | ++ AIROHA_PCS_ANA_JCPLL_SDM_ORD_3SDM | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_SDM_MODE, 0x0)); ++ ++ regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_SDM_HREN, ++ AIROHA_PCS_ANA_JCPLL_SDM_HREN); ++ ++ /* Setup SSC */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_SSC_DELTA, ++ AIROHA_PCS_ANA_JCPLL_SSC_PERIOD | ++ AIROHA_PCS_ANA_JCPLL_SSC_DELTA, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_SSC_PERIOD, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_SSC_DELTA, 0x0)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_SSC_TRI_EN, ++ AIROHA_PCS_ANA_JCPLL_SSC_DELTA1 | ++ AIROHA_PCS_ANA_JCPLL_SSC_TRI_EN, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_SSC_DELTA1, 0x0)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_VCO_TCLVAR, ++ AIROHA_PCS_ANA_JCPLL_SSC_PHASE_INI | ++ AIROHA_PCS_ANA_JCPLL_SSC_EN | ++ AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_L | ++ AIROHA_PCS_ANA_JCPLL_VCO_TCLVAR, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_L, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_VCO_TCLVAR, 0x0)); ++ ++ /* Setup LPF */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_IB_EXT_EN, ++ AIROHA_PCS_ANA_JCPLL_CHP_IOFST | ++ AIROHA_PCS_ANA_JCPLL_CHP_IBIAS | ++ AIROHA_PCS_ANA_JCPLL_LPF_SHCK_EN, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_CHP_IOFST, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_CHP_IBIAS, 0x18)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_LPF_BR, ++ AIROHA_PCS_ANA_JCPLL_LPF_BWR | ++ AIROHA_PCS_ANA_JCPLL_LPF_BP | ++ AIROHA_PCS_ANA_JCPLL_LPF_BC | ++ AIROHA_PCS_ANA_JCPLL_LPF_BR, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_LPF_BWR, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_LPF_BP, 0x10) | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_LPF_BC, 0x1f) | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_LPF_BR, BIT(3) | BIT(1))); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_LPF_BWC, ++ AIROHA_PCS_ANA_JCPLL_LPF_BWC, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_LPF_BWC, 0x0)); ++ ++ /* Setup VCO */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_VCODIV, ++ AIROHA_PCS_ANA_JCPLL_VCO_SCAPWR | ++ AIROHA_PCS_ANA_JCPLL_VCO_HALFLSB_EN | ++ AIROHA_PCS_ANA_JCPLL_VCO_CFIX, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_VCO_SCAPWR, 0x4) | ++ AIROHA_PCS_ANA_JCPLL_VCO_HALFLSB_EN | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_VCO_CFIX, 0x1)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_VCO_TCLVAR, ++ AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_L | ++ AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_H | ++ AIROHA_PCS_ANA_JCPLL_VCO_TCLVAR, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_L, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_H, 0x3) | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_VCO_TCLVAR, 0x3)); ++ ++ /* Setup PCW */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_SDM_PCW, ++ AIROHA_PCS_PMA_FORCE_DA_JCPLL_SDM_PCW, ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_JCPLL_SDM_PCW, 0x25800000)); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_FE_VOS, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_JCPLL_SDM_PCW); ++ ++ /* Setup DIV */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_MMD_PREDIV_MODE, ++ AIROHA_PCS_ANA_JCPLL_POSTDIV_D5 | ++ AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE, ++ AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE_2); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_VCODIV, ++ AIROHA_PCS_ANA_JCPLL_VCODIV, ++ AIROHA_PCS_ANA_JCPLL_VCODIV_1); ++ ++ /* Setup KBand */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_KBAND_KFC, ++ AIROHA_PCS_ANA_JCPLL_KBAND_KS | ++ AIROHA_PCS_ANA_JCPLL_KBAND_KF | ++ AIROHA_PCS_ANA_JCPLL_KBAND_KFC, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_KBAND_KS, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_KBAND_KF, 0x3) | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_KBAND_KFC, 0x0)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_LPF_BWC, ++ AIROHA_PCS_ANA_JCPLL_KBAND_DIV | ++ AIROHA_PCS_ANA_JCPLL_KBAND_CODE | ++ AIROHA_PCS_ANA_JCPLL_KBAND_OPTION, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_KBAND_DIV, 0x2) | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_KBAND_CODE, 0xe4)); ++ ++ /* Setup TCL */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_SPARE_H, ++ AIROHA_PCS_ANA_JCPLL_TCL_KBAND_VREF, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_TCL_KBAND_VREF, kband_vref)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_SDM_HREN, ++ AIROHA_PCS_ANA_JCPLL_TCL_AMP_VREF | ++ AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN | ++ AIROHA_PCS_ANA_JCPLL_TCL_AMP_EN, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_TCL_AMP_VREF, 0x5) | ++ AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN_4 | ++ AIROHA_PCS_ANA_JCPLL_TCL_AMP_EN); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_TCL_CMP_EN, ++ AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW | ++ AIROHA_PCS_ANA_JCPLL_TCL_LPF_EN, ++ AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW_1 | ++ AIROHA_PCS_ANA_JCPLL_TCL_LPF_EN); ++ ++ /* Enable PLL */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_CKOUT_EN, ++ AIROHA_PCS_PMA_FORCE_DA_JCPLL_EN); ++ ++ /* Enale PLL Output */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_CKOUT_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_JCPLL_CKOUT_EN | ++ AIROHA_PCS_PMA_FORCE_DA_JCPLL_CKOUT_EN); ++} ++ ++static void airoha_pcs_txpll_bringup(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ u32 lpf_chp_ibias, lpf_bp, lpf_bwr, lpf_bwc; ++ u32 vco_cfix; ++ u32 pcw; ++ u32 tcl_amp_vref; ++ bool sdm_hren; ++ bool vcodiv; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ lpf_chp_ibias = 0xf; ++ lpf_bp = BIT(1); ++ lpf_bwr = BIT(3) | BIT(1) | BIT(0); ++ lpf_bwc = BIT(4) | BIT(3); ++ vco_cfix = BIT(1) | BIT(0); ++ pcw = BIT(27); ++ tcl_amp_vref = BIT(3) | BIT(1) | BIT(0); ++ vcodiv = false; ++ sdm_hren = false; ++ break; ++ case PHY_INTERFACE_MODE_2500BASEX: ++ lpf_chp_ibias = 0xa; ++ lpf_bp = BIT(2) | BIT(0); ++ lpf_bwr = 0; ++ lpf_bwc = 0; ++ vco_cfix = 0; ++ pcw = BIT(27) | BIT(25); ++ tcl_amp_vref = BIT(3) | BIT(2) | BIT(0); ++ vcodiv = true; ++ sdm_hren = false; ++ break; ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ lpf_chp_ibias = 0xf; ++ lpf_bp = BIT(1); ++ lpf_bwr = BIT(3) | BIT(1) | BIT(0); ++ lpf_bwc = BIT(4) | BIT(3); ++ vco_cfix = BIT(0); ++ pcw = BIT(27) | BIT(22); ++ tcl_amp_vref = BIT(3) | BIT(1) | BIT(0); ++ vcodiv = false; ++ sdm_hren = true; ++ break; ++ default: ++ return; ++ } ++ ++ /* Setup VCO LDO Output */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SSC_PERIOD, ++ AIROHA_PCS_ANA_TXPLL_LDO_VCO_OUT | ++ AIROHA_PCS_ANA_TXPLL_LDO_OUT, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LDO_VCO_OUT, 0x1) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LDO_OUT, 0x1)); ++ ++ /* Setup RSTB */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_REFIN_INTERNAL, ++ AIROHA_PCS_ANA_TXPLL_PLL_RSTB | ++ AIROHA_PCS_ANA_TXPLL_RST_DLY | ++ AIROHA_PCS_ANA_TXPLL_REFIN_DIV | ++ AIROHA_PCS_ANA_TXPLL_REFIN_INTERNAL, ++ AIROHA_PCS_ANA_TXPLL_PLL_RSTB | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_RST_DLY, 0x4) | ++ AIROHA_PCS_ANA_TXPLL_REFIN_DIV_1 | ++ AIROHA_PCS_ANA_TXPLL_REFIN_INTERNAL); ++ ++ /* Enable PLL force selection and Force Disable */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_CKOUT_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_EN | ++ AIROHA_PCS_PMA_FORCE_DA_TXPLL_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_EN); ++ ++ /* Setup SDM */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SDM_DI_EN, ++ AIROHA_PCS_ANA_TXPLL_SDM_MODE | ++ AIROHA_PCS_ANA_TXPLL_SDM_IFM | ++ AIROHA_PCS_ANA_TXPLL_SDM_DI_LS | ++ AIROHA_PCS_ANA_TXPLL_SDM_DI_EN, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_SDM_MODE, 0) | ++ AIROHA_PCS_ANA_TXPLL_SDM_DI_LS_2_23); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SDM_ORD, ++ AIROHA_PCS_ANA_TXPLL_SDM_HREN | ++ AIROHA_PCS_ANA_TXPLL_SDM_OUT | ++ AIROHA_PCS_ANA_TXPLL_SDM_ORD, ++ (sdm_hren ? AIROHA_PCS_ANA_TXPLL_SDM_HREN : 0) | ++ AIROHA_PCS_ANA_TXPLL_SDM_ORD_3SDM); ++ ++ /* Setup SSC */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SSC_DELTA1, ++ AIROHA_PCS_ANA_TXPLL_SSC_DELTA | ++ AIROHA_PCS_ANA_TXPLL_SSC_DELTA1, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_SSC_DELTA, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_SSC_DELTA1, 0x0)); ++ ++ regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SSC_EN, ++ AIROHA_PCS_ANA_TXPLL_SSC_TRI_EN | ++ AIROHA_PCS_ANA_TXPLL_SSC_PHASE_INI | ++ AIROHA_PCS_ANA_TXPLL_SSC_EN); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SSC_PERIOD, ++ AIROHA_PCS_ANA_TXPLL_SSC_PERIOD, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_SSC_PERIOD, 0x0)); ++ ++ /* Setup LPF */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_CHP_IBIAS, ++ AIROHA_PCS_ANA_TXPLL_LPF_BC | ++ AIROHA_PCS_ANA_TXPLL_LPF_BR | ++ AIROHA_PCS_ANA_TXPLL_CHP_IOFST | ++ AIROHA_PCS_ANA_TXPLL_CHP_IBIAS, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BC, 0x1f) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BR, 0x5) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_CHP_IOFST, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_CHP_IBIAS, lpf_chp_ibias)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_LPF_BP, ++ AIROHA_PCS_ANA_TXPLL_LPF_BWC | ++ AIROHA_PCS_ANA_TXPLL_LPF_BWR | ++ AIROHA_PCS_ANA_TXPLL_LPF_BP, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BWC, lpf_bwc) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BWR, lpf_bwr) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BP, lpf_bp)); ++ ++ /* Setup VCO */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_LPF_EN, ++ AIROHA_PCS_ANA_TXPLL_VCO_CFIX, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_CFIX, vco_cfix)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_VCO_HALFLSB_EN, ++ AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_L | ++ AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_H | ++ AIROHA_PCS_ANA_TXPLL_VCO_TCLVAR | ++ AIROHA_PCS_ANA_TXPLL_VCO_SCAPWR | ++ AIROHA_PCS_ANA_TXPLL_VCO_HALFLSB_EN, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_L, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_H, 0x4) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_TCLVAR, 0x4) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_SCAPWR, 0x7) | ++ AIROHA_PCS_ANA_TXPLL_VCO_HALFLSB_EN); ++ ++ /* Setup PCW */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_SDM_PCW, ++ AIROHA_PCS_PMA_FORCE_DA_TXPLL_SDM_PCW, pcw); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_IDAC, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_SDM_PCW); ++ ++ /* Setup KBand */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_KBAND_CODE, ++ AIROHA_PCS_ANA_TXPLL_KBAND_KF | ++ AIROHA_PCS_ANA_TXPLL_KBAND_KFC | ++ AIROHA_PCS_ANA_TXPLL_KBAND_DIV | ++ AIROHA_PCS_ANA_TXPLL_KBAND_CODE, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_KF, 0x3) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_KFC, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_DIV, 0x4) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_CODE, 0xe4)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_KBAND_KS, ++ AIROHA_PCS_ANA_TXPLL_KBAND_KS, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_KS, 0x1)); ++ ++ regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_LPF_BP, ++ AIROHA_PCS_ANA_TXPLL_KBAND_OPTION); ++ ++ /* Setup DIV */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_KBAND_KS, ++ AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE | ++ AIROHA_PCS_ANA_TXPLL_POSTDIV_EN, ++ AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE_2); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_LPF_EN, ++ AIROHA_PCS_ANA_TXPLL_VCODIV, ++ vcodiv ? AIROHA_PCS_ANA_TXPLL_VCODIV_2 : ++ AIROHA_PCS_ANA_TXPLL_VCODIV_1); ++ ++ /* Setup TCL */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_KBAND_VREF, ++ AIROHA_PCS_ANA_TXPLL_TCL_KBAND_VREF, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_TCL_KBAND_VREF, 0xf)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_AMP_GAIN, ++ AIROHA_PCS_ANA_TXPLL_TCL_AMP_VREF | ++ AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_TCL_AMP_VREF, tcl_amp_vref) | ++ AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN_4); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_LPF_EN, ++ AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW | ++ AIROHA_PCS_ANA_TXPLL_TCL_LPF_EN, ++ AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW_0_5 | ++ AIROHA_PCS_ANA_TXPLL_TCL_LPF_EN); ++ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SDM_ORD, ++ AIROHA_PCS_ANA_TXPLL_TCL_AMP_EN); ++ ++ /* Enable PLL */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_CKOUT_EN, ++ AIROHA_PCS_PMA_FORCE_DA_TXPLL_EN); ++ ++ /* Enale PLL Output */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_CKOUT_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_CKOUT_EN | ++ AIROHA_PCS_PMA_FORCE_DA_TXPLL_CKOUT_EN); ++} ++ ++static void airoha_pcs_pll_bringup(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ airoha_pcs_jcpll_bringup(priv, interface); ++ ++ usleep_range(200, 300); ++ ++ airoha_pcs_txpll_bringup(priv, interface); ++ ++ usleep_range(200, 300); ++} ++ ++static void airoha_pcs_tx_bringup(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ u32 tx_rate_ctrl; ++ u32 ckin_divisor; ++ u32 fir_cn1, fir_c0b, fir_c1; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ ckin_divisor = BIT(1); ++ tx_rate_ctrl = BIT(0); ++ fir_cn1 = 0; ++ fir_c0b = 12; ++ fir_c1 = 0; ++ break; ++ case PHY_INTERFACE_MODE_2500BASEX: ++ ckin_divisor = BIT(2); ++ tx_rate_ctrl = BIT(0); ++ fir_cn1 = 0; ++ fir_c0b = 11; ++ fir_c1 = 1; ++ break; ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ ckin_divisor = BIT(2) | BIT(0); ++ tx_rate_ctrl = BIT(1); ++ fir_cn1 = 1; ++ fir_c0b = 1; ++ fir_c1 = 11; ++ break; ++ default: ++ return; ++ } ++ ++ /* Set TX rate ctrl */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_XPON_TX_RATE_CTRL, ++ AIROHA_PCS_PMA_PON_TX_RATE_CTRL, ++ FIELD_PREP(AIROHA_PCS_PMA_PON_TX_RATE_CTRL, ++ tx_rate_ctrl)); ++ ++ /* Setup TX Config */ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TX_CKLDO_EN, ++ AIROHA_PCS_ANA_TX_DMEDGEGEN_EN | ++ AIROHA_PCS_ANA_TX_CKLDO_EN); ++ ++ udelay(1); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_ACJTAG_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_CKIN_SEL | ++ AIROHA_PCS_PMA_FORCE_DA_TX_CKIN_SEL); ++ ++ /* FIXME: Ask Airoha TX term is OK to reset? */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_TERM_SEL, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_CKIN_DIVISOR | ++ AIROHA_PCS_PMA_FORCE_DA_TX_CKIN_DIVISOR | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_TERM_SEL | ++ AIROHA_PCS_PMA_FORCE_DA_TX_TERM_SEL, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_CKIN_DIVISOR | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_CKIN_DIVISOR, ++ ckin_divisor) | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_TERM_SEL, 0x0)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_RATE_CTRL, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_RATE_CTRL | ++ AIROHA_PCS_PMA_FORCE_DA_TX_RATE_CTRL, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_RATE_CTRL | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_RATE_CTRL, ++ tx_rate_ctrl)); ++ ++ /* Setup TX FIR Load Parameters (Reference 660mV) */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_FIR_C0B, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_CN1 | ++ AIROHA_PCS_PMA_FORCE_DA_TX_FIR_CN1 | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C0B | ++ AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C0B, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_CN1 | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_FIR_CN1, fir_cn1) | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C0B | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C0B, fir_c0b)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_FIR_C1, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C2 | ++ AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C2 | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C1 | ++ AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C1, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C1 | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C1, fir_c1)); ++ ++ /* Reset TX Bar */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_TX_RST_B, ++ AIROHA_PCS_PMA_TXCALIB_RST_B | AIROHA_PCS_PMA_TX_TOP_RST_B); ++} ++ ++static void airoha_pcs_rx_bringup(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ u32 rx_rate_ctrl; ++ u32 osr; ++ u32 pr_cdr_beta_dac; ++ u32 cdr_pr_buf_in_sr; ++ bool cdr_pr_cap_en; ++ u32 sigdet_vth_sel; ++ u32 phyck_div, phyck_sel; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ osr = BIT(1) | BIT(0); /* 1.25G */ ++ pr_cdr_beta_dac = BIT(3); ++ rx_rate_ctrl = 0; ++ cdr_pr_cap_en = false; ++ cdr_pr_buf_in_sr = BIT(2) | BIT(1) | BIT(0); ++ sigdet_vth_sel = BIT(2) | BIT(1); ++ phyck_div = BIT(5) | BIT(3) | BIT(0); ++ phyck_sel = BIT(0); ++ break; ++ case PHY_INTERFACE_MODE_2500BASEX: ++ osr = BIT(0); /* 2.5G */ ++ pr_cdr_beta_dac = BIT(2) | BIT(1); ++ rx_rate_ctrl = 0; ++ cdr_pr_cap_en = true; ++ cdr_pr_buf_in_sr = BIT(2) | BIT(1); ++ sigdet_vth_sel = BIT(2) | BIT(1); ++ phyck_div = BIT(3) | BIT(1) | BIT(0); ++ phyck_sel = BIT(0); ++ break; ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ osr = 0; /* 10G */ ++ cdr_pr_cap_en = false; ++ pr_cdr_beta_dac = BIT(3); ++ rx_rate_ctrl = BIT(1); ++ cdr_pr_buf_in_sr = BIT(2) | BIT(1) | BIT(0); ++ sigdet_vth_sel = BIT(1); ++ phyck_div = BIT(6) | BIT(1); ++ phyck_sel = BIT(1); ++ break; ++ default: ++ return; ++ } ++ ++ /* Set RX rate ctrl */ ++ if (interface == PHY_INTERFACE_MODE_2500BASEX) ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_2, ++ AIROHA_PCS_PMA_CK_RATE, ++ AIROHA_PCS_PMA_CK_RATE_10); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_XPON_RX_RESERVED_1, ++ AIROHA_PCS_PMA_XPON_RX_RATE_CTRL, ++ FIELD_PREP(AIROHA_PCS_PMA_XPON_RX_RATE_CTRL, rx_rate_ctrl)); ++ ++ /* Setup RX Path */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_5, ++ AIROHA_PCS_PMA_FLL_IDAC_MIN | ++ AIROHA_PCS_PMA_FLL_IDAC_MAX, ++ FIELD_PREP(AIROHA_PCS_PMA_FLL_IDAC_MIN, 0x400) | ++ FIELD_PREP(AIROHA_PCS_PMA_FLL_IDAC_MAX, 0x3ff)); ++ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_DAC_D1_BYPASS_AEQ, ++ AIROHA_PCS_ANA_RX_DAC_EYE_BYPASS_AEQ | ++ AIROHA_PCS_ANA_RX_DAC_E1_BYPASS_AEQ | ++ AIROHA_PCS_ANA_RX_DAC_E0_BYPASS_AEQ | ++ AIROHA_PCS_ANA_RX_DAC_D1_BYPASS_AEQ); ++ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_FE_PEAKING_CTRL_MSB, ++ AIROHA_PCS_ANA_RX_DAC_D0_BYPASS_AEQ); ++ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_FE_VCM_GEN_PWDB, ++ AIROHA_PCS_ANA_FE_VCM_GEN_PWDB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_LCPLL_PWCTL_SETTING_1, ++ AIROHA_PCS_PMA_LCPLL_MAN_PWDB); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_AEQ_CFORCE, ++ AIROHA_PCS_ANA_AEQ_OFORCE, ++ AIROHA_PCS_ANA_AEQ_OFORCE_CTLE); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_OSCAL_WATCH_WNDW, ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE, ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA2VOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA2IOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA1VOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA1IOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE2VOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE2IOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE1VOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE1IOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_LVSH | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_COMPOS); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_4, ++ AIROHA_PCS_PMA_DISB_BLWC_OFFSET); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EXTRAL_CTRL, ++ AIROHA_PCS_PMA_DISB_LEQ); ++ ++ regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PD_PICAL_CKD8_INV, ++ AIROHA_PCS_ANA_CDR_PD_EDGE_DIS | ++ AIROHA_PCS_ANA_CDR_PD_PICAL_CKD8_INV); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_AEQ_BYPASS, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_AEQ_CKON | ++ AIROHA_PCS_PMA_FORCE_DA_AEQ_CKON, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_AEQ_CKON); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_AEQ_RSTB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_INJCK_SEL | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_INJCK_SEL); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_MONPR_EN, ++ AIROHA_PCS_ANA_RX_DAC_MON | ++ AIROHA_PCS_ANA_CDR_PR_XFICK_EN | ++ AIROHA_PCS_ANA_CDR_PR_MONDPI_EN | ++ AIROHA_PCS_ANA_CDR_PR_MONDPR_EN, ++ FIELD_PREP(AIROHA_PCS_ANA_RX_DAC_MON, 0x0) | ++ AIROHA_PCS_ANA_CDR_PR_XFICK_EN); ++ ++ /* Setup FE Gain and FE Peacking */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_FE_GAIN_CTRL, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_GAIN_CTRL | ++ AIROHA_PCS_PMA_FORCE_DA_RX_FE_GAIN_CTRL, ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_RX_FE_GAIN_CTRL, 0x0)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_SDM_SCAN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_PEAKING_CTRL | ++ AIROHA_PCS_PMA_FORCE_DA_RX_PEAKING_CTRL, ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_RX_PEAKING_CTRL, 0x0)); ++ ++ /* Setup FE VOS */ ++ if (interface != PHY_INTERFACE_MODE_USXGMII && ++ interface != PHY_INTERFACE_MODE_10GBASER) ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_FE_VOS, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_FE_VOS | ++ AIROHA_PCS_PMA_FORCE_DA_FE_VOS, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_FE_VOS | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_FE_VOS, 0x0)); ++ ++ /* Setup FLL PR FMeter (no bypass mode)*/ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PLL_TDC_FREQDET_0, ++ AIROHA_PCS_PMA_PLL_LOCK_CYCLECNT, ++ FIELD_PREP(AIROHA_PCS_PMA_PLL_LOCK_CYCLECNT, 0x1)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PLL_TDC_FREQDET_1, ++ AIROHA_PCS_PMA_PLL_LOCK_TARGET_END | ++ AIROHA_PCS_PMA_PLL_LOCK_TARGET_BEG, ++ FIELD_PREP(AIROHA_PCS_PMA_PLL_LOCK_TARGET_END, 0xffff) | ++ FIELD_PREP(AIROHA_PCS_PMA_PLL_LOCK_TARGET_BEG, 0x0)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PLL_TDC_FREQDET_3, ++ AIROHA_PCS_PMA_PLL_LOCK_LOCKTH, ++ FIELD_PREP(AIROHA_PCS_PMA_PLL_LOCK_LOCKTH, 0x1)); ++ ++ /* FIXME: Warn and Ask Airoha about typo in air_eth_xsgmii.c line 1391 */ ++ /* AIROHA_PCS_ANA_REV_1_FE_BUF1_BIAS_CTRL is set 0x0 in SDK but seems a typo */ ++ /* Setup REV */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_REV_0, ++ AIROHA_PCS_ANA_REV_1_FE_BUF1_BIAS_CTRL | ++ AIROHA_PCS_ANA_REV_1_FE_BUF2_BIAS_CTRL | ++ AIROHA_PCS_ANA_REV_1_SIGDET_ILEAK, ++ FIELD_PREP(AIROHA_PCS_ANA_REV_1_FE_BUF1_BIAS_CTRL, BIT(2)) | ++ FIELD_PREP(AIROHA_PCS_ANA_REV_1_FE_BUF2_BIAS_CTRL, BIT(2)) | ++ FIELD_PREP(AIROHA_PCS_ANA_REV_1_SIGDET_ILEAK, 0x0)); ++ ++ /* Setup Rdy Timeout */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_5, ++ AIROHA_PCS_PMA_RX_RDY | ++ AIROHA_PCS_PMA_RX_BLWC_RDY_EN, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_RDY, 0xa) | ++ FIELD_PREP(AIROHA_PCS_PMA_RX_BLWC_RDY_EN, 0x5)); ++ ++ /* Setup CaBoundry Init */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_0, ++ AIROHA_PCS_PMA_RX_OS_START | ++ AIROHA_PCS_PMA_OSC_SPEED_OPT, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_OS_START, 0x1) | ++ AIROHA_PCS_PMA_OSC_SPEED_OPT_0_1); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_6, ++ AIROHA_PCS_PMA_RX_OS_END, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_OS_END, 0x2)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_1, ++ AIROHA_PCS_PMA_RX_PICAL_END | ++ AIROHA_PCS_PMA_RX_PICAL_START, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_PICAL_END, 0x32) | ++ FIELD_PREP(AIROHA_PCS_PMA_RX_PICAL_START, 0x2)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_4, ++ AIROHA_PCS_PMA_RX_SDCAL_END | ++ AIROHA_PCS_PMA_RX_SDCAL_START, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_SDCAL_END, 0x32) | ++ FIELD_PREP(AIROHA_PCS_PMA_RX_SDCAL_START, 0x2)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_2, ++ AIROHA_PCS_PMA_RX_PDOS_END | ++ AIROHA_PCS_PMA_RX_PDOS_START, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_PDOS_END, 0x32) | ++ FIELD_PREP(AIROHA_PCS_PMA_RX_PDOS_START, 0x2)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_3, ++ AIROHA_PCS_PMA_RX_FEOS_END | ++ AIROHA_PCS_PMA_RX_FEOS_START, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_FEOS_END, 0x32) | ++ FIELD_PREP(AIROHA_PCS_PMA_RX_FEOS_START, 0x2)); ++ ++ /* Setup By Serdes*/ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_AEQ_SPEED, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_OSR_SEL | ++ AIROHA_PCS_PMA_FORCE_DA_OSR_SEL, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_OSR_SEL | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_OSR_SEL, osr)); ++ ++ /* Setup RX OSR */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PD_PICAL_CKD8_INV, ++ AIROHA_PCS_ANA_CDR_PD_EDGE_DIS, ++ osr ? AIROHA_PCS_ANA_CDR_PD_EDGE_DIS : 0); ++ ++ /* Setup CDR LPF Ratio */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_LPF_RATIO, ++ AIROHA_PCS_ANA_CDR_LPF_TOP_LIM | ++ AIROHA_PCS_ANA_CDR_LPF_RATIO, ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_LPF_TOP_LIM, 0x20000) | ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_LPF_RATIO, osr)); ++ ++ /* Setup CDR PR */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_BETA_DAC, ++ AIROHA_PCS_ANA_CDR_PR_KBAND_DIV | ++ AIROHA_PCS_ANA_CDR_PR_BETA_SEL | ++ AIROHA_PCS_ANA_CDR_PR_VCOADC_OS | ++ AIROHA_PCS_ANA_CDR_PR_BETA_DAC, ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_KBAND_DIV, 0x4) | ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_BETA_SEL, 0x1) | ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_VCOADC_OS, 0x8) | ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_BETA_DAC, pr_cdr_beta_dac)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_VREG_IBAND_VAL, ++ AIROHA_PCS_ANA_CDR_PR_FBKSEL | ++ AIROHA_PCS_ANA_CDR_PR_VREG_DAC_BAND | ++ AIROHA_PCS_ANA_CDR_PR_VREG_CKBUF_VAL | ++ AIROHA_PCS_ANA_CDR_PR_VREG_IBAND_VAL, ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_FBKSEL, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_VREG_DAC_BAND, pr_cdr_beta_dac) | ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_VREG_CKBUF_VAL, 0x6) | ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_VREG_IBAND_VAL, 0x6)); ++ ++ /* Setup Eye Mon */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PHY_EQ_CTRL_3, ++ AIROHA_PCS_PMA_EQ_DEBUG_SEL | ++ AIROHA_PCS_PMA_FOM_NUM_ORDER | ++ AIROHA_PCS_PMA_A_SEL, ++ FIELD_PREP(AIROHA_PCS_PMA_EQ_DEBUG_SEL, 0x0) | ++ FIELD_PREP(AIROHA_PCS_PMA_FOM_NUM_ORDER, 0x1) | ++ FIELD_PREP(AIROHA_PCS_PMA_A_SEL, 0x3)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_2, ++ AIROHA_PCS_PMA_DATA_SHIFT | ++ AIROHA_PCS_PMA_EYECNT_FAST, ++ AIROHA_PCS_PMA_EYECNT_FAST); ++ ++ /* Calibration Start */ ++ ++ /* Enable SYS */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_SYS_EN_SEL_0, ++ AIROHA_PCS_PMA_RX_SYS_EN_SEL, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_SYS_EN_SEL, 0x1)); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_LCPLL_PWCTL_SETTING_0, ++ AIROHA_PCS_PMA_SW_LCPLL_EN); ++ ++ usleep_range(500, 600); ++ ++ /* Setup FLL PR FMeter (bypass mode)*/ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_8, ++ AIROHA_PCS_PMA_DISB_FBCK_LOCK); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_9, ++ AIROHA_PCS_PMA_FORCE_FBCK_LOCK); ++ ++ /* Enable CMLEQ */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_FE_EQ_HZEN, ++ AIROHA_PCS_ANA_RX_FE_VB_EQ3_EN | ++ AIROHA_PCS_ANA_RX_FE_VB_EQ2_EN | ++ AIROHA_PCS_ANA_RX_FE_VB_EQ1_EN | ++ AIROHA_PCS_ANA_RX_FE_EQ_HZEN, ++ AIROHA_PCS_ANA_RX_FE_VB_EQ3_EN | ++ AIROHA_PCS_ANA_RX_FE_VB_EQ2_EN | ++ AIROHA_PCS_ANA_RX_FE_VB_EQ1_EN); ++ ++ /* Setup CDR PR */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_MONPR_EN, ++ AIROHA_PCS_ANA_CDR_PR_CAP_EN | ++ AIROHA_PCS_ANA_CDR_BUF_IN_SR, ++ (cdr_pr_cap_en ? AIROHA_PCS_ANA_CDR_PR_CAP_EN : 0) | ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_BUF_IN_SR, cdr_pr_buf_in_sr)); ++ ++ /* Setup CDR xxx Pwdb, set force and disable */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PWDB | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PWDB | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PIEYE_PWDB | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PIEYE_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PWDB | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PIEYE_PWDB); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PD_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_KBAND_RSTB | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_KBAND_RSTB | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PD_PWDB | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PD_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PD_PWDB); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_FE_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_PDOSCAL_EN | ++ AIROHA_PCS_PMA_FORCE_DA_RX_PDOSCAL_EN | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PWDB | ++ AIROHA_PCS_PMA_FORCE_DA_RX_FE_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PWDB); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_SCAN_RST_B, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SIGDET_PWDB | ++ AIROHA_PCS_PMA_FORCE_DA_RX_SIGDET_PWDB | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SCAN_RST_B | ++ AIROHA_PCS_PMA_FORCE_DA_RX_SCAN_RST_B, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SIGDET_PWDB); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_DA_XPON_PWDB_0, ++ AIROHA_PCS_PMA_XPON_CDR_PR_PD_PWDB | ++ AIROHA_PCS_PMA_XPON_CDR_PR_PIEYE_PWDB | ++ AIROHA_PCS_PMA_XPON_CDR_PW_PWDB | ++ AIROHA_PCS_PMA_XPON_RX_FE_PWDB); ++ ++ /* FIXME: Ask Airoha WHY it's cleared? */ ++ /* regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_SIGDET_NOVTH, ++ * AIROHA_PCS_ANA_RX_FE_50OHMS_SEL); ++ */ ++ ++ /* Setup SigDet */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_SIGDET_NOVTH, ++ AIROHA_PCS_ANA_RX_SIGDET_VTH_SEL | ++ AIROHA_PCS_ANA_RX_SIGDET_PEAK, ++ FIELD_PREP(AIROHA_PCS_ANA_RX_SIGDET_VTH_SEL, sigdet_vth_sel) | ++ FIELD_PREP(AIROHA_PCS_ANA_RX_SIGDET_PEAK, BIT(1))); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_DAC_RANGE, ++ AIROHA_PCS_ANA_RX_SIGDET_LPF_CTRL, ++ FIELD_PREP(AIROHA_PCS_ANA_RX_SIGDET_LPF_CTRL, BIT(1) | BIT(0))); ++ ++ /* Disable SigDet Pwdb */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_DA_XPON_PWDB_1, ++ AIROHA_PCS_PMA_RX_SIDGET_PWDB); ++ ++ /* Setup PHYCK */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_PHYCK_DIV, ++ AIROHA_PCS_ANA_RX_TDC_CK_SEL | ++ AIROHA_PCS_ANA_RX_PHYCK_RSTB | ++ AIROHA_PCS_ANA_RX_PHYCK_SEL | ++ AIROHA_PCS_ANA_RX_PHYCK_DIV, ++ AIROHA_PCS_ANA_RX_PHYCK_RSTB | ++ FIELD_PREP(AIROHA_PCS_ANA_RX_PHYCK_SEL, phyck_sel) | ++ FIELD_PREP(AIROHA_PCS_ANA_RX_PHYCK_DIV, phyck_div)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_BUSBIT_SEL, ++ AIROHA_PCS_ANA_RX_PHY_CK_SEL_FORCE | ++ AIROHA_PCS_ANA_RX_PHY_CK_SEL, ++ AIROHA_PCS_ANA_RX_PHY_CK_SEL_FORCE); ++ ++ usleep_range(100, 200); ++ ++ /* Enable CDR xxx Pwdb */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PWDB | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PIEYE_PWDB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PD_PWDB, ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PD_PWDB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_FE_PWDB, ++ AIROHA_PCS_PMA_FORCE_DA_RX_FE_PWDB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_SCAN_RST_B, ++ AIROHA_PCS_PMA_FORCE_DA_RX_SIGDET_PWDB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_DA_XPON_PWDB_0, ++ AIROHA_PCS_PMA_XPON_CDR_PR_PD_PWDB | ++ AIROHA_PCS_PMA_XPON_CDR_PR_PIEYE_PWDB | ++ AIROHA_PCS_PMA_XPON_CDR_PW_PWDB | ++ AIROHA_PCS_PMA_XPON_RX_FE_PWDB); ++ ++ /* Enable SigDet Pwdb */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_DA_XPON_PWDB_1, ++ AIROHA_PCS_PMA_RX_SIDGET_PWDB); ++} ++ ++static unsigned int airoha_pcs_apply_cdr_pr_idac(struct airoha_pcs_priv *priv, ++ u32 cdr_pr_idac) ++{ ++ u32 val; ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_IDAC, ++ AIROHA_PCS_PMA_FORCE_CDR_PR_IDAC, ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_CDR_PR_IDAC, ++ cdr_pr_idac)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_FREQ_DET_4, ++ AIROHA_PCS_PMA_FREQLOCK_DET_EN, ++ AIROHA_PCS_PMA_FREQLOCK_DET_EN_FORCE_0); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_FREQ_DET_4, ++ AIROHA_PCS_PMA_FREQLOCK_DET_EN, ++ AIROHA_PCS_PMA_FREQLOCK_DET_EN_NORMAL); ++ ++ usleep_range(5000, 7000); ++ ++ regmap_read(priv->xfi_pma, AIROHA_PCS_PMA_RX_FREQDET, &val); ++ ++ return FIELD_GET(AIROHA_PCS_PMA_FL_OUT, val); ++} ++ ++static void airoha_pcs_rx_prcal(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ unsigned int remaining_prcal_search_bits; ++ unsigned int fl_out_diff = UINT_MAX; ++ u32 best_prcal_search_bit; ++ unsigned int prcal_search; ++ int prcal_search_bit; ++ unsigned int fl_out; ++ int cdr_pr_idac = 0; ++ ++ u32 target_fl_out; ++ u32 cyclecnt; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: /* DS_1.25G / US_1.25G */ ++ case PHY_INTERFACE_MODE_1000BASEX: ++ target_fl_out = 0xa3d6; ++ cyclecnt = 32767; ++ break; ++ case PHY_INTERFACE_MODE_2500BASEX: /* DS_9.95328G / US_9.95328G */ ++ target_fl_out = 0xa000; ++ cyclecnt = 20000; ++ break; ++ case PHY_INTERFACE_MODE_USXGMII: /* DS_10.3125G / US_1.25G */ ++ case PHY_INTERFACE_MODE_10GBASER: ++ target_fl_out = 0x9edf; ++ cyclecnt = 32767; ++ break; ++ default: ++ return; ++ } ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_REF_RST_N); ++ ++ usleep_range(100, 200); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_FREQ_DET_2, ++ AIROHA_PCS_PMA_LOCK_TARGET_END | ++ AIROHA_PCS_PMA_LOCK_TARGET_BEG, ++ FIELD_PREP(AIROHA_PCS_PMA_LOCK_TARGET_END, target_fl_out + 100) | ++ FIELD_PREP(AIROHA_PCS_PMA_LOCK_TARGET_BEG, target_fl_out - 100)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_FREQ_DET_1, ++ AIROHA_PCS_PMA_UNLOCK_CYCLECNT | ++ AIROHA_PCS_PMA_LOCK_CYCLECNT, ++ FIELD_PREP(AIROHA_PCS_PMA_UNLOCK_CYCLECNT, cyclecnt) | ++ FIELD_PREP(AIROHA_PCS_PMA_LOCK_CYCLECNT, cyclecnt)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_FREQ_DET_4, ++ AIROHA_PCS_PMA_LOCK_UNLOCKTH | ++ AIROHA_PCS_PMA_LOCK_LOCKTH, ++ FIELD_PREP(AIROHA_PCS_PMA_LOCK_UNLOCKTH, 3) | ++ FIELD_PREP(AIROHA_PCS_PMA_LOCK_LOCKTH, 3)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_FREQ_DET_3, ++ AIROHA_PCS_PMA_UNLOCK_TARGET_END | ++ AIROHA_PCS_PMA_UNLOCK_TARGET_BEG, ++ FIELD_PREP(AIROHA_PCS_PMA_UNLOCK_TARGET_END, target_fl_out + 100) | ++ FIELD_PREP(AIROHA_PCS_PMA_UNLOCK_TARGET_BEG, target_fl_out - 100)); ++ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_INJ_MODE, ++ AIROHA_PCS_ANA_CDR_PR_INJ_FORCE_OFF); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_LPF_C_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_LPF_R_EN | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_LPF_R_EN | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_LPF_C_EN | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_LPF_C_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_LPF_R_EN | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_LPF_R_EN | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_LPF_C_EN); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_IDAC, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_IDAC); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PWDB); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PWDB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PWDB); ++ ++ /* Calibration logic: ++ * First check the major value by looping with every ++ * value in the last 3 bit of CDR_PR_IDAC. ++ * Get the signal level and save the value that is closer to ++ * the target. ++ * ++ * Then check each remaining 7 bits in search of the deadline ++ * where the signal gets farther than signal target. ++ * ++ * Finally fine tune for the remaining bits to find the one that ++ * produce the closest signal level. ++ */ ++ for (prcal_search = 0; prcal_search < 8 ; prcal_search++) { ++ unsigned int fl_out_diff_new; ++ u32 cdr_pr_idac_tmp; ++ ++ /* try to find the upper value by setting the last 3 bit */ ++ cdr_pr_idac_tmp = FIELD_PREP(AIROHA_PCS_PMA_FORCE_CDR_PR_IDAC_MAJOR, ++ prcal_search); ++ fl_out = airoha_pcs_apply_cdr_pr_idac(priv, cdr_pr_idac_tmp); ++ ++ /* Use absolute values to find the closest one to target */ ++ fl_out_diff_new = abs(fl_out - target_fl_out); ++ if (fl_out_diff_new < fl_out_diff) { ++ cdr_pr_idac = cdr_pr_idac_tmp; ++ fl_out_diff = fl_out_diff_new; ++ } ++ } ++ ++ /* Deadline search part. ++ * We start from top bits to bottom as we progressively decrease the ++ * signal. ++ */ ++ for (prcal_search_bit = 7; prcal_search_bit >= 0; prcal_search_bit--) { ++ unsigned int fl_out_diff_new; ++ u32 cdr_pr_idac_tmp; ++ ++ cdr_pr_idac_tmp = cdr_pr_idac | BIT(prcal_search_bit); ++ fl_out = airoha_pcs_apply_cdr_pr_idac(priv, cdr_pr_idac_tmp); ++ ++ /* Use absolute values to find the closest one to target */ ++ fl_out_diff_new = abs(fl_out - target_fl_out); ++ if (fl_out_diff_new < fl_out_diff) { ++ best_prcal_search_bit = prcal_search_bit; ++ fl_out_diff = fl_out_diff_new; ++ } ++ } ++ ++ /* Set the idac with the best value we found and ++ * reset the search bit to start from bottom to top. ++ */ ++ cdr_pr_idac |= BIT(best_prcal_search_bit); ++ remaining_prcal_search_bits = best_prcal_search_bit; ++ prcal_search_bit = 0; ++ ++ /* Fine tune part. ++ * Test remaining bits to find an even closer signal level to target ++ * by increasing the signal. ++ */ ++ while (remaining_prcal_search_bits) { ++ unsigned int fl_out_diff_new; ++ u32 cdr_pr_idac_tmp; ++ ++ cdr_pr_idac_tmp = cdr_pr_idac | BIT(prcal_search_bit); ++ fl_out = airoha_pcs_apply_cdr_pr_idac(priv, cdr_pr_idac_tmp); ++ ++ /* Use absolute values to find the closest one to target */ ++ fl_out_diff_new = abs(fl_out - target_fl_out); ++ /* Assume we found the deadline when the new absolue signal difference ++ * from target is greater than the previous and the difference is at ++ * least 10% greater between the old and new value. ++ * This is to account for signal detection level tollerance making ++ * sure we are actually over a deadline (AKA we are getting farther ++ * from target) ++ */ ++ if (fl_out_diff_new > fl_out_diff && ++ (abs(fl_out_diff_new - fl_out_diff) * 100) / fl_out_diff > 10) { ++ /* Exit early if we are already at the deadline */ ++ if (prcal_search_bit == 0) ++ break; ++ ++ /* We found the deadline, set the value to the previous ++ * bit, and reset the loop to fine tune with the ++ * remaining values. ++ */ ++ cdr_pr_idac |= BIT(prcal_search_bit - 1); ++ remaining_prcal_search_bits = prcal_search_bit - 1; ++ prcal_search_bit = 0; ++ } else { ++ /* Update the signal level diff and try the next bit */ ++ fl_out_diff = fl_out_diff_new; ++ ++ /* If we didn't found the deadline, set the last bit ++ * and reset the loop to fine tune with the remainig ++ * values. ++ */ ++ if (prcal_search_bit == remaining_prcal_search_bits - 1) { ++ cdr_pr_idac |= BIT(prcal_search_bit); ++ remaining_prcal_search_bits = prcal_search_bit; ++ prcal_search_bit = 0; ++ } else { ++ prcal_search_bit++; ++ } ++ } ++ } ++ ++ fl_out = airoha_pcs_apply_cdr_pr_idac(priv, cdr_pr_idac); ++ dev_dbg(priv->dev, "Selected CDR Pr Idac: %x Fl Out: %x\n", cdr_pr_idac, fl_out); ++ if (abs(fl_out - target_fl_out) > 100) ++ dev_dbg(priv->dev, "Fl Out is %d far from target %d on intermediate calibration.\n", ++ abs(fl_out - target_fl_out), target_fl_out); ++ ++ /* Setup Load Band */ ++ regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_INJ_MODE, ++ AIROHA_PCS_ANA_CDR_PR_INJ_FORCE_OFF); ++ ++ /* Disable force of LPF C previously enabled */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_LPF_C_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_LPF_C_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_IDAC, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_IDAC); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_B, ++ AIROHA_PCS_PMA_LOAD_EN); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_1, ++ AIROHA_PCS_PMA_LPATH_IDAC, ++ FIELD_PREP(AIROHA_PCS_PMA_LPATH_IDAC, cdr_pr_idac)); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PWDB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PWDB); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PWDB); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_REF_RST_N); ++ ++ usleep_range(100, 200); ++} ++ ++/* This is used to both calibrate and lock to signal (after a previous ++ * calibration) after a global reset. ++ */ ++static void airoha_pcs_cdr_reset(struct airoha_pcs_priv *priv, ++ phy_interface_t interface, bool calibrate) ++{ ++ /* Setup LPF L2D force and disable */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA); ++ ++ /* Calibrate IDAC and setup Load Band */ ++ if (calibrate) ++ airoha_pcs_rx_prcal(priv, interface); ++ ++ /* Setup LPF RSTB force and disable */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB); ++ ++ usleep_range(700, 1000); ++ ++ /* Force Enable LPF RSTB */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB); ++ ++ usleep_range(100, 200); ++ ++ /* Force Enable LPF L2D */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA); ++ ++ /* Disable LPF RSTB force bit */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB); ++ ++ /* Disable LPF L2D force bit */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA); ++} ++ ++static int airoha_pcs_phya_bringup(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ int calibration_try = 0; ++ u32 val; ++ ++ airoha_pcs_tx_bringup(priv, interface); ++ airoha_pcs_rx_bringup(priv, interface); ++ ++ usleep_range(100, 200); ++ ++retry_calibration: ++ airoha_pcs_cdr_reset(priv, interface, true); ++ ++ /* Global reset clear */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_HSG_RXPCS_RST_N | ++ AIROHA_PCS_PMA_SW_HSG_TXPCS_RST_N | ++ AIROHA_PCS_PMA_SW_HSG_RXPCS_BIST_RST_N | ++ AIROHA_PCS_PMA_SW_XFI_RXPCS_RST_N | ++ AIROHA_PCS_PMA_SW_XFI_TXPCS_RST_N | ++ AIROHA_PCS_PMA_SW_TX_FIFO_RST_N | ++ AIROHA_PCS_PMA_SW_REF_RST_N | ++ AIROHA_PCS_PMA_SW_ALLPCS_RST_N | ++ AIROHA_PCS_PMA_SW_PMA_RST_N | ++ AIROHA_PCS_PMA_SW_TX_RST_N | ++ AIROHA_PCS_PMA_SW_RX_RST_N | ++ AIROHA_PCS_PMA_SW_RX_FIFO_RST_N, ++ AIROHA_PCS_PMA_SW_REF_RST_N); ++ ++ usleep_range(100, 200); ++ ++ /* Global reset */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_HSG_RXPCS_RST_N | ++ AIROHA_PCS_PMA_SW_HSG_TXPCS_RST_N | ++ AIROHA_PCS_PMA_SW_HSG_RXPCS_BIST_RST_N | ++ AIROHA_PCS_PMA_SW_XFI_RXPCS_RST_N | ++ AIROHA_PCS_PMA_SW_XFI_TXPCS_RST_N | ++ AIROHA_PCS_PMA_SW_TX_FIFO_RST_N | ++ AIROHA_PCS_PMA_SW_REF_RST_N | ++ AIROHA_PCS_PMA_SW_ALLPCS_RST_N | ++ AIROHA_PCS_PMA_SW_PMA_RST_N | ++ AIROHA_PCS_PMA_SW_TX_RST_N | ++ AIROHA_PCS_PMA_SW_RX_RST_N | ++ AIROHA_PCS_PMA_SW_RX_FIFO_RST_N); ++ ++ usleep_range(5000, 7000); ++ ++ airoha_pcs_cdr_reset(priv, interface, false); ++ ++ /* It was discovered that after a global reset and auto mode gets ++ * actually enabled, the fl_out from calibration might change and ++ * might deviates a lot from the expected value it was calibrated for. ++ * To correctly work, the PCS FreqDet module needs to Lock to the fl_out ++ * (frequency level output) or no signal can correctly be transmitted. ++ * This is detected by checking the FreqDet module Lock bit. ++ * ++ * If it's detected that the FreqDet module is not locked, retry ++ * calibration. From observation on real hardware with a 10g SFP module, ++ * it required a maximum of an additional calibration to actually make ++ * the FreqDet module to lock. Try 10 times before failing to handle ++ * really strange case. ++ */ ++ regmap_read(priv->xfi_pma, AIROHA_PCS_PMA_RX_FREQDET, &val); ++ if (!(val & AIROHA_PCS_PMA_FBCK_LOCK)) { ++ if (calibration_try > AIROHA_PCS_MAX_CALIBRATION_TRY) { ++ dev_err(priv->dev, "No FBCK Lock from FreqDet module after %d calibration try. PCS won't work.\n", ++ AIROHA_PCS_MAX_CALIBRATION_TRY); ++ return -EIO; ++ } ++ ++ calibration_try++; ++ ++ dev_dbg(priv->dev, "No FBCK Lock from FreqDet module, retry calibration.\n"); ++ goto retry_calibration; ++ } ++ ++ return 0; ++} ++ ++static void airoha_pcs_get_state_sgmii(struct airoha_pcs_priv *priv, ++ unsigned int neg_mode, ++ struct phylink_link_state *state) ++{ ++ u32 bmsr, lpa; ++ ++ regmap_read(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_1, ++ &bmsr); ++ regmap_read(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_5, ++ &lpa); ++ ++ bmsr = (AIROHA_PCS_HSGMII_AN_SGMII_AN_COMPLETE | ++ AIROHA_PCS_HSGMII_AN_SGMII_REMOTE_FAULT | ++ AIROHA_PCS_HSGMII_AN_SGMII_AN_ABILITY | ++ AIROHA_PCS_HSGMII_AN_SGMII_LINK_STATUS) & bmsr; ++ lpa = AIROHA_PCS_HSGMII_AN_SGMII_PARTNER_ABILITY & lpa; ++ ++ phylink_mii_c22_pcs_decode_state(state, neg_mode, bmsr, lpa); ++} ++ ++static void airoha_pcs_get_state_usxgmii(struct airoha_pcs_priv *priv, ++ struct phylink_link_state *state) ++{ ++ u32 lpa; ++ ++ /* Toggle AN Status */ ++ regmap_set_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_AN_CONTROL_6, ++ AIROHA_PCS_USXGMII_TOG_PCS_AUTONEG_STS); ++ regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_AN_CONTROL_6, ++ AIROHA_PCS_USXGMII_TOG_PCS_AUTONEG_STS); ++ ++ regmap_read(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_AN_STATS_0, &lpa); ++ ++ state->link = !!(lpa & MDIO_USXGMII_LINK); ++ state->an_complete = state->link; ++ ++ phylink_decode_usxgmii_word(state, lpa); ++} ++ ++static void airoha_pcs_get_state(struct phylink_pcs *pcs, ++ unsigned int neg_mode, ++ struct phylink_link_state *state) ++{ ++ struct airoha_pcs_priv *priv = phylink_pcs_to_airoha_pcs_port(pcs); ++ ++ switch (state->interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ airoha_pcs_get_state_sgmii(priv, neg_mode, state); ++ break; ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ airoha_pcs_get_state_usxgmii(priv, state); ++ break; ++ default: ++ return; ++ } ++} ++ ++static int airoha_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, ++ phy_interface_t interface, ++ const unsigned long *advertising, ++ bool permit_pause_to_mac) ++{ ++ struct airoha_pcs_priv *priv = phylink_pcs_to_airoha_pcs_port(pcs); ++ u32 rate_adapt; ++ int ret; ++ ++ priv->interface = interface; ++ ++ /* Select HSGMII or USXGMII in SCU regs */ ++ airoha_pcs_setup_scu(priv, interface); ++ ++ /* Enable Analog Common Lane */ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CMN_EN, ++ AIROHA_PCS_ANA_CMN_EN); ++ ++ /* Setup PLL */ ++ airoha_pcs_pll_bringup(priv, interface); ++ ++ /* Setup PHYA */ ++ ret = airoha_pcs_phya_bringup(priv, interface); ++ if (ret) ++ return ret; ++ ++ /* Set final configuration for various modes */ ++ airoha_pcs_init(priv, interface); ++ ++ /* Configure Interrupt for various modes */ ++ airoha_pcs_interrupt_init(priv, interface); ++ ++ /* FIXME: With an attached Aeonsemi PHY, rate adaption is needed ++ * even with no inband. ++ */ ++ rate_adapt = AIROHA_PCS_HSGMII_RATE_ADAPT_RX_EN | ++ AIROHA_PCS_HSGMII_RATE_ADAPT_TX_EN; ++ ++ /* AN Auto Settings (Rate Adaptation) */ ++ regmap_update_bits(priv->hsgmii_rate_adp, AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_0, ++ AIROHA_PCS_HSGMII_RATE_ADAPT_RX_BYPASS | ++ AIROHA_PCS_HSGMII_RATE_ADAPT_TX_BYPASS | ++ AIROHA_PCS_HSGMII_RATE_ADAPT_RX_EN | ++ AIROHA_PCS_HSGMII_RATE_ADAPT_TX_EN, rate_adapt); ++ ++ /* FIXME: With an attached Aeonsemi PHY, AN is needed ++ * even with no inband. ++ */ ++ if (interface == PHY_INTERFACE_MODE_USXGMII || ++ interface == PHY_INTERFACE_MODE_10GBASER) { ++ regmap_set_bits(priv->usxgmii_pcs, ++ AIROHA_PCS_USXGMII_PCS_AN_CONTROL_0, ++ AIROHA_PCS_USXGMII_AN_ENABLE); ++ } ++ ++ /* Clear any force bit that my be set by bootloader */ ++ if (interface == PHY_INTERFACE_MODE_SGMII || ++ interface == PHY_INTERFACE_MODE_1000BASEX || ++ interface == PHY_INTERFACE_MODE_2500BASEX) { ++ regmap_clear_bits(priv->multi_sgmii, AIROHA_PCS_MULTI_SGMII_SGMII_STS_CTRL_0, ++ AIROHA_PCS_LINK_MODE_P0 | ++ AIROHA_PCS_FORCE_SPD_MODE_P0 | ++ AIROHA_PCS_FORCE_LINKDOWN_P0 | ++ AIROHA_PCS_FORCE_LINKUP_P0); ++ } ++ ++ /* Toggle Rate Adaption for SGMII/HSGMII mode */ ++ if (interface == PHY_INTERFACE_MODE_SGMII || ++ interface == PHY_INTERFACE_MODE_1000BASEX || ++ interface == PHY_INTERFACE_MODE_2500BASEX) { ++ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) ++ regmap_clear_bits(priv->hsgmii_rate_adp, ++ AIROHA_PCS_HSGMII_RATE_ADP_P0_CTRL_0, ++ AIROHA_PCS_HSGMII_P0_DIS_MII_MODE); ++ else ++ regmap_set_bits(priv->hsgmii_rate_adp, ++ AIROHA_PCS_HSGMII_RATE_ADP_P0_CTRL_0, ++ AIROHA_PCS_HSGMII_P0_DIS_MII_MODE); ++ } ++ ++ /* Setup AN Link Timer */ ++ if (interface == PHY_INTERFACE_MODE_SGMII || ++ interface == PHY_INTERFACE_MODE_1000BASEX || ++ interface == PHY_INTERFACE_MODE_2500BASEX) { ++ u32 an_timer; ++ ++ an_timer = phylink_get_link_timer_ns(interface); ++ ++ /* Value needs to be shifted by 4, seems value is internally * 16 */ ++ regmap_update_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_11, ++ AIROHA_PCS_HSGMII_AN_SGMII_LINK_TIMER, ++ FIELD_PREP(AIROHA_PCS_HSGMII_AN_SGMII_LINK_TIMER, ++ an_timer >> 4)); ++ ++ regmap_update_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_3, ++ AIROHA_PCS_HSGMII_PCS_LINK_STSTIME, ++ FIELD_PREP(AIROHA_PCS_HSGMII_PCS_LINK_STSTIME, ++ an_timer >> 4)); ++ } ++ ++ /* Setup SGMII AN and advertisement in DEV_ABILITY */ ++ if (interface == PHY_INTERFACE_MODE_SGMII && ++ neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { ++ int advertise = phylink_mii_c22_pcs_encode_advertisement(interface, ++ advertising); ++ if (advertise < 0) ++ return advertise; ++ ++ regmap_set_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_0, ++ AIROHA_PCS_HSGMII_AN_SGMII_RA_ENABLE); ++ ++ regmap_update_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_4, ++ AIROHA_PCS_HSGMII_AN_SGMII_DEV_ABILITY, ++ FIELD_PREP(AIROHA_PCS_HSGMII_AN_SGMII_DEV_ABILITY, ++ advertise)); ++ } else { ++ regmap_clear_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_0, ++ AIROHA_PCS_HSGMII_AN_SGMII_RA_ENABLE); ++ } ++ ++ if (interface == PHY_INTERFACE_MODE_SGMII || ++ interface == PHY_INTERFACE_MODE_1000BASEX) { ++ u32 if_mode = AIROHA_PCS_HSGMII_AN_SGMII_EN | ++ AIROHA_PCS_HSGMII_AN_SIDEBAND_EN; ++ ++ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { ++ regmap_set_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_13, ++ AIROHA_PCS_HSGMII_AN_SGMII_REMOTE_FAULT_DIS); ++ ++ /* Clear force speed bits and MAC mode */ ++ regmap_clear_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_6, ++ AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_10 | ++ AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_100 | ++ AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_1000 | ++ AIROHA_PCS_HSGMII_PCS_MAC_MODE | ++ AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL | ++ AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT); ++ } else { ++ if_mode |= AIROHA_PCS_HSGMII_AN_SGMII_COMPAT_EN; ++ ++ regmap_clear_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_13, ++ AIROHA_PCS_HSGMII_AN_SGMII_REMOTE_FAULT_DIS); ++ ++ /* AN off force rate adaption, speed is set later in Link Up */ ++ regmap_update_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_6, ++ AIROHA_PCS_HSGMII_PCS_MAC_MODE | ++ AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT, ++ AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT); ++ } ++ ++ regmap_update_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_13, ++ AIROHA_PCS_HSGMII_AN_SGMII_IF_MODE_5_0, if_mode); ++ ++ /* FIXME: Airoha apply a different configuration here */ ++ /* They force rate adaption */ ++ regmap_set_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_6, ++ AIROHA_PCS_HSGMII_PCS_TX_ENABLE | ++ AIROHA_PCS_HSGMII_PCS_MODE2_EN); ++ } ++ ++ if (interface == PHY_INTERFACE_MODE_1000BASEX && ++ neg_mode != PHYLINK_PCS_NEG_INBAND_ENABLED) { ++ regmap_set_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_1, ++ AIROHA_PCS_SGMII_SEND_AN_ERR_EN); ++ ++ regmap_set_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_FORCE_CL37, ++ AIROHA_PCS_HSGMII_AN_FORCE_AN_DONE); ++ } ++ ++ /* Configure Flow Control on XFI */ ++ regmap_update_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_GIB_CFG, ++ AIROHA_PCS_XFI_TX_FC_EN | AIROHA_PCS_XFI_RX_FC_EN, ++ permit_pause_to_mac ? ++ AIROHA_PCS_XFI_TX_FC_EN | AIROHA_PCS_XFI_RX_FC_EN : ++ 0); ++ ++ return 0; ++} ++ ++static void airoha_pcs_an_restart(struct phylink_pcs *pcs) ++{ ++ struct airoha_pcs_priv *priv = phylink_pcs_to_airoha_pcs_port(pcs); ++ ++ switch (priv->interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ regmap_set_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_0, ++ AIROHA_PCS_HSGMII_AN_SGMII_AN_RESTART); ++ udelay(3); ++ regmap_clear_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_0, ++ AIROHA_PCS_HSGMII_AN_SGMII_AN_RESTART); ++ break; ++ case PHY_INTERFACE_MODE_USXGMII: ++ regmap_set_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_AN_CONTROL_0, ++ AIROHA_PCS_USXGMII_AN_RESTART); ++ udelay(3); ++ regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_AN_CONTROL_0, ++ AIROHA_PCS_USXGMII_AN_RESTART); ++ default: ++ return; ++ } ++} ++ ++static void airoha_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode, ++ phy_interface_t interface, int speed, int duplex) ++{ ++ struct airoha_pcs_priv *priv = phylink_pcs_to_airoha_pcs_port(pcs); ++ ++ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { ++ if (interface == PHY_INTERFACE_MODE_SGMII) { ++ regmap_update_bits(priv->hsgmii_rate_adp, ++ AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_1, ++ AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_WR_THR | ++ AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_RD_THR, ++ FIELD_PREP(AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_WR_THR, 0x0) | ++ FIELD_PREP(AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_RD_THR, 0x0)); ++ udelay(1); ++ regmap_update_bits(priv->hsgmii_rate_adp, ++ AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_1, ++ AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_WR_THR | ++ AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_RD_THR, ++ FIELD_PREP(AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_WR_THR, 0xf) | ++ FIELD_PREP(AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_RD_THR, 0x5)); ++ } ++ } else { ++ if (interface == PHY_INTERFACE_MODE_USXGMII || ++ interface == PHY_INTERFACE_MODE_10GBASER) { ++ u32 mode; ++ u32 rate_adapt; ++ ++ switch (speed) { ++ case SPEED_10000: ++ rate_adapt = AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_10000; ++ mode = AIROHA_PCS_USXGMII_MODE_10000; ++ break; ++ case SPEED_5000: ++ rate_adapt = AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_5000; ++ mode = AIROHA_PCS_USXGMII_MODE_5000; ++ break; ++ case SPEED_2500: ++ rate_adapt = AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_2500; ++ mode = AIROHA_PCS_USXGMII_MODE_2500; ++ break; ++ case SPEED_1000: ++ rate_adapt = AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_1000; ++ mode = AIROHA_PCS_USXGMII_MODE_1000; ++ break; ++ case SPEED_100: ++ rate_adapt = AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_100; ++ mode = AIROHA_PCS_USXGMII_MODE_100; ++ break; ++ } ++ ++ /* Trigger USXGMII change mode and force selected speed */ ++ regmap_update_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_AN_CONTROL_7, ++ AIROHA_PCS_USXGMII_RATE_UPDATE_MODE | ++ AIROHA_PCS_USXGMII_MODE, ++ AIROHA_PCS_USXGMII_RATE_UPDATE_MODE | mode); ++ ++ regmap_update_bits(priv->hsgmii_rate_adp, AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_11, ++ AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_EN | ++ AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE, ++ AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_EN | ++ rate_adapt); ++ } ++ ++ if (interface == PHY_INTERFACE_MODE_SGMII || ++ interface == PHY_INTERFACE_MODE_1000BASEX) { ++ u32 force_speed; ++ u32 rate_adapt; ++ ++ switch (speed) { ++ case SPEED_1000: ++ force_speed = AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_1000; ++ rate_adapt = AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL_1000; ++ break; ++ case SPEED_100: ++ force_speed = AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_100; ++ rate_adapt = AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL_100; ++ break; ++ case SPEED_10: ++ force_speed = AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_10; ++ rate_adapt = AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL_10; ++ break; ++ } ++ ++ regmap_update_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_6, ++ AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_10 | ++ AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_100 | ++ AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_1000 | ++ AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL, ++ force_speed | rate_adapt); ++ } ++ ++ if (interface == PHY_INTERFACE_MODE_SGMII || ++ interface == PHY_INTERFACE_MODE_2500BASEX) { ++ u32 ck_gen_mode; ++ u32 speed_reg; ++ u32 if_mode; ++ ++ switch (speed) { ++ case SPEED_2500: ++ speed_reg = AIROHA_PCS_LINK_MODE_P0_2_5G; ++ break; ++ case SPEED_1000: ++ speed_reg = AIROHA_PCS_LINK_MODE_P0_1G; ++ if_mode = AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE_1000; ++ ck_gen_mode = AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_1000; ++ break; ++ case SPEED_100: ++ speed_reg = AIROHA_PCS_LINK_MODE_P0_100M; ++ if_mode = AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE_100; ++ ck_gen_mode = AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_100; ++ break; ++ case SPEED_10: ++ speed_reg = AIROHA_PCS_LINK_MODE_P0_100M; ++ if_mode = AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE_10; ++ ck_gen_mode = AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_10; ++ break; ++ } ++ ++ if (interface == PHY_INTERFACE_MODE_SGMII) { ++ regmap_update_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_13, ++ AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE, ++ if_mode); ++ ++ regmap_update_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_AN_SGMII_MODE_FORCE, ++ AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE | ++ AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_SEL, ++ ck_gen_mode | ++ AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_SEL); ++ } ++ ++ regmap_update_bits(priv->multi_sgmii, AIROHA_PCS_MULTI_SGMII_SGMII_STS_CTRL_0, ++ AIROHA_PCS_LINK_MODE_P0 | ++ AIROHA_PCS_FORCE_SPD_MODE_P0, ++ speed_reg | ++ AIROHA_PCS_FORCE_SPD_MODE_P0); ++ } ++ } ++ ++ /* Reset TXPCS on link up */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_HSG_TXPCS_RST_N); ++ ++ usleep_range(100, 200); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_HSG_TXPCS_RST_N); ++} ++ ++static const struct phylink_pcs_ops airoha_pcs_ops = { ++ .pcs_get_state = airoha_pcs_get_state, ++ .pcs_config = airoha_pcs_config, ++ .pcs_an_restart = airoha_pcs_an_restart, ++ .pcs_link_up = airoha_pcs_link_up, ++}; ++ ++static const struct regmap_config airoha_pcs_regmap_config = { ++ .reg_bits = 32, ++ .val_bits = 32, ++ .reg_stride = 4, ++}; ++ ++static int airoha_pcs_probe(struct platform_device *pdev) ++{ ++ struct regmap_config syscon_config = airoha_pcs_regmap_config; ++ struct device *dev = &pdev->dev; ++ struct airoha_pcs_priv *priv; ++ void __iomem *base; ++ int ret; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->dev = dev; ++ priv->data = of_device_get_match_data(dev); ++ ++ base = devm_platform_ioremap_resource_byname(pdev, "xfi_mac"); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ syscon_config.name = "xfi_mac"; ++ priv->xfi_mac = devm_regmap_init_mmio(dev, base, &syscon_config); ++ if (IS_ERR(priv->xfi_mac)) ++ return PTR_ERR(priv->xfi_mac); ++ ++ base = devm_platform_ioremap_resource_byname(pdev, "hsgmii_an"); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ syscon_config.name = "hsgmii_an"; ++ priv->hsgmii_an = devm_regmap_init_mmio(dev, base, &syscon_config); ++ if (IS_ERR(priv->hsgmii_an)) ++ return PTR_ERR(priv->hsgmii_an); ++ ++ base = devm_platform_ioremap_resource_byname(pdev, "hsgmii_pcs"); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ syscon_config.name = "hsgmii_pcs"; ++ priv->hsgmii_pcs = devm_regmap_init_mmio(dev, base, &syscon_config); ++ if (IS_ERR(priv->hsgmii_pcs)) ++ return PTR_ERR(priv->hsgmii_pcs); ++ ++ base = devm_platform_ioremap_resource_byname(pdev, "hsgmii_rate_adp"); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ syscon_config.name = "hsgmii_rate_adp"; ++ priv->hsgmii_rate_adp = devm_regmap_init_mmio(dev, base, &syscon_config); ++ if (IS_ERR(priv->hsgmii_rate_adp)) ++ return PTR_ERR(priv->hsgmii_rate_adp); ++ ++ base = devm_platform_ioremap_resource_byname(pdev, "multi_sgmii"); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ syscon_config.name = "multi_sgmii"; ++ priv->multi_sgmii = devm_regmap_init_mmio(dev, base, &syscon_config); ++ if (IS_ERR(priv->multi_sgmii)) ++ return PTR_ERR(priv->multi_sgmii); ++ ++ base = devm_platform_ioremap_resource_byname(pdev, "usxgmii"); ++ if (IS_ERR(base) && PTR_ERR(base) != -ENOENT) ++ return PTR_ERR(base); ++ ++ syscon_config.name = "usxgmii"; ++ priv->usxgmii_pcs = devm_regmap_init_mmio(dev, base, &syscon_config); ++ if (IS_ERR(priv->usxgmii_pcs)) ++ return PTR_ERR(priv->usxgmii_pcs); ++ ++ base = devm_platform_ioremap_resource_byname(pdev, "xfi_pma"); ++ if (IS_ERR(base) && PTR_ERR(base) != -ENOENT) ++ return PTR_ERR(base); ++ ++ syscon_config.name = "xfi_pma"; ++ priv->xfi_pma = devm_regmap_init_mmio(dev, base, &syscon_config); ++ if (IS_ERR(priv->xfi_pma)) ++ return PTR_ERR(priv->xfi_pma); ++ ++ base = devm_platform_ioremap_resource_byname(pdev, "xfi_ana"); ++ if (IS_ERR(base) && PTR_ERR(base) != -ENOENT) ++ return PTR_ERR(base); ++ ++ syscon_config.name = "xfi_ana"; ++ priv->xfi_ana = devm_regmap_init_mmio(dev, base, &syscon_config); ++ if (IS_ERR(priv->xfi_ana)) ++ return PTR_ERR(priv->xfi_ana); ++ ++ /* SCU is used to toggle XFI or HSGMII in global SoC registers */ ++ priv->scu = syscon_regmap_lookup_by_compatible("airoha,en7581-scu"); ++ if (IS_ERR(priv->scu)) ++ return PTR_ERR(priv->scu); ++ ++ priv->rsts[0].id = "mac"; ++ priv->rsts[1].id = "phy"; ++ ret = devm_reset_control_bulk_get_exclusive(dev, ARRAY_SIZE(priv->rsts), ++ priv->rsts); ++ if (ret) ++ return dev_err_probe(dev, ret, "failed to get bulk reset lines\n"); ++ ++ platform_set_drvdata(pdev, priv); ++ ++ priv->pcs.ops = &airoha_pcs_ops; ++ priv->pcs.poll = true; ++ ++ __set_bit(PHY_INTERFACE_MODE_SGMII, priv->pcs.supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_1000BASEX, priv->pcs.supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_2500BASEX, priv->pcs.supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_10GBASER, priv->pcs.supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_USXGMII, priv->pcs.supported_interfaces); ++ ++ return fwnode_pcs_add_provider(dev_fwnode(dev), fwnode_pcs_simple_get, ++ &priv->pcs); ++} ++ ++static void airoha_pcs_remove(struct platform_device *pdev) ++{ ++ struct airoha_pcs_priv *priv = platform_get_drvdata(pdev); ++ ++ fwnode_pcs_del_provider(dev_fwnode(&pdev->dev)); ++ ++ rtnl_lock(); ++ phylink_release_pcs(&priv->pcs); ++ rtnl_unlock(); ++} ++ ++static const struct airoha_pcs_match_data an7581_pcs_eth = { ++ .port_type = AIROHA_PCS_ETH, ++}; ++ ++static const struct airoha_pcs_match_data an7581_pcs_pon = { ++ .port_type = AIROHA_PCS_PON, ++}; ++ ++static const struct of_device_id airoha_pcs_of_table[] = { ++ { .compatible = "airoha,an7581-pcs-eth", .data = &an7581_pcs_eth }, ++ { .compatible = "airoha,an7581-pcs-pon", .data = &an7581_pcs_pon }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, airoha_pcs_of_table); ++ ++static struct platform_driver airoha_pcs_driver = { ++ .driver = { ++ .name = "airoha-pcs", ++ .of_match_table = airoha_pcs_of_table, ++ }, ++ .probe = airoha_pcs_probe, ++ .remove = airoha_pcs_remove, ++}; ++module_platform_driver(airoha_pcs_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("Airoha PCS driver"); ++MODULE_AUTHOR("Christian Marangi "); +diff --git a/include/linux/pcs/pcs-airoha.h b/include/linux/pcs/pcs-airoha.h +new file mode 100644 +index 000000000000..07797645ff15 +--- /dev/null ++++ b/include/linux/pcs/pcs-airoha.h +@@ -0,0 +1,11 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++ ++#ifndef __LINUX_PCS_AIROHA_H ++#define __LINUX_PCS_AIROHA_H ++ ++/* XFI_MAC */ ++#define AIROHA_PCS_XFI_MAC_XFI_GIB_CFG 0x0 ++#define AIROHA_PCS_XFI_TX_FC_EN BIT(5) ++#define AIROHA_PCS_XFI_RX_FC_EN BIT(4) ++ ++#endif /* __LINUX_PCS_AIROHA_H */ +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0060-dt-bindings-net-pcs-Document-support-for-Airoha-Ethe.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0060-dt-bindings-net-pcs-Document-support-for-Airoha-Ethe.patch new file mode 100644 index 0000000000..1052cea2ea --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0060-dt-bindings-net-pcs-Document-support-for-Airoha-Ethe.patch @@ -0,0 +1,141 @@ +From 867bdc4af013a1f530133b01c7d4494a99d88b2b Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 7 Apr 2025 00:14:03 +0200 +Subject: [PATCH 60/84] dt-bindings: net: pcs: Document support for Airoha + Ethernet PCS + +Document support for Airoha Ethernet PCS for AN7581 SoC. + +Airoha AN7581 SoC expose multiple Physical Coding Sublayer (PCS) for +the various Serdes port supporting different Media Independent Interface +(10BASE-R, USXGMII, 2500BASE-X, 1000BASE-X, SGMII). + +This follow the new PCS provider with the use of #pcs-cells property. + +Signed-off-by: Christian Marangi +--- + .../bindings/net/pcs/airoha,pcs.yaml | 112 ++++++++++++++++++ + 1 file changed, 112 insertions(+) + create mode 100644 Documentation/devicetree/bindings/net/pcs/airoha,pcs.yaml + +diff --git a/Documentation/devicetree/bindings/net/pcs/airoha,pcs.yaml b/Documentation/devicetree/bindings/net/pcs/airoha,pcs.yaml +new file mode 100644 +index 000000000000..8bcf7757c728 +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/pcs/airoha,pcs.yaml +@@ -0,0 +1,112 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/net/pcs/airoha,pcs.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Airoha Ethernet PCS and Serdes ++ ++maintainers: ++ - Christian Marangi ++ ++description: ++ Airoha AN7581 SoC expose multiple Physical Coding Sublayer (PCS) for ++ the various Serdes port supporting different Media Independent Interface ++ (10BASE-R, USXGMII, 2500BASE-X, 1000BASE-X, SGMII). ++ ++properties: ++ compatible: ++ enum: ++ - airoha,an7581-pcs-eth ++ - airoha,an7581-pcs-pon ++ ++ reg: ++ items: ++ - description: XFI MAC reg ++ - description: HSGMII AN reg ++ - description: HSGMII PCS reg ++ - description: MULTI SGMII reg ++ - description: USXGMII reg ++ - description: HSGMII rate adaption reg ++ - description: XFI Analog register ++ - description: XFI PMA (Physical Medium Attachment) register ++ ++ reg-names: ++ items: ++ - const: xfi_mac ++ - const: hsgmii_an ++ - const: hsgmii_pcs ++ - const: multi_sgmii ++ - const: usxgmii ++ - const: hsgmii_rate_adp ++ - const: xfi_ana ++ - const: xfi_pma ++ ++ resets: ++ items: ++ - description: MAC reset ++ - description: PHY reset ++ ++ reset-names: ++ items: ++ - const: mac ++ - const: phy ++ ++ "#pcs-cells": ++ const: 0 ++ ++required: ++ - compatible ++ - reg ++ - reg-names ++ - resets ++ - reset-names ++ - "#pcs-cells" ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ ++ pcs@1fa08000 { ++ compatible = "airoha,an7581-pcs-pon"; ++ reg = <0x1fa08000 0x1000>, ++ <0x1fa80000 0x60>, ++ <0x1fa80a00 0x164>, ++ <0x1fa84000 0x450>, ++ <0x1fa85900 0x338>, ++ <0x1fa86000 0x300>, ++ <0x1fa8a000 0x1000>, ++ <0x1fa8b000 0x1000>; ++ reg-names = "xfi_mac", "hsgmii_an", "hsgmii_pcs", ++ "multi_sgmii", "usxgmii", ++ "hsgmii_rate_adp", "xfi_ana", "xfi_pma"; ++ ++ resets = <&scuclk EN7581_XPON_MAC_RST>, ++ <&scuclk EN7581_XPON_PHY_RST>; ++ reset-names = "mac", "phy"; ++ ++ #pcs-cells = <0>; ++ }; ++ ++ pcs@1fa09000 { ++ compatible = "airoha,an7581-pcs-eth"; ++ reg = <0x1fa09000 0x1000>, ++ <0x1fa70000 0x60>, ++ <0x1fa70a00 0x164>, ++ <0x1fa74000 0x450>, ++ <0x1fa75900 0x338>, ++ <0x1fa76000 0x300>, ++ <0x1fa7a000 0x1000>, ++ <0x1fa7b000 0x1000>; ++ reg-names = "xfi_mac", "hsgmii_an", "hsgmii_pcs", ++ "multi_sgmii", "usxgmii", ++ "hsgmii_rate_adp", "xfi_ana", "xfi_pma"; ++ ++ resets = <&scuclk EN7581_XSI_MAC_RST>, ++ <&scuclk EN7581_XSI_PHY_RST>; ++ reset-names = "mac", "phy"; ++ ++ #pcs-cells = <0>; ++ }; +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0061-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0061-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch new file mode 100644 index 0000000000..39809896c1 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0061-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch @@ -0,0 +1,367 @@ +From df68e3182801a4c6c4a7e3b3f68cefb8f58f52d3 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 12 Dec 2023 03:47:18 +0000 +Subject: [PATCH 61/84] net: pcs: pcs-mtk-lynxi: add platform driver for MT7988 + +Introduce a full platform MFD driver for the LynxI (H)SGMII PCS which +is going to initially be used for the MT7988 SoC. + +Signed-off-by: Daniel Golle +--- + drivers/net/pcs/pcs-mtk-lynxi.c | 206 +++++++++++++++++++++++++++++--- + 1 file changed, 189 insertions(+), 17 deletions(-) + +diff --git a/drivers/net/pcs/pcs-mtk-lynxi.c b/drivers/net/pcs/pcs-mtk-lynxi.c +index 149ddf51d785..19c1b29beeac 100644 +--- a/drivers/net/pcs/pcs-mtk-lynxi.c ++++ b/drivers/net/pcs/pcs-mtk-lynxi.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + // Copyright (c) 2018-2019 MediaTek Inc. +-/* A library for MediaTek SGMII circuit ++/* A library and platform driver for the MediaTek LynxI SGMII circuit + * + * Author: Sean Wang + * Author: Alexander Couzens +@@ -8,11 +8,20 @@ + * + */ + ++#include + #include ++#include ++#include + #include ++#include + #include ++#include ++#include + #include ++#include + #include ++#include ++#include + + /* SGMII subsystem config registers */ + /* BMCR (low 16) BMSR (high 16) */ +@@ -65,6 +74,8 @@ + #define SGMII_PN_SWAP_MASK GENMASK(1, 0) + #define SGMII_PN_SWAP_TX_RX (BIT(0) | BIT(1)) + ++#define MTK_NETSYS_V3_AMA_RGC3 0x128 ++ + /* struct mtk_pcs_lynxi - This structure holds each sgmii regmap andassociated + * data + * @regmap: The register map pointing at the range used to setup +@@ -74,13 +85,26 @@ + * @interface: Currently configured interface mode + * @pcs: Phylink PCS structure + * @flags: Flags indicating hardware properties ++ * @rstc: Reset controller ++ * @sgmii_sel: SGMII Register Clock ++ * @sgmii_rx: SGMII RX Clock ++ * @sgmii_tx: SGMII TX Clock ++ * @node: List node + */ + struct mtk_pcs_lynxi { + struct regmap *regmap; ++ struct device *dev; + u32 ana_rgc3; + phy_interface_t interface; + struct phylink_pcs pcs; + u32 flags; ++ int advertise; ++ struct reset_control *rstc; ++ struct clk *sgmii_sel; ++ struct clk *sgmii_rx; ++ struct clk *sgmii_tx; ++ struct phy *xfi_tphy; ++ struct list_head node; + }; + + static struct mtk_pcs_lynxi *pcs_to_mtk_pcs_lynxi(struct phylink_pcs *pcs) +@@ -120,6 +144,17 @@ static void mtk_pcs_lynxi_get_state(struct phylink_pcs *pcs, + FIELD_GET(SGMII_LPA, adv)); + } + ++static void mtk_sgmii_reset(struct mtk_pcs_lynxi *mpcs) ++{ ++ if (!mpcs->rstc) ++ return; ++ ++ reset_control_assert(mpcs->rstc); ++ udelay(100); ++ reset_control_deassert(mpcs->rstc); ++ mdelay(1); ++} ++ + static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, + const unsigned long *advertising, +@@ -128,12 +163,14 @@ static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode, + struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); + bool mode_changed = false, changed; + unsigned int rgc3, sgm_mode, bmcr; +- int advertise, link_timer; ++ int link_timer; + +- advertise = phylink_mii_c22_pcs_encode_advertisement(interface, +- advertising); +- if (advertise < 0) +- return advertise; ++ if (advertising) { ++ mpcs->advertise = phylink_mii_c22_pcs_encode_advertisement(interface, ++ advertising); ++ if (mpcs->advertise < 0) ++ return mpcs->advertise; ++ } + + /* Clearing IF_MODE_BIT0 switches the PCS to BASE-X mode, and + * we assume that fixes it's speed at bitrate = line rate (in +@@ -165,6 +202,10 @@ static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode, + SGMII_PHYA_PWD); + + /* Reset SGMII PCS state */ ++ if (mpcs->xfi_tphy) ++ phy_reset(mpcs->xfi_tphy); ++ ++ mtk_sgmii_reset(mpcs); + regmap_set_bits(mpcs->regmap, SGMSYS_RESERVED_0, + SGMII_SW_RESET); + +@@ -192,7 +233,7 @@ static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode, + + /* Update the advertisement, noting whether it has changed */ + regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE, +- SGMII_ADVERTISE, advertise, &changed); ++ SGMII_ADVERTISE, mpcs->advertise, &changed); + + /* Update the sgmsys mode register */ + regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE, +@@ -215,6 +256,10 @@ static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode, + usleep_range(50, 100); + regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0); + ++ /* Setup PMA/PMD */ ++ if (mpcs->xfi_tphy) ++ phy_set_mode_ext(mpcs->xfi_tphy, PHY_MODE_ETHERNET, interface); ++ + return changed || mode_changed; + } + +@@ -233,6 +278,11 @@ static void mtk_pcs_lynxi_link_up(struct phylink_pcs *pcs, + struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); + unsigned int sgm_mode; + ++ if (mpcs->xfi_tphy) { ++ phy_reset(mpcs->xfi_tphy); ++ phy_set_mode_ext(mpcs->xfi_tphy, PHY_MODE_ETHERNET, interface); ++ } ++ + if (neg_mode != PHYLINK_PCS_NEG_INBAND_ENABLED) { + /* Force the speed and duplex setting */ + if (speed == SPEED_10) +@@ -249,13 +299,39 @@ static void mtk_pcs_lynxi_link_up(struct phylink_pcs *pcs, + SGMII_DUPLEX_HALF | SGMII_SPEED_MASK, + sgm_mode); + } ++ ++ mtk_pcs_lynxi_config(pcs, neg_mode, interface, NULL, false); ++} ++ ++static int mtk_pcs_lynxi_enable(struct phylink_pcs *pcs) ++{ ++ struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); ++ ++ if (mpcs->sgmii_tx && mpcs->sgmii_rx) { ++ clk_prepare_enable(mpcs->sgmii_rx); ++ clk_prepare_enable(mpcs->sgmii_tx); ++ } ++ ++ if (mpcs->xfi_tphy) ++ phy_power_on(mpcs->xfi_tphy); ++ ++ return 0; + } + + static void mtk_pcs_lynxi_disable(struct phylink_pcs *pcs) + { + struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs); + ++ regmap_set_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD); ++ ++ if (mpcs->sgmii_tx && mpcs->sgmii_rx) { ++ clk_disable_unprepare(mpcs->sgmii_tx); ++ clk_disable_unprepare(mpcs->sgmii_rx); ++ } ++ + mpcs->interface = PHY_INTERFACE_MODE_NA; ++ if (mpcs->xfi_tphy) ++ phy_power_off(mpcs->xfi_tphy); + } + + static const struct phylink_pcs_ops mtk_pcs_lynxi_ops = { +@@ -265,11 +341,12 @@ static const struct phylink_pcs_ops mtk_pcs_lynxi_ops = { + .pcs_an_restart = mtk_pcs_lynxi_restart_an, + .pcs_link_up = mtk_pcs_lynxi_link_up, + .pcs_disable = mtk_pcs_lynxi_disable, ++ .pcs_enable = mtk_pcs_lynxi_enable, + }; + +-struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev, +- struct regmap *regmap, u32 ana_rgc3, +- u32 flags) ++static struct phylink_pcs *mtk_pcs_lynxi_init(struct device *dev, struct regmap *regmap, ++ u32 ana_rgc3, u32 flags, ++ struct mtk_pcs_lynxi *prealloc) + { + struct mtk_pcs_lynxi *mpcs; + u32 id, ver; +@@ -277,29 +354,33 @@ struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev, + + ret = regmap_read(regmap, SGMSYS_PCS_DEVICE_ID, &id); + if (ret < 0) +- return NULL; ++ return ERR_PTR(ret); + + if (id != SGMII_LYNXI_DEV_ID) { + dev_err(dev, "unknown PCS device id %08x\n", id); +- return NULL; ++ return ERR_PTR(-ENODEV); + } + + ret = regmap_read(regmap, SGMSYS_PCS_SCRATCH, &ver); + if (ret < 0) +- return NULL; ++ return ERR_PTR(ret); + + ver = FIELD_GET(SGMII_DEV_VERSION, ver); + if (ver != 0x1) { + dev_err(dev, "unknown PCS device version %04x\n", ver); +- return NULL; ++ return ERR_PTR(-ENODEV); + } + + dev_dbg(dev, "MediaTek LynxI SGMII PCS (id 0x%08x, ver 0x%04x)\n", id, + ver); + +- mpcs = kzalloc(sizeof(*mpcs), GFP_KERNEL); +- if (!mpcs) +- return NULL; ++ if (prealloc) { ++ mpcs = prealloc; ++ } else { ++ mpcs = kzalloc(sizeof(*mpcs), GFP_KERNEL); ++ if (!mpcs) ++ return ERR_PTR(-ENOMEM); ++ }; + + mpcs->ana_rgc3 = ana_rgc3; + mpcs->regmap = regmap; +@@ -313,6 +394,13 @@ struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev, + __set_bit(PHY_INTERFACE_MODE_2500BASEX, mpcs->pcs.supported_interfaces); + + return &mpcs->pcs; ++}; ++ ++struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev, ++ struct regmap *regmap, u32 ana_rgc3, ++ u32 flags) ++{ ++ return mtk_pcs_lynxi_init(dev, regmap, ana_rgc3, flags, NULL); + } + EXPORT_SYMBOL(mtk_pcs_lynxi_create); + +@@ -325,5 +413,89 @@ void mtk_pcs_lynxi_destroy(struct phylink_pcs *pcs) + } + EXPORT_SYMBOL(mtk_pcs_lynxi_destroy); + ++#ifdef CONFIG_FWNODE_PCS ++static int mtk_pcs_lynxi_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ struct mtk_pcs_lynxi *mpcs; ++ struct phylink_pcs *pcs; ++ struct regmap *regmap; ++ u32 flags = 0; ++ ++ mpcs = devm_kzalloc(dev, sizeof(*mpcs), GFP_KERNEL); ++ if (!mpcs) ++ return -ENOMEM; ++ ++ mpcs->dev = dev; ++ regmap = syscon_node_to_regmap(np->parent); ++ if (IS_ERR(regmap)) ++ return PTR_ERR(regmap); ++ ++ if (of_property_read_bool(np->parent, "mediatek,pnswap")) ++ flags |= MTK_SGMII_FLAG_PN_SWAP; ++ ++ mpcs->rstc = of_reset_control_get_shared(np->parent, NULL); ++ if (IS_ERR(mpcs->rstc)) ++ return PTR_ERR(mpcs->rstc); ++ ++ reset_control_deassert(mpcs->rstc); ++ mpcs->sgmii_sel = devm_clk_get_enabled(dev, "sgmii_sel"); ++ if (IS_ERR(mpcs->sgmii_sel)) ++ return PTR_ERR(mpcs->sgmii_sel); ++ ++ mpcs->sgmii_rx = devm_clk_get(dev, "sgmii_rx"); ++ if (IS_ERR(mpcs->sgmii_rx)) ++ return PTR_ERR(mpcs->sgmii_rx); ++ ++ mpcs->sgmii_tx = devm_clk_get(dev, "sgmii_tx"); ++ if (IS_ERR(mpcs->sgmii_tx)) ++ return PTR_ERR(mpcs->sgmii_tx); ++ ++ mpcs->xfi_tphy = devm_of_phy_get(mpcs->dev, np, NULL); ++ if (IS_ERR(mpcs->xfi_tphy)) ++ return PTR_ERR(mpcs->xfi_tphy); ++ ++ pcs = mtk_pcs_lynxi_init(dev, regmap, (uintptr_t)of_device_get_match_data(dev), ++ flags, mpcs); ++ if (IS_ERR(pcs)) ++ return PTR_ERR(pcs); ++ ++ regmap_set_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, SGMII_PHYA_PWD); ++ ++ platform_set_drvdata(pdev, mpcs); ++ ++ return fwnode_pcs_add_provider(of_fwnode_handle(np), fwnode_pcs_simple_get, &mpcs->pcs); ++} ++ ++static void mtk_pcs_lynxi_remove(struct platform_device *pdev) ++{ ++ struct mtk_pcs_lynxi *mpcs = platform_get_drvdata(pdev); ++ ++ fwnode_pcs_del_provider(dev_fwnode(&pdev->dev)); ++ ++ rtnl_lock(); ++ phylink_release_pcs(&mpcs->pcs); ++ rtnl_unlock(); ++}; ++ ++static const struct of_device_id mtk_pcs_lynxi_of_match[] = { ++ { .compatible = "mediatek,mt7988-sgmii", .data = (void *)MTK_NETSYS_V3_AMA_RGC3 }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, mtk_pcs_lynxi_of_match); ++ ++static struct platform_driver mtk_pcs_lynxi_driver = { ++ .driver = { ++ .name = "mtk-pcs-lynxi", ++ .of_match_table = mtk_pcs_lynxi_of_match, ++ }, ++ .probe = mtk_pcs_lynxi_probe, ++ .remove = mtk_pcs_lynxi_remove, ++}; ++module_platform_driver(mtk_pcs_lynxi_driver); ++#endif ++ ++MODULE_AUTHOR("Daniel Golle "); + MODULE_DESCRIPTION("MediaTek SGMII library for LynxI"); + MODULE_LICENSE("GPL"); +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0062-dt-bindings-net-pcs-add-bindings-for-MediaTek-USXGMI.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0062-dt-bindings-net-pcs-add-bindings-for-MediaTek-USXGMI.patch new file mode 100644 index 0000000000..dd2b70b969 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0062-dt-bindings-net-pcs-add-bindings-for-MediaTek-USXGMI.patch @@ -0,0 +1,87 @@ +From 7a515019768258fa8183fd1784745197a5bc45d3 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 12 Dec 2023 03:47:31 +0000 +Subject: [PATCH 62/84] dt-bindings: net: pcs: add bindings for MediaTek + USXGMII PCS + +MediaTek's USXGMII can be found in the MT7988 SoC. We need to access +it in order to configure and monitor the Ethernet SerDes link in +USXGMII, 10GBase-R and 5GBase-R mode. By including a wrapped +legacy 1000Base-X/2500Base-X/Cisco SGMII LynxI PCS as well, those +interface modes are also available. + +Signed-off-by: Daniel Golle +--- + .../bindings/net/pcs/mediatek,usxgmii.yaml | 60 +++++++++++++++++++ + 1 file changed, 60 insertions(+) + create mode 100644 Documentation/devicetree/bindings/net/pcs/mediatek,usxgmii.yaml + +diff --git a/Documentation/devicetree/bindings/net/pcs/mediatek,usxgmii.yaml b/Documentation/devicetree/bindings/net/pcs/mediatek,usxgmii.yaml +new file mode 100644 +index 000000000000..0cdaa3545edb +--- /dev/null ++++ b/Documentation/devicetree/bindings/net/pcs/mediatek,usxgmii.yaml +@@ -0,0 +1,60 @@ ++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/net/pcs/mediatek,usxgmii.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: MediaTek USXGMII PCS ++ ++maintainers: ++ - Daniel Golle ++ ++description: ++ The MediaTek USXGMII PCS provides physical link control and status ++ for USXGMII, 10GBase-R and 5GBase-R links on the SerDes interfaces ++ provided by the PEXTP PHY. ++ In order to also support legacy 2500Base-X, 1000Base-X and Cisco ++ SGMII an existing mediatek,*-sgmiisys LynxI PCS is wrapped to ++ provide those interfaces modes on the same SerDes interfaces shared ++ with the USXGMII PCS. ++ ++properties: ++ $nodename: ++ pattern: "^pcs@[0-9a-f]+$" ++ ++ compatible: ++ const: mediatek,mt7988-usxgmiisys ++ ++ reg: ++ maxItems: 1 ++ ++ clocks: ++ items: ++ - description: USXGMII top-level clock ++ ++ resets: ++ items: ++ - description: XFI reset ++ ++required: ++ - compatible ++ - reg ++ - clocks ++ - resets ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ #define MT7988_TOPRGU_XFI0_GRST 12 ++ soc { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ usxgmiisys0: pcs@10080000 { ++ compatible = "mediatek,mt7988-usxgmiisys"; ++ reg = <0 0x10080000 0 0x1000>; ++ clocks = <&topckgen CLK_TOP_USXGMII_SBUS_0_SEL>; ++ resets = <&watchdog MT7988_TOPRGU_XFI0_GRST>; ++ }; ++ }; +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0063-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0063-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch new file mode 100644 index 0000000000..28bcc53d56 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0063-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch @@ -0,0 +1,576 @@ +From 00c9b2059de66096114b0a566ffcb4481aa83f81 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 12 Dec 2023 03:47:47 +0000 +Subject: [PATCH 63/84] net: pcs: add driver for MediaTek USXGMII PCS + +Add driver for USXGMII PCS found in the MediaTek MT7988 SoC and supporting +USXGMII, 10GBase-R and 5GBase-R interface modes. + +Signed-off-by: Daniel Golle +--- + MAINTAINERS | 2 + + drivers/net/pcs/Kconfig | 12 + + drivers/net/pcs/Kconfig.orig | 55 ++++ + drivers/net/pcs/Makefile | 1 + + drivers/net/pcs/pcs-mtk-usxgmii.c | 440 ++++++++++++++++++++++++++++++ + 5 files changed, 510 insertions(+) + create mode 100644 drivers/net/pcs/Kconfig.orig + create mode 100644 drivers/net/pcs/pcs-mtk-usxgmii.c + +diff --git a/MAINTAINERS b/MAINTAINERS +index c0b444e5fd5a..ad3b057e1c43 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -15275,7 +15275,9 @@ M: Daniel Golle + L: netdev@vger.kernel.org + S: Maintained + F: drivers/net/pcs/pcs-mtk-lynxi.c ++F: drivers/net/pcs/pcs-mtk-usxgmii.c + F: include/linux/pcs/pcs-mtk-lynxi.h ++F: include/linux/pcs/pcs-mtk-usxgmii.h + + MEDIATEK ETHERNET PHY DRIVERS + M: Daniel Golle +diff --git a/drivers/net/pcs/Kconfig b/drivers/net/pcs/Kconfig +index 69d28cd1e624..a63c910da105 100644 +--- a/drivers/net/pcs/Kconfig ++++ b/drivers/net/pcs/Kconfig +@@ -39,6 +39,18 @@ config PCS_MTK_LYNXI + This module provides helpers to phylink for managing the LynxI PCS + which is part of MediaTek's SoC and Ethernet switch ICs. + ++config PCS_MTK_USXGMII ++ tristate "MediaTek USXGMII PCS" ++ select FWNODE_PCS ++ select PCS_MTK_LYNXI ++ select PHYLINK ++ imply PHY_MTK_PEXTP ++ help ++ This module provides a driver for MediaTek's USXGMII PCS supporting ++ 10GBase-R, 5GBase-R and USXGMII interface modes. ++ 1000Base-X, 2500Base-X and Cisco SGMII are supported on the same ++ differential pairs via an embedded LynxI PCS. ++ + config PCS_RZN1_MIIC + tristate "Renesas RZ/N1 MII converter" + depends on OF && (ARCH_RZN1 || COMPILE_TEST) +diff --git a/drivers/net/pcs/Kconfig.orig b/drivers/net/pcs/Kconfig.orig +new file mode 100644 +index 000000000000..4f26acc7d47a +--- /dev/null ++++ b/drivers/net/pcs/Kconfig.orig +@@ -0,0 +1,55 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++# ++# PCS Layer Configuration ++# ++ ++menu "PCS device drivers" ++ ++config OF_PCS ++ tristate ++ depends on OF ++ depends on PHYLINK ++ help ++ OpenFirmware PCS accessors ++ ++config PCS_XPCS ++ tristate "Synopsys DesignWare Ethernet XPCS" ++ select PHYLINK ++ help ++ This module provides a driver and helper functions for Synopsys ++ DesignWare XPCS controllers. ++ ++config PCS_LYNX ++ tristate ++ help ++ This module provides helpers to phylink for managing the Lynx PCS ++ which is part of the Layerscape and QorIQ Ethernet SERDES. ++ ++config PCS_MTK_LYNXI ++ tristate ++ select REGMAP ++ help ++ This module provides helpers to phylink for managing the LynxI PCS ++ which is part of MediaTek's SoC and Ethernet switch ICs. ++ ++config PCS_MTK_USXGMII ++ tristate "MediaTek USXGMII PCS" ++ select OF_PCS ++ select PCS_MTK_LYNXI ++ select PHY_MTK_PEXTP ++ select PHYLINK ++ help ++ This module provides a driver for MediaTek's USXGMII PCS supporting ++ 10GBase-R, 5GBase-R and USXGMII interface modes. ++ 1000Base-X, 2500Base-X and Cisco SGMII are supported on the same ++ differential pairs via an embedded LynxI PHY. ++ ++config PCS_RZN1_MIIC ++ tristate "Renesas RZ/N1 MII converter" ++ depends on OF && (ARCH_RZN1 || COMPILE_TEST) ++ help ++ This module provides a driver for the MII converter that is available ++ on RZ/N1 SoCs. This PCS converts MII to RMII/RGMII or can be set in ++ pass-through mode for MII. ++ ++endmenu +diff --git a/drivers/net/pcs/Makefile b/drivers/net/pcs/Makefile +index c48450f08fb7..8492324b84e5 100644 +--- a/drivers/net/pcs/Makefile ++++ b/drivers/net/pcs/Makefile +@@ -9,4 +9,5 @@ pcs_xpcs-$(CONFIG_PCS_XPCS) := pcs-xpcs.o pcs-xpcs-plat.o \ + obj-$(CONFIG_PCS_XPCS) += pcs_xpcs.o + obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o + obj-$(CONFIG_PCS_MTK_LYNXI) += pcs-mtk-lynxi.o ++obj-$(CONFIG_PCS_MTK_USXGMII) += pcs-mtk-usxgmii.o + obj-$(CONFIG_PCS_RZN1_MIIC) += pcs-rzn1-miic.o +diff --git a/drivers/net/pcs/pcs-mtk-usxgmii.c b/drivers/net/pcs/pcs-mtk-usxgmii.c +new file mode 100644 +index 000000000000..c2fa0ba8fcc7 +--- /dev/null ++++ b/drivers/net/pcs/pcs-mtk-usxgmii.c +@@ -0,0 +1,440 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2023 MediaTek Inc. ++ * Author: Henry Yen ++ * Daniel Golle ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* USXGMII subsystem config registers */ ++/* Register to control speed */ ++#define RG_PHY_TOP_SPEED_CTRL1 0x80c ++#define USXGMII_RATE_UPDATE_MODE BIT(31) ++#define USXGMII_MAC_CK_GATED BIT(29) ++#define USXGMII_IF_FORCE_EN BIT(28) ++#define USXGMII_RATE_ADAPT_MODE GENMASK(10, 8) ++#define USXGMII_RATE_ADAPT_MODE_X1 0 ++#define USXGMII_RATE_ADAPT_MODE_X2 1 ++#define USXGMII_RATE_ADAPT_MODE_X4 2 ++#define USXGMII_RATE_ADAPT_MODE_X10 3 ++#define USXGMII_RATE_ADAPT_MODE_X100 4 ++#define USXGMII_RATE_ADAPT_MODE_X5 5 ++#define USXGMII_RATE_ADAPT_MODE_X50 6 ++#define USXGMII_XFI_RX_MODE GENMASK(6, 4) ++#define USXGMII_XFI_TX_MODE GENMASK(2, 0) ++#define USXGMII_XFI_MODE_10G 0 ++#define USXGMII_XFI_MODE_5G 1 ++#define USXGMII_XFI_MODE_2P5G 3 ++ ++/* Register to control PCS AN */ ++#define RG_PCS_AN_CTRL0 0x810 ++#define USXGMII_AN_RESTART BIT(31) ++#define USXGMII_AN_SYNC_CNT GENMASK(30, 11) ++#define USXGMII_AN_ENABLE BIT(0) ++ ++#define RG_PCS_AN_CTRL2 0x818 ++#define USXGMII_LINK_TIMER_IDLE_DETECT GENMASK(29, 20) ++#define USXGMII_LINK_TIMER_COMP_ACK_DETECT GENMASK(19, 10) ++#define USXGMII_LINK_TIMER_AN_RESTART GENMASK(9, 0) ++ ++/* Register to read PCS AN status */ ++#define RG_PCS_AN_STS0 0x81c ++#define USXGMII_LPA GENMASK(15, 0) ++#define USXGMII_LPA_LATCH BIT(31) ++ ++/* Register to read PCS link status */ ++#define RG_PCS_RX_STATUS0 0x904 ++#define RG_PCS_RX_STATUS_UPDATE BIT(16) ++#define RG_PCS_RX_LINK_STATUS BIT(2) ++ ++/* struct mtk_usxgmii_pcs - This structure holds each usxgmii PCS ++ * @pcs: Phylink PCS structure ++ * @dev: Pointer to device structure ++ * @base: IO memory to access PCS hardware ++ * @clk: Pointer to USXGMII clk ++ * @reset: Pointer to USXGMII reset control ++ * @interface: Currently selected interface mode ++ * @neg_mode: Currently used phylink neg_mode ++ * @node: List node ++ */ ++struct mtk_usxgmii_pcs { ++ struct phylink_pcs pcs; ++ struct device *dev; ++ void __iomem *base; ++ struct clk *clk; ++ struct reset_control *reset; ++ struct phy *xfi_tphy; ++ phy_interface_t interface; ++ unsigned int neg_mode; ++ struct list_head node; ++}; ++ ++static u32 mtk_r32(struct mtk_usxgmii_pcs *mpcs, unsigned int reg) ++{ ++ return ioread32(mpcs->base + reg); ++} ++ ++static void mtk_m32(struct mtk_usxgmii_pcs *mpcs, unsigned int reg, u32 mask, u32 set) ++{ ++ u32 val; ++ ++ val = ioread32(mpcs->base + reg); ++ val &= ~mask; ++ val |= set; ++ iowrite32(val, mpcs->base + reg); ++} ++ ++static struct mtk_usxgmii_pcs *pcs_to_mtk_usxgmii_pcs(struct phylink_pcs *pcs) ++{ ++ return container_of(pcs, struct mtk_usxgmii_pcs, pcs); ++} ++ ++static void mtk_usxgmii_reset(struct mtk_usxgmii_pcs *mpcs) ++{ ++ reset_control_assert(mpcs->reset); ++ udelay(100); ++ reset_control_deassert(mpcs->reset); ++ ++ mdelay(10); ++} ++ ++static int mtk_usxgmii_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, ++ phy_interface_t interface, ++ const unsigned long *advertising, ++ bool permit_pause_to_mac) ++{ ++ struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs); ++ unsigned int an_ctrl = 0, link_timer = 0, xfi_mode = 0, adapt_mode = 0; ++ bool mode_changed = false; ++ ++ if (interface == PHY_INTERFACE_MODE_USXGMII) { ++ an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0x1FF) | USXGMII_AN_ENABLE; ++ link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x7B) | ++ FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x7B) | ++ FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x7B); ++ xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_MODE_10G) | ++ FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_MODE_10G); ++ } else if (interface == PHY_INTERFACE_MODE_10GBASER) { ++ an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0x1FF); ++ link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x7B) | ++ FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x7B) | ++ FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x7B); ++ xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_MODE_10G) | ++ FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_MODE_10G); ++ adapt_mode = USXGMII_RATE_UPDATE_MODE; ++ } else if (interface == PHY_INTERFACE_MODE_5GBASER) { ++ an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0xFF); ++ link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x3D) | ++ FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x3D) | ++ FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x3D); ++ xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_MODE_5G) | ++ FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_MODE_5G); ++ adapt_mode = USXGMII_RATE_UPDATE_MODE; ++ } else { ++ return -EINVAL; ++ } ++ ++ adapt_mode |= FIELD_PREP(USXGMII_RATE_ADAPT_MODE, USXGMII_RATE_ADAPT_MODE_X1); ++ ++ if (mpcs->interface != interface) { ++ mpcs->interface = interface; ++ mode_changed = true; ++ } ++ ++ phy_reset(mpcs->xfi_tphy); ++ mtk_usxgmii_reset(mpcs); ++ ++ /* Setup USXGMII AN ctrl */ ++ mtk_m32(mpcs, RG_PCS_AN_CTRL0, ++ USXGMII_AN_SYNC_CNT | USXGMII_AN_ENABLE, ++ an_ctrl); ++ ++ mtk_m32(mpcs, RG_PCS_AN_CTRL2, ++ USXGMII_LINK_TIMER_IDLE_DETECT | ++ USXGMII_LINK_TIMER_COMP_ACK_DETECT | ++ USXGMII_LINK_TIMER_AN_RESTART, ++ link_timer); ++ ++ mpcs->neg_mode = neg_mode; ++ ++ /* Gated MAC CK */ ++ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1, ++ USXGMII_MAC_CK_GATED, USXGMII_MAC_CK_GATED); ++ ++ /* Enable interface force mode */ ++ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1, ++ USXGMII_IF_FORCE_EN, USXGMII_IF_FORCE_EN); ++ ++ /* Setup USXGMII adapt mode */ ++ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1, ++ USXGMII_RATE_UPDATE_MODE | USXGMII_RATE_ADAPT_MODE, ++ adapt_mode); ++ ++ /* Setup USXGMII speed */ ++ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1, ++ USXGMII_XFI_RX_MODE | USXGMII_XFI_TX_MODE, ++ xfi_mode); ++ ++ usleep_range(1, 10); ++ ++ /* Un-gated MAC CK */ ++ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1, USXGMII_MAC_CK_GATED, 0); ++ ++ usleep_range(1, 10); ++ ++ /* Disable interface force mode for the AN mode */ ++ if (an_ctrl & USXGMII_AN_ENABLE) ++ mtk_m32(mpcs, RG_PHY_TOP_SPEED_CTRL1, USXGMII_IF_FORCE_EN, 0); ++ ++ /* Setup PMA/PMD */ ++ phy_set_mode_ext(mpcs->xfi_tphy, PHY_MODE_ETHERNET, interface); ++ ++ return mode_changed; ++} ++ ++static void mtk_usxgmii_pcs_get_fixed_speed(struct mtk_usxgmii_pcs *mpcs, ++ struct phylink_link_state *state) ++{ ++ u32 val = mtk_r32(mpcs, RG_PHY_TOP_SPEED_CTRL1); ++ int speed; ++ ++ /* Calculate speed from interface speed and rate adapt mode */ ++ switch (FIELD_GET(USXGMII_XFI_RX_MODE, val)) { ++ case USXGMII_XFI_MODE_10G: ++ speed = 10000; ++ break; ++ case USXGMII_XFI_MODE_5G: ++ speed = 5000; ++ break; ++ case USXGMII_XFI_MODE_2P5G: ++ speed = 2500; ++ break; ++ default: ++ state->speed = SPEED_UNKNOWN; ++ return; ++ } ++ ++ switch (FIELD_GET(USXGMII_RATE_ADAPT_MODE, val)) { ++ case USXGMII_RATE_ADAPT_MODE_X100: ++ speed /= 100; ++ break; ++ case USXGMII_RATE_ADAPT_MODE_X50: ++ speed /= 50; ++ break; ++ case USXGMII_RATE_ADAPT_MODE_X10: ++ speed /= 10; ++ break; ++ case USXGMII_RATE_ADAPT_MODE_X5: ++ speed /= 5; ++ break; ++ case USXGMII_RATE_ADAPT_MODE_X4: ++ speed /= 4; ++ break; ++ case USXGMII_RATE_ADAPT_MODE_X2: ++ speed /= 2; ++ break; ++ case USXGMII_RATE_ADAPT_MODE_X1: ++ break; ++ default: ++ state->speed = SPEED_UNKNOWN; ++ return; ++ } ++ ++ state->speed = speed; ++ state->duplex = DUPLEX_FULL; ++} ++ ++static void mtk_usxgmii_pcs_get_an_state(struct mtk_usxgmii_pcs *mpcs, ++ struct phylink_link_state *state) ++{ ++ u16 lpa; ++ ++ /* Refresh LPA by toggling LPA_LATCH */ ++ mtk_m32(mpcs, RG_PCS_AN_STS0, USXGMII_LPA_LATCH, USXGMII_LPA_LATCH); ++ ndelay(1020); ++ mtk_m32(mpcs, RG_PCS_AN_STS0, USXGMII_LPA_LATCH, 0); ++ ndelay(1020); ++ lpa = FIELD_GET(USXGMII_LPA, mtk_r32(mpcs, RG_PCS_AN_STS0)); ++ ++ phylink_decode_usxgmii_word(state, lpa); ++} ++ ++static void mtk_usxgmii_pcs_get_state(struct phylink_pcs *pcs, ++ unsigned int neg_mode, ++ struct phylink_link_state *state) ++{ ++ struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs); ++ ++ /* Refresh USXGMII link status by toggling RG_PCS_AN_STATUS_UPDATE */ ++ mtk_m32(mpcs, RG_PCS_RX_STATUS0, RG_PCS_RX_STATUS_UPDATE, ++ RG_PCS_RX_STATUS_UPDATE); ++ ndelay(1020); ++ mtk_m32(mpcs, RG_PCS_RX_STATUS0, RG_PCS_RX_STATUS_UPDATE, 0); ++ ndelay(1020); ++ ++ /* Read USXGMII link status */ ++ state->link = FIELD_GET(RG_PCS_RX_LINK_STATUS, ++ mtk_r32(mpcs, RG_PCS_RX_STATUS0)); ++ ++ /* Continuously repeat re-configuration sequence until link comes up */ ++ if (!state->link) { ++ mtk_usxgmii_pcs_config(pcs, mpcs->neg_mode, ++ state->interface, NULL, false); ++ return; ++ } ++ ++ if (FIELD_GET(USXGMII_AN_ENABLE, mtk_r32(mpcs, RG_PCS_AN_CTRL0))) ++ mtk_usxgmii_pcs_get_an_state(mpcs, state); ++ else ++ mtk_usxgmii_pcs_get_fixed_speed(mpcs, state); ++} ++ ++static void mtk_usxgmii_pcs_restart_an(struct phylink_pcs *pcs) ++{ ++ struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs); ++ ++ mtk_m32(mpcs, RG_PCS_AN_CTRL0, USXGMII_AN_RESTART, USXGMII_AN_RESTART); ++} ++ ++static void mtk_usxgmii_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode, ++ phy_interface_t interface, ++ int speed, int duplex) ++{ ++ struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs); ++ ++ /* Reconfiguring USXGMII to ensure the quality of the RX signal ++ * after the line side link up. ++ */ ++ mtk_usxgmii_pcs_config(pcs, neg_mode, interface, NULL, false); ++ phy_reset(mpcs->xfi_tphy); ++ phy_set_mode_ext(mpcs->xfi_tphy, PHY_MODE_ETHERNET, interface); ++} ++ ++static int mtk_usxgmii_pcs_enable(struct phylink_pcs *pcs) ++{ ++ struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs); ++ ++ phy_power_on(mpcs->xfi_tphy); ++ ++ return 0; ++} ++ ++static void mtk_usxgmii_pcs_disable(struct phylink_pcs *pcs) ++{ ++ struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs); ++ ++ mpcs->interface = PHY_INTERFACE_MODE_NA; ++ mpcs->neg_mode = -1; ++ ++ phy_power_off(mpcs->xfi_tphy); ++} ++ ++static unsigned int mtk_usxgmii_pcs_inband_caps(struct phylink_pcs *pcs, ++ phy_interface_t interface) ++{ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_5GBASER: ++ case PHY_INTERFACE_MODE_10GBASER: ++ case PHY_INTERFACE_MODE_USXGMII: ++ return LINK_INBAND_ENABLE; ++ ++ default: ++ return 0; ++ } ++} ++ ++static const struct phylink_pcs_ops mtk_usxgmii_pcs_ops = { ++ .pcs_inband_caps = mtk_usxgmii_pcs_inband_caps, ++ .pcs_config = mtk_usxgmii_pcs_config, ++ .pcs_get_state = mtk_usxgmii_pcs_get_state, ++ .pcs_an_restart = mtk_usxgmii_pcs_restart_an, ++ .pcs_link_up = mtk_usxgmii_pcs_link_up, ++ .pcs_enable = mtk_usxgmii_pcs_enable, ++ .pcs_disable = mtk_usxgmii_pcs_disable, ++}; ++ ++static int mtk_usxgmii_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct mtk_usxgmii_pcs *mpcs; ++ ++ mpcs = devm_kzalloc(dev, sizeof(*mpcs), GFP_KERNEL); ++ if (!mpcs) ++ return -ENOMEM; ++ ++ mpcs->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(mpcs->base)) ++ return PTR_ERR(mpcs->base); ++ ++ mpcs->dev = dev; ++ mpcs->pcs.ops = &mtk_usxgmii_pcs_ops; ++ mpcs->pcs.poll = true; ++ mpcs->interface = PHY_INTERFACE_MODE_NA; ++ mpcs->neg_mode = -1; ++ ++ __set_bit(PHY_INTERFACE_MODE_5GBASER, mpcs->pcs.supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_10GBASER, mpcs->pcs.supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_USXGMII, mpcs->pcs.supported_interfaces); ++ ++ mpcs->clk = devm_clk_get_enabled(mpcs->dev, NULL); ++ if (IS_ERR(mpcs->clk)) ++ return PTR_ERR(mpcs->clk); ++ ++ mpcs->xfi_tphy = devm_of_phy_get(mpcs->dev, dev->of_node, NULL); ++ if (IS_ERR(mpcs->xfi_tphy)) ++ return PTR_ERR(mpcs->xfi_tphy); ++ ++ mpcs->reset = devm_reset_control_get_shared(dev, NULL); ++ if (IS_ERR(mpcs->reset)) ++ return PTR_ERR(mpcs->reset); ++ ++ reset_control_deassert(mpcs->reset); ++ ++ platform_set_drvdata(pdev, mpcs); ++ ++ return fwnode_pcs_add_provider(dev_fwnode(dev), fwnode_pcs_simple_get, &mpcs->pcs); ++} ++ ++static void mtk_usxgmii_remove(struct platform_device *pdev) ++{ ++ struct mtk_usxgmii_pcs *mpcs = platform_get_drvdata(pdev); ++ ++ fwnode_pcs_del_provider(dev_fwnode(&pdev->dev)); ++ ++ rtnl_lock(); ++ phylink_release_pcs(&mpcs->pcs); ++ rtnl_unlock(); ++}; ++ ++static const struct of_device_id mtk_usxgmii_of_mtable[] = { ++ { .compatible = "mediatek,mt7988-usxgmiisys" }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, mtk_usxgmii_of_mtable); ++ ++static struct platform_driver mtk_usxgmii_driver = { ++ .driver = { ++ .name = "mtk-pcs-usxgmii", ++ .of_match_table = mtk_usxgmii_of_mtable, ++ }, ++ .probe = mtk_usxgmii_probe, ++ .remove = mtk_usxgmii_remove, ++}; ++module_platform_driver(mtk_usxgmii_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("MediaTek USXGMII PCS driver"); ++MODULE_AUTHOR("Daniel Golle "); +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0064-net-ethernet-mtk_eth_soc-add-more-DMA-monitor-for-MT.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0064-net-ethernet-mtk_eth_soc-add-more-DMA-monitor-for-MT.patch new file mode 100644 index 0000000000..f10f72f9bf --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0064-net-ethernet-mtk_eth_soc-add-more-DMA-monitor-for-MT.patch @@ -0,0 +1,141 @@ +From 67b86aed2e5cad973b8616f685228c03f94ef9b9 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Fri, 1 Sep 2023 12:31:38 +0100 +Subject: [PATCH 64/84] net: ethernet: mtk_eth_soc: add more DMA monitor for + MT7988 + +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 55 +++++++++++++++++++-- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 11 +++++ + 2 files changed, 61 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index ac7250003b1d..e5f0b9220aa1 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -4022,10 +4022,13 @@ static void mtk_hw_warm_reset(struct mtk_eth *eth) + static bool mtk_hw_check_dma_hang(struct mtk_eth *eth) + { + const struct mtk_reg_map *reg_map = eth->soc->reg_map; +- bool gmac1_tx, gmac2_tx, gdm1_tx, gdm2_tx; ++ bool gmac1_tx, gmac2_tx, gmac3_tx = false, gdm1_tx, gdm2_tx, gdm3_tx = false; + bool oq_hang, cdm1_busy, adma_busy; + bool wtx_busy, cdm_full, oq_free; +- u32 wdidx, val, gdm1_fc, gdm2_fc; ++ u32 wdidx, val, gdm1_fc, gdm2_fc, gdm3_fc; ++ u32 tdma_glo_cfg, cur_fsm, ipq10; ++ bool rx_busy, tx_busy, cur_fsm_tx, cur_fsm_rx; ++ + bool qfsm_hang, qfwd_hang; + bool ret = false; + +@@ -4061,12 +4064,19 @@ static bool mtk_hw_check_dma_hang(struct mtk_eth *eth) + gdm2_tx = FIELD_GET(GENMASK(31, 16), mtk_r32(eth, MTK_FE_GDM2_FSM)) > 0; + gmac1_tx = FIELD_GET(GENMASK(31, 24), mtk_r32(eth, MTK_MAC_FSM(0))) != 1; + gmac2_tx = FIELD_GET(GENMASK(31, 24), mtk_r32(eth, MTK_MAC_FSM(1))) != 1; +- gdm1_fc = mtk_r32(eth, reg_map->gdm1_cnt + 0x24); +- gdm2_fc = mtk_r32(eth, reg_map->gdm1_cnt + 0x64); ++ gdm1_fc = mtk_r32(eth, reg_map->gdm1_cnt + MTK_GDM_RX_FC_OFFSET(eth, 0)); ++ gdm2_fc = mtk_r32(eth, reg_map->gdm1_cnt + MTK_GDM_RX_FC_OFFSET(eth, 1)); ++ ++ if (mtk_is_netsys_v3_or_greater(eth)) { ++ gdm3_tx = FIELD_GET(GENMASK(31, 16), mtk_r32(eth, MTK_FE_GDM3_FSM)) > 0; ++ gmac3_tx = FIELD_GET(GENMASK(31, 24), mtk_r32(eth, MTK_MAC_FSM(2))) != 1; ++ gdm3_fc = mtk_r32(eth, reg_map->gdm1_cnt + MTK_GDM_RX_FC_OFFSET(eth, 2)); ++ } + + if (qfsm_hang && qfwd_hang && + ((gdm1_tx && gmac1_tx && gdm1_fc < 1) || +- (gdm2_tx && gmac2_tx && gdm2_fc < 1))) { ++ (gdm2_tx && gmac2_tx && gdm2_fc < 1) || ++ (mtk_is_netsys_v3_or_greater(eth) && gdm3_tx && gmac3_tx && gdm3_fc < 1))) { + if (++eth->reset.qdma_hang_count > 2) { + eth->reset.qdma_hang_count = 0; + ret = true; +@@ -4088,12 +4098,47 @@ static bool mtk_hw_check_dma_hang(struct mtk_eth *eth) + goto out; + } + ++ if (mtk_is_netsys_v3_or_greater(eth)) { ++ ipq10 = mtk_r32(eth, reg_map->pse_iq_sta + 24) & GENMASK(23, 0); ++ cur_fsm = mtk_r32(eth, MTK_FE_CDM6_FSM); ++ tdma_glo_cfg = mtk_r32(eth, MTK_TDMA_GLO_CFG); ++ cur_fsm_rx = !(cur_fsm & GENMASK(27, 16)); ++ cur_fsm_tx = !(cur_fsm & GENMASK(24, 0)); ++ tx_busy = !(tdma_glo_cfg & BIT(1)); ++ rx_busy = !(tdma_glo_cfg & BIT(3)); ++ ++ if (ipq10 && cur_fsm_tx && tx_busy && ++ cur_fsm_tx == !!(eth->reset.pre_fsm & GENMASK(24, 0)) && ++ ipq10 == eth->reset.pre_ipq10) { ++ if (++eth->reset.tdma_tx_hang_count > 2) { ++ eth->reset.tdma_tx_hang_count = 0; ++ ret = true; ++ } ++ goto out; ++ } ++ ++ if (cur_fsm_rx && rx_busy && ++ cur_fsm_rx == (eth->reset.pre_fsm & GENMASK(27, 16))) { ++ if (++eth->reset.tdma_rx_hang_count > 2) { ++ eth->reset.tdma_rx_hang_count = 0; ++ ret = true; ++ } ++ goto out; ++ } ++ } ++ + eth->reset.wdma_hang_count = 0; + eth->reset.qdma_hang_count = 0; + eth->reset.adma_hang_count = 0; ++ eth->reset.tdma_tx_hang_count = 0; ++ eth->reset.tdma_rx_hang_count = 0; + out: + eth->reset.wdidx = wdidx; + ++ if (mtk_is_netsys_v3_or_greater(eth)) { ++ eth->reset.pre_fsm = cur_fsm; ++ eth->reset.pre_ipq10 = ipq10; ++ } + return ret; + } + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +index 88406e80dfec..91b2375f9405 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -401,6 +401,8 @@ + #define RX_DMA_VTAG_V2 BIT(0) + #define RX_DMA_L4_VALID_V2 BIT(2) + ++#define MTK_TDMA_GLO_CFG 0x6204 ++ + /* PHY Polling and SMI Master Control registers */ + #define MTK_PPSC 0x10000 + #define PPSC_MDC_CFG GENMASK(29, 24) +@@ -659,6 +661,11 @@ + #define MTK_FE_IRQ_RX 1 + #define MTK_FE_IRQ_NUM (MTK_FE_IRQ_RX + 1) + ++#define MTK_STAT_OFFSET 0x40 ++#define MTK_STAT_OFFSET_V3 0x80 ++#define MTK_GDM_RX_FC 0x24 ++#define MTK_GDM_RX_FC_OFFSET(eth, i) (i * (mtk_is_netsys_v3_or_greater(eth) ? MTK_STAT_OFFSET_V3 : MTK_STAT_OFFSET) + MTK_GDM_RX_FC) ++ + struct mtk_rx_dma { + unsigned int rxd1; + unsigned int rxd2; +@@ -1392,6 +1399,10 @@ struct mtk_eth { + u8 wdma_hang_count; + u8 qdma_hang_count; + u8 adma_hang_count; ++ u8 tdma_rx_hang_count; ++ u8 tdma_tx_hang_count; ++ u32 pre_ipq10; ++ u32 pre_fsm; + } reset; + }; + +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0065-hwrng-add-driver-for-MediaTek-TRNG-SMC.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0065-hwrng-add-driver-for-MediaTek-TRNG-SMC.patch new file mode 100644 index 0000000000..32ae098e53 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0065-hwrng-add-driver-for-MediaTek-TRNG-SMC.patch @@ -0,0 +1,140 @@ +From 2d33fddfcc8e36b50910e92bb965a75c4685fb98 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Wed, 25 Jan 2023 00:27:49 +0000 +Subject: [PATCH 65/84] hwrng: add driver for MediaTek TRNG SMC + +Add driver providing kernel-side support for the Random Number +Generator hardware found on Mediatek SoCs which have a driver in ARM +TrustedFirmware-A allowing Linux to read random numbers using a +non-standard vendor-defined Secure Monitor Call. + +Signed-off-by: Daniel Golle +--- + drivers/char/hw_random/Kconfig | 16 +++++++ + drivers/char/hw_random/Makefile | 1 + + drivers/char/hw_random/mtk-rng-v2.c | 74 +++++++++++++++++++++++++++++ + 3 files changed, 91 insertions(+) + create mode 100644 drivers/char/hw_random/mtk-rng-v2.c + +diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig +index c85827843447..1a5fd4a966bd 100644 +--- a/drivers/char/hw_random/Kconfig ++++ b/drivers/char/hw_random/Kconfig +@@ -477,6 +477,22 @@ config HW_RANDOM_MTK + + If unsure, say Y. + ++config HW_RANDOM_MTK_V2 ++ tristate "Mediatek Random Number Generator support (v2/SMC)" ++ depends on HW_RANDOM ++ depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST ++ default y ++ help ++ This driver provides kernel-side support for the Random Number ++ Generator hardware found on Mediatek SoCs which have a driver ++ in ARM TrustedFirmware-A allowing Linux to read using a non- ++ standard vendor-defined Secure Monitor Call. ++ ++ To compile this driver as a module, choose M here. the ++ module will be called mtk-rng-v2. ++ ++ If unsure, say Y. ++ + config HW_RANDOM_S390 + tristate "S390 True Random Number Generator support" + depends on S390 +diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile +index b9132b3f5d21..1e7ad556e784 100644 +--- a/drivers/char/hw_random/Makefile ++++ b/drivers/char/hw_random/Makefile +@@ -41,6 +41,7 @@ obj-$(CONFIG_HW_RANDOM_PIC32) += pic32-rng.o + obj-$(CONFIG_HW_RANDOM_MESON) += meson-rng.o + obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o + obj-$(CONFIG_HW_RANDOM_MTK) += mtk-rng.o ++obj-$(CONFIG_HW_RANDOM_MTK_V2) += mtk-rng-v2.o + obj-$(CONFIG_HW_RANDOM_S390) += s390-trng.o + obj-$(CONFIG_HW_RANDOM_KEYSTONE) += ks-sa-rng.o + obj-$(CONFIG_HW_RANDOM_OPTEE) += optee-rng.o +diff --git a/drivers/char/hw_random/mtk-rng-v2.c b/drivers/char/hw_random/mtk-rng-v2.c +new file mode 100644 +index 000000000000..6e61f4361d9e +--- /dev/null ++++ b/drivers/char/hw_random/mtk-rng-v2.c +@@ -0,0 +1,74 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Driver for Mediatek Hardware Random Number Generator (v2/SMCC) ++ * ++ * Copyright (C) 2023 Daniel Golle ++ * based on patch from Mingming Su ++ */ ++#define MTK_RNG_DEV KBUILD_MODNAME ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MTK_SIP_KERNEL_GET_RND MTK_SIP_SMC_CMD(0x550) ++ ++static int mtk_rng_v2_read(struct hwrng *rng, void *buf, size_t max, bool wait) ++{ ++ struct arm_smccc_res res; ++ int retval = 0; ++ ++ while (max >= sizeof(u32)) { ++ arm_smccc_smc(MTK_SIP_KERNEL_GET_RND, 0, 0, 0, 0, 0, 0, 0, ++ &res); ++ if (res.a0) ++ break; ++ ++ *(u32 *)buf = res.a1; ++ retval += sizeof(u32); ++ buf += sizeof(u32); ++ max -= sizeof(u32); ++ } ++ ++ return retval || !wait ? retval : -EIO; ++} ++ ++static int mtk_rng_v2_probe(struct platform_device *pdev) ++{ ++ struct hwrng *trng; ++ ++ trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL); ++ if (!trng) ++ return -ENOMEM; ++ ++ trng->name = pdev->name; ++ trng->read = mtk_rng_v2_read; ++ trng->quality = 900; ++ ++ return devm_hwrng_register(&pdev->dev, trng); ++} ++ ++static const struct of_device_id mtk_rng_v2_match[] = { ++ { .compatible = "mediatek,mt7981-rng" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, mtk_rng_v2_match); ++ ++static struct platform_driver mtk_rng_v2_driver = { ++ .probe = mtk_rng_v2_probe, ++ .driver = { ++ .name = KBUILD_MODNAME, ++ .of_match_table = mtk_rng_v2_match, ++ }, ++}; ++module_platform_driver(mtk_rng_v2_driver); ++ ++MODULE_DESCRIPTION("Mediatek Random Number Generator Driver (v2/SMC)"); ++MODULE_AUTHOR("Daniel Golle "); ++MODULE_LICENSE("GPL"); +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0066-dts64-enable-sata-and-disable-pcie-slot-CN8-shared.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0066-dts64-enable-sata-and-disable-pcie-slot-CN8-shared.patch new file mode 100644 index 0000000000..820bd7febe --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0066-dts64-enable-sata-and-disable-pcie-slot-CN8-shared.patch @@ -0,0 +1,39 @@ +From 2bb35754b2c9f707d1921952dbc6314ea285f360 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Wed, 27 Nov 2019 17:19:07 +0100 +Subject: [PATCH 66/84] dts64: enable sata and disable pcie-slot CN8 (shared) + +--- + arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +index 9f100b18a676..7e6c5c25cfa1 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts ++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts +@@ -323,7 +323,7 @@ &pio { + asm-sel-hog { + gpio-hog; + gpios = <90 GPIO_ACTIVE_HIGH>; +- output-high; ++ output-low; + }; + + /* eMMC is shared pin with parallel NAND */ +@@ -597,11 +597,11 @@ &pwrap { + }; + + &sata { +- status = "disabled"; ++ status = "okay"; + }; + + &sata_phy { +- status = "disabled"; ++ status = "okay"; + }; + + &spi0 { +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0067-arm64-dts-mt7622-fix-sata.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0067-arm64-dts-mt7622-fix-sata.patch new file mode 100644 index 0000000000..ca6dfd093b --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0067-arm64-dts-mt7622-fix-sata.patch @@ -0,0 +1,29 @@ +From 951a242f5e95fc590e383ba9c9f0a91f3313b49d Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Thu, 27 Jun 2024 22:48:27 +0200 +Subject: [PATCH 67/84] arm64: dts: mt7622: fix sata + +[ 2.480551] ahci-mtk 1a200000.sata: missing phy-mode phandle +[ 2.486249] ahci-mtk 1a200000.sata: probe with driver ahci-mtk failed with error -22 + +Fixes: 3ba5a6159434 ("arm64: dts: mediatek: mt7622: fix clock controllers") +--- + arch/arm64/boot/dts/mediatek/mt7622.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +index 917fa39a74f8..f22983c33365 100644 +--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi +@@ -790,7 +790,7 @@ u2port1: usb-phy@1a0c5000 { + }; + + pciesys: clock-controller@1a100800 { +- compatible = "mediatek,mt7622-pciesys"; ++ compatible = "mediatek,mt7622-pciesys","syscon"; + reg = <0 0x1a100800 0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0068-kdeb-try-to-add-kernels-for-bpi-boards-to-deb-packag.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0068-kdeb-try-to-add-kernels-for-bpi-boards-to-deb-packag.patch new file mode 100644 index 0000000000..b7a37e819d --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0068-kdeb-try-to-add-kernels-for-bpi-boards-to-deb-packag.patch @@ -0,0 +1,65 @@ +From b8a589bd3322f55d7642e2c32f5aceb33c792e6e Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sun, 14 Jan 2024 14:47:21 +0100 +Subject: [PATCH 68/84] kdeb: try to add kernels for bpi-boards to deb-packages + +--- + scripts/package/builddeb | 41 ++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 39 insertions(+), 2 deletions(-) + +diff --git a/scripts/package/builddeb b/scripts/package/builddeb +index 3627ca227e5a..4c2142959768 100755 +--- a/scripts/package/builddeb ++++ b/scripts/package/builddeb +@@ -61,9 +61,46 @@ install_linux_image () { + parisc|mips|powerpc) + installed_image_path="boot/vmlinux-${KERNELRELEASE}";; + *) +- installed_image_path="boot/vmlinuz-${KERNELRELEASE}";; ++ source_image_path="./$board.itb" ++ installed_image_path=boot/$board-${KERNELRELEASE}.itb ++ case $board in ++ bpi-r2) ++ mkdir -p "${pdir}/boot/bananapi/$board/linux/dtb" ++ DTBFILE=arch/arm/boot/dts/mediatek/mt7623n-bananapi-bpi-r2.dtb ++ cp ${srctree}/uImage_nodt "${pdir}/boot/bananapi/$board/linux/uImage-${KERNELRELEASE}_nodt" ++ source_image_path="${srctree}/uImage" ++ installed_image_path="boot/bananapi/$board/linux/uImage-${KERNELRELEASE}" ++ ;; ++ bpi-r64) ++ mkdir -p "${pdir}/boot/bananapi/$board/linux/dtb" ++ DTBFILE=arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dtb ++ cp ${srctree}/uImage_nodt "${pdir}/boot/bananapi/$board/linux/uImage-${KERNELRELEASE}_nodt" ++ ;; ++ bpi-r2pro) ++ DTBFILE=arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dtb ++ mkdir -p ${pdir}/boot/extlinux/ ++ cp arch/arm64/boot/Image.gz "${pdir}/boot/extlinux/Image-${KERNELRELEASE}.gz" ++ ;; ++ bpi-r3|bpi-r4) ++ #R3/R4 only use FIT and no standalone kernel/dtbs ++ ;; ++ *) ++ installed_image_path="boot/vmlinuz-${KERNELRELEASE}" ++ source_image_path="$($MAKE -s -f ${srctree}/Makefile image_name)" ++ ;; ++ esac ++ ;; + esac +- cp "$(${MAKE} -s -f ${srctree}/Makefile image_name)" "${pdir}/${installed_image_path}" ++ ++ if [ -n "$DTBFILE" ];then ++ if [ $board != "bpi-r2pro" ];then ++ cp $DTBFILE "${pdir}/boot/bananapi/$board/linux/dtb/$board-${KERNELRELEASE}.dtb" ++ else ++ cp $DTBFILE "${pdir}/boot/extlinux/$board-${KERNELRELEASE}.dtb" ++ fi ++ fi ++ ++ cp "${source_image_path}" "${pdir}/${installed_image_path}" + + if [ "${ARCH}" != um ]; then + install_maint_scripts "${pdir}" +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0069-kdeb-fix-deb-build-for-R3-R4.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0069-kdeb-fix-deb-build-for-R3-R4.patch new file mode 100644 index 0000000000..d8efd079ae --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0069-kdeb-fix-deb-build-for-R3-R4.patch @@ -0,0 +1,26 @@ +From 7483e1ad82099905e2f462be333074c8f8942f13 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Tue, 22 Apr 2025 19:45:32 +0200 +Subject: [PATCH 69/84] kdeb: fix deb build for R3+R4 + +due to the set +u unassigned variables will be handled as error +and so build fails. +--- + scripts/package/builddeb | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/scripts/package/builddeb b/scripts/package/builddeb +index 4c2142959768..11429129e044 100755 +--- a/scripts/package/builddeb ++++ b/scripts/package/builddeb +@@ -63,6 +63,7 @@ install_linux_image () { + *) + source_image_path="./$board.itb" + installed_image_path=boot/$board-${KERNELRELEASE}.itb ++ DTBFILE="" + case $board in + bpi-r2) + mkdir -p "${pdir}/boot/bananapi/$board/linux/dtb" +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0070-build.conf-change-to-r4.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0070-build.conf-change-to-r4.patch new file mode 100644 index 0000000000..b21a4a72da --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0070-build.conf-change-to-r4.patch @@ -0,0 +1,25 @@ +From 0df363d725b08ae1b2d848415ce2384da6556d20 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sat, 21 Jun 2025 15:00:03 +0200 +Subject: [PATCH 70/84] build.conf: change to r4 + +--- + build.conf | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/build.conf b/build.conf +index c6521172e2da..0dc98280f6fa 100644 +--- a/build.conf ++++ b/build.conf +@@ -13,7 +13,7 @@ board=bpi-r2 + #board=bpi-r64 + #board=bpi-r2pro + #board=bpi-r3 +-#board=bpi-r4 ++board=bpi-r4 + + #r64 with rtl8367 + #boardversion=v0.1 +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0071-defconfig-r4-disable-STRICT_DEVMEM-to-allow-register.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0071-defconfig-r4-disable-STRICT_DEVMEM-to-allow-register.patch new file mode 100644 index 0000000000..01108d5f23 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0071-defconfig-r4-disable-STRICT_DEVMEM-to-allow-register.patch @@ -0,0 +1,22 @@ +From cc587f5c5de71d50be7d030529e381e1f7c5028a Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Thu, 12 Jun 2025 20:38:59 +0200 +Subject: [PATCH 71/84] defconfig: r4: disable STRICT_DEVMEM to allow + register-reads + +--- + arch/arm64/configs/mt7988a_bpi-r4_defconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm64/configs/mt7988a_bpi-r4_defconfig b/arch/arm64/configs/mt7988a_bpi-r4_defconfig +index 29bc60ce564f..8447280fcd8b 100644 +--- a/arch/arm64/configs/mt7988a_bpi-r4_defconfig ++++ b/arch/arm64/configs/mt7988a_bpi-r4_defconfig +@@ -1308,3 +1308,4 @@ CONFIG_MEDIATEK_2P5GE_PHY=m + #CONFIG_FB_MODE_HELPERS=y + #CONFIG_DRM_PANEL_MIPI_DBI=m + #CONFIG_BACKLIGHT_PWM=m ++CONFIG_STRICT_DEVMEM=n +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0072-net-ethernet-mtk_eth_soc-add-register-definitions-fo.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0072-net-ethernet-mtk_eth_soc-add-register-definitions-fo.patch new file mode 100644 index 0000000000..82ae42ee68 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0072-net-ethernet-mtk_eth_soc-add-register-definitions-fo.patch @@ -0,0 +1,125 @@ +From 3dd0307c7129a0b1cc7616eec7500d12f1955f2c Mon Sep 17 00:00:00 2001 +From: Mason Chang +Date: Tue, 18 Mar 2025 14:09:26 +0800 +Subject: [PATCH 72/84] net: ethernet: mtk_eth_soc: add register definitions + for rss and lro + +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 25 +++++++++++++++- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 32 +++++++++++++++------ + 2 files changed, 47 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index e5f0b9220aa1..98d700c55d73 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -52,13 +52,18 @@ static const struct mtk_reg_map mtk_reg_map = { + .rx_ptr = 0x0900, + .rx_cnt_cfg = 0x0904, + .pcrx_ptr = 0x0908, ++ .lro_ctrl_dw0 = 0x0980, + .glo_cfg = 0x0a04, + .rst_idx = 0x0a08, + .delay_irq = 0x0a0c, + .irq_status = 0x0a20, + .irq_mask = 0x0a28, + .adma_rx_dbg0 = 0x0a38, +- .int_grp = 0x0a50, ++ .lro_alt_score_delta = 0x0a4c, ++ .int_grp = 0x0a50, ++ .lro_rx1_dly_int = 0x0a70, ++ .lro_ring_dip_dw0 = 0x0b04, ++ .lro_ring_ctrl_dw1 = 0x0b28, + }, + .qdma = { + .qtx_cfg = 0x1800, +@@ -115,6 +120,7 @@ static const struct mtk_reg_map mt7986_reg_map = { + .tx_irq_mask = 0x461c, + .tx_irq_status = 0x4618, + .pdma = { ++ .rss_glo_cfg = 0x2800, + .rx_ptr = 0x4100, + .rx_cnt_cfg = 0x4104, + .pcrx_ptr = 0x4108, +@@ -125,6 +131,12 @@ static const struct mtk_reg_map mt7986_reg_map = { + .irq_mask = 0x4228, + .adma_rx_dbg0 = 0x4238, + .int_grp = 0x4250, ++ .int_grp3 = 0x422c, ++ .lro_ctrl_dw0 = 0x4180, ++ .lro_alt_score_delta = 0x424c, ++ .lro_rx1_dly_int = 0x4270, ++ .lro_ring_dip_dw0 = 0x4304, ++ .lro_ring_ctrl_dw1 = 0x4328, + }, + .qdma = { + .qtx_cfg = 0x4400, +@@ -172,10 +184,21 @@ static const struct mtk_reg_map mt7988_reg_map = { + .glo_cfg = 0x6a04, + .rst_idx = 0x6a08, + .delay_irq = 0x6a0c, ++ .rx_cfg = 0x6a10, + .irq_status = 0x6a20, + .irq_mask = 0x6a28, + .adma_rx_dbg0 = 0x6a38, + .int_grp = 0x6a50, ++ .int_grp3 = 0x6a58, ++ .tx_delay_irq = 0x6ab0, ++ .rx_delay_irq = 0x6ac0, ++ .lro_ctrl_dw0 = 0x6c08, ++ .lro_alt_score_delta = 0x6c1c, ++ .lro_ring_dip_dw0 = 0x6c14, ++ .lro_ring_ctrl_dw1 = 0x6c38, ++ .lro_alt_dbg = 0x6c40, ++ .lro_alt_dbg_data = 0x6c44, ++ .rss_glo_cfg = 0x7000, + }, + .qdma = { + .qtx_cfg = 0x4400, +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +index 91b2375f9405..eb2328596c8b 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -1189,16 +1189,30 @@ struct mtk_reg_map { + u32 tx_irq_mask; + u32 tx_irq_status; + struct { +- u32 rx_ptr; /* rx base pointer */ +- u32 rx_cnt_cfg; /* rx max count configuration */ +- u32 pcrx_ptr; /* rx cpu pointer */ +- u32 glo_cfg; /* global configuration */ +- u32 rst_idx; /* reset index */ +- u32 delay_irq; /* delay interrupt */ +- u32 irq_status; /* interrupt status */ +- u32 irq_mask; /* interrupt mask */ ++ u32 rx_ptr; /* rx base pointer */ ++ u32 rx_cnt_cfg; /* rx max count configuration */ ++ u32 pcrx_ptr; /* rx cpu pointer */ ++ u32 pdrx_ptr; /* rx dma pointer */ ++ u32 glo_cfg; /* global configuration */ ++ u32 rst_idx; /* reset index */ ++ u32 rx_cfg; /* rx dma configuration */ ++ u32 delay_irq; /* delay interrupt */ ++ u32 irq_status; /* interrupt status */ ++ u32 irq_mask; /* interrupt mask */ + u32 adma_rx_dbg0; +- u32 int_grp; ++ u32 int_grp; /* interrupt group1 */ ++ u32 int_grp3; /* interrupt group3 */ ++ u32 tx_delay_irq; /* tx delay interrupt */ ++ u32 rx_delay_irq; /* rx delay interrupt */ ++ u32 lro_ctrl_dw0; /* lro ctrl dword0 */ ++ u32 lro_alt_score_delta; /* lro auto-learn score delta */ ++ u32 lro_rx1_dly_int; /* lro rx ring1 delay interrupt */ ++ u32 lro_ring_dip_dw0; /* lro ring dip dword0 */ ++ u32 lro_ring_ctrl_dw1; /* lro ring ctrl dword1 */ ++ u32 lro_alt_dbg; /* lro auto-learn debug */ ++ u32 lro_alt_dbg_data; /* lro auto-learn debug data */ ++ u32 rss_glo_cfg; /* rss global configuration */ ++ + } pdma; + struct { + u32 qtx_cfg; /* tx queue configuration */ +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0073-net-ethernet-mtk_eth_soc-add-rss-support.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0073-net-ethernet-mtk_eth_soc-add-rss-support.patch new file mode 100644 index 0000000000..f52635836a --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0073-net-ethernet-mtk_eth_soc-add-rss-support.patch @@ -0,0 +1,1300 @@ +From 75b7467317d1b9b3f7d92d8940182407ceb58fa5 Mon Sep 17 00:00:00 2001 +From: Mason Chang +Date: Wed, 19 Mar 2025 11:20:39 +0800 +Subject: [PATCH 73/84] net: ethernet: mtk_eth_soc: add rss support + +Add RSS support. + +We can adjust SMP affinity with the following command: +echo [CPU bitmap num] > /proc/irq/[virtual IRQ ID]/smp_affinity, +with interrupts evenly assigned to 4 CPUs, we were able to measure +an RX throughput of 7.3Gbps using iperf3 on the MT7988. Further +optimizations will be carried out in the future. + +The experimental command is as follows: +PC: iperf3 -c [IP] -P 10 +DUT: iperf3 -s + +The entire indirection table can be imagined as 128 buckets, we +can use the ethtool command to mark which RX ring we want to send +the packets in these buckets to. + +Show RSS RX ring parameters in indirection table and RSS hash key: +ethtool -x [interface] +Change RSS RX rings weight under uniform distribution: +ethtool --set-rxfh-indir [interface] equal [ring num] +Change RSS RX rings weight under non-uniform distribution: +ethtool --set-rxfh-indir [interface] weight [ring0 weight] +[ring1 weight] [ring2 weight] [ring3 weight] + +Signed-off-by: Mason Chang +Signed-off-by: Frank Wunderlich +--- +based on mtk-feed: +https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/refs/heads/master/autobuild/unified/filogic/24.10/files/target/linux/mediatek/patches-6.6/999-2710-net-ethernet-mtk_eth_soc-add-rss-support.patch + +changes not yet: +- dropped MTK_PDMA_INT | MTK_RSS from mt798[16] capability +- fix mtk_{get,set}_rxfh callback header +- add missing mtk_mac_assign_address +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 536 +++++++++++++++----- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 96 +++- + 2 files changed, 495 insertions(+), 137 deletions(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index 98d700c55d73..18895e307824 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -1308,6 +1308,7 @@ static bool mtk_rx_get_desc(struct mtk_eth *eth, struct mtk_rx_dma_v2 *rxd, + if (mtk_is_netsys_v3_or_greater(eth)) { + rxd->rxd5 = READ_ONCE(dma_rxd->rxd5); + rxd->rxd6 = READ_ONCE(dma_rxd->rxd6); ++ rxd->rxd7 = READ_ONCE(dma_rxd->rxd7); + } + + return true; +@@ -1875,47 +1876,9 @@ static netdev_tx_t mtk_start_xmit(struct sk_buff *skb, struct net_device *dev) + return NETDEV_TX_OK; + } + +-static struct mtk_rx_ring *mtk_get_rx_ring(struct mtk_eth *eth) ++static void mtk_update_rx_cpu_idx(struct mtk_eth *eth, struct mtk_rx_ring *ring) + { +- int i; +- struct mtk_rx_ring *ring; +- int idx; +- +- if (!eth->hwlro) +- return ð->rx_ring[0]; +- +- for (i = 0; i < MTK_MAX_RX_RING_NUM; i++) { +- struct mtk_rx_dma *rxd; +- +- ring = ð->rx_ring[i]; +- idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size); +- rxd = ring->dma + idx * eth->soc->rx.desc_size; +- if (rxd->rxd2 & RX_DMA_DONE) { +- ring->calc_idx_update = true; +- return ring; +- } +- } +- +- return NULL; +-} +- +-static void mtk_update_rx_cpu_idx(struct mtk_eth *eth) +-{ +- struct mtk_rx_ring *ring; +- int i; +- +- if (!eth->hwlro) { +- ring = ð->rx_ring[0]; +- mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg); +- } else { +- for (i = 0; i < MTK_MAX_RX_RING_NUM; i++) { +- ring = ð->rx_ring[i]; +- if (ring->calc_idx_update) { +- ring->calc_idx_update = false; +- mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg); +- } +- } +- } ++ mtk_w32(eth, ring->calc_idx, ring->crx_idx_reg); + } + + static bool mtk_page_pool_enabled(struct mtk_eth *eth) +@@ -1946,7 +1909,7 @@ static struct page_pool *mtk_create_page_pool(struct mtk_eth *eth, + return pp; + + err = __xdp_rxq_info_reg(xdp_q, eth->dummy_dev, id, +- eth->rx_napi.napi_id, PAGE_SIZE); ++ eth->rx_napi[id].napi.napi_id, PAGE_SIZE); + if (err < 0) + goto err_free_pp; + +@@ -2235,7 +2198,8 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, + struct mtk_eth *eth) + { + struct dim_sample dim_sample = {}; +- struct mtk_rx_ring *ring; ++ struct mtk_napi *rx_napi = container_of(napi, struct mtk_napi, napi); ++ struct mtk_rx_ring *ring = rx_napi->rx_ring; + bool xdp_flush = false; + int idx; + struct sk_buff *skb; +@@ -2246,16 +2210,15 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, + dma_addr_t dma_addr = DMA_MAPPING_ERROR; + int ppe_idx = 0; + ++ if (unlikely(!ring)) ++ goto rx_done; ++ + while (done < budget) { + unsigned int pktlen, *rxdcsum; + struct net_device *netdev; + u32 hash, reason; + int mac = 0; + +- ring = mtk_get_rx_ring(eth); +- if (unlikely(!ring)) +- goto rx_done; +- + idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size); + rxd = ring->dma + idx * eth->soc->rx.desc_size; + data = ring->data[idx]; +@@ -2447,7 +2410,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, + * we continue + */ + wmb(); +- mtk_update_rx_cpu_idx(eth); ++ mtk_update_rx_cpu_idx(eth, ring); + } + + eth->rx_packets += done; +@@ -2657,7 +2620,9 @@ static int mtk_napi_tx(struct napi_struct *napi, int budget) + + static int mtk_napi_rx(struct napi_struct *napi, int budget) + { +- struct mtk_eth *eth = container_of(napi, struct mtk_eth, rx_napi); ++ struct mtk_napi *rx_napi = container_of(napi, struct mtk_napi, napi); ++ struct mtk_eth *eth = rx_napi->eth; ++ struct mtk_rx_ring *ring = rx_napi->rx_ring; + const struct mtk_reg_map *reg_map = eth->soc->reg_map; + int rx_done_total = 0; + +@@ -2666,7 +2631,7 @@ static int mtk_napi_rx(struct napi_struct *napi, int budget) + do { + int rx_done; + +- mtk_w32(eth, eth->soc->rx.irq_done_mask, ++ mtk_w32(eth, MTK_RX_DONE_INT(ring->ring_no), + reg_map->pdma.irq_status); + rx_done = mtk_poll_rx(napi, budget - rx_done_total, eth); + rx_done_total += rx_done; +@@ -2682,10 +2647,10 @@ static int mtk_napi_rx(struct napi_struct *napi, int budget) + return budget; + + } while (mtk_r32(eth, reg_map->pdma.irq_status) & +- eth->soc->rx.irq_done_mask); ++ MTK_RX_DONE_INT(ring->ring_no)); + + if (napi_complete_done(napi, rx_done_total)) +- mtk_rx_irq_enable(eth, eth->soc->rx.irq_done_mask); ++ mtk_rx_irq_enable(eth, MTK_RX_DONE_INT(ring->ring_no)); + + return rx_done_total; + } +@@ -2931,6 +2896,7 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag) + else + ring->crx_idx_reg = reg_map->pdma.pcrx_ptr + + ring_no * MTK_QRX_OFFSET; ++ ring->ring_no = ring_no; + /* make sure that all changes to the dma ring are flushed before we + * continue + */ +@@ -2999,6 +2965,7 @@ static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, bool in_ + + static int mtk_hwlro_rx_init(struct mtk_eth *eth) + { ++ const struct mtk_reg_map *reg_map = eth->soc->reg_map; + int i; + u32 ring_ctrl_dw1 = 0, ring_ctrl_dw2 = 0, ring_ctrl_dw3 = 0; + u32 lro_ctrl_dw0 = 0, lro_ctrl_dw3 = 0; +@@ -3059,6 +3026,7 @@ static int mtk_hwlro_rx_init(struct mtk_eth *eth) + + static void mtk_hwlro_rx_uninit(struct mtk_eth *eth) + { ++ const struct mtk_reg_map *reg_map = eth->soc->reg_map; + int i; + u32 val; + +@@ -3085,6 +3053,7 @@ static void mtk_hwlro_rx_uninit(struct mtk_eth *eth) + + static void mtk_hwlro_val_ipaddr(struct mtk_eth *eth, int idx, __be32 ip) + { ++ const struct mtk_reg_map *reg_map = eth->soc->reg_map; + u32 reg_val; + + reg_val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(idx)); +@@ -3100,6 +3069,7 @@ static void mtk_hwlro_val_ipaddr(struct mtk_eth *eth, int idx, __be32 ip) + + static void mtk_hwlro_inval_ipaddr(struct mtk_eth *eth, int idx) + { ++ const struct mtk_reg_map *reg_map = eth->soc->reg_map; + u32 reg_val; + + reg_val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(idx)); +@@ -3235,6 +3205,111 @@ static int mtk_hwlro_get_fdir_all(struct net_device *dev, + return 0; + } + ++static u32 mtk_rss_indr_table(struct mtk_rss_params *rss_params, int index) ++{ ++ u32 val = 0; ++ int i; ++ ++ for (i = 16 * index; i < 16 * index + 16; i++) ++ val |= (rss_params->indirection_table[i] << (2 * (i % 16))); ++ ++ return val; ++} ++ ++static int mtk_rss_init(struct mtk_eth *eth) ++{ ++ const struct mtk_soc_data *soc = eth->soc; ++ const struct mtk_reg_map *reg_map = eth->soc->reg_map; ++ struct mtk_rss_params *rss_params = ð->rss_params; ++ static u8 hash_key[MTK_RSS_HASH_KEYSIZE] = { ++ 0xfa, 0x01, 0xac, 0xbe, 0x3b, 0xb7, 0x42, 0x6a, ++ 0x0c, 0xf2, 0x30, 0x80, 0xa3, 0x2d, 0xcb, 0x77, ++ 0xb4, 0x30, 0x7b, 0xae, 0xcb, 0x2b, 0xca, 0xd0, ++ 0xb0, 0x8f, 0xa3, 0x43, 0x3d, 0x25, 0x67, 0x41, ++ 0xc2, 0x0e, 0x5b, 0x25, 0xda, 0x56, 0x5a, 0x6d}; ++ u32 val; ++ int i; ++ ++ memcpy(rss_params->hash_key, hash_key, MTK_RSS_HASH_KEYSIZE); ++ ++ for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE; i++) ++ rss_params->indirection_table[i] = i % eth->soc->rss_num; ++ ++ if (soc->rx.desc_size == sizeof(struct mtk_rx_dma)) { ++ /* Set RSS rings to PSE modes */ ++ for (i = 1; i <= MTK_HW_LRO_RING_NUM; i++) { ++ val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(i)); ++ val |= MTK_RING_PSE_MODE; ++ mtk_w32(eth, val, MTK_LRO_CTRL_DW2_CFG(i)); ++ } ++ ++ /* Enable non-lro multiple rx */ ++ val = mtk_r32(eth, reg_map->pdma.lro_ctrl_dw0); ++ val |= MTK_NON_LRO_MULTI_EN; ++ mtk_w32(eth, val, reg_map->pdma.lro_ctrl_dw0); ++ ++ /* Enable RSS dly int supoort */ ++ val |= MTK_LRO_DLY_INT_EN; ++ mtk_w32(eth, val, reg_map->pdma.lro_ctrl_dw0); ++ } ++ ++ /* Hash Type */ ++ val = mtk_r32(eth, reg_map->pdma.rss_glo_cfg); ++ val |= MTK_RSS_IPV4_STATIC_HASH; ++ val |= MTK_RSS_IPV6_STATIC_HASH; ++ mtk_w32(eth, val, reg_map->pdma.rss_glo_cfg); ++ ++ /* Hash Key */ ++ for (i = 0; i < MTK_RSS_HASH_KEYSIZE / sizeof(u32); i++) ++ mtk_w32(eth, rss_params->hash_key[i], MTK_RSS_HASH_KEY_DW(i)); ++ ++ /* Select the size of indirection table */ ++ for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE / 16; i++) ++ mtk_w32(eth, mtk_rss_indr_table(rss_params, i), ++ MTK_RSS_INDR_TABLE_DW(i)); ++ ++ /* Pause */ ++ val |= MTK_RSS_CFG_REQ; ++ mtk_w32(eth, val, reg_map->pdma.rss_glo_cfg); ++ ++ /* Enable RSS */ ++ val |= MTK_RSS_EN; ++ mtk_w32(eth, val, reg_map->pdma.rss_glo_cfg); ++ ++ /* Release pause */ ++ val &= ~(MTK_RSS_CFG_REQ); ++ mtk_w32(eth, val, reg_map->pdma.rss_glo_cfg); ++ ++ /* Set perRSS GRP INT */ ++ mtk_m32(eth, MTK_RX_DONE_INT(MTK_RSS_RING(1)), ++ MTK_RX_DONE_INT(MTK_RSS_RING(1)), reg_map->pdma.int_grp); ++ mtk_m32(eth, MTK_RX_DONE_INT(MTK_RSS_RING(2)), ++ MTK_RX_DONE_INT(MTK_RSS_RING(2)), reg_map->pdma.int_grp + 0x4); ++ mtk_m32(eth, MTK_RX_DONE_INT(MTK_RSS_RING(3)), ++ MTK_RX_DONE_INT(MTK_RSS_RING(3)), reg_map->pdma.int_grp3); ++ ++ return 0; ++} ++ ++static void mtk_rss_uninit(struct mtk_eth *eth) ++{ ++ const struct mtk_reg_map *reg_map = eth->soc->reg_map; ++ u32 val; ++ ++ /* Pause */ ++ val = mtk_r32(eth, reg_map->pdma.rss_glo_cfg); ++ val |= MTK_RSS_CFG_REQ; ++ mtk_w32(eth, val, reg_map->pdma.rss_glo_cfg); ++ ++ /* Disable RSS */ ++ val &= ~(MTK_RSS_EN); ++ mtk_w32(eth, val, reg_map->pdma.rss_glo_cfg); ++ ++ /* Release pause */ ++ val &= ~(MTK_RSS_CFG_REQ); ++ mtk_w32(eth, val, reg_map->pdma.rss_glo_cfg); ++} ++ + static netdev_features_t mtk_fix_features(struct net_device *dev, + netdev_features_t features) + { +@@ -3325,6 +3400,17 @@ static int mtk_dma_init(struct mtk_eth *eth) + return err; + } + ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) { ++ for (i = 1; i < MTK_RX_RSS_NUM; i++) { ++ err = mtk_rx_alloc(eth, MTK_RSS_RING(i), MTK_RX_FLAGS_NORMAL); ++ if (err) ++ return err; ++ } ++ err = mtk_rss_init(eth); ++ if (err) ++ return err; ++ } ++ + if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) { + /* Enable random early drop and set drop threshold + * automatically +@@ -3371,6 +3457,12 @@ static void mtk_dma_free(struct mtk_eth *eth) + mtk_rx_clean(eth, ð->rx_ring[i], false); + } + ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) { ++ mtk_rss_uninit(eth); ++ for (i = 1; i < MTK_RX_RSS_NUM; i++) ++ mtk_rx_clean(eth, ð->rx_ring[MTK_RSS_RING(i)], true); ++ } ++ + for (i = 0; i < DIV_ROUND_UP(soc->tx.fq_dma_size, MTK_FQ_DMA_LENGTH); i++) { + kfree(eth->scratch_head[i]); + eth->scratch_head[i] = NULL; +@@ -3403,23 +3495,23 @@ static void mtk_tx_timeout(struct net_device *dev, unsigned int txqueue) + schedule_work(ð->pending_work); + } + +-static int mtk_get_irqs(struct platform_device *pdev, struct mtk_eth *eth) ++static int mtk_get_irqs_fe(struct platform_device *pdev, struct mtk_eth *eth) + { + int i; + + /* future SoCs beginning with MT7988 should use named IRQs in dts */ +- eth->irq[MTK_FE_IRQ_TX] = platform_get_irq_byname_optional(pdev, "fe1"); +- eth->irq[MTK_FE_IRQ_RX] = platform_get_irq_byname_optional(pdev, "fe2"); +- if (eth->irq[MTK_FE_IRQ_TX] >= 0 && eth->irq[MTK_FE_IRQ_RX] >= 0) ++ eth->irq_fe[MTK_FE_IRQ_TX] = platform_get_irq_byname_optional(pdev, "fe1"); ++ eth->irq_fe[MTK_FE_IRQ_RX] = platform_get_irq_byname_optional(pdev, "fe2"); ++ if (eth->irq_fe[MTK_FE_IRQ_TX] >= 0 && eth->irq_fe[MTK_FE_IRQ_RX] >= 0) + return 0; + + /* only use legacy mode if platform_get_irq_byname_optional returned -ENXIO */ +- if (eth->irq[MTK_FE_IRQ_TX] != -ENXIO) +- return dev_err_probe(&pdev->dev, eth->irq[MTK_FE_IRQ_TX], ++ if (eth->irq_fe[MTK_FE_IRQ_TX] != -ENXIO) ++ return dev_err_probe(&pdev->dev, eth->irq_fe[MTK_FE_IRQ_TX], + "Error requesting FE TX IRQ\n"); + +- if (eth->irq[MTK_FE_IRQ_RX] != -ENXIO) +- return dev_err_probe(&pdev->dev, eth->irq[MTK_FE_IRQ_RX], ++ if (eth->irq_fe[MTK_FE_IRQ_RX] != -ENXIO) ++ return dev_err_probe(&pdev->dev, eth->irq_fe[MTK_FE_IRQ_RX], + "Error requesting FE RX IRQ\n"); + + if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) +@@ -3434,14 +3526,14 @@ static int mtk_get_irqs(struct platform_device *pdev, struct mtk_eth *eth) + for (i = 0; i < MTK_FE_IRQ_NUM; i++) { + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) { + if (i == MTK_FE_IRQ_SHARED) +- eth->irq[MTK_FE_IRQ_SHARED] = platform_get_irq(pdev, i); ++ eth->irq_fe[MTK_FE_IRQ_SHARED] = platform_get_irq(pdev, i); + else +- eth->irq[i] = eth->irq[MTK_FE_IRQ_SHARED]; ++ eth->irq_fe[i] = eth->irq_fe[MTK_FE_IRQ_SHARED]; + } else { +- eth->irq[i] = platform_get_irq(pdev, i + 1); ++ eth->irq_fe[i] = platform_get_irq(pdev, i + 1); + } + +- if (eth->irq[i] < 0) { ++ if (eth->irq_fe[i] < 0) { + dev_err(&pdev->dev, "no IRQ%d resource found\n", i); + return -ENXIO; + } +@@ -3450,14 +3542,37 @@ static int mtk_get_irqs(struct platform_device *pdev, struct mtk_eth *eth) + return 0; + } + +-static irqreturn_t mtk_handle_irq_rx(int irq, void *_eth) ++static int mtk_get_irqs_pdma(struct platform_device *pdev, struct mtk_eth *eth) + { +- struct mtk_eth *eth = _eth; ++ char *rxring = "pdma0"; ++ int i; ++ ++ for (i = 0; i < MTK_PDMA_IRQ_NUM; i++) { ++ rxring[4] = '0' + i; ++ eth->irq_pdma[i] = platform_get_irq_byname(pdev, rxring); ++ if (eth->irq_pdma[i] < 0) ++ return eth->irq_pdma[i]; ++ } ++ ++ return 0; ++} ++ ++static irqreturn_t mtk_handle_irq_rx(int irq, void *priv) ++{ ++ struct mtk_napi *rx_napi = priv; ++ struct mtk_eth *eth = rx_napi->eth; ++ struct mtk_rx_ring *ring = rx_napi->rx_ring; + + eth->rx_events++; +- if (likely(napi_schedule_prep(ð->rx_napi))) { +- mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask); +- __napi_schedule(ð->rx_napi); ++ if (unlikely(!(mtk_r32(eth, eth->soc->reg_map->pdma.irq_status) & ++ mtk_r32(eth, eth->soc->reg_map->pdma.irq_mask) & ++ MTK_RX_DONE_INT(ring->ring_no)))) ++ return IRQ_NONE; ++ ++ ++ if (likely(napi_schedule_prep(&rx_napi->napi))) { ++ mtk_rx_irq_disable(eth, MTK_RX_DONE_INT(ring->ring_no)); ++ __napi_schedule(&rx_napi->napi); + } + + return IRQ_HANDLED; +@@ -3482,10 +3597,10 @@ static irqreturn_t mtk_handle_irq(int irq, void *_eth) + const struct mtk_reg_map *reg_map = eth->soc->reg_map; + + if (mtk_r32(eth, reg_map->pdma.irq_mask) & +- eth->soc->rx.irq_done_mask) { ++ MTK_RX_DONE_INT(0)) { + if (mtk_r32(eth, reg_map->pdma.irq_status) & +- eth->soc->rx.irq_done_mask) +- mtk_handle_irq_rx(irq, _eth); ++ MTK_RX_DONE_INT(0)) ++ mtk_handle_irq_rx(irq, ð->rx_napi[0]); + } + if (mtk_r32(eth, reg_map->tx_irq_mask) & MTK_TX_DONE_INT) { + if (mtk_r32(eth, reg_map->tx_irq_status) & MTK_TX_DONE_INT) +@@ -3502,10 +3617,10 @@ static void mtk_poll_controller(struct net_device *dev) + struct mtk_eth *eth = mac->hw; + + mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask); +- mtk_handle_irq_rx(eth->irq[MTK_FE_IRQ_RX], dev); ++ mtk_rx_irq_disable(eth, MTK_RX_DONE_INT(0)); ++ mtk_handle_irq_rx(eth->irq_fe[MTK_FE_IRQ_RX], ð->rx_napi[0]); + mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_enable(eth, eth->soc->rx.irq_done_mask); ++ mtk_rx_irq_enable(eth, MTK_RX_DONE_INT(0)); + } + #endif + +@@ -3677,9 +3792,17 @@ static int mtk_open(struct net_device *dev) + } + + napi_enable(ð->tx_napi); +- napi_enable(ð->rx_napi); ++ napi_enable(ð->rx_napi[0].napi); + mtk_tx_irq_enable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_enable(eth, soc->rx.irq_done_mask); ++ mtk_rx_irq_enable(eth, MTK_RX_DONE_INT(0)); ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) { ++ for (i = 1; i < MTK_RX_RSS_NUM; i++) { ++ napi_enable(ð->rx_napi[MTK_RSS_RING(i)].napi); ++ mtk_rx_irq_enable(eth, MTK_RX_DONE_INT(MTK_RSS_RING(i))); ++ } ++ } ++ + refcount_set(ð->dma_refcnt, 1); + } else { + refcount_inc(ð->dma_refcnt); +@@ -3764,9 +3887,16 @@ static int mtk_stop(struct net_device *dev) + mtk_gdm_config(eth, i, MTK_GDMA_DROP_ALL); + + mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); +- mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask); ++ mtk_rx_irq_disable(eth, MTK_RX_DONE_INT(0)); + napi_disable(ð->tx_napi); +- napi_disable(ð->rx_napi); ++ napi_disable(ð->rx_napi[0].napi); ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) { ++ for (i = 1; i < MTK_RX_RSS_NUM; i++) { ++ mtk_rx_irq_disable(eth, MTK_RX_DONE_INT(MTK_RSS_RING(i))); ++ napi_disable(ð->rx_napi[MTK_RSS_RING(i)].napi); ++ } ++ } + + cancel_work_sync(ð->rx_dim.work); + cancel_work_sync(ð->tx_dim.work); +@@ -3877,9 +4007,7 @@ static void mtk_dim_rx(struct work_struct *work) + dim->profile_ix); + spin_lock_bh(ð->dim_lock); + +- val = mtk_r32(eth, reg_map->pdma.delay_irq); +- val &= MTK_PDMA_DELAY_TX_MASK; +- val |= MTK_PDMA_DELAY_RX_EN; ++ val = MTK_PDMA_DELAY_RX_EN; + + cur = min_t(u32, DIV_ROUND_UP(cur_profile.usec, 20), MTK_PDMA_DELAY_PTIME_MASK); + val |= cur << MTK_PDMA_DELAY_RX_PTIME_SHIFT; +@@ -3887,9 +4015,19 @@ static void mtk_dim_rx(struct work_struct *work) + cur = min_t(u32, cur_profile.pkts, MTK_PDMA_DELAY_PINT_MASK); + val |= cur << MTK_PDMA_DELAY_RX_PINT_SHIFT; + +- mtk_w32(eth, val, reg_map->pdma.delay_irq); + if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) +- mtk_w32(eth, val, reg_map->qdma.delay_irq); ++ mtk_m32(eth, MTK_PDMA_DELAY_TX_MASK, ++ val << MTK_PDMA_DELAY_TX_PTIME_SHIFT, reg_map->qdma.delay_irq); ++ ++ if (eth->soc->rx.desc_size == sizeof(struct mtk_rx_dma)) { ++ mtk_m32(eth, MTK_PDMA_DELAY_RX_MASK, val, reg_map->pdma.delay_irq); ++ mtk_w32(eth, val, reg_map->pdma.lro_rx1_dly_int); ++ mtk_w32(eth, val, reg_map->pdma.lro_rx1_dly_int + 0x4); ++ mtk_w32(eth, val, reg_map->pdma.lro_rx1_dly_int + 0x8); ++ } else { ++ val = val | (val << MTK_PDMA_DELAY_RX_RING_SHIFT); ++ mtk_w32(eth, val, reg_map->pdma.rx_delay_irq); ++ } + + spin_unlock_bh(ð->dim_lock); + +@@ -3908,9 +4046,7 @@ static void mtk_dim_tx(struct work_struct *work) + dim->profile_ix); + spin_lock_bh(ð->dim_lock); + +- val = mtk_r32(eth, reg_map->pdma.delay_irq); +- val &= MTK_PDMA_DELAY_RX_MASK; +- val |= MTK_PDMA_DELAY_TX_EN; ++ val = MTK_PDMA_DELAY_TX_EN; + + cur = min_t(u32, DIV_ROUND_UP(cur_profile.usec, 20), MTK_PDMA_DELAY_PTIME_MASK); + val |= cur << MTK_PDMA_DELAY_TX_PTIME_SHIFT; +@@ -3918,9 +4054,16 @@ static void mtk_dim_tx(struct work_struct *work) + cur = min_t(u32, cur_profile.pkts, MTK_PDMA_DELAY_PINT_MASK); + val |= cur << MTK_PDMA_DELAY_TX_PINT_SHIFT; + +- mtk_w32(eth, val, reg_map->pdma.delay_irq); + if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA)) +- mtk_w32(eth, val, reg_map->qdma.delay_irq); ++ mtk_m32(eth, MTK_PDMA_DELAY_RX_MASK, ++ val >> MTK_PDMA_DELAY_TX_PTIME_SHIFT, reg_map->qdma.delay_irq); ++ ++ if (eth->soc->rx.desc_size == sizeof(struct mtk_rx_dma)) { ++ mtk_m32(eth, MTK_PDMA_DELAY_TX_MASK, val, reg_map->pdma.delay_irq); ++ } else { ++ mtk_w32(eth, val >> MTK_PDMA_DELAY_TX_PTIME_SHIFT, ++ reg_map->pdma.tx_delay_irq); ++ } + + spin_unlock_bh(ð->dim_lock); + +@@ -4183,6 +4326,25 @@ static void mtk_hw_reset_monitor_work(struct work_struct *work) + MTK_DMA_MONITOR_TIMEOUT); + } + ++static int mtk_napi_init(struct mtk_eth *eth) ++{ ++ struct mtk_napi *rx_napi = ð->rx_napi[0]; ++ int i; ++ ++ rx_napi->eth = eth; ++ rx_napi->rx_ring = ð->rx_ring[0]; ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) { ++ for (i = 1; i < MTK_RX_RSS_NUM; i++) { ++ rx_napi = ð->rx_napi[MTK_RSS_RING(i)]; ++ rx_napi->eth = eth; ++ rx_napi->rx_ring = ð->rx_ring[MTK_RSS_RING(i)]; ++ } ++ } ++ ++ return 0; ++} ++ + static int mtk_hw_init(struct mtk_eth *eth, bool reset) + { + u32 dma_mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA | +@@ -4272,12 +4434,12 @@ static int mtk_hw_init(struct mtk_eth *eth, bool reset) + */ + val = mtk_r32(eth, MTK_CDMQ_IG_CTRL); + mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL); +- if (mtk_is_netsys_v1(eth)) { +- val = mtk_r32(eth, MTK_CDMP_IG_CTRL); +- mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL); + ++ val = mtk_r32(eth, MTK_CDMP_IG_CTRL); ++ mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL); ++ ++ if (mtk_is_netsys_v1(eth)) + mtk_w32(eth, 1, MTK_CDMP_EG_CTRL); +- } + + /* set interrupt delays based on current Net DIM sample */ + mtk_dim_rx(ð->rx_dim.work); +@@ -4288,11 +4450,17 @@ static int mtk_hw_init(struct mtk_eth *eth, bool reset) + mtk_rx_irq_disable(eth, ~0); + + /* FE int grouping */ +- mtk_w32(eth, MTK_TX_DONE_INT, reg_map->pdma.int_grp); +- mtk_w32(eth, eth->soc->rx.irq_done_mask, reg_map->pdma.int_grp + 4); ++ + mtk_w32(eth, MTK_TX_DONE_INT, reg_map->qdma.int_grp); +- mtk_w32(eth, eth->soc->rx.irq_done_mask, reg_map->qdma.int_grp + 4); +- mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP); ++ mtk_w32(eth, MTK_RX_DONE_INT(0), reg_map->qdma.int_grp + 4); ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_PDMA_INT)) { ++ mtk_w32(eth, 0x210FFFF2, MTK_FE_INT_GRP); ++ } else { ++ mtk_w32(eth, MTK_TX_DONE_INT, reg_map->pdma.int_grp); ++ mtk_w32(eth, MTK_RX_DONE_INT(0), reg_map->pdma.int_grp + 4); ++ mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP); ++ } + + if (mtk_is_netsys_v3_or_greater(eth)) { + /* PSE dummy page mechanism */ +@@ -4730,6 +4898,8 @@ static void mtk_get_ethtool_stats(struct net_device *dev, + static int mtk_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, + u32 *rule_locs) + { ++ struct mtk_mac *mac = netdev_priv(dev); ++ struct mtk_eth *eth = mac->hw; + int ret = -EOPNOTSUPP; + + switch (cmd->cmd) { +@@ -4737,6 +4907,9 @@ static int mtk_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, + if (dev->hw_features & NETIF_F_LRO) { + cmd->data = MTK_MAX_RX_RING_NUM; + ret = 0; ++ } else if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) { ++ cmd->data = MTK_RX_RSS_NUM; ++ ret = 0; + } + break; + case ETHTOOL_GRXCLSRLCNT: +@@ -4811,6 +4984,72 @@ static int mtk_set_eee(struct net_device *dev, struct ethtool_keee *eee) + return phylink_ethtool_set_eee(mac->phylink, eee); + } + ++static u32 mtk_get_rxfh_key_size(struct net_device *dev) ++{ ++ return MTK_RSS_HASH_KEYSIZE; ++} ++ ++static u32 mtk_get_rxfh_indir_size(struct net_device *dev) ++{ ++ return MTK_RSS_MAX_INDIRECTION_TABLE; ++} ++ ++static int mtk_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, ++ u8 *hfunc) ++{ ++ struct mtk_mac *mac = netdev_priv(dev); ++ struct mtk_eth *eth = mac->hw; ++ struct mtk_rss_params *rss_params = ð->rss_params; ++ int i; ++ ++ if (hfunc) ++ *hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */ ++ ++ if (key) { ++ memcpy(key, rss_params->hash_key, ++ sizeof(rss_params->hash_key)); ++ } ++ ++ if (indir) { ++ for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE; i++) ++ indir[i] = rss_params->indirection_table[i]; ++ } ++ ++ return 0; ++} ++ ++static int mtk_set_rxfh(struct net_device *dev, const u32 *indir, ++ const u8 *key, const u8 hfunc) ++{ ++ struct mtk_mac *mac = netdev_priv(dev); ++ struct mtk_eth *eth = mac->hw; ++ struct mtk_rss_params *rss_params = ð->rss_params; ++ const struct mtk_reg_map *reg_map = eth->soc->reg_map; ++ int i; ++ ++ if (hfunc != ETH_RSS_HASH_NO_CHANGE && ++ hfunc != ETH_RSS_HASH_TOP) ++ return -EOPNOTSUPP; ++ ++ if (key) { ++ memcpy(rss_params->hash_key, key, ++ sizeof(rss_params->hash_key)); ++ for (i = 0; i < MTK_RSS_HASH_KEYSIZE / sizeof(u32); i++) ++ mtk_w32(eth, rss_params->hash_key[i], ++ MTK_RSS_HASH_KEY_DW(i)); ++ } ++ ++ if (indir) { ++ for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE; i++) ++ rss_params->indirection_table[i] = indir[i]; ++ for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE / 16; i++) ++ mtk_w32(eth, mtk_rss_indr_table(rss_params, i), ++ MTK_RSS_INDR_TABLE_DW(i)); ++ } ++ ++ return 0; ++} ++ + static u16 mtk_select_queue(struct net_device *dev, struct sk_buff *skb, + struct net_device *sb_dev) + { +@@ -4845,6 +5084,10 @@ static const struct ethtool_ops mtk_ethtool_ops = { + .set_rxnfc = mtk_set_rxnfc, + .get_eee = mtk_get_eee, + .set_eee = mtk_set_eee, ++ .get_rxfh_key_size = mtk_get_rxfh_key_size, ++ .get_rxfh_indir_size = mtk_get_rxfh_indir_size, ++ .get_rxfh = mtk_get_rxfh, ++ .set_rxfh = mtk_set_rxfh, + }; + + static const struct net_device_ops mtk_netdev_ops = { +@@ -5073,7 +5316,7 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) + eth->netdev[id]->features |= eth->soc->hw_features; + eth->netdev[id]->ethtool_ops = &mtk_ethtool_ops; + +- eth->netdev[id]->irq = eth->irq[MTK_FE_IRQ_SHARED]; ++ eth->netdev[id]->irq = eth->irq_fe[MTK_FE_IRQ_SHARED]; + eth->netdev[id]->dev.of_node = np; + + phylink = phylink_create(&mac->phylink_config, +@@ -5194,6 +5437,7 @@ static int mtk_probe(struct platform_device *pdev) + struct resource *res = NULL; + struct device_node *mac_np; + struct mtk_eth *eth; ++ char *irqname; + int err, i; + + eth = devm_kzalloc(&pdev->dev, sizeof(*eth), GFP_KERNEL); +@@ -5326,10 +5570,16 @@ static int mtk_probe(struct platform_device *pdev) + } + } + +- err = mtk_get_irqs(pdev, eth); ++ err = mtk_get_irqs_fe(pdev, eth); + if (err) + goto err_wed_exit; + ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_PDMA_INT)) { ++ err = mtk_get_irqs_pdma(pdev, eth); ++ if (err) ++ goto err_wed_exit; ++ } ++ + for (i = 0; i < ARRAY_SIZE(eth->clks); i++) { + eth->clks[i] = devm_clk_get(eth->dev, + mtk_clks_source_name[i]); +@@ -5372,23 +5622,56 @@ static int mtk_probe(struct platform_device *pdev) + } + } + ++ err = mtk_napi_init(eth); ++ if (err) ++ goto err_free_dev; ++ + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_INT)) { +- err = devm_request_irq(eth->dev, eth->irq[MTK_FE_IRQ_SHARED], ++ err = devm_request_irq(eth->dev, eth->irq_fe[MTK_FE_IRQ_SHARED], + mtk_handle_irq, 0, + dev_name(eth->dev), eth); + } else { +- err = devm_request_irq(eth->dev, eth->irq[MTK_FE_IRQ_TX], ++ irqname = devm_kasprintf(eth->dev, GFP_KERNEL, "%s TX", ++ dev_name(eth->dev)); ++ err = devm_request_irq(eth->dev, eth->irq_fe[MTK_FE_IRQ_TX], + mtk_handle_irq_tx, 0, +- dev_name(eth->dev), eth); ++ irqname, eth); + if (err) + goto err_free_dev; + +- err = devm_request_irq(eth->dev, eth->irq[MTK_FE_IRQ_RX], +- mtk_handle_irq_rx, 0, +- dev_name(eth->dev), eth); ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_PDMA_INT)) { ++ irqname = devm_kasprintf(eth->dev, GFP_KERNEL, "%s PDMA RX %d", ++ dev_name(eth->dev), 0); ++ err = devm_request_irq(eth->dev, eth->irq_pdma[0], ++ mtk_handle_irq_rx, IRQF_SHARED, ++ irqname, ð->rx_napi[0]); ++ if (err) ++ goto err_free_dev; ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) { ++ for (i = 1; i < MTK_RX_RSS_NUM; i++) { ++ irqname = devm_kasprintf(eth->dev, GFP_KERNEL, ++ "%s RSS RX %d", ++ dev_name(eth->dev), i); ++ err = devm_request_irq(eth->dev, ++ eth->irq_pdma[MTK_RSS_RING(i)], ++ mtk_handle_irq_rx, IRQF_SHARED, ++ irqname, ++ ð->rx_napi[MTK_RSS_RING(i)]); ++ if (err) ++ goto err_free_dev; ++ } ++ } ++ } else { ++ irqname = devm_kasprintf(eth->dev, GFP_KERNEL, "%s RX", ++ dev_name(eth->dev)); ++ err = devm_request_irq(eth->dev, eth->irq_fe[MTK_FE_IRQ_RX], ++ mtk_handle_irq_rx, 0, ++ irqname, ð->rx_napi[0]); ++ if (err) ++ goto err_free_dev; ++ } + } +- if (err) +- goto err_free_dev; + + /* No MT7628/88 support yet */ + if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) { +@@ -5429,7 +5712,7 @@ static int mtk_probe(struct platform_device *pdev) + } else + netif_info(eth, probe, eth->netdev[i], + "mediatek frame engine at 0x%08lx, irq %d\n", +- eth->netdev[i]->base_addr, eth->irq[MTK_FE_IRQ_SHARED]); ++ eth->netdev[i]->base_addr, eth->irq_fe[MTK_FE_IRQ_SHARED]); + } + + /* we run 2 devices on the same DMA ring so we need a dummy device +@@ -5442,7 +5725,13 @@ static int mtk_probe(struct platform_device *pdev) + goto err_unreg_netdev; + } + netif_napi_add(eth->dummy_dev, ð->tx_napi, mtk_napi_tx); +- netif_napi_add(eth->dummy_dev, ð->rx_napi, mtk_napi_rx); ++ netif_napi_add(eth->dummy_dev, ð->rx_napi[0].napi, mtk_napi_rx); ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) { ++ for (i = 1; i < MTK_RX_RSS_NUM; i++) ++ netif_napi_add(eth->dummy_dev, ð->rx_napi[MTK_RSS_RING(i)].napi, ++ mtk_napi_rx); ++ } + + platform_set_drvdata(pdev, eth); + schedule_delayed_work(ð->reset.monitor_work, +@@ -5486,7 +5775,12 @@ static void mtk_remove(struct platform_device *pdev) + mtk_hw_deinit(eth); + + netif_napi_del(ð->tx_napi); +- netif_napi_del(ð->rx_napi); ++ netif_napi_del(ð->rx_napi[0].napi); ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) { ++ for (i = 1; i < MTK_RX_RSS_NUM; i++) ++ netif_napi_del(ð->rx_napi[MTK_RSS_RING(i)].napi); ++ } + mtk_cleanup(eth); + free_netdev(eth->dummy_dev); + mtk_mdio_cleanup(eth); +@@ -5499,6 +5793,7 @@ static const struct mtk_soc_data mt2701_data = { + .required_clks = MT7623_CLKS_BITMAP, + .required_pctl = true, + .version = 1, ++ .rss_num = 0, + .tx = { + .desc_size = sizeof(struct mtk_tx_dma), + .dma_max_len = MTK_TX_DMA_BUF_LEN, +@@ -5508,7 +5803,6 @@ static const struct mtk_soc_data mt2701_data = { + }, + .rx = { + .desc_size = sizeof(struct mtk_rx_dma), +- .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID, + .dma_size = MTK_DMA_SIZE(2K), + .dma_max_len = MTK_TX_DMA_BUF_LEN, +@@ -5527,6 +5821,7 @@ static const struct mtk_soc_data mt7621_data = { + .ppe_num = 1, + .hash_offset = 2, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, ++ .rss_num = 0, + .tx = { + .desc_size = sizeof(struct mtk_tx_dma), + .dma_max_len = MTK_TX_DMA_BUF_LEN, +@@ -5536,7 +5831,6 @@ static const struct mtk_soc_data mt7621_data = { + }, + .rx = { + .desc_size = sizeof(struct mtk_rx_dma), +- .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID, + .dma_size = MTK_DMA_SIZE(2K), + .dma_max_len = MTK_TX_DMA_BUF_LEN, +@@ -5557,6 +5851,7 @@ static const struct mtk_soc_data mt7622_data = { + .hash_offset = 2, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, ++ .rss_num = 0, + .tx = { + .desc_size = sizeof(struct mtk_tx_dma), + .dma_max_len = MTK_TX_DMA_BUF_LEN, +@@ -5566,7 +5861,6 @@ static const struct mtk_soc_data mt7622_data = { + }, + .rx = { + .desc_size = sizeof(struct mtk_rx_dma), +- .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID, + .dma_size = MTK_DMA_SIZE(2K), + .dma_max_len = MTK_TX_DMA_BUF_LEN, +@@ -5586,6 +5880,7 @@ static const struct mtk_soc_data mt7623_data = { + .hash_offset = 2, + .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE, + .disable_pll_modes = true, ++ .rss_num = 0, + .tx = { + .desc_size = sizeof(struct mtk_tx_dma), + .dma_max_len = MTK_TX_DMA_BUF_LEN, +@@ -5595,7 +5890,6 @@ static const struct mtk_soc_data mt7623_data = { + }, + .rx = { + .desc_size = sizeof(struct mtk_rx_dma), +- .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID, + .dma_size = MTK_DMA_SIZE(2K), + .dma_max_len = MTK_TX_DMA_BUF_LEN, +@@ -5612,6 +5906,7 @@ static const struct mtk_soc_data mt7629_data = { + .required_pctl = false, + .has_accounting = true, + .version = 1, ++ .rss_num = 0, + .tx = { + .desc_size = sizeof(struct mtk_tx_dma), + .dma_max_len = MTK_TX_DMA_BUF_LEN, +@@ -5621,7 +5916,6 @@ static const struct mtk_soc_data mt7629_data = { + }, + .rx = { + .desc_size = sizeof(struct mtk_rx_dma), +- .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID, + .dma_size = MTK_DMA_SIZE(2K), + .dma_max_len = MTK_TX_DMA_BUF_LEN, +@@ -5642,16 +5936,16 @@ static const struct mtk_soc_data mt7981_data = { + .hash_offset = 4, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, ++ .rss_num = 4, + .tx = { + .desc_size = sizeof(struct mtk_tx_dma_v2), + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, +- .dma_size = MTK_DMA_SIZE(2K), ++ .dma_size = MTK_DMA_SIZE(4K), + .fq_dma_size = MTK_DMA_SIZE(2K), + }, + .rx = { + .desc_size = sizeof(struct mtk_rx_dma), +- .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, +@@ -5672,6 +5966,7 @@ static const struct mtk_soc_data mt7986_data = { + .hash_offset = 4, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE, ++ .rss_num = 4, + .tx = { + .desc_size = sizeof(struct mtk_tx_dma_v2), + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, +@@ -5681,7 +5976,6 @@ static const struct mtk_soc_data mt7986_data = { + }, + .rx = { + .desc_size = sizeof(struct mtk_rx_dma), +- .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, +@@ -5702,20 +5996,20 @@ static const struct mtk_soc_data mt7988_data = { + .hash_offset = 4, + .has_accounting = true, + .foe_entry_size = MTK_FOE_ENTRY_V3_SIZE, ++ .rss_num = 4, + .tx = { + .desc_size = sizeof(struct mtk_tx_dma_v2), + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, +- .dma_size = MTK_DMA_SIZE(2K), ++ .dma_size = MTK_DMA_SIZE(4K), + .fq_dma_size = MTK_DMA_SIZE(4K), + }, + .rx = { + .desc_size = sizeof(struct mtk_rx_dma_v2), +- .irq_done_mask = MTK_RX_DONE_INT_V2, + .dma_l4_valid = RX_DMA_L4_VALID_V2, + .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, + .dma_len_offset = 8, +- .dma_size = MTK_DMA_SIZE(2K), ++ .dma_size = MTK_DMA_SIZE(1K), + }, + }; + +@@ -5726,6 +6020,7 @@ static const struct mtk_soc_data rt5350_data = { + .required_clks = MT7628_CLKS_BITMAP, + .required_pctl = false, + .version = 1, ++ .rss_num = 0, + .tx = { + .desc_size = sizeof(struct mtk_tx_dma), + .dma_max_len = MTK_TX_DMA_BUF_LEN, +@@ -5734,7 +6029,6 @@ static const struct mtk_soc_data rt5350_data = { + }, + .rx = { + .desc_size = sizeof(struct mtk_rx_dma), +- .irq_done_mask = MTK_RX_DONE_INT, + .dma_l4_valid = RX_DMA_L4_VALID_PDMA, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +index eb2328596c8b..a163a04bb927 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -77,6 +77,8 @@ + #define MTK_HW_LRO_BW_THRE 3000 + #define MTK_HW_LRO_REPLACE_DELTA 1000 + #define MTK_HW_LRO_SDL_REMAIN_ROOM 1522 ++#define MTK_RSS_HASH_KEYSIZE 40 ++#define MTK_RSS_MAX_INDIRECTION_TABLE 128 + + /* Frame Engine Global Configuration */ + #define MTK_FE_GLO_CFG(x) (((x) == MTK_GMAC3_ID) ? 0x24 : 0x00) +@@ -98,6 +100,8 @@ + #define MTK_GDM1_AF BIT(28) + #define MTK_GDM2_AF BIT(29) + ++#define MTK_PDMA_IRQ_NUM (4) ++ + /* PDMA HW LRO Alter Flow Timer Register */ + #define MTK_PDMA_LRO_ALT_REFRESH_TIMER 0x1c + +@@ -180,7 +184,10 @@ + + /* PDMA HW LRO Control Registers */ + #define MTK_PDMA_LRO_CTRL_DW0 0x980 ++#define MTK_HW_LRO_RING_NUM (mtk_is_netsys_v3_or_greater(eth) ? 4 : 3) + #define MTK_LRO_EN BIT(0) ++#define MTK_NON_LRO_MULTI_EN BIT(2) ++#define MTK_LRO_DLY_INT_EN BIT(5) + #define MTK_L3_CKS_UPD_EN BIT(7) + #define MTK_L3_CKS_UPD_EN_V2 BIT(19) + #define MTK_LRO_ALT_PKT_CNT_MODE BIT(21) +@@ -199,6 +206,19 @@ + #define MTK_MULTI_EN BIT(10) + #define MTK_PDMA_SIZE_8DWORDS (1 << 4) + ++/* PDMA RSS Control Registers */ ++#define MTK_RX_NAPI_NUM (4) ++#define MTK_RX_RSS_NUM (eth->soc->rss_num) ++#define MTK_RSS_RING(x) (x) ++#define MTK_RSS_EN BIT(0) ++#define MTK_RSS_CFG_REQ BIT(2) ++#define MTK_RSS_IPV6_STATIC_HASH (0x7 << 8) ++#define MTK_RSS_IPV4_STATIC_HASH (0x7 << 12) ++#define MTK_RSS_HASH_KEY_DW(x) (reg_map->pdma.rss_glo_cfg + 0x20 + \ ++ ((x) * 0x4)) ++#define MTK_RSS_INDR_TABLE_DW(x) (reg_map->pdma.rss_glo_cfg + 0x50 + \ ++ ((x) * 0x4)) ++ + /* PDMA Global Configuration Register */ + #define MTK_PDMA_LRO_SDL 0x3000 + #define MTK_RX_CFG_SDL_OFFSET 16 +@@ -210,6 +230,7 @@ + /* PDMA Delay Interrupt Register */ + #define MTK_PDMA_DELAY_RX_MASK GENMASK(15, 0) + #define MTK_PDMA_DELAY_RX_EN BIT(15) ++#define MTK_PDMA_DELAY_RX_RING_SHIFT 16 + #define MTK_PDMA_DELAY_RX_PINT_SHIFT 8 + #define MTK_PDMA_DELAY_RX_PTIME_SHIFT 0 + +@@ -230,14 +251,12 @@ + #define MTK_RING_MYIP_VLD BIT(9) + + /* PDMA HW LRO Ring Control Registers */ +-#define MTK_LRO_RX_RING0_CTRL_DW1 0xb28 +-#define MTK_LRO_RX_RING0_CTRL_DW2 0xb2c +-#define MTK_LRO_RX_RING0_CTRL_DW3 0xb30 +-#define MTK_LRO_CTRL_DW1_CFG(x) (MTK_LRO_RX_RING0_CTRL_DW1 + (x * 0x40)) +-#define MTK_LRO_CTRL_DW2_CFG(x) (MTK_LRO_RX_RING0_CTRL_DW2 + (x * 0x40)) +-#define MTK_LRO_CTRL_DW3_CFG(x) (MTK_LRO_RX_RING0_CTRL_DW3 + (x * 0x40)) ++#define MTK_LRO_CTRL_DW1_CFG(x) (reg_map->pdma.lro_ring_ctrl_dw1 + (x * 0x40)) ++#define MTK_LRO_CTRL_DW2_CFG(x) (reg_map->pdma.lro_ring_ctrl_dw1 + 0x4 + (x * 0x40)) ++#define MTK_LRO_CTRL_DW3_CFG(x) (reg_map->pdma.lro_ring_ctrl_dw1 + 0x8 + (x * 0x40)) + #define MTK_RING_AGE_TIME_L ((MTK_HW_LRO_AGE_TIME & 0x3ff) << 22) + #define MTK_RING_AGE_TIME_H ((MTK_HW_LRO_AGE_TIME >> 10) & 0x3f) ++#define MTK_RING_PSE_MODE (1 << 6) + #define MTK_RING_AUTO_LERAN_MODE (3 << 6) + #define MTK_RING_VLD BIT(8) + #define MTK_RING_MAX_AGG_TIME ((MTK_HW_LRO_AGG_TIME & 0xffff) << 10) +@@ -291,7 +310,20 @@ + #define FC_THRES_MIN 0x4444 + + /* QDMA Interrupt Status Register */ +-#define MTK_RX_DONE_DLY BIT(30) ++#define MTK_RX_DONE_INT_V1(ring_no) \ ++ ( \ ++ (ring_no) ? \ ++ BIT(24 + (ring_no)) : \ ++ BIT(30) \ ++ ) ++ ++#define MTK_RX_DONE_INT_V2(ring_no) BIT(24 + (ring_no)) ++ ++#define MTK_RX_DONE_INT(ring_no) \ ++ (mtk_is_netsys_v3_or_greater(eth) ? \ ++ MTK_RX_DONE_INT_V2(ring_no) : \ ++ MTK_RX_DONE_INT_V1(ring_no)) ++ + #define MTK_TX_DONE_DLY BIT(28) + #define MTK_RX_DONE_INT3 BIT(19) + #define MTK_RX_DONE_INT2 BIT(18) +@@ -301,11 +333,8 @@ + #define MTK_TX_DONE_INT2 BIT(2) + #define MTK_TX_DONE_INT1 BIT(1) + #define MTK_TX_DONE_INT0 BIT(0) +-#define MTK_RX_DONE_INT MTK_RX_DONE_DLY + #define MTK_TX_DONE_INT MTK_TX_DONE_DLY + +-#define MTK_RX_DONE_INT_V2 BIT(14) +- + #define MTK_CDM_TXFIFO_RDY BIT(7) + + /* QDMA Interrupt grouping registers */ +@@ -959,6 +988,7 @@ struct mtk_tx_ring { + struct mtk_tx_dma *dma_pdma; /* For MT7628/88 PDMA handling */ + dma_addr_t phys_pdma; + int cpu_idx; ++ bool in_sram; + }; + + /* PDMA rx ring mode */ +@@ -984,13 +1014,38 @@ struct mtk_rx_ring { + u16 buf_size; + u16 dma_size; + bool calc_idx_update; ++ bool in_sram; + u16 calc_idx; + u32 crx_idx_reg; ++ u32 ring_no; + /* page_pool */ + struct page_pool *page_pool; + struct xdp_rxq_info xdp_q; + }; + ++/* struct mtk_rss_params - This is the structure holding parameters ++ for the RSS ring ++ * @hash_key The element is used to record the ++ secret key for the RSS ring ++ * indirection_table The element is used to record the ++ indirection table for the RSS ring ++ */ ++struct mtk_rss_params { ++ u32 hash_key[MTK_RSS_HASH_KEYSIZE / sizeof(u32)]; ++ u8 indirection_table[MTK_RSS_MAX_INDIRECTION_TABLE]; ++}; ++ ++/* struct mtk_napi - This is the structure holding NAPI-related information, ++ * and a mtk_napi struct is binding to one interrupt group ++ * @napi: The NAPI struct ++ * @rx_ring: Pointer to the memory holding info about the RX ring ++ */ ++struct mtk_napi { ++ struct napi_struct napi; ++ struct mtk_eth *eth; ++ struct mtk_rx_ring *rx_ring; ++}; ++ + enum mkt_eth_capabilities { + MTK_RGMII_BIT = 0, + MTK_TRGMII_BIT, +@@ -1003,7 +1058,9 @@ enum mkt_eth_capabilities { + MTK_INFRA_BIT, + MTK_SHARED_SGMII_BIT, + MTK_HWLRO_BIT, ++ MTK_RSS_BIT, + MTK_SHARED_INT_BIT, ++ MTK_PDMA_INT_BIT, + MTK_TRGMII_MT7621_CLK_BIT, + MTK_QDMA_BIT, + MTK_SOC_MT7628_BIT, +@@ -1050,7 +1107,9 @@ enum mkt_eth_capabilities { + #define MTK_INFRA BIT_ULL(MTK_INFRA_BIT) + #define MTK_SHARED_SGMII BIT_ULL(MTK_SHARED_SGMII_BIT) + #define MTK_HWLRO BIT_ULL(MTK_HWLRO_BIT) ++#define MTK_RSS BIT_ULL(MTK_RSS_BIT) + #define MTK_SHARED_INT BIT_ULL(MTK_SHARED_INT_BIT) ++#define MTK_PDMA_INT BIT_ULL(MTK_PDMA_INT_BIT) + #define MTK_TRGMII_MT7621_CLK BIT_ULL(MTK_TRGMII_MT7621_CLK_BIT) + #define MTK_QDMA BIT_ULL(MTK_QDMA_BIT) + #define MTK_SOC_MT7628 BIT_ULL(MTK_SOC_MT7628_BIT) +@@ -1160,18 +1219,19 @@ enum mkt_eth_capabilities { + #define MT7981_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \ + MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ + MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \ +- MTK_RSTCTRL_PPE1 | MTK_SRAM) ++ MTK_RSTCTRL_PPE1 | MTK_SRAM | MTK_PDMA_INT | MTK_RSS) + + #define MT7986_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \ + MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ +- MTK_RSTCTRL_PPE1 | MTK_SRAM) ++ MTK_RSTCTRL_PPE1 | MTK_SRAM | MTK_PDMA_INT | MTK_RSS) + + #define MT7988_CAPS (MTK_36BIT_DMA | MTK_GDM1_ESW | MTK_GMAC1_SGMII | \ + MTK_GMAC2_2P5GPHY | MTK_GMAC2_SGMII | MTK_GMAC2_USXGMII | \ + MTK_GMAC3_SGMII | MTK_GMAC3_USXGMII | \ + MTK_MUX_GMAC123_TO_GEPHY_SGMII | \ + MTK_MUX_GMAC123_TO_USXGMII | MTK_MUX_GMAC2_TO_2P5GPHY | \ +- MTK_QDMA | MTK_RSTCTRL_PPE1 | MTK_RSTCTRL_PPE2 | MTK_SRAM) ++ MTK_QDMA | MTK_SRAM | MTK_PDMA_INT | MTK_RSS | \ ++ MTK_RSTCTRL_PPE1 | MTK_RSTCTRL_PPE2) + + struct mtk_tx_dma_desc_info { + dma_addr_t addr; +@@ -1269,6 +1329,7 @@ struct mtk_reg_map { + struct mtk_soc_data { + const struct mtk_reg_map *reg_map; + u32 ana_rgc3; ++ u32 rss_num; + u64 caps; + u64 required_clks; + bool required_pctl; +@@ -1316,7 +1377,8 @@ struct mtk_soc_data { + * dummy for NAPI to work + * @netdev: The netdev instances + * @mac: Each netdev is linked to a physical MAC +- * @irq: The IRQ that we are using ++ * @irq_fe: Array of IRQs of the frame engine ++ * @irq_pdma: Array of IRQs of the PDMA used for RSS + * @msg_enable: Ethtool msg level + * @ethsys: The register map pointing at the range used to setup + * MII modes +@@ -1360,7 +1422,8 @@ struct mtk_eth { + struct net_device *dummy_dev; + struct net_device *netdev[MTK_MAX_DEVS]; + struct mtk_mac *mac[MTK_MAX_DEVS]; +- int irq[MTK_FE_IRQ_NUM]; ++ int irq_fe[MTK_FE_IRQ_NUM]; ++ int irq_pdma[MTK_PDMA_IRQ_NUM]; + u32 msg_enable; + unsigned long sysclk; + struct regmap *ethsys; +@@ -1373,7 +1436,8 @@ struct mtk_eth { + struct mtk_rx_ring rx_ring[MTK_MAX_RX_RING_NUM]; + struct mtk_rx_ring rx_ring_qdma; + struct napi_struct tx_napi; +- struct napi_struct rx_napi; ++ struct mtk_napi rx_napi[MTK_RX_NAPI_NUM]; ++ struct mtk_rss_params rss_params; + void *scratch_ring; + dma_addr_t phy_scratch_ring; + void *scratch_head[MTK_FQ_DMA_HEAD]; +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0074-net-mediatek-mtk_eth_soc-drop-RSS-capabilty-for-mt79.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0074-net-mediatek-mtk_eth_soc-drop-RSS-capabilty-for-mt79.patch new file mode 100644 index 0000000000..9c8422e2eb --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0074-net-mediatek-mtk_eth_soc-drop-RSS-capabilty-for-mt79.patch @@ -0,0 +1,31 @@ +From 4a4061dcab5bf9a5b35bd51f7538cac720c9719d Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sat, 12 Jul 2025 14:58:39 +0200 +Subject: [PATCH 74/84] net: mediatek: mtk_eth_soc: drop RSS capabilty for + mt798[16] + +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +index a163a04bb927..025f4a8119f7 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -1219,11 +1219,11 @@ enum mkt_eth_capabilities { + #define MT7981_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \ + MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ + MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \ +- MTK_RSTCTRL_PPE1 | MTK_SRAM | MTK_PDMA_INT | MTK_RSS) ++ MTK_RSTCTRL_PPE1 | MTK_SRAM | MTK_PDMA_INT) + + #define MT7986_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \ + MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ +- MTK_RSTCTRL_PPE1 | MTK_SRAM | MTK_PDMA_INT | MTK_RSS) ++ MTK_RSTCTRL_PPE1 | MTK_SRAM | MTK_PDMA_INT) + + #define MT7988_CAPS (MTK_36BIT_DMA | MTK_GDM1_ESW | MTK_GMAC1_SGMII | \ + MTK_GMAC2_2P5GPHY | MTK_GMAC2_SGMII | MTK_GMAC2_USXGMII | \ +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0075-net-mtk_eth_soc-fix-mtk_-get-set-_rxfh-callback-head.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0075-net-mtk_eth_soc-fix-mtk_-get-set-_rxfh-callback-head.patch new file mode 100644 index 0000000000..3231ba3e94 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0075-net-mtk_eth_soc-fix-mtk_-get-set-_rxfh-callback-head.patch @@ -0,0 +1,87 @@ +From c28e7f6075c7bd6e0dcf29cddd285ce4ec8ada85 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Fri, 20 Dec 2024 14:40:39 +0100 +Subject: [PATCH 75/84] net: mtk_eth_soc: fix mtk_{get,set}_rxfh callback + header + +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 31 ++++++++++----------- + 1 file changed, 15 insertions(+), 16 deletions(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index 18895e307824..5d2cfd026935 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -4994,32 +4994,31 @@ static u32 mtk_get_rxfh_indir_size(struct net_device *dev) + return MTK_RSS_MAX_INDIRECTION_TABLE; + } + +-static int mtk_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, +- u8 *hfunc) ++static int mtk_get_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh) + { + struct mtk_mac *mac = netdev_priv(dev); + struct mtk_eth *eth = mac->hw; + struct mtk_rss_params *rss_params = ð->rss_params; + int i; + +- if (hfunc) +- *hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */ ++ if (rxfh->hfunc) ++ rxfh->hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */ + +- if (key) { +- memcpy(key, rss_params->hash_key, ++ if (rxfh->key) { ++ memcpy(rxfh->key, rss_params->hash_key, + sizeof(rss_params->hash_key)); + } + +- if (indir) { ++ if (rxfh->indir) { + for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE; i++) +- indir[i] = rss_params->indirection_table[i]; ++ rxfh->indir[i] = rss_params->indirection_table[i]; + } + + return 0; + } + +-static int mtk_set_rxfh(struct net_device *dev, const u32 *indir, +- const u8 *key, const u8 hfunc) ++static int mtk_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh, ++ struct netlink_ext_ack *extack) + { + struct mtk_mac *mac = netdev_priv(dev); + struct mtk_eth *eth = mac->hw; +@@ -5027,21 +5026,21 @@ static int mtk_set_rxfh(struct net_device *dev, const u32 *indir, + const struct mtk_reg_map *reg_map = eth->soc->reg_map; + int i; + +- if (hfunc != ETH_RSS_HASH_NO_CHANGE && +- hfunc != ETH_RSS_HASH_TOP) ++ if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE && ++ rxfh->hfunc != ETH_RSS_HASH_TOP) + return -EOPNOTSUPP; + +- if (key) { +- memcpy(rss_params->hash_key, key, ++ if (rxfh->key) { ++ memcpy(rss_params->hash_key, rxfh->key, + sizeof(rss_params->hash_key)); + for (i = 0; i < MTK_RSS_HASH_KEYSIZE / sizeof(u32); i++) + mtk_w32(eth, rss_params->hash_key[i], + MTK_RSS_HASH_KEY_DW(i)); + } + +- if (indir) { ++ if (rxfh->indir) { + for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE; i++) +- rss_params->indirection_table[i] = indir[i]; ++ rss_params->indirection_table[i] = rxfh->indir[i]; + for (i = 0; i < MTK_RSS_MAX_INDIRECTION_TABLE / 16; i++) + mtk_w32(eth, mtk_rss_indr_table(rss_params, i), + MTK_RSS_INDR_TABLE_DW(i)); +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0076-net-ethernet-mtk_eth_soc-Add-LRO-support.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0076-net-ethernet-mtk_eth_soc-Add-LRO-support.patch new file mode 100644 index 0000000000..15d23f4fa0 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0076-net-ethernet-mtk_eth_soc-Add-LRO-support.patch @@ -0,0 +1,514 @@ +From d1b69872d8379a4860bfd0eebcb9bcbb85c3686c Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Fri, 21 Mar 2025 11:22:43 +0100 +Subject: [PATCH 76/84] net: ethernet: mtk_eth_soc: Add LRO support + +based on +https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/e5b6f723b733f1ddc613e9d9e8db7a82e0b42e5c +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 213 ++++++++++++++++++-- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 47 +++-- + 2 files changed, 220 insertions(+), 40 deletions(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index 5d2cfd026935..799dc58e2581 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -2819,7 +2819,7 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag) + if (!ring->data) + return -ENOMEM; + +- if (mtk_page_pool_enabled(eth)) { ++ if (mtk_page_pool_enabled(eth) && rcu_access_pointer(eth->prog)) { + struct page_pool *pp; + + pp = mtk_create_page_pool(eth, &ring->xdp_q, ring_no, +@@ -2966,7 +2966,8 @@ static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, bool in_ + static int mtk_hwlro_rx_init(struct mtk_eth *eth) + { + const struct mtk_reg_map *reg_map = eth->soc->reg_map; +- int i; ++ const struct mtk_soc_data *soc = eth->soc; ++ int i, val; + u32 ring_ctrl_dw1 = 0, ring_ctrl_dw2 = 0, ring_ctrl_dw3 = 0; + u32 lro_ctrl_dw0 = 0, lro_ctrl_dw3 = 0; + +@@ -2987,7 +2988,7 @@ static int mtk_hwlro_rx_init(struct mtk_eth *eth) + ring_ctrl_dw2 |= MTK_RING_MAX_AGG_CNT_L; + ring_ctrl_dw3 |= MTK_RING_MAX_AGG_CNT_H; + +- for (i = 1; i < MTK_MAX_RX_RING_NUM; i++) { ++ for (i = 1; i <= MTK_HW_LRO_RING_NUM; i++) { + mtk_w32(eth, ring_ctrl_dw1, MTK_LRO_CTRL_DW1_CFG(i)); + mtk_w32(eth, ring_ctrl_dw2, MTK_LRO_CTRL_DW2_CFG(i)); + mtk_w32(eth, ring_ctrl_dw3, MTK_LRO_CTRL_DW3_CFG(i)); +@@ -3009,8 +3010,22 @@ static int mtk_hwlro_rx_init(struct mtk_eth *eth) + mtk_w32(eth, (MTK_HW_LRO_TIMER_UNIT << 16) | MTK_HW_LRO_REFRESH_TIME, + MTK_PDMA_LRO_ALT_REFRESH_TIMER); + +- /* set HW LRO mode & the max aggregation count for rx packets */ +- lro_ctrl_dw3 |= MTK_ADMA_MODE | (MTK_HW_LRO_MAX_AGG_CNT & 0xff); ++ if (mtk_is_netsys_v3_or_greater(eth)) { ++ val = mtk_r32(eth, reg_map->pdma.rx_cfg); ++ mtk_w32(eth, val | ((MTK_PDMA_LRO_SDL + MTK_MAX_RX_LENGTH) << ++ MTK_RX_CFG_SDL_OFFSET), reg_map->pdma.rx_cfg); ++ ++ lro_ctrl_dw0 |= MTK_PDMA_LRO_SDL << MTK_CTRL_DW0_SDL_OFFSET; ++ ++ /* enable cpu reason black list */ ++ lro_ctrl_dw0 |= MTK_LRO_CRSN_BNW; ++ ++ /* no use PPE cpu reason */ ++ mtk_w32(eth, 0xffffffff, MTK_PDMA_LRO_CTRL_DW1); ++ } else { ++ /* set HW LRO mode & the max aggregation count for rx packets */ ++ lro_ctrl_dw3 |= MTK_ADMA_MODE | (MTK_HW_LRO_MAX_AGG_CNT & 0xff); ++ } + + /* the minimal remaining room of SDL0 in RXD for lro aggregation */ + lro_ctrl_dw3 |= MTK_LRO_MIN_RXD_SDL; +@@ -3021,6 +3036,16 @@ static int mtk_hwlro_rx_init(struct mtk_eth *eth) + mtk_w32(eth, lro_ctrl_dw3, MTK_PDMA_LRO_CTRL_DW3); + mtk_w32(eth, lro_ctrl_dw0, MTK_PDMA_LRO_CTRL_DW0); + ++ if (mtk_is_netsys_v2_or_greater(eth)) { ++ i = (soc->rx.desc_size == sizeof(struct mtk_rx_dma_v2)) ? 1 : 0; ++ mtk_m32(eth, MTK_RX_DONE_INT(MTK_HW_LRO_RING(i)), ++ MTK_RX_DONE_INT(MTK_HW_LRO_RING(i)), reg_map->pdma.int_grp); ++ mtk_m32(eth, MTK_RX_DONE_INT(MTK_HW_LRO_RING(i + 1)), ++ MTK_RX_DONE_INT(MTK_HW_LRO_RING(i + 1)), reg_map->pdma.int_grp + 0x4); ++ mtk_m32(eth, MTK_RX_DONE_INT(MTK_HW_LRO_RING(i + 2)), ++ MTK_RX_DONE_INT(MTK_HW_LRO_RING(i + 2)), reg_map->pdma.int_grp3); ++ } ++ + return 0; + } + +@@ -3044,7 +3069,7 @@ static void mtk_hwlro_rx_uninit(struct mtk_eth *eth) + } + + /* invalidate lro rings */ +- for (i = 1; i < MTK_MAX_RX_RING_NUM; i++) ++ for (i = 1; i <= MTK_HW_LRO_RING_NUM; i++) + mtk_w32(eth, 0, MTK_LRO_CTRL_DW2_CFG(i)); + + /* disable HW LRO */ +@@ -3093,6 +3118,64 @@ static int mtk_hwlro_get_ip_cnt(struct mtk_mac *mac) + return cnt; + } + ++static int mtk_hwlro_add_ipaddr_idx(struct net_device *dev, u32 ip4dst) ++{ ++ struct mtk_mac *mac = netdev_priv(dev); ++ struct mtk_eth *eth = mac->hw; ++ const struct mtk_reg_map *reg_map = eth->soc->reg_map; ++ u32 reg_val; ++ int i; ++ ++ /* check for duplicate IP address in the current DIP list */ ++ for (i = 1; i <= MTK_HW_LRO_DIP_NUM; i++) { ++ reg_val = mtk_r32(eth, MTK_LRO_DIP_DW0_CFG(i)); ++ if (reg_val == ip4dst) ++ break; ++ } ++ ++ if (i < MTK_HW_LRO_DIP_NUM + 1) { ++ netdev_warn(dev, "Duplicate IP address at DIP(%d)!\n", i); ++ return -EEXIST; ++ } ++ ++ /* find out available DIP index */ ++ for (i = 1; i <= MTK_HW_LRO_DIP_NUM; i++) { ++ reg_val = mtk_r32(eth, MTK_LRO_DIP_DW0_CFG(i)); ++ if (reg_val == 0UL) ++ break; ++ } ++ ++ if (i >= MTK_HW_LRO_DIP_NUM + 1) { ++ netdev_warn(dev, "DIP index is currently out of resource!\n"); ++ return -EBUSY; ++ } ++ ++ return i; ++} ++ ++static int mtk_hwlro_get_ipaddr_idx(struct net_device *dev, u32 ip4dst) ++{ ++ struct mtk_mac *mac = netdev_priv(dev); ++ struct mtk_eth *eth = mac->hw; ++ const struct mtk_reg_map *reg_map = eth->soc->reg_map; ++ u32 reg_val; ++ int i; ++ ++ /* find out DIP index that matches the given IP address */ ++ for (i = 1; i <= MTK_HW_LRO_DIP_NUM; i++) { ++ reg_val = mtk_r32(eth, MTK_LRO_DIP_DW0_CFG(i)); ++ if (reg_val == ip4dst) ++ break; ++ } ++ ++ if (i >= MTK_HW_LRO_DIP_NUM + 1) { ++ netdev_warn(dev, "DIP address is not exist!\n"); ++ return -ENOENT; ++ } ++ ++ return i; ++} ++ + static int mtk_hwlro_add_ipaddr(struct net_device *dev, + struct ethtool_rxnfc *cmd) + { +@@ -3101,15 +3184,19 @@ static int mtk_hwlro_add_ipaddr(struct net_device *dev, + struct mtk_mac *mac = netdev_priv(dev); + struct mtk_eth *eth = mac->hw; + int hwlro_idx; ++ u32 ip4dst; + + if ((fsp->flow_type != TCP_V4_FLOW) || + (!fsp->h_u.tcp_ip4_spec.ip4dst) || + (fsp->location > 1)) + return -EINVAL; + +- mac->hwlro_ip[fsp->location] = htonl(fsp->h_u.tcp_ip4_spec.ip4dst); +- hwlro_idx = (mac->id * MTK_MAX_LRO_IP_CNT) + fsp->location; ++ ip4dst = htonl(fsp->h_u.tcp_ip4_spec.ip4dst); ++ hwlro_idx = mtk_hwlro_add_ipaddr_idx(dev, ip4dst); ++ if (hwlro_idx < 0) ++ return hwlro_idx; + ++ mac->hwlro_ip[fsp->location] = ip4dst; + mac->hwlro_ip_cnt = mtk_hwlro_get_ip_cnt(mac); + + mtk_hwlro_val_ipaddr(eth, hwlro_idx, mac->hwlro_ip[fsp->location]); +@@ -3125,13 +3212,17 @@ static int mtk_hwlro_del_ipaddr(struct net_device *dev, + struct mtk_mac *mac = netdev_priv(dev); + struct mtk_eth *eth = mac->hw; + int hwlro_idx; ++ u32 ip4dst; + + if (fsp->location > 1) + return -EINVAL; + +- mac->hwlro_ip[fsp->location] = 0; +- hwlro_idx = (mac->id * MTK_MAX_LRO_IP_CNT) + fsp->location; ++ ip4dst = mac->hwlro_ip[fsp->location]; ++ hwlro_idx = mtk_hwlro_get_ipaddr_idx(dev, ip4dst); ++ if (hwlro_idx < 0) ++ return hwlro_idx; + ++ mac->hwlro_ip[fsp->location] = 0; + mac->hwlro_ip_cnt = mtk_hwlro_get_ip_cnt(mac); + + mtk_hwlro_inval_ipaddr(eth, hwlro_idx); +@@ -3139,6 +3230,24 @@ static int mtk_hwlro_del_ipaddr(struct net_device *dev, + return 0; + } + ++static void mtk_hwlro_netdev_enable(struct net_device *dev) ++{ ++ struct mtk_mac *mac = netdev_priv(dev); ++ struct mtk_eth *eth = mac->hw; ++ int i, hwlro_idx; ++ ++ for (i = 0; i < MTK_MAX_LRO_IP_CNT; i++) { ++ if (mac->hwlro_ip[i] == 0) ++ continue; ++ ++ hwlro_idx = mtk_hwlro_get_ipaddr_idx(dev, mac->hwlro_ip[i]); ++ if (hwlro_idx < 0) ++ continue; ++ ++ mtk_hwlro_val_ipaddr(eth, hwlro_idx, mac->hwlro_ip[i]); ++ } ++} ++ + static void mtk_hwlro_netdev_disable(struct net_device *dev) + { + struct mtk_mac *mac = netdev_priv(dev); +@@ -3146,8 +3255,14 @@ static void mtk_hwlro_netdev_disable(struct net_device *dev) + int i, hwlro_idx; + + for (i = 0; i < MTK_MAX_LRO_IP_CNT; i++) { ++ if (mac->hwlro_ip[i] == 0) ++ continue; ++ ++ hwlro_idx = mtk_hwlro_get_ipaddr_idx(dev, mac->hwlro_ip[i]); ++ if (hwlro_idx < 0) ++ continue; ++ + mac->hwlro_ip[i] = 0; +- hwlro_idx = (mac->id * MTK_MAX_LRO_IP_CNT) + i; + + mtk_hwlro_inval_ipaddr(eth, hwlro_idx); + } +@@ -3333,6 +3448,8 @@ static int mtk_set_features(struct net_device *dev, netdev_features_t features) + + if ((diff & NETIF_F_LRO) && !(features & NETIF_F_LRO)) + mtk_hwlro_netdev_disable(dev); ++ else if ((diff & NETIF_F_LRO) && (features & NETIF_F_LRO)) ++ mtk_hwlro_netdev_enable(dev); + + return 0; + } +@@ -3390,8 +3507,8 @@ static int mtk_dma_init(struct mtk_eth *eth) + return err; + + if (eth->hwlro) { +- for (i = 1; i < MTK_MAX_RX_RING_NUM; i++) { +- err = mtk_rx_alloc(eth, i, MTK_RX_FLAGS_HWLRO); ++ for (i = 0; i < MTK_HW_LRO_RING_NUM; i++) { ++ err = mtk_rx_alloc(eth, MTK_HW_LRO_RING(i), MTK_RX_FLAGS_HWLRO); + if (err) + return err; + } +@@ -3453,8 +3570,8 @@ static void mtk_dma_free(struct mtk_eth *eth) + + if (eth->hwlro) { + mtk_hwlro_rx_uninit(eth); +- for (i = 1; i < MTK_MAX_RX_RING_NUM; i++) +- mtk_rx_clean(eth, ð->rx_ring[i], false); ++ for (i = 0; i < MTK_HW_LRO_RING_NUM; i++) ++ mtk_rx_clean(eth, ð->rx_ring[MTK_HW_LRO_RING(i)], false); + } + + if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) { +@@ -3650,16 +3767,21 @@ static int mtk_start_dma(struct mtk_eth *eth) + val |= MTK_RX_BT_32DWORDS; + mtk_w32(eth, val, reg_map->qdma.glo_cfg); + +- mtk_w32(eth, +- MTK_RX_DMA_EN | rx_2b_offset | +- MTK_RX_BT_32DWORDS | MTK_MULTI_EN, +- reg_map->pdma.glo_cfg); ++ val = mtk_r32(eth, reg_map->pdma.glo_cfg); ++ val |= MTK_RX_DMA_EN | rx_2b_offset | ++ MTK_RX_BT_32DWORDS | MTK_MULTI_EN; ++ mtk_w32(eth, val, reg_map->pdma.glo_cfg); + } else { + mtk_w32(eth, MTK_TX_WB_DDONE | MTK_TX_DMA_EN | MTK_RX_DMA_EN | + MTK_MULTI_EN | MTK_PDMA_SIZE_8DWORDS, + reg_map->pdma.glo_cfg); + } + ++ if (eth->hwlro && mtk_is_netsys_v3_or_greater(eth)) { ++ val = mtk_r32(eth, reg_map->pdma.glo_cfg); ++ mtk_w32(eth, val | MTK_RX_DMA_LRO_EN, reg_map->pdma.glo_cfg); ++ } ++ + return 0; + } + +@@ -3803,6 +3925,13 @@ static int mtk_open(struct net_device *dev) + } + } + ++ if (eth->hwlro) { ++ for (i = 0; i < MTK_HW_LRO_RING_NUM; i++) { ++ napi_enable(ð->rx_napi[MTK_HW_LRO_RING(i)].napi); ++ mtk_rx_irq_enable(eth, MTK_RX_DONE_INT(MTK_HW_LRO_RING(i))); ++ } ++ } ++ + refcount_set(ð->dma_refcnt, 1); + } else { + refcount_inc(ð->dma_refcnt); +@@ -3898,6 +4027,14 @@ static int mtk_stop(struct net_device *dev) + } + } + ++ if (eth->hwlro) { ++ for (i = 0; i < MTK_HW_LRO_RING_NUM; i++) { ++ mtk_rx_irq_disable(eth, MTK_RX_DONE_INT(MTK_HW_LRO_RING(i))); ++ napi_synchronize(ð->rx_napi[MTK_HW_LRO_RING(i)].napi); ++ napi_disable(ð->rx_napi[MTK_HW_LRO_RING(i)].napi); ++ } ++ } ++ + cancel_work_sync(ð->rx_dim.work); + cancel_work_sync(ð->tx_dim.work); + +@@ -4342,6 +4479,14 @@ static int mtk_napi_init(struct mtk_eth *eth) + } + } + ++ if (eth->hwlro) { ++ for (i = 0; i < MTK_HW_LRO_RING_NUM; i++) { ++ rx_napi = ð->rx_napi[MTK_HW_LRO_RING(i)]; ++ rx_napi->eth = eth; ++ rx_napi->rx_ring = ð->rx_ring[MTK_HW_LRO_RING(i)]; ++ } ++ } ++ + return 0; + } + +@@ -4905,7 +5050,7 @@ static int mtk_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, + switch (cmd->cmd) { + case ETHTOOL_GRXRINGS: + if (dev->hw_features & NETIF_F_LRO) { +- cmd->data = MTK_MAX_RX_RING_NUM; ++ cmd->data = MTK_HW_LRO_RING_NUM; + ret = 0; + } else if (MTK_HAS_CAPS(eth->soc->caps, MTK_RSS)) { + cmd->data = MTK_RX_RSS_NUM; +@@ -5661,6 +5806,21 @@ static int mtk_probe(struct platform_device *pdev) + goto err_free_dev; + } + } ++ ++ if (eth->hwlro) { ++ for (i = 0; i < MTK_HW_LRO_RING_NUM; i++) { ++ irqname = devm_kasprintf(eth->dev, GFP_KERNEL, ++ "%s LRO RX %d", ++ dev_name(eth->dev), i); ++ err = devm_request_irq(eth->dev, ++ eth->irq_pdma[MTK_HW_LRO_IRQ(i)], ++ mtk_handle_irq_rx, IRQF_SHARED, ++ irqname, ++ ð->rx_napi[MTK_HW_LRO_RING(i)]); ++ if (err) ++ goto err_free_dev; ++ } ++ } + } else { + irqname = devm_kasprintf(eth->dev, GFP_KERNEL, "%s RX", + dev_name(eth->dev)); +@@ -5732,6 +5892,13 @@ static int mtk_probe(struct platform_device *pdev) + mtk_napi_rx); + } + ++ if (eth->hwlro) { ++ for (i = 0; i < MTK_HW_LRO_RING_NUM; i++) { ++ netif_napi_add(eth->dummy_dev, ð->rx_napi[MTK_HW_LRO_RING(i)].napi, ++ mtk_napi_rx); ++ } ++ } ++ + platform_set_drvdata(pdev, eth); + schedule_delayed_work(ð->reset.monitor_work, + MTK_DMA_MONITOR_TIMEOUT); +@@ -5780,6 +5947,12 @@ static void mtk_remove(struct platform_device *pdev) + for (i = 1; i < MTK_RX_RSS_NUM; i++) + netif_napi_del(ð->rx_napi[MTK_RSS_RING(i)].napi); + } ++ ++ if (eth->hwlro) { ++ for (i = 0; i < MTK_HW_LRO_RING_NUM; i++) ++ netif_napi_del(ð->rx_napi[MTK_HW_LRO_RING(i)].napi); ++ } ++ + mtk_cleanup(eth); + free_netdev(eth->dummy_dev); + mtk_mdio_cleanup(eth); +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +index 025f4a8119f7..f4f6ea355c52 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -36,7 +36,7 @@ + #define MTK_DMA_SIZE(x) (SZ_##x) + #define MTK_FQ_DMA_HEAD 32 + #define MTK_FQ_DMA_LENGTH 2048 +-#define MTK_RX_ETH_HLEN (ETH_HLEN + ETH_FCS_LEN) ++#define MTK_RX_ETH_HLEN (VLAN_ETH_HLEN + VLAN_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 | \ +@@ -64,10 +64,13 @@ + + #define MTK_QRX_OFFSET 0x10 + +-#define MTK_MAX_RX_RING_NUM 4 +-#define MTK_HW_LRO_DMA_SIZE 8 ++#define MTK_MAX_RX_RING_NUM (8) ++#define MTK_HW_LRO_DMA_SIZE (mtk_is_netsys_v3_or_greater(eth) ? 64 : 8) ++#define IS_HW_LRO_RING(ring_no) (mtk_is_netsys_v3_or_greater(eth) ? \ ++ (((ring_no) > 3) && ((ring_no) < 8)) : \ ++ (((ring_no) > 0) && ((ring_no) < 4))) + +-#define MTK_MAX_LRO_RX_LENGTH (4096 * 3) ++#define MTK_MAX_LRO_RX_LENGTH (4096 * 3 + MTK_MAX_RX_LENGTH) + #define MTK_MAX_LRO_IP_CNT 2 + #define MTK_HW_LRO_TIMER_UNIT 1 /* 20 us */ + #define MTK_HW_LRO_REFRESH_TIME 50000 /* 1 sec. */ +@@ -183,31 +186,35 @@ + #define MTK_CDMM_THRES 0x165c + + /* PDMA HW LRO Control Registers */ +-#define MTK_PDMA_LRO_CTRL_DW0 0x980 ++#define MTK_HW_LRO_DIP_NUM (mtk_is_netsys_v3_or_greater(eth) ? 4 : 3) + #define MTK_HW_LRO_RING_NUM (mtk_is_netsys_v3_or_greater(eth) ? 4 : 3) ++#define MTK_HW_LRO_RING(x) ((x) + (mtk_is_netsys_v3_or_greater(eth) ? 4 : 1)) ++#define MTK_HW_LRO_IRQ(x) ((x) + (mtk_is_netsys_v3_or_greater(eth) ? 0 : 1)) ++#define MTK_LRO_CRSN_BNW BIT((mtk_is_netsys_v3_or_greater(eth) ? 22 : 6)) + #define MTK_LRO_EN BIT(0) + #define MTK_NON_LRO_MULTI_EN BIT(2) + #define MTK_LRO_DLY_INT_EN BIT(5) +-#define MTK_L3_CKS_UPD_EN BIT(7) +-#define MTK_L3_CKS_UPD_EN_V2 BIT(19) ++#define MTK_L3_CKS_UPD_EN BIT(mtk_is_netsys_v3_or_greater(eth) ? 19 : 7) + #define MTK_LRO_ALT_PKT_CNT_MODE BIT(21) +-#define MTK_LRO_RING_RELINQUISH_REQ (0x7 << 26) +-#define MTK_LRO_RING_RELINQUISH_REQ_V2 (0xf << 24) +-#define MTK_LRO_RING_RELINQUISH_DONE (0x7 << 29) +-#define MTK_LRO_RING_RELINQUISH_DONE_V2 (0xf << 28) +- +-#define MTK_PDMA_LRO_CTRL_DW1 0x984 +-#define MTK_PDMA_LRO_CTRL_DW2 0x988 +-#define MTK_PDMA_LRO_CTRL_DW3 0x98c ++#define MTK_LRO_RING_RELINQUISH_REQ (mtk_is_netsys_v3_or_greater(eth) ? 0xf << 24 : 0x7 << 26) ++#define MTK_LRO_RING_RELINQUISH_DONE (mtk_is_netsys_v3_or_greater(eth) ? 0xf << 28 : 0x7 << 29) ++ ++#define MTK_PDMA_LRO_CTRL_DW0 (reg_map->pdma.lro_ctrl_dw0) ++#define MTK_PDMA_LRO_CTRL_DW1 (reg_map->pdma.lro_ctrl_dw0 + 0x04) ++#define MTK_PDMA_LRO_CTRL_DW2 (reg_map->pdma.lro_ctrl_dw0 + 0x08) ++#define MTK_PDMA_LRO_CTRL_DW3 (reg_map->pdma.lro_ctrl_dw0 + 0x0c) + #define MTK_ADMA_MODE BIT(15) + #define MTK_LRO_MIN_RXD_SDL (MTK_HW_LRO_SDL_REMAIN_ROOM << 16) + ++#define MTK_CTRL_DW0_SDL_OFFSET (3) ++#define MTK_CTRL_DW0_SDL_MASK BITS(3, 18) ++ + #define MTK_RX_DMA_LRO_EN BIT(8) + #define MTK_MULTI_EN BIT(10) + #define MTK_PDMA_SIZE_8DWORDS (1 << 4) + + /* PDMA RSS Control Registers */ +-#define MTK_RX_NAPI_NUM (4) ++#define MTK_RX_NAPI_NUM (8) + #define MTK_RX_RSS_NUM (eth->soc->rss_num) + #define MTK_RSS_RING(x) (x) + #define MTK_RSS_EN BIT(0) +@@ -243,11 +250,10 @@ + #define MTK_PDMA_DELAY_PTIME_MASK 0xff + + /* PDMA HW LRO Alter Flow Delta Register */ +-#define MTK_PDMA_LRO_ALT_SCORE_DELTA 0xa4c ++#define MTK_PDMA_LRO_ALT_SCORE_DELTA (reg_map->pdma.lro_alt_score_delta) + + /* PDMA HW LRO IP Setting Registers */ +-#define MTK_LRO_RX_RING0_DIP_DW0 0xb04 +-#define MTK_LRO_DIP_DW0_CFG(x) (MTK_LRO_RX_RING0_DIP_DW0 + (x * 0x40)) ++#define MTK_LRO_DIP_DW0_CFG(x) (reg_map->pdma.lro_ring_dip_dw0 + (x * 0x40)) + #define MTK_RING_MYIP_VLD BIT(9) + + /* PDMA HW LRO Ring Control Registers */ +@@ -1231,7 +1237,7 @@ enum mkt_eth_capabilities { + MTK_MUX_GMAC123_TO_GEPHY_SGMII | \ + MTK_MUX_GMAC123_TO_USXGMII | MTK_MUX_GMAC2_TO_2P5GPHY | \ + MTK_QDMA | MTK_SRAM | MTK_PDMA_INT | MTK_RSS | \ +- MTK_RSTCTRL_PPE1 | MTK_RSTCTRL_PPE2) ++ MTK_HWLRO | MTK_RSTCTRL_PPE1 | MTK_RSTCTRL_PPE2) + + struct mtk_tx_dma_desc_info { + dma_addr_t addr; +@@ -1512,6 +1518,7 @@ struct mtk_mac { + + /* the struct describing the SoC. these are declared in the soc_xyz.c files */ + extern const struct of_device_id of_mtk_match[]; ++extern u32 mtk_hwlro_stats_ebl; + + static inline bool mtk_is_netsys_v1(struct mtk_eth *eth) + { +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0077-readme-add-README.md-for-RSS-LRO.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0077-readme-add-README.md-for-RSS-LRO.patch new file mode 100644 index 0000000000..2452d5acc2 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0077-readme-add-README.md-for-RSS-LRO.patch @@ -0,0 +1,101 @@ +From 0d853dd76392d669385fd472c1154c2a818ae2e6 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Tue, 10 Jun 2025 23:28:00 +0200 +Subject: [PATCH 77/84] readme: add README.md for RSS/LRO + +--- + README.md | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 82 insertions(+) + create mode 100644 README.md + +diff --git a/README.md b/README.md +new file mode 100644 +index 000000000000..f6b88d4d502a +--- /dev/null ++++ b/README.md +@@ -0,0 +1,82 @@ ++# RSS / LRO ++ ++HW-acceleration for ending traffic. ++For routed traffic PPE is needed and hw offloading in nftables. ++Bridged traffic may need addional changes (openwrt use bridger utility). ++ ++## RSS ++ ++(Receive Side Scaling) ++ ++using 4 additional IRQ for spreading load ++ ++cat /proc/interrupts | grep ethernet ++ ++echo 1 > /proc/irq/105/smp_affinity ++echo 2 > /proc/irq/106/smp_affinity ++echo 4 > /proc/irq/107/smp_affinity ++echo 8 > /proc/irq/108/smp_affinity ++ ++moving tx frame-engine irq to different cpu (here 3rd) ++echo 4 > /proc/irq/103/smp_affinity ++ ++disable RPS (Receive Packet Steering) for all macs: ++echo 0 > /sys/devices/platform/soc/15100000.ethernet/net/eth0/queues/rx-0/rps_cpus ++ ++pay attention on iperf-version (iperf 3.17 is ok, 3.12 is not) ++ ++traffic must be created using multiple streams so that it can be splitted, so use multithreaded iperf3 ++ ++on R4: ++bin/iperf3 -s ++ ++on the other side: ++iperf3 -c 192.168.1.1 -i 1 -P 4 ++ ++you should reach ~9.3 GBit/s ++ ++and see spreading load over CPU cores ++ ++root@bpi-r4-phy-8G:~# cat /proc/interrupts | grep eth ++103: 20 198366 0 0 GICv3 229 Level 15100000.ethernet ++105: 3611 0 0 0 GICv3 221 Level 15100000.ethernet, 15100000.ethernet ++106: 2 6842 0 0 GICv3 222 Level 15100000.ethernet, 15100000.ethernet ++107: 4 0 27643 0 GICv3 223 Level 15100000.ethernet, 15100000.ethernet ++108: 3 0 0 27925 GICv3 224 Level 15100000.ethernet, 15100000.ethernet ++ ++using the default iperf3 from debian bookworm (3.12) results in only 6.7GBit/s ++ ++## LRO ++(Large Receive Offload) ++ ++Add HW LRO RX rule: ++ ++ethtool -N [interface] flow-type tcp4 dst-ip [IP] action 0 loc [0/1] ++ ++Delete HW LRO RX rule: ++ ++ethtool -N [interface] delete [0/1] ++ ++Enable/Disable HW LRO rule: ++ ++ethtool -K [interface] lro [on | off] ++ ++Show the current offload features: ++ ++ethtool -k [interface] ++ ++example: ++ ++ethtool -N eth2 flow-type tcp4 dst-ip 192.168.1.1 action 0 loc 0 ++ethtool -K eth2 lro on ++ethtool -k eth2 ++ ++using iperf instead of iperf3! ++ ++verify with propritary debugfs ++Enable HW LRO rings ++echo 4 1 > /proc/mtketh/hw_lro_auto_tlb ++Enable HW LRO statistics ++echo 5 1 > /proc/mtketh/hw_lro_auto_tlb ++ ++cat /proc/mtketh/hw_lro_stats +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0078-net-ethernet-mtk_eth_soc-support-forced-reset-contro.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0078-net-ethernet-mtk_eth_soc-support-forced-reset-contro.patch new file mode 100644 index 0000000000..242a5d8d5b --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0078-net-ethernet-mtk_eth_soc-support-forced-reset-contro.patch @@ -0,0 +1,61 @@ +From ad2f0a1e65bd58dee78804dc28736ff616381356 Mon Sep 17 00:00:00 2001 +From: Bo-Cun Chen +Date: Wed, 27 Nov 2024 10:16:27 +0800 +Subject: [PATCH 78/84] net: ethernet: mtk_eth_soc: support forced reset + control + +Without this patch, users are unable to control the forced reset +through the proprietary debugfs. + +Signed-off-by: Bo-Cun Chen +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 6 ++++-- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 + + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index 799dc58e2581..730146eb322e 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3609,7 +3609,8 @@ static void mtk_tx_timeout(struct net_device *dev, unsigned int txqueue) + eth->netdev[mac->id]->stats.tx_errors++; + netif_err(eth, tx_err, dev, "transmit timed out\n"); + +- schedule_work(ð->pending_work); ++ if (atomic_read(ð->reset.force)) ++ schedule_work(ð->pending_work); + } + + static int mtk_get_irqs_fe(struct platform_device *pdev, struct mtk_eth *eth) +@@ -4455,7 +4456,7 @@ static void mtk_hw_reset_monitor_work(struct work_struct *work) + goto out; + + /* DMA stuck checks */ +- if (mtk_hw_check_dma_hang(eth)) ++ if (mtk_hw_check_dma_hang(eth) && atomic_read(ð->reset.force)) + schedule_work(ð->pending_work); + + out: +@@ -5617,6 +5618,7 @@ static int mtk_probe(struct platform_device *pdev) + + eth->rx_dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE; + INIT_WORK(ð->rx_dim.work, mtk_dim_rx); ++ atomic_set(ð->reset.force, 0); + INIT_DELAYED_WORK(ð->reset.monitor_work, mtk_hw_reset_monitor_work); + + eth->tx_dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE; +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +index f4f6ea355c52..14c3ce16f733 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -1479,6 +1479,7 @@ struct mtk_eth { + + struct { + struct delayed_work monitor_work; ++ atomic_t force; + u32 wdidx; + u8 wdma_hang_count; + u8 qdma_hang_count; +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0079-net-mediatek-add-proprietary-debugfs.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0079-net-mediatek-add-proprietary-debugfs.patch new file mode 100644 index 0000000000..1ac6251b4f --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0079-net-mediatek-add-proprietary-debugfs.patch @@ -0,0 +1,3007 @@ +From 3e9c1d3f9d6001378c48848925bbd263b5107c1a Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Wed, 15 Jan 2025 20:00:57 +0100 +Subject: [PATCH 79/84] net: mediatek: add proprietary debugfs + +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:355:5: warning: no previous prototype for 'mt798x_iomap' [-Wmissing-prototypes] + 355 | int mt798x_iomap(void) + | ^~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:375:5: warning: no previous prototype for 'mt798x_iounmap' [-Wmissing-prototypes] + 375 | int mt798x_iounmap(void) + | ^~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:384:6: warning: no previous prototype for 'mt7530_mdio_w32' [-Wmissing-prototypes] + 384 | void mt7530_mdio_w32(struct mtk_eth *eth, u16 reg, u32 val) + | ^~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:399:5: warning: no previous prototype for 'mt7530_mdio_r32' [-Wmissing-prototypes] + 399 | u32 mt7530_mdio_r32(struct mtk_eth *eth, u32 reg) + | ^~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:420:6: warning: no previous prototype for 'mtk_switch_w32' [-Wmissing-prototypes] + 420 | void mtk_switch_w32(struct mtk_eth *eth, u32 val, unsigned int reg) + | ^~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:426:5: warning: no previous prototype for 'mtk_switch_r32' [-Wmissing-prototypes] + 426 | u32 mtk_switch_r32(struct mtk_eth *eth, unsigned int reg) + | ^~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: In function 'mtketh_debugfs_reset': +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:680:39: error: 'struct ' has no member named 'force' + 680 | atomic_set(ð->reset.force, 0); + | ^ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:683:44: error: 'struct ' has no member named 'force' + 683 | if (atomic_read(ð->reset.force)) + | ^ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:689:39: error: 'struct ' has no member named 'force' + 689 | atomic_set(ð->reset.force, 1); + | ^ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: At top level: +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:782:6: warning: no previous prototype for 'mii_mgr_read_combine' [-Wmissing-prototypes] + 782 | void mii_mgr_read_combine(struct mtk_eth *eth, u32 phy_addr, u32 phy_register, + | ^~~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:792:6: warning: no previous prototype for 'mii_mgr_write_combine' [-Wmissing-prototypes] + 792 | void mii_mgr_write_combine(struct mtk_eth *eth, u16 phy_addr, u16 phy_register, + | ^~~~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:991:6: warning: no previous prototype for 'dump_each_port' [-Wmissing-prototypes] + 991 | void dump_each_port(struct seq_file *seq, struct mtk_eth *eth, u32 base) + | ^~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: In function 'dump_each_port': +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1003:33: warning: suggest braces around empty body in an 'else' statement [-Wempty-body] + 1003 | ; + | ^ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: At top level: +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1011:5: warning: no previous prototype for 'esw_cnt_read' [-Wmissing-prototypes] + 1011 | int esw_cnt_read(struct seq_file *seq, void *v) + | ^~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1085:6: warning: no previous prototype for 'xfi_mib_dump' [-Wmissing-prototypes] + 1085 | void xfi_mib_dump(struct seq_file *seq, u32 gdm_id) + | ^~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1111:5: warning: no previous prototype for 'xfi_cnt_read' [-Wmissing-prototypes] + 1111 | int xfi_cnt_read(struct seq_file *seq, void *v) + | ^~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1144:5: warning: no previous prototype for 'tx_ring_read' [-Wmissing-prototypes] + 1144 | int tx_ring_read(struct seq_file *seq, void *v) + | ^~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1190:5: warning: no previous prototype for 'hwtx_ring_read' [-Wmissing-prototypes] + 1190 | int hwtx_ring_read(struct seq_file *seq, void *v) + | ^~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1230:5: warning: no previous prototype for 'rx_ring_read' [-Wmissing-prototypes] + 1230 | int rx_ring_read(struct seq_file *seq, void *v) + | ^~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1282:5: warning: no previous prototype for 'dbg_regs_read' [-Wmissing-prototypes] + 1282 | int dbg_regs_read(struct seq_file *seq, void *v) + | ^~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1482:9: warning: no previous prototype for 'hw_lro_stats_write' [-Wmissing-prototypes] + 1482 | ssize_t hw_lro_stats_write(struct file *file, const char __user *buffer, + | ^~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1501:5: warning: no previous prototype for 'hw_lro_stats_read_v1' [-Wmissing-prototypes] + 1501 | int hw_lro_stats_read_v1(struct seq_file *seq, void *v) + | ^~~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1598:5: warning: no previous prototype for 'hw_lro_stats_read_v2' [-Wmissing-prototypes] + 1598 | int hw_lro_stats_read_v2(struct seq_file *seq, void *v) + | ^~~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1705:5: warning: no previous prototype for 'hw_lro_stats_read_wrapper' [-Wmissing-prototypes] + 1705 | int hw_lro_stats_read_wrapper(struct seq_file *seq, void *v) + | ^~~~~~~~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1730:5: warning: no previous prototype for 'hwlro_agg_cnt_ctrl' [-Wmissing-prototypes] + 1730 | int hwlro_agg_cnt_ctrl(int cnt) + | ^~~~~~~~~~~~~~~~~~ +In file included from /media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:29: +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: In function 'hwlro_agg_cnt_ctrl': +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.h:263:42: error: 'reg_map' undeclared (first use in this function); did you mean 'regmap'? + 263 | #define MTK_LRO_CTRL_DW2_CFG(x) (reg_map->pdma.lro_ring_ctrl_dw1 + 0x4 + (x * 0x40)) + | ^~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.h:118:37: note: in expansion of macro 'MTK_LRO_CTRL_DW2_CFG' + 118 | u32 reg_val1 = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(x)); \ + | ^~~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1736:17: note: in expansion of macro 'SET_PDMA_RXRING_MAX_AGG_CNT' + 1736 | SET_PDMA_RXRING_MAX_AGG_CNT(eth, i, cnt); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.h:263:42: note: each undeclared identifier is reported only once for each function it appears in + 263 | #define MTK_LRO_CTRL_DW2_CFG(x) (reg_map->pdma.lro_ring_ctrl_dw1 + 0x4 + (x * 0x40)) + | ^~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.h:118:37: note: in expansion of macro 'MTK_LRO_CTRL_DW2_CFG' + 118 | u32 reg_val1 = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(x)); \ + | ^~~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1736:17: note: in expansion of macro 'SET_PDMA_RXRING_MAX_AGG_CNT' + 1736 | SET_PDMA_RXRING_MAX_AGG_CNT(eth, i, cnt); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: At top level: +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1741:5: warning: no previous prototype for 'hwlro_agg_time_ctrl' [-Wmissing-prototypes] + 1741 | int hwlro_agg_time_ctrl(int time) + | ^~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: In function 'hwlro_agg_time_ctrl': +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.h:263:42: error: 'reg_map' undeclared (first use in this function); did you mean 'regmap'? + 263 | #define MTK_LRO_CTRL_DW2_CFG(x) (reg_map->pdma.lro_ring_ctrl_dw1 + 0x4 + (x * 0x40)) + | ^~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.h:131:36: note: in expansion of macro 'MTK_LRO_CTRL_DW2_CFG' + 131 | u32 reg_val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(x)); \ + | ^~~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1747:17: note: in expansion of macro 'SET_PDMA_RXRING_AGG_TIME' + 1747 | SET_PDMA_RXRING_AGG_TIME(eth, i, time); + | ^~~~~~~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: At top level: +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1752:5: warning: no previous prototype for 'hwlro_age_time_ctrl' [-Wmissing-prototypes] + 1752 | int hwlro_age_time_ctrl(int time) + | ^~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: In function 'hwlro_age_time_ctrl': +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.h:262:42: error: 'reg_map' undeclared (first use in this function); did you mean 'regmap'? + 262 | #define MTK_LRO_CTRL_DW1_CFG(x) (reg_map->pdma.lro_ring_ctrl_dw1 + (x * 0x40)) + | ^~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.h:139:37: note: in expansion of macro 'MTK_LRO_CTRL_DW1_CFG' + 139 | u32 reg_val1 = mtk_r32(eth, MTK_LRO_CTRL_DW1_CFG(x)); \ + | ^~~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1758:17: note: in expansion of macro 'SET_PDMA_RXRING_AGE_TIME' + 1758 | SET_PDMA_RXRING_AGE_TIME(eth, i, time); + | ^~~~~~~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: At top level: +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1762:5: warning: no previous prototype for 'hwlro_threshold_ctrl' [-Wmissing-prototypes] + 1762 | int hwlro_threshold_ctrl(int bandwidth) + | ^~~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1771:5: warning: no previous prototype for 'hwlro_ring_enable_ctrl' [-Wmissing-prototypes] + 1771 | int hwlro_ring_enable_ctrl(int enable) + | ^~~~~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: In function 'hwlro_ring_enable_ctrl': +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.h:263:42: error: 'reg_map' undeclared (first use in this function); did you mean 'regmap'? + 263 | #define MTK_LRO_CTRL_DW2_CFG(x) (reg_map->pdma.lro_ring_ctrl_dw1 + 0x4 + (x * 0x40)) + | ^~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.h:159:36: note: in expansion of macro 'MTK_LRO_CTRL_DW2_CFG' + 159 | u32 reg_val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(x)); \ + | ^~~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1779:17: note: in expansion of macro 'SET_PDMA_RXRING_VALID' + 1779 | SET_PDMA_RXRING_VALID(eth, i, enable); + | ^~~~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: At top level: +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1784:5: warning: no previous prototype for 'hwlro_stats_enable_ctrl' [-Wmissing-prototypes] + 1784 | int hwlro_stats_enable_ctrl(int enable) + | ^~~~~~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1801:9: warning: no previous prototype for 'hw_lro_auto_tlb_write' [-Wmissing-prototypes] + 1801 | ssize_t hw_lro_auto_tlb_write(struct file *file, const char __user *buffer, + | ^~~~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1839:6: warning: no previous prototype for 'hw_lro_auto_tlb_dump_v1' [-Wmissing-prototypes] + 1839 | void hw_lro_auto_tlb_dump_v1(struct seq_file *seq, u32 index) + | ^~~~~~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1898:6: warning: no previous prototype for 'hw_lro_auto_tlb_dump_v2' [-Wmissing-prototypes] + 1898 | void hw_lro_auto_tlb_dump_v2(struct seq_file *seq, u32 index) + | ^~~~~~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1969:5: warning: no previous prototype for 'hw_lro_auto_tlb_read' [-Wmissing-prototypes] + 1969 | int hw_lro_auto_tlb_read(struct seq_file *seq, void *v) + | ^~~~~~~~~~~~~~~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c: In function 'hw_lro_auto_tlb_read': +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.h:262:42: error: 'reg_map' undeclared (first use in this function); did you mean 'regmap'? + 262 | #define MTK_LRO_CTRL_DW1_CFG(x) (reg_map->pdma.lro_ring_ctrl_dw1 + (x * 0x40)) + | ^~~~~~~ +/media/data_ext/git/kernel/BPI-R2-4.14/drivers/net/ethernet/mediatek/mtk_eth_dbg.c:2009:40: note: in expansion of macro 'MTK_LRO_CTRL_DW1_CFG' + 2009 | reg_op1 = mtk_r32(eth, MTK_LRO_CTRL_DW1_CFG(i)); + | ^~~~~~~~~~~~~~~~~~~~ +make[7]: *** [/media/data_ext/git/kernel/BPI-R2-4.14/scripts/Makefile.build:194: drivers/net/ethernet/mediatek/mtk_eth_dbg.o] Error 1 +make[7]: *** Waiting for unfinished jobs.... +make[6]: *** [/media/data_ext/git/kernel/BPI-R2-4.14/scripts/Makefile.build:440: drivers/net/ethernet/mediatek] Error 2 +make[5]: *** [/media/data_ext/git/kernel/BPI-R2-4.14/scripts/Makefile.build:440: drivers/net/ethernet] Error 2 +make[1]: Leaving directory '/media/data_ext/git/kernel/build' + +fix build-errors/warnings for mtk_eth_dbg + +these are still there: + +In file included from drivers/net/ethernet/mediatek/mtk_eth_dbg.c:29: +drivers/net/ethernet/mediatek/mtk_eth_dbg.c: In function 'hwlro_threshold_ctrl': +drivers/net/ethernet/mediatek/mtk_eth_soc.h:204:34: error: 'reg_map' undeclared (first use in this function); did you mean 'regmap'? + 204 | #define MTK_PDMA_LRO_CTRL_DW2 (reg_map->pdma.lro_ctrl_dw0 + 0x08) + | ^~~~~~~ +drivers/net/ethernet/mediatek/mtk_eth_dbg.h:152:36: note: in expansion of macro 'MTK_PDMA_LRO_CTRL_DW2' + 152 | u32 reg_val = mtk_r32(eth, MTK_PDMA_LRO_CTRL_DW2); \ + | ^~~~~~~~~~~~~~~~~~~~~ +drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1769:9: note: in expansion of macro 'SET_PDMA_LRO_BW_THRESHOLD' + 1769 | SET_PDMA_LRO_BW_THRESHOLD(eth, bandwidth); + | ^~~~~~~~~~~~~~~~~~~~~~~~~ +drivers/net/ethernet/mediatek/mtk_eth_soc.h:204:34: note: each undeclared identifier is reported only once for each function it appears in + 204 | #define MTK_PDMA_LRO_CTRL_DW2 (reg_map->pdma.lro_ctrl_dw0 + 0x08) + | ^~~~~~~ +drivers/net/ethernet/mediatek/mtk_eth_dbg.h:152:36: note: in expansion of macro 'MTK_PDMA_LRO_CTRL_DW2' + 152 | u32 reg_val = mtk_r32(eth, MTK_PDMA_LRO_CTRL_DW2); \ + | ^~~~~~~~~~~~~~~~~~~~~ +drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1769:9: note: in expansion of macro 'SET_PDMA_LRO_BW_THRESHOLD' + 1769 | SET_PDMA_LRO_BW_THRESHOLD(eth, bandwidth); + | ^~~~~~~~~~~~~~~~~~~~~~~~~ +drivers/net/ethernet/mediatek/mtk_eth_dbg.c: In function 'hw_lro_auto_tlb_dump_v1': +drivers/net/ethernet/mediatek/mtk_eth_soc.h:202:34: error: 'reg_map' undeclared (first use in this function); did you mean 'regmap'? + 202 | #define MTK_PDMA_LRO_CTRL_DW0 (reg_map->pdma.lro_ctrl_dw0) + | ^~~~~~~ +drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1868:26: note: in expansion of macro 'MTK_PDMA_LRO_CTRL_DW0' + 1868 | if (mtk_r32(eth, MTK_PDMA_LRO_CTRL_DW0) & MTK_LRO_ALT_PKT_CNT_MODE) + | ^~~~~~~~~~~~~~~~~~~~~ +drivers/net/ethernet/mediatek/mtk_eth_dbg.c: In function 'hw_lro_auto_tlb_dump_v2': +drivers/net/ethernet/mediatek/mtk_eth_soc.h:202:34: error: 'reg_map' undeclared (first use in this function); did you mean 'regmap'? + 202 | #define MTK_PDMA_LRO_CTRL_DW0 (reg_map->pdma.lro_ctrl_dw0) + | ^~~~~~~ +drivers/net/ethernet/mediatek/mtk_eth_dbg.c:1919:26: note: in expansion of macro 'MTK_PDMA_LRO_CTRL_DW0' + 1919 | if (mtk_r32(eth, MTK_PDMA_LRO_CTRL_DW0) & MTK_LRO_ALT_PKT_CNT_MODE) + | ^~~~~~~~~~~~~~~~~~~~~ + +more fixes for mtk_eth_dbg after adding lro code + +net: mediatek: update propritary debugfs + +net: mediatek: add some missing values +--- + drivers/net/ethernet/mediatek/Makefile | 2 +- + drivers/net/ethernet/mediatek/mtk_eth_dbg.c | 2152 +++++++++++++++++++ + drivers/net/ethernet/mediatek/mtk_eth_dbg.h | 335 +++ + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 22 +- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 66 +- + 5 files changed, 2570 insertions(+), 7 deletions(-) + create mode 100644 drivers/net/ethernet/mediatek/mtk_eth_dbg.c + create mode 100644 drivers/net/ethernet/mediatek/mtk_eth_dbg.h + +diff --git a/drivers/net/ethernet/mediatek/Makefile b/drivers/net/ethernet/mediatek/Makefile +index 03e008fbc859..b6b45ce24bd1 100644 +--- a/drivers/net/ethernet/mediatek/Makefile ++++ b/drivers/net/ethernet/mediatek/Makefile +@@ -4,7 +4,7 @@ + # + + obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o +-mtk_eth-y := mtk_eth_soc.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o ++mtk_eth-y := mtk_eth_soc.o mtk_eth_path.o mtk_eth_dbg.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_wed_wo.o + ifdef CONFIG_DEBUG_FS + mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_debugfs.o +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_dbg.c b/drivers/net/ethernet/mediatek/mtk_eth_dbg.c +new file mode 100644 +index 000000000000..28b04d52cb57 +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_eth_dbg.c +@@ -0,0 +1,2152 @@ ++/* ++ * Copyright (C) 2018 MediaTek Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Copyright (C) 2009-2016 John Crispin ++ * Copyright (C) 2009-2016 Felix Fietkau ++ * Copyright (C) 2013-2016 Michael Lee ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "mtk_eth_soc.h" ++#include "mtk_eth_dbg.h" ++#include "mtk_wed_regs.h" ++ ++u32 hw_lro_agg_num_cnt[MTK_MAX_RX_RING_NUM][MTK_HW_LRO_MAX_AGG_CNT + 1]; ++u32 hw_lro_agg_size_cnt[MTK_MAX_RX_RING_NUM][16]; ++u32 hw_lro_tot_agg_cnt[MTK_MAX_RX_RING_NUM]; ++u32 hw_lro_tot_flush_cnt[MTK_MAX_RX_RING_NUM]; ++u32 hw_lro_agg_flush_cnt[MTK_MAX_RX_RING_NUM]; ++u32 hw_lro_age_flush_cnt[MTK_MAX_RX_RING_NUM]; ++u32 hw_lro_seq_flush_cnt[MTK_MAX_RX_RING_NUM]; ++u32 hw_lro_timestamp_flush_cnt[MTK_MAX_RX_RING_NUM]; ++u32 hw_lro_norule_flush_cnt[MTK_MAX_RX_RING_NUM]; ++u32 mtk_hwlro_stats_ebl; ++u32 dbg_show_level; ++ ++static struct proc_dir_entry *proc_hw_lro_stats, *proc_hw_lro_auto_tlb; ++typedef int (*mtk_lro_dbg_func) (int par); ++ ++struct mtk_eth_debug { ++ struct dentry *root; ++ void __iomem *base; ++ int direct_access; ++}; ++ ++struct mtk_eth *g_eth; ++ ++struct mtk_eth_debug eth_debug; ++ ++static ssize_t qdma_sched_show(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct mtk_eth *eth = g_eth; ++ const struct mtk_soc_data *soc = eth->soc; ++ long id = (long)file->private_data; ++ char *buf; ++ unsigned int len = 0, buf_len = 1500; ++ u32 qdma_tx_sch, sch_reg; ++ int enable, scheduling, max_rate, scheduler, i; ++ ssize_t ret_cnt; ++ ++ buf = kzalloc(buf_len, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ if (mtk_is_netsys_v2_or_greater(eth)) ++ qdma_tx_sch = mtk_r32(eth, soc->reg_map->qdma.tx_sch_rate + (id >> 1) * 0x4); ++ else ++ qdma_tx_sch = mtk_r32(eth, soc->reg_map->qdma.tx_sch_rate); ++ ++ if (id & 0x1) ++ qdma_tx_sch >>= 16; ++ ++ qdma_tx_sch &= MTK_QDMA_TX_SCH; ++ enable = FIELD_GET(MTK_QDMA_TX_SCH_RATE_EN, qdma_tx_sch); ++ scheduling = FIELD_GET(MTK_QDMA_TX_SCH_MAX_WFQ, qdma_tx_sch); ++ max_rate = FIELD_GET(MTK_QDMA_TX_SCH_RATE_MAN, qdma_tx_sch); ++ qdma_tx_sch = FIELD_GET(MTK_QDMA_TX_SCH_RATE_EXP, qdma_tx_sch); ++ while (qdma_tx_sch--) ++ max_rate *= 10; ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "EN\tScheduling\tMAX\tQueue#\n%d\t%s%16d\t", enable, ++ (scheduling == 1) ? "WRR" : "SP", max_rate); ++ ++ for (i = 0; i < MTK_QDMA_NUM_QUEUES; i++) { ++ mtk_w32(eth, (i / MTK_QTX_PER_PAGE), soc->reg_map->qdma.page); ++ sch_reg = mtk_r32(eth, soc->reg_map->qdma.qtx_sch + ++ (id % MTK_QTX_PER_PAGE) * MTK_QTX_OFFSET); ++ if (mtk_is_netsys_v2_or_greater(eth)) ++ scheduler = FIELD_GET(MTK_QTX_SCH_TX_SEL_V2, sch_reg); ++ else ++ scheduler = FIELD_GET(MTK_QTX_SCH_TX_SEL, sch_reg); ++ if (id == scheduler) ++ len += scnprintf(buf + len, buf_len - len, "%d ", i); ++ } ++ ++ len += scnprintf(buf + len, buf_len - len, "\n"); ++ if (len > buf_len) ++ len = buf_len; ++ ++ ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ ++ kfree(buf); ++ ++ return ret_cnt; ++} ++ ++static ssize_t qdma_sched_write(struct file *file, const char __user *buf, ++ size_t length, loff_t *offset) ++{ ++ struct mtk_eth *eth = g_eth; ++ const struct mtk_soc_data *soc = eth->soc; ++ long id = (long)file->private_data; ++ char line[64] = {0}, scheduling[32]; ++ int enable, rate, exp = 0, shift = 0; ++ size_t size; ++ u32 qdma_tx_sch, val = 0; ++ ++ if (length >= sizeof(line)) ++ return -EINVAL; ++ ++ if (copy_from_user(line, buf, length)) ++ return -EFAULT; ++ ++ if (sscanf(line, "%1d %3s %9d", &enable, scheduling, &rate) != 3) ++ return -EFAULT; ++ ++ if (mtk_is_netsys_v3_or_greater(eth)) { ++ if (rate > 10000000 || rate < 0) ++ return -EINVAL; ++ } else { ++ if (rate > 1000000 || rate < 0) ++ return -EINVAL; ++ } ++ ++ while (rate > 127) { ++ rate /= 10; ++ exp++; ++ } ++ ++ line[length] = '\0'; ++ ++ if (enable) ++ val |= MTK_QDMA_TX_SCH_RATE_EN; ++ if (strcmp(scheduling, "sp") != 0) ++ val |= MTK_QDMA_TX_SCH_MAX_WFQ; ++ val |= FIELD_PREP(MTK_QDMA_TX_SCH_RATE_MAN, rate); ++ val |= FIELD_PREP(MTK_QDMA_TX_SCH_RATE_EXP, exp); ++ if (id & 0x1) ++ shift = 16; ++ ++ if (mtk_is_netsys_v2_or_greater(eth)) ++ qdma_tx_sch = mtk_r32(eth, soc->reg_map->qdma.tx_sch_rate + (id >> 1) * 0x4); ++ else ++ qdma_tx_sch = mtk_r32(eth, soc->reg_map->qdma.tx_sch_rate); ++ ++ qdma_tx_sch &= ~(MTK_QDMA_TX_SCH << shift); ++ qdma_tx_sch |= val << shift; ++ if (mtk_is_netsys_v2_or_greater(eth)) ++ mtk_w32(eth, qdma_tx_sch, soc->reg_map->qdma.tx_sch_rate + (id >> 1) * 0x4); ++ else ++ mtk_w32(eth, qdma_tx_sch, soc->reg_map->qdma.tx_sch_rate); ++ ++ size = strlen(line); ++ *offset += size; ++ ++ return length; ++} ++ ++static const struct file_operations qdma_sched_fops = { ++ .open = simple_open, ++ .read = qdma_sched_show, ++ .write = qdma_sched_write, ++ .llseek = default_llseek, ++}; ++ ++static ssize_t qdma_queue_show(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct mtk_eth *eth = g_eth; ++ const struct mtk_soc_data *soc = eth->soc; ++ long id = (long)file->private_data; ++ char *buf; ++ unsigned int len = 0, buf_len = 1500; ++ u32 qtx_sch, qtx_cfg; ++ int scheduler; ++ int min_rate_en, min_rate, min_rate_exp; ++ int max_rate_en, max_weight, max_rate, max_rate_exp; ++ ssize_t ret_cnt; ++ ++ buf = kzalloc(buf_len, GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ mtk_w32(eth, (id / MTK_QTX_PER_PAGE), soc->reg_map->qdma.page); ++ qtx_cfg = mtk_r32(eth, soc->reg_map->qdma.qtx_cfg + ++ (id % MTK_QTX_PER_PAGE) * MTK_QTX_OFFSET); ++ qtx_sch = mtk_r32(eth, soc->reg_map->qdma.qtx_sch + ++ (id % MTK_QTX_PER_PAGE) * MTK_QTX_OFFSET); ++ if (mtk_is_netsys_v2_or_greater(eth)) ++ scheduler = FIELD_GET(MTK_QTX_SCH_TX_SEL_V2, qtx_sch); ++ else ++ scheduler = FIELD_GET(MTK_QTX_SCH_TX_SEL, qtx_sch); ++ ++ min_rate_en = FIELD_GET(MTK_QTX_SCH_MIN_RATE_EN, qtx_sch); ++ min_rate = FIELD_GET(MTK_QTX_SCH_MIN_RATE_MAN, qtx_sch); ++ min_rate_exp = FIELD_GET(MTK_QTX_SCH_MIN_RATE_EXP, qtx_sch); ++ max_rate_en = FIELD_GET(MTK_QTX_SCH_MAX_RATE_EN, qtx_sch); ++ max_weight = FIELD_GET(MTK_QTX_SCH_MAX_RATE_WEIGHT, qtx_sch); ++ max_rate = FIELD_GET(MTK_QTX_SCH_MAX_RATE_MAN, qtx_sch); ++ max_rate_exp = FIELD_GET(MTK_QTX_SCH_MAX_RATE_EXP, qtx_sch); ++ ++ while (min_rate_exp--) ++ min_rate *= 10; ++ ++ while (max_rate_exp--) ++ max_rate *= 10; ++ ++ len += scnprintf(buf + len, buf_len - len, ++ "scheduler: %d\nhw resv: %d\nsw resv: %d\n", scheduler, ++ (qtx_cfg >> 8) & 0xff, qtx_cfg & 0xff); ++ ++ if (mtk_is_netsys_v2_or_greater(eth)) { ++ /* Switch to debug mode */ ++ mtk_m32(eth, MTK_MIB_ON_QTX_CFG, MTK_MIB_ON_QTX_CFG, soc->reg_map->qdma.qtx_mib_if); ++ mtk_m32(eth, MTK_VQTX_MIB_EN, MTK_VQTX_MIB_EN, soc->reg_map->qdma.qtx_mib_if); ++ qtx_cfg = mtk_r32(eth, soc->reg_map->qdma.qtx_cfg + ++ (id % MTK_QTX_PER_PAGE) * MTK_QTX_OFFSET); ++ qtx_sch = mtk_r32(eth, soc->reg_map->qdma.qtx_sch + ++ (id % MTK_QTX_PER_PAGE) * MTK_QTX_OFFSET); ++ len += scnprintf(buf + len, buf_len - len, ++ "packet count: %u\n", qtx_cfg); ++ len += scnprintf(buf + len, buf_len - len, ++ "packet drop: %u\n\n", qtx_sch); ++ ++ /* Recover to normal mode */ ++ mtk_m32(eth, MTK_MIB_ON_QTX_CFG, 0, soc->reg_map->qdma.qtx_mib_if); ++ mtk_m32(eth, MTK_VQTX_MIB_EN, 0, soc->reg_map->qdma.qtx_mib_if); ++ } ++ ++ len += scnprintf(buf + len, buf_len - len, ++ " EN RATE WEIGHT\n"); ++ len += scnprintf(buf + len, buf_len - len, ++ "----------------------------\n"); ++ len += scnprintf(buf + len, buf_len - len, ++ "max%5d%9d%9d\n", max_rate_en, max_rate, max_weight); ++ len += scnprintf(buf + len, buf_len - len, ++ "min%5d%9d -\n", min_rate_en, min_rate); ++ ++ if (len > buf_len) ++ len = buf_len; ++ ++ ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); ++ ++ kfree(buf); ++ ++ return ret_cnt; ++} ++ ++static ssize_t qdma_queue_write(struct file *file, const char __user *buf, ++ size_t length, loff_t *offset) ++{ ++ struct mtk_eth *eth = g_eth; ++ const struct mtk_soc_data *soc = eth->soc; ++ long id = (long)file->private_data; ++ char line[64] = {0}; ++ int max_enable, max_rate, max_exp = 0; ++ int min_enable, min_rate, min_exp = 0; ++ int weight; ++ int resv; ++ int scheduler; ++ size_t size; ++ u32 qtx_sch = 0, qtx_cfg = 0; ++ ++ mtk_w32(eth, (id / MTK_QTX_PER_PAGE), soc->reg_map->qdma.page); ++ if (length >= sizeof(line)) ++ return -EINVAL; ++ ++ if (copy_from_user(line, buf, length)) ++ return -EFAULT; ++ ++ if (sscanf(line, "%d %d %d %d %d %d %d", &scheduler, &min_enable, &min_rate, ++ &max_enable, &max_rate, &weight, &resv) != 7) ++ return -EFAULT; ++ ++ line[length] = '\0'; ++ ++ if (mtk_is_netsys_v2_or_greater(eth)) { ++ if (max_rate > 10000000 || max_rate < 0 || ++ min_rate > 10000000 || min_rate < 0) ++ return -EINVAL; ++ } else { ++ if (max_rate > 1000000 || max_rate < 0 || ++ min_rate > 1000000 || min_rate < 0) ++ return -EINVAL; ++ } ++ ++ while (max_rate > 127) { ++ max_rate /= 10; ++ max_exp++; ++ } ++ ++ while (min_rate > 127) { ++ min_rate /= 10; ++ min_exp++; ++ } ++ ++ if (mtk_is_netsys_v2_or_greater(eth)) ++ qtx_sch |= FIELD_PREP(MTK_QTX_SCH_TX_SEL_V2, scheduler); ++ else ++ qtx_sch |= FIELD_PREP(MTK_QTX_SCH_TX_SEL, scheduler); ++ ++ if (min_enable) ++ qtx_sch |= MTK_QTX_SCH_MIN_RATE_EN; ++ qtx_sch |= FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, min_rate); ++ qtx_sch |= FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, min_exp); ++ if (max_enable) ++ qtx_sch |= MTK_QTX_SCH_MAX_RATE_EN; ++ qtx_sch |= FIELD_PREP(MTK_QTX_SCH_MAX_RATE_WEIGHT, weight); ++ qtx_sch |= FIELD_PREP(MTK_QTX_SCH_MAX_RATE_MAN, max_rate); ++ qtx_sch |= FIELD_PREP(MTK_QTX_SCH_MAX_RATE_EXP, max_exp); ++ mtk_w32(eth, qtx_sch, soc->reg_map->qdma.qtx_sch + ++ (id % MTK_QTX_PER_PAGE) * MTK_QTX_OFFSET); ++ ++ qtx_cfg = mtk_r32(eth, soc->reg_map->qdma.qtx_cfg + ++ (id % MTK_QTX_PER_PAGE) * MTK_QTX_OFFSET); ++ qtx_cfg &= 0xffff0000; ++ qtx_cfg |= FIELD_PREP(MTK_QTX_CFG_HW_RESV, resv); ++ qtx_cfg |= FIELD_PREP(MTK_QTX_CFG_SW_RESV, resv); ++ mtk_w32(eth, qtx_cfg, soc->reg_map->qdma.qtx_cfg + ++ (id % MTK_QTX_PER_PAGE) * MTK_QTX_OFFSET); ++ ++ size = strlen(line); ++ *offset += size; ++ ++ return length; ++} ++ ++static const struct file_operations qdma_queue_fops = { ++ .open = simple_open, ++ .read = qdma_queue_show, ++ .write = qdma_queue_write, ++ .llseek = default_llseek, ++}; ++ ++static int mt798x_iomap(void) ++{ ++ struct device_node *np = NULL; ++ ++ np = of_find_node_by_name(NULL, "switch0"); ++ if (np) { ++ eth_debug.base = of_iomap(np, 0); ++ if (!eth_debug.base) { ++ pr_err("of_iomap failed\n"); ++ of_node_put(np); ++ return -ENOMEM; ++ } ++ ++ of_node_put(np); ++ eth_debug.direct_access = 1; ++ } ++ ++ return 0; ++} ++ ++static int mt798x_iounmap(void) ++{ ++ eth_debug.direct_access = 0; ++ if (eth_debug.base) ++ iounmap(eth_debug.base); ++ ++ return 0; ++} ++ ++static void mt7530_mdio_w32(struct mtk_eth *eth, u16 reg, u32 val) ++{ ++ mutex_lock(ð->mii_bus->mdio_lock); ++ ++ if (eth_debug.direct_access) ++ __raw_writel(val, eth_debug.base + reg); ++ else { ++ _mtk_mdio_write_c22(eth, 0x1f, 0x1f, (reg >> 6) & 0x3ff); ++ _mtk_mdio_write_c22(eth, 0x1f, (reg >> 2) & 0xf, val & 0xffff); ++ _mtk_mdio_write_c22(eth, 0x1f, 0x10, val >> 16); ++ } ++ ++ mutex_unlock(ð->mii_bus->mdio_lock); ++} ++ ++static u32 mt7530_mdio_r32(struct mtk_eth *eth, u32 reg) ++{ ++ u16 high, low; ++ u32 ret; ++ ++ mutex_lock(ð->mii_bus->mdio_lock); ++ ++ if (eth_debug.direct_access) { ++ ret = __raw_readl(eth_debug.base + reg); ++ mutex_unlock(ð->mii_bus->mdio_lock); ++ return ret; ++ } ++ _mtk_mdio_write_c22(eth, 0x1f, 0x1f, (reg >> 6) & 0x3ff); ++ low = _mtk_mdio_read_c22(eth, 0x1f, (reg >> 2) & 0xf); ++ high = _mtk_mdio_read_c22(eth, 0x1f, 0x10); ++ ++ mutex_unlock(ð->mii_bus->mdio_lock); ++ ++ return (high << 16) | (low & 0xffff); ++} ++ ++void mtk_switch_w32(struct mtk_eth *eth, u32 val, unsigned int reg) ++{ ++ mtk_w32(eth, val, reg + 0x10000); ++} ++EXPORT_SYMBOL(mtk_switch_w32); ++ ++u32 mtk_switch_r32(struct mtk_eth *eth, unsigned int reg) ++{ ++ return mtk_r32(eth, reg + 0x10000); ++} ++EXPORT_SYMBOL(mtk_switch_r32); ++ ++static int mtketh_debug_show(struct seq_file *m, void *private) ++{ ++ struct mtk_eth *eth = m->private; ++ struct mtk_mac *mac = 0; ++ int i = 0; ++ ++ for (i = 0 ; i < MTK_MAX_DEVS ; i++) { ++ if (!eth->mac[i] || ++ of_phy_is_fixed_link(eth->mac[i]->of_node)) ++ continue; ++ mac = eth->mac[i]; ++/* FIXME */ ++/* ++ while (j < 30) { ++ d = _mtk_mdio_read_c22(eth, mac->phy_dev->addr, j); ++ ++ seq_printf(m, "phy=%d, reg=0x%08x, data=0x%08x\n", ++ mac->phy_dev->addr, j, d); ++ j++; ++ } ++*/ ++ } ++ return 0; ++} ++ ++static int mtketh_debug_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, mtketh_debug_show, inode->i_private); ++} ++ ++static const struct file_operations mtketh_debug_fops = { ++ .owner = THIS_MODULE, ++ .open = mtketh_debug_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int mtketh_mt7530sw_debug_show(struct seq_file *m, void *private) ++{ ++ struct mtk_eth *eth = m->private; ++ u32 offset, data; ++ int i; ++ struct mt7530_ranges { ++ u32 start; ++ u32 end; ++ } ranges[] = { ++ {0x0, 0xac}, ++ {0x1000, 0x10e0}, ++ {0x1100, 0x1140}, ++ {0x1200, 0x1240}, ++ {0x1300, 0x1340}, ++ {0x1400, 0x1440}, ++ {0x1500, 0x1540}, ++ {0x1600, 0x1640}, ++ {0x1800, 0x1848}, ++ {0x1900, 0x1948}, ++ {0x1a00, 0x1a48}, ++ {0x1b00, 0x1b48}, ++ {0x1c00, 0x1c48}, ++ {0x1d00, 0x1d48}, ++ {0x1e00, 0x1e48}, ++ {0x1f60, 0x1ffc}, ++ {0x2000, 0x212c}, ++ {0x2200, 0x222c}, ++ {0x2300, 0x232c}, ++ {0x2400, 0x242c}, ++ {0x2500, 0x252c}, ++ {0x2600, 0x262c}, ++ {0x3000, 0x3014}, ++ {0x30c0, 0x30f8}, ++ {0x3100, 0x3114}, ++ {0x3200, 0x3214}, ++ {0x3300, 0x3314}, ++ {0x3400, 0x3414}, ++ {0x3500, 0x3514}, ++ {0x3600, 0x3614}, ++ {0x4000, 0x40d4}, ++ {0x4100, 0x41d4}, ++ {0x4200, 0x42d4}, ++ {0x4300, 0x43d4}, ++ {0x4400, 0x44d4}, ++ {0x4500, 0x45d4}, ++ {0x4600, 0x46d4}, ++ {0x4f00, 0x461c}, ++ {0x7000, 0x7038}, ++ {0x7120, 0x7124}, ++ {0x7800, 0x7804}, ++ {0x7810, 0x7810}, ++ {0x7830, 0x7830}, ++ {0x7a00, 0x7a7c}, ++ {0x7b00, 0x7b04}, ++ {0x7e00, 0x7e04}, ++ {0x7ffc, 0x7ffc}, ++ }; ++ ++ if (!mt7530_exist(eth)) ++ return -EOPNOTSUPP; ++ ++ if ((!eth->mac[0] || !of_phy_is_fixed_link(eth->mac[0]->of_node)) && ++ (!eth->mac[1] || !of_phy_is_fixed_link(eth->mac[1]->of_node))) { ++ seq_puts(m, "no switch found\n"); ++ return 0; ++ } ++ ++ for (i = 0 ; i < ARRAY_SIZE(ranges) ; i++) { ++ for (offset = ranges[i].start; ++ offset <= ranges[i].end; offset += 4) { ++ data = mt7530_mdio_r32(eth, offset); ++ seq_printf(m, "mt7530 switch reg=0x%08x, data=0x%08x\n", ++ offset, data); ++ } ++ } ++ ++ return 0; ++} ++ ++static int mtketh_debug_mt7530sw_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, mtketh_mt7530sw_debug_show, inode->i_private); ++} ++ ++static const struct file_operations mtketh_debug_mt7530sw_fops = { ++ .owner = THIS_MODULE, ++ .open = mtketh_debug_mt7530sw_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static ssize_t mtketh_mt7530sw_debugfs_write(struct file *file, ++ const char __user *ptr, ++ size_t len, loff_t *off) ++{ ++ struct mtk_eth *eth = file->private_data; ++ char buf[32], *token, *p = buf; ++ unsigned long reg, value, phy; ++ int ret; ++ ++ if (!mt7530_exist(eth)) ++ return -EOPNOTSUPP; ++ ++ if (*off != 0) ++ return 0; ++ ++ if (len > sizeof(buf) - 1) ++ len = sizeof(buf) - 1; ++ ++ ret = strncpy_from_user(buf, ptr, len); ++ if (ret < 0) ++ return ret; ++ buf[len] = '\0'; ++ ++ token = strsep(&p, " "); ++ if (!token) ++ return -EINVAL; ++ if (kstrtoul(token, 16, (unsigned long *)&phy)) ++ return -EINVAL; ++ ++ token = strsep(&p, " "); ++ if (!token) ++ return -EINVAL; ++ if (kstrtoul(token, 16, (unsigned long *)®)) ++ return -EINVAL; ++ ++ token = strsep(&p, " "); ++ if (!token) ++ return -EINVAL; ++ if (kstrtoul(token, 16, (unsigned long *)&value)) ++ return -EINVAL; ++ ++ pr_info("%s:phy=%d, reg=0x%lx, val=0x%lx\n", __func__, ++ 0x1f, reg, value); ++ mt7530_mdio_w32(eth, reg, value); ++ pr_info("%s:phy=%d, reg=0x%lx, val=0x%x confirm..\n", __func__, ++ 0x1f, reg, mt7530_mdio_r32(eth, reg)); ++ ++ return len; ++} ++ ++static ssize_t mtketh_debugfs_write(struct file *file, const char __user *ptr, ++ size_t len, loff_t *off) ++{ ++ struct mtk_eth *eth = file->private_data; ++ char buf[32], *token, *p = buf; ++ unsigned long reg, value, phy; ++ int ret; ++ ++ if (*off != 0) ++ return 0; ++ ++ if (len > sizeof(buf) - 1) ++ len = sizeof(buf) - 1; ++ ++ ret = strncpy_from_user(buf, ptr, len); ++ if (ret < 0) ++ return ret; ++ buf[len] = '\0'; ++ ++ token = strsep(&p, " "); ++ if (!token) ++ return -EINVAL; ++ if (kstrtoul(token, 16, (unsigned long *)&phy)) ++ return -EINVAL; ++ ++ token = strsep(&p, " "); ++ ++ if (!token) ++ return -EINVAL; ++ if (kstrtoul(token, 16, (unsigned long *)®)) ++ return -EINVAL; ++ ++ token = strsep(&p, " "); ++ ++ if (!token) ++ return -EINVAL; ++ if (kstrtoul(token, 16, (unsigned long *)&value)) ++ return -EINVAL; ++ ++ pr_info("%s:phy=%ld, reg=0x%lx, val=0x%lx\n", __func__, ++ phy, reg, value); ++ ++ _mtk_mdio_write_c22(eth, phy, reg, value); ++ ++ pr_info("%s:phy=%ld, reg=0x%lx, val=0x%x confirm..\n", __func__, ++ phy, reg, _mtk_mdio_read_c22(eth, phy, reg)); ++ ++ return len; ++} ++ ++static ssize_t mtketh_debugfs_reset(struct file *file, const char __user *ptr, ++ size_t len, loff_t *off) ++{ ++ struct mtk_eth *eth = file->private_data; ++ unsigned long dbg_level = 0; ++ char buf[8] = ""; ++ int count = len; ++ ++ len = min((size_t)count, sizeof(buf) - 1); ++ if (copy_from_user(buf, ptr, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ if (kstrtoul(buf, 0, &dbg_level)) ++ return -EINVAL; ++ ++ switch (dbg_level) { ++ case 0: ++ atomic_set(ð->reset.force, 0); ++ break; ++ case 1: ++ if (atomic_read(ð->reset.force)) ++ schedule_work(ð->pending_work); ++ else ++ pr_info(" stat:disable\n"); ++ break; ++ case 2: ++ atomic_set(ð->reset.force, 1); ++ break; ++ default: ++ pr_info("Usage: echo [level] > /sys/kernel/debug/mtketh/reset\n"); ++ pr_info("Commands: [level]\n"); ++ pr_info(" 0 disable FE force reset\n"); ++ pr_info(" 1 trigger FE and WDMA force reset\n"); ++ pr_info(" 2 enable FE force reset\n"); ++ break; ++ } ++ ++ return count; ++} ++ ++static const struct file_operations fops_reg_w = { ++ .owner = THIS_MODULE, ++ .open = simple_open, ++ .write = mtketh_debugfs_write, ++ .llseek = noop_llseek, ++}; ++ ++static const struct file_operations fops_eth_reset = { ++ .owner = THIS_MODULE, ++ .open = simple_open, ++ .write = mtketh_debugfs_reset, ++ .llseek = noop_llseek, ++}; ++ ++static const struct file_operations fops_mt7530sw_reg_w = { ++ .owner = THIS_MODULE, ++ .open = simple_open, ++ .write = mtketh_mt7530sw_debugfs_write, ++ .llseek = noop_llseek, ++}; ++ ++void mtketh_debugfs_exit(struct mtk_eth *eth) ++{ ++ debugfs_remove_recursive(eth_debug.root); ++} ++ ++int mtketh_debugfs_init(struct mtk_eth *eth) ++{ ++ char name[16]; ++ int i, ret = 0; ++ ++ eth_debug.root = debugfs_create_dir("mtketh", NULL); ++ if (!eth_debug.root) { ++ dev_notice(eth->dev, "%s:err at %d\n", __func__, __LINE__); ++ ret = -ENOMEM; ++ } ++ ++ debugfs_create_file("phy_regs", 0444, ++ eth_debug.root, eth, &mtketh_debug_fops); ++ debugfs_create_file("phy_reg_w", 0200, ++ eth_debug.root, eth, &fops_reg_w); ++ debugfs_create_file("reset", 0444, ++ eth_debug.root, eth, &fops_eth_reset); ++ if (mt7530_exist(eth)) { ++ debugfs_create_file("mt7530sw_regs", 0444, ++ eth_debug.root, eth, ++ &mtketh_debug_mt7530sw_fops); ++ debugfs_create_file("mt7530sw_reg_w", 0200, ++ eth_debug.root, eth, ++ &fops_mt7530sw_reg_w); ++ } ++ ++ for (i = 0; i < (mtk_is_netsys_v2_or_greater(eth) ? 4 : 2); i++) { ++ ret = snprintf(name, sizeof(name), "qdma_sch%d", i); ++ if (ret != strlen(name)) { ++ ret = -ENOMEM; ++ goto err; ++ } ++ debugfs_create_file(name, 0444, eth_debug.root, (void *)(uintptr_t)i, ++ &qdma_sched_fops); ++ } ++ ++ for (i = 0; i < MTK_QDMA_NUM_QUEUES; i++) { ++ ret = snprintf(name, sizeof(name), "qdma_txq%d", i); ++ if (ret != strlen(name)) { ++ ret = -ENOMEM; ++ goto err; ++ } ++ debugfs_create_file(name, 0444, eth_debug.root, (void *)(uintptr_t)i, ++ &qdma_queue_fops); ++ } ++ ++ return 0; ++ ++err: ++ debugfs_remove_recursive(eth_debug.root); ++ return ret; ++} ++ ++static void mii_mgr_read_combine(struct mtk_eth *eth, u32 phy_addr, u32 phy_register, ++ u32 *read_data) ++{ ++ if (mt7530_exist(eth) && phy_addr == 31) ++ *read_data = mt7530_mdio_r32(eth, phy_register); ++ ++ else ++ *read_data = mdiobus_read(eth->mii_bus, phy_addr, phy_register); ++} ++ ++static void mii_mgr_write_combine(struct mtk_eth *eth, u16 phy_addr, u16 phy_register, ++ u32 write_data) ++{ ++ if (mt7530_exist(eth) && phy_addr == 31) ++ mt7530_mdio_w32(eth, phy_register, write_data); ++ ++ else ++ mdiobus_write(eth->mii_bus, phy_addr, phy_register, write_data); ++} ++ ++static void mii_mgr_read_cl45(struct mtk_eth *eth, u16 port, u16 devad, u16 reg, u16 *data) ++{ ++ *data = mdiobus_c45_read(eth->mii_bus, port, devad, reg); ++} ++ ++static void mii_mgr_write_cl45(struct mtk_eth *eth, u16 port, u16 devad, u16 reg, u16 data) ++{ ++ mdiobus_c45_write(eth->mii_bus, port, devad, reg, data); ++} ++ ++int mtk_do_priv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ++{ ++ struct mtk_mac *mac = netdev_priv(dev); ++ struct mtk_eth *eth = mac->hw; ++ struct mtk_mii_ioctl_data mii; ++ struct mtk_esw_reg reg; ++ u16 val; ++ ++ switch (cmd) { ++ case MTKETH_MII_READ: ++ if (copy_from_user(&mii, ifr->ifr_data, sizeof(mii))) ++ goto err_copy; ++ mii_mgr_read_combine(eth, mii.phy_id, mii.reg_num, ++ &mii.val_out); ++ if (copy_to_user(ifr->ifr_data, &mii, sizeof(mii))) ++ goto err_copy; ++ ++ return 0; ++ case MTKETH_MII_WRITE: ++ if (copy_from_user(&mii, ifr->ifr_data, sizeof(mii))) ++ goto err_copy; ++ mii_mgr_write_combine(eth, mii.phy_id, mii.reg_num, ++ mii.val_in); ++ return 0; ++ case MTKETH_MII_READ_CL45: ++ if (copy_from_user(&mii, ifr->ifr_data, sizeof(mii))) ++ goto err_copy; ++ mii_mgr_read_cl45(eth, ++ mdio_phy_id_prtad(mii.phy_id), ++ mdio_phy_id_devad(mii.phy_id), ++ mii.reg_num, ++ &val); ++ mii.val_out = val; ++ if (copy_to_user(ifr->ifr_data, &mii, sizeof(mii))) ++ goto err_copy; ++ ++ return 0; ++ case MTKETH_MII_WRITE_CL45: ++ if (copy_from_user(&mii, ifr->ifr_data, sizeof(mii))) ++ goto err_copy; ++ val = mii.val_in; ++ mii_mgr_write_cl45(eth, ++ mdio_phy_id_prtad(mii.phy_id), ++ mdio_phy_id_devad(mii.phy_id), ++ mii.reg_num, ++ val); ++ return 0; ++ case MTKETH_ESW_REG_READ: ++ if (!mt7530_exist(eth)) ++ return -EOPNOTSUPP; ++ if (copy_from_user(®, ifr->ifr_data, sizeof(reg))) ++ goto err_copy; ++ if (reg.off > REG_ESW_MAX) ++ return -EINVAL; ++ reg.val = mtk_switch_r32(eth, reg.off); ++ ++ if (copy_to_user(ifr->ifr_data, ®, sizeof(reg))) ++ goto err_copy; ++ ++ return 0; ++ case MTKETH_ESW_REG_WRITE: ++ if (!mt7530_exist(eth)) ++ return -EOPNOTSUPP; ++ if (copy_from_user(®, ifr->ifr_data, sizeof(reg))) ++ goto err_copy; ++ if (reg.off > REG_ESW_MAX) ++ return -EINVAL; ++ mtk_switch_w32(eth, reg.val, reg.off); ++ ++ return 0; ++ default: ++ break; ++ } ++ ++ return -EOPNOTSUPP; ++err_copy: ++ return -EFAULT; ++} ++ ++static void gdm_reg_dump_v3(struct mtk_eth *eth, u32 gdm_id, u32 mib_base) ++{ ++ pr_info("| GDMA%d_RX_GBCNT : %010u (Rx Good Bytes) |\n", ++ gdm_id, mtk_r32(eth, mib_base)); ++ pr_info("| GDMA%d_RX_GPCNT : %010u (Rx Good Pkts) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x08)); ++ pr_info("| GDMA%d_RX_OERCNT : %010u (overflow error) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x10)); ++ pr_info("| GDMA%d_RX_FERCNT : %010u (FCS error) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x14)); ++ pr_info("| GDMA%d_RX_SERCNT : %010u (too short) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x18)); ++ pr_info("| GDMA%d_RX_LERCNT : %010u (too long) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x1C)); ++ pr_info("| GDMA%d_RX_CERCNT : %010u (checksum error) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x20)); ++ pr_info("| GDMA%d_RX_FCCNT : %010u (flow control) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x24)); ++ pr_info("| GDMA%d_RX_VDPCNT : %010u (VID drop) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x28)); ++ pr_info("| GDMA%d_RX_PFCCNT : %010u (priority flow control)\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x2C)); ++ pr_info("| GDMA%d_TX_GBCNT : %010u (Tx Good Bytes) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x40)); ++ pr_info("| GDMA%d_TX_GPCNT : %010u (Tx Good Pkts) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x48)); ++ pr_info("| GDMA%d_TX_SKIPCNT: %010u (abort count) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x50)); ++ pr_info("| GDMA%d_TX_COLCNT : %010u (collision count)|\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x54)); ++ pr_info("| GDMA%d_TX_OERCNT : %010u (overflow error) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x58)); ++ pr_info("| GDMA%d_TX_FCCNT : %010u (flow control) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x60)); ++ pr_info("| GDMA%d_TX_PFCCNT : %010u (priority flow control)\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x64)); ++ pr_info("| |\n"); ++} ++ ++static void gdm_reg_dump_v2(struct mtk_eth *eth, u32 gdm_id, u32 mib_base) ++{ ++ pr_info("| GDMA%d_RX_GBCNT : %010u (Rx Good Bytes) |\n", ++ gdm_id, mtk_r32(eth, mib_base)); ++ pr_info("| GDMA%d_RX_GPCNT : %010u (Rx Good Pkts) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x08)); ++ pr_info("| GDMA%d_RX_OERCNT : %010u (overflow error) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x10)); ++ pr_info("| GDMA%d_RX_FERCNT : %010u (FCS error) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x14)); ++ pr_info("| GDMA%d_RX_SERCNT : %010u (too short) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x18)); ++ pr_info("| GDMA%d_RX_LERCNT : %010u (too long) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x1C)); ++ pr_info("| GDMA%d_RX_CERCNT : %010u (checksum error) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x20)); ++ pr_info("| GDMA%d_RX_FCCNT : %010u (flow control) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x24)); ++ pr_info("| GDMA%d_TX_SKIPCNT: %010u (abort count) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x28)); ++ pr_info("| GDMA%d_TX_COLCNT : %010u (collision count) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x2C)); ++ pr_info("| GDMA%d_TX_GBCNT : %010u (Tx Good Bytes) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x30)); ++ pr_info("| GDMA%d_TX_GPCNT : %010u (Tx Good Pkts) |\n", ++ gdm_id, mtk_r32(eth, mib_base + 0x38)); ++ pr_info("| |\n"); ++} ++ ++static void gdm_cnt_read(struct mtk_eth *eth) ++{ ++ const struct mtk_reg_map *reg_map = eth->soc->reg_map; ++ struct mtk_hw_stats *hw_stats; ++ u32 i, mib_base; ++ ++ pr_info("\n <>\n"); ++ pr_info(" |\n"); ++ pr_info("+-----------------------------------------------+\n"); ++ pr_info("| <> |\n"); ++ pr_info("+-----------------------------------------------+\n"); ++ pr_info(" |\n"); ++ pr_info("+-----------------------------------------------+\n"); ++ pr_info("| <> |\n"); ++ ++ for (i = 0; i < MTK_MAX_DEVS; i++) { ++ if (!eth->mac[i] || !eth->mac[i]->hw_stats) ++ continue; ++ ++ hw_stats = eth->mac[i]->hw_stats; ++ ++ mib_base = reg_map->gdm1_cnt + hw_stats->reg_offset * i; ++ ++ if (mtk_is_netsys_v3_or_greater(eth)) ++ gdm_reg_dump_v3(eth, i + 1, mib_base); ++ else ++ gdm_reg_dump_v2(eth, i + 1, mib_base); ++ } ++ ++ pr_info("+-----------------------------------------------+\n"); ++} ++ ++static void dump_each_port(struct seq_file *seq, struct mtk_eth *eth, u32 base) ++{ ++ u32 pkt_cnt = 0; ++ int i = 0; ++ ++ for (i = 0; i < 7; i++) { ++ if (mtk_is_netsys_v3_or_greater(eth)) { ++ if ((base == 0x402C) && (i == 6)) ++ base = 0x408C; ++ else if ((base == 0x408C) && (i == 6)) ++ base = 0x402C; ++ else { ++ }; ++ } ++ pkt_cnt = mt7530_mdio_r32(eth, (base) + (i * 0x100)); ++ seq_printf(seq, "%8u ", pkt_cnt); ++ } ++ seq_puts(seq, "\n"); ++} ++ ++static int esw_cnt_read(struct seq_file *seq, void *v) ++{ ++ struct mtk_eth *eth = g_eth; ++ ++ gdm_cnt_read(eth); ++ ++ if (!mt7530_exist(eth)) ++ return 0; ++ ++ mt798x_iomap(); ++ ++ seq_printf(seq, "===================== %8s %8s %8s %8s %8s %8s %8s\n", ++ "Port0", "Port1", "Port2", "Port3", "Port4", "Port5", ++ "Port6"); ++ seq_puts(seq, "Tx Drop Packet :"); ++ dump_each_port(seq, eth, 0x4000); ++ seq_puts(seq, "Tx CRC Error :"); ++ dump_each_port(seq, eth, 0x4004); ++ seq_puts(seq, "Tx Unicast Packet :"); ++ dump_each_port(seq, eth, 0x4008); ++ seq_puts(seq, "Tx Multicast Packet :"); ++ dump_each_port(seq, eth, 0x400C); ++ seq_puts(seq, "Tx Broadcast Packet :"); ++ dump_each_port(seq, eth, 0x4010); ++ seq_puts(seq, "Tx Collision Event :"); ++ dump_each_port(seq, eth, 0x4014); ++ seq_puts(seq, "Tx Pause Packet :"); ++ dump_each_port(seq, eth, 0x402C); ++ seq_puts(seq, "Rx Drop Packet :"); ++ dump_each_port(seq, eth, 0x4060); ++ seq_puts(seq, "Rx Filtering Packet :"); ++ dump_each_port(seq, eth, 0x4064); ++ seq_puts(seq, "Rx Unicast Packet :"); ++ dump_each_port(seq, eth, 0x4068); ++ seq_puts(seq, "Rx Multicast Packet :"); ++ dump_each_port(seq, eth, 0x406C); ++ seq_puts(seq, "Rx Broadcast Packet :"); ++ dump_each_port(seq, eth, 0x4070); ++ seq_puts(seq, "Rx Alignment Error :"); ++ dump_each_port(seq, eth, 0x4074); ++ seq_puts(seq, "Rx CRC Error :"); ++ dump_each_port(seq, eth, 0x4078); ++ seq_puts(seq, "Rx Undersize Error :"); ++ dump_each_port(seq, eth, 0x407C); ++ seq_puts(seq, "Rx Fragment Error :"); ++ dump_each_port(seq, eth, 0x4080); ++ seq_puts(seq, "Rx Oversize Error :"); ++ dump_each_port(seq, eth, 0x4084); ++ seq_puts(seq, "Rx Jabber Error :"); ++ dump_each_port(seq, eth, 0x4088); ++ seq_puts(seq, "Rx Pause Packet :"); ++ dump_each_port(seq, eth, 0x408C); ++ mt7530_mdio_w32(eth, 0x4fe0, 0xf0); ++ mt7530_mdio_w32(eth, 0x4fe0, 0x800000f0); ++ ++ seq_puts(seq, "\n"); ++ ++ mt798x_iounmap(); ++ ++ return 0; ++} ++ ++static int switch_count_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, esw_cnt_read, 0); ++} ++ ++static const struct proc_ops switch_count_fops = { ++ .proc_open = switch_count_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release ++}; ++ ++static void xfi_mib_dump(struct seq_file *seq, u32 gdm_id) ++{ ++ struct mtk_eth *eth = g_eth; ++ ++ PRINT_FORMATTED_XFI_MIB(seq, TX_PKT_CNT, GENMASK(31, 0)); ++ PRINT_FORMATTED_XFI_MIB(seq, TX_ETH_CNT, GENMASK(31, 0)); ++ PRINT_FORMATTED_XFI_MIB(seq, TX_PAUSE_CNT, GENMASK(15, 0)); ++ PRINT_FORMATTED_XFI_MIB(seq, TX_BYTE_CNT, GENMASK(31, 0)); ++ PRINT_FORMATTED_XFI_MIB64(seq, TX_UC_PKT_CNT); ++ PRINT_FORMATTED_XFI_MIB64(seq, TX_MC_PKT_CNT); ++ PRINT_FORMATTED_XFI_MIB64(seq, TX_BC_PKT_CNT); ++ ++ PRINT_FORMATTED_XFI_MIB(seq, RX_PKT_CNT, GENMASK(31, 0)); ++ PRINT_FORMATTED_XFI_MIB(seq, RX_ETH_CNT, GENMASK(31, 0)); ++ PRINT_FORMATTED_XFI_MIB(seq, RX_PAUSE_CNT, GENMASK(15, 0)); ++ PRINT_FORMATTED_XFI_MIB(seq, RX_LEN_ERR_CNT, GENMASK(15, 0)); ++ PRINT_FORMATTED_XFI_MIB(seq, RX_CRC_ERR_CNT, GENMASK(15, 0)); ++ PRINT_FORMATTED_XFI_MIB64(seq, RX_UC_PKT_CNT); ++ PRINT_FORMATTED_XFI_MIB64(seq, RX_MC_PKT_CNT); ++ PRINT_FORMATTED_XFI_MIB64(seq, RX_BC_PKT_CNT); ++ PRINT_FORMATTED_XFI_MIB(seq, RX_UC_DROP_CNT, GENMASK(31, 0)); ++ PRINT_FORMATTED_XFI_MIB(seq, RX_BC_DROP_CNT, GENMASK(31, 0)); ++ PRINT_FORMATTED_XFI_MIB(seq, RX_MC_DROP_CNT, GENMASK(31, 0)); ++ PRINT_FORMATTED_XFI_MIB(seq, RX_ALL_DROP_CNT, GENMASK(31, 0)); ++} ++ ++static int xfi_cnt_read(struct seq_file *seq, void *v) ++{ ++ struct mtk_eth *eth = g_eth; ++ int i; ++ ++ seq_puts(seq, "+------------------------------------+\n"); ++ seq_puts(seq, "| <> |\n"); ++ ++ for (i = MTK_GMAC2_ID; i < MTK_GMAC_ID_MAX; i++) { ++ xfi_mib_dump(seq, i); ++ mtk_m32(eth, 0x1, 0x1, MTK_XFI_MIB_BASE(i) + MTK_XFI_CNT_CTRL); ++ seq_puts(seq, "| |\n"); ++ } ++ ++ seq_puts(seq, "+------------------------------------+\n"); ++ ++ return 0; ++} ++ ++static int xfi_count_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, xfi_cnt_read, 0); ++} ++ ++static const struct proc_ops xfi_count_fops = { ++ .proc_open = xfi_count_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release ++}; ++ ++static struct proc_dir_entry *proc_tx_ring, *proc_hwtx_ring, *proc_rx_ring; ++ ++static int tx_ring_read(struct seq_file *seq, void *v) ++{ ++ struct mtk_eth *eth = g_eth; ++ struct mtk_tx_ring *ring = &g_eth->tx_ring; ++ struct mtk_tx_dma_v2 *tx_ring; ++ int i = 0; ++ ++ seq_printf(seq, "free count = %d\n", (int)atomic_read(&ring->free_count)); ++ seq_printf(seq, "cpu next free: %d\n", ++ (int)(ring->next_free - (struct mtk_tx_dma *)ring->dma)); ++ seq_printf(seq, "cpu last free: %d\n", ++ (int)(ring->last_free - (struct mtk_tx_dma *)ring->dma)); ++ for (i = 0; i < eth->soc->tx.dma_size; i++) { ++ dma_addr_t tmp = ring->phys + ++ i * (dma_addr_t)eth->soc->tx.desc_size; ++ ++ tx_ring = ring->dma + i * eth->soc->tx.desc_size; ++ ++ seq_printf(seq, "%d (%pad): %08x %08x %08x %08x", i, &tmp, ++ tx_ring->txd1, tx_ring->txd2, ++ tx_ring->txd3, tx_ring->txd4); ++ ++ if (mtk_is_netsys_v2_or_greater(eth)) { ++ seq_printf(seq, " %08x %08x %08x %08x", ++ tx_ring->txd5, tx_ring->txd6, ++ tx_ring->txd7, tx_ring->txd8); ++ } ++ ++ seq_puts(seq, "\n"); ++ } ++ ++ return 0; ++} ++ ++static int tx_ring_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, tx_ring_read, NULL); ++} ++ ++static const struct proc_ops tx_ring_fops = { ++ .proc_open = tx_ring_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release ++}; ++ ++static int hwtx_ring_read(struct seq_file *seq, void *v) ++{ ++ struct mtk_eth *eth = g_eth; ++ struct mtk_tx_dma_v2 *hwtx_ring; ++ int i = 0; ++ ++ for (i = 0; i < MTK_QDMA_RING_SIZE; i++) { ++ dma_addr_t addr = eth->phy_scratch_ring + ++ i * (dma_addr_t)eth->soc->tx.desc_size; ++ ++ hwtx_ring = eth->scratch_ring + i * eth->soc->tx.desc_size; ++ ++ seq_printf(seq, "%d (%pad): %08x %08x %08x %08x", i, &addr, ++ hwtx_ring->txd1, hwtx_ring->txd2, ++ hwtx_ring->txd3, hwtx_ring->txd4); ++ ++ if (mtk_is_netsys_v2_or_greater(eth)) { ++ seq_printf(seq, " %08x %08x %08x %08x", ++ hwtx_ring->txd5, hwtx_ring->txd6, ++ hwtx_ring->txd7, hwtx_ring->txd8); ++ } ++ ++ seq_puts(seq, "\n"); ++ } ++ ++ return 0; ++} ++ ++static int hwtx_ring_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, hwtx_ring_read, NULL); ++} ++ ++static const struct proc_ops hwtx_ring_fops = { ++ .proc_open = hwtx_ring_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release ++}; ++ ++static int rx_ring_read(struct seq_file *seq, void *v) ++{ ++ struct mtk_eth *eth = g_eth; ++ struct mtk_rx_ring *ring = &g_eth->rx_ring[0]; ++ struct mtk_rx_dma_v2 *rx_ring; ++ int i = 0; ++ ++ seq_printf(seq, "next to read: %d\n", ++ NEXT_DESP_IDX(ring->calc_idx, eth->soc->rx.dma_size)); ++ for (i = 0; i < eth->soc->rx.dma_size; i++) { ++ rx_ring = ring->dma + i * eth->soc->rx.desc_size; ++ ++ seq_printf(seq, "%d: %08x %08x %08x %08x", i, ++ rx_ring->rxd1, rx_ring->rxd2, ++ rx_ring->rxd3, rx_ring->rxd4); ++ ++ if (mtk_is_netsys_v2_or_greater(eth)) { ++ seq_printf(seq, " %08x %08x %08x %08x", ++ rx_ring->rxd5, rx_ring->rxd6, ++ rx_ring->rxd7, rx_ring->rxd8); ++ } ++ ++ seq_puts(seq, "\n"); ++ } ++ ++ return 0; ++} ++ ++static int rx_ring_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, rx_ring_read, NULL); ++} ++ ++static const struct proc_ops rx_ring_fops = { ++ .proc_open = rx_ring_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release ++}; ++ ++static inline u32 mtk_dbg_r32(u32 reg) ++{ ++ void __iomem *virt_reg; ++ u32 val; ++ ++ virt_reg = ioremap(reg, 32); ++ val = __raw_readl(virt_reg); ++ iounmap(virt_reg); ++ ++ return val; ++} ++ ++static int dbg_regs_read(struct seq_file *seq, void *v) ++{ ++ struct mtk_eth *eth = g_eth; ++ const struct mtk_reg_map *reg_map = eth->soc->reg_map; ++ ++ seq_puts(seq, " <>\n"); ++ ++ seq_printf(seq, "| FE_INT_STA : %08x |\n", ++ mtk_r32(eth, MTK_FE_INT_STATUS)); ++ if (mtk_is_netsys_v2_or_greater(eth)) ++ seq_printf(seq, "| FE_INT_STA2 : %08x |\n", ++ mtk_r32(eth, MTK_FE_INT_STATUS2)); ++ ++ seq_printf(seq, "| PSE_FQFC_CFG : %08x |\n", ++ mtk_r32(eth, MTK_PSE_FQFC_CFG)); ++ seq_printf(seq, "| PSE_IQ_STA1 : %08x |\n", ++ mtk_r32(eth, reg_map->pse_iq_sta + 0x00)); ++ seq_printf(seq, "| PSE_IQ_STA2 : %08x |\n", ++ mtk_r32(eth, reg_map->pse_iq_sta + 0x04)); ++ ++ if (mtk_is_netsys_v2_or_greater(eth)) { ++ seq_printf(seq, "| PSE_IQ_STA3 : %08x |\n", ++ mtk_r32(eth, reg_map->pse_iq_sta + 0x08)); ++ seq_printf(seq, "| PSE_IQ_STA4 : %08x |\n", ++ mtk_r32(eth, reg_map->pse_iq_sta + 0x0c)); ++ seq_printf(seq, "| PSE_IQ_STA5 : %08x |\n", ++ mtk_r32(eth, reg_map->pse_iq_sta + 0x10)); ++ seq_printf(seq, "| PSE_IQ_STA6 : %08x |\n", ++ mtk_r32(eth, reg_map->pse_iq_sta + 0x14)); ++ seq_printf(seq, "| PSE_IQ_STA7 : %08x |\n", ++ mtk_r32(eth, reg_map->pse_iq_sta + 0x18)); ++ seq_printf(seq, "| PSE_IQ_STA8 : %08x |\n", ++ mtk_r32(eth, reg_map->pse_iq_sta + 0x1c)); ++ } ++ ++ seq_printf(seq, "| PSE_OQ_STA1 : %08x |\n", ++ mtk_r32(eth, reg_map->pse_oq_sta + 0x00)); ++ seq_printf(seq, "| PSE_OQ_STA2 : %08x |\n", ++ mtk_r32(eth, reg_map->pse_oq_sta + 0x04)); ++ ++ if (mtk_is_netsys_v2_or_greater(eth)) { ++ seq_printf(seq, "| PSE_OQ_STA3 : %08x |\n", ++ mtk_r32(eth, reg_map->pse_oq_sta + 0x08)); ++ seq_printf(seq, "| PSE_OQ_STA4 : %08x |\n", ++ mtk_r32(eth, reg_map->pse_oq_sta + 0x0c)); ++ seq_printf(seq, "| PSE_OQ_STA5 : %08x |\n", ++ mtk_r32(eth, reg_map->pse_oq_sta + 0x10)); ++ seq_printf(seq, "| PSE_OQ_STA6 : %08x |\n", ++ mtk_r32(eth, reg_map->pse_oq_sta + 0x14)); ++ seq_printf(seq, "| PSE_OQ_STA7 : %08x |\n", ++ mtk_r32(eth, reg_map->pse_oq_sta + 0x18)); ++ seq_printf(seq, "| PSE_OQ_STA8 : %08x |\n", ++ mtk_r32(eth, reg_map->pse_oq_sta + 0x1c)); ++ } ++ ++ seq_printf(seq, "| PDMA_CRX_IDX : %08x |\n", ++ mtk_r32(eth, reg_map->pdma.pcrx_ptr)); ++ seq_printf(seq, "| PDMA_DRX_IDX : %08x |\n", ++ mtk_r32(eth, reg_map->pdma.pdrx_ptr)); ++ seq_printf(seq, "| QDMA_CTX_IDX : %08x |\n", ++ mtk_r32(eth, reg_map->qdma.ctx_ptr)); ++ seq_printf(seq, "| QDMA_DTX_IDX : %08x |\n", ++ mtk_r32(eth, reg_map->qdma.dtx_ptr)); ++ seq_printf(seq, "| QDMA_FQ_CNT : %08x |\n", ++ mtk_r32(eth, reg_map->qdma.fq_count)); ++ seq_printf(seq, "| QDMA_FWD_CNT : %08x |\n", ++ mtk_r32(eth, reg_map->qdma.fwd_count)); ++ seq_printf(seq, "| QDMA_FSM : %08x |\n", ++ mtk_r32(eth, reg_map->qdma.fsm)); ++ seq_printf(seq, "| FE_PSE_FREE : %08x |\n", ++ mtk_r32(eth, MTK_FE_PSE_FREE)); ++ seq_printf(seq, "| FE_DROP_FQ : %08x |\n", ++ mtk_r32(eth, MTK_FE_DROP_FQ)); ++ seq_printf(seq, "| FE_DROP_FC : %08x |\n", ++ mtk_r32(eth, MTK_FE_DROP_FC)); ++ seq_printf(seq, "| FE_DROP_PPE : %08x |\n", ++ mtk_r32(eth, MTK_FE_DROP_PPE)); ++ seq_printf(seq, "| GDM1_IG_CTRL : %08x |\n", ++ mtk_r32(eth, MTK_GDMA_FWD_CFG(0))); ++ seq_printf(seq, "| GDM2_IG_CTRL : %08x |\n", ++ mtk_r32(eth, MTK_GDMA_FWD_CFG(1))); ++ if (mtk_is_netsys_v3_or_greater(eth)) { ++ seq_printf(seq, "| GDM3_IG_CTRL : %08x |\n", ++ mtk_r32(eth, MTK_GDMA_FWD_CFG(2))); ++ } ++ seq_printf(seq, "| MAC_P1_MCR : %08x |\n", ++ mtk_r32(eth, MTK_MAC_MCR(0))); ++ seq_printf(seq, "| MAC_P2_MCR : %08x |\n", ++ mtk_r32(eth, MTK_MAC_MCR(1))); ++ if (mtk_is_netsys_v3_or_greater(eth)) { ++ seq_printf(seq, "| MAC_P3_MCR : %08x |\n", ++ mtk_r32(eth, MTK_MAC_MCR(2))); ++ } ++ seq_printf(seq, "| MAC_P1_FSM : %08x |\n", ++ mtk_r32(eth, MTK_MAC_FSM(0))); ++ seq_printf(seq, "| MAC_P2_FSM : %08x |\n", ++ mtk_r32(eth, MTK_MAC_FSM(1))); ++ if (mtk_is_netsys_v3_or_greater(eth)) { ++ seq_printf(seq, "| MAC_P3_FSM : %08x |\n", ++ mtk_r32(eth, MTK_MAC_FSM(2))); ++ } ++ ++ if (mtk_is_netsys_v2_or_greater(eth)) { ++ seq_printf(seq, "| FE_CDM1_FSM : %08x |\n", ++ mtk_r32(eth, MTK_FE_CDM1_FSM)); ++ seq_printf(seq, "| FE_CDM2_FSM : %08x |\n", ++ mtk_r32(eth, MTK_FE_CDM2_FSM)); ++ seq_printf(seq, "| FE_CDM3_FSM : %08x |\n", ++ mtk_r32(eth, MTK_FE_CDM3_FSM)); ++ seq_printf(seq, "| FE_CDM4_FSM : %08x |\n", ++ mtk_r32(eth, MTK_FE_CDM4_FSM)); ++ seq_printf(seq, "| FE_CDM5_FSM : %08x |\n", ++ mtk_r32(eth, MTK_FE_CDM5_FSM)); ++ seq_printf(seq, "| FE_CDM6_FSM : %08x |\n", ++ mtk_r32(eth, MTK_FE_CDM6_FSM)); ++ seq_printf(seq, "| FE_GDM1_FSM : %08x |\n", ++ mtk_r32(eth, MTK_FE_GDM1_FSM)); ++ seq_printf(seq, "| FE_GDM2_FSM : %08x |\n", ++ mtk_r32(eth, MTK_FE_GDM2_FSM)); ++ seq_printf(seq, "| SGMII_EFUSE : %08x |\n", ++ mtk_dbg_r32(MTK_SGMII_EFUSE)); ++ seq_printf(seq, "| SGMII0_RX_CNT : %08x |\n", ++ mtk_dbg_r32(MTK_SGMII_FALSE_CARRIER_CNT(0))); ++ seq_printf(seq, "| SGMII1_RX_CNT : %08x |\n", ++ mtk_dbg_r32(MTK_SGMII_FALSE_CARRIER_CNT(1))); ++ seq_printf(seq, "| WED_RTQM_GLO : %08x |\n", ++ mtk_dbg_r32(MTK_WED_RTQM_GLO_CFG)); ++ } ++ ++ mtk_w32(eth, 0xffffffff, MTK_FE_INT_STATUS); ++ if (mtk_is_netsys_v2_or_greater(eth)) ++ mtk_w32(eth, 0xffffffff, MTK_FE_INT_STATUS2); ++ ++ return 0; ++} ++ ++static int dbg_regs_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, dbg_regs_read, 0); ++} ++ ++static const struct proc_ops dbg_regs_fops = { ++ .proc_open = dbg_regs_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_release = single_release ++}; ++ ++void hw_lro_stats_update(u32 ring_no, struct mtk_rx_dma_v2 *rxd) ++{ ++ struct mtk_eth *eth = g_eth; ++ u32 idx, agg_cnt, agg_size; ++ ++ if (mtk_is_netsys_v3_or_greater(eth)) { ++ idx = ring_no - 4; ++ agg_cnt = FIELD_GET(RX_DMA_GET_AGG_CNT_V2, rxd->rxd6); ++ } else { ++ idx = ring_no - 1; ++ agg_cnt = FIELD_GET(RX_DMA_GET_AGG_CNT, rxd->rxd2); ++ } ++ ++ if (idx >= MTK_HW_LRO_RING_NUM) ++ return; ++ ++ agg_size = RX_DMA_GET_PLEN0(rxd->rxd2); ++ ++ hw_lro_agg_size_cnt[idx][agg_size / 5000]++; ++ hw_lro_agg_num_cnt[idx][agg_cnt]++; ++ hw_lro_tot_flush_cnt[idx]++; ++ hw_lro_tot_agg_cnt[idx] += agg_cnt; ++} ++ ++void hw_lro_flush_stats_update(u32 ring_no, struct mtk_rx_dma_v2 *rxd) ++{ ++ struct mtk_eth *eth = g_eth; ++ u32 idx, flush_reason; ++ ++ if (mtk_is_netsys_v3_or_greater(eth)) { ++ idx = ring_no - 4; ++ flush_reason = FIELD_GET(RX_DMA_GET_FLUSH_RSN_V2, rxd->rxd6); ++ } else { ++ idx = ring_no - 1; ++ flush_reason = FIELD_GET(RX_DMA_GET_REV, rxd->rxd2); ++ } ++ ++ if (idx >= MTK_HW_LRO_RING_NUM) ++ return; ++ ++ if ((flush_reason & 0x7) == MTK_HW_LRO_AGG_FLUSH) ++ hw_lro_agg_flush_cnt[idx]++; ++ else if ((flush_reason & 0x7) == MTK_HW_LRO_AGE_FLUSH) ++ hw_lro_age_flush_cnt[idx]++; ++ else if ((flush_reason & 0x7) == MTK_HW_LRO_NOT_IN_SEQ_FLUSH) ++ hw_lro_seq_flush_cnt[idx]++; ++ else if ((flush_reason & 0x7) == MTK_HW_LRO_TIMESTAMP_FLUSH) ++ hw_lro_timestamp_flush_cnt[idx]++; ++ else if ((flush_reason & 0x7) == MTK_HW_LRO_NON_RULE_FLUSH) ++ hw_lro_norule_flush_cnt[idx]++; ++} ++ ++static ssize_t hw_lro_stats_write(struct file *file, const char __user *buffer, ++ size_t count, loff_t *data) ++{ ++ memset(hw_lro_agg_num_cnt, 0, sizeof(hw_lro_agg_num_cnt)); ++ memset(hw_lro_agg_size_cnt, 0, sizeof(hw_lro_agg_size_cnt)); ++ memset(hw_lro_tot_agg_cnt, 0, sizeof(hw_lro_tot_agg_cnt)); ++ memset(hw_lro_tot_flush_cnt, 0, sizeof(hw_lro_tot_flush_cnt)); ++ memset(hw_lro_agg_flush_cnt, 0, sizeof(hw_lro_agg_flush_cnt)); ++ memset(hw_lro_age_flush_cnt, 0, sizeof(hw_lro_age_flush_cnt)); ++ memset(hw_lro_seq_flush_cnt, 0, sizeof(hw_lro_seq_flush_cnt)); ++ memset(hw_lro_timestamp_flush_cnt, 0, ++ sizeof(hw_lro_timestamp_flush_cnt)); ++ memset(hw_lro_norule_flush_cnt, 0, sizeof(hw_lro_norule_flush_cnt)); ++ ++ pr_info("clear hw lro cnt table\n"); ++ ++ return count; ++} ++ ++static int hw_lro_stats_read_v1(struct seq_file *seq, void *v) ++{ ++ int i; ++ ++ seq_puts(seq, "HW LRO statistic dump:\n"); ++ ++ /* Agg number count */ ++ seq_puts(seq, "Cnt: RING1 | RING2 | RING3 | Total\n"); ++ for (i = 0; i <= MTK_HW_LRO_MAX_AGG_CNT; i++) { ++ seq_printf(seq, " %d : %d %d %d %d\n", ++ i, hw_lro_agg_num_cnt[0][i], ++ hw_lro_agg_num_cnt[1][i], hw_lro_agg_num_cnt[2][i], ++ hw_lro_agg_num_cnt[0][i] + hw_lro_agg_num_cnt[1][i] + ++ hw_lro_agg_num_cnt[2][i]); ++ } ++ ++ /* Total agg count */ ++ seq_puts(seq, "Total agg: RING1 | RING2 | RING3 | Total\n"); ++ seq_printf(seq, " %d %d %d %d\n", ++ hw_lro_tot_agg_cnt[0], hw_lro_tot_agg_cnt[1], ++ hw_lro_tot_agg_cnt[2], ++ hw_lro_tot_agg_cnt[0] + hw_lro_tot_agg_cnt[1] + ++ hw_lro_tot_agg_cnt[2]); ++ ++ /* Total flush count */ ++ seq_puts(seq, "Total flush: RING1 | RING2 | RING3 | Total\n"); ++ seq_printf(seq, " %d %d %d %d\n", ++ hw_lro_tot_flush_cnt[0], hw_lro_tot_flush_cnt[1], ++ hw_lro_tot_flush_cnt[2], ++ hw_lro_tot_flush_cnt[0] + hw_lro_tot_flush_cnt[1] + ++ hw_lro_tot_flush_cnt[2]); ++ ++ /* Avg agg count */ ++ seq_puts(seq, "Avg agg: RING1 | RING2 | RING3 | Total\n"); ++ seq_printf(seq, " %d %d %d %d\n", ++ (hw_lro_tot_flush_cnt[0]) ? ++ hw_lro_tot_agg_cnt[0] / hw_lro_tot_flush_cnt[0] : 0, ++ (hw_lro_tot_flush_cnt[1]) ? ++ hw_lro_tot_agg_cnt[1] / hw_lro_tot_flush_cnt[1] : 0, ++ (hw_lro_tot_flush_cnt[2]) ? ++ hw_lro_tot_agg_cnt[2] / hw_lro_tot_flush_cnt[2] : 0, ++ (hw_lro_tot_flush_cnt[0] + hw_lro_tot_flush_cnt[1] + ++ hw_lro_tot_flush_cnt[2]) ? ++ ((hw_lro_tot_agg_cnt[0] + hw_lro_tot_agg_cnt[1] + ++ hw_lro_tot_agg_cnt[2]) / (hw_lro_tot_flush_cnt[0] + ++ hw_lro_tot_flush_cnt[1] + hw_lro_tot_flush_cnt[2])) : 0); ++ ++ /* Statistics of aggregation size counts */ ++ seq_puts(seq, "HW LRO flush pkt len:\n"); ++ seq_puts(seq, " Length | RING1 | RING2 | RING3 | Total\n"); ++ for (i = 0; i < 15; i++) { ++ seq_printf(seq, "%d~%d: %d %d %d %d\n", i * 5000, ++ (i + 1) * 5000, hw_lro_agg_size_cnt[0][i], ++ hw_lro_agg_size_cnt[1][i], hw_lro_agg_size_cnt[2][i], ++ hw_lro_agg_size_cnt[0][i] + ++ hw_lro_agg_size_cnt[1][i] + ++ hw_lro_agg_size_cnt[2][i]); ++ } ++ ++ seq_puts(seq, "Flush reason: RING1 | RING2 | RING3 | Total\n"); ++ seq_printf(seq, "AGG timeout: %d %d %d %d\n", ++ hw_lro_agg_flush_cnt[0], hw_lro_agg_flush_cnt[1], ++ hw_lro_agg_flush_cnt[2], ++ (hw_lro_agg_flush_cnt[0] + hw_lro_agg_flush_cnt[1] + ++ hw_lro_agg_flush_cnt[2])); ++ ++ seq_printf(seq, "AGE timeout: %d %d %d %d\n", ++ hw_lro_age_flush_cnt[0], hw_lro_age_flush_cnt[1], ++ hw_lro_age_flush_cnt[2], ++ (hw_lro_age_flush_cnt[0] + hw_lro_age_flush_cnt[1] + ++ hw_lro_age_flush_cnt[2])); ++ ++ seq_printf(seq, "Not in-sequence: %d %d %d %d\n", ++ hw_lro_seq_flush_cnt[0], hw_lro_seq_flush_cnt[1], ++ hw_lro_seq_flush_cnt[2], ++ (hw_lro_seq_flush_cnt[0] + hw_lro_seq_flush_cnt[1] + ++ hw_lro_seq_flush_cnt[2])); ++ ++ seq_printf(seq, "Timestamp: %d %d %d %d\n", ++ hw_lro_timestamp_flush_cnt[0], ++ hw_lro_timestamp_flush_cnt[1], ++ hw_lro_timestamp_flush_cnt[2], ++ (hw_lro_timestamp_flush_cnt[0] + ++ hw_lro_timestamp_flush_cnt[1] + ++ hw_lro_timestamp_flush_cnt[2])); ++ ++ seq_printf(seq, "No LRO rule: %d %d %d %d\n", ++ hw_lro_norule_flush_cnt[0], ++ hw_lro_norule_flush_cnt[1], ++ hw_lro_norule_flush_cnt[2], ++ (hw_lro_norule_flush_cnt[0] + ++ hw_lro_norule_flush_cnt[1] + ++ hw_lro_norule_flush_cnt[2])); ++ ++ return 0; ++} ++ ++static int hw_lro_stats_read_v2(struct seq_file *seq, void *v) ++{ ++ int i; ++ ++ seq_puts(seq, "HW LRO statistic dump:\n"); ++ ++ /* Agg number count */ ++ seq_puts(seq, "Cnt: RING4 | RING5 | RING6 | RING7 Total\n"); ++ for (i = 0; i <= MTK_HW_LRO_MAX_AGG_CNT; i++) { ++ seq_printf(seq, ++ " %d : %d %d %d %d %d\n", ++ i, hw_lro_agg_num_cnt[0][i], hw_lro_agg_num_cnt[1][i], ++ hw_lro_agg_num_cnt[2][i], hw_lro_agg_num_cnt[3][i], ++ hw_lro_agg_num_cnt[0][i] + hw_lro_agg_num_cnt[1][i] + ++ hw_lro_agg_num_cnt[2][i] + hw_lro_agg_num_cnt[3][i]); ++ } ++ ++ /* Total agg count */ ++ seq_puts(seq, "Total agg: RING4 | RING5 | RING6 | RING7 Total\n"); ++ seq_printf(seq, " %d %d %d %d %d\n", ++ hw_lro_tot_agg_cnt[0], hw_lro_tot_agg_cnt[1], ++ hw_lro_tot_agg_cnt[2], hw_lro_tot_agg_cnt[3], ++ hw_lro_tot_agg_cnt[0] + hw_lro_tot_agg_cnt[1] + ++ hw_lro_tot_agg_cnt[2] + hw_lro_tot_agg_cnt[3]); ++ ++ /* Total flush count */ ++ seq_puts(seq, "Total flush: RING4 | RING5 | RING6 | RING7 Total\n"); ++ seq_printf(seq, " %d %d %d %d %d\n", ++ hw_lro_tot_flush_cnt[0], hw_lro_tot_flush_cnt[1], ++ hw_lro_tot_flush_cnt[2], hw_lro_tot_flush_cnt[3], ++ hw_lro_tot_flush_cnt[0] + hw_lro_tot_flush_cnt[1] + ++ hw_lro_tot_flush_cnt[2] + hw_lro_tot_flush_cnt[3]); ++ ++ /* Avg agg count */ ++ seq_puts(seq, "Avg agg: RING4 | RING5 | RING6 | RING7 Total\n"); ++ seq_printf(seq, " %d %d %d %d %d\n", ++ (hw_lro_tot_flush_cnt[0]) ? ++ hw_lro_tot_agg_cnt[0] / hw_lro_tot_flush_cnt[0] : 0, ++ (hw_lro_tot_flush_cnt[1]) ? ++ hw_lro_tot_agg_cnt[1] / hw_lro_tot_flush_cnt[1] : 0, ++ (hw_lro_tot_flush_cnt[2]) ? ++ hw_lro_tot_agg_cnt[2] / hw_lro_tot_flush_cnt[2] : 0, ++ (hw_lro_tot_flush_cnt[3]) ? ++ hw_lro_tot_agg_cnt[3] / hw_lro_tot_flush_cnt[3] : 0, ++ (hw_lro_tot_flush_cnt[0] + hw_lro_tot_flush_cnt[1] + ++ hw_lro_tot_flush_cnt[2] + hw_lro_tot_flush_cnt[3]) ? ++ ((hw_lro_tot_agg_cnt[0] + hw_lro_tot_agg_cnt[1] + ++ hw_lro_tot_agg_cnt[2] + hw_lro_tot_agg_cnt[3]) / ++ (hw_lro_tot_flush_cnt[0] + hw_lro_tot_flush_cnt[1] + ++ hw_lro_tot_flush_cnt[2] + hw_lro_tot_flush_cnt[3])) : 0); ++ ++ /* Statistics of aggregation size counts */ ++ seq_puts(seq, "HW LRO flush pkt len:\n"); ++ seq_puts(seq, " Length | RING4 | RING5 | RING6 | RING7 Total\n"); ++ for (i = 0; i < 15; i++) { ++ seq_printf(seq, "%d~%d: %d %d %d %d %d\n", ++ i * 5000, (i + 1) * 5000, ++ hw_lro_agg_size_cnt[0][i], hw_lro_agg_size_cnt[1][i], ++ hw_lro_agg_size_cnt[2][i], hw_lro_agg_size_cnt[3][i], ++ hw_lro_agg_size_cnt[0][i] + ++ hw_lro_agg_size_cnt[1][i] + ++ hw_lro_agg_size_cnt[2][i] + ++ hw_lro_agg_size_cnt[3][i]); ++ } ++ ++ seq_puts(seq, "Flush reason: RING4 | RING5 | RING6 | RING7 Total\n"); ++ seq_printf(seq, "AGG timeout: %d %d %d %d %d\n", ++ hw_lro_agg_flush_cnt[0], hw_lro_agg_flush_cnt[1], ++ hw_lro_agg_flush_cnt[2], hw_lro_agg_flush_cnt[3], ++ (hw_lro_agg_flush_cnt[0] + hw_lro_agg_flush_cnt[1] + ++ hw_lro_agg_flush_cnt[2] + hw_lro_agg_flush_cnt[3])); ++ ++ seq_printf(seq, "AGE timeout: %d %d %d %d %d\n", ++ hw_lro_age_flush_cnt[0], hw_lro_age_flush_cnt[1], ++ hw_lro_age_flush_cnt[2], hw_lro_age_flush_cnt[3], ++ (hw_lro_age_flush_cnt[0] + hw_lro_age_flush_cnt[1] + ++ hw_lro_age_flush_cnt[2] + hw_lro_age_flush_cnt[3])); ++ ++ seq_printf(seq, "Not in-sequence: %d %d %d %d %d\n", ++ hw_lro_seq_flush_cnt[0], hw_lro_seq_flush_cnt[1], ++ hw_lro_seq_flush_cnt[2], hw_lro_seq_flush_cnt[3], ++ (hw_lro_seq_flush_cnt[0] + hw_lro_seq_flush_cnt[1] + ++ hw_lro_seq_flush_cnt[2] + hw_lro_seq_flush_cnt[3])); ++ ++ seq_printf(seq, "Timestamp: %d %d %d %d %d\n", ++ hw_lro_timestamp_flush_cnt[0], ++ hw_lro_timestamp_flush_cnt[1], ++ hw_lro_timestamp_flush_cnt[2], ++ hw_lro_timestamp_flush_cnt[3], ++ (hw_lro_timestamp_flush_cnt[0] + ++ hw_lro_timestamp_flush_cnt[1] + ++ hw_lro_timestamp_flush_cnt[2] + ++ hw_lro_timestamp_flush_cnt[3])); ++ ++ seq_printf(seq, "No LRO rule: %d %d %d %d %d\n", ++ hw_lro_norule_flush_cnt[0], ++ hw_lro_norule_flush_cnt[1], ++ hw_lro_norule_flush_cnt[2], ++ hw_lro_norule_flush_cnt[3], ++ (hw_lro_norule_flush_cnt[0] + ++ hw_lro_norule_flush_cnt[1] + ++ hw_lro_norule_flush_cnt[2] + ++ hw_lro_norule_flush_cnt[3])); ++ ++ return 0; ++} ++ ++static int hw_lro_stats_read_wrapper(struct seq_file *seq, void *v) ++{ ++ struct mtk_eth *eth = g_eth; ++ ++ if (mtk_is_netsys_v2_or_greater(eth)) ++ hw_lro_stats_read_v2(seq, v); ++ else ++ hw_lro_stats_read_v1(seq, v); ++ ++ return 0; ++} ++ ++static int hw_lro_stats_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, hw_lro_stats_read_wrapper, NULL); ++} ++ ++static const struct proc_ops hw_lro_stats_fops = { ++ .proc_open = hw_lro_stats_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_write = hw_lro_stats_write, ++ .proc_release = single_release ++}; ++ ++static int hwlro_agg_cnt_ctrl(int cnt) ++{ ++ struct mtk_eth *eth = g_eth; ++ const struct mtk_reg_map *reg_map = eth->soc->reg_map; ++ int i; ++ ++ for (i = 1; i <= MTK_HW_LRO_RING_NUM; i++) ++ SET_PDMA_RXRING_MAX_AGG_CNT(eth, i, cnt); ++ ++ return 0; ++} ++ ++static int hwlro_agg_time_ctrl(int time) ++{ ++ struct mtk_eth *eth = g_eth; ++ const struct mtk_reg_map *reg_map = eth->soc->reg_map; ++ int i; ++ ++ for (i = 1; i <= MTK_HW_LRO_RING_NUM; i++) ++ SET_PDMA_RXRING_AGG_TIME(eth, i, time); ++ ++ return 0; ++} ++ ++static int hwlro_age_time_ctrl(int time) ++{ ++ struct mtk_eth *eth = g_eth; ++ const struct mtk_reg_map *reg_map = eth->soc->reg_map; ++ int i; ++ ++ for (i = 1; i <= MTK_HW_LRO_RING_NUM; i++) ++ SET_PDMA_RXRING_AGE_TIME(eth, i, time); ++ return 0; ++} ++ ++static int hwlro_threshold_ctrl(int bandwidth) ++{ ++ struct mtk_eth *eth = g_eth; ++ const struct mtk_reg_map *reg_map = eth->soc->reg_map; ++ ++ SET_PDMA_LRO_BW_THRESHOLD(eth, bandwidth); ++ ++ return 0; ++} ++ ++static int hwlro_ring_enable_ctrl(int enable) ++{ ++ struct mtk_eth *eth = g_eth; ++ const struct mtk_reg_map *reg_map = eth->soc->reg_map; ++ int i; ++ ++ pr_info("[%s] %s HW LRO rings\n", __func__, (enable) ? "Enable" : "Disable"); ++ ++ for (i = 1; i <= MTK_HW_LRO_RING_NUM; i++) ++ SET_PDMA_RXRING_VALID(eth, i, enable); ++ ++ return 0; ++} ++ ++static int hwlro_stats_enable_ctrl(int enable) ++{ ++ pr_info("[%s] %s HW LRO statistics\n", __func__, (enable) ? "Enable" : "Disable"); ++ mtk_hwlro_stats_ebl = enable; ++ ++ return 0; ++} ++ ++static const mtk_lro_dbg_func lro_dbg_func[] = { ++ [0] = hwlro_agg_cnt_ctrl, ++ [1] = hwlro_agg_time_ctrl, ++ [2] = hwlro_age_time_ctrl, ++ [3] = hwlro_threshold_ctrl, ++ [4] = hwlro_ring_enable_ctrl, ++ [5] = hwlro_stats_enable_ctrl, ++}; ++ ++static ssize_t hw_lro_auto_tlb_write(struct file *file, const char __user *buffer, ++ size_t count, loff_t *data) ++{ ++ char buf[32]; ++ char *p_buf; ++ char *p_token = NULL; ++ char *p_delimiter = " \t"; ++ long x = 0, y = 0; ++ u32 len = count; ++ int ret; ++ ++ if (len >= sizeof(buf)) { ++ pr_info("Input handling fail!\n"); ++ return -1; ++ } ++ ++ if (copy_from_user(buf, buffer, len)) ++ return -EFAULT; ++ ++ buf[len] = '\0'; ++ ++ p_buf = buf; ++ p_token = strsep(&p_buf, p_delimiter); ++ if (!p_token) ++ x = 0; ++ else ++ ret = kstrtol(p_token, 10, &x); ++ ++ p_token = strsep(&p_buf, "\t\n "); ++ if (p_token) ++ ret = kstrtol(p_token, 10, &y); ++ ++ if (lro_dbg_func[x] && (ARRAY_SIZE(lro_dbg_func) > x)) ++ (*lro_dbg_func[x]) (y); ++ ++ return count; ++} ++ ++static void hw_lro_auto_tlb_dump_v1(struct seq_file *seq, u32 index) ++{ ++ struct mtk_eth *eth = g_eth; ++ struct mtk_lro_alt_v1 alt; ++ const struct mtk_reg_map *reg_map = eth->soc->reg_map; ++ __be32 addr; ++ u32 tlb_info[9]; ++ u32 dw_len, cnt, priority; ++ u32 entry; ++ int i; ++ ++ if (index > 4) ++ index = index - 1; ++ entry = (index * 9) + 1; ++ ++ /* read valid entries of the auto-learn table */ ++ mtk_w32(eth, entry, MTK_FE_ALT_CF8); ++ ++ for (i = 0; i < 9; i++) ++ tlb_info[i] = mtk_r32(eth, MTK_FE_ALT_SEQ_CFC); ++ ++ memcpy(&alt, tlb_info, sizeof(struct mtk_lro_alt_v1)); ++ ++ dw_len = alt.alt_info7.dw_len; ++ cnt = alt.alt_info6.cnt; ++ ++ if (mtk_r32(eth, MTK_PDMA_LRO_CTRL_DW0) & MTK_LRO_ALT_PKT_CNT_MODE) ++ priority = cnt; /* packet count */ ++ else ++ priority = dw_len; /* byte count */ ++ ++ /* dump valid entries of the auto-learn table */ ++ if (index >= 4) ++ seq_printf(seq, "\n===== TABLE Entry: %d (Act) =====\n", index); ++ else ++ seq_printf(seq, "\n===== TABLE Entry: %d (LRU) =====\n", index); ++ ++ if (alt.alt_info8.ipv4) { ++ addr = htonl(alt.alt_info1.sip0); ++ seq_printf(seq, "SIP = %pI4 (IPv4)\n", &addr); ++ } else { ++ seq_printf(seq, "SIP = %08X:%08X:%08X:%08X (IPv6)\n", ++ alt.alt_info4.sip3, alt.alt_info3.sip2, ++ alt.alt_info2.sip1, alt.alt_info1.sip0); ++ } ++ ++ seq_printf(seq, "DIP_ID = %d\n", alt.alt_info8.dip_id); ++ seq_printf(seq, "TCP SPORT = %d | TCP DPORT = %d\n", ++ alt.alt_info0.stp, alt.alt_info0.dtp); ++ seq_printf(seq, "VLAN_VID_VLD = %d\n", alt.alt_info6.vlan_vid_vld); ++ seq_printf(seq, "VLAN1 = %d | VLAN2 = %d | VLAN3 = %d | VLAN4 =%d\n", ++ (alt.alt_info5.vlan_vid0 & 0xfff), ++ ((alt.alt_info5.vlan_vid0 >> 12) & 0xfff), ++ ((alt.alt_info6.vlan_vid1 << 8) | ++ ((alt.alt_info5.vlan_vid0 >> 24) & 0xfff)), ++ ((alt.alt_info6.vlan_vid1 >> 4) & 0xfff)); ++ seq_printf(seq, "TPUT = %d | FREQ = %d\n", dw_len, cnt); ++ seq_printf(seq, "PRIORITY = %d\n", priority); ++} ++ ++static void hw_lro_auto_tlb_dump_v2(struct seq_file *seq, u32 index) ++{ ++ struct mtk_eth *eth = g_eth; ++ struct mtk_lro_alt_v2 alt; ++ const struct mtk_reg_map *reg_map = eth->soc->reg_map; ++ u32 score = 0, ipv4 = 0; ++ u32 ipv6[4] = { 0 }; ++ u32 tlb_info[12]; ++ int i; ++ ++ /* read valid entries of the auto-learn table */ ++ mtk_w32(eth, index << MTK_LRO_ALT_INDEX_OFFSET, reg_map->pdma.lro_alt_dbg); ++ ++ for (i = 0; i < 11; i++) ++ tlb_info[i] = mtk_r32(eth, reg_map->pdma.lro_alt_dbg_data); ++ ++ memcpy(&alt, tlb_info, sizeof(struct mtk_lro_alt_v2)); ++ ++ if (mtk_r32(eth, MTK_PDMA_LRO_CTRL_DW0) & MTK_LRO_ALT_PKT_CNT_MODE) ++ score = 1; /* packet count */ ++ else ++ score = 0; /* byte count */ ++ ++ /* dump valid entries of the auto-learn table */ ++ if (alt.alt_info0.valid) { ++ if (index < 5) ++ seq_printf(seq, ++ "\n===== TABLE Entry: %d (onging) =====\n", ++ index); ++ else ++ seq_printf(seq, ++ "\n===== TABLE Entry: %d (candidate) =====\n", ++ index); ++ ++ if (alt.alt_info1.v4_valid) { ++ ipv4 = (alt.alt_info4.sip0_h << 23) | ++ alt.alt_info5.sip0_l; ++ seq_printf(seq, "SIP = 0x%x: (IPv4)\n", ipv4); ++ ++ ipv4 = (alt.alt_info8.dip0_h << 23) | ++ alt.alt_info9.dip0_l; ++ seq_printf(seq, "DIP = 0x%x: (IPv4)\n", ipv4); ++ } else if (alt.alt_info1.v6_valid) { ++ ipv6[3] = (alt.alt_info1.sip3_h << 23) | ++ (alt.alt_info2.sip3_l << 9); ++ ipv6[2] = (alt.alt_info2.sip2_h << 23) | ++ (alt.alt_info3.sip2_l << 9); ++ ipv6[1] = (alt.alt_info3.sip1_h << 23) | ++ (alt.alt_info4.sip1_l << 9); ++ ipv6[0] = (alt.alt_info4.sip0_h << 23) | ++ (alt.alt_info5.sip0_l << 9); ++ seq_printf(seq, "SIP = 0x%x:0x%x:0x%x:0x%x (IPv6)\n", ++ ipv6[3], ipv6[2], ipv6[1], ipv6[0]); ++ ++ ipv6[3] = (alt.alt_info5.dip3_h << 23) | ++ (alt.alt_info6.dip3_l << 9); ++ ipv6[2] = (alt.alt_info6.dip2_h << 23) | ++ (alt.alt_info7.dip2_l << 9); ++ ipv6[1] = (alt.alt_info7.dip1_h << 23) | ++ (alt.alt_info8.dip1_l << 9); ++ ipv6[0] = (alt.alt_info8.dip0_h << 23) | ++ (alt.alt_info9.dip0_l << 9); ++ seq_printf(seq, "DIP = 0x%x:0x%x:0x%x:0x%x (IPv6)\n", ++ ipv6[3], ipv6[2], ipv6[1], ipv6[0]); ++ } ++ ++ seq_printf(seq, "TCP SPORT = %d | TCP DPORT = %d\n", ++ (alt.alt_info9.sp_h << 7) | (alt.alt_info10.sp_l), ++ alt.alt_info10.dp); ++ } ++} ++ ++static int hw_lro_auto_tlb_read(struct seq_file *seq, void *v) ++{ ++ struct mtk_eth *eth = g_eth; ++ int i; ++ u32 reg_val; ++ u32 reg_op1, reg_op2, reg_op3, reg_op4; ++ u32 agg_cnt, agg_time, age_time; ++ const struct mtk_reg_map *reg_map = eth->soc->reg_map; ++ ++ seq_puts(seq, "Usage of /proc/mtketh/hw_lro_auto_tlb:\n"); ++ seq_puts(seq, "echo [function] [setting] > /proc/mtketh/hw_lro_auto_tlb\n"); ++ seq_puts(seq, "Functions:\n"); ++ seq_puts(seq, "[0] = hwlro_agg_cnt_ctrl\n"); ++ seq_puts(seq, "[1] = hwlro_agg_time_ctrl\n"); ++ seq_puts(seq, "[2] = hwlro_age_time_ctrl\n"); ++ seq_puts(seq, "[3] = hwlro_threshold_ctrl\n"); ++ seq_puts(seq, "[4] = hwlro_ring_enable_ctrl\n"); ++ seq_puts(seq, "[5] = hwlro_stats_enable_ctrl\n\n"); ++ ++ if (mtk_is_netsys_v3_or_greater(eth)) { ++ for (i = 1; i <= 8; i++) ++ hw_lro_auto_tlb_dump_v2(seq, i); ++ } else { ++ /* Read valid entries of the auto-learn table */ ++ mtk_w32(eth, 0, MTK_FE_ALT_CF8); ++ reg_val = mtk_r32(eth, MTK_FE_ALT_SEQ_CFC); ++ ++ seq_printf(seq, ++ "HW LRO Auto-learn Table: (MTK_FE_ALT_SEQ_CFC=0x%x)\n", ++ reg_val); ++ ++ for (i = 7; i >= 0; i--) { ++ if (reg_val & (1 << i)) ++ hw_lro_auto_tlb_dump_v1(seq, i); ++ } ++ } ++ ++ /* Read the agg_time/age_time/agg_cnt of LRO rings */ ++ seq_puts(seq, "\nHW LRO Ring Settings\n"); ++ ++ for (i = 1; i <= MTK_HW_LRO_RING_NUM; i++) { ++ reg_op1 = mtk_r32(eth, MTK_LRO_CTRL_DW1_CFG(i)); ++ reg_op2 = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(i)); ++ reg_op3 = mtk_r32(eth, MTK_LRO_CTRL_DW3_CFG(i)); ++ reg_op4 = mtk_r32(eth, MTK_PDMA_LRO_CTRL_DW2); ++ ++ agg_cnt = ++ ((reg_op3 & 0x3) << 6) | ++ ((reg_op2 >> MTK_LRO_RING_AGG_CNT_L_OFFSET) & 0x3f); ++ agg_time = (reg_op2 >> MTK_LRO_RING_AGG_TIME_OFFSET) & 0xffff; ++ age_time = ++ ((reg_op2 & 0x3f) << 10) | ++ ((reg_op1 >> MTK_LRO_RING_AGE_TIME_L_OFFSET) & 0x3ff); ++ seq_printf(seq, ++ "Ring[%d]: MAX_AGG_CNT=%d, AGG_TIME=%d, AGE_TIME=%d, Threshold=%d\n", ++ !(mtk_is_netsys_v2_or_greater(eth)) ? ++ i : i+3, ++ agg_cnt, agg_time, age_time, reg_op4); ++ } ++ ++ seq_puts(seq, "\n"); ++ ++ return 0; ++} ++ ++static int hw_lro_auto_tlb_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, hw_lro_auto_tlb_read, NULL); ++} ++ ++static const struct proc_ops hw_lro_auto_tlb_fops = { ++ .proc_open = hw_lro_auto_tlb_open, ++ .proc_read = seq_read, ++ .proc_lseek = seq_lseek, ++ .proc_write = hw_lro_auto_tlb_write, ++ .proc_release = single_release ++}; ++ ++struct proc_dir_entry *proc_reg_dir; ++static struct proc_dir_entry *proc_esw_cnt, *proc_xfi_cnt, ++ *proc_dbg_regs, *proc_reset_event; ++ ++int debug_proc_init(struct mtk_eth *eth) ++{ ++ g_eth = eth; ++ ++ if (!proc_reg_dir) ++ proc_reg_dir = proc_mkdir(PROCREG_DIR, NULL); ++ ++ proc_tx_ring = ++ proc_create(PROCREG_TXRING, 0, proc_reg_dir, &tx_ring_fops); ++ if (!proc_tx_ring) ++ pr_notice("!! FAIL to create %s PROC !!\n", PROCREG_TXRING); ++ ++ proc_hwtx_ring = ++ proc_create(PROCREG_HWTXRING, 0, proc_reg_dir, &hwtx_ring_fops); ++ if (!proc_hwtx_ring) ++ pr_notice("!! FAIL to create %s PROC !!\n", PROCREG_HWTXRING); ++ ++ proc_rx_ring = ++ proc_create(PROCREG_RXRING, 0, proc_reg_dir, &rx_ring_fops); ++ if (!proc_rx_ring) ++ pr_notice("!! FAIL to create %s PROC !!\n", PROCREG_RXRING); ++ ++ proc_esw_cnt = ++ proc_create(PROCREG_ESW_CNT, 0, proc_reg_dir, &switch_count_fops); ++ if (!proc_esw_cnt) ++ pr_notice("!! FAIL to create %s PROC !!\n", PROCREG_ESW_CNT); ++ ++ if (mtk_is_netsys_v3_or_greater(g_eth)) { ++ proc_xfi_cnt = ++ proc_create(PROCREG_XFI_CNT, 0, ++ proc_reg_dir, &xfi_count_fops); ++ if (!proc_xfi_cnt) ++ pr_notice("!! FAIL to create %s PROC !!\n", ++ PROCREG_XFI_CNT); ++ } ++ ++ proc_dbg_regs = ++ proc_create(PROCREG_DBG_REGS, 0, proc_reg_dir, &dbg_regs_fops); ++ if (!proc_dbg_regs) ++ pr_notice("!! FAIL to create %s PROC !!\n", PROCREG_DBG_REGS); ++ ++ if (g_eth->hwlro) { ++ proc_hw_lro_stats = ++ proc_create(PROCREG_HW_LRO_STATS, 0, proc_reg_dir, ++ &hw_lro_stats_fops); ++ if (!proc_hw_lro_stats) ++ pr_info("!! FAIL to create %s PROC !!\n", PROCREG_HW_LRO_STATS); ++ ++ proc_hw_lro_auto_tlb = ++ proc_create(PROCREG_HW_LRO_AUTO_TLB, 0, proc_reg_dir, ++ &hw_lro_auto_tlb_fops); ++ if (!proc_hw_lro_auto_tlb) ++ pr_info("!! FAIL to create %s PROC !!\n", ++ PROCREG_HW_LRO_AUTO_TLB); ++ } ++ ++ dbg_show_level = 1; ++ ++ return 0; ++} ++ ++void debug_proc_exit(void) ++{ ++ if (proc_tx_ring) ++ remove_proc_entry(PROCREG_TXRING, proc_reg_dir); ++ ++ if (proc_hwtx_ring) ++ remove_proc_entry(PROCREG_HWTXRING, proc_reg_dir); ++ ++ if (proc_rx_ring) ++ remove_proc_entry(PROCREG_RXRING, proc_reg_dir); ++ ++ if (proc_esw_cnt) ++ remove_proc_entry(PROCREG_ESW_CNT, proc_reg_dir); ++ ++ if (proc_xfi_cnt) ++ remove_proc_entry(PROCREG_XFI_CNT, proc_reg_dir); ++ ++ if (proc_reg_dir) ++ remove_proc_entry(PROCREG_DIR, 0); ++ ++ if (proc_dbg_regs) ++ remove_proc_entry(PROCREG_DBG_REGS, proc_reg_dir); ++ ++ if (g_eth->hwlro) { ++ if (proc_hw_lro_stats) ++ remove_proc_entry(PROCREG_HW_LRO_STATS, proc_reg_dir); ++ ++ if (proc_hw_lro_auto_tlb) ++ remove_proc_entry(PROCREG_HW_LRO_AUTO_TLB, proc_reg_dir); ++ } ++ ++ if (proc_reset_event) ++ remove_proc_entry(PROCREG_RESET_EVENT, proc_reg_dir); ++} +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_dbg.h b/drivers/net/ethernet/mediatek/mtk_eth_dbg.h +new file mode 100644 +index 000000000000..7371131c5448 +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_eth_dbg.h +@@ -0,0 +1,335 @@ ++/* ++ * Copyright (C) 2018 MediaTek Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Copyright (C) 2009-2016 John Crispin ++ * Copyright (C) 2009-2016 Felix Fietkau ++ * Copyright (C) 2013-2016 Michael Lee ++ */ ++ ++#ifndef MTK_ETH_DBG_H ++#define MTK_ETH_DBG_H ++ ++/* Debug Purpose Register */ ++#define MTK_PSE_FQFC_CFG 0x100 ++#define MTK_FE_CDM1_FSM 0x220 ++#define MTK_FE_CDM2_FSM 0x224 ++#define MTK_FE_CDM3_FSM 0x238 ++#define MTK_FE_CDM4_FSM 0x298 ++#define MTK_FE_CDM5_FSM 0x318 ++#define MTK_FE_CDM6_FSM 0x328 ++#define MTK_FE_GDM1_FSM 0x228 ++#define MTK_FE_GDM2_FSM 0x22C ++#define MTK_FE_GDM3_FSM 0x23C ++#define MTK_FE_PSE_FREE 0x240 ++#define MTK_FE_DROP_FQ 0x244 ++#define MTK_FE_DROP_FC 0x248 ++#define MTK_FE_DROP_PPE 0x24C ++#define MTK_MAC_FSM(x) (0x1010C + ((x) * 0x100)) ++#define MTK_SGMII_FALSE_CARRIER_CNT(x) (0x10060028 + ((x) * 0x10000)) ++#define MTK_SGMII_EFUSE 0x11D008C8 ++ ++#define MTKETH_MII_READ 0x89F3 ++#define MTKETH_MII_WRITE 0x89F4 ++#define MTKETH_ESW_REG_READ 0x89F1 ++#define MTKETH_ESW_REG_WRITE 0x89F2 ++#define MTKETH_MII_READ_CL45 0x89FC ++#define MTKETH_MII_WRITE_CL45 0x89FD ++#define REG_ESW_MAX 0xFC ++ ++#define PROCREG_ESW_CNT "esw_cnt" ++#define PROCREG_XFI_CNT "xfi_cnt" ++#define PROCREG_TXRING "tx_ring" ++#define PROCREG_HWTXRING "hwtx_ring" ++#define PROCREG_RXRING "rx_ring" ++#define PROCREG_DIR "mtketh" ++#define PROCREG_DBG_REGS "dbg_regs" ++#define PROCREG_RSS_CTRL "rss_ctrl" ++#define PROCREG_HW_LRO_STATS "hw_lro_stats" ++#define PROCREG_HW_LRO_AUTO_TLB "hw_lro_auto_tlb" ++#define PROCREG_RESET_EVENT "reset_event" ++ ++/* XFI MAC MIB Register */ ++#define MTK_XFI_MIB_BASE(x) (MTK_XMAC_MCR(x)) ++#define MTK_XFI_CNT_CTRL 0x100 ++#define MTK_XFI_TX_PKT_CNT 0x108 ++#define MTK_XFI_TX_ETH_CNT 0x114 ++#define MTK_XFI_TX_PAUSE_CNT 0x120 ++#define MTK_XFI_TX_BYTE_CNT 0x134 ++#define MTK_XFI_TX_UC_PKT_CNT_L 0x150 ++#define MTK_XFI_TX_UC_PKT_CNT_H 0x154 ++#define MTK_XFI_TX_MC_PKT_CNT_L 0x160 ++#define MTK_XFI_TX_MC_PKT_CNT_H 0x164 ++#define MTK_XFI_TX_BC_PKT_CNT_L 0x170 ++#define MTK_XFI_TX_BC_PKT_CNT_H 0x174 ++ ++#define MTK_XFI_RX_PKT_CNT 0x188 ++#define MTK_XFI_RX_ETH_CNT 0x18C ++#define MTK_XFI_RX_PAUSE_CNT 0x190 ++#define MTK_XFI_RX_LEN_ERR_CNT 0x194 ++#define MTK_XFI_RX_CRC_ERR_CNT 0x198 ++#define MTK_XFI_RX_UC_PKT_CNT_L 0x1C0 ++#define MTK_XFI_RX_UC_PKT_CNT_H 0x1C4 ++#define MTK_XFI_RX_MC_PKT_CNT_L 0x1D0 ++#define MTK_XFI_RX_MC_PKT_CNT_H 0x1D4 ++#define MTK_XFI_RX_BC_PKT_CNT_L 0x1E0 ++#define MTK_XFI_RX_BC_PKT_CNT_H 0x1E4 ++#define MTK_XFI_RX_UC_DROP_CNT 0x200 ++#define MTK_XFI_RX_BC_DROP_CNT 0x204 ++#define MTK_XFI_RX_MC_DROP_CNT 0x208 ++#define MTK_XFI_RX_ALL_DROP_CNT 0x20C ++ ++#define PRINT_FORMATTED_XFI_MIB(seq, reg, mask) \ ++{ \ ++ seq_printf(seq, "| XFI%d_%s : %010lu |\n", \ ++ gdm_id, #reg, \ ++ FIELD_GET(mask, mtk_r32(eth, \ ++ MTK_XFI_MIB_BASE(gdm_id) + \ ++ MTK_XFI_##reg))); \ ++} ++ ++#define PRINT_FORMATTED_XFI_MIB64(seq, reg) \ ++{ \ ++ seq_printf(seq, "| XFI%d_%s : %010llu |\n", \ ++ gdm_id, #reg, \ ++ mtk_r32(eth, MTK_XFI_MIB_BASE(gdm_id) + \ ++ MTK_XFI_##reg##_L) + \ ++ ((u64)mtk_r32(eth, MTK_XFI_MIB_BASE(gdm_id) +\ ++ MTK_XFI_##reg##_H) << 32)); \ ++} ++ ++/* HW LRO flush reason */ ++#define MTK_HW_LRO_AGG_FLUSH (1) ++#define MTK_HW_LRO_AGE_FLUSH (2) ++#define MTK_HW_LRO_NOT_IN_SEQ_FLUSH (3) ++#define MTK_HW_LRO_TIMESTAMP_FLUSH (4) ++#define MTK_HW_LRO_NON_RULE_FLUSH (5) ++ ++#define SET_PDMA_RXRING_MAX_AGG_CNT(eth, x, y) \ ++{ \ ++ u32 reg_val1 = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(x)); \ ++ u32 reg_val2 = mtk_r32(eth, MTK_LRO_CTRL_DW3_CFG(x)); \ ++ reg_val1 &= ~MTK_LRO_RING_AGG_CNT_L_MASK; \ ++ reg_val2 &= ~MTK_LRO_RING_AGG_CNT_H_MASK; \ ++ reg_val1 |= ((y) & 0x3f) << MTK_LRO_RING_AGG_CNT_L_OFFSET; \ ++ reg_val2 |= (((y) >> 6) & 0x03) << \ ++ MTK_LRO_RING_AGG_CNT_H_OFFSET; \ ++ mtk_w32(eth, reg_val1, MTK_LRO_CTRL_DW2_CFG(x)); \ ++ mtk_w32(eth, reg_val2, MTK_LRO_CTRL_DW3_CFG(x)); \ ++} ++ ++#define SET_PDMA_RXRING_AGG_TIME(eth, x, y) \ ++{ \ ++ u32 reg_val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(x)); \ ++ reg_val &= ~MTK_LRO_RING_AGG_TIME_MASK; \ ++ reg_val |= ((y) & 0xffff) << MTK_LRO_RING_AGG_TIME_OFFSET; \ ++ mtk_w32(eth, reg_val, MTK_LRO_CTRL_DW2_CFG(x)); \ ++} ++ ++#define SET_PDMA_RXRING_AGE_TIME(eth, x, y) \ ++{ \ ++ u32 reg_val1 = mtk_r32(eth, MTK_LRO_CTRL_DW1_CFG(x)); \ ++ u32 reg_val2 = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(x)); \ ++ reg_val1 &= ~MTK_LRO_RING_AGE_TIME_L_MASK; \ ++ reg_val2 &= ~MTK_LRO_RING_AGE_TIME_H_MASK; \ ++ reg_val1 |= ((y) & 0x3ff) << MTK_LRO_RING_AGE_TIME_L_OFFSET; \ ++ reg_val2 |= (((y) >> 10) & 0x03f) << \ ++ MTK_LRO_RING_AGE_TIME_H_OFFSET; \ ++ mtk_w32(eth, reg_val1, MTK_LRO_CTRL_DW1_CFG(x)); \ ++ mtk_w32(eth, reg_val2, MTK_LRO_CTRL_DW2_CFG(x)); \ ++} ++ ++#define SET_PDMA_LRO_BW_THRESHOLD(eth, x) \ ++{ \ ++ u32 reg_val = mtk_r32(eth, MTK_PDMA_LRO_CTRL_DW2); \ ++ reg_val = (x); \ ++ mtk_w32(eth, reg_val, MTK_PDMA_LRO_CTRL_DW2); \ ++} ++ ++#define SET_PDMA_RXRING_VALID(eth, x, y) \ ++{ \ ++ u32 reg_val = mtk_r32(eth, MTK_LRO_CTRL_DW2_CFG(x)); \ ++ reg_val &= ~(0x1 << MTK_LRO_RING_RX_PORT_VLD_OFFSET); \ ++ reg_val |= ((y) & 0x1) << MTK_LRO_RING_RX_PORT_VLD_OFFSET; \ ++ mtk_w32(eth, reg_val, MTK_LRO_CTRL_DW2_CFG(x)); \ ++} ++ ++struct mtk_lro_alt_v1_info0 { ++ u32 dtp : 16; ++ u32 stp : 16; ++}; ++ ++struct mtk_lro_alt_v1_info1 { ++ u32 sip0 : 32; ++}; ++ ++struct mtk_lro_alt_v1_info2 { ++ u32 sip1 : 32; ++}; ++ ++struct mtk_lro_alt_v1_info3 { ++ u32 sip2 : 32; ++}; ++ ++struct mtk_lro_alt_v1_info4 { ++ u32 sip3 : 32; ++}; ++ ++struct mtk_lro_alt_v1_info5 { ++ u32 vlan_vid0 : 32; ++}; ++ ++struct mtk_lro_alt_v1_info6 { ++ u32 vlan_vid1 : 16; ++ u32 vlan_vid_vld : 4; ++ u32 cnt : 12; ++}; ++ ++struct mtk_lro_alt_v1_info7 { ++ u32 dw_len : 32; ++}; ++ ++struct mtk_lro_alt_v1_info8 { ++ u32 dip_id : 2; ++ u32 ipv6 : 1; ++ u32 ipv4 : 1; ++ u32 resv : 27; ++ u32 valid : 1; ++}; ++ ++struct mtk_lro_alt_v1 { ++ struct mtk_lro_alt_v1_info0 alt_info0; ++ struct mtk_lro_alt_v1_info1 alt_info1; ++ struct mtk_lro_alt_v1_info2 alt_info2; ++ struct mtk_lro_alt_v1_info3 alt_info3; ++ struct mtk_lro_alt_v1_info4 alt_info4; ++ struct mtk_lro_alt_v1_info5 alt_info5; ++ struct mtk_lro_alt_v1_info6 alt_info6; ++ struct mtk_lro_alt_v1_info7 alt_info7; ++ struct mtk_lro_alt_v1_info8 alt_info8; ++}; ++ ++struct mtk_lro_alt_v2_info0 { ++ u32 v2_id_h:3; ++ u32 v1_id:12; ++ u32 v0_id:12; ++ u32 v3_valid:1; ++ u32 v2_valid:1; ++ u32 v1_valid:1; ++ u32 v0_valid:1; ++ u32 valid:1; ++}; ++ ++struct mtk_lro_alt_v2_info1 { ++ u32 sip3_h:9; ++ u32 v6_valid:1; ++ u32 v4_valid:1; ++ u32 v3_id:12; ++ u32 v2_id_l:9; ++}; ++ ++struct mtk_lro_alt_v2_info2 { ++ u32 sip2_h:9; ++ u32 sip3_l:23; ++}; ++struct mtk_lro_alt_v2_info3 { ++ u32 sip1_h:9; ++ u32 sip2_l:23; ++}; ++struct mtk_lro_alt_v2_info4 { ++ u32 sip0_h:9; ++ u32 sip1_l:23; ++}; ++struct mtk_lro_alt_v2_info5 { ++ u32 dip3_h:9; ++ u32 sip0_l:23; ++}; ++struct mtk_lro_alt_v2_info6 { ++ u32 dip2_h:9; ++ u32 dip3_l:23; ++}; ++struct mtk_lro_alt_v2_info7 { ++ u32 dip1_h:9; ++ u32 dip2_l:23; ++}; ++struct mtk_lro_alt_v2_info8 { ++ u32 dip0_h:9; ++ u32 dip1_l:23; ++}; ++struct mtk_lro_alt_v2_info9 { ++ u32 sp_h:9; ++ u32 dip0_l:23; ++}; ++struct mtk_lro_alt_v2_info10 { ++ u32 resv:9; ++ u32 dp:16; ++ u32 sp_l:7; ++}; ++ ++struct mtk_lro_alt_v2 { ++ struct mtk_lro_alt_v2_info0 alt_info0; ++ struct mtk_lro_alt_v2_info1 alt_info1; ++ struct mtk_lro_alt_v2_info2 alt_info2; ++ struct mtk_lro_alt_v2_info3 alt_info3; ++ struct mtk_lro_alt_v2_info4 alt_info4; ++ struct mtk_lro_alt_v2_info5 alt_info5; ++ struct mtk_lro_alt_v2_info6 alt_info6; ++ struct mtk_lro_alt_v2_info7 alt_info7; ++ struct mtk_lro_alt_v2_info8 alt_info8; ++ struct mtk_lro_alt_v2_info9 alt_info9; ++ struct mtk_lro_alt_v2_info10 alt_info10; ++}; ++ ++struct mtk_esw_reg { ++ unsigned int off; ++ unsigned int val; ++}; ++ ++struct mtk_mii_ioctl_data { ++ u16 phy_id; ++ u16 reg_num; ++ unsigned int val_in; ++ unsigned int val_out; ++}; ++ ++#if defined(CONFIG_NET_DSA_MT7530) || defined(CONFIG_MT753X_GSW) ++static inline bool mt7530_exist(struct mtk_eth *eth) ++{ ++ return true; ++} ++#else ++static inline bool mt7530_exist(struct mtk_eth *eth) ++{ ++ return false; ++} ++#endif ++ ++extern int _mtk_mdio_write_c22(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg, ++ u32 write_data); ++extern int _mtk_mdio_write_c45(struct mtk_eth *eth, u32 phy_addr, ++ u32 devad, u32 phy_reg, u32 write_data); ++extern int _mtk_mdio_read_c22(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg); ++extern int _mtk_mdio_read_c45(struct mtk_eth *eth, u32 phy_addr, ++ u32 devad, u32 phy_reg); ++ ++void mtk_switch_w32(struct mtk_eth *eth, u32 val, unsigned int reg); ++u32 mtk_switch_r32(struct mtk_eth *eth, unsigned int reg); ++ ++int debug_proc_init(struct mtk_eth *eth); ++void debug_proc_exit(void); ++ ++int mtketh_debugfs_init(struct mtk_eth *eth); ++void mtketh_debugfs_exit(struct mtk_eth *eth); ++int mtk_do_priv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); ++void hw_lro_stats_update(u32 ring_no, struct mtk_rx_dma_v2 *rxd); ++void hw_lro_flush_stats_update(u32 ring_no, struct mtk_rx_dma_v2 *rxd); ++ ++#endif /* MTK_ETH_DBG_H */ +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index 730146eb322e..045619d37d83 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -52,6 +52,7 @@ static const struct mtk_reg_map mtk_reg_map = { + .rx_ptr = 0x0900, + .rx_cnt_cfg = 0x0904, + .pcrx_ptr = 0x0908, ++ .pdrx_ptr = 0x090c, + .lro_ctrl_dw0 = 0x0980, + .glo_cfg = 0x0a04, + .rst_idx = 0x0a08, +@@ -77,9 +78,11 @@ static const struct mtk_reg_map mtk_reg_map = { + .fc_th = 0x1a10, + .tx_sch_rate = 0x1a14, + .int_grp = 0x1a20, ++ .fsm = 0x1a34, + .hred = 0x1a44, + .ctx_ptr = 0x1b00, + .dtx_ptr = 0x1b04, ++ .fwd_count = 0x1b08, + .crx_ptr = 0x1b10, + .drx_ptr = 0x1b14, + .fq_head = 0x1b20, +@@ -107,6 +110,7 @@ static const struct mtk_reg_map mt7628_reg_map = { + .rx_ptr = 0x0900, + .rx_cnt_cfg = 0x0904, + .pcrx_ptr = 0x0908, ++ .pdrx_ptr = 0x090c, + .glo_cfg = 0x0a04, + .rst_idx = 0x0a08, + .delay_irq = 0x0a0c, +@@ -124,6 +128,7 @@ static const struct mtk_reg_map mt7986_reg_map = { + .rx_ptr = 0x4100, + .rx_cnt_cfg = 0x4104, + .pcrx_ptr = 0x4108, ++ .pdrx_ptr = 0x410c, + .glo_cfg = 0x4204, + .rst_idx = 0x4208, + .delay_irq = 0x420c, +@@ -149,9 +154,12 @@ static const struct mtk_reg_map mt7986_reg_map = { + .delay_irq = 0x460c, + .fc_th = 0x4610, + .int_grp = 0x4620, ++ .fsm = 0x4634, + .hred = 0x4644, ++ .qtx_mib_if = 0x46bc, + .ctx_ptr = 0x4700, + .dtx_ptr = 0x4704, ++ .fwd_count = 0x4708, + .crx_ptr = 0x4710, + .drx_ptr = 0x4714, + .fq_head = 0x4720, +@@ -181,6 +189,7 @@ static const struct mtk_reg_map mt7988_reg_map = { + .rx_ptr = 0x6900, + .rx_cnt_cfg = 0x6904, + .pcrx_ptr = 0x6908, ++ .pdrx_ptr = 0x690c, + .glo_cfg = 0x6a04, + .rst_idx = 0x6a08, + .delay_irq = 0x6a0c, +@@ -211,9 +220,12 @@ static const struct mtk_reg_map mt7988_reg_map = { + .delay_irq = 0x460c, + .fc_th = 0x4610, + .int_grp = 0x4620, ++ .fsm = 0x4634, + .hred = 0x4644, ++ .qtx_mib_if = 0x46bc, + .ctx_ptr = 0x4700, + .dtx_ptr = 0x4704, ++ .fwd_count = 0x4708, + .crx_ptr = 0x4710, + .drx_ptr = 0x4714, + .fq_head = 0x4720, +@@ -348,7 +360,7 @@ static int mtk_mdio_busy_wait(struct mtk_eth *eth) + return -ETIMEDOUT; + } + +-static int _mtk_mdio_write_c22(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg, ++int _mtk_mdio_write_c22(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg, + u32 write_data) + { + int ret; +@@ -408,7 +420,7 @@ static int _mtk_mdio_write_c45(struct mtk_eth *eth, u32 phy_addr, + return 0; + } + +-static int _mtk_mdio_read_c22(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg) ++int _mtk_mdio_read_c22(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg) + { + int ret; + +@@ -2579,12 +2591,12 @@ static int mtk_poll_tx(struct mtk_eth *eth, int budget) + + static void mtk_handle_status_irq(struct mtk_eth *eth) + { +- u32 status2 = mtk_r32(eth, MTK_INT_STATUS2); ++ u32 status2 = mtk_r32(eth, MTK_FE_INT_STATUS); + + if (unlikely(status2 & (MTK_GDM1_AF | MTK_GDM2_AF))) { + mtk_stats_update(eth); + mtk_w32(eth, (MTK_GDM1_AF | MTK_GDM2_AF), +- MTK_INT_STATUS2); ++ MTK_FE_INT_STATUS); + } + } + +@@ -3588,7 +3600,7 @@ static void mtk_dma_free(struct mtk_eth *eth) + + static bool mtk_hw_reset_check(struct mtk_eth *eth) + { +- u32 val = mtk_r32(eth, MTK_INT_STATUS2); ++ u32 val = mtk_r32(eth, MTK_FE_INT_STATUS); + + return (val & MTK_FE_INT_FQ_EMPTY) || (val & MTK_FE_INT_RFIFO_UF) || + (val & MTK_FE_INT_RFIFO_OV) || (val & MTK_FE_INT_TSO_FAIL) || +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +index 14c3ce16f733..e19a81d3b141 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -92,7 +92,7 @@ + #define RST_GL_PSE BIT(0) + + /* Frame Engine Interrupt Status Register */ +-#define MTK_INT_STATUS2 0x08 ++#define MTK_FE_INT_STATUS 0x08 + #define MTK_FE_INT_ENABLE 0x0c + #define MTK_FE_INT_FQ_EMPTY BIT(8) + #define MTK_FE_INT_TSO_FAIL BIT(12) +@@ -111,6 +111,14 @@ + /* Frame Engine Interrupt Grouping Register */ + #define MTK_FE_INT_GRP 0x20 + ++/* Frame Engine Interrupt Status 2 Register */ ++#define MTK_FE_INT_STATUS2 0x28 ++ ++/* Frame Engine LRO Auto-Learn Table Information */ ++#define MTK_FE_ALT_CF8 0x300 ++#define MTK_FE_ALT_SGL_CFC 0x304 ++#define MTK_FE_ALT_SEQ_CFC 0x308 ++ + /* CDMP Ingress Control Register */ + #define MTK_CDMQ_IG_CTRL 0x1400 + #define MTK_CDMQ_STAG_EN BIT(0) +@@ -226,6 +234,13 @@ + #define MTK_RSS_INDR_TABLE_DW(x) (reg_map->pdma.rss_glo_cfg + 0x50 + \ + ((x) * 0x4)) + ++/* PDMA HW LRO ALT Debug Registers */ ++#define MTK_LRO_ALT_DBG 0xc40 ++#define MTK_LRO_ALT_INDEX_OFFSET (8) ++ ++/* PDMA HW LRO ALT Data Registers */ ++#define MTK_LRO_ALT_DBG_DATA 0xc44 ++ + /* PDMA Global Configuration Register */ + #define MTK_PDMA_LRO_SDL 0x3000 + #define MTK_RX_CFG_SDL_OFFSET 16 +@@ -269,7 +284,29 @@ + #define MTK_RING_MAX_AGG_CNT_L ((MTK_HW_LRO_MAX_AGG_CNT & 0x3f) << 26) + #define MTK_RING_MAX_AGG_CNT_H ((MTK_HW_LRO_MAX_AGG_CNT >> 6) & 0x3) + ++/* PDMA HW LRO Ring Control Mask */ ++#define MTK_LRO_RING_AGG_CNT_H_MASK GENMASK(1, 0) ++#define MTK_LRO_RING_AGG_TIME_MASK GENMASK(25, 10) ++#define MTK_LRO_RING_AGG_CNT_L_MASK GENMASK(31, 26) ++#define MTK_LRO_RING_AGE_TIME_H_MASK GENMASK(5, 0) ++#define MTK_LRO_RING_AGE_TIME_L_MASK GENMASK(31, 22) ++ ++/* PDMA HW LRO Ring Control 1 Offsets */ ++#define MTK_LRO_RING_AGE_TIME_L_OFFSET (22) ++ ++/* PDMA HW LRO Ring Control 2 Offsets */ ++#define MTK_LRO_RING_AGE_TIME_H_OFFSET (0) ++#define MTK_LRO_RING_RX_MODE_OFFSET (6) ++#define MTK_LRO_RING_RX_PORT_VLD_OFFSET (8) ++#define MTK_LRO_RING_AGG_TIME_OFFSET (10) ++#define MTK_LRO_RING_AGG_CNT_L_OFFSET (26) ++ ++/* PDMA HW LRO Ring Control 3 Offsets */ ++#define MTK_LRO_RING_AGG_CNT_H_OFFSET (0) ++ + /* QDMA TX Queue Configuration Registers */ ++#define MTK_QTX_CFG_HW_RESV GENMASK(15, 8) ++#define MTK_QTX_CFG_SW_RESV GENMASK(7, 0) + #define MTK_QTX_OFFSET 0x10 + #define QDMA_RES_THRES 4 + +@@ -287,8 +324,19 @@ + #define MTK_QTX_SCH_MAX_RATE_MAN GENMASK(10, 4) + #define MTK_QTX_SCH_MAX_RATE_EXP GENMASK(3, 0) + ++/* QDMA Page Configuration Register */ ++#define MTK_QTX_PER_PAGE (16) ++ ++/* QDMA TX Queue MIB Interface Register */ ++#define MTK_MIB_ON_QTX_CFG BIT(31) ++#define MTK_VQTX_MIB_EN BIT(28) ++ + /* QDMA TX Scheduler Rate Control Register */ ++#define MTK_QDMA_TX_SCH GENMASK(15, 0) + #define MTK_QDMA_TX_SCH_MAX_WFQ BIT(15) ++#define MTK_QDMA_TX_SCH_RATE_EN BIT(11) ++#define MTK_QDMA_TX_SCH_RATE_MAN GENMASK(10, 4) ++#define MTK_QDMA_TX_SCH_RATE_EXP GENMASK(3, 0) + + /* QDMA Global Configuration Register */ + #define MTK_RX_2B_OFFSET BIT(31) +@@ -424,6 +472,10 @@ + #define RX_DMA_L4_VALID_PDMA BIT(30) /* when PDMA is used */ + #define RX_DMA_SPECIAL_TAG BIT(22) + ++/* PDMA descriptor rxd2 */ ++#define RX_DMA_GET_AGG_CNT GENMASK(9, 2) ++#define RX_DMA_GET_REV GENMASK(15, 10) ++ + /* PDMA descriptor rxd5 */ + #define MTK_RXD5_FOE_ENTRY GENMASK(14, 0) + #define MTK_RXD5_PPE_CPU_REASON GENMASK(22, 18) +@@ -438,6 +490,10 @@ + + #define MTK_TDMA_GLO_CFG 0x6204 + ++/* PDMA V2 descriptor rxd6 */ ++#define RX_DMA_GET_FLUSH_RSN_V2 GENMASK(2, 0) ++#define RX_DMA_GET_AGG_CNT_V2 GENMASK(23, 16) ++ + /* PHY Polling and SMI Master Control registers */ + #define MTK_PPSC 0x10000 + #define PPSC_MDC_CFG GENMASK(29, 24) +@@ -1286,14 +1342,18 @@ struct mtk_reg_map { + u32 rx_ptr; /* rx base pointer */ + u32 rx_cnt_cfg; /* rx max count configuration */ + u32 qcrx_ptr; /* rx cpu pointer */ ++ u32 page; /* page configuration */ + u32 glo_cfg; /* global configuration */ + u32 rst_idx; /* reset index */ + u32 delay_irq; /* delay interrupt */ + u32 fc_th; /* flow control */ + u32 int_grp; ++ u32 fsm; + u32 hred; /* interrupt mask */ ++ u32 qtx_mib_if; /* tx queue mib interface */ + u32 ctx_ptr; /* tx acquire cpu pointer */ + u32 dtx_ptr; /* tx acquire dma pointer */ ++ u32 fwd_count; /* tx forward count */ + u32 crx_ptr; /* tx release cpu pointer */ + u32 drx_ptr; /* tx release dma pointer */ + u32 fq_head; /* fq head pointer */ +@@ -1640,6 +1700,10 @@ void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg); + u32 mtk_r32(struct mtk_eth *eth, unsigned reg); + u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned int reg); + ++int _mtk_mdio_read_c22(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg); ++int _mtk_mdio_write_c22(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg, ++ u32 write_data); ++ + int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id); + int mtk_gmac_2p5gphy_path_setup(struct mtk_eth *eth, int mac_id); + int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id); +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0080-enable-debugfs.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0080-enable-debugfs.patch new file mode 100644 index 0000000000..88344c0ca3 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0080-enable-debugfs.patch @@ -0,0 +1,52 @@ +From 59da261a6f057fd191d56b4171dcc12f7b6bd077 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sat, 18 Jan 2025 15:59:43 +0100 +Subject: [PATCH 80/84] enable debugfs + +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index 045619d37d83..84ab560a1b80 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -32,6 +32,7 @@ + #include + + #include "mtk_eth_soc.h" ++#include "mtk_eth_dbg.h" + #include "mtk_wed.h" + + static int mtk_msg_level = -1; +@@ -384,7 +385,7 @@ int _mtk_mdio_write_c22(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg, + return 0; + } + +-static int _mtk_mdio_write_c45(struct mtk_eth *eth, u32 phy_addr, ++int _mtk_mdio_write_c45(struct mtk_eth *eth, u32 phy_addr, + u32 devad, u32 phy_reg, u32 write_data) + { + int ret; +@@ -442,7 +443,7 @@ int _mtk_mdio_read_c22(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg) + return mtk_r32(eth, MTK_PHY_IAC) & PHY_IAC_DATA_MASK; + } + +-static int _mtk_mdio_read_c45(struct mtk_eth *eth, u32 phy_addr, ++int _mtk_mdio_read_c45(struct mtk_eth *eth, u32 phy_addr, + u32 devad, u32 phy_reg) + { + int ret; +@@ -5913,6 +5914,9 @@ static int mtk_probe(struct platform_device *pdev) + } + } + ++ mtketh_debugfs_init(eth); ++ debug_proc_init(eth); ++ + platform_set_drvdata(pdev, eth); + schedule_delayed_work(ð->reset.monitor_work, + MTK_DMA_MONITOR_TIMEOUT); +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0081-net-mediatek-mtk_eth_soc-add-RSS-capabilty-for-mt798.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0081-net-mediatek-mtk_eth_soc-add-RSS-capabilty-for-mt798.patch new file mode 100644 index 0000000000..43bac070d5 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0081-net-mediatek-mtk_eth_soc-add-RSS-capabilty-for-mt798.patch @@ -0,0 +1,31 @@ +From 9e860e36b0a842cb3de4136cde7258b34caf3564 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sat, 12 Jul 2025 14:59:51 +0200 +Subject: [PATCH 81/84] net: mediatek: mtk_eth_soc: add RSS capabilty for + mt798[16] + +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +index e19a81d3b141..0cb99f1c1772 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -1281,11 +1281,11 @@ enum mkt_eth_capabilities { + #define MT7981_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \ + MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ + MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \ +- MTK_RSTCTRL_PPE1 | MTK_SRAM | MTK_PDMA_INT) ++ MTK_RSTCTRL_PPE1 | MTK_SRAM | MTK_PDMA_INT | MTK_RSS) + + #define MT7986_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \ + MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ +- MTK_RSTCTRL_PPE1 | MTK_SRAM | MTK_PDMA_INT) ++ MTK_RSTCTRL_PPE1 | MTK_SRAM | MTK_PDMA_INT | MTK_RSS) + + #define MT7988_CAPS (MTK_36BIT_DMA | MTK_GDM1_ESW | MTK_GMAC1_SGMII | \ + MTK_GMAC2_2P5GPHY | MTK_GMAC2_SGMII | MTK_GMAC2_USXGMII | \ +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0082-net-mediatek-mtk_eth_soc-enable-lro-stats-from-debug.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0082-net-mediatek-mtk_eth_soc-enable-lro-stats-from-debug.patch new file mode 100644 index 0000000000..586c54e8cb --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0082-net-mediatek-mtk_eth_soc-enable-lro-stats-from-debug.patch @@ -0,0 +1,53 @@ +From cc6820376ccbacfcf7a495b3d6817c1c7e916f3e Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Fri, 7 Mar 2025 13:14:20 +0100 +Subject: [PATCH 82/84] net: mediatek: mtk_eth_soc: enable lro stats from + debugfs + +echo 4 1 > /proc/mtketh/hw_lro_auto_tlb #enable rings +echo 5 1 > /proc/mtketh/hw_lro_auto_tlb #enable statistics +cat /proc/mtketh/hw_lro_stats + +had to disable CONFIG_STRICT_DEVMEM for register values + +root@bpi-r4-v11:~ +busybox devmem 0x15106C54 #LRO2_RING1_DIP_DW0 Destination IP address +0xC0A80101 #192.168.1.1 +root@bpi-r4-v11:~ +busybox devmem 0x15106C58 #LRO2_RING1_DIP_DW1 Destination IP address +0x00000000 +root@bpi-r4-v11:~ +busybox devmem 0x15106C5C #LRO2_RING1_DIP_DW2 Destination IP address +0x00000000 +root@bpi-r4-v11:~ +busybox devmem 0x15106C60 LRO2_RING1_DIP_DW3 Destination IP address +0x00000000 +root@bpi-r4-v11:~ +busybox devmem 0x15106c7c +0x00002BC0 +=LRO2_RING1_CTRL_DW2 LRO2_MAX_AGGREGATED_CNT_L = 0x00002BC0 (bit8 = 1 and bit9 = 1) +means that both DIP and flow information have been enabled. +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index 84ab560a1b80..a500ac80e715 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -2393,6 +2393,12 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget, + if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) + mtk_ppe_check_skb(eth->ppe[ppe_idx], skb, hash); + ++ if (eth->hwlro && mtk_hwlro_stats_ebl && ++ IS_HW_LRO_RING(ring->ring_no)) { ++ hw_lro_stats_update(ring->ring_no, &trxd); ++ hw_lro_flush_stats_update(ring->ring_no, &trxd); ++ } ++ + skb_record_rx_queue(skb, 0); + napi_gro_receive(napi, skb); + +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0083-net-mediatek-change-mt7986-from-RSS-to-LRO-only-1-po.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0083-net-mediatek-change-mt7986-from-RSS-to-LRO-only-1-po.patch new file mode 100644 index 0000000000..9f8e21f651 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0083-net-mediatek-change-mt7986-from-RSS-to-LRO-only-1-po.patch @@ -0,0 +1,78 @@ +From 2cd641be6c6440c61c1f730722dab5e359acf6da Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sat, 12 Apr 2025 14:36:54 +0200 +Subject: [PATCH 83/84] net: mediatek change mt7986 from RSS to LRO (only 1 + possible) - untested + +https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/30c22fcf9e2dd7d04e630969557c8ef3e96bf451 +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 15 ++++++++------- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 +- + 2 files changed, 9 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index a500ac80e715..eef833f1cd06 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3036,11 +3036,6 @@ static int mtk_hwlro_rx_init(struct mtk_eth *eth) + + lro_ctrl_dw0 |= MTK_PDMA_LRO_SDL << MTK_CTRL_DW0_SDL_OFFSET; + +- /* enable cpu reason black list */ +- lro_ctrl_dw0 |= MTK_LRO_CRSN_BNW; +- +- /* no use PPE cpu reason */ +- mtk_w32(eth, 0xffffffff, MTK_PDMA_LRO_CTRL_DW1); + } else { + /* set HW LRO mode & the max aggregation count for rx packets */ + lro_ctrl_dw3 |= MTK_ADMA_MODE | (MTK_HW_LRO_MAX_AGG_CNT & 0xff); +@@ -3052,9 +3047,15 @@ static int mtk_hwlro_rx_init(struct mtk_eth *eth) + /* enable HW LRO */ + lro_ctrl_dw0 |= MTK_LRO_EN; + ++ /* enable cpu reason black list */ ++ lro_ctrl_dw0 |= MTK_LRO_CRSN_BNW; ++ + mtk_w32(eth, lro_ctrl_dw3, MTK_PDMA_LRO_CTRL_DW3); + mtk_w32(eth, lro_ctrl_dw0, MTK_PDMA_LRO_CTRL_DW0); + ++ /* no use PPE cpu reason */ ++ mtk_w32(eth, 0xffffffff, MTK_PDMA_LRO_CTRL_DW1); ++ + if (mtk_is_netsys_v2_or_greater(eth)) { + i = (soc->rx.desc_size == sizeof(struct mtk_rx_dma_v2)) ? 1 : 0; + mtk_m32(eth, MTK_RX_DONE_INT(MTK_HW_LRO_RING(i)), +@@ -6142,7 +6143,7 @@ static const struct mtk_soc_data mt7981_data = { + }, + .rx = { + .desc_size = sizeof(struct mtk_rx_dma), +- .dma_l4_valid = RX_DMA_L4_VALID_V2, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + .dma_size = MTK_DMA_SIZE(2K), +@@ -6172,7 +6173,7 @@ static const struct mtk_soc_data mt7986_data = { + }, + .rx = { + .desc_size = sizeof(struct mtk_rx_dma), +- .dma_l4_valid = RX_DMA_L4_VALID_V2, ++ .dma_l4_valid = RX_DMA_L4_VALID, + .dma_max_len = MTK_TX_DMA_BUF_LEN, + .dma_len_offset = 16, + .dma_size = MTK_DMA_SIZE(2K), +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +index 0cb99f1c1772..5ecd6381ad6e 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -1285,7 +1285,7 @@ enum mkt_eth_capabilities { + + #define MT7986_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \ + MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ +- MTK_RSTCTRL_PPE1 | MTK_SRAM | MTK_PDMA_INT | MTK_RSS) ++ MTK_RSTCTRL_PPE1 | MTK_SRAM | MTK_PDMA_INT | MTK_HWLRO) + + #define MT7988_CAPS (MTK_36BIT_DMA | MTK_GDM1_ESW | MTK_GMAC1_SGMII | \ + MTK_GMAC2_2P5GPHY | MTK_GMAC2_SGMII | MTK_GMAC2_USXGMII | \ +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/patches.armbian/0084-net-mediatek-mtk_eth_soc-check-if-irqs-were-loaded-t.patch b/patch/kernel/archive/filogic-6.16/patches.armbian/0084-net-mediatek-mtk_eth_soc-check-if-irqs-were-loaded-t.patch new file mode 100644 index 0000000000..62f4ab4c4f --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/patches.armbian/0084-net-mediatek-mtk_eth_soc-check-if-irqs-were-loaded-t.patch @@ -0,0 +1,47 @@ +From 2c586e5b7bf54b2f94ffc6bb00618afad3725cf8 Mon Sep 17 00:00:00 2001 +From: Frank Wunderlich +Date: Sat, 12 Jul 2025 15:45:22 +0200 +Subject: [PATCH 84/84] net: mediatek: mtk_eth_soc: check if irqs were loaded + to keep backwards compatibility + +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +index eef833f1cd06..106bbeb21ea0 100644 +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3340,6 +3340,11 @@ static int mtk_hwlro_get_fdir_all(struct net_device *dev, + return 0; + } + ++static bool mtk_rss_available(struct mtk_eth *eth) ++{ ++ return (eth->soc->rss_num && eth->irq_pdma[eth->soc->rss_num - 1]>=0); ++} ++ + static u32 mtk_rss_indr_table(struct mtk_rss_params *rss_params, int index) + { + u32 val = 0; +@@ -4620,7 +4625,7 @@ static int mtk_hw_init(struct mtk_eth *eth, bool reset) + mtk_w32(eth, MTK_TX_DONE_INT, reg_map->qdma.int_grp); + mtk_w32(eth, MTK_RX_DONE_INT(0), reg_map->qdma.int_grp + 4); + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_PDMA_INT)) { ++ if (mtk_rss_available(eth)) { + mtk_w32(eth, 0x210FFFF2, MTK_FE_INT_GRP); + } else { + mtk_w32(eth, MTK_TX_DONE_INT, reg_map->pdma.int_grp); +@@ -5805,7 +5810,7 @@ static int mtk_probe(struct platform_device *pdev) + if (err) + goto err_free_dev; + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_PDMA_INT)) { ++ if (mtk_rss_available(eth)) { + irqname = devm_kasprintf(eth->dev, GFP_KERNEL, "%s PDMA RX %d", + dev_name(eth->dev), 0); + err = devm_request_irq(eth->dev, eth->irq_pdma[0], +-- +2.30.2 + diff --git a/patch/kernel/archive/filogic-6.16/series.armbian b/patch/kernel/archive/filogic-6.16/series.armbian deleted file mode 100644 index 1256d8347c..0000000000 --- a/patch/kernel/archive/filogic-6.16/series.armbian +++ /dev/null @@ -1,10 +0,0 @@ -# -# This file is made manually by simply copying text -# from the target series.* files. -# Add (-) at the beginning of the line if the patch should not be applied. -# At the same time, the patch does not need to be deleted. -# - # diff between frank-w's BPI-Router-Linux-kernel/ v.6.16-rsslro, and a tree with the v6.16.12 tree rebased into it - # Note, some patches appear to have been backported into the 6.16-stable branch - patches.armbian/0001-6.16.12.diff - patches.armbian/mt7988a-bananapi-bpi-r4-sd.patch diff --git a/patch/kernel/archive/filogic-6.16/series.armbian b/patch/kernel/archive/filogic-6.16/series.armbian new file mode 120000 index 0000000000..491b6449c8 --- /dev/null +++ b/patch/kernel/archive/filogic-6.16/series.armbian @@ -0,0 +1 @@ +series.conf \ No newline at end of file diff --git a/patch/kernel/archive/filogic-6.16/series.conf b/patch/kernel/archive/filogic-6.16/series.conf index 1256d8347c..0fedd0533f 100644 --- a/patch/kernel/archive/filogic-6.16/series.conf +++ b/patch/kernel/archive/filogic-6.16/series.conf @@ -4,7 +4,97 @@ # Add (-) at the beginning of the line if the patch should not be applied. # At the same time, the patch does not need to be deleted. # - # diff between frank-w's BPI-Router-Linux-kernel/ v.6.16-rsslro, and a tree with the v6.16.12 tree rebased into it - # Note, some patches appear to have been backported into the 6.16-stable branch - patches.armbian/0001-6.16.12.diff + +# patch series derived from: +# `git format-patch -o ~/build/armbian-build/patch/kernel/archive/filogic-6.16/patches.armbian/ v6.16.12..6.16.12-rsslro` +# where 6.16.12-rsslro was from taking https://github.com/frank-w/BPI-Router-Linux branch:6.16-rsslro +# then `git rebase v6.16.12` where this tag was from https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git tag:v6.16.12 +# two patches are then skipped for being empty, 0001 & 0017 + + -patches.armbian/0001-v6-coverletter-net-next-rework-IRQ-handling-in-mtk_e.patch + patches.armbian/0002-net-ethernet-mtk_eth_soc-support-named-IRQs.patch + patches.armbian/0003-net-ethernet-mtk_eth_soc-add-consts-for-irq-index.patch + patches.armbian/0004-net-ethernet-mtk_eth_soc-skip-first-IRQ-if-not-used.patch + patches.armbian/0005-net-ethernet-mtk_eth_soc-only-use-legacy-mode-on-mis.patch + patches.armbian/0006-build.sh-add-build-script-config-defconfig-and-fit-s.patch + patches.armbian/0007-build.sh-add-additional-build-script-config-defconfi.patch + patches.armbian/0008-defconfig-r3-fix-warning-about-BASE_SMALL.patch + patches.armbian/0009-build.conf-change-upload-target.patch + patches.armbian/0010-arm-dts-mt7623-swap-mmc-and-put-uart2-first.patch + patches.armbian/0011-arm64-dts-disable-dtbs-for-dtbs_check.patch + patches.armbian/0012-dt-bindings-interconnect-add-mt7988-cci-compatible.patch + patches.armbian/0013-arm64-dts-mediatek-mt7988-add-cci-node.patch + patches.armbian/0014-arm64-dts-mediatek-mt7988a-bpi-r4-add-proc-supply-fo.patch + patches.armbian/0015-arm64-dts-mediatek-mt7988a-bpi-r4-drop-unused-pins.patch + patches.armbian/0016-arm64-dts-mediatek-mt7988a-bpi-r4-add-gpio-leds.patch + -patches.armbian/0017-v9-coverletter-further-mt7988-devicetree-work.patch + patches.armbian/0018-dt-bindings-net-mediatek-net-update-mac-subnode-patt.patch + patches.armbian/0019-dt-bindings-net-mediatek-net-allow-up-to-8-IRQs.patch + patches.armbian/0020-dt-bindings-net-mediatek-net-allow-irq-names.patch + patches.armbian/0021-dt-bindings-net-mediatek-net-add-sram-property.patch + patches.armbian/0022-dt-bindings-net-dsa-mediatek-mt7530-add-dsa-port-def.patch + patches.armbian/0023-dt-bindings-net-dsa-mediatek-mt7530-add-internal-mdi.patch + patches.armbian/0024-arm64-dts-mediatek-mt7986-add-sram-node.patch + patches.armbian/0025-arm64-dts-mediatek-mt7986-add-interrupts-for-RSS-and.patch + patches.armbian/0026-arm64-dts-mediatek-mt7988-add-basic-ethernet-nodes.patch + patches.armbian/0027-arm64-dts-mediatek-mt7988-add-switch-node.patch + patches.armbian/0028-arm64-dts-mediatek-mt7988a-bpi-r4-add-aliases-for-et.patch + patches.armbian/0029-arm64-dts-mediatek-mt7988a-bpi-r4-add-sfp-cages-and-.patch + patches.armbian/0030-arm64-dts-mediatek-mt7988a-bpi-r4-configure-switch-p.patch + patches.armbian/0031-arm64-dts-mediatek-mt7988a-bpi-r4-drop-readonly-from.patch + patches.armbian/0032-dt-bindings-net-pcs-mediatek-sgmiisys-add-phys-and-r.patch + patches.armbian/0033-dt-binding-sgmiisys-re-add-pcs-cells.patch + patches.armbian/0034-dts-re-add-sgmiisys.patch + patches.armbian/0035-arm64-dts-mt7988-add-cpufreq-calibration-efuse-subno.patch + patches.armbian/0036-net-ethernet-mtk_eth_soc-move-desc-assignment-below-.patch + patches.armbian/0037-dts-enable-mt818-36-for-cci-testing.patch + patches.armbian/0038-Revert-dts-enable-mt818-36-for-cci-testing.patch + patches.armbian/0039-enable-bpi-r3-DTBs-for-testing.patch + patches.armbian/0040-only-enable-mediatek-for-arm-to-increase-dtbs_check.patch + patches.armbian/0041-enable-some-arm64-dts-to-check-binding.patch + patches.armbian/0042-defconfig-r4-add-sram-driver.patch + patches.armbian/0043-net-ethernet-mtk_eth_soc-improve-support-for-named-i.patch + patches.armbian/0044-net-ethernet-mtk_eth_soc-fix-kernel-doc-comment.patch + patches.armbian/0045-net-ethernet-mtk_eth_soc-use-generic-allocator-for-S.patch + patches.armbian/0046-defconfig-r3-add-sram.patch + patches.armbian/0047-WIP-dts64-r4-add-ubi-partition-to-spin-nand.patch + patches.armbian/0048-add-mtd-rw-driver.patch + patches.armbian/0049-arm64-dts-add-usxgmii-pcs-and-link-both-pcs.patch + patches.armbian/0050-arm64-dts-update-bpi-r4.dtsi-to-actual-state.patch + patches.armbian/0051-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch + patches.armbian/0052-net-phylink-keep-and-use-MAC-supported_interfaces-in.patch + patches.armbian/0053-net-phy-introduce-phy_interface_copy-helper.patch + patches.armbian/0054-net-phylink-introduce-internal-phylink-PCS-handling.patch + patches.armbian/0055-net-phylink-add-phylink_release_pcs-to-externally-re.patch + patches.armbian/0056-net-pcs-implement-Firmware-node-support-for-PCS-driv.patch + patches.armbian/0057-net-phylink-support-late-PCS-provider-attach.patch + patches.armbian/0058-dt-bindings-net-ethernet-controller-permit-to-define.patch + patches.armbian/0059-net-pcs-airoha-add-PCS-driver-for-Airoha-SoC.patch + patches.armbian/0060-dt-bindings-net-pcs-Document-support-for-Airoha-Ethe.patch + patches.armbian/0061-net-pcs-pcs-mtk-lynxi-add-platform-driver-for-MT7988.patch + patches.armbian/0062-dt-bindings-net-pcs-add-bindings-for-MediaTek-USXGMI.patch + patches.armbian/0063-net-pcs-add-driver-for-MediaTek-USXGMII-PCS.patch + patches.armbian/0064-net-ethernet-mtk_eth_soc-add-more-DMA-monitor-for-MT.patch + patches.armbian/0065-hwrng-add-driver-for-MediaTek-TRNG-SMC.patch + patches.armbian/0066-dts64-enable-sata-and-disable-pcie-slot-CN8-shared.patch + patches.armbian/0067-arm64-dts-mt7622-fix-sata.patch + patches.armbian/0068-kdeb-try-to-add-kernels-for-bpi-boards-to-deb-packag.patch + patches.armbian/0069-kdeb-fix-deb-build-for-R3-R4.patch + patches.armbian/0070-build.conf-change-to-r4.patch + patches.armbian/0071-defconfig-r4-disable-STRICT_DEVMEM-to-allow-register.patch + patches.armbian/0072-net-ethernet-mtk_eth_soc-add-register-definitions-fo.patch + patches.armbian/0073-net-ethernet-mtk_eth_soc-add-rss-support.patch + patches.armbian/0074-net-mediatek-mtk_eth_soc-drop-RSS-capabilty-for-mt79.patch + patches.armbian/0075-net-mtk_eth_soc-fix-mtk_-get-set-_rxfh-callback-head.patch + patches.armbian/0076-net-ethernet-mtk_eth_soc-Add-LRO-support.patch + patches.armbian/0077-readme-add-README.md-for-RSS-LRO.patch + patches.armbian/0078-net-ethernet-mtk_eth_soc-support-forced-reset-contro.patch + patches.armbian/0079-net-mediatek-add-proprietary-debugfs.patch + patches.armbian/0080-enable-debugfs.patch + patches.armbian/0081-net-mediatek-mtk_eth_soc-add-RSS-capabilty-for-mt798.patch + patches.armbian/0082-net-mediatek-mtk_eth_soc-enable-lro-stats-from-debug.patch + patches.armbian/0083-net-mediatek-change-mt7986-from-RSS-to-LRO-only-1-po.patch + patches.armbian/0084-net-mediatek-mtk_eth_soc-check-if-irqs-were-loaded-t.patch +# this patch is not from frank-w's tree, but rather is an adaptation to the armbian build framework +# vs the OpenWRT framework's method of building the relevant FDTs as used by the bootloader. patches.armbian/mt7988a-bananapi-bpi-r4-sd.patch